{- management of the git-annex branch
-
- - Copyright 2011-2021 Joey Hess <id@joeyh.name>
+ - Copyright 2011-2022 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU AGPL version 3 or higher.
-}
getUnmergedRefs,
RegardingUUID(..),
change,
+ ChangeOrAppend(..),
+ changeOrAppend,
maybeChange,
commitMessage,
createMessage,
import Control.Concurrent.MVar
import qualified System.FilePath.ByteString as P
-import Annex.Common
+import Annex.Common hiding (append)
import Types.BranchState
import Annex.BranchState
import Annex.Journal
in when (v /= b) $ set jl ru file b
_ -> noop
+data ChangeOrAppend t = Change t | Append t
+
+{- Applies a function that can either modify the content of the file,
+ - or append to the file. Appending can be more efficient when several
+ - lines are written to a file in succession.
+ -}
+changeOrAppend :: Journalable content => RegardingUUID -> RawFilePath -> (L.ByteString -> ChangeOrAppend content) -> Annex ()
+changeOrAppend ru file f = lockJournal $ \jl -> do
+ oldc <- getToChange jl ru file
+ case f oldc of
+ Change newc -> set jl ru file newc
+ Append toappend -> append jl ru file oldc toappend
+
{- Only get private information when the RegardingUUID is itself private. -}
getToChange :: JournalLocked -> RegardingUUID -> RawFilePath -> Annex L.ByteString
getToChange jl ru f = flip (getLocal' jl) f . GetPrivate =<< regardingPrivateUUID ru
-- a log file immediately after writing it.
invalidateCache
+{- Appends content to the journal file.
+ -
+ - The ByteString is the content that the file had before appending.
+ - It is either the content of the journal file or the content from the
+ - branch. When the journal file does not exist yet, this content is
+ - written to it before appending.
+ -}
+append :: Journalable content => JournalLocked -> RegardingUUID -> RawFilePath -> L.ByteString -> content -> Annex ()
+append jl ru f oldc toappend = do
+ journalChanged
+ appendJournalFile jl ru f oldc toappend
+ fastDebug "Annex.Branch" ("append " ++ fromRawFilePath f)
+ invalidateCache
+
{- Commit message used when making a commit of whatever data has changed
- to the git-annex brach. -}
commitMessage :: Annex String
-- exists
write `catchIO` (const (createAnnexDirectory jd >> write))
+{- Appends content to a journal file.
+ -
+ - TODO: Inefficient! -}
+appendJournalFile :: Journalable content => JournalLocked -> RegardingUUID -> RawFilePath -> L.ByteString -> content -> Annex ()
+appendJournalFile _jl ru file oldcontent toappend = withOtherTmp $ \tmp -> do
+ jd <- fromRepo =<< ifM (regardingPrivateUUID ru)
+ ( return gitAnnexPrivateJournalDir
+ , return gitAnnexJournalDir
+ )
+ let jfile = journalFile file
+ let tmpfile = tmp P.</> jfile
+ let write = liftIO $ do
+ withFile (fromRawFilePath tmpfile) WriteMode $ \h -> do
+ writeJournalHandle h oldcontent
+ writeJournalHandle h toappend
+ write `catchIO` (const (createAnnexDirectory jd >> write))
+
data JournalledContent
= NoJournalledContent
| JournalledContent L.ByteString
- A line of the log will look like: "date N INFO"
- Where N=1 when the INFO is present, 0 otherwise.
-
- - Copyright 2010-2021 Joey Hess <id@joeyh.name>
+ - Copyright 2010-2022 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU AGPL version 3 or higher.
-}
addLog' :: Annex.Branch.RegardingUUID -> RawFilePath -> LogStatus -> LogInfo -> CandidateVectorClock -> Annex ()
addLog' ru file logstatus loginfo c =
- Annex.Branch.change ru file $ \b ->
+ Annex.Branch.changeOrAppend ru file $ \b ->
let old = parseLog b
line = genLine logstatus loginfo c old
- in buildLog $ compactLog (line : old)
+ in if isNewInfo line old
+ then Annex.Branch.Append $ buildLog [line]
+ else Annex.Branch.Change $ buildLog $
+ compactLog (line : old)
{- When a LogLine already exists with the same status and info, but an
- older timestamp, that LogLine is preserved, rather than updating the log
{- git-annex presence log, pure operations
-
- - Copyright 2010-2019 Joey Hess <id@joeyh.name>
+ - Copyright 2010-2021 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU AGPL version 3 or higher.
-}
logMap :: [LogLine] -> LogMap
logMap = foldr insertNewerLogLine M.empty
+{- Check if the info of the given line is not in the list of LogLines. -}
+isNewInfo :: LogLine -> [LogLine] -> Bool
+isNewInfo l old = not (any issame old)
+ where
+ issame l' = info l' == info l
+
insertBetter :: (LogLine -> Bool) -> LogLine -> LogMap -> Maybe LogMap
insertBetter betterthan l m
| better = Just (M.insert i l m)