aboutsummaryrefslogtreecommitdiff
path: root/Git/Ref.hs
diff options
context:
space:
mode:
authorGravatar Joey Hess <joey@kitenet.net>2012-04-11 12:21:54 -0400
committerGravatar Joey Hess <joey@kitenet.net>2012-04-11 12:21:54 -0400
commit0be6ebb0aad2cc9135479f3a3725e7c21add4989 (patch)
treee9020ae323b9a54a46de1ba40e0f9a9c9b467220 /Git/Ref.hs
parent028972c80f01122350dfc7520ffa8461d403aaa1 (diff)
added a git ref legality checker
git-check-ref-format is .. wow. Good design on one level, but what a mess.
Diffstat (limited to 'Git/Ref.hs')
-rw-r--r--Git/Ref.hs23
1 files changed, 23 insertions, 0 deletions
diff --git a/Git/Ref.hs b/Git/Ref.hs
index f483aede0..c7abdb00a 100644
--- a/Git/Ref.hs
+++ b/Git/Ref.hs
@@ -11,6 +11,8 @@ import Common
import Git
import Git.Command
+import Data.Char (chr)
+
{- Converts a fully qualified git ref into a user-visible string. -}
describe :: Ref -> String
describe = show . base
@@ -61,3 +63,24 @@ matchingUniq :: Ref -> Repo -> IO [(Ref, Branch)]
matchingUniq ref repo = nubBy uniqref <$> matching ref repo
where
uniqref (a, _) (b, _) = a == b
+
+{- Checks if a String is a legal git ref name.
+ -
+ - The rules for this are complex; see git-check-ref-format(1) -}
+legalRef :: Bool -> String -> Bool
+legalRef allowonelevel s
+ | any ("." `isPrefixOf`) pathbits = False
+ | any (".lock" `isSuffixOf`) pathbits = False
+ | not allowonelevel && length pathbits < 2 = False
+ | ".." `isInfixOf` s = False
+ | any (\c -> [c] `isInfixOf` s) illegalchars = False
+ | "/" `isPrefixOf` s = False
+ | "/" `isSuffixOf` s = False
+ | "//" `isInfixOf` s = False
+ | "." `isSuffixOf` s = False
+ | "@{" `isInfixOf` s = False
+ | otherwise = True
+ where
+ pathbits = split "/" s
+ illegalchars = " ~^:?*[\\" ++ controlchars
+ controlchars = chr 0o177 : [chr 0 .. chr (0o40-1)]