diff options
-rw-r--r-- | Assistant/Threads/Committer.hs | 16 | ||||
-rw-r--r-- | Command/PreCommit.hs | 38 | ||||
-rw-r--r-- | Git/DiffTree.hs | 25 | ||||
-rw-r--r-- | Git/Ref.hs | 7 | ||||
-rw-r--r-- | Seek.hs | 3 | ||||
-rw-r--r-- | debian/changelog | 1 | ||||
-rw-r--r-- | doc/bugs/direct_mode_renames.mdwn | 6 | ||||
-rw-r--r-- | doc/design/assistant/desymlink.mdwn | 12 |
8 files changed, 75 insertions, 33 deletions
diff --git a/Assistant/Threads/Committer.hs b/Assistant/Threads/Committer.hs index 3d0148b02..d90b0e1cb 100644 --- a/Assistant/Threads/Committer.hs +++ b/Assistant/Threads/Committer.hs @@ -82,12 +82,16 @@ commitStaged = do case v of Left _ -> return False Right _ -> do - void $ inRepo $ Git.Command.runBool "commit" $ nomessage - [ Param "--quiet" - {- Avoid running the usual git-annex pre-commit hook; - - watch does the same symlink fixing, and we don't want - - to deal with unlocked files in these commits. -} - , Param "--no-verify" + direct <- isDirect + void $ inRepo $ Git.Command.runBool "commit" $ nomessage $ + catMaybes + [ Just $ Param "--quiet" + {- In indirect mode, avoid running the + - usual git-annex pre-commit hook; + - watch does the same symlink fixing, + - and we don't want to deal with unlocked + - files in these commits. -} + , if direct then Nothing else Just $ Param "--no-verify" ] {- Empty commits may be made if tree changes cancel - each other out, etc. Git returns nonzero on those, diff --git a/Command/PreCommit.hs b/Command/PreCommit.hs index 7ecf496a9..23b6ecc0a 100644 --- a/Command/PreCommit.hs +++ b/Command/PreCommit.hs @@ -1,6 +1,6 @@ {- git-annex command - - - Copyright 2010 Joey Hess <joey@kitenet.net> + - Copyright 2010, 2013 Joey Hess <joey@kitenet.net> - - Licensed under the GNU GPL version 3 or higher. -} @@ -11,22 +11,42 @@ import Common.Annex import Command import qualified Command.Add import qualified Command.Fix +import qualified Git.DiffTree +import Annex.CatFile +import Annex.Content.Direct +import Git.Sha def :: [Command] def = [command "pre-commit" paramPaths seek "run by git pre-commit hook"] -{- The pre-commit hook needs to fix symlinks to all files being committed. - - And, it needs to inject unlocked files into the annex. -} seek :: [CommandSeek] seek = + -- fix symlinks to files being committed [ whenNotDirect $ withFilesToBeCommitted $ whenAnnexed $ Command.Fix.start - , whenNotDirect $ withFilesUnlockedToBeCommitted start] + -- inject unlocked files into the annex + , whenNotDirect $ withFilesUnlockedToBeCommitted startIndirect + -- update direct mode mappings for committed files + , whenDirect $ withWords startDirect + ] -start :: FilePath -> CommandStart -start file = next $ perform file - -perform :: FilePath -> CommandPerform -perform file = do +startIndirect :: FilePath -> CommandStart +startIndirect file = next $ do unlessM (doCommand $ Command.Add.start file) $ error $ "failed to add " ++ file ++ "; canceling commit" next $ return True + +startDirect :: [String] -> CommandStart +startDirect _ = next $ do + (diffs, clean) <- inRepo $ Git.DiffTree.diffIndex + forM_ diffs go + next $ liftIO clean + where + go diff = do + withkey (Git.DiffTree.srcsha diff) removeAssociatedFile + withkey (Git.DiffTree.dstsha diff) addAssociatedFile + where + withkey sha a = when (sha /= nullSha) $ do + k <- catKey sha + case k of + Nothing -> noop + Just key -> void $ a key (Git.DiffTree.file diff) diff --git a/Git/DiffTree.hs b/Git/DiffTree.hs index af230b495..f122a4fb5 100644 --- a/Git/DiffTree.hs +++ b/Git/DiffTree.hs @@ -9,7 +9,7 @@ module Git.DiffTree ( DiffTreeItem(..), diffTree, diffTreeRecursive, - parseDiffTree + diffIndex, ) where import Numeric @@ -20,6 +20,7 @@ import Git import Git.Sha import Git.Command import qualified Git.Filename +import qualified Git.Ref data DiffTreeItem = DiffTreeItem { srcmode :: FileMode @@ -32,19 +33,29 @@ data DiffTreeItem = DiffTreeItem {- Diffs two tree Refs. -} diffTree :: Ref -> Ref -> Repo -> IO ([DiffTreeItem], IO Bool) -diffTree = diffTree' [] +diffTree src dst = getdiff (Param "diff-tree") + [Param (show src), Param (show dst)] {- Diffs two tree Refs, recursing into sub-trees -} diffTreeRecursive :: Ref -> Ref -> Repo -> IO ([DiffTreeItem], IO Bool) -diffTreeRecursive = diffTree' [Param "-r"] +diffTreeRecursive src dst = getdiff (Param "diff-tree") + [Param "-r", Param (show src), Param (show dst)] -diffTree' :: [CommandParam] -> Ref -> Ref -> Repo -> IO ([DiffTreeItem], IO Bool) -diffTree' params src dst repo = do +{- Diffs between the repository and index. Does nothing if there is not + - yet a commit in the repository. -} +diffIndex :: Repo -> IO ([DiffTreeItem], IO Bool) +diffIndex repo = do + ifM (Git.Ref.headExists repo) + ( getdiff (Param "diff-index") [Param "--cached", Param "HEAD"] repo + , return ([], return True) + ) + +getdiff :: CommandParam -> [CommandParam] -> Repo -> IO ([DiffTreeItem], IO Bool) +getdiff command params repo = do (diff, cleanup) <- pipeNullSplit ps repo return (parseDiffTree diff, cleanup) where - ps = Params "diff-tree -z --raw --no-renames -l0" : params ++ - [Param (show src), Param (show dst)] + ps = command : Params "-z --raw --no-renames -l0" : params {- Parses diff-tree output. -} parseDiffTree :: [String] -> [DiffTreeItem] diff --git a/Git/Ref.hs b/Git/Ref.hs index 02adf0547..3f7613726 100644 --- a/Git/Ref.hs +++ b/Git/Ref.hs @@ -37,6 +37,13 @@ exists :: Ref -> Repo -> IO Bool exists ref = runBool "show-ref" [Param "--verify", Param "-q", Param $ show ref] +{- Checks if HEAD exists. It generally will, except for in a repository + - that was just created. -} +headExists :: Repo -> IO Bool +headExists repo = do + ls <- lines <$> pipeReadStrict [Param "show-ref", Param "--head"] repo + return $ any (" HEAD" `isSuffixOf`) ls + {- Get the sha of a fully qualified git ref, if it exists. -} sha :: Branch -> Repo -> IO (Maybe Sha) sha branch repo = process <$> showref repo @@ -127,3 +127,6 @@ notSymlink f = liftIO $ not . isSymbolicLink <$> getSymbolicLinkStatus f whenNotDirect :: CommandSeek -> CommandSeek whenNotDirect a params = ifM isDirect ( return [] , a params ) + +whenDirect :: CommandSeek -> CommandSeek +whenDirect a params = ifM isDirect ( a params, return [] ) diff --git a/debian/changelog b/debian/changelog index c289794c9..e67147f3d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -10,6 +10,7 @@ git-annex (3.20130125) UNRELEASED; urgency=low * assistant: Ignore .DS_Store on OSX. * assistant: Fix location log when adding new file in direct mode. * Deal with stale mappings for deleted file in direct mode. + * pre-commit: Update direct mode mappings. -- Joey Hess <joeyh@debian.org> Sat, 26 Jan 2013 15:48:40 +1100 diff --git a/doc/bugs/direct_mode_renames.mdwn b/doc/bugs/direct_mode_renames.mdwn index d0c7a8b30..60f449300 100644 --- a/doc/bugs/direct_mode_renames.mdwn +++ b/doc/bugs/direct_mode_renames.mdwn @@ -8,6 +8,8 @@ file working properly in direct mode. Perhaps the pre-commit hook needs to update the mapping for files that were deleted or added. -(This also affects moves of files when the assistant is being used. +This also affects moves of files when the assistant is being used. In this case, the assistant updates the mapping to add the new name, -but does not delete the old name from the mapping.) +but does not delete the old name from the mapping. + +> [[done]]; the pre-commit hook now updates the mappings. --[[Joey]] diff --git a/doc/design/assistant/desymlink.mdwn b/doc/design/assistant/desymlink.mdwn index 05f965358..ffa37399d 100644 --- a/doc/design/assistant/desymlink.mdwn +++ b/doc/design/assistant/desymlink.mdwn @@ -58,9 +58,9 @@ is converted to a real file when it becomes present. This allows just cloning one of these repositories normally, and then as the files are synced in, they become real files. * Maintain a local mapping from keys to files in the tree. This is needed - when sending/receiving keys to know what file to access. Note that a key - can map to multiple files. And that when a file is deleted or moved, the - mapping needs to be updated. + when sending/receiving/dropping keys to know what file to access. + Note that a key can map to multiple files. And that when a file is + deleted or moved, the mapping needs to be updated. * May need a reverse mapping, from files in the tree to keys? TBD (Currently, getting by looking up symlinks using `git cat-file`) (Needed to make things like `git annex drop` that want to map from the @@ -87,12 +87,6 @@ is converted to a real file when it becomes present. * kqueue does not deliver an event when an existing file is modified. This doesn't affect OSX, which uses FSEvents now, but it makes direct mode assistant not 100% on other BSD's. -* The mapping is not updated when files are deleted (or for the deletion - part of a rename). So it can contain old filenames that are no longer in - use. Code that uses the mapping has to take care to check that the - files they refer to exists, which is a good idea anyway. But, - it would be good to at some point update the mappings to remove deleted - files (fsck does this FWIW). ## done |