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:
parent
8728695b9c
commit
9155ed1072
15 changed files with 184 additions and 21 deletions
|
@ -109,8 +109,7 @@ commonFieldParsers =
|
||||||
, optionalStringParser sameasUUIDField HiddenField
|
, optionalStringParser sameasUUIDField HiddenField
|
||||||
, optionalStringParser typeField
|
, optionalStringParser typeField
|
||||||
(FieldDesc "type of special remote")
|
(FieldDesc "type of special remote")
|
||||||
, trueFalseParser autoEnableField (Just False)
|
, autoEnableFieldParser
|
||||||
(FieldDesc "automatically enable special remote")
|
|
||||||
, costParser costField
|
, costParser costField
|
||||||
(FieldDesc "default cost of this special remote")
|
(FieldDesc "default cost of this special remote")
|
||||||
, yesNoParser exportTreeField (Just False)
|
, yesNoParser exportTreeField (Just False)
|
||||||
|
@ -121,6 +120,10 @@ commonFieldParsers =
|
||||||
(FieldDesc "directory whose content is preferred")
|
(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
|
{- 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. -}
|
- of that uuid. These values cannot be overridden in the remote's config. -}
|
||||||
sameasInherits :: S.Set RemoteConfigField
|
sameasInherits :: S.Set RemoteConfigField
|
||||||
|
|
|
@ -20,6 +20,8 @@ git-annex (10.20230408) UNRELEASED; urgency=medium
|
||||||
* enableremote: Support enableremote of a git remote (that was previously
|
* enableremote: Support enableremote of a git remote (that was previously
|
||||||
set up with initremote) when additional parameters such as autoenable=
|
set up with initremote) when additional parameters such as autoenable=
|
||||||
are passed.
|
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
|
-- Joey Hess <id@joeyh.name> Sat, 08 Apr 2023 13:57:18 -0400
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,7 @@ import qualified Command.Init
|
||||||
import qualified Command.Describe
|
import qualified Command.Describe
|
||||||
import qualified Command.InitRemote
|
import qualified Command.InitRemote
|
||||||
import qualified Command.EnableRemote
|
import qualified Command.EnableRemote
|
||||||
|
import qualified Command.ConfigRemote
|
||||||
import qualified Command.RenameRemote
|
import qualified Command.RenameRemote
|
||||||
import qualified Command.EnableTor
|
import qualified Command.EnableTor
|
||||||
import qualified Command.Multicast
|
import qualified Command.Multicast
|
||||||
|
@ -154,6 +155,7 @@ cmds testoptparser testrunner mkbenchmarkgenerator = map addGitAnnexCommonOption
|
||||||
, Command.Describe.cmd
|
, Command.Describe.cmd
|
||||||
, Command.InitRemote.cmd
|
, Command.InitRemote.cmd
|
||||||
, Command.EnableRemote.cmd
|
, Command.EnableRemote.cmd
|
||||||
|
, Command.ConfigRemote.cmd
|
||||||
, Command.RenameRemote.cmd
|
, Command.RenameRemote.cmd
|
||||||
, Command.EnableTor.cmd
|
, Command.EnableTor.cmd
|
||||||
, Command.Multicast.cmd
|
, Command.Multicast.cmd
|
||||||
|
|
62
Command/ConfigRemote.hs
Normal file
62
Command/ConfigRemote.hs
Normal 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
|
|
@ -1,6 +1,6 @@
|
||||||
{- git-annex command
|
{- 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.
|
- 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
|
start (name:rest) = go =<< filter matchingname <$> Annex.getGitRemotes
|
||||||
where
|
where
|
||||||
matchingname r = Git.remoteName r == Just name
|
matchingname r = Git.remoteName r == Just name
|
||||||
go [] =
|
go [] = deadLast name $
|
||||||
let use = startSpecialRemote name (Logs.Remote.keyValToConfig Proposed rest)
|
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 (r:_)
|
go (r:_)
|
||||||
| not (null rest) = go []
|
| not (null rest) = go []
|
||||||
| otherwise = do
|
| otherwise = do
|
||||||
|
@ -74,29 +69,34 @@ startNormalRemote name r = starting "enableremote (normal)" ai si $ do
|
||||||
si = SeekInput [name]
|
si = SeekInput [name]
|
||||||
|
|
||||||
startSpecialRemote :: Git.RemoteName -> Remote.RemoteConfig -> [(UUID, Remote.RemoteConfig, Maybe (SpecialRemote.ConfigFrom UUID))] -> CommandStart
|
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
|
m <- SpecialRemote.specialRemoteMap
|
||||||
confm <- Logs.Remote.remoteConfigMap
|
confm <- Logs.Remote.remoteConfigMap
|
||||||
Remote.nameToUUID' name >>= \case
|
Remote.nameToUUID' name >>= \case
|
||||||
([u], _) | u `M.member` m ->
|
([u], _) | u `M.member` m ->
|
||||||
startSpecialRemote name config $
|
startSpecialRemote' cname perform name config $
|
||||||
[(u, fromMaybe M.empty (M.lookup u confm), Nothing)]
|
[(u, fromMaybe M.empty (M.lookup u confm), Nothing)]
|
||||||
(_, msg) -> unknownNameError msg
|
(_, msg) -> unknownNameError msg
|
||||||
startSpecialRemote name config ((u, c, mcu):[]) =
|
startSpecialRemote' cname perform name config ((u, c, mcu):[]) =
|
||||||
starting "enableremote" ai si $ do
|
starting cname ai si $ do
|
||||||
let fullconfig = config `M.union` c
|
let fullconfig = config `M.union` c
|
||||||
t <- either giveup return (SpecialRemote.findType fullconfig)
|
t <- either giveup return (SpecialRemote.findType fullconfig)
|
||||||
gc <- maybe (liftIO dummyRemoteGitConfig)
|
gc <- maybe (liftIO dummyRemoteGitConfig)
|
||||||
(return . Remote.gitconfig)
|
(return . Remote.gitconfig)
|
||||||
=<< Remote.byUUID u
|
=<< Remote.byUUID u
|
||||||
performSpecialRemote t u c fullconfig gc mcu
|
perform t u c fullconfig gc mcu
|
||||||
where
|
where
|
||||||
ai = ActionItemOther (Just (UnquotedString name))
|
ai = ActionItemOther (Just (UnquotedString name))
|
||||||
si = SeekInput [name]
|
si = SeekInput [name]
|
||||||
startSpecialRemote _ _ _ =
|
startSpecialRemote' _ _ _ _ _ =
|
||||||
giveup "Multiple remotes have that name. Either use git-annex renameremote to rename them, or specify the uuid of the remote to enable."
|
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
|
performSpecialRemote t u oldc c gc mcu = do
|
||||||
(c', u') <- R.setup t (R.Enable oldc) (Just u) Nothing c gc
|
(c', u') <- R.setup t (R.Enable oldc) (Just u) Nothing c gc
|
||||||
next $ cleanupSpecialRemote t u' c' mcu
|
next $ cleanupSpecialRemote t u' c' mcu
|
||||||
|
@ -138,3 +138,11 @@ unknownNameError prefix = do
|
||||||
, liftIO . getDynamicConfig . remoteAnnexIgnore
|
, liftIO . getDynamicConfig . remoteAnnexIgnore
|
||||||
=<< Annex.getRemoteGitConfig r
|
=<< 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
|
||||||
|
|
|
@ -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.
|
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]]
|
||||||
|
|
||||||
|
|
|
@ -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.
|
but exits successfully and without autoenabling it.
|
||||||
|
|
||||||
Compare with datalad's behavior when it is a regular git remote. The failure there
|
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
|
happens because git-annex auto-enables the remote successfully, and then
|
||||||
fetch from it, but the repo is not available.
|
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
|
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
|
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.
|
||||||
"""]]
|
"""]]
|
||||||
|
|
|
@ -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.
|
||||||
|
"""]]
|
|
@ -0,0 +1,7 @@
|
||||||
|
[[!comment format=mdwn
|
||||||
|
username="joey"
|
||||||
|
subject="""comment 7"""
|
||||||
|
date="2023-04-18T19:29:28Z"
|
||||||
|
content="""
|
||||||
|
Implemented `git-annex configremote`
|
||||||
|
"""]]
|
41
doc/git-annex-configremote.mdwn
Normal file
41
doc/git-annex-configremote.mdwn
Normal 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.
|
|
@ -70,6 +70,10 @@ Also, the [[git-annex-common-options]](1) can be used.
|
||||||
|
|
||||||
[[git-annex-initremote]](1)
|
[[git-annex-initremote]](1)
|
||||||
|
|
||||||
|
[[git-annex-configremote]](1)
|
||||||
|
|
||||||
|
[[git-annex-renameremote]](1)
|
||||||
|
|
||||||
# AUTHOR
|
# AUTHOR
|
||||||
|
|
||||||
Joey Hess <id@joeyh.name>
|
Joey Hess <id@joeyh.name>
|
||||||
|
|
|
@ -125,6 +125,8 @@ want to use `git annex renameremote`.
|
||||||
|
|
||||||
[[git-annex-enableremote]](1)
|
[[git-annex-enableremote]](1)
|
||||||
|
|
||||||
|
[[git-annex-configremote]](1)
|
||||||
|
|
||||||
[[git-annex-renameremote]](1)
|
[[git-annex-renameremote]](1)
|
||||||
|
|
||||||
# AUTHOR
|
# AUTHOR
|
||||||
|
|
|
@ -38,6 +38,8 @@ the git config if you want to rename it there.
|
||||||
|
|
||||||
[[git-annex-enableremote]](1)
|
[[git-annex-enableremote]](1)
|
||||||
|
|
||||||
|
[[git-annex-configremote]](1)
|
||||||
|
|
||||||
# AUTHOR
|
# AUTHOR
|
||||||
|
|
||||||
Joey Hess <id@joeyh.name>
|
Joey Hess <id@joeyh.name>
|
||||||
|
|
|
@ -222,6 +222,13 @@ content from the key-value store.
|
||||||
|
|
||||||
See [[git-annex-enableremote]](1) for details.
|
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`
|
* `renameremote`
|
||||||
|
|
||||||
Renames a special remote.
|
Renames a special remote.
|
||||||
|
|
|
@ -50,6 +50,7 @@ Extra-Source-Files:
|
||||||
doc/git-annex-calckey.mdwn
|
doc/git-annex-calckey.mdwn
|
||||||
doc/git-annex-checkpresentkey.mdwn
|
doc/git-annex-checkpresentkey.mdwn
|
||||||
doc/git-annex-config.mdwn
|
doc/git-annex-config.mdwn
|
||||||
|
doc/git-annex-configremote.mdwn
|
||||||
doc/git-annex-contentlocation.mdwn
|
doc/git-annex-contentlocation.mdwn
|
||||||
doc/git-annex-copy.mdwn
|
doc/git-annex-copy.mdwn
|
||||||
doc/git-annex-dead.mdwn
|
doc/git-annex-dead.mdwn
|
||||||
|
@ -711,6 +712,7 @@ Executable git-annex
|
||||||
Command.CheckPresentKey
|
Command.CheckPresentKey
|
||||||
Command.Config
|
Command.Config
|
||||||
Command.ConfigList
|
Command.ConfigList
|
||||||
|
Command.ConfigRemote
|
||||||
Command.ContentLocation
|
Command.ContentLocation
|
||||||
Command.Copy
|
Command.Copy
|
||||||
Command.Dead
|
Command.Dead
|
||||||
|
|
Loading…
Add table
Reference in a new issue