split out two more Git modules
This commit is contained in:
parent
25b2cc4148
commit
9db8ec210f
8 changed files with 139 additions and 117 deletions
|
@ -22,6 +22,7 @@ import System.Posix.Files
|
||||||
import Common.Annex
|
import Common.Annex
|
||||||
import qualified Git
|
import qualified Git
|
||||||
import qualified Git.Config
|
import qualified Git.Config
|
||||||
|
import qualified Git.CheckAttr
|
||||||
import qualified Annex
|
import qualified Annex
|
||||||
import Types.Key
|
import Types.Key
|
||||||
import qualified Types.Backend as B
|
import qualified Types.Backend as B
|
||||||
|
@ -103,7 +104,7 @@ chooseBackends :: [FilePath] -> Annex [BackendFile]
|
||||||
chooseBackends fs = Annex.getState Annex.forcebackend >>= go
|
chooseBackends fs = Annex.getState Annex.forcebackend >>= go
|
||||||
where
|
where
|
||||||
go Nothing = do
|
go Nothing = do
|
||||||
pairs <- inRepo $ Git.checkAttr "annex.backend" fs
|
pairs <- inRepo $ Git.CheckAttr.lookup "annex.backend" fs
|
||||||
return $ map (\(f,b) -> (maybeLookupBackendName b, f)) pairs
|
return $ map (\(f,b) -> (maybeLookupBackendName b, f)) pairs
|
||||||
go (Just _) = do
|
go (Just _) = do
|
||||||
l <- orderedList
|
l <- orderedList
|
||||||
|
|
113
Git.hs
113
Git.hs
|
@ -45,25 +45,16 @@ module Git (
|
||||||
repoRemoteName,
|
repoRemoteName,
|
||||||
repoRemoteNameSet,
|
repoRemoteNameSet,
|
||||||
repoRemoteNameFromKey,
|
repoRemoteNameFromKey,
|
||||||
checkAttr,
|
|
||||||
decodeGitFile,
|
|
||||||
encodeGitFile,
|
|
||||||
reap,
|
reap,
|
||||||
useIndex,
|
useIndex,
|
||||||
getSha,
|
getSha,
|
||||||
shaSize,
|
shaSize,
|
||||||
assertLocal,
|
assertLocal,
|
||||||
|
|
||||||
prop_idempotent_deencode
|
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import qualified Data.Map as M hiding (map, split)
|
import qualified Data.Map as M
|
||||||
import Network.URI
|
import Network.URI
|
||||||
import Data.Char
|
import Data.Char
|
||||||
import Data.Word (Word8)
|
|
||||||
import Codec.Binary.UTF8.String (encode)
|
|
||||||
import Text.Printf
|
|
||||||
import System.Exit
|
|
||||||
import System.Posix.Env (setEnv, unsetEnv, getEnv)
|
import System.Posix.Env (setEnv, unsetEnv, getEnv)
|
||||||
import qualified Data.ByteString.Lazy.Char8 as L
|
import qualified Data.ByteString.Lazy.Char8 as L
|
||||||
|
|
||||||
|
@ -360,105 +351,3 @@ configTrue s = map toLower s == "true"
|
||||||
{- Access to raw config Map -}
|
{- Access to raw config Map -}
|
||||||
configMap :: Repo -> M.Map String String
|
configMap :: Repo -> M.Map String String
|
||||||
configMap = config
|
configMap = config
|
||||||
|
|
||||||
{- Efficiently looks up a gitattributes value for each file in a list. -}
|
|
||||||
checkAttr :: String -> [FilePath] -> Repo -> IO [(FilePath, String)]
|
|
||||||
checkAttr attr files repo = do
|
|
||||||
-- git check-attr needs relative filenames input; it will choke
|
|
||||||
-- on some absolute filenames. This also means it will output
|
|
||||||
-- all relative filenames.
|
|
||||||
cwd <- getCurrentDirectory
|
|
||||||
let relfiles = map (relPathDirToFile cwd . absPathFrom cwd) files
|
|
||||||
(_, fromh, toh) <- hPipeBoth "git" (toCommand params)
|
|
||||||
_ <- forkProcess $ do
|
|
||||||
hClose fromh
|
|
||||||
hPutStr toh $ join "\0" relfiles
|
|
||||||
hClose toh
|
|
||||||
exitSuccess
|
|
||||||
hClose toh
|
|
||||||
(map topair . lines) <$> hGetContents fromh
|
|
||||||
where
|
|
||||||
params = gitCommandLine
|
|
||||||
[ Param "check-attr"
|
|
||||||
, Param attr
|
|
||||||
, Params "-z --stdin"
|
|
||||||
] repo
|
|
||||||
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. Decode that (annoyingly
|
|
||||||
- complex) encoding. -}
|
|
||||||
decodeGitFile :: String -> FilePath
|
|
||||||
decodeGitFile [] = []
|
|
||||||
decodeGitFile f@(c:s)
|
|
||||||
-- encoded strings will be inside double quotes
|
|
||||||
| c == '"' = unescape ("", middle)
|
|
||||||
| otherwise = f
|
|
||||||
where
|
|
||||||
e = '\\'
|
|
||||||
middle = init s
|
|
||||||
unescape (b, []) = b
|
|
||||||
-- look for escapes starting with '\'
|
|
||||||
unescape (b, v) = b ++ beginning ++ unescape (decode rest)
|
|
||||||
where
|
|
||||||
pair = span (/= e) v
|
|
||||||
beginning = fst pair
|
|
||||||
rest = snd pair
|
|
||||||
isescape x = x == e
|
|
||||||
-- \NNN is an octal encoded character
|
|
||||||
decode (x:n1:n2:n3:rest)
|
|
||||||
| isescape x && alloctal = (fromoctal, rest)
|
|
||||||
where
|
|
||||||
alloctal = isOctDigit n1 &&
|
|
||||||
isOctDigit n2 &&
|
|
||||||
isOctDigit n3
|
|
||||||
fromoctal = [chr $ readoctal [n1, n2, n3]]
|
|
||||||
readoctal o = read $ "0o" ++ o :: Int
|
|
||||||
-- \C is used for a few special characters
|
|
||||||
decode (x:nc:rest)
|
|
||||||
| isescape x = ([echar nc], rest)
|
|
||||||
where
|
|
||||||
echar 'a' = '\a'
|
|
||||||
echar 'b' = '\b'
|
|
||||||
echar 'f' = '\f'
|
|
||||||
echar 'n' = '\n'
|
|
||||||
echar 'r' = '\r'
|
|
||||||
echar 't' = '\t'
|
|
||||||
echar 'v' = '\v'
|
|
||||||
echar a = a
|
|
||||||
decode n = ("", n)
|
|
||||||
|
|
||||||
{- Should not need to use this, except for testing decodeGitFile. -}
|
|
||||||
encodeGitFile :: FilePath -> String
|
|
||||||
encodeGitFile s = foldl (++) "\"" (map echar s) ++ "\""
|
|
||||||
where
|
|
||||||
e c = '\\' : [c]
|
|
||||||
echar '\a' = e 'a'
|
|
||||||
echar '\b' = e 'b'
|
|
||||||
echar '\f' = e 'f'
|
|
||||||
echar '\n' = e 'n'
|
|
||||||
echar '\r' = e 'r'
|
|
||||||
echar '\t' = e 't'
|
|
||||||
echar '\v' = e 'v'
|
|
||||||
echar '\\' = e '\\'
|
|
||||||
echar '"' = e '"'
|
|
||||||
echar x
|
|
||||||
| ord x < 0x20 = e_num x -- low ascii
|
|
||||||
| ord x >= 256 = e_utf x
|
|
||||||
| ord x > 0x7E = e_num x -- high ascii
|
|
||||||
| otherwise = [x] -- printable ascii
|
|
||||||
where
|
|
||||||
showoctal i = '\\' : printf "%03o" i
|
|
||||||
e_num c = showoctal $ ord c
|
|
||||||
-- unicode character is decomposed to
|
|
||||||
-- Word8s and each is shown in octal
|
|
||||||
e_utf c = showoctal =<< (encode [c] :: [Word8])
|
|
||||||
|
|
||||||
{- for quickcheck -}
|
|
||||||
prop_idempotent_deencode :: String -> Bool
|
|
||||||
prop_idempotent_deencode s = s == decodeGitFile (encodeGitFile s)
|
|
||||||
|
|
44
Git/CheckAttr.hs
Normal file
44
Git/CheckAttr.hs
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
{- git check-attr interface
|
||||||
|
-
|
||||||
|
- Copyright 2010, 2011 Joey Hess <joey@kitenet.net>
|
||||||
|
-
|
||||||
|
- Licensed under the GNU GPL version 3 or higher.
|
||||||
|
-}
|
||||||
|
|
||||||
|
module Git.CheckAttr where
|
||||||
|
|
||||||
|
import System.Exit
|
||||||
|
|
||||||
|
import Common
|
||||||
|
import Git
|
||||||
|
import qualified Git.Filename
|
||||||
|
|
||||||
|
{- Efficiently looks up a gitattributes value for each file in a list. -}
|
||||||
|
lookup :: String -> [FilePath] -> Repo -> IO [(FilePath, String)]
|
||||||
|
lookup attr files repo = do
|
||||||
|
-- git check-attr needs relative filenames input; it will choke
|
||||||
|
-- on some absolute filenames. This also means it will output
|
||||||
|
-- all relative filenames.
|
||||||
|
cwd <- getCurrentDirectory
|
||||||
|
let relfiles = map (relPathDirToFile cwd . absPathFrom cwd) files
|
||||||
|
(_, fromh, toh) <- hPipeBoth "git" (toCommand params)
|
||||||
|
_ <- forkProcess $ do
|
||||||
|
hClose fromh
|
||||||
|
hPutStr toh $ join "\0" relfiles
|
||||||
|
hClose toh
|
||||||
|
exitSuccess
|
||||||
|
hClose toh
|
||||||
|
(map topair . lines) <$> hGetContents fromh
|
||||||
|
where
|
||||||
|
params = gitCommandLine
|
||||||
|
[ Param "check-attr"
|
||||||
|
, Param attr
|
||||||
|
, Params "-z --stdin"
|
||||||
|
] repo
|
||||||
|
topair l = (file, value)
|
||||||
|
where
|
||||||
|
file = Git.Filename.decode $ join sep $ take end bits
|
||||||
|
value = bits !! end
|
||||||
|
end = length bits - 1
|
||||||
|
bits = split sep l
|
||||||
|
sep = ": " ++ attr ++ ": "
|
84
Git/Filename.hs
Normal file
84
Git/Filename.hs
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
{- Some git commands output encoded filenames, in a rather annoyingly complex
|
||||||
|
- C-style encoding.
|
||||||
|
-
|
||||||
|
- Copyright 2010, 2011 Joey Hess <joey@kitenet.net>
|
||||||
|
-
|
||||||
|
- Licensed under the GNU GPL version 3 or higher.
|
||||||
|
-}
|
||||||
|
|
||||||
|
module Git.Filename where
|
||||||
|
|
||||||
|
import qualified Codec.Binary.UTF8.String
|
||||||
|
import Data.Char
|
||||||
|
import Data.Word (Word8)
|
||||||
|
import Text.Printf
|
||||||
|
|
||||||
|
decode :: String -> FilePath
|
||||||
|
decode [] = []
|
||||||
|
decode f@(c:s)
|
||||||
|
-- encoded strings will be inside double quotes
|
||||||
|
| c == '"' = unescape ("", middle)
|
||||||
|
| otherwise = f
|
||||||
|
where
|
||||||
|
e = '\\'
|
||||||
|
middle = init s
|
||||||
|
unescape (b, []) = b
|
||||||
|
-- look for escapes starting with '\'
|
||||||
|
unescape (b, v) = b ++ beginning ++ unescape (handle rest)
|
||||||
|
where
|
||||||
|
pair = span (/= e) v
|
||||||
|
beginning = fst pair
|
||||||
|
rest = snd pair
|
||||||
|
isescape x = x == e
|
||||||
|
-- \NNN is an octal encoded character
|
||||||
|
handle (x:n1:n2:n3:rest)
|
||||||
|
| isescape x && alloctal = (fromoctal, rest)
|
||||||
|
where
|
||||||
|
alloctal = isOctDigit n1 &&
|
||||||
|
isOctDigit n2 &&
|
||||||
|
isOctDigit n3
|
||||||
|
fromoctal = [chr $ readoctal [n1, n2, n3]]
|
||||||
|
readoctal o = read $ "0o" ++ o :: Int
|
||||||
|
-- \C is used for a few special characters
|
||||||
|
handle (x:nc:rest)
|
||||||
|
| isescape x = ([echar nc], rest)
|
||||||
|
where
|
||||||
|
echar 'a' = '\a'
|
||||||
|
echar 'b' = '\b'
|
||||||
|
echar 'f' = '\f'
|
||||||
|
echar 'n' = '\n'
|
||||||
|
echar 'r' = '\r'
|
||||||
|
echar 't' = '\t'
|
||||||
|
echar 'v' = '\v'
|
||||||
|
echar a = a
|
||||||
|
handle n = ("", n)
|
||||||
|
|
||||||
|
{- Should not need to use this, except for testing decode. -}
|
||||||
|
encode :: FilePath -> String
|
||||||
|
encode s = foldl (++) "\"" (map echar s) ++ "\""
|
||||||
|
where
|
||||||
|
e c = '\\' : [c]
|
||||||
|
echar '\a' = e 'a'
|
||||||
|
echar '\b' = e 'b'
|
||||||
|
echar '\f' = e 'f'
|
||||||
|
echar '\n' = e 'n'
|
||||||
|
echar '\r' = e 'r'
|
||||||
|
echar '\t' = e 't'
|
||||||
|
echar '\v' = e 'v'
|
||||||
|
echar '\\' = e '\\'
|
||||||
|
echar '"' = e '"'
|
||||||
|
echar x
|
||||||
|
| ord x < 0x20 = e_num x -- low ascii
|
||||||
|
| ord x >= 256 = e_utf x
|
||||||
|
| ord x > 0x7E = e_num x -- high ascii
|
||||||
|
| otherwise = [x] -- printable ascii
|
||||||
|
where
|
||||||
|
showoctal i = '\\' : printf "%03o" i
|
||||||
|
e_num c = showoctal $ ord c
|
||||||
|
-- unicode character is decomposed to
|
||||||
|
-- Word8s and each is shown in octal
|
||||||
|
e_utf c = showoctal =<< (Codec.Binary.UTF8.String.encode [c] :: [Word8])
|
||||||
|
|
||||||
|
{- for quickcheck -}
|
||||||
|
prop_idempotent_deencode :: String -> Bool
|
||||||
|
prop_idempotent_deencode s = s == decode (encode s)
|
|
@ -17,6 +17,7 @@ import System.Posix.Types
|
||||||
import qualified Data.ByteString.Lazy.Char8 as L
|
import qualified Data.ByteString.Lazy.Char8 as L
|
||||||
|
|
||||||
import Git
|
import Git
|
||||||
|
import qualified Git.Filename
|
||||||
import Utility.SafeCommand
|
import Utility.SafeCommand
|
||||||
|
|
||||||
data TreeItem = TreeItem
|
data TreeItem = TreeItem
|
||||||
|
@ -38,7 +39,7 @@ parseLsTree l = TreeItem
|
||||||
{ mode = fst $ head $ readOct $ L.unpack m
|
{ mode = fst $ head $ readOct $ L.unpack m
|
||||||
, typeobj = L.unpack t
|
, typeobj = L.unpack t
|
||||||
, sha = L.unpack s
|
, sha = L.unpack s
|
||||||
, file = decodeGitFile $ L.unpack f
|
, file = Git.Filename.decode $ L.unpack f
|
||||||
}
|
}
|
||||||
where
|
where
|
||||||
-- l = <mode> SP <type> SP <sha> TAB <file>
|
-- l = <mode> SP <type> SP <sha> TAB <file>
|
||||||
|
|
3
Seek.hs
3
Seek.hs
|
@ -18,6 +18,7 @@ import Backend
|
||||||
import qualified Annex
|
import qualified Annex
|
||||||
import qualified Git
|
import qualified Git
|
||||||
import qualified Git.LsFiles as LsFiles
|
import qualified Git.LsFiles as LsFiles
|
||||||
|
import qualified Git.CheckAttr
|
||||||
import qualified Limit
|
import qualified Limit
|
||||||
|
|
||||||
seekHelper :: ([FilePath] -> Git.Repo -> IO [FilePath]) -> [FilePath] -> Annex [FilePath]
|
seekHelper :: ([FilePath] -> Git.Repo -> IO [FilePath]) -> [FilePath] -> Annex [FilePath]
|
||||||
|
@ -31,7 +32,7 @@ withFilesInGit a params = prepFiltered a $ seekHelper LsFiles.inRepo params
|
||||||
withAttrFilesInGit :: String -> ((FilePath, String) -> CommandStart) -> CommandSeek
|
withAttrFilesInGit :: String -> ((FilePath, String) -> CommandStart) -> CommandSeek
|
||||||
withAttrFilesInGit attr a params = do
|
withAttrFilesInGit attr a params = do
|
||||||
files <- seekHelper LsFiles.inRepo params
|
files <- seekHelper LsFiles.inRepo params
|
||||||
prepFilteredGen a fst $ inRepo $ Git.checkAttr attr files
|
prepFilteredGen a fst $ inRepo $ Git.CheckAttr.lookup attr files
|
||||||
|
|
||||||
withNumCopies :: (Maybe Int -> FilePath -> CommandStart) -> CommandSeek
|
withNumCopies :: (Maybe Int -> FilePath -> CommandStart) -> CommandSeek
|
||||||
withNumCopies a params = withAttrFilesInGit "annex.numcopies" go params
|
withNumCopies a params = withAttrFilesInGit "annex.numcopies" go params
|
||||||
|
|
|
@ -11,6 +11,7 @@ import Common
|
||||||
import qualified Git.UnionMerge
|
import qualified Git.UnionMerge
|
||||||
import qualified Git.Config
|
import qualified Git.Config
|
||||||
import qualified Git.Construct
|
import qualified Git.Construct
|
||||||
|
import qualified Git.Branch
|
||||||
import qualified Git
|
import qualified Git
|
||||||
|
|
||||||
header :: String
|
header :: String
|
||||||
|
@ -44,5 +45,5 @@ main = do
|
||||||
_ <- Git.useIndex (tmpIndex g)
|
_ <- Git.useIndex (tmpIndex g)
|
||||||
setup g
|
setup g
|
||||||
Git.UnionMerge.merge aref bref g
|
Git.UnionMerge.merge aref bref g
|
||||||
_ <- Git.commit "union merge" newref [aref, bref] g
|
_ <- Git.Branch.commit "union merge" newref [aref, bref] g
|
||||||
cleanup g
|
cleanup g
|
||||||
|
|
3
test.hs
3
test.hs
|
@ -27,6 +27,7 @@ import qualified Backend
|
||||||
import qualified Git
|
import qualified Git
|
||||||
import qualified Git.Config
|
import qualified Git.Config
|
||||||
import qualified Git.Construct
|
import qualified Git.Construct
|
||||||
|
import qualified Git.Filename
|
||||||
import qualified Locations
|
import qualified Locations
|
||||||
import qualified Types.Backend
|
import qualified Types.Backend
|
||||||
import qualified Types
|
import qualified Types
|
||||||
|
@ -69,7 +70,7 @@ propigate (Counts { errors = e , failures = f }, _)
|
||||||
|
|
||||||
quickcheck :: Test
|
quickcheck :: Test
|
||||||
quickcheck = TestLabel "quickcheck" $ TestList
|
quickcheck = TestLabel "quickcheck" $ TestList
|
||||||
[ qctest "prop_idempotent_deencode" Git.prop_idempotent_deencode
|
[ qctest "prop_idempotent_deencode" Git.Filename.prop_idempotent_deencode
|
||||||
, qctest "prop_idempotent_fileKey" Locations.prop_idempotent_fileKey
|
, qctest "prop_idempotent_fileKey" Locations.prop_idempotent_fileKey
|
||||||
, qctest "prop_idempotent_key_read_show" Types.Key.prop_idempotent_key_read_show
|
, qctest "prop_idempotent_key_read_show" Types.Key.prop_idempotent_key_read_show
|
||||||
, qctest "prop_idempotent_shellEscape" Utility.SafeCommand.prop_idempotent_shellEscape
|
, qctest "prop_idempotent_shellEscape" Utility.SafeCommand.prop_idempotent_shellEscape
|
||||||
|
|
Loading…
Add table
Reference in a new issue