From 9155ed1072ae0968247c6f4bdac8ed70cca270c9 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Tue, 18 Apr 2023 15:30:49 -0400 Subject: [PATCH] configremote New command, currently limited to changing autoenable= setting of a special remote. It will probably never be used for more than that given the limitations on it. Sponsored-by: Brock Spratlen on Patreon --- Annex/SpecialRemote/Config.hs | 7 ++- CHANGELOG | 2 + CmdLine/GitAnnex.hs | 2 + Command/ConfigRemote.hs | 62 +++++++++++++++++++ Command/EnableRemote.hs | 40 +++++++----- ...ing_remote_auto-enabling_not_possible.mdwn | 2 + ..._ccb5b6960da43a93ff0b7404190c51de._comment | 7 ++- ..._5b6359663efb608b9a78ab17c02be9ee._comment | 18 ++++++ ..._995b88efc83f76f14ccb22bc2a6ef4bd._comment | 7 +++ doc/git-annex-configremote.mdwn | 41 ++++++++++++ doc/git-annex-enableremote.mdwn | 4 ++ doc/git-annex-initremote.mdwn | 2 + doc/git-annex-renameremote.mdwn | 2 + doc/git-annex.mdwn | 7 +++ git-annex.cabal | 2 + 15 files changed, 184 insertions(+), 21 deletions(-) create mode 100644 Command/ConfigRemote.hs create mode 100644 doc/bugs/Disabling_remote_auto-enabling_not_possible/comment_6_5b6359663efb608b9a78ab17c02be9ee._comment create mode 100644 doc/bugs/Disabling_remote_auto-enabling_not_possible/comment_7_995b88efc83f76f14ccb22bc2a6ef4bd._comment create mode 100644 doc/git-annex-configremote.mdwn diff --git a/Annex/SpecialRemote/Config.hs b/Annex/SpecialRemote/Config.hs index f1475577fc..6422139809 100644 --- a/Annex/SpecialRemote/Config.hs +++ b/Annex/SpecialRemote/Config.hs @@ -109,8 +109,7 @@ commonFieldParsers = , optionalStringParser sameasUUIDField HiddenField , optionalStringParser typeField (FieldDesc "type of special remote") - , trueFalseParser autoEnableField (Just False) - (FieldDesc "automatically enable special remote") + , autoEnableFieldParser , costParser costField (FieldDesc "default cost of this special remote") , yesNoParser exportTreeField (Just False) @@ -121,6 +120,10 @@ commonFieldParsers = (FieldDesc "directory whose content is preferred") ] +autoEnableFieldParser :: RemoteConfigFieldParser +autoEnableFieldParser = trueFalseParser autoEnableField (Just False) + (FieldDesc "automatically enable special remote") + {- A remote with sameas-uuid set will inherit these values from the config - of that uuid. These values cannot be overridden in the remote's config. -} sameasInherits :: S.Set RemoteConfigField diff --git a/CHANGELOG b/CHANGELOG index 86cd04570a..a01981d495 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -20,6 +20,8 @@ git-annex (10.20230408) UNRELEASED; urgency=medium * enableremote: Support enableremote of a git remote (that was previously set up with initremote) when additional parameters such as autoenable= are passed. + * configremote: New command, currently limited to changing autoenable= + setting of a special remote. -- Joey Hess Sat, 08 Apr 2023 13:57:18 -0400 diff --git a/CmdLine/GitAnnex.hs b/CmdLine/GitAnnex.hs index 9c8e40bfba..7c1dec0663 100644 --- a/CmdLine/GitAnnex.hs +++ b/CmdLine/GitAnnex.hs @@ -56,6 +56,7 @@ import qualified Command.Init import qualified Command.Describe import qualified Command.InitRemote import qualified Command.EnableRemote +import qualified Command.ConfigRemote import qualified Command.RenameRemote import qualified Command.EnableTor import qualified Command.Multicast @@ -154,6 +155,7 @@ cmds testoptparser testrunner mkbenchmarkgenerator = map addGitAnnexCommonOption , Command.Describe.cmd , Command.InitRemote.cmd , Command.EnableRemote.cmd + , Command.ConfigRemote.cmd , Command.RenameRemote.cmd , Command.EnableTor.cmd , Command.Multicast.cmd diff --git a/Command/ConfigRemote.hs b/Command/ConfigRemote.hs new file mode 100644 index 0000000000..862fcb2cb8 --- /dev/null +++ b/Command/ConfigRemote.hs @@ -0,0 +1,62 @@ +{- git-annex command + - + - Copyright 2023 Joey Hess + - + - Licensed under the GNU AGPL version 3 or higher. + -} + +{-# LANGUAGE OverloadedStrings #-} + +module Command.ConfigRemote where + +import Command +import qualified Logs.Remote +import qualified Git.Types as Git +import qualified Annex.SpecialRemote as SpecialRemote +import qualified Types.Remote as Remote +import Types.ProposedAccepted +import Command.EnableRemote (unknownNameError, startSpecialRemote', PerformSpecialRemote, deadLast) + +import qualified Data.Map as M + +cmd :: Command +cmd = command "configremote" SectionSetup + "changes special remote configuration" + (paramPair paramName $ paramOptional $ paramRepeating paramParamValue) + (withParams seek) + +seek :: CmdParams -> CommandSeek +seek = withWords (commandAction . start) + +start :: [String] -> CommandStart +start [] = unknownNameError "Specify the remote to configure." +start (name:rest) = do + cfg <- safeConfig rest + deadLast name $ startSpecialRemote name cfg + +{- Since this command stores config without calling the remote's setup + - method to validate it, it can only be used on fields that are known to + - be safe to change in all remotes. -} +safeConfig :: [String] -> Annex Remote.RemoteConfig +safeConfig cs = do + let rc = Logs.Remote.keyValToConfig Proposed cs + forM_ (M.keys rc) $ \k -> + when (fromProposedAccepted k `notElem` safefields) $ + giveup $ "Cannot change field \"" ++ fromProposedAccepted k ++ "\" with this command. Use git-annex enableremote instead." + case SpecialRemote.parseRemoteConfig rc (Remote.RemoteConfigParser ps Nothing) of + Left err -> giveup err + Right _ -> return rc + where + ps = [ SpecialRemote.autoEnableFieldParser ] + safefields = [ fromProposedAccepted SpecialRemote.autoEnableField ] + +startSpecialRemote :: Git.RemoteName -> Remote.RemoteConfig -> [(UUID, Remote.RemoteConfig, Maybe (SpecialRemote.ConfigFrom UUID))] -> CommandStart +startSpecialRemote = startSpecialRemote' "configremote" performSpecialRemote + +performSpecialRemote :: PerformSpecialRemote +performSpecialRemote _ u _ c _ mcu = do + case mcu of + Nothing -> Logs.Remote.configSet u c + Just (SpecialRemote.ConfigFrom cu) -> + Logs.Remote.configSet cu c + next $ return True diff --git a/Command/EnableRemote.hs b/Command/EnableRemote.hs index 99a713cd3b..d28a981842 100644 --- a/Command/EnableRemote.hs +++ b/Command/EnableRemote.hs @@ -1,6 +1,6 @@ {- git-annex command - - - Copyright 2013-2020 Joey Hess + - Copyright 2013-2023 Joey Hess - - Licensed under the GNU AGPL version 3 or higher. -} @@ -43,13 +43,8 @@ start [] = unknownNameError "Specify the remote to enable." start (name:rest) = go =<< filter matchingname <$> Annex.getGitRemotes where matchingname r = Git.remoteName r == Just name - go [] = - let use = startSpecialRemote name (Logs.Remote.keyValToConfig Proposed rest) - in SpecialRemote.findExisting' name >>= \case - -- enable dead remote only when there is no - -- other remote with the same name - ([], l) -> use l - (l, _) -> use l + go [] = deadLast name $ + startSpecialRemote name (Logs.Remote.keyValToConfig Proposed rest) go (r:_) | not (null rest) = go [] | otherwise = do @@ -74,29 +69,34 @@ startNormalRemote name r = starting "enableremote (normal)" ai si $ do si = SeekInput [name] startSpecialRemote :: Git.RemoteName -> Remote.RemoteConfig -> [(UUID, Remote.RemoteConfig, Maybe (SpecialRemote.ConfigFrom UUID))] -> CommandStart -startSpecialRemote name config [] = do +startSpecialRemote = startSpecialRemote' "enableremote" performSpecialRemote + +type PerformSpecialRemote = RemoteType -> UUID -> R.RemoteConfig -> R.RemoteConfig -> RemoteGitConfig -> Maybe (SpecialRemote.ConfigFrom UUID) -> CommandPerform + +startSpecialRemote' :: String -> PerformSpecialRemote -> Git.RemoteName -> Remote.RemoteConfig -> [(UUID, Remote.RemoteConfig, Maybe (SpecialRemote.ConfigFrom UUID))] -> CommandStart +startSpecialRemote' cname perform name config [] = do m <- SpecialRemote.specialRemoteMap confm <- Logs.Remote.remoteConfigMap Remote.nameToUUID' name >>= \case ([u], _) | u `M.member` m -> - startSpecialRemote name config $ + startSpecialRemote' cname perform name config $ [(u, fromMaybe M.empty (M.lookup u confm), Nothing)] (_, msg) -> unknownNameError msg -startSpecialRemote name config ((u, c, mcu):[]) = - starting "enableremote" ai si $ do +startSpecialRemote' cname perform name config ((u, c, mcu):[]) = + starting cname ai si $ do let fullconfig = config `M.union` c t <- either giveup return (SpecialRemote.findType fullconfig) gc <- maybe (liftIO dummyRemoteGitConfig) (return . Remote.gitconfig) =<< Remote.byUUID u - performSpecialRemote t u c fullconfig gc mcu + perform t u c fullconfig gc mcu where ai = ActionItemOther (Just (UnquotedString name)) si = SeekInput [name] -startSpecialRemote _ _ _ = - giveup "Multiple remotes have that name. Either use git-annex renameremote to rename them, or specify the uuid of the remote to enable." +startSpecialRemote' _ _ _ _ _ = + giveup "Multiple remotes have that name. Either use git-annex renameremote to rename them, or specify the uuid of the remote." -performSpecialRemote :: RemoteType -> UUID -> R.RemoteConfig -> R.RemoteConfig -> RemoteGitConfig -> Maybe (SpecialRemote.ConfigFrom UUID) -> CommandPerform +performSpecialRemote :: PerformSpecialRemote performSpecialRemote t u oldc c gc mcu = do (c', u') <- R.setup t (R.Enable oldc) (Just u) Nothing c gc next $ cleanupSpecialRemote t u' c' mcu @@ -138,3 +138,11 @@ unknownNameError prefix = do , liftIO . getDynamicConfig . remoteAnnexIgnore =<< Annex.getRemoteGitConfig r ] + +-- Use dead remote only when there is no other remote +-- with the same name +deadLast :: Git.RemoteName -> ([(UUID, Remote.RemoteConfig, Maybe (SpecialRemote.ConfigFrom UUID))] -> Annex a) -> Annex a +deadLast name use = + SpecialRemote.findExisting' name >>= \case + ([], l) -> use l + (l, _) -> use l diff --git a/doc/bugs/Disabling_remote_auto-enabling_not_possible.mdwn b/doc/bugs/Disabling_remote_auto-enabling_not_possible.mdwn index 08b7321c75..b90623b009 100644 --- a/doc/bugs/Disabling_remote_auto-enabling_not_possible.mdwn +++ b/doc/bugs/Disabling_remote_auto-enabling_not_possible.mdwn @@ -61,3 +61,5 @@ I am on Debian sid. I tried git-annex versions 10.20221003 and 10.20230126 -- bo Loads! This particular issue started to show up in the datalad support channels due to aging infrastructure setups with still popular datasets tracking them using autoenabling special remotes. +> [[fixed|done]] --[[Joey]] + diff --git a/doc/bugs/Disabling_remote_auto-enabling_not_possible/comment_5_ccb5b6960da43a93ff0b7404190c51de._comment b/doc/bugs/Disabling_remote_auto-enabling_not_possible/comment_5_ccb5b6960da43a93ff0b7404190c51de._comment index c3c244b21b..c61178fbfe 100644 --- a/doc/bugs/Disabling_remote_auto-enabling_not_possible/comment_5_ccb5b6960da43a93ff0b7404190c51de._comment +++ b/doc/bugs/Disabling_remote_auto-enabling_not_possible/comment_5_ccb5b6960da43a93ff0b7404190c51de._comment @@ -23,10 +23,11 @@ Likewise `git-annex init` displays the message from the special remote as a warn but exits successfully and without autoenabling it. Compare with datalad's behavior when it is a regular git remote. The failure there -happens because git-annex auto-enables the remote, and the datalad tries to -fetch from it, but the repo is not available. +happens because git-annex auto-enables the remote successfully, and then +datalad tries to fetch from it, but the repo is not available. So other than the special case of a git remote stored by initremote, this bug's real impact seems to only be that enableremote can't be used to change the -configuration of a remote in this state. +configuration of a remote that's not accessible and `git-annex init` will +warn about such a remote. """]] diff --git a/doc/bugs/Disabling_remote_auto-enabling_not_possible/comment_6_5b6359663efb608b9a78ab17c02be9ee._comment b/doc/bugs/Disabling_remote_auto-enabling_not_possible/comment_6_5b6359663efb608b9a78ab17c02be9ee._comment new file mode 100644 index 0000000000..7baf64ce95 --- /dev/null +++ b/doc/bugs/Disabling_remote_auto-enabling_not_possible/comment_6_5b6359663efb608b9a78ab17c02be9ee._comment @@ -0,0 +1,18 @@ +[[!comment format=mdwn + username="joey" + subject="""comment 6""" + date="2023-04-18T18:11:18Z" + content=""" +Seems that `git-annex configremote` would be very limited in what +configuration it can change. Changing configuration with enableremote +re-runs the `setup` method, which is passed a RemoteConfig with the user's +proposed changes and can either fail if the config is not valid, or return +a RemoteConfig that might not be the same as the input one. Since `setup` also +prepares to use the remote, which is what's failing when the remote is not +accessible, it could not be used by `configremote`. + +So, I think autoenable is about the only config setting that it would make +sense for configremote to be able to change. Changing anything else would +risk storing a configuration that `setup` would not allow. Which could +break the remote in arbitrary ways. +"""]] diff --git a/doc/bugs/Disabling_remote_auto-enabling_not_possible/comment_7_995b88efc83f76f14ccb22bc2a6ef4bd._comment b/doc/bugs/Disabling_remote_auto-enabling_not_possible/comment_7_995b88efc83f76f14ccb22bc2a6ef4bd._comment new file mode 100644 index 0000000000..1750b0c764 --- /dev/null +++ b/doc/bugs/Disabling_remote_auto-enabling_not_possible/comment_7_995b88efc83f76f14ccb22bc2a6ef4bd._comment @@ -0,0 +1,7 @@ +[[!comment format=mdwn + username="joey" + subject="""comment 7""" + date="2023-04-18T19:29:28Z" + content=""" +Implemented `git-annex configremote` +"""]] diff --git a/doc/git-annex-configremote.mdwn b/doc/git-annex-configremote.mdwn new file mode 100644 index 0000000000..d852373c7b --- /dev/null +++ b/doc/git-annex-configremote.mdwn @@ -0,0 +1,41 @@ +# NAME + +git-annex configremote - changes special remote configuration + +# SYNOPSIS + +git annex configemote `name|uuid|desc [param=value ...]` + +# DESCRIPTION + +Changes the configuration of a special remote that was set up earlier +by `git-annex initremote`. The special remote does not need to be enabled +for use in the current repository, and this command will not enable it. + +This command can currently only be used to change the value of the +`autoenable` parameter, eg "autoenable=false". + +To change other parameters, use `git-annex enableremote` + +# OPTIONS + +Most options are not prefixed by a dash, and set parameters of the remote, +as shown above. + +Also, the [[git-annex-common-options]](1) can be used. + +# SEE ALSO + +[[git-annex]](1) + +[[git-annex-initremote]](1) + +[[git-annex-configremote]](1) + +[[git-annex-renameremote]](1) + +# AUTHOR + +Joey Hess + +Warning: Automatically converted into a man page by mdwn2man. Edit with care. diff --git a/doc/git-annex-enableremote.mdwn b/doc/git-annex-enableremote.mdwn index fcd3b6a7cc..3f07fabb76 100644 --- a/doc/git-annex-enableremote.mdwn +++ b/doc/git-annex-enableremote.mdwn @@ -70,6 +70,10 @@ Also, the [[git-annex-common-options]](1) can be used. [[git-annex-initremote]](1) +[[git-annex-configremote]](1) + +[[git-annex-renameremote]](1) + # AUTHOR Joey Hess diff --git a/doc/git-annex-initremote.mdwn b/doc/git-annex-initremote.mdwn index 3a0006a464..d87ab4e45c 100644 --- a/doc/git-annex-initremote.mdwn +++ b/doc/git-annex-initremote.mdwn @@ -125,6 +125,8 @@ want to use `git annex renameremote`. [[git-annex-enableremote]](1) +[[git-annex-configremote]](1) + [[git-annex-renameremote]](1) # AUTHOR diff --git a/doc/git-annex-renameremote.mdwn b/doc/git-annex-renameremote.mdwn index 36a027e68c..7db88ce8c8 100644 --- a/doc/git-annex-renameremote.mdwn +++ b/doc/git-annex-renameremote.mdwn @@ -38,6 +38,8 @@ the git config if you want to rename it there. [[git-annex-enableremote]](1) +[[git-annex-configremote]](1) + # AUTHOR Joey Hess diff --git a/doc/git-annex.mdwn b/doc/git-annex.mdwn index aac408d3ff..2e94f7d4b1 100644 --- a/doc/git-annex.mdwn +++ b/doc/git-annex.mdwn @@ -222,6 +222,13 @@ content from the key-value store. See [[git-annex-enableremote]](1) for details. +* `configremote name [param=value ...]` + + Changes configuration of an existing special remote. + + See [[git-annex-configremote]](1) for details. + + * `renameremote` Renames a special remote. diff --git a/git-annex.cabal b/git-annex.cabal index af7eecfadf..3c131d0b80 100644 --- a/git-annex.cabal +++ b/git-annex.cabal @@ -50,6 +50,7 @@ Extra-Source-Files: doc/git-annex-calckey.mdwn doc/git-annex-checkpresentkey.mdwn doc/git-annex-config.mdwn + doc/git-annex-configremote.mdwn doc/git-annex-contentlocation.mdwn doc/git-annex-copy.mdwn doc/git-annex-dead.mdwn @@ -711,6 +712,7 @@ Executable git-annex Command.CheckPresentKey Command.Config Command.ConfigList + Command.ConfigRemote Command.ContentLocation Command.Copy Command.Dead