aboutsummaryrefslogtreecommitdiff
path: root/Annex
diff options
context:
space:
mode:
authorGravatar Joey Hess <joeyh@joeyh.name>2016-09-26 16:47:59 -0400
committerGravatar Joey Hess <joeyh@joeyh.name>2016-09-26 16:48:57 -0400
commit4c025e7ea806c5416bcafe3283c49746875b7bcd (patch)
tree9d32e1f3c27bd4e3e9388839e7cff7f3687ed4a2 /Annex
parentf468c42146ff164936b8138271793323e893acf8 (diff)
Optimisations to time it takes git-annex to walk working tree and find files to work on. Sped up by around 18%.
key2file and file2key were top cost centers according to profiling. The repeated use of replace was not efficient. This new approach is quite a lot more efficient. This commit was sponsored by Denis Dzyubenko on Patreon.
Diffstat (limited to 'Annex')
-rw-r--r--Annex/Locations.hs20
1 files changed, 15 insertions, 5 deletions
diff --git a/Annex/Locations.hs b/Annex/Locations.hs
index 058993cd2..a6af4d417 100644
--- a/Annex/Locations.hs
+++ b/Annex/Locations.hs
@@ -452,15 +452,25 @@ preSanitizeKeyName = concatMap escape
- can cause existing objects to get lost.
-}
keyFile :: Key -> FilePath
-keyFile key = replace "/" "%" $ replace ":" "&c" $
- replace "%" "&s" $ replace "&" "&a" $ key2file key
+keyFile = concatMap esc . key2file
+ where
+ esc '&' = "&a"
+ esc '%' = "&s"
+ esc ':' = "&c"
+ esc '/' = "%"
+ esc c = [c]
{- Reverses keyFile, converting a filename fragment (ie, the basename of
- the symlink target) into a key. -}
fileKey :: FilePath -> Maybe Key
-fileKey file = file2key $
- replace "&a" "&" $ replace "&s" "%" $
- replace "&c" ":" $ replace "%" "/" file
+fileKey = file2key . unesc []
+ where
+ unesc r [] = reverse r
+ unesc r ('%':cs) = unesc ('/':r) cs
+ unesc r ('&':'c':cs) = unesc (':':r) cs
+ unesc r ('&':'s':cs) = unesc ('%':r) cs
+ unesc r ('&':'a':cs) = unesc ('&':r) cs
+ unesc r (c:cs) = unesc (c:r) cs
{- for quickcheck -}
prop_isomorphic_fileKey :: String -> Bool