git-annex/Assistant/MakeRepo.hs

99 lines
3.1 KiB
Haskell
Raw Normal View History

2019-08-26 16:32:45 +00:00
{- making local repositories
2014-06-16 22:59:23 +00:00
-
- Copyright 2012-2014 Joey Hess <id@joeyh.name>
2014-06-16 22:59:23 +00:00
-
- Licensed under the GNU AGPL version 3 or higher.
2014-06-16 22:59:23 +00:00
-}
{-# LANGUAGE OverloadedStrings #-}
2019-08-26 16:32:45 +00:00
module Assistant.MakeRepo where
2014-06-16 22:59:23 +00:00
import Assistant.WebApp.Common
import Annex.Init
import qualified Git.Construct
import qualified Git.Config
import qualified Git.Command
import qualified Git.Branch
2014-06-16 22:59:23 +00:00
import qualified Annex
import Annex.UUID
import Annex.AdjustedBranch
import Annex.Action
2014-06-16 22:59:23 +00:00
import Types.StandardGroups
import Logs.PreferredContent
import qualified Annex.Branch
import Utility.Process.Transcript
import Config
2014-06-16 22:59:23 +00:00
{- Makes a new git repository. Or, if a git repository already
- exists, returns False. -}
makeRepo :: FilePath -> Bool -> IO Bool
makeRepo path bare = ifM (probeRepoExists path)
( return False
, do
(transcript, ok) <-
processTranscript "git" (toCommand params) Nothing
unless ok $
giveup $ "git init failed!\nOutput:\n" ++ transcript
2014-06-16 22:59:23 +00:00
return True
)
where
baseparams = [Param "init", Param "--quiet"]
params
| bare = baseparams ++ [Param "--bare", File path]
| otherwise = baseparams ++ [File path]
{- Runs an action in the git repository in the specified directory. -}
inDir :: FilePath -> Annex a -> IO a
inDir dir a = do
state <- Annex.new
=<< Git.Config.read
=<< Git.Construct.fromPath (toRawFilePath dir)
avoid flushing keys db queue after each Annex action The flush was only done Annex.run' to make sure that the queue was flushed before git-annex exits. But, doing it there means that as soon as one change gets queued, it gets flushed soon after, which contributes to excessive writes to the database, slowing git-annex down. (This does not yet speed git-annex up, but it is a stepping stone to doing so.) Database queues do not autoflush when garbage collected, so have to be flushed explicitly. I don't think it's possible to make them autoflush (except perhaps if git-annex sqitched to using ResourceT..). The comment in Database.Keys.closeDb used to be accurate, since the automatic flushing did mean that all writes reached the database even when closeDb was not called. But now, closeDb or flushDb needs to be called before stopping using an Annex state. So, removed that comment. In Remote.Git, change to using quiesce everywhere that it used to use stopCoProcesses. This means that uses on onLocal in there are just as slow as before. I considered only calling closeDb on the local git remotes when git-annex exits. But, the reason that Remote.Git calls stopCoProcesses in each onLocal is so as not to leave git processes running that have files open on the remote repo, when it's on removable media. So, it seemed to make sense to also closeDb after each one, since sqlite may also keep files open. Although that has not seemed to cause problems with removable media so far. It was also just easier to quiesce in each onLocal than once at the end. This does likely leave performance on the floor, so could be revisited. In Annex.Content.saveState, there was no reason to close the db, flushing it is enough. The rest of the changes are from auditing for Annex.new, and making sure that quiesce is called, after any action that might possibly need it. After that audit, I'm pretty sure that the change to Annex.run' is safe. The only concern might be that this does let more changes get queued for write to the db, and if git-annex is interrupted, those will be lost. But interrupting git-annex can obviously already prevent it from writing the most recent change to the db, so it must recover from such lost data... right? Sponsored-by: Dartmouth College's Datalad project
2022-10-12 17:50:46 +00:00
Annex.eval state $ a `finally` quiesce True
2014-06-16 22:59:23 +00:00
{- Creates a new repository, and returns its UUID. -}
initRepo :: Bool -> Bool -> FilePath -> Maybe String -> Maybe StandardGroup -> IO UUID
initRepo True primary_assistant_repo dir desc mgroup = inDir dir $ do
initRepo' desc mgroup
{- Initialize the master branch, so things that expect
- to have it will work, before any files are added. -}
unlessM (fromMaybe False . Git.Config.isBare <$> gitRepo) $ do
cmode <- annexCommitMode <$> Annex.getGitConfig
void $ inRepo $ Git.Branch.commitCommand cmode
(Git.Branch.CommitQuiet True)
[ Param "--allow-empty"
2014-06-16 22:59:23 +00:00
, Param "-m"
, Param "created repository"
]
{- Repositories directly managed by the assistant use
- an adjusted unlocked branch with annex.thin set.
2014-06-16 22:59:23 +00:00
-
2023-03-14 02:39:16 +00:00
- Automatic gc is disabled, as it can be slow. Instead, gc is done
2014-06-16 22:59:23 +00:00
- once a day.
-}
when primary_assistant_repo $ do
void $ enterAdjustedBranch (LinkAdjustment UnlockAdjustment)
setConfig (annexConfig "thin") (Git.Config.boolConfig True)
2014-06-16 22:59:23 +00:00
inRepo $ Git.Command.run
[Param "config", Param "gc.auto", Param "0"]
getUUID
{- Repo already exists, could be a non-git-annex repo though so
- still initialize it. -}
initRepo False _ dir desc mgroup = inDir dir $ do
initRepo' desc mgroup
getUUID
initRepo' :: Maybe String -> Maybe StandardGroup -> Annex ()
initRepo' desc mgroup = unlessM isInitialized $ do
initialize desc Nothing
2014-06-16 22:59:23 +00:00
u <- getUUID
maybe noop (defaultStandardGroup u) mgroup
{- Ensure branch gets committed right away so it is
- available for merging immediately. -}
Annex.Branch.commit =<< Annex.Branch.commitMessage
2014-06-16 22:59:23 +00:00
{- Checks if a git repo exists at a location. -}
probeRepoExists :: FilePath -> IO Bool
probeRepoExists dir = isJust <$>
catchDefaultIO Nothing (Git.Construct.checkForRepo dir)