From 484a74f073fadf63eb3f46f1281fc1716ab6bd33 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 27 May 2020 11:54:39 -0400 Subject: [PATCH] auto-init autoenable=yes Try to enable special remotes configured with autoenable=yes when git-annex auto-initialization happens in a new clone of an existing repo. Previously, git-annex init had to be explicitly run to enable them. That was a bit of a wart of a special case for users to need to keep in mind. Special remotes cannot display anything when autoenabled this way, to avoid interfering with the output of git-annex query commands. Any error messages will be hidden, and if it fails, nothing is displayed. The user will realize the remote isn't enable when they try to use it, and can run git-annex init manually then to try the autoenable again and see what failed. That seems like a reasonable approach, and it's less complicated than communicating something across a pipe in order to display it as a side message. Other reason not to do that is that, if the first command the user runs is one like git-annex find that has machine readable output, any message about autoenable failing would need to not be displayed anyway. So better to not display a failure message ever, for consistency. (Had to split out Remote.List.Util to avoid an import cycle.) --- Annex/Init.hs | 32 +++++++++++++++++-- Assistant/DeleteRemote.hs | 4 +-- Assistant/MakeRemote.hs | 8 +++-- Assistant/Sync.hs | 4 +-- Assistant/Threads/ConfigMonitor.hs | 4 +-- Assistant/WebApp/Configurators/Edit.hs | 6 ++-- Assistant/WebApp/RepoList.hs | 4 +-- CHANGELOG | 6 ++++ Command/Init.hs | 19 +++++++++-- Remote.hs | 3 +- Remote/List.hs | 12 ------- Remote/List/Util.hs | 24 ++++++++++++++ ...61__true_seems_to_not_work_any_longer.mdwn | 2 ++ doc/git-annex-init.mdwn | 5 +++ doc/git-annex-initremote.mdwn | 8 ++--- git-annex.cabal | 1 + 16 files changed, 105 insertions(+), 37 deletions(-) create mode 100644 Remote/List/Util.hs diff --git a/Annex/Init.hs b/Annex/Init.hs index 5acfccf7f6..d7c1ebd9ed 100644 --- a/Annex/Init.hs +++ b/Annex/Init.hs @@ -1,6 +1,6 @@ {- git-annex repository initialization - - - Copyright 2011-2019 Joey Hess + - Copyright 2011-2020 Joey Hess - - Licensed under the GNU AGPL version 3 or higher. -} @@ -35,11 +35,13 @@ import Annex.Difference import Annex.UUID import Annex.WorkTree import Annex.Fixup +import Annex.Path import Config import Config.Files import Config.Smudge import qualified Upgrade.V5.Direct as Direct import qualified Annex.AdjustedBranch as AdjustedBranch +import Remote.List.Util (remotesChanged) import Annex.Environment import Annex.Hook import Annex.InodeSentinal @@ -150,8 +152,10 @@ ensureInitialized :: Annex () ensureInitialized = getVersion >>= maybe needsinit checkUpgrade where needsinit = ifM Annex.Branch.hasSibling - ( initialize Nothing Nothing - , giveup $ "First run: git-annex init" + ( do + initialize Nothing Nothing + autoEnableSpecialRemotes + , giveup "First run: git-annex init" ) {- Checks if a repository is initialized. Does not check version for ugrade. -} @@ -287,3 +291,25 @@ fixupUnusualReposAfterInit :: Annex () fixupUnusualReposAfterInit = do gc <- Annex.getGitConfig void $ inRepo $ \r -> fixupUnusualRepos r gc + +{- Try to enable any special remotes that are configured to do so. + - + - The enabling is done in a child process to avoid it using stdio. + -} +autoEnableSpecialRemotes :: Annex () +autoEnableSpecialRemotes = do + rp <- fromRawFilePath <$> fromRepo Git.repoPath + cmd <- liftIO programPath + liftIO $ withNullHandle $ \nullh -> do + let p = proc cmd + [ "init" + , "--autoenable" + ] + (Nothing, Nothing, Nothing, pid) <- createProcess $ p + { std_out = UseHandle nullh + , std_err = UseHandle nullh + , std_in = UseHandle nullh + , cwd = Just rp + } + void $ waitForProcess pid + remotesChanged diff --git a/Assistant/DeleteRemote.hs b/Assistant/DeleteRemote.hs index c7cf807831..f0743401bd 100644 --- a/Assistant/DeleteRemote.hs +++ b/Assistant/DeleteRemote.hs @@ -16,7 +16,7 @@ import Types.Transfer import Logs.Location import Assistant.DaemonStatus import qualified Remote -import Remote.List +import Remote.List.Util import qualified Git.Remote.Remove import Logs.Trust import qualified Annex @@ -35,7 +35,7 @@ disableRemote uuid = do <$> liftAnnex (Remote.remoteFromUUID uuid) liftAnnex $ do inRepo $ Git.Remote.Remove.remove (Remote.name remote) - void $ remoteListRefresh + remotesChanged updateSyncRemotes return remote diff --git a/Assistant/MakeRemote.hs b/Assistant/MakeRemote.hs index 3b36ef9a51..45ceb01337 100644 --- a/Assistant/MakeRemote.hs +++ b/Assistant/MakeRemote.hs @@ -13,7 +13,7 @@ import Assistant.Common import Assistant.Ssh import qualified Types.Remote as R import qualified Remote -import Remote.List +import Remote.List.Util import qualified Remote.Rsync as Rsync import qualified Remote.GCrypt as GCrypt import qualified Git @@ -46,7 +46,7 @@ makeSshRemote sshdata = maker (sshRepoName sshdata) (genSshUrl sshdata) addRemote :: Annex RemoteName -> Annex Remote addRemote a = do name <- a - void remoteListRefresh + remotesChanged maybe (error "failed to add remote") return =<< Remote.byName (Just name) @@ -174,7 +174,9 @@ previouslyUsedCredPair -> (Remote -> Bool) -> Annex (Maybe CredPair) previouslyUsedCredPair getstorage remotetype criteria = - getM fromstorage =<< filter criteria . filter sametype <$> remoteList + getM fromstorage + =<< filter criteria . filter sametype + <$> Remote.remoteList where sametype r = R.typename (R.remotetype r) == R.typename remotetype fromstorage r = do diff --git a/Assistant/Sync.hs b/Assistant/Sync.hs index 5b19d5216a..2b0fae5c97 100644 --- a/Assistant/Sync.hs +++ b/Assistant/Sync.hs @@ -22,8 +22,8 @@ import qualified Git import qualified Git.Command import qualified Remote import qualified Types.Remote as Remote -import qualified Remote.List as Remote import qualified Annex.Branch +import Remote.List.Util import Annex.UUID import Annex.TaggedPush import Annex.Ssh @@ -268,7 +268,7 @@ changeSyncFlag r enabled = do repo <- Remote.getRepo r let key = Config.remoteAnnexConfig repo "sync" Config.setConfig key (boolConfig enabled) - void Remote.remoteListRefresh + remotesChanged updateExportTreeFromLogAll :: Assistant () updateExportTreeFromLogAll = do diff --git a/Assistant/Threads/ConfigMonitor.hs b/Assistant/Threads/ConfigMonitor.hs index b8ccb9e23d..a0d748df66 100644 --- a/Assistant/Threads/ConfigMonitor.hs +++ b/Assistant/Threads/ConfigMonitor.hs @@ -18,7 +18,7 @@ import Logs.Trust import Logs.PreferredContent import Logs.Group import Logs.NumCopies -import Remote.List (remoteListRefresh) +import Remote.List.Util import qualified Git.LsTree as LsTree import Git.Types import Git.FilePath @@ -60,7 +60,7 @@ type Configs = S.Set (RawFilePath, Sha) configFilesActions :: [(RawFilePath, Assistant ())] configFilesActions = [ (uuidLog, void $ liftAnnex uuidDescMapLoad) - , (remoteLog, void $ liftAnnex remoteListRefresh) + , (remoteLog, void $ liftAnnex remotesChanged) , (trustLog, void $ liftAnnex trustMapLoad) , (groupLog, void $ liftAnnex groupMapLoad) , (numcopiesLog, void $ liftAnnex globalNumCopiesLoad) diff --git a/Assistant/WebApp/Configurators/Edit.hs b/Assistant/WebApp/Configurators/Edit.hs index c82fbe248f..cacacdc024 100644 --- a/Assistant/WebApp/Configurators/Edit.hs +++ b/Assistant/WebApp/Configurators/Edit.hs @@ -25,7 +25,7 @@ import qualified Remote.S3 as S3 #endif import qualified Remote import qualified Types.Remote as Remote -import qualified Remote.List as Remote +import Remote.List.Util import Logs.UUID import Logs.Group import Logs.PreferredContent @@ -116,7 +116,7 @@ setRepoConfig uuid mremote oldc newc = do , Param $ T.unpack $ repoName oldc , Param name ] - void Remote.remoteListRefresh + remotesChanged liftAssistant updateSyncRemotes when associatedDirectoryChanged $ case repoAssociatedDirectory newc of Nothing -> noop @@ -309,7 +309,7 @@ getUpgradeRepositoryR r = go =<< liftAnnex (repoIdRemote r) setConfig (remoteAnnexConfig repo "ignore") (Git.Config.boolConfig False) - liftAnnex $ void Remote.remoteListRefresh + liftAnnex remotesChanged liftAssistant updateSyncRemotes liftAssistant $ syncRemote rmt redirect DashboardR diff --git a/Assistant/WebApp/RepoList.hs b/Assistant/WebApp/RepoList.hs index f388dd77b9..9fcca1ae26 100644 --- a/Assistant/WebApp/RepoList.hs +++ b/Assistant/WebApp/RepoList.hs @@ -14,7 +14,7 @@ import Assistant.DaemonStatus import Assistant.WebApp.Notifications import qualified Remote import qualified Types.Remote as Remote -import Remote.List (remoteListRefresh) +import Remote.List.Util import Annex.UUID (getUUID) import Logs.Remote import Logs.Trust @@ -242,7 +242,7 @@ getRepositoriesReorderR = do when (Remote.cost r /= newcost) $ do repo <- Remote.getRepo r setRemoteCost repo newcost - void remoteListRefresh + remotesChanged fromjs = fromMaybe (RepoUUID NoUUID) . readish . T.unpack reorderCosts :: Remote -> [Remote] -> [(Remote, Cost)] diff --git a/CHANGELOG b/CHANGELOG index b19ab01110..95dd7fe9f8 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,11 @@ git-annex (8.20200523) UNRELEASED; urgency=medium + * Try to enable special remotes configured with autoenable=yes + when git-annex auto-initialization happens in a new clone of an + existing repo. Previously, git-annex init had to be explicitly run to + enable them. Special remotes cannot display anything when autoenabled + this way, to avoid interfering with the output of git-annex query + commands. * export: Added options for json output. * import: Added --json-progress. * addurl: Make --preserve-filename also apply when eg a torrent contains diff --git a/Command/Init.hs b/Command/Init.hs index 65bb05ca0b..b79f5be635 100644 --- a/Command/Init.hs +++ b/Command/Init.hs @@ -1,6 +1,6 @@ {- git-annex command - - - Copyright 2010 Joey Hess + - Copyright 2010-2020 Joey Hess - - Licensed under the GNU AGPL version 3 or higher. -} @@ -24,6 +24,7 @@ cmd = dontCheck repoExists $ data InitOptions = InitOptions { initDesc :: String , initVersion :: Maybe RepoVersion + , autoEnableOnly :: Bool } optParser :: CmdParamsDesc -> Parser InitOptions @@ -33,6 +34,10 @@ optParser desc = InitOptions ( long "version" <> metavar paramValue <> help "Override default annex.version" )) + <*> switch + ( long "autoenable" + <> help "only enable special remotes configured with autoenable=true" + ) parseRepoVersion :: MonadFail m => String -> m RepoVersion parseRepoVersion s = case RepoVersion <$> readish s of @@ -47,8 +52,11 @@ seek :: InitOptions -> CommandSeek seek = commandAction . start start :: InitOptions -> CommandStart -start os = starting "init" (ActionItemOther (Just $ initDesc os)) $ - perform os +start os + | autoEnableOnly os = starting "init" (ActionItemOther (Just "autoenable")) $ + performAutoEnableOnly + | otherwise = starting "init" (ActionItemOther (Just $ initDesc os)) $ + perform os perform :: InitOptions -> CommandPerform perform os = do @@ -63,3 +71,8 @@ perform os = do (initVersion os) Annex.SpecialRemote.autoEnable next $ return True + +performAutoEnableOnly :: CommandPerform +performAutoEnableOnly = do + Annex.SpecialRemote.autoEnable + next $ return True diff --git a/Remote.hs b/Remote.hs index 6670925df0..581a035eaf 100644 --- a/Remote.hs +++ b/Remote.hs @@ -74,6 +74,7 @@ import Logs.Trust import Logs.Location hiding (logStatus) import Logs.Web import Remote.List +import Remote.List.Util import Config import Config.DynamicConfig import Git.Types (RemoteName, ConfigKey(..), fromConfigValue) @@ -286,7 +287,7 @@ remoteFromUUID u = ifM ((==) u <$> getUUID) findinmap = M.lookup u <$> remoteMap id {- Re-read remote list in case a new remote has popped up. -} tryharder = do - void remoteListRefresh + remotesChanged findinmap {- Filters a list of remotes to ones that have the listed uuids. -} diff --git a/Remote/List.hs b/Remote/List.hs index e605a62cd1..db8c53feb5 100644 --- a/Remote/List.hs +++ b/Remote/List.hs @@ -21,7 +21,6 @@ import Remote.Helper.Hooks import Remote.Helper.ReadOnly import Remote.Helper.ExportImport import qualified Git -import qualified Git.Config import qualified Remote.Git import qualified Remote.GCrypt @@ -90,17 +89,6 @@ remoteList' autoinit = do >>= mapM (remoteGen m t) >>= return . catMaybes -{- Forces the remoteList to be re-generated, re-reading the git config. -} -remoteListRefresh :: Annex [Remote] -remoteListRefresh = do - newg <- inRepo Git.Config.reRead - Annex.changeState $ \s -> s - { Annex.remotes = [] - , Annex.gitremotes = Nothing - , Annex.repo = newg - } - remoteList - {- Generates a Remote. -} remoteGen :: M.Map UUID RemoteConfig -> RemoteType -> Git.Repo -> Annex (Maybe Remote) remoteGen m t g = do diff --git a/Remote/List/Util.hs b/Remote/List/Util.hs new file mode 100644 index 0000000000..382a98fa5d --- /dev/null +++ b/Remote/List/Util.hs @@ -0,0 +1,24 @@ +{- git-annex remote list utils + - + - Copyright 2011-2020 Joey Hess + - + - Licensed under the GNU AGPL version 3 or higher. + -} + +module Remote.List.Util where + +import Annex.Common +import qualified Annex +import qualified Git.Config + +{- Call when remotes have changed. Re-reads the git config, and + - invalidates the cache so the remoteList will be re-generated next time + - it's used. -} +remotesChanged :: Annex () +remotesChanged = do + newg <- inRepo Git.Config.reRead + Annex.changeState $ \s -> s + { Annex.remotes = [] + , Annex.gitremotes = Nothing + , Annex.repo = newg + } diff --git a/doc/bugs/autoenable__61__true_seems_to_not_work_any_longer.mdwn b/doc/bugs/autoenable__61__true_seems_to_not_work_any_longer.mdwn index b5396e7faf..021f9bf6d5 100644 --- a/doc/bugs/autoenable__61__true_seems_to_not_work_any_longer.mdwn +++ b/doc/bugs/autoenable__61__true_seems_to_not_work_any_longer.mdwn @@ -78,3 +78,5 @@ I am a little confused though since we do test for this scenario in datalad and [[!tag projects/datalad]] [[!meta title="autoenable not done for implicit init"]] + +> [[done]], autoinit will now autoenable --[[Joey]] diff --git a/doc/git-annex-init.mdwn b/doc/git-annex-init.mdwn index c6b814b277..2c48977e40 100644 --- a/doc/git-annex-init.mdwn +++ b/doc/git-annex-init.mdwn @@ -48,6 +48,11 @@ to the user who tries to run git-annex init. When the version given is one that automatically upgrades to a newer version, it will automatically use the newer version instead. +* --autoenable + + Only enable any special remotes that were configured with + autoenable=true, do not otherwise initialize anything. + # SEE ALSO [[git-annex]](1) diff --git a/doc/git-annex-initremote.mdwn b/doc/git-annex-initremote.mdwn index ca204eac7f..c3fd0b0da0 100644 --- a/doc/git-annex-initremote.mdwn +++ b/doc/git-annex-initremote.mdwn @@ -93,10 +93,10 @@ want to use `git annex renameremote`. * `autoenable` To avoid `git annex enableremote` needing to be run, - you can pass "autoenable=true". Then when [[git-annex-init]](1) - is run in a new clone, it will attempt to enable the special remote. Of - course, this works best when the special remote does not need anything - special to be done to get it enabled. + you can pass "autoenable=true". Then when git-annex is run in a new clone, + it will attempt to enable the special remote. Of course, this works best + when the special remote does not need anything special to be done to get + it enabled. * `uuid` diff --git a/git-annex.cabal b/git-annex.cabal index d702fd81d6..9aa7430b18 100644 --- a/git-annex.cabal +++ b/git-annex.cabal @@ -956,6 +956,7 @@ Executable git-annex Remote.Helper.Ssh Remote.Hook Remote.List + Remote.List.Util Remote.P2P Remote.Rsync Remote.Rsync.RsyncUrl