optimisation

avoids a redundant call to git show-ref
This commit is contained in:
Joey Hess 2011-12-12 03:30:47 -04:00
parent f9cd3f6ad1
commit 79345ad5fc

View file

@ -79,20 +79,14 @@ withIndex' bootstrapping a = do
- Compares the ref stored in the lock file with the current - Compares the ref stored in the lock file with the current
- ref of the branch to see if an update is needed. - ref of the branch to see if an update is needed.
-} -}
updateIndex :: Annex (Maybe Git.Ref) updateIndex :: Git.Ref -> Annex ()
updateIndex = do updateIndex branchref = do
branchref <- getRef fullname lock <- fromRepo gitAnnexIndexLock
go branchref lockref <- Git.Ref . firstLine <$>
return branchref liftIO (catchDefaultIO (readFileStrict lock) "")
where when (lockref /= branchref) $ do
go Nothing = return () withIndex $ mergeIndex [fullname]
go (Just branchref) = do setIndexRef branchref
lock <- fromRepo gitAnnexIndexLock
lockref <- Git.Ref . firstLine <$>
liftIO (catchDefaultIO (readFileStrict lock) "")
when (lockref /= branchref) $ do
withIndex $ mergeIndex [fullname]
setIndexRef branchref
{- Record that the branch's index has been updated to correspond to a {- Record that the branch's index has been updated to correspond to a
- given ref of the branch. -} - given ref of the branch. -}
@ -115,13 +109,13 @@ setIndexRef ref = do
- change is reverted. This race is detected and another commit made - change is reverted. This race is detected and another commit made
- to fix it. - to fix it.
-} -}
commitBranch :: String -> [Git.Ref] -> Annex () commitBranch :: Git.Ref -> String -> [Git.Ref] -> Annex ()
commitBranch message parents = do commitBranch branchref message parents = do
expected <- updateIndex updateIndex branchref
committedref <- inRepo $ Git.commit message fullname parents committedref <- inRepo $ Git.commit message fullname parents
setIndexRef committedref setIndexRef committedref
parentrefs <- commitparents <$> catObject committedref parentrefs <- commitparents <$> catObject committedref
when (racedetected expected parentrefs) $ when (racedetected branchref parentrefs) $
fixrace committedref parentrefs fixrace committedref parentrefs
where where
-- look for "parent ref" lines and return the refs -- look for "parent ref" lines and return the refs
@ -133,10 +127,7 @@ commitBranch message parents = do
{- The race can be detected by checking the commit's {- The race can be detected by checking the commit's
- parent, which will be the newly pushed branch, - parent, which will be the newly pushed branch,
- instead of the expected ref that the index was updated to. -} - instead of the expected ref that the index was updated to. -}
racedetected Nothing parentrefs racedetected expectedref parentrefs
| null parentrefs = False -- first commit, no parents
| otherwise = True -- race on first commit
racedetected (Just expectedref) parentrefs
| expectedref `elem` parentrefs = False -- good parent | expectedref `elem` parentrefs = False -- good parent
| otherwise = True -- race! | otherwise = True -- race!
@ -144,7 +135,7 @@ commitBranch message parents = do
- into the index, and recommit on top of the bad commit. -} - into the index, and recommit on top of the bad commit. -}
fixrace committedref lostrefs = do fixrace committedref lostrefs = do
mergeIndex lostrefs mergeIndex lostrefs
commitBranch racemessage [committedref] commitBranch committedref racemessage [committedref]
racemessage = message ++ " (recovery from race)" racemessage = message ++ " (recovery from race)"
@ -179,20 +170,31 @@ getCache file = getState >>= go
{- Creates the branch, if it does not already exist. -} {- Creates the branch, if it does not already exist. -}
create :: Annex () create :: Annex ()
create = unlessM hasBranch $ hasOrigin >>= go create = do
_ <- getBranch
return ()
{- Returns the ref of the branch, creating it first if necessary. -}
getBranch :: Annex (Git.Ref)
getBranch = maybe (hasOrigin >>= go >>= use) (return) =<< getRef fullname
where where
go True = do go True = do
inRepo $ Git.run "branch" inRepo $ Git.run "branch"
[Param $ show name, Param $ show originname] [Param $ show name, Param $ show originname]
maybe (return ()) setIndexRef =<< getRef fullname fromMaybe (error $ "failed to create " ++ show name)
go False = withIndex' True $ <$> getRef fullname
setIndexRef =<< (inRepo $ Git.commit "branch created" fullname []) go False = withIndex' True $ do
inRepo $ Git.commit "branch created" fullname []
use ref = do
setIndexRef ref
return ref
{- Stages the journal, and commits staged changes to the branch. -} {- Stages the journal, and commits staged changes to the branch. -}
commit :: String -> Annex () commit :: String -> Annex ()
commit message = whenM journalDirty $ lockJournal $ do commit message = whenM journalDirty $ lockJournal $ do
stageJournalFiles stageJournalFiles
withIndex $ commitBranch message [fullname] ref <- getBranch
withIndex $ commitBranch ref message [fullname]
{- Ensures that the branch and index are is up-to-date; should be {- Ensures that the branch and index are is up-to-date; should be
- called before data is read from it. Runs only once per git-annex run. - called before data is read from it. Runs only once per git-annex run.
@ -209,14 +211,14 @@ commit message = whenM journalDirty $ lockJournal $ do
-} -}
update :: Annex () update :: Annex ()
update = onceonly $ do update = onceonly $ do
-- ensure branch exists -- ensure branch exists, and get its current ref
create branchref <- getBranch
-- check what needs updating before taking the lock -- check what needs updating before taking the lock
dirty <- journalDirty dirty <- journalDirty
c <- filterM (changedBranch fullname . snd) =<< siblingBranches c <- filterM (changedBranch fullname . snd) =<< siblingBranches
let (refs, branches) = unzip c let (refs, branches) = unzip c
if (not dirty && null refs) if (not dirty && null refs)
then simpleupdate then updateIndex branchref
else withIndex $ lockJournal $ do else withIndex $ lockJournal $ do
when dirty stageJournalFiles when dirty stageJournalFiles
let merge_desc = if null branches let merge_desc = if null branches
@ -229,17 +231,15 @@ update = onceonly $ do
mergeIndex branches mergeIndex branches
ff <- if dirty then return False else tryFastForwardTo refs ff <- if dirty then return False else tryFastForwardTo refs
if ff if ff
then simpleupdate then updateIndex branchref
else commitBranch merge_desc (nub $ fullname:refs) else commitBranch branchref merge_desc
(nub $ fullname:refs)
invalidateCache invalidateCache
where where
onceonly a = unlessM (branchUpdated <$> getState) $ do onceonly a = unlessM (branchUpdated <$> getState) $ do
r <- a r <- a
disableUpdate disableUpdate
return r return r
simpleupdate = do
_ <- updateIndex
return ()
{- Checks if the second branch has any commits not present on the first {- Checks if the second branch has any commits not present on the first
- branch. -} - branch. -}
@ -306,21 +306,16 @@ refExists :: Git.Ref -> Annex Bool
refExists ref = inRepo $ Git.runBool "show-ref" refExists ref = inRepo $ Git.runBool "show-ref"
[Param "--verify", Param "-q", Param $ show ref] [Param "--verify", Param "-q", Param $ show ref]
{- Get the ref of a branch. -} {- Get the ref of a branch. (Must be a fully qualified branch name) -}
getRef :: Git.Branch -> Annex (Maybe Git.Ref) getRef :: Git.Branch -> Annex (Maybe Git.Ref)
getRef branch = process . L.unpack <$> showref getRef branch = process . L.unpack <$> showref
where where
showref = inRepo $ Git.pipeRead [Param "show-ref", showref = inRepo $ Git.pipeRead [Param "show-ref",
Param "--hash", -- get the hash Param "--hash", -- get the hash
Params "--verify", -- only exact match
Param $ show branch] Param $ show branch]
process [] = Nothing process [] = Nothing
process s = Just $ Git.Ref $ firstLine s process s = Just $ Git.Ref $ firstLine s
{- Does the main git-annex branch exist? -}
hasBranch :: Annex Bool
hasBranch = refExists fullname
{- Does origin/git-annex exist? -} {- Does origin/git-annex exist? -}
hasOrigin :: Annex Bool hasOrigin :: Annex Bool
hasOrigin = refExists originname hasOrigin = refExists originname