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.)
This commit is contained in:
Joey Hess 2020-05-27 11:54:39 -04:00
parent 731815891d
commit 484a74f073
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
16 changed files with 105 additions and 37 deletions

View file

@ -1,6 +1,6 @@
{- git-annex repository initialization {- git-annex repository initialization
- -
- Copyright 2011-2019 Joey Hess <id@joeyh.name> - Copyright 2011-2020 Joey Hess <id@joeyh.name>
- -
- Licensed under the GNU AGPL version 3 or higher. - Licensed under the GNU AGPL version 3 or higher.
-} -}
@ -35,11 +35,13 @@ import Annex.Difference
import Annex.UUID import Annex.UUID
import Annex.WorkTree import Annex.WorkTree
import Annex.Fixup import Annex.Fixup
import Annex.Path
import Config import Config
import Config.Files import Config.Files
import Config.Smudge import Config.Smudge
import qualified Upgrade.V5.Direct as Direct import qualified Upgrade.V5.Direct as Direct
import qualified Annex.AdjustedBranch as AdjustedBranch import qualified Annex.AdjustedBranch as AdjustedBranch
import Remote.List.Util (remotesChanged)
import Annex.Environment import Annex.Environment
import Annex.Hook import Annex.Hook
import Annex.InodeSentinal import Annex.InodeSentinal
@ -150,8 +152,10 @@ ensureInitialized :: Annex ()
ensureInitialized = getVersion >>= maybe needsinit checkUpgrade ensureInitialized = getVersion >>= maybe needsinit checkUpgrade
where where
needsinit = ifM Annex.Branch.hasSibling needsinit = ifM Annex.Branch.hasSibling
( initialize Nothing Nothing ( do
, giveup $ "First run: git-annex init" initialize Nothing Nothing
autoEnableSpecialRemotes
, giveup "First run: git-annex init"
) )
{- Checks if a repository is initialized. Does not check version for ugrade. -} {- Checks if a repository is initialized. Does not check version for ugrade. -}
@ -287,3 +291,25 @@ fixupUnusualReposAfterInit :: Annex ()
fixupUnusualReposAfterInit = do fixupUnusualReposAfterInit = do
gc <- Annex.getGitConfig gc <- Annex.getGitConfig
void $ inRepo $ \r -> fixupUnusualRepos r gc 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

View file

@ -16,7 +16,7 @@ import Types.Transfer
import Logs.Location import Logs.Location
import Assistant.DaemonStatus import Assistant.DaemonStatus
import qualified Remote import qualified Remote
import Remote.List import Remote.List.Util
import qualified Git.Remote.Remove import qualified Git.Remote.Remove
import Logs.Trust import Logs.Trust
import qualified Annex import qualified Annex
@ -35,7 +35,7 @@ disableRemote uuid = do
<$> liftAnnex (Remote.remoteFromUUID uuid) <$> liftAnnex (Remote.remoteFromUUID uuid)
liftAnnex $ do liftAnnex $ do
inRepo $ Git.Remote.Remove.remove (Remote.name remote) inRepo $ Git.Remote.Remove.remove (Remote.name remote)
void $ remoteListRefresh remotesChanged
updateSyncRemotes updateSyncRemotes
return remote return remote

View file

@ -13,7 +13,7 @@ import Assistant.Common
import Assistant.Ssh import Assistant.Ssh
import qualified Types.Remote as R import qualified Types.Remote as R
import qualified Remote import qualified Remote
import Remote.List import Remote.List.Util
import qualified Remote.Rsync as Rsync import qualified Remote.Rsync as Rsync
import qualified Remote.GCrypt as GCrypt import qualified Remote.GCrypt as GCrypt
import qualified Git import qualified Git
@ -46,7 +46,7 @@ makeSshRemote sshdata = maker (sshRepoName sshdata) (genSshUrl sshdata)
addRemote :: Annex RemoteName -> Annex Remote addRemote :: Annex RemoteName -> Annex Remote
addRemote a = do addRemote a = do
name <- a name <- a
void remoteListRefresh remotesChanged
maybe (error "failed to add remote") return maybe (error "failed to add remote") return
=<< Remote.byName (Just name) =<< Remote.byName (Just name)
@ -174,7 +174,9 @@ previouslyUsedCredPair
-> (Remote -> Bool) -> (Remote -> Bool)
-> Annex (Maybe CredPair) -> Annex (Maybe CredPair)
previouslyUsedCredPair getstorage remotetype criteria = previouslyUsedCredPair getstorage remotetype criteria =
getM fromstorage =<< filter criteria . filter sametype <$> remoteList getM fromstorage
=<< filter criteria . filter sametype
<$> Remote.remoteList
where where
sametype r = R.typename (R.remotetype r) == R.typename remotetype sametype r = R.typename (R.remotetype r) == R.typename remotetype
fromstorage r = do fromstorage r = do

View file

@ -22,8 +22,8 @@ import qualified Git
import qualified Git.Command import qualified Git.Command
import qualified Remote import qualified Remote
import qualified Types.Remote as Remote import qualified Types.Remote as Remote
import qualified Remote.List as Remote
import qualified Annex.Branch import qualified Annex.Branch
import Remote.List.Util
import Annex.UUID import Annex.UUID
import Annex.TaggedPush import Annex.TaggedPush
import Annex.Ssh import Annex.Ssh
@ -268,7 +268,7 @@ changeSyncFlag r enabled = do
repo <- Remote.getRepo r repo <- Remote.getRepo r
let key = Config.remoteAnnexConfig repo "sync" let key = Config.remoteAnnexConfig repo "sync"
Config.setConfig key (boolConfig enabled) Config.setConfig key (boolConfig enabled)
void Remote.remoteListRefresh remotesChanged
updateExportTreeFromLogAll :: Assistant () updateExportTreeFromLogAll :: Assistant ()
updateExportTreeFromLogAll = do updateExportTreeFromLogAll = do

View file

@ -18,7 +18,7 @@ import Logs.Trust
import Logs.PreferredContent import Logs.PreferredContent
import Logs.Group import Logs.Group
import Logs.NumCopies import Logs.NumCopies
import Remote.List (remoteListRefresh) import Remote.List.Util
import qualified Git.LsTree as LsTree import qualified Git.LsTree as LsTree
import Git.Types import Git.Types
import Git.FilePath import Git.FilePath
@ -60,7 +60,7 @@ type Configs = S.Set (RawFilePath, Sha)
configFilesActions :: [(RawFilePath, Assistant ())] configFilesActions :: [(RawFilePath, Assistant ())]
configFilesActions = configFilesActions =
[ (uuidLog, void $ liftAnnex uuidDescMapLoad) [ (uuidLog, void $ liftAnnex uuidDescMapLoad)
, (remoteLog, void $ liftAnnex remoteListRefresh) , (remoteLog, void $ liftAnnex remotesChanged)
, (trustLog, void $ liftAnnex trustMapLoad) , (trustLog, void $ liftAnnex trustMapLoad)
, (groupLog, void $ liftAnnex groupMapLoad) , (groupLog, void $ liftAnnex groupMapLoad)
, (numcopiesLog, void $ liftAnnex globalNumCopiesLoad) , (numcopiesLog, void $ liftAnnex globalNumCopiesLoad)

View file

@ -25,7 +25,7 @@ import qualified Remote.S3 as S3
#endif #endif
import qualified Remote import qualified Remote
import qualified Types.Remote as Remote import qualified Types.Remote as Remote
import qualified Remote.List as Remote import Remote.List.Util
import Logs.UUID import Logs.UUID
import Logs.Group import Logs.Group
import Logs.PreferredContent import Logs.PreferredContent
@ -116,7 +116,7 @@ setRepoConfig uuid mremote oldc newc = do
, Param $ T.unpack $ repoName oldc , Param $ T.unpack $ repoName oldc
, Param name , Param name
] ]
void Remote.remoteListRefresh remotesChanged
liftAssistant updateSyncRemotes liftAssistant updateSyncRemotes
when associatedDirectoryChanged $ case repoAssociatedDirectory newc of when associatedDirectoryChanged $ case repoAssociatedDirectory newc of
Nothing -> noop Nothing -> noop
@ -309,7 +309,7 @@ getUpgradeRepositoryR r = go =<< liftAnnex (repoIdRemote r)
setConfig setConfig
(remoteAnnexConfig repo "ignore") (remoteAnnexConfig repo "ignore")
(Git.Config.boolConfig False) (Git.Config.boolConfig False)
liftAnnex $ void Remote.remoteListRefresh liftAnnex remotesChanged
liftAssistant updateSyncRemotes liftAssistant updateSyncRemotes
liftAssistant $ syncRemote rmt liftAssistant $ syncRemote rmt
redirect DashboardR redirect DashboardR

View file

@ -14,7 +14,7 @@ import Assistant.DaemonStatus
import Assistant.WebApp.Notifications import Assistant.WebApp.Notifications
import qualified Remote import qualified Remote
import qualified Types.Remote as Remote import qualified Types.Remote as Remote
import Remote.List (remoteListRefresh) import Remote.List.Util
import Annex.UUID (getUUID) import Annex.UUID (getUUID)
import Logs.Remote import Logs.Remote
import Logs.Trust import Logs.Trust
@ -242,7 +242,7 @@ getRepositoriesReorderR = do
when (Remote.cost r /= newcost) $ do when (Remote.cost r /= newcost) $ do
repo <- Remote.getRepo r repo <- Remote.getRepo r
setRemoteCost repo newcost setRemoteCost repo newcost
void remoteListRefresh remotesChanged
fromjs = fromMaybe (RepoUUID NoUUID) . readish . T.unpack fromjs = fromMaybe (RepoUUID NoUUID) . readish . T.unpack
reorderCosts :: Remote -> [Remote] -> [(Remote, Cost)] reorderCosts :: Remote -> [Remote] -> [(Remote, Cost)]

View file

@ -1,5 +1,11 @@
git-annex (8.20200523) UNRELEASED; urgency=medium 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. * export: Added options for json output.
* import: Added --json-progress. * import: Added --json-progress.
* addurl: Make --preserve-filename also apply when eg a torrent contains * addurl: Make --preserve-filename also apply when eg a torrent contains

View file

@ -1,6 +1,6 @@
{- git-annex command {- git-annex command
- -
- Copyright 2010 Joey Hess <id@joeyh.name> - Copyright 2010-2020 Joey Hess <id@joeyh.name>
- -
- Licensed under the GNU AGPL version 3 or higher. - Licensed under the GNU AGPL version 3 or higher.
-} -}
@ -24,6 +24,7 @@ cmd = dontCheck repoExists $
data InitOptions = InitOptions data InitOptions = InitOptions
{ initDesc :: String { initDesc :: String
, initVersion :: Maybe RepoVersion , initVersion :: Maybe RepoVersion
, autoEnableOnly :: Bool
} }
optParser :: CmdParamsDesc -> Parser InitOptions optParser :: CmdParamsDesc -> Parser InitOptions
@ -33,6 +34,10 @@ optParser desc = InitOptions
( long "version" <> metavar paramValue ( long "version" <> metavar paramValue
<> help "Override default annex.version" <> help "Override default annex.version"
)) ))
<*> switch
( long "autoenable"
<> help "only enable special remotes configured with autoenable=true"
)
parseRepoVersion :: MonadFail m => String -> m RepoVersion parseRepoVersion :: MonadFail m => String -> m RepoVersion
parseRepoVersion s = case RepoVersion <$> readish s of parseRepoVersion s = case RepoVersion <$> readish s of
@ -47,7 +52,10 @@ seek :: InitOptions -> CommandSeek
seek = commandAction . start seek = commandAction . start
start :: InitOptions -> CommandStart start :: InitOptions -> CommandStart
start os = starting "init" (ActionItemOther (Just $ initDesc os)) $ start os
| autoEnableOnly os = starting "init" (ActionItemOther (Just "autoenable")) $
performAutoEnableOnly
| otherwise = starting "init" (ActionItemOther (Just $ initDesc os)) $
perform os perform os
perform :: InitOptions -> CommandPerform perform :: InitOptions -> CommandPerform
@ -63,3 +71,8 @@ perform os = do
(initVersion os) (initVersion os)
Annex.SpecialRemote.autoEnable Annex.SpecialRemote.autoEnable
next $ return True next $ return True
performAutoEnableOnly :: CommandPerform
performAutoEnableOnly = do
Annex.SpecialRemote.autoEnable
next $ return True

View file

@ -74,6 +74,7 @@ import Logs.Trust
import Logs.Location hiding (logStatus) import Logs.Location hiding (logStatus)
import Logs.Web import Logs.Web
import Remote.List import Remote.List
import Remote.List.Util
import Config import Config
import Config.DynamicConfig import Config.DynamicConfig
import Git.Types (RemoteName, ConfigKey(..), fromConfigValue) import Git.Types (RemoteName, ConfigKey(..), fromConfigValue)
@ -286,7 +287,7 @@ remoteFromUUID u = ifM ((==) u <$> getUUID)
findinmap = M.lookup u <$> remoteMap id findinmap = M.lookup u <$> remoteMap id
{- Re-read remote list in case a new remote has popped up. -} {- Re-read remote list in case a new remote has popped up. -}
tryharder = do tryharder = do
void remoteListRefresh remotesChanged
findinmap findinmap
{- Filters a list of remotes to ones that have the listed uuids. -} {- Filters a list of remotes to ones that have the listed uuids. -}

View file

@ -21,7 +21,6 @@ import Remote.Helper.Hooks
import Remote.Helper.ReadOnly import Remote.Helper.ReadOnly
import Remote.Helper.ExportImport import Remote.Helper.ExportImport
import qualified Git import qualified Git
import qualified Git.Config
import qualified Remote.Git import qualified Remote.Git
import qualified Remote.GCrypt import qualified Remote.GCrypt
@ -90,17 +89,6 @@ remoteList' autoinit = do
>>= mapM (remoteGen m t) >>= mapM (remoteGen m t)
>>= return . catMaybes >>= 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. -} {- Generates a Remote. -}
remoteGen :: M.Map UUID RemoteConfig -> RemoteType -> Git.Repo -> Annex (Maybe Remote) remoteGen :: M.Map UUID RemoteConfig -> RemoteType -> Git.Repo -> Annex (Maybe Remote)
remoteGen m t g = do remoteGen m t g = do

24
Remote/List/Util.hs Normal file
View file

@ -0,0 +1,24 @@
{- git-annex remote list utils
-
- Copyright 2011-2020 Joey Hess <id@joeyh.name>
-
- 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
}

View file

@ -78,3 +78,5 @@ I am a little confused though since we do test for this scenario in datalad and
[[!tag projects/datalad]] [[!tag projects/datalad]]
[[!meta title="autoenable not done for implicit init"]] [[!meta title="autoenable not done for implicit init"]]
> [[done]], autoinit will now autoenable --[[Joey]]

View file

@ -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 When the version given is one that automatically upgrades to a newer
version, it will automatically use the newer version instead. 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 # SEE ALSO
[[git-annex]](1) [[git-annex]](1)

View file

@ -93,10 +93,10 @@ want to use `git annex renameremote`.
* `autoenable` * `autoenable`
To avoid `git annex enableremote` needing to be run, To avoid `git annex enableremote` needing to be run,
you can pass "autoenable=true". Then when [[git-annex-init]](1) you can pass "autoenable=true". Then when git-annex is run in a new clone,
is run in a new clone, it will attempt to enable the special remote. Of it will attempt to enable the special remote. Of course, this works best
course, this works best when the special remote does not need anything when the special remote does not need anything special to be done to get
special to be done to get it enabled. it enabled.
* `uuid` * `uuid`

View file

@ -956,6 +956,7 @@ Executable git-annex
Remote.Helper.Ssh Remote.Helper.Ssh
Remote.Hook Remote.Hook
Remote.List Remote.List
Remote.List.Util
Remote.P2P Remote.P2P
Remote.Rsync Remote.Rsync
Remote.Rsync.RsyncUrl Remote.Rsync.RsyncUrl