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
This commit is contained in:
Joey Hess 2023-04-18 15:30:49 -04:00
parent 8728695b9c
commit 9155ed1072
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
15 changed files with 184 additions and 21 deletions

View file

@ -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

View file

@ -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 <id@joeyh.name> Sat, 08 Apr 2023 13:57:18 -0400

View file

@ -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

62
Command/ConfigRemote.hs Normal file
View file

@ -0,0 +1,62 @@
{- git-annex command
-
- Copyright 2023 Joey Hess <id@joeyh.name>
-
- 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

View file

@ -1,6 +1,6 @@
{- git-annex command
-
- Copyright 2013-2020 Joey Hess <id@joeyh.name>
- Copyright 2013-2023 Joey Hess <id@joeyh.name>
-
- 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

View file

@ -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]]

View file

@ -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.
"""]]

View file

@ -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.
"""]]

View file

@ -0,0 +1,7 @@
[[!comment format=mdwn
username="joey"
subject="""comment 7"""
date="2023-04-18T19:29:28Z"
content="""
Implemented `git-annex configremote`
"""]]

View file

@ -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 <id@joeyh.name>
Warning: Automatically converted into a man page by mdwn2man. Edit with care.

View file

@ -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 <id@joeyh.name>

View file

@ -125,6 +125,8 @@ want to use `git annex renameremote`.
[[git-annex-enableremote]](1)
[[git-annex-configremote]](1)
[[git-annex-renameremote]](1)
# AUTHOR

View file

@ -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 <id@joeyh.name>

View file

@ -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.

View file

@ -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