enableremote: Better handling of the unusual case where multiple special remotes have been initialized with the same name

Before it would pick one at random, though preferring ones that were not
dead over dead ones.

Now, if one is dead and the other not, it will use the non-dead one. But if
both are not dead, or both dead, it will error out, suggesting the user
clarify what they want to enable.

Sponsored-by: Luke Shumaker on Patreon
This commit is contained in:
Joey Hess 2022-01-05 15:12:01 -04:00
parent 7f3628331c
commit 58afb00f6e
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
3 changed files with 26 additions and 11 deletions

View file

@ -1,6 +1,6 @@
{- git-annex special remote configuration {- git-annex special remote configuration
- -
- Copyright 2011-2019 Joey Hess <id@joeyh.name> - Copyright 2011-2021 Joey Hess <id@joeyh.name>
- -
- Licensed under the GNU AGPL version 3 or higher. - Licensed under the GNU AGPL version 3 or higher.
-} -}
@ -25,16 +25,22 @@ import qualified Types.Remote as Remote
import Git.Types (RemoteName) import Git.Types (RemoteName)
import qualified Data.Map as M import qualified Data.Map as M
import Data.Ord
{- See if there's an existing special remote with this name. {- See if there's an existing special remote with this name.
- -
- Prefer remotes that are not dead when a name appears multiple times. -} - Remotes that are not dead come first in the list
- when a name appears multiple times. -}
findExisting :: RemoteName -> Annex (Maybe (UUID, RemoteConfig, Maybe (ConfigFrom UUID))) findExisting :: RemoteName -> Annex (Maybe (UUID, RemoteConfig, Maybe (ConfigFrom UUID)))
findExisting name = do findExisting name = do
(a, b) <- findExisting' name
return (headMaybe (a++b))
{- Dead remotes with the name are in the second list, all others in the
- first list. -}
findExisting' :: RemoteName -> Annex ([(UUID, RemoteConfig, Maybe (ConfigFrom UUID))], [(UUID, RemoteConfig, Maybe (ConfigFrom UUID))])
findExisting' name = do
t <- trustMap t <- trustMap
headMaybe partition (\(u, _, _) -> M.lookup u t /= Just DeadTrusted)
. sortBy (comparing $ \(u, _, _) -> Down $ M.lookup u t)
. findByRemoteConfig (\c -> lookupName c == Just name) . findByRemoteConfig (\c -> lookupName c == Just name)
<$> Logs.Remote.remoteConfigMap <$> Logs.Remote.remoteConfigMap

View file

@ -3,6 +3,8 @@ git-annex (8.20211232) UNRELEASED; urgency=medium
* export: When a non-annexed symlink is in the tree to be exported, skip it. * export: When a non-annexed symlink is in the tree to be exported, skip it.
* import: When the previously exported tree contained a non-annexed symlink, * import: When the previously exported tree contained a non-annexed symlink,
preserve it in the imported tree so it does not get deleted. preserve it in the imported tree so it does not get deleted.
* enableremote: Better handling of the unusual case where
multiple special remotes have been initialized with the same name.
-- Joey Hess <id@joeyh.name> Mon, 03 Jan 2022 14:01:14 -0400 -- Joey Hess <id@joeyh.name> Mon, 03 Jan 2022 14:01:14 -0400

View file

@ -43,8 +43,13 @@ 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 [] = startSpecialRemote name (Logs.Remote.keyValToConfig Proposed rest) go [] =
=<< SpecialRemote.findExisting name 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 (r:_) = do go (r:_) = do
-- This could be either a normal git remote or a special -- This could be either a normal git remote or a special
-- remote that has an url (eg gcrypt). -- remote that has an url (eg gcrypt).
@ -69,16 +74,16 @@ startNormalRemote name restparams r
ai = ActionItemOther (Just name) ai = ActionItemOther (Just name)
si = SeekInput [name] si = SeekInput [name]
startSpecialRemote :: Git.RemoteName -> Remote.RemoteConfig -> Maybe (UUID, Remote.RemoteConfig, Maybe (SpecialRemote.ConfigFrom UUID)) -> CommandStart startSpecialRemote :: Git.RemoteName -> Remote.RemoteConfig -> [(UUID, Remote.RemoteConfig, Maybe (SpecialRemote.ConfigFrom UUID))] -> CommandStart
startSpecialRemote name config Nothing = do startSpecialRemote 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
Right u | u `M.member` m -> Right u | u `M.member` m ->
startSpecialRemote name config $ startSpecialRemote name config $
Just (u, fromMaybe M.empty (M.lookup u confm), Nothing) [(u, fromMaybe M.empty (M.lookup u confm), Nothing)]
_ -> unknownNameError "Unknown remote name." _ -> unknownNameError "Unknown remote name."
startSpecialRemote name config (Just (u, c, mcu)) = startSpecialRemote name config ((u, c, mcu):[]) =
starting "enableremote" ai si $ do starting "enableremote" 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)
@ -89,6 +94,8 @@ startSpecialRemote name config (Just (u, c, mcu)) =
where where
ai = ActionItemOther (Just name) ai = ActionItemOther (Just name)
si = SeekInput [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."
performSpecialRemote :: RemoteType -> UUID -> R.RemoteConfig -> R.RemoteConfig -> RemoteGitConfig -> Maybe (SpecialRemote.ConfigFrom UUID) -> CommandPerform performSpecialRemote :: RemoteType -> UUID -> R.RemoteConfig -> R.RemoteConfig -> RemoteGitConfig -> Maybe (SpecialRemote.ConfigFrom UUID) -> CommandPerform
performSpecialRemote t u oldc c gc mcu = do performSpecialRemote t u oldc c gc mcu = do