git-repair 1.20151215 → 1.20161111
raw patch · 49 files changed
+550/−494 lines, 49 filessetup-changed
Files
- .gitignore +0/−3
- Build/Configure.hs +2/−0
- Build/TestConfig.hs +3/−1
- Build/Version.hs +7/−5
- Build/collect-ghc-options.sh +0/−12
- Build/make-sdist.sh +0/−21
- CHANGELOG +13/−0
- Git.hs +11/−2
- Git/Branch.hs +58/−22
- Git/CatFile.hs +102/−28
- Git/Command.hs +4/−2
- Git/Construct.hs +1/−0
- Git/FilePath.hs +13/−4
- Git/Fsck.hs +50/−17
- Git/Index.hs +18/−3
- Git/LsTree.hs +21/−12
- Git/Ref.hs +10/−8
- Git/Repair.hs +2/−2
- Git/Types.hs +22/−1
- Makefile +0/−34
- Setup.hs +2/−0
- Utility/CoProcess.hs +8/−14
- Utility/Directory.hs +7/−2
- Utility/Exception.hs +16/−2
- Utility/FileMode.hs +2/−1
- Utility/FileSize.hs +4/−2
- Utility/FileSystemEncoding.hs +8/−0
- Utility/Format.hs +4/−4
- Utility/Metered.hs +24/−1
- Utility/Path.hs +14/−8
- Utility/PosixFiles.hs +9/−1
- Utility/Process.hs +7/−5
- Utility/QuickCheck.hs +7/−3
- Utility/Rsync.hs +3/−3
- Utility/SystemDirectory.hs +16/−0
- Utility/Tmp.hs +1/−1
- Utility/UserInfo.hs +8/−9
- configure.hs +0/−6
- debian/changelog +0/−105
- debian/compat +0/−1
- debian/control +0/−36
- debian/copyright +0/−35
- debian/git-repair.lintian-overrides +0/−1
- debian/manpages +0/−1
- debian/rules +0/−10
- doc/index.mdwn +0/−55
- doc/news/version_1.20141027.mdwn +0/−1
- doc/news/version_1.20151215.mdwn +0/−5
- git-repair.cabal +73/−5
− .gitignore
@@ -1,3 +0,0 @@-Build/SysConfig.hs-tags-git-repair
Build/Configure.hs view
@@ -1,5 +1,7 @@ {- Checks system configuration and generates SysConfig.hs. -} +{-# OPTIONS_GHC -fno-warn-tabs #-}+ module Build.Configure where import System.Environment
Build/TestConfig.hs view
@@ -1,14 +1,16 @@ {- Tests the system and generates Build.SysConfig.hs. -} +{-# OPTIONS_GHC -fno-warn-tabs #-}+ module Build.TestConfig where import Utility.Path import Utility.Monad import Utility.SafeCommand+import Utility.Directory import System.IO import System.FilePath-import System.Directory type ConfigKey = String data ConfigValue =
Build/Version.hs view
@@ -1,24 +1,26 @@ {- Package version determination, for configure script. -} +{-# OPTIONS_GHC -fno-warn-tabs #-}+ module Build.Version where -import Data.Maybe-import Control.Applicative import Data.List import System.Environment-import System.Directory import Data.Char import System.Process+import Control.Applicative+import Prelude import Utility.Monad import Utility.Exception+import Utility.Directory type Version = String {- Set when making an official release. (Distribution vendors should set - this too.) -} isReleaseBuild :: IO Bool-isReleaseBuild = isJust <$> catchMaybeIO (getEnv "RELEASE_BUILD")+isReleaseBuild = (== Just "1") <$> catchMaybeIO (getEnv "RELEASE_BUILD") {- Version is usually based on the major version from the changelog, - plus the date of the last commit, plus the git rev of that commit.@@ -44,7 +46,7 @@ getChangelogVersion :: IO Version getChangelogVersion = do- changelog <- readFile "debian/changelog"+ changelog <- readFile "CHANGELOG" let verline = takeWhile (/= '\n') changelog return $ middle (words verline !! 1) where
− Build/collect-ghc-options.sh
@@ -1,12 +0,0 @@-#!/bin/sh-# Generate --ghc-options to pass LDFLAGS, CFLAGS, and CPPFLAGS through ghc-# and on to ld, cc, and cpp.-for w in $LDFLAGS; do- printf -- "-optl%s\n" "$w"-done-for w in $CFLAGS; do- printf -- "-optc%s\n" "$w"-done-for w in $CPPFLAGS; do- printf -- "-optc-Wp,%s\n" "$w"-done
− Build/make-sdist.sh
@@ -1,21 +0,0 @@-#!/bin/sh-#-# Workaround for `cabal sdist` requiring all included files to be listed-# in .cabal.--# Create target directory-sdist_dir=git-repair-$(grep '^Version:' git-repair.cabal | sed -re 's/Version: *//')-mkdir --parents dist/$sdist_dir--find . \( -name .git -or -name dist -or -name cabal-dev \) -prune \- -or -not -name \\*.orig -not -type d -print \-| perl -ne "print unless length >= 100 - length q{$sdist_dir}" \-| xargs cp --parents --target-directory dist/$sdist_dir--cd dist-tar --format=ustar -caf $sdist_dir.tar.gz $sdist_dir--# Check that tarball can be unpacked by cabal.-# It's picky about tar longlinks etc.-rm -rf $sdist_dir-cabal unpack $sdist_dir.tar.gz
CHANGELOG view
@@ -1,3 +1,16 @@+git-repair (1.20161111) unstable; urgency=medium++ * git-repair.cabal: Add Setup-Depends.+ * Updated cabal file explictly lists source files. The tarball+ on hackage will include only the files needed for cabal install;+ it is NOT the full git-repair source tree.+ * debian/changelog: Converted to symlinks to CHANGELOG.+ * Merge from git-annex.+ * Makefile: Support building with stack as well as cabal.+ * Makefile: The CABAL variable has been renamed to BUILDER.++ -- Joey Hess <id@joeyh.name> Fri, 11 Nov 2016 14:56:14 -0400+ git-repair (1.20151215) unstable; urgency=medium * Fix insecure temporary permissions and potential denial of
Git.hs view
@@ -26,8 +26,10 @@ repoDescribe, repoLocation, repoPath,+ repoWorkTree, localGitDir, attributes,+ attributesLocal, hookPath, assertLocal, adjustPath,@@ -72,6 +74,10 @@ repoPath Repo { location = LocalUnknown dir } = dir repoPath Repo { location = Unknown } = error "unknown repoPath" +repoWorkTree :: Repo -> Maybe FilePath+repoWorkTree Repo { location = Local { worktree = Just d } } = Just d+repoWorkTree _ = Nothing+ {- Path to a local repository's .git directory. -} localGitDir :: Repo -> FilePath localGitDir Repo { location = Local { gitdir = d } } = d@@ -125,8 +131,11 @@ {- Path to a repository's gitattributes file. -} attributes :: Repo -> FilePath attributes repo- | repoIsLocalBare repo = repoPath repo ++ "/info/.gitattributes"- | otherwise = repoPath repo ++ "/.gitattributes"+ | repoIsLocalBare repo = attributesLocal repo+ | otherwise = repoPath repo </> ".gitattributes"++attributesLocal :: Repo -> FilePath+attributesLocal repo = localGitDir repo </> "info" </> "attributes" {- Path to a given hook script in a repository, only if the hook exists - and is executable. -}
Git/Branch.hs view
@@ -13,6 +13,7 @@ import Git import Git.Sha import Git.Command+import qualified Git.Config import qualified Git.Ref import qualified Git.BuildVersion @@ -23,7 +24,7 @@ - branch is not created yet. So, this also looks at show-ref HEAD - to double-check. -}-current :: Repo -> IO (Maybe Git.Ref)+current :: Repo -> IO (Maybe Branch) current r = do v <- currentUnsafe r case v of@@ -35,7 +36,7 @@ ) {- The current branch, which may not really exist yet. -}-currentUnsafe :: Repo -> IO (Maybe Git.Ref)+currentUnsafe :: Repo -> IO (Maybe Branch) currentUnsafe r = parse . firstLine <$> pipeReadStrict [Param "symbolic-ref", Param "-q", Param $ fromRef Git.Ref.headRef] r where@@ -48,15 +49,25 @@ changed :: Branch -> Branch -> Repo -> IO Bool changed origbranch newbranch repo | origbranch == newbranch = return False- | otherwise = not . null <$> diffs+ | otherwise = not . null+ <$> changed' origbranch newbranch [Param "-n1"] repo where- diffs = pipeReadStrict++changed' :: Branch -> Branch -> [CommandParam] -> Repo -> IO String+changed' origbranch newbranch extraps repo = pipeReadStrict ps repo+ where+ ps = [ Param "log" , Param (fromRef origbranch ++ ".." ++ fromRef newbranch)- , Param "-n1" , Param "--pretty=%H"- ] repo+ ] ++ extraps +{- Lists commits that are in the second branch and not in the first branch. -}+changedCommits :: Branch -> Branch -> [CommandParam] -> Repo -> IO [Sha]+changedCommits origbranch newbranch extraps repo = + catMaybes . map extractSha . lines+ <$> changed' origbranch newbranch extraps repo+ {- Check if it's possible to fast-forward from the old - ref to the new ref. -@@ -90,7 +101,7 @@ where no_ff = return False do_ff to = do- update branch to repo+ update' branch to repo return True findbest c [] = return $ Just c findbest c (r:rs)@@ -104,27 +115,37 @@ (False, True) -> findbest c rs -- worse (False, False) -> findbest c rs -- same -{- The user may have set commit.gpgsign, indending all their manual+{- The user may have set commit.gpgsign, intending all their manual - commits to be signed. But signing automatic/background commits could - easily lead to unwanted gpg prompts or failures. -} data CommitMode = ManualCommit | AutomaticCommit deriving (Eq) +{- Prevent signing automatic commits. -} applyCommitMode :: CommitMode -> [CommandParam] -> [CommandParam] applyCommitMode commitmode ps | commitmode == AutomaticCommit && not (Git.BuildVersion.older "2.0.0") = Param "--no-gpg-sign" : ps | otherwise = ps +{- Some versions of git commit-tree honor commit.gpgsign themselves,+ - but others need -S to be passed to enable gpg signing of manual commits. -}+applyCommitModeForCommitTree :: CommitMode -> [CommandParam] -> Repo -> [CommandParam]+applyCommitModeForCommitTree commitmode ps r+ | commitmode == ManualCommit =+ case (Git.Config.getMaybe "commit.gpgsign" r) of+ Just s | Git.Config.isTrue s == Just True ->+ Param "-S":ps+ _ -> ps'+ | otherwise = ps'+ where+ ps' = applyCommitMode commitmode ps+ {- Commit via the usual git command. -} commitCommand :: CommitMode -> [CommandParam] -> Repo -> IO Bool commitCommand = commitCommand' runBool -{- Commit will fail when the tree is clean. This suppresses that error. -}-commitQuiet :: CommitMode -> [CommandParam] -> Repo -> IO ()-commitQuiet commitmode ps = void . tryIO . commitCommand' runQuiet commitmode ps- commitCommand' :: ([CommandParam] -> Repo -> IO a) -> CommitMode -> [CommandParam] -> Repo -> IO a commitCommand' runner commitmode ps = runner $ Param "commit" : applyCommitMode commitmode ps@@ -144,36 +165,51 @@ pipeReadStrict [Param "write-tree"] repo ifM (cancommit tree) ( do- sha <- getSha "commit-tree" $- pipeWriteRead ([Param "commit-tree", Param (fromRef tree)] ++ ps) sendmsg repo- update branch sha repo+ sha <- commitTree commitmode message parentrefs tree repo+ update' branch sha repo return $ Just sha , return Nothing ) where- ps = applyCommitMode commitmode $- map Param $ concatMap (\r -> ["-p", fromRef r]) parentrefs cancommit tree | allowempty = return True | otherwise = case parentrefs of [p] -> maybe False (tree /=) <$> Git.Ref.tree p repo _ -> return True- sendmsg = Just $ flip hPutStr message commitAlways :: CommitMode -> String -> Branch -> [Ref] -> Repo -> IO Sha commitAlways commitmode message branch parentrefs repo = fromJust <$> commit commitmode True message branch parentrefs repo +commitTree :: CommitMode -> String -> [Ref] -> Ref -> Repo -> IO Sha+commitTree commitmode message parentrefs tree repo =+ getSha "commit-tree" $+ pipeWriteRead ([Param "commit-tree", Param (fromRef tree)] ++ ps)+ sendmsg repo+ where+ sendmsg = Just $ flip hPutStr message+ ps = applyCommitModeForCommitTree commitmode parentparams repo+ parentparams = map Param $ concatMap (\r -> ["-p", fromRef r]) parentrefs+ {- A leading + makes git-push force pushing a branch. -} forcePush :: String -> String forcePush b = "+" ++ b -{- Updates a branch (or other ref) to a new Sha. -}-update :: Branch -> Sha -> Repo -> IO ()-update branch sha = run +{- Updates a branch (or other ref) to a new Sha or branch Ref. -}+update :: String -> Branch -> Ref -> Repo -> IO ()+update message branch r = run [ Param "update-ref"+ , Param "-m"+ , Param message , Param $ fromRef branch- , Param $ fromRef sha+ , Param $ fromRef r+ ]++update' :: Branch -> Ref -> Repo -> IO ()+update' branch r = run+ [ Param "update-ref"+ , Param $ fromRef branch+ , Param $ fromRef r ] {- Checks out a branch, creating it if necessary. -}
Git/CatFile.hs view
@@ -1,6 +1,6 @@ {- git cat-file interface -- - Copyright 2011, 2013 Joey Hess <id@joeyh.name>+ - Copyright 2011-2016 Joey Hess <id@joeyh.name> - - Licensed under the GNU GPL version 3 or higher. -}@@ -13,13 +13,19 @@ catFile, catFileDetails, catTree,+ catCommit, catObject, catObjectDetails,+ catObjectMetaData, ) where import System.IO import qualified Data.ByteString as S import qualified Data.ByteString.Lazy as L+import qualified Data.ByteString.Lazy.Char8 as L8+import qualified Data.Map as M+import Data.String+import Data.Char import Data.Tuple.Utils import Numeric import System.Posix.Types@@ -32,21 +38,28 @@ import Git.FilePath import qualified Utility.CoProcess as CoProcess -data CatFileHandle = CatFileHandle CoProcess.CoProcessHandle Repo+data CatFileHandle = CatFileHandle + { catFileProcess :: CoProcess.CoProcessHandle+ , checkFileProcess :: CoProcess.CoProcessHandle+ } catFileStart :: Repo -> IO CatFileHandle catFileStart = catFileStart' True catFileStart' :: Bool -> Repo -> IO CatFileHandle-catFileStart' restartable repo = do- coprocess <- CoProcess.rawMode =<< gitCoProcessStart restartable+catFileStart' restartable repo = CatFileHandle+ <$> startp "--batch"+ <*> startp "--batch-check=%(objectname) %(objecttype) %(objectsize)"+ where+ startp p = gitCoProcessStart restartable [ Param "cat-file"- , Param "--batch"+ , Param p ] repo- return $ CatFileHandle coprocess repo catFileStop :: CatFileHandle -> IO ()-catFileStop (CatFileHandle p _) = CoProcess.stop p+catFileStop h = do+ CoProcess.stop (catFileProcess h)+ CoProcess.stop (checkFileProcess h) {- Reads a file from a specified branch. -} catFile :: CatFileHandle -> Branch -> FilePath -> IO L.ByteString@@ -63,32 +76,52 @@ catObject h object = maybe L.empty fst3 <$> catObjectDetails h object catObjectDetails :: CatFileHandle -> Ref -> IO (Maybe (L.ByteString, Sha, ObjectType))-catObjectDetails (CatFileHandle hdl _) object = CoProcess.query hdl send receive+catObjectDetails h object = query (catFileProcess h) object $ \from -> do+ header <- hGetLine from+ case parseResp object header of+ Just (ParsedResp sha size objtype) -> do+ content <- S.hGet from (fromIntegral size)+ eatchar '\n' from+ return $ Just (L.fromChunks [content], sha, objtype)+ Just DNE -> return Nothing+ Nothing -> error $ "unknown response from git cat-file " ++ show (header, object) where- query = fromRef object- send to = hPutStrLn to query- receive from = do- header <- hGetLine from- case words header of- [sha, objtype, size]- | length sha == shaSize ->- case (readObjectType objtype, reads size) of- (Just t, [(bytes, "")]) -> readcontent t bytes from sha- _ -> dne- | otherwise -> dne- _- | header == fromRef object ++ " missing" -> dne- | otherwise -> error $ "unknown response from git cat-file " ++ show (header, query)- readcontent objtype bytes from sha = do- content <- S.hGet from bytes- eatchar '\n' from- return $ Just (L.fromChunks [content], Ref sha, objtype)- dne = return Nothing eatchar expected from = do c <- hGetChar from when (c /= expected) $ error $ "missing " ++ (show expected) ++ " from git cat-file" +{- Gets the size and type of an object, without reading its content. -}+catObjectMetaData :: CatFileHandle -> Ref -> IO (Maybe (Integer, ObjectType))+catObjectMetaData h object = query (checkFileProcess h) object $ \from -> do+ resp <- hGetLine from+ case parseResp object resp of+ Just (ParsedResp _ size objtype) ->+ return $ Just (size, objtype)+ Just DNE -> return Nothing+ Nothing -> error $ "unknown response from git cat-file " ++ show (resp, object)++data ParsedResp = ParsedResp Sha Integer ObjectType | DNE++query :: CoProcess.CoProcessHandle -> Ref -> (Handle -> IO a) -> IO a+query hdl object receive = CoProcess.query hdl send receive+ where+ send to = hPutStrLn to (fromRef object)++parseResp :: Ref -> String -> Maybe ParsedResp+parseResp object l + | " missing" `isSuffixOf` l -- less expensive than full check+ && l == fromRef object ++ " missing" = Just DNE+ | otherwise = case words l of+ [sha, objtype, size]+ | length sha == shaSize ->+ case (readObjectType objtype, reads size) of+ (Just t, [(bytes, "")]) -> + Just $ ParsedResp (Ref sha) bytes t+ _ -> Nothing+ | otherwise -> Nothing+ _ -> Nothing+ {- Gets a list of files and directories in a tree. (Not recursive.) -} catTree :: CatFileHandle -> Ref -> IO [(FilePath, FileMode)] catTree h treeref = go <$> catObjectDetails h treeref@@ -104,10 +137,51 @@ (dropsha rest) -- these 20 bytes after the NUL hold the file's sha- -- TODO: convert from raw form to regular sha dropsha = L.drop 21 parsemodefile b = let (modestr, file) = separate (== ' ') (decodeBS b) in (file, readmode modestr) readmode = fromMaybe 0 . fmap fst . headMaybe . readOct++catCommit :: CatFileHandle -> Ref -> IO (Maybe Commit)+catCommit h commitref = go <$> catObjectDetails h commitref+ where+ go (Just (b, _, CommitObject)) = parseCommit b+ go _ = Nothing++parseCommit :: L.ByteString -> Maybe Commit+parseCommit b = Commit+ <$> (extractSha . L8.unpack =<< field "tree")+ <*> Just (maybe [] (mapMaybe (extractSha . L8.unpack)) (fields "parent"))+ <*> (parsemetadata <$> field "author")+ <*> (parsemetadata <$> field "committer")+ <*> Just (L8.unpack $ L.intercalate (L.singleton nl) message)+ where+ field n = headMaybe =<< fields n+ fields n = M.lookup (fromString n) fieldmap+ fieldmap = M.fromListWith (++) ((map breakfield) header)+ breakfield l =+ let (k, sp_v) = L.break (== sp) l+ in (k, [L.drop 1 sp_v])+ (header, message) = separate L.null ls+ ls = L.split nl b++ -- author and committer lines have the form: "name <email> date"+ -- The email is always present, even if empty "<>"+ parsemetadata l = CommitMetaData+ { commitName = whenset $ L.init name_sp+ , commitEmail = whenset email+ , commitDate = whenset $ L.drop 2 gt_sp_date+ }+ where+ (name_sp, rest) = L.break (== lt) l+ (email, gt_sp_date) = L.break (== gt) (L.drop 1 rest)+ whenset v+ | L.null v = Nothing+ | otherwise = Just (L8.unpack v)++ nl = fromIntegral (ord '\n')+ sp = fromIntegral (ord ' ')+ lt = fromIntegral (ord '<')+ gt = fromIntegral (ord '>')
Git/Command.hs view
@@ -17,9 +17,11 @@ {- Constructs a git command line operating on the specified repo. -} gitCommandLine :: [CommandParam] -> Repo -> [CommandParam] gitCommandLine params r@(Repo { location = l@(Local { } ) }) =- setdir : settree ++ gitGlobalOpts r ++ params+ setdir ++ settree ++ gitGlobalOpts r ++ params where- setdir = Param $ "--git-dir=" ++ gitdir l+ setdir+ | gitEnvOverridesGitDir r = []+ | otherwise = [Param $ "--git-dir=" ++ gitdir l] settree = case worktree l of Nothing -> [] Just t -> [Param $ "--work-tree=" ++ t]
Git/Construct.hs view
@@ -236,6 +236,7 @@ , remotes = [] , remoteName = Nothing , gitEnv = Nothing+ , gitEnvOverridesGitDir = False , gitGlobalOpts = [] }
Git/FilePath.hs view
@@ -14,8 +14,10 @@ module Git.FilePath ( TopFilePath,- fromTopFilePath,+ BranchFilePath(..),+ descBranchFilePath, getTopFilePath,+ fromTopFilePath, toTopFilePath, asTopFilePath, InternalGitPath,@@ -31,11 +33,18 @@ {- A FilePath, relative to the top of the git repository. -} newtype TopFilePath = TopFilePath { getTopFilePath :: FilePath }- deriving (Show)+ deriving (Show, Eq, Ord) -{- Returns an absolute FilePath. -}+{- A file in a branch or other treeish. -}+data BranchFilePath = BranchFilePath Ref TopFilePath++{- Git uses the branch:file form to refer to a BranchFilePath -}+descBranchFilePath :: BranchFilePath -> String+descBranchFilePath (BranchFilePath b f) = fromRef b ++ ':' : getTopFilePath f++{- Path to a TopFilePath, within the provided git repo. -} fromTopFilePath :: TopFilePath -> Git.Repo -> FilePath-fromTopFilePath p repo = absPathFrom (repoPath repo) (getTopFilePath p)+fromTopFilePath p repo = combine (repoPath repo) (getTopFilePath p) {- The input FilePath can be absolute, or relative to the CWD. -} toTopFilePath :: FilePath -> Git.Repo -> IO TopFilePath
Git/Fsck.hs view
@@ -5,6 +5,8 @@ - Licensed under the GNU GPL version 3 or higher. -} +{-# LANGUAGE BangPatterns #-}+ module Git.Fsck ( FsckResults(..), MissingObjects,@@ -25,8 +27,6 @@ import qualified Data.Set as S import Control.Concurrent.Async -type MissingObjects = S.Set Sha- data FsckResults = FsckFoundMissing { missingObjects :: MissingObjects@@ -35,6 +35,25 @@ | FsckFailed deriving (Show) +data FsckOutput + = FsckOutput MissingObjects Truncated+ | NoFsckOutput+ | AllDuplicateEntriesWarning++type MissingObjects = S.Set Sha++type Truncated = Bool++instance Monoid FsckOutput where+ mempty = NoFsckOutput+ mappend (FsckOutput s1 t1) (FsckOutput s2 t2) = FsckOutput (S.union s1 s2) (t1 || t2)+ mappend (FsckOutput s t) _ = FsckOutput s t+ mappend _ (FsckOutput s t) = FsckOutput s t+ mappend NoFsckOutput NoFsckOutput = NoFsckOutput+ mappend AllDuplicateEntriesWarning AllDuplicateEntriesWarning = AllDuplicateEntriesWarning+ mappend AllDuplicateEntriesWarning NoFsckOutput = AllDuplicateEntriesWarning+ mappend NoFsckOutput AllDuplicateEntriesWarning = AllDuplicateEntriesWarning+ {- Runs fsck to find some of the broken objects in the repository. - May not find all broken objects, if fsck fails on bad data in some of - the broken objects it does find.@@ -58,18 +77,24 @@ { std_out = CreatePipe , std_err = CreatePipe }- (bad1, bad2) <- concurrently- (readMissingObjs maxobjs r supportsNoDangling (stdoutHandle p))- (readMissingObjs maxobjs r supportsNoDangling (stderrHandle p))+ (o1, o2) <- concurrently+ (parseFsckOutput maxobjs r supportsNoDangling (stdoutHandle p))+ (parseFsckOutput maxobjs r supportsNoDangling (stderrHandle p)) fsckok <- checkSuccessProcess pid- let truncated = S.size bad1 == maxobjs || S.size bad1 == maxobjs- let badobjs = S.union bad1 bad2-- if S.null badobjs && not fsckok- then return FsckFailed- else return $ FsckFoundMissing badobjs truncated+ case mappend o1 o2 of+ FsckOutput badobjs truncated+ | S.null badobjs && not fsckok -> return FsckFailed+ | otherwise -> return $ FsckFoundMissing badobjs truncated+ NoFsckOutput+ | not fsckok -> return FsckFailed+ | otherwise -> return noproblem+ -- If all fsck output was duplicateEntries warnings,+ -- the repository is not broken, it just has some unusual+ -- tree objects in it. So ignore nonzero exit status.+ AllDuplicateEntriesWarning -> return noproblem where maxobjs = 10000+ noproblem = FsckFoundMissing S.empty False foundBroken :: FsckResults -> Bool foundBroken FsckFailed = True@@ -87,10 +112,18 @@ findMissing :: [Sha] -> Repo -> IO MissingObjects findMissing objs r = S.fromList <$> filterM (`isMissing` r) objs -readMissingObjs :: Int -> Repo -> Bool -> Handle -> IO MissingObjects-readMissingObjs maxobjs r supportsNoDangling h = do- objs <- take maxobjs . findShas supportsNoDangling <$> hGetContents h- findMissing objs r+parseFsckOutput :: Int -> Repo -> Bool -> Handle -> IO FsckOutput+parseFsckOutput maxobjs r supportsNoDangling h = do+ ls <- lines <$> hGetContents h+ if null ls+ then return NoFsckOutput+ else if all ("duplicateEntries" `isInfixOf`) ls+ then return AllDuplicateEntriesWarning+ else do+ let shas = findShas supportsNoDangling ls+ let !truncated = length shas > maxobjs+ missingobjs <- findMissing (take maxobjs shas) r+ return $ FsckOutput missingobjs truncated isMissing :: Sha -> Repo -> IO Bool isMissing s r = either (const True) (const False) <$> tryIO dump@@ -100,8 +133,8 @@ , Param (fromRef s) ] r -findShas :: Bool -> String -> [Sha]-findShas supportsNoDangling = catMaybes . map extractSha . concat . map words . filter wanted . lines+findShas :: Bool -> [String] -> [Sha]+findShas supportsNoDangling = catMaybes . map extractSha . concat . map words . filter wanted where wanted l | supportsNoDangling = True
Git/Index.hs view
@@ -14,6 +14,20 @@ indexEnv :: String indexEnv = "GIT_INDEX_FILE" +{- Gets value to set GIT_INDEX_FILE to. Input should be absolute path,+ - or relative to the CWD.+ -+ - When relative, GIT_INDEX_FILE is interpreted by git as being + - relative to the top of the work tree of the git repository,+ - not to the CWD. Worse, other environment variables (GIT_WORK_TREE)+ - or git options (--work-tree) or configuration (core.worktree)+ - can change what the relative path is interpreted relative to.+ -+ - So, an absolute path is the only safe option for this to return.+ -}+indexEnvVal :: FilePath -> IO String+indexEnvVal = absPath+ {- Forces git to use the specified index file. - - Returns an action that will reset back to the default@@ -21,10 +35,11 @@ - - Warning: Not thread safe. -}-override :: FilePath -> IO (IO ())-override index = do+override :: FilePath -> Repo -> IO (IO ())+override index _r = do res <- getEnv var- setEnv var index True+ val <- indexEnvVal index+ setEnv var val True return $ reset res where var = "GIT_INDEX_FILE"
Git/LsTree.hs view
@@ -1,16 +1,19 @@ {- git ls-tree interface -- - Copyright 2011 Joey Hess <id@joeyh.name>+ - Copyright 2011-2016 Joey Hess <id@joeyh.name> - - Licensed under the GNU GPL version 3 or higher. -} +{-# LANGUAGE BangPatterns #-}+ module Git.LsTree ( TreeItem(..), lsTree,+ lsTree', lsTreeParams, lsTreeFiles,- parseLsTree+ parseLsTree, ) where import Common@@ -26,16 +29,20 @@ data TreeItem = TreeItem { mode :: FileMode , typeobj :: String- , sha :: String+ , sha :: Ref , file :: TopFilePath } deriving Show {- Lists the complete contents of a tree, recursing into sub-trees, - with lazy output. -}-lsTree :: Ref -> Repo -> IO [TreeItem]-lsTree t repo = map parseLsTree- <$> pipeNullSplitZombie (lsTreeParams t []) repo+lsTree :: Ref -> Repo -> IO ([TreeItem], IO Bool)+lsTree = lsTree' [] +lsTree' :: [CommandParam] -> Ref -> Repo -> IO ([TreeItem], IO Bool)+lsTree' ps t repo = do+ (l, cleanup) <- pipeNullSplit (lsTreeParams t ps) repo+ return (map parseLsTree l, cleanup)+ lsTreeParams :: Ref -> [CommandParam] -> [CommandParam] lsTreeParams r ps = [ Param "ls-tree"@@ -63,16 +70,18 @@ - (The --long format is not currently supported.) -} parseLsTree :: String -> TreeItem parseLsTree l = TreeItem - { mode = fst $ Prelude.head $ readOct m+ { mode = smode , typeobj = t- , sha = s- , file = asTopFilePath $ Git.Filename.decode f+ , sha = Ref s+ , file = sfile } where -- l = <mode> SP <type> SP <sha> TAB <file> -- All fields are fixed, so we can pull them out of -- specific positions in the line. (m, past_m) = splitAt 7 l- (t, past_t) = splitAt 4 past_m- (s, past_s) = splitAt shaSize $ Prelude.tail past_t- f = Prelude.tail past_s+ (!t, past_t) = splitAt 4 past_m+ (!s, past_s) = splitAt shaSize $ Prelude.tail past_t+ !f = Prelude.tail past_s+ !smode = fst $ Prelude.head $ readOct m+ !sfile = asTopFilePath $ Git.Filename.decode f
Git/Ref.hs view
@@ -18,24 +18,26 @@ headRef :: Ref headRef = Ref "HEAD" +headFile :: Repo -> FilePath+headFile r = localGitDir r </> "HEAD"++setHeadRef :: Ref -> Repo -> IO ()+setHeadRef ref r = writeFile (headFile r) ("ref: " ++ fromRef ref)+ {- Converts a fully qualified git ref into a user-visible string. -} describe :: Ref -> String describe = fromRef . base -{- Often git refs are fully qualified (eg: refs/heads/master).- - Converts such a fully qualified ref into a base ref (eg: master). -}+{- Often git refs are fully qualified + - (eg refs/heads/master or refs/remotes/origin/master).+ - Converts such a fully qualified ref into a base ref+ - (eg: master or origin/master). -} base :: Ref -> Ref base = Ref . remove "refs/heads/" . remove "refs/remotes/" . fromRef where remove prefix s | prefix `isPrefixOf` s = drop (length prefix) s | otherwise = s--{- Given a directory and any ref, takes the basename of the ref and puts- - it under the directory. -}-under :: String -> Ref -> Ref-under dir r = Ref $ dir ++ "/" ++- (reverse $ takeWhile (/= '/') $ reverse $ fromRef r) {- Given a directory such as "refs/remotes/origin", and a ref such as - refs/heads/master, yields a version of that ref under the directory,
Git/Repair.hs view
@@ -342,8 +342,8 @@ | S.member treesha missing = return False | otherwise = do (ls, cleanup) <- pipeNullSplit (LsTree.lsTreeParams treesha []) r- let objshas = map (extractSha . LsTree.sha . LsTree.parseLsTree) ls- if any isNothing objshas || any (`S.member` missing) (catMaybes objshas)+ let objshas = map (LsTree.sha . LsTree.parseLsTree) ls+ if any (`S.member` missing) objshas then do void cleanup return False
Git/Types.hs view
@@ -11,7 +11,6 @@ import qualified Data.Map as M import System.Posix.Types import Utility.SafeCommand-import Utility.URI () {- Support repositories on local disk, and repositories accessed via an URL. -@@ -40,6 +39,7 @@ , remoteName :: Maybe RemoteName -- alternate environment to use when running git commands , gitEnv :: Maybe [(String, String)]+ , gitEnvOverridesGitDir :: Bool -- global options to pass to git when running git commands , gitGlobalOpts :: [CommandParam] } deriving (Show, Eq, Ord)@@ -98,3 +98,24 @@ toBlobType 0o100755 = Just ExecutableBlob toBlobType 0o120000 = Just SymlinkBlob toBlobType _ = Nothing++fromBlobType :: BlobType -> FileMode+fromBlobType FileBlob = 0o100644+fromBlobType ExecutableBlob = 0o100755+fromBlobType SymlinkBlob = 0o120000++data Commit = Commit+ { commitTree :: Sha+ , commitParent :: [Sha]+ , commitAuthorMetaData :: CommitMetaData+ , commitCommitterMetaData :: CommitMetaData+ , commitMessage :: String+ }+ deriving (Show)++data CommitMetaData = CommitMetaData+ { commitName :: Maybe String+ , commitEmail :: Maybe String+ , commitDate :: Maybe String -- In raw git form, "epoch -tzoffset"+ }+ deriving (Show)
− Makefile
@@ -1,34 +0,0 @@-PREFIX=/usr-CABAL?=cabal # set to "./Setup" if you lack a cabal program--build: Build/SysConfig.hs- $(CABAL) build- ln -sf dist/build/git-repair/git-repair git-repair- @$(MAKE) tags >/dev/null 2>&1 &--Build/SysConfig.hs: configure.hs Build/TestConfig.hs Build/Configure.hs- if [ "$(CABAL)" = ./Setup ]; then ghc --make Setup; fi- $(CABAL) configure --ghc-options="$(shell Build/collect-ghc-options.sh)"--install: build- install -d $(DESTDIR)$(PREFIX)/bin- install git-repair $(DESTDIR)$(PREFIX)/bin- install -d $(DESTDIR)$(PREFIX)/share/man/man1- install -m 0644 git-repair.1 $(DESTDIR)$(PREFIX)/share/man/man1--clean:- rm -rf git-repair git-repair-test.log \- dist configure Build/SysConfig.hs Setup tags- find . -name \*.o -exec rm {} \;- find . -name \*.hi -exec rm {} \;--# Upload to hackage.-hackage: clean- ./Build/make-sdist.sh- @cabal upload dist/*.tar.gz--# hothasktags chokes on some template haskell etc, so ignore errors-tags:- (for f in $$(find . | grep -v /.git/ | grep -v /tmp/ | grep -v /dist/ | grep -v /doc/ | egrep '\.hs$$'); do hothasktags -c --cpp -c -traditional -c --include=dist/build/autogen/cabal_macros.h $$f; done) 2>/dev/null | sort > tags--.PHONY: tags
Setup.hs view
@@ -1,3 +1,5 @@+{-# OPTIONS_GHC -fno-warn-tabs #-}+ {- cabal setup file -} import Distribution.Simple
Utility/CoProcess.hs view
@@ -13,7 +13,6 @@ start, stop, query,- rawMode ) where import Common@@ -44,7 +43,15 @@ start' :: CoProcessSpec -> IO CoProcessState start' s = do (pid, from, to) <- startInteractiveProcess (coProcessCmd s) (coProcessParams s) (coProcessEnv s)+ rawMode from+ rawMode to return $ CoProcessState pid to from s+ where+ rawMode h = do+ fileEncoding h+#ifdef mingw32_HOST_OS+ hSetNewlineMode h noNewlineTranslation+#endif stop :: CoProcessHandle -> IO () stop ch = do@@ -79,16 +86,3 @@ { coProcessNumRestarts = coProcessNumRestarts (coProcessSpec s) - 1 } putMVar ch s' query ch send receive--rawMode :: CoProcessHandle -> IO CoProcessHandle-rawMode ch = do- s <- readMVar ch- raw $ coProcessFrom s- raw $ coProcessTo s- return ch- where- raw h = do- fileEncoding h-#ifdef mingw32_HOST_OS- hSetNewlineMode h noNewlineTranslation-#endif
Utility/Directory.hs view
@@ -8,10 +8,12 @@ {-# LANGUAGE CPP #-} {-# OPTIONS_GHC -fno-warn-tabs #-} -module Utility.Directory where+module Utility.Directory (+ module Utility.Directory,+ module Utility.SystemDirectory+) where import System.IO.Error-import System.Directory import Control.Monad import System.FilePath import Control.Applicative@@ -28,6 +30,7 @@ import Control.Monad.IfElse #endif +import Utility.SystemDirectory import Utility.PosixFiles import Utility.Tmp import Utility.Exception@@ -134,11 +137,13 @@ _ <- tryIO $ removeFile tmp throwM e' +#ifndef mingw32_HOST_OS isdir f = do r <- tryIO $ getFileStatus f case r of (Left _) -> return False (Right s) -> return $ isDirectory s+#endif {- Removes a file, which may or may not exist, and does not have to - be a regular file.
Utility/Exception.hs view
@@ -5,7 +5,7 @@ - License: BSD-2-clause -} -{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE CPP, ScopedTypeVariables #-} {-# OPTIONS_GHC -fno-warn-tabs #-} module Utility.Exception (@@ -21,12 +21,18 @@ tryNonAsync, tryWhenExists, catchIOErrorType,- IOErrorType(..)+ IOErrorType(..),+ catchPermissionDenied, ) where import Control.Monad.Catch as X hiding (Handler) import qualified Control.Monad.Catch as M import Control.Exception (IOException, AsyncException)+#ifdef MIN_VERSION_GLASGOW_HASKELL+#if MIN_VERSION_GLASGOW_HASKELL(7,10,0,0)+import Control.Exception (SomeAsyncException)+#endif+#endif import Control.Monad import Control.Monad.IO.Class (liftIO, MonadIO) import System.IO.Error (isDoesNotExistError, ioeGetErrorType)@@ -73,6 +79,11 @@ catchNonAsync :: MonadCatch m => m a -> (SomeException -> m a) -> m a catchNonAsync a onerr = a `catches` [ M.Handler (\ (e :: AsyncException) -> throwM e)+#ifdef MIN_VERSION_GLASGOW_HASKELL+#if MIN_VERSION_GLASGOW_HASKELL(7,10,0,0)+ , M.Handler (\ (e :: SomeAsyncException) -> throwM e)+#endif+#endif , M.Handler (\ (e :: SomeException) -> onerr e) ] @@ -97,3 +108,6 @@ onlymatching e | ioeGetErrorType e == errtype = onmatchingerr e | otherwise = throwM e++catchPermissionDenied :: MonadCatch m => (IOException -> m a) -> m a -> m a+catchPermissionDenied = catchIOErrorType PermissionDenied
Utility/FileMode.hs view
@@ -18,9 +18,10 @@ import Utility.PosixFiles #ifndef mingw32_HOST_OS import System.Posix.Files+import Control.Monad.IO.Class (liftIO) #endif+import Control.Monad.IO.Class (MonadIO) import Foreign (complement)-import Control.Monad.IO.Class (liftIO, MonadIO) import Control.Monad.Catch import Utility.Exception
Utility/FileSize.hs view
@@ -13,13 +13,15 @@ import System.IO #endif +type FileSize = Integer+ {- Gets the size of a file. - - This is better than using fileSize, because on Windows that returns a - FileOffset which maxes out at 2 gb. - See https://github.com/jystic/unix-compat/issues/16 -}-getFileSize :: FilePath -> IO Integer+getFileSize :: FilePath -> IO FileSize #ifndef mingw32_HOST_OS getFileSize f = fmap (fromIntegral . fileSize) (getFileStatus f) #else@@ -27,7 +29,7 @@ #endif {- Gets the size of the file, when its FileStatus is already known. -}-getFileSize' :: FilePath -> FileStatus -> IO Integer+getFileSize' :: FilePath -> FileStatus -> IO FileSize #ifndef mingw32_HOST_OS getFileSize' _ s = return $ fromIntegral $ fileSize s #else
Utility/FileSystemEncoding.hs view
@@ -19,6 +19,7 @@ encodeW8NUL, decodeW8NUL, truncateFilePath,+ setConsoleEncoding, ) where import qualified GHC.Foreign as GHC@@ -164,3 +165,10 @@ else go (c:coll) (cnt - x') (L8.drop 1 bs) _ -> coll #endif++{- This avoids ghc's output layer crashing on invalid encoded characters in+ - filenames when printing them out. -}+setConsoleEncoding :: IO ()+setConsoleEncoding = do+ fileEncoding stdout+ fileEncoding stderr
Utility/Format.hs view
@@ -103,7 +103,7 @@ {- Decodes a C-style encoding, where \n is a newline, \NNN is an octal - encoded character, and \xNN is a hex encoded character. -}-decode_c :: FormatString -> FormatString+decode_c :: FormatString -> String decode_c [] = [] decode_c s = unescape ("", s) where@@ -141,14 +141,14 @@ handle n = ("", n) {- Inverse of decode_c. -}-encode_c :: FormatString -> FormatString+encode_c :: String -> FormatString encode_c = encode_c' (const False) {- Encodes more strictly, including whitespace. -}-encode_c_strict :: FormatString -> FormatString+encode_c_strict :: String -> FormatString encode_c_strict = encode_c' isSpace -encode_c' :: (Char -> Bool) -> FormatString -> FormatString+encode_c' :: (Char -> Bool) -> String -> FormatString encode_c' p = concatMap echar where e c = '\\' : [c]
Utility/Metered.hs view
@@ -1,6 +1,6 @@ {- Metered IO and actions -- - Copyright 2012-2105 Joey Hess <id@joeyh.name>+ - Copyright 2012-2106 Joey Hess <id@joeyh.name> - - License: BSD-2-clause -}@@ -21,6 +21,8 @@ import Control.Concurrent import Control.Concurrent.Async import Control.Monad.IO.Class (MonadIO)+import Data.Time.Clock+import Data.Time.Clock.POSIX {- An action that can be run repeatedly, updating it on the bytes processed. -@@ -259,3 +261,24 @@ where p = (proc cmd (toCommand params)) { env = environ }++-- | Limit a meter to only update once per unit of time.+--+-- It's nice to display the final update to 100%, even if it comes soon+-- after a previous update. To make that happen, a total size has to be+-- provided.+rateLimitMeterUpdate :: NominalDiffTime -> Maybe Integer -> MeterUpdate -> IO MeterUpdate+rateLimitMeterUpdate delta totalsize meterupdate = do+ lastupdate <- newMVar (toEnum 0 :: POSIXTime)+ return $ mu lastupdate+ where+ mu lastupdate n@(BytesProcessed i) = case totalsize of+ Just t | i >= t -> meterupdate n+ _ -> do+ now <- getPOSIXTime+ prev <- takeMVar lastupdate+ if now - prev >= delta+ then do+ putMVar lastupdate now+ meterupdate n+ else putMVar lastupdate prev
Utility/Path.hs view
@@ -12,7 +12,6 @@ import Data.String.Utils import System.FilePath-import System.Directory import Data.List import Data.Maybe import Data.Char@@ -29,6 +28,7 @@ import qualified "MissingH" System.Path as MissingH import Utility.Monad import Utility.UserInfo+import Utility.Directory {- Simplifies a path, removing any "." component, collapsing "dir/..", - and removing the trailing path separator.@@ -60,7 +60,7 @@ {- Makes a path absolute. - - The first parameter is a base directory (ie, the cwd) to use if the path- - is not already absolute.+ - is not already absolute, and should itsef be absolute. - - Does not attempt to deal with edge cases or ensure security with - untrusted inputs.@@ -252,15 +252,21 @@ where f = takeFileName file -{- Converts a DOS style path to a Cygwin style path. Only on Windows.- - Any trailing '\' is preserved as a trailing '/' -}-toCygPath :: FilePath -> FilePath+{- Converts a DOS style path to a msys2 style path. Only on Windows.+ - Any trailing '\' is preserved as a trailing '/' + - + - Taken from: http://sourceforge.net/p/msys2/wiki/MSYS2%20introduction/i+ -+ - The virtual filesystem contains:+ - /c, /d, ... mount points for Windows drives+ -}+toMSYS2Path :: FilePath -> FilePath #ifndef mingw32_HOST_OS-toCygPath = id+toMSYS2Path = id #else-toCygPath p+toMSYS2Path p | null drive = recombine parts- | otherwise = recombine $ "/cygdrive" : driveletter drive : parts+ | otherwise = recombine $ "/" : driveletter drive : parts where (drive, p') = splitDrive p parts = splitDirectories p'
Utility/PosixFiles.hs view
@@ -1,6 +1,6 @@ {- POSIX files (and compatablity wrappers). -- - This is like System.PosixCompat.Files, except with a fixed rename.+ - This is like System.PosixCompat.Files, but with a few fixes. - - Copyright 2014 Joey Hess <id@joeyh.name> -@@ -21,6 +21,7 @@ import System.Posix.Files (rename) #else import qualified System.Win32.File as Win32+import qualified System.Win32.HardLink as Win32 #endif {- System.PosixCompat.Files.rename on Windows calls renameFile,@@ -31,4 +32,11 @@ #ifdef mingw32_HOST_OS rename :: FilePath -> FilePath -> IO () rename src dest = Win32.moveFileEx src dest Win32.mOVEFILE_REPLACE_EXISTING+#endif++{- System.PosixCompat.Files.createLink throws an error, but windows+ - does support hard links. -}+#ifdef mingw32_HOST_OS+createLink :: FilePath -> FilePath -> IO ()+createLink = Win32.createHardLink #endif
Utility/Process.hs view
@@ -18,6 +18,7 @@ readProcessEnv, writeReadProcessEnv, forceSuccessProcess,+ forceSuccessProcess', checkSuccessProcess, ignoreFailureProcess, createProcessSuccess,@@ -129,11 +130,12 @@ -- | Waits for a ProcessHandle, and throws an IOError if the process -- did not exit successfully. forceSuccessProcess :: CreateProcess -> ProcessHandle -> IO ()-forceSuccessProcess p pid = do- code <- waitForProcess pid- case code of- ExitSuccess -> return ()- ExitFailure n -> fail $ showCmd p ++ " exited " ++ show n+forceSuccessProcess p pid = waitForProcess pid >>= forceSuccessProcess' p++forceSuccessProcess' :: CreateProcess -> ExitCode -> IO ()+forceSuccessProcess' _ ExitSuccess = return ()+forceSuccessProcess' p (ExitFailure n) = fail $+ showCmd p ++ " exited " ++ show n -- | Waits for a ProcessHandle and returns True if it exited successfully. -- Note that using this with createProcessChecked will throw away
Utility/QuickCheck.hs view
@@ -6,7 +6,7 @@ -} {-# OPTIONS_GHC -fno-warn-orphans #-}-{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE TypeSynonymInstances, CPP #-} module Utility.QuickCheck ( module X@@ -16,16 +16,20 @@ import Test.QuickCheck as X import Data.Time.Clock.POSIX import System.Posix.Types+#if ! MIN_VERSION_QuickCheck(2,8,2) import qualified Data.Map as M import qualified Data.Set as S+#endif import Control.Applicative import Prelude -instance (Arbitrary k, Arbitrary v, Eq k, Ord k) => Arbitrary (M.Map k v) where+#if ! MIN_VERSION_QuickCheck(2,8,2)+instance (Arbitrary k, Arbitrary v, Ord k) => Arbitrary (M.Map k v) where arbitrary = M.fromList <$> arbitrary -instance (Arbitrary v, Eq v, Ord v) => Arbitrary (S.Set v) where+instance (Arbitrary v, Ord v) => Arbitrary (S.Set v) where arbitrary = S.fromList <$> arbitrary+#endif {- Times before the epoch are excluded. -} instance Arbitrary POSIXTime where
Utility/Rsync.hs view
@@ -54,16 +54,16 @@ rsync :: [CommandParam] -> IO Bool rsync = boolSystem "rsync" . rsyncParamsFixup -{- On Windows, rsync is from Cygwin, and expects to get Cygwin formatted+{- On Windows, rsync is from msys2, and expects to get msys2 formatted - paths to files. (It thinks that C:foo refers to a host named "C"). - Fix up the Params appropriately. -} rsyncParamsFixup :: [CommandParam] -> [CommandParam] #ifdef mingw32_HOST_OS rsyncParamsFixup = map fixup where- fixup (File f) = File (toCygPath f)+ fixup (File f) = File (toMSYS2Path f) fixup (Param s)- | rsyncUrlIsPath s = Param (toCygPath s)+ | rsyncUrlIsPath s = Param (toMSYS2Path s) fixup p = p #else rsyncParamsFixup = id
+ Utility/SystemDirectory.hs view
@@ -0,0 +1,16 @@+{- System.Directory without its conflicting isSymbolicLink+ -+ - Copyright 2016 Joey Hess <id@joeyh.name>+ -+ - License: BSD-2-clause+ -}++-- Disable warnings because only some versions of System.Directory export+-- isSymbolicLink.+{-# OPTIONS_GHC -fno-warn-tabs -w #-}++module Utility.SystemDirectory (+ module System.Directory+) where++import System.Directory hiding (isSymbolicLink)
Utility/Tmp.hs view
@@ -11,9 +11,9 @@ module Utility.Tmp where import System.IO-import System.Directory import Control.Monad.IfElse import System.FilePath+import System.Directory import Control.Monad.IO.Class #ifndef mingw32_HOST_OS import System.Posix.Temp (mkdtemp)
Utility/UserInfo.hs view
@@ -15,18 +15,17 @@ ) where import Utility.Env+import Utility.Data import System.PosixCompat-#ifndef mingw32_HOST_OS import Control.Applicative-#endif import Prelude {- Current user's home directory. - - getpwent will fail on LDAP or NIS, so use HOME if set. -} myHomeDir :: IO FilePath-myHomeDir = myVal env homeDirectory+myHomeDir = either error return =<< myVal env homeDirectory where #ifndef mingw32_HOST_OS env = ["HOME"]@@ -35,7 +34,7 @@ #endif {- Current user's user name. -}-myUserName :: IO String+myUserName :: IO (Either String String) myUserName = myVal env userName where #ifndef mingw32_HOST_OS@@ -49,15 +48,15 @@ #if defined(__ANDROID__) || defined(mingw32_HOST_OS) myUserGecos = return Nothing #else-myUserGecos = Just <$> myVal [] userGecos+myUserGecos = eitherToMaybe <$> myVal [] userGecos #endif -myVal :: [String] -> (UserEntry -> String) -> IO String+myVal :: [String] -> (UserEntry -> String) -> IO (Either String String) myVal envvars extract = go envvars where #ifndef mingw32_HOST_OS- go [] = extract <$> (getUserEntryForID =<< getEffectiveUserID)+ go [] = Right . extract <$> (getUserEntryForID =<< getEffectiveUserID) #else- go [] = error $ "environment not set: " ++ show envvars+ go [] = return $ Left ("environment not set: " ++ show envvars) #endif- go (v:vs) = maybe (go vs) return =<< getEnv v+ go (v:vs) = maybe (go vs) (return . Right) =<< getEnv v
− configure.hs
@@ -1,6 +0,0 @@-{- configure program -}--import Build.Configure--main :: IO ()-main = run tests
− debian/changelog
@@ -1,105 +0,0 @@-git-repair (1.20151215) unstable; urgency=medium-- * Fix insecure temporary permissions and potential denial of- service attack when creating temp dirs. Closes: #807341- * Merge from git-annex.-- -- Joey Hess <id@joeyh.name> Tue, 15 Dec 2015 20:47:59 -0400--git-repair (1.20150106) unstable; urgency=medium-- * Debian package is now maintained by Richard Hartmann.- * Fix build with process 1.2.1.0.- * Merge from git-annex.-- -- Joey Hess <id@joeyh.name> Tue, 06 Jan 2015 19:09:23 -0400--git-repair (1.20141027) unstable; urgency=medium-- * Adjust cabal file to support network-uri split.- * Merge Build/ from git-annex, including removing a use of deprecated- System.Cmd.-- -- Joey Hess <joeyh@debian.org> Mon, 27 Oct 2014 11:09:56 -0400--git-repair (1.20141026) unstable; urgency=medium-- * Prevent auto gc from happening when fetching from a remote.- * Merge from git-annex.-- -- Joey Hess <joeyh@debian.org> Sun, 26 Oct 2014 13:37:30 -0400--git-repair (1.20140914) unstable; urgency=medium-- * Update to build with optparse-applicative 0.10. Closes: #761552-- -- Joey Hess <joeyh@debian.org> Sun, 14 Sep 2014 12:48:27 -0400--git-repair (1.20140815) unstable; urgency=medium-- * Removing bad objects could leave fsck finding no more unreachable objects,- but some branches no longer accessible. Fix this, including support for- fixing up repositories that were incompletely repaired before.- * Merge from git-annex.-- -- Joey Hess <joeyh@debian.org> Fri, 15 Aug 2014 13:49:09 -0400--git-repair (1.20140423) unstable; urgency=medium-- * Improve memory usage when git fsck finds a great many broken objects.- * Merge from git-annex.-- -- Joey Hess <joeyh@debian.org> Wed, 23 Apr 2014 14:01:30 -0400--git-repair (1.20140227) unstable; urgency=medium-- * Optimise unpacking of pack files, and avoid repeated error- messages about corrupt pack files.- * Add swapping 2 files test case.-- -- Joey Hess <joeyh@debian.org> Thu, 27 Feb 2014 11:56:27 -0400--git-repair (1.20140115) unstable; urgency=medium-- * Support old git versions from before git fsck --no-dangling was- implemented.- * Fix bug in packed refs file exploding code that caused a .gitrefs- directory to be created instead of .git/refs- * Check git version at run time.-- -- Joey Hess <joeyh@debian.org> Wed, 15 Jan 2014 16:53:30 -0400--git-repair (1.20131213) unstable; urgency=low-- * Improve repair of index files in some situations.-- -- Joey Hess <joeyh@debian.org> Fri, 13 Dec 2013 14:51:51 -0400--git-repair (1.20131203) unstable; urgency=low-- * Fix build deps. Closes: #731179-- -- Joey Hess <joeyh@debian.org> Tue, 03 Dec 2013 15:02:21 -0400--git-repair (1.20131122) unstable; urgency=low-- * Added test mode, which can be used to randomly corrupt test - repositories, in reproducible ways, which allows easy- corruption-driven-development.- * Improve repair code in the case where the index file is corrupt,- and this hides other problems.- * Write a dummy .git/HEAD if the file is missing or corrupt, as- git otherwise will not treat the repository as a git repo.- * Improve fsck code to find badly corrupted objects that crash git fsck- before it can complain about them.- * Fixed crashes on bad file encodings.- * Can now run 10000 tests (git-repair --test -n 10000 --force)- with 0 failures.-- -- Joey Hess <joeyh@debian.org> Fri, 22 Nov 2013 11:16:03 -0400--git-repair (1.20131118) unstable; urgency=low-- * First release-- -- Joey Hess <joeyh@debian.org> Mon, 18 Nov 2013 13:38:12 -0400
− debian/compat
@@ -1,1 +0,0 @@-9
− debian/control
@@ -1,36 +0,0 @@-Source: git-repair-Section: utils-Priority: optional-Build-Depends: - debhelper (>= 9),- ghc,- git,- libghc-missingh-dev,- libghc-hslogger-dev,- libghc-network-dev,- libghc-exceptions-dev (>= 0.6),- libghc-transformers-dev,- libghc-unix-compat-dev,- libghc-ifelse-dev,- libghc-text-dev,- libghc-quickcheck2-dev,- libghc-utf8-string-dev,- libghc-async-dev,- libghc-optparse-applicative-dev (>= 0.10.0)-Maintainer: Richard Hartmann <richih@debian.org>-Standards-Version: 3.9.5-Vcs-Git: git://git-repair.branchable.com/-Homepage: http://git-repair.branchable.com/--Package: git-repair-Architecture: any-Section: utils-Depends: ${misc:Depends}, ${shlibs:Depends}, git, rsync-Description: repair various forms of damage to git repositories- git-repair can repair various forms of damage to git repositories.- .- It is a complement to git fsck, which finds problems, but does not fix them.- .- As well as avoiding the need to rm -rf a damaged repository and re-clone,- using git-repair can help rescue commits you've made to the damaged- repository and not yet pushed out.
− debian/copyright
@@ -1,35 +0,0 @@-Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/-Source: native package--Files: *-Copyright: © 2013 Joey Hess <joey@kitenet.net>-License: GPL-3+- The full text of version 3 of the GPL is distributed as doc/GPL in- this package's source, or in /usr/share/common-licenses/GPL-3 on- Debian systems.--Files: Utility/*-Copyright: 2012-2014 Joey Hess <joey@kitenet.net>-License: BSD-2-clause--License: BSD-2-clause- Redistribution and use in source and binary forms, with or without- modification, are permitted provided that the following conditions- are met:- 1. Redistributions of source code must retain the above copyright- notice, this list of conditions and the following disclaimer.- 2. Redistributions in binary form must reproduce the above copyright- notice, this list of conditions and the following disclaimer in the- documentation and/or other materials provided with the distribution.- .- THIS SOFTWARE IS PROVIDED BY AUTHORS AND CONTRIBUTORS ``AS IS'' AND- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF- SUCH DAMAGE.
− debian/git-repair.lintian-overrides
@@ -1,1 +0,0 @@-binary-or-shlib-defines-rpath
− debian/manpages
@@ -1,1 +0,0 @@-git-repair.1
− debian/rules
@@ -1,10 +0,0 @@-#!/usr/bin/make -f--# Avoid using cabal, as it writes to $HOME-export CABAL=./Setup--# Do use the changelog's version number, rather than making one up.-export RELEASE_BUILD=1--%:- dh $@
− doc/index.mdwn
@@ -1,55 +0,0 @@-`git-repair` can repair various forms of damage to git repositories.--It is a complement to `git fsck`, which finds problems, but does not fix-them.--As well as avoiding the need to rm -rf a damaged repository and re-clone,-using git-repair can help rescue commits you've made to the damaged-repository and not yet pushed out.--## download--* `git clone git://git-repair.branchable.com/ git-repair`-* from [Hackage](http://hackage.haskell.org/package/git-repair)--## install--This is a Haskell program, developed as a spinoff of-[git-annex](http://git-annex.branchable.com/).--To build it, you will need to install the-[Haskell Platform](http://www.haskell.org/platform/).--Then to install it:-- cabal update; cabal install git-repair --bindir=$HOME/bin--## how it works--`git-repair` starts by deleting all corrupt objects, and-retreiving all missing objects that it can from the remotes of the-repository.--If that is not sufficient to fully recover the repository, it can also-reset branches back to commits before the corruption happened, delete-branches that are no longer available due to the lost data, and remove any-missing files from the index. It will only do this if run with the-`--force` option, since that rewrites history and throws out missing data.--After running this command, you will probably want to run `git fsck` to-verify it fixed the repository.--Note that fsck may still complain about objects referenced by the reflog,-or the stash, if they were unable to be recovered. This command does not-try to clean up either the reflog or the stash. --Also note that the `--force` option never touches tags, even if they are no-longer usable due to missing data, so fsck may also find problems with-tags.--Since this command unpacks all packs in the repository, you may want to-run `git gc` afterwards.--## news--[[!inline pages="news/* and !*/Discussion" show="4" archive=yes]]
− doc/news/version_1.20141027.mdwn
@@ -1,1 +0,0 @@-git-repair 1.20140613 released
− doc/news/version_1.20151215.mdwn
@@ -1,5 +0,0 @@-git-repair 1.20151215 released with [[!toggle text="these changes"]]-[[!toggleable text="""- * Fix insecure temporary permissions and potential denial of- service attack when creating temp dirs. Closes: #[807341](http://bugs.debian.org/807341)- * Merge from git-annex."""]]
git-repair.cabal view
@@ -1,5 +1,5 @@ Name: git-repair-Version: 1.20151215+Version: 1.20161111 Cabal-Version: >= 1.8 License: GPL Maintainer: Joey Hess <joey@kitenet.net>@@ -7,7 +7,6 @@ Stability: Stable Copyright: 2013 Joey Hess License-File: GPL-Extra-Source-Files: CHANGELOG Build-Type: Custom Homepage: http://git-repair.branchable.com/ Category: Utility@@ -21,11 +20,24 @@ As well as avoiding the need to rm -rf a damaged repository and re-clone, using git-repair can help rescue commits you've made to the damaged repository and not yet pushed out.+Extra-Source-Files:+ CHANGELOG+ TODO+ git-repair.1 Flag network-uri Description: Get Network.URI from the network-uri package Default: True +custom-setup+ Setup-Depends: base (>= 4.5), hslogger, MissingH, unix-compat, process,+ unix, filepath, exceptions, bytestring, directory, IfElse, data-default,+ Cabal++source-repository head+ type: git+ location: git://git-repair.branchable.com/+ Executable git-repair Main-Is: git-repair.hs GHC-Options: -threaded -Wall -fno-warn-tabs@@ -44,6 +56,62 @@ else Build-Depends: unix -source-repository head- type: git- location: git://git-repair.branchable.com/+ Other-Modules:+ Build.Configure+ Build.TestConfig+ Build.Version+ Common+ Git+ Git.Branch+ Git.BuildVersion+ Git.CatFile+ Git.Command+ Git.Config+ Git.Construct+ Git.CurrentRepo+ Git.Destroyer+ Git.DiffTreeItem+ Git.FilePath+ Git.Filename+ Git.Fsck+ Git.Index+ Git.LsFiles+ Git.LsTree+ Git.Objects+ Git.Ref+ Git.RefLog+ Git.Remote+ Git.Repair+ Git.Sha+ Git.Types+ Git.UpdateIndex+ Git.Url+ Git.Version+ Utility.Applicative+ Utility.Batch+ Utility.CoProcess+ Utility.Data+ Utility.Directory+ Utility.DottedVersion+ Utility.Env+ Utility.Exception+ Utility.FileMode+ Utility.FileSize+ Utility.FileSystemEncoding+ Utility.Format+ Utility.Metered+ Utility.Misc+ Utility.Monad+ Utility.PartialPrelude+ Utility.Path+ Utility.PosixFiles+ Utility.Process+ Utility.Process.Shim+ Utility.QuickCheck+ Utility.Rsync+ Utility.SafeCommand+ Utility.SystemDirectory+ Utility.ThreadScheduler+ Utility.Tmp+ Utility.URI+ Utility.UserInfo