summaryrefslogtreecommitdiff
path: root/Annex/View.hs
diff options
context:
space:
mode:
authorGravatar Joey Hess <joeyh@joeyh.name>2016-01-08 13:55:35 -0400
committerGravatar Joey Hess <joeyh@joeyh.name>2016-01-08 13:55:35 -0400
commit8df4e37f0dda20be0a13487f71bacf483aedaf58 (patch)
treefc628244c59aaa1e04658847c0a3ee8d4fbc45bd /Annex/View.hs
parent6b4fc5e985ed96e14ebc89e67b373dd66c857bc5 (diff)
better fix for slash in view metadata
The homomorphs are back, just encoded such that it doesn't crash in LANG=C However, I noticed a bug in the old escaping; [pseudoSlash] was escaped the same as ['/','/']. Fixed by using '%' to escape pseudoSlash. Which requires doubling '%' to escape it, but that's already done in the escaping of worktree filenames in a view, so is probably ok.
Diffstat (limited to 'Annex/View.hs')
-rw-r--r--Annex/View.hs36
1 files changed, 25 insertions, 11 deletions
diff --git a/Annex/View.hs b/Annex/View.hs
index 92a7ffc48..060301fd5 100644
--- a/Annex/View.hs
+++ b/Annex/View.hs
@@ -222,23 +222,37 @@ viewComponentMatcher viewcomponent = \metadata ->
| S.null s = Nothing
| otherwise = Just (S.toList s)
+-- This is '∕', a unicode character that displays the same as '/' but is
+-- not it. It is encoded using the filesystem encoding, which allows it
+-- to be used even when not in a unicode capable locale.
+pseudoSlash :: String
+pseudoSlash = "\56546\56456\56469"
+
+-- And this is '╲' similarly.
+pseudoBackslash :: String
+pseudoBackslash = "\56546\56469\56498"
+
toViewPath :: MetaValue -> FilePath
-toViewPath = concatMap escapeslash . fromMetaValue
+toViewPath = escapeslash [] . fromMetaValue
where
- escapeslash c
- | c == '/' = "%_"
- | c == '\\' = "%."
- | c == '%' = "%%"
- | otherwise = [c]
+ escapeslash s ('/':cs) = escapeslash (pseudoSlash:s) cs
+ escapeslash s ('\\':cs) = escapeslash (pseudoBackslash:s) cs
+ escapeslash s ('%':cs) = escapeslash ("%%":s) cs
+ escapeslash s (c1:c2:c3:cs)
+ | [c1,c2,c3] == pseudoSlash = escapeslash ("%":pseudoSlash:s) cs
+ | [c1,c2,c3] == pseudoBackslash = escapeslash ("%":pseudoBackslash:s) cs
+ | otherwise = escapeslash ([c1]:s) (c2:c3:cs)
+ escapeslash s cs = concat (reverse (cs:s))
fromViewPath :: FilePath -> MetaValue
fromViewPath = toMetaValue . deescapeslash []
where
- deescapeslash s [] = reverse s
- deescapeslash s ('%':'_':cs) = deescapeslash ('/':s) cs
- deescapeslash s ('%':'.':cs) = deescapeslash ('\\':s) cs
- deescapeslash s ('%':'%':cs) = deescapeslash ('%':s) cs
- deescapeslash s (c:cs) = deescapeslash (c:s) cs
+ deescapeslash s ('%':escapedc:cs) = deescapeslash ([escapedc]:s) cs
+ deescapeslash s (c1:c2:c3:cs)
+ | [c1,c2,c3] == pseudoSlash = deescapeslash ("/":s) cs
+ | [c1,c2,c3] == pseudoBackslash = deescapeslash ("\\":s) cs
+ | otherwise = deescapeslash ([c1]:s) (c2:c3:cs)
+ deescapeslash s cs = concat (reverse (cs:s))
prop_viewPath_roundtrips :: MetaValue -> Bool
prop_viewPath_roundtrips v = fromViewPath (toViewPath v) == v