summaryrefslogtreecommitdiff
path: root/GitRepo.hs
diff options
context:
space:
mode:
authorGravatar Joey Hess <joey@kitenet.net>2010-11-02 01:07:34 -0400
committerGravatar Joey Hess <joey@kitenet.net>2010-11-02 01:07:34 -0400
commit790613333c2d946d28fe62ef7da8ed3a23428f99 (patch)
treec1aef7c3e84413352c663247c0f323d48295d91a /GitRepo.hs
parent58c89565e9f9b3a05b0b4ff33944b543d226c398 (diff)
deal with git's insane octal filename encoding
Diffstat (limited to 'GitRepo.hs')
-rw-r--r--GitRepo.hs31
1 files changed, 30 insertions, 1 deletions
diff --git a/GitRepo.hs b/GitRepo.hs
index 244acda86..389aa35fe 100644
--- a/GitRepo.hs
+++ b/GitRepo.hs
@@ -156,11 +156,40 @@ checkAttr repo attr files = do
where
params = gitCommandLine repo ["check-attr", attr, "-z", "--stdin"]
files0 = join "\0" files
- topair l = (bits !! 0, join sep $ drop 1 $ bits)
+ topair l = (file, value)
where
+ file = decodeGitFile $ join sep $ take end bits
+ value = bits !! end
+ end = length bits - 1
bits = split sep l
sep = ": " ++ attr ++ ": "
+{- Some git commands output encoded filenames. Such a filename
+ - will always be double-quoted, and then \nnn (in octal) is used
+ - to escape high characters. -}
+decodeGitFile :: String -> FilePath
+decodeGitFile [] = []
+decodeGitFile f@(c:s)
+ | c == '"' = unescape middle
+ | otherwise = f
+ where
+ e = "\\"
+ middle = take (length s - 1) s
+ unescape v = foldl (++) beginning $ map decode $ split e rest
+ where
+ pair = span (/= '\\') v
+ beginning = fst pair
+ rest = snd pair
+ decode [] = ""
+ decode n
+ | length num == 3 = (chr $ readoctal num):rest
+ | otherwise = e++n
+ where
+ pair = span isOctDigit n
+ num = fst pair
+ rest = snd pair
+ readoctal o = read $ "0o" ++ o :: Int
+
{- Path to a repository's .git directory, relative to its workTree. -}
gitDir :: Repo -> String
gitDir repo