diff --git a/CHANGELOG b/CHANGELOG index 7df1684639..d0c23b2b19 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,10 @@ +git-annex (10.20250103) UNRELEASED; urgency=medium + + * Improve handing of ssh connection problems during + remote annex.uuid discovery. + + -- Joey Hess Fri, 03 Jan 2025 14:30:38 -0400 + git-annex (10.20250102) upstream; urgency=medium * Added config `url..annexInsteadOf` corresponding to git's diff --git a/Git/Config.hs b/Git/Config.hs index 82edf69002..b6fd77b249 100644 --- a/Git/Config.hs +++ b/Git/Config.hs @@ -255,9 +255,9 @@ coreBare = "core.bare" {- Runs a command to get the configuration of a repo, - and returns a repo populated with the configuration, as well as the raw - - output and the standard error of the command. -} -fromPipe :: Repo -> String -> [CommandParam] -> ConfigStyle -> IO (Either SomeException (Repo, S.ByteString, String)) -fromPipe r cmd params st = tryNonAsync $ withCreateProcess p go + - output and the exit status and standard error of the command. -} +fromPipe :: Repo -> String -> [CommandParam] -> ConfigStyle -> IO (Repo, S.ByteString, ExitCode, String) +fromPipe r cmd params st = withCreateProcess p go where p = (proc cmd $ toCommand params) { std_out = CreatePipe @@ -267,9 +267,13 @@ fromPipe r cmd params st = tryNonAsync $ withCreateProcess p go withAsync (getstderr pid herr []) $ \errreader -> do val <- S.hGetContents hout err <- wait errreader - forceSuccessProcess p pid - r' <- store val st r - return (r', val, err) + exitcode <- waitForProcess pid + case exitcode of + ExitSuccess -> do + r' <- store val st r + return (r', val, exitcode, err) + ExitFailure _ -> + return (r, val, exitcode, err) go _ _ _ _ = error "internal" getstderr pid herr c = hGetLineUntilExitOrEOF pid herr >>= \case @@ -278,7 +282,7 @@ fromPipe r cmd params st = tryNonAsync $ withCreateProcess p go {- Reads git config from a specified file and returns the repo populated - with the configuration. -} -fromFile :: Repo -> FilePath -> IO (Either SomeException (Repo, S.ByteString, String)) +fromFile :: Repo -> FilePath -> IO (Repo, S.ByteString, ExitCode, String) fromFile r f = fromPipe r "git" [ Param "config" , Param "--file" diff --git a/Remote/GCrypt.hs b/Remote/GCrypt.hs index cb549b7994..8a3852c6b1 100644 --- a/Remote/GCrypt.hs +++ b/Remote/GCrypt.hs @@ -22,7 +22,6 @@ import qualified Data.Map as M import qualified Data.ByteString as S import qualified Data.ByteString.Lazy as L import qualified System.FilePath.ByteString as P -import Control.Exception import Data.Default import Annex.Common @@ -59,7 +58,6 @@ import Utility.Tmp import Logs.Remote import Utility.Gpg import Utility.SshHost -import Utility.Tuple import Utility.Directory.Create import Messages.Progress import Types.ProposedAccepted @@ -508,16 +506,25 @@ getGCryptId :: Bool -> Git.Repo -> RemoteGitConfig -> Annex (Maybe Git.GCrypt.GC getGCryptId fast r gc | Git.repoIsLocal r || Git.repoIsLocalUnknown r = extract <$> liftIO (catchMaybeIO $ Git.Config.read r) - | not fast = extract . liftM fst3 <$> getM (eitherToMaybe <$>) - [ Ssh.onRemote NoConsumeStdin r (\f p -> liftIO (Git.Config.fromPipe r f p Git.Config.ConfigList), return (Left $ giveup "configlist failed")) "configlist" [] [] - , getConfigViaRsync r gc + | not fast = extract <$> getM id + [ Ssh.onRemote NoConsumeStdin r (configpipe, return Nothing) "configlist" [] [] + , getconfig $ getConfigViaRsync r gc ] | otherwise = return (Nothing, r) where extract Nothing = (Nothing, r) extract (Just r') = (fromConfigValue <$> Git.Config.getMaybe coreGCryptId r', r') -getConfigViaRsync :: Git.Repo -> RemoteGitConfig -> Annex (Either SomeException (Git.Repo, S.ByteString, String)) + configpipe f p = getconfig $ liftIO $ + Git.Config.fromPipe r f p Git.Config.ConfigList + + getconfig a = do + (r', _, exitcode, _) <- a + if exitcode == ExitSuccess + then return (Just r') + else return Nothing + +getConfigViaRsync :: Git.Repo -> RemoteGitConfig -> Annex (Git.Repo, S.ByteString, ExitCode, String) getConfigViaRsync r gc = do let (rsynctransport, rsyncurl, _) = rsyncTransport r gc opts <- rsynctransport diff --git a/Remote/Git.hs b/Remote/Git.hs index d77fce1fd8..2dc132501e 100644 --- a/Remote/Git.hs +++ b/Remote/Git.hs @@ -278,14 +278,25 @@ tryGitConfigRead autoinit r hasuuid | Git.repoIsSsh r = storeUpdatedRemote $ do v <- Ssh.onRemote NoConsumeStdin r ( pipedconfig Git.Config.ConfigList autoinit (Git.repoDescribe r) - , return (Left "configlist failed") + , error "internal" ) "configlist" [] configlistfields case v of Right r' | haveconfig r' -> return r' - | otherwise -> configlist_failed - Left _ -> configlist_failed + | otherwise -> do + configlist_failed + return r + Left exitcode -> do + -- ssh exits 255 when there was an error + -- connecting to the remote server. + if exitcode /= ExitFailure 255 + then do + configlist_failed + return r + else do + warning $ UnquotedString $ "Unable to connect to repository " ++ Git.repoDescribe r ++ " to get its annex.uuid configuration." + return r | Git.repoIsHttp r = storeUpdatedRemote geturlconfig | Git.GCrypt.isEncrypted r = handlegcrypt =<< getConfigMaybe (remoteAnnexConfig r "uuid") | Git.repoIsUrl r = do @@ -298,31 +309,35 @@ tryGitConfigRead autoinit r hasuuid haveconfig = not . M.null . Git.config pipedconfig st mustincludeuuuid configloc cmd params = do - v <- liftIO $ Git.Config.fromPipe r cmd params st - case v of - Right (r', val, _err) -> do + (r', val, exitcode, _err) <- liftIO $ + Git.Config.fromPipe r cmd params st + if exitcode == ExitSuccess + then do unless (isUUIDConfigured r' || val == mempty || not mustincludeuuuid) $ do warning $ UnquotedString $ "Failed to get annex.uuid configuration of repository " ++ Git.repoDescribe r warning $ UnquotedString $ "Instead, got: " ++ show val warning "This is unexpected; please check the network transport!" return $ Right r' - Left l -> do + else do warning $ UnquotedString $ "Unable to parse git config from " ++ configloc - return $ Left (show l) + return $ Left exitcode geturlconfig = Url.withUrlOptionsPromptingCreds $ \uo -> do let url = Git.repoLocation r ++ "/config" v <- withTmpFile "git-annex.tmp" $ \tmpfile h -> do liftIO $ hClose h Url.download' nullMeterUpdate Nothing url tmpfile uo >>= \case - Right () -> pipedconfig Git.Config.ConfigNullList - False url "git" - [ Param "config" - , Param "--null" - , Param "--list" - , Param "--file" - , File tmpfile - ] + Right () -> + pipedconfig Git.Config.ConfigNullList + False url "git" + [ Param "config" + , Param "--null" + , Param "--list" + , Param "--file" + , File tmpfile + ] >>= return . \case + Right r' -> Right r' + Left exitcode -> Left $ "git config exited " ++ show exitcode Left err -> return (Left err) case v of Right r' -> do @@ -342,15 +357,7 @@ tryGitConfigRead autoinit r hasuuid warning $ UnquotedString $ url ++ " " ++ err return r - {- Is this remote just not available, or does - - it not have git-annex-shell? - - Find out by trying to fetch from the remote. -} - configlist_failed = case Git.remoteName r of - Nothing -> return r - Just n -> do - whenM (inRepo $ Git.Command.runBool [Param "fetch", Param "--quiet", Param n]) $ do - set_ignore "does not have git-annex installed" True - return r + configlist_failed = set_ignore "does not have git-annex installed" True set_ignore msg longmessage = do case Git.remoteName r of diff --git a/doc/forum/Control_socket_connect__40__..__47__.git__47__annex__47__ssh__47__server.lo/comment_1_f530349d80ca5f43e9b2304f63e4b960._comment b/doc/forum/Control_socket_connect__40__..__47__.git__47__annex__47__ssh__47__server.lo/comment_1_f530349d80ca5f43e9b2304f63e4b960._comment new file mode 100644 index 0000000000..f3b36a3056 --- /dev/null +++ b/doc/forum/Control_socket_connect__40__..__47__.git__47__annex__47__ssh__47__server.lo/comment_1_f530349d80ca5f43e9b2304f63e4b960._comment @@ -0,0 +1,16 @@ +[[!comment format=mdwn + username="joey" + subject="""comment 1""" + date="2025-01-03T17:33:05Z" + content=""" +I don't know why ssh is failing to connect via the socket file like that. +Generally when a socket file like this exists, there is a background ssh +process that is servicing connections to it. It may be there was some +problem with that process. + +git-annex interprets ssh failing as the ssh server not having git-annex +installed, even though in this case it's some other problem. I have made +some changes that improve this, so in this situation it should not set +annex-ignore again, but will instead complain that it cannot connect to the +server. +"""]]