avoid redundant prompt for http password in git-annex get that does autoinit

autoEnableSpecialRemotes runs a subprocess, and if the uuid for a git
remote has not been probed yet, that will do a http get that will prompt
for a password. And then the parent process will subsequently prompt
for a password when getting annexed files from the remote.

So the solution is for autoEnableSpecialRemotes to run remoteList before
the subprocess, which will probe for the uuid for the git remote in the
same process that will later be used to get annexed files.

But, Remote.Git imports Annex.Init, and Remote.List imports Remote.Git,
so Annex.Init cannot import Remote.List. Had to pass remoteList into
functions in Annex.Init to get around this dependency loop.
This commit is contained in:
Joey Hess 2022-09-09 14:43:43 -04:00
parent 9621beabc4
commit c62fe5e9a8
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
6 changed files with 44 additions and 13 deletions

View file

@ -201,8 +201,8 @@ getInitializedVersion = do
- -
- Checks repository version and handles upgrades too. - Checks repository version and handles upgrades too.
-} -}
ensureInitialized :: Annex () ensureInitialized :: Annex [Remote] -> Annex ()
ensureInitialized = getInitializedVersion >>= maybe needsinit checkUpgrade ensureInitialized remotelist = getInitializedVersion >>= maybe needsinit checkUpgrade
where where
needsinit = ifM autoInitializeAllowed needsinit = ifM autoInitializeAllowed
( do ( do
@ -210,7 +210,7 @@ ensureInitialized = getInitializedVersion >>= maybe needsinit checkUpgrade
Right () -> noop Right () -> noop
Left e -> giveup $ show e ++ "\n" ++ Left e -> giveup $ show e ++ "\n" ++
"git-annex: automatic initialization failed due to above problems" "git-annex: automatic initialization failed due to above problems"
autoEnableSpecialRemotes autoEnableSpecialRemotes remotelist
, giveup "First run: git-annex init" , giveup "First run: git-annex init"
) )
@ -254,13 +254,13 @@ guardSafeToUseRepo a = ifM (inRepo Git.Config.checkRepoConfigInaccessible)
- -
- Checks repository version and handles upgrades too. - Checks repository version and handles upgrades too.
-} -}
autoInitialize :: Annex () autoInitialize :: Annex [Remote] -> Annex ()
autoInitialize = getInitializedVersion >>= maybe needsinit checkUpgrade autoInitialize remotelist = getInitializedVersion >>= maybe needsinit checkUpgrade
where where
needsinit = needsinit =
whenM (initializeAllowed <&&> autoInitializeAllowed) $ do whenM (initializeAllowed <&&> autoInitializeAllowed) $ do
initialize True Nothing Nothing initialize True Nothing Nothing
autoEnableSpecialRemotes autoEnableSpecialRemotes remotelist
{- Checks if a repository is initialized. Does not check version for ugrade. -} {- Checks if a repository is initialized. Does not check version for ugrade. -}
isInitialized :: Annex Bool isInitialized :: Annex Bool
@ -440,9 +440,17 @@ fixupUnusualReposAfterInit = do
{- Try to enable any special remotes that are configured to do so. {- 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. - The enabling is done in a child process to avoid it using stdio.
-
- The remotelist should be Remote.List.remoteList, which cannot
- be imported here due to a dependency loop.
-} -}
autoEnableSpecialRemotes :: Annex () autoEnableSpecialRemotes :: Annex [Remote] -> Annex ()
autoEnableSpecialRemotes = do autoEnableSpecialRemotes remotelist = do
-- Get all existing git remotes to probe for their uuid here,
-- so it is not done inside the child process. Doing it in there
-- could result in password prompts for http credentials,
-- which would then not end up cached in this process's state.
_ <- remotelist
rp <- fromRawFilePath <$> fromRepo Git.repoPath rp <- fromRawFilePath <$> fromRepo Git.repoPath
withNullHandle $ \nullh -> gitAnnexChildProcess "init" withNullHandle $ \nullh -> gitAnnexChildProcess "init"
[ Param "--autoenable" ] [ Param "--autoenable" ]

View file

@ -28,6 +28,7 @@ import Utility.Daemon
import Types.Transfer import Types.Transfer
import Types.ActionItem import Types.ActionItem
import Types.WorkerPool as ReExported import Types.WorkerPool as ReExported
import Remote.List
{- Generates a normal Command -} {- Generates a normal Command -}
command :: String -> CommandSection -> String -> CmdParamsDesc -> (CmdParamsDesc -> CommandParser) -> Command command :: String -> CommandSection -> String -> CmdParamsDesc -> (CmdParamsDesc -> CommandParser) -> Command
@ -125,7 +126,7 @@ commonChecks :: [CommandCheck]
commonChecks = [repoExists] commonChecks = [repoExists]
repoExists :: CommandCheck repoExists :: CommandCheck
repoExists = CommandCheck 0 ensureInitialized repoExists = CommandCheck 0 (ensureInitialized remoteList)
notBareRepo :: Command -> Command notBareRepo :: Command -> Command
notBareRepo = addCheck checkNotBareRepo notBareRepo = addCheck checkNotBareRepo

View file

@ -16,6 +16,7 @@ import Config.Files.AutoStart
import qualified BuildInfo import qualified BuildInfo
import Utility.HumanTime import Utility.HumanTime
import Assistant.Install import Assistant.Install
import Remote.List
import Control.Concurrent.Async import Control.Concurrent.Async
@ -62,7 +63,7 @@ start o
stop stop
| otherwise = do | otherwise = do
liftIO ensureInstalled liftIO ensureInstalled
ensureInitialized ensureInitialized remoteList
Command.Watch.start True (daemonOptions o) (startDelayOption o) Command.Watch.start True (daemonOptions o) (startDelayOption o)
startNoRepo :: AssistantOptions -> IO () startNoRepo :: AssistantOptions -> IO ()

View file

@ -350,7 +350,7 @@ tryGitConfigRead autoinit r hasuuid
readlocalannexconfig = do readlocalannexconfig = do
let check = do let check = do
Annex.BranchState.disableUpdate Annex.BranchState.disableUpdate
catchNonAsync autoInitialize $ \e -> catchNonAsync (autoInitialize (pure [])) $ \e ->
warning $ "remote " ++ Git.repoDescribe r ++ warning $ "remote " ++ Git.repoDescribe r ++
":" ++ show e ":" ++ show e
Annex.getState Annex.repo Annex.getState Annex.repo
@ -605,7 +605,7 @@ repairRemote r a = return $ do
s <- Annex.new r s <- Annex.new r
Annex.eval s $ do Annex.eval s $ do
Annex.BranchState.disableUpdate Annex.BranchState.disableUpdate
ensureInitialized ensureInitialized (pure [])
a `finally` stopCoProcesses a `finally` stopCoProcesses
data LocalRemoteAnnex = LocalRemoteAnnex Git.Repo (MVar [(Annex.AnnexState, Annex.AnnexRead)]) data LocalRemoteAnnex = LocalRemoteAnnex Git.Repo (MVar [(Annex.AnnexState, Annex.AnnexRead)])
@ -647,7 +647,7 @@ onLocal' (LocalRemoteAnnex repo mv) a = liftIO (takeMVar mv) >>= \case
[] -> do [] -> do
liftIO $ putMVar mv [] liftIO $ putMVar mv []
v <- newLocal repo v <- newLocal repo
go (v, ensureInitialized >> a) go (v, ensureInitialized (pure []) >> a)
(v:rest) -> do (v:rest) -> do
liftIO $ putMVar mv rest liftIO $ putMVar mv rest
go (v, a) go (v, a)

View file

@ -31,3 +31,5 @@ and wondered if such excessive prompting could be avoided without engaging `git`
[[!meta author=yoh]] [[!meta author=yoh]]
[[!tag projects/repronim]] [[!tag projects/repronim]]
> [[fixed|done]] --[[Joey]]

View file

@ -0,0 +1,19 @@
[[!comment format=mdwn
username="joey"
subject="""comment 4"""
date="2022-09-09T18:39:06Z"
content="""
Fixed the autoinit case.
I'm going to close this as done, despite the cases mentioned above where
subprocesses might redundantly prompt for the credentials.
Another reason
to not worry about those is that `git-annex sync` runs `git fetch` and `git
push` (more than once), so there will be several password prompts there.
So when git-annex runs a git-annex subprocess, it follows it's just as ok
for it to do its own password prompts as it is for a git subprocess to do
so. The solution to either is certianly to enable git's credential cache.
So the scope of this todo has to be limited to prompting done by a single
git-annex process.
"""]]