From 1f73db3469e29448bcb1520893de11b23da6fb1f Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Sat, 25 Feb 2012 16:11:47 -0400 Subject: improve alwayscommit=false mode Now changes are staged into the branch's index, but not committed, which avoids growing a large journal. And sync and merge always explicitly commit, ensuring that even when they do nothing else, they commit the staged changes. Added a flag file to indicate that the branch's journal contains uncommitted changes. (Could use git ls-files, but don't want to run that every time.) In the future, this ability to have uncommitted changes staged in the journal might be used on remotes after a series of oneshot commands. --- Annex/Branch.hs | 33 ++++++++++++++++++++++++++++++--- Annex/Content.hs | 8 +++++--- Command/Merge.hs | 2 ++ Command/Sync.hs | 1 + Locations.hs | 5 +++++ debian/changelog | 2 +- 6 files changed, 44 insertions(+), 7 deletions(-) diff --git a/Annex/Branch.hs b/Annex/Branch.hs index acab417fb..52089ac97 100644 --- a/Annex/Branch.hs +++ b/Annex/Branch.hs @@ -18,6 +18,7 @@ module Annex.Branch ( get, change, commit, + stage, files, ) where @@ -114,14 +115,14 @@ updateTo pairs = do -- ensure branch exists, and get its current ref branchref <- getBranch -- check what needs updating before taking the lock - dirty <- journalDirty + dirty <- unCommitted (refs, branches) <- unzip <$> filterM isnewer pairs if not dirty && null refs then updateIndex branchref else withIndex $ lockJournal $ do when dirty stageJournal let merge_desc = if null branches - then "update" + then "update" else "merging " ++ unwords (map Git.Ref.describe branches) ++ " into " ++ show name @@ -182,11 +183,17 @@ set file content = do {- Stages the journal, and commits staged changes to the branch. -} commit :: String -> Annex () -commit message = whenM journalDirty $ lockJournal $ do +commit message = whenM unCommitted $ lockJournal $ do stageJournal ref <- getBranch withIndex $ commitBranch ref message [fullname] +{- Stages the journal, not making a commit to the branch. -} +stage :: Annex () +stage = whenM journalDirty $ lockJournal $ do + stageJournal + setUnCommitted + {- Commits the staged changes in the index to the branch. - - Ensures that the branch's index file is first updated to the state @@ -213,6 +220,7 @@ commitBranch branchref message parents = do parentrefs <- commitparents <$> catObject committedref when (racedetected branchref parentrefs) $ fixrace committedref parentrefs + setCommitted where -- look for "parent ref" lines and return the refs commitparents = map (Git.Ref . snd) . filter isparent . @@ -301,6 +309,25 @@ setIndexSha ref = do lock <- fromRepo gitAnnexIndexLock liftIO $ writeFile lock $ show ref ++ "\n" +{- Checks if there are uncommitted changes in the branch's index or journal. -} +unCommitted :: Annex Bool +unCommitted = do + d <- liftIO . doesFileExist =<< fromRepo gitAnnexIndexDirty + if d + then return d + else journalDirty + +setUnCommitted :: Annex () +setUnCommitted = do + file <- fromRepo gitAnnexIndexDirty + liftIO $ writeFile file "1" + +setCommitted :: Annex () +setCommitted = do + file <- fromRepo gitAnnexIndexDirty + _ <- liftIO $ tryIO $ removeFile file + return () + {- Stages the journal into the index. -} stageJournal :: Annex () stageJournal = do diff --git a/Annex/Content.hs b/Annex/Content.hs index 3a388129e..f328051e3 100644 --- a/Annex/Content.hs +++ b/Annex/Content.hs @@ -312,9 +312,11 @@ getKeysPresent' dir = do saveState :: Bool -> Annex () saveState oneshot = do Annex.Queue.flush False - alwayscommit <- Git.configTrue <$> fromRepo (Git.Config.get "annex.alwayscommit" "true") - unless (oneshot || not alwayscommit) $ do - Annex.Branch.commit "update" + unless oneshot $ do + alwayscommit <- Git.configTrue <$> fromRepo (Git.Config.get "annex.alwayscommit" "true") + if alwayscommit + then Annex.Branch.commit "update" + else Annex.Branch.stage {- Downloads content from any of a list of urls. -} downloadUrl :: [Url.URLString] -> FilePath -> Annex Bool diff --git a/Command/Merge.hs b/Command/Merge.hs index c1f7e899a..0f4661497 100644 --- a/Command/Merge.hs +++ b/Command/Merge.hs @@ -26,4 +26,6 @@ start = do perform :: CommandPerform perform = do Annex.Branch.update + -- commit explicitly, in case no remote branches were merged + Annex.Branch.commit "update" next $ return True diff --git a/Command/Sync.hs b/Command/Sync.hs index 8e237ae84..f7ebba6f5 100644 --- a/Command/Sync.hs +++ b/Command/Sync.hs @@ -75,6 +75,7 @@ commit = do showStart "commit" "" next $ next $ do showOutput + Annex.Branch.commit "update" -- Commit will fail when the tree is clean, so ignore failure. _ <- inRepo $ Git.Command.runBool "commit" [Param "-a", Param "-m", Param "git-annex automatic sync"] diff --git a/Locations.hs b/Locations.hs index 03d6deb1d..244388e0e 100644 --- a/Locations.hs +++ b/Locations.hs @@ -22,6 +22,7 @@ module Locations ( gitAnnexJournalLock, gitAnnexIndex, gitAnnexIndexLock, + gitAnnexIndexDirty, gitAnnexSshDir, isLinkToAnnex, annexHashes, @@ -143,6 +144,10 @@ gitAnnexIndex r = gitAnnexDir r "index" gitAnnexIndexLock :: Git.Repo -> FilePath gitAnnexIndexLock r = gitAnnexDir r "index.lck" +{- Flag file for .git/annex/index. -} +gitAnnexIndexDirty :: Git.Repo -> FilePath +gitAnnexIndexDirty r = gitAnnexDir r "index.dirty" + {- .git/annex/ssh/ is used for ssh connection caching -} gitAnnexSshDir :: Git.Repo -> FilePath gitAnnexSshDir r = addTrailingPathSeparator $ gitAnnexDir r "ssh" diff --git a/debian/changelog b/debian/changelog index 44cdb3782..bb838ed60 100644 --- a/debian/changelog +++ b/debian/changelog @@ -37,7 +37,7 @@ git-annex (3.20120124) UNRELEASED; urgency=low a remote's location log. * To avoid commits of data to the git-annex branch after each command is run, set annex.alwayscommit=false. Its data will then be committed - less frequently, when a merge or sync is done. + less frequently, when a merge or sync is done. -- Joey Hess Tue, 24 Jan 2012 16:21:55 -0400 -- cgit v1.2.3