Add locking to avoid races when changing the git-annex branch.
This commit is contained in:
parent
f77979b8b5
commit
d357556141
4 changed files with 29 additions and 12 deletions
29
Branch.hs
29
Branch.hs
|
@ -29,6 +29,8 @@ import Data.Maybe
|
|||
import System.IO
|
||||
import System.IO.Binary
|
||||
import System.Posix.Process
|
||||
import System.Posix.IO
|
||||
import System.Posix.Files
|
||||
import System.Exit
|
||||
import qualified Data.ByteString.Lazy.Char8 as L
|
||||
|
||||
|
@ -129,7 +131,8 @@ create = unlessM hasBranch $ do
|
|||
|
||||
{- Stages the journal, and commits staged changes to the branch. -}
|
||||
commit :: String -> Annex ()
|
||||
commit message = whenM stageJournalFiles $ do
|
||||
commit message = lockJournal $
|
||||
whenM stageJournalFiles $ do
|
||||
g <- Annex.gitRepo
|
||||
withIndex $ liftIO $ Git.commit g message fullname [fullname]
|
||||
|
||||
|
@ -138,7 +141,7 @@ commit message = whenM stageJournalFiles $ do
|
|||
update :: Annex ()
|
||||
update = do
|
||||
state <- getState
|
||||
unless (branchUpdated state) $ withIndex $ do
|
||||
unless (branchUpdated state) $ withIndex $ lockJournal $ do
|
||||
{- Since branches get merged into the index, it's important to
|
||||
- first stage the journal into the index. Otherwise, any
|
||||
- changes in the journal would later get staged, and might
|
||||
|
@ -154,6 +157,7 @@ update = do
|
|||
g <- Annex.gitRepo
|
||||
unless (null updated && not staged) $ liftIO $
|
||||
Git.commit g "update" fullname (fullname:updated)
|
||||
|
||||
Annex.changeState $ \s -> s { Annex.branchstate = state { branchUpdated = True } }
|
||||
invalidateCache
|
||||
|
||||
|
@ -215,13 +219,7 @@ updateRef ref
|
|||
|
||||
{- Applies a function to modifiy the content of a file. -}
|
||||
change :: FilePath -> (String -> String) -> Annex ()
|
||||
change file a = do
|
||||
lock
|
||||
get file >>= return . a >>= set file
|
||||
unlock
|
||||
where
|
||||
lock = return ()
|
||||
unlock = return ()
|
||||
change file a = lockJournal $ get file >>= return . a >>= set file
|
||||
|
||||
{- Records new content of a file into the journal. -}
|
||||
set :: FilePath -> String -> Annex ()
|
||||
|
@ -277,7 +275,7 @@ setJournalFile file content = do
|
|||
writeBinaryFile tmpfile content
|
||||
renameFile tmpfile jfile
|
||||
|
||||
{- Gets journalled content for a file in the branch. -}
|
||||
{- Gets any journalled content for a file in the branch. -}
|
||||
getJournalFile :: FilePath -> Annex (Maybe String)
|
||||
getJournalFile file = do
|
||||
g <- Annex.gitRepo
|
||||
|
@ -346,3 +344,14 @@ journalFile repo file = gitAnnexJournalDir repo </> concatMap mangle file
|
|||
- filename on the branch. -}
|
||||
fileJournal :: FilePath -> FilePath
|
||||
fileJournal = replace "//" "_" . replace "_" "/"
|
||||
|
||||
{- Runs an action that modifies the journal, using locking to avoid
|
||||
- contention with other git-annex processes. -}
|
||||
lockJournal :: Annex a -> Annex a
|
||||
lockJournal a = do
|
||||
g <- Annex.gitRepo
|
||||
h <- liftIO $ createFile (gitAnnexJournalLock g) stdFileMode
|
||||
liftIO $ waitToSetLock h (WriteLock, AbsoluteSeek, 0, 0)
|
||||
r <- a
|
||||
liftIO $ closeFd h
|
||||
return r
|
||||
|
|
|
@ -18,6 +18,7 @@ module Locations (
|
|||
gitAnnexBadLocation,
|
||||
gitAnnexUnusedLog,
|
||||
gitAnnexJournalDir,
|
||||
gitAnnexJournalLock,
|
||||
isLinkToAnnex,
|
||||
hashDirMixed,
|
||||
hashDirLower,
|
||||
|
@ -109,6 +110,10 @@ gitAnnexUnusedLog prefix r = gitAnnexDir r </> (prefix ++ "unused")
|
|||
gitAnnexJournalDir :: Git.Repo -> FilePath
|
||||
gitAnnexJournalDir r = addTrailingPathSeparator $ gitAnnexDir r </> "journal"
|
||||
|
||||
{- Lock file for the journal. -}
|
||||
gitAnnexJournalLock :: Git.Repo -> FilePath
|
||||
gitAnnexJournalLock r = gitAnnexDir r </> "journal.lck"
|
||||
|
||||
{- Checks a symlink target to see if it appears to point to annexed content. -}
|
||||
isLinkToAnnex :: FilePath -> Bool
|
||||
isLinkToAnnex s = ("/.git/" ++ objectDir) `isInfixOf` s
|
||||
|
|
1
debian/changelog
vendored
1
debian/changelog
vendored
|
@ -6,6 +6,7 @@ git-annex (3.20110929) UNRELEASED; urgency=low
|
|||
* When displaying a list of repositories, show git remote names
|
||||
in addition to their descriptions.
|
||||
* Contain the zombie hordes.
|
||||
* Add locking to avoid races when changing the git-annex branch.
|
||||
|
||||
-- Joey Hess <joeyh@debian.org> Thu, 29 Sep 2011 18:58:53 -0400
|
||||
|
||||
|
|
|
@ -49,3 +49,5 @@ Make Branch.change transactional, so it takes a lock, reads a file,
|
|||
applies a function to it, and writes the changed file.
|
||||
|
||||
Make Branch.update hold the same lock.
|
||||
|
||||
> [[Done]].
|
||||
|
|
Loading…
Reference in a new issue