From d3fbda13e40133d759708cdf240d2d3c18da0cbc Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Wed, 30 Jul 2025 14:08:26 -0400 Subject: [PATCH] p2p --enable p2p: Added --enable option, which can be used to enable P2P networks provided by external commands git-annex-p2p- Made git-annex p2p --enable tor behave the same as git-annex enable-tor, to make tor a bit less of a special case. However, it canot be run as root, since it cannot take the user id parameter. --- Annex/ExternalAddonProcess.hs | 5 +++-- Backend/External.hs | 2 +- CHANGELOG | 7 +++++++ Command/EnableTor.hs | 12 +++++++----- Command/P2P.hs | 26 ++++++++++++++++++++++++-- P2P/Generic.hs | 8 ++++---- Remote/External.hs | 2 +- doc/git-annex-p2p.mdwn | 4 +++- 8 files changed, 50 insertions(+), 16 deletions(-) diff --git a/Annex/ExternalAddonProcess.hs b/Annex/ExternalAddonProcess.hs index 887f9f6466..6e2af92d61 100644 --- a/Annex/ExternalAddonProcess.hs +++ b/Annex/ExternalAddonProcess.hs @@ -33,8 +33,9 @@ data ExternalAddonStartError = ProgramNotInstalled String | ProgramFailure String -startExternalAddonProcess :: String -> [CommandParam] -> ExternalAddonPID -> Annex (Either ExternalAddonStartError ExternalAddonProcess) -startExternalAddonProcess basecmd ps pid = do +-- | Starts an external addon process that speaks a protocol over stdio. +startExternalAddonProcessProtocol :: String -> [CommandParam] -> ExternalAddonPID -> Annex (Either ExternalAddonStartError ExternalAddonProcess) +startExternalAddonProcessProtocol basecmd ps pid = do errrelayer <- mkStderrRelayer g <- Annex.gitRepo cmdpath <- liftIO $ searchPath basecmd diff --git a/Backend/External.hs b/Backend/External.hs index 23977d1ce7..77373cf3ae 100644 --- a/Backend/External.hs +++ b/Backend/External.hs @@ -215,7 +215,7 @@ poolVar = unsafePerformIO $ newMVar M.empty -- using it. newExternalState :: ExternalBackendName -> HasExt -> ExternalAddonPID -> Annex ExternalState newExternalState ebname hasext pid = do - st <- startExternalAddonProcess basecmd [] pid + st <- startExternalAddonProcessProtocol basecmd [] pid st' <- case st of Left (ProgramNotInstalled msg) -> warnonce msg >> return st Left (ProgramFailure msg) -> warnonce msg >> return st diff --git a/CHANGELOG b/CHANGELOG index 3acf44fd33..cb1223ee0d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,10 @@ +git-annex (10.20250722) UNRELEASED; urgency=medium + + * p2p: Added --enable option, which can be used to enable P2P networks + provided by external commands git-annex-p2p- + + -- Joey Hess Wed, 30 Jul 2025 13:45:42 -0400 + git-annex (10.20250721) upstream; urgency=medium * Improved workaround for git 2.50 bug, avoding an occasional test suite diff --git a/Command/EnableTor.hs b/Command/EnableTor.hs index c4b323d825..f8c1d75a8d 100644 --- a/Command/EnableTor.hs +++ b/Command/EnableTor.hs @@ -38,11 +38,11 @@ cmd = noCommit $ dontCheck repoExists $ "uid" (withParams seek) seek :: CmdParams -> CommandSeek -seek = withWords (commandAction . start) +seek = withWords (commandAction . start . Just) -- This runs as root, so avoid making any commits or initializing -- git-annex, or doing other things that create root-owned files. -start :: [String] -> CommandStart +start :: Maybe [String] -> CommandStart #ifndef mingw32_HOST_OS start os = do #else @@ -53,9 +53,11 @@ start _os = do let si = SeekInput [] curruserid <- liftIO getEffectiveUserID if curruserid == 0 - then case readish =<< headMaybe os of - Nothing -> giveup "Need user-id parameter." - Just userid -> go userid + then case os of + Just os' -> case readish =<< headMaybe os' of + Nothing -> giveup "Need user-id parameter." + Just userid -> go userid + Nothing -> giveup "Cannot run this command as root." else starting "enable-tor" ai si $ do gitannex <- fromOsPath <$> liftIO programPath let ps = [Param (cmdname cmd), Param (show curruserid)] diff --git a/Command/P2P.hs b/Command/P2P.hs index 0ee588f42a..491355507c 100644 --- a/Command/P2P.hs +++ b/Command/P2P.hs @@ -1,6 +1,6 @@ {- git-annex command - - - Copyright 2016 Joey Hess + - Copyright 2016-2025 Joey Hess - - Licensed under the GNU AGPL version 3 or higher. -} @@ -13,6 +13,7 @@ import Command import P2P.Address import P2P.Auth import P2P.IO +import P2P.Generic import qualified P2P.Protocol as P2P import Git.Types import qualified Git.Remote @@ -27,6 +28,7 @@ import Utility.ThreadScheduler import Utility.SafeOutput import qualified Utility.FileIO as F import qualified Utility.MagicWormhole as Wormhole +import qualified Command.EnableTor as EnableTor import Control.Concurrent.Async import qualified Data.Text as T @@ -40,10 +42,11 @@ data P2POpts = GenAddresses | LinkRemote | Pair + | Enable P2PNetName optParser :: CmdParamsDesc -> Parser (P2POpts, Maybe RemoteName) optParser _ = (,) - <$> (pair <|> linkremote <|> genaddresses) + <$> (pair <|> linkremote <|> genaddresses <|> enable) <*> optional name where genaddresses = flag' GenAddresses @@ -58,6 +61,10 @@ optParser _ = (,) ( long "pair" <> help "pair with another repository" ) + enable = Enable . P2PNetName <$> strOption + ( long "enable" <> metavar paramName + <> help "enable using a P2P network" + ) name = Git.Remote.makeLegalName <$> strOption ( long "name" <> metavar paramName @@ -75,6 +82,8 @@ seek (Pair, Just name) = commandAction $ seek (Pair, Nothing) = commandAction $ do name <- unusedPeerRemoteName startPairing name =<< loadP2PAddresses +seek (Enable netname, _) = commandAction $ + enableNetwork netname unusedPeerRemoteName :: Annex RemoteName unusedPeerRemoteName = go (1 :: Integer) =<< usednames @@ -316,3 +325,16 @@ setupLink remotename (P2PAddressAuth addr authtoken) = do return LinkSuccess go (Right Nothing) = return $ AuthenticationError "Unable to authenticate with peer. Please check the address and try again." go (Left e) = return $ AuthenticationError $ "Unable to authenticate with peer: " ++ describeProtoFailure e + +enableNetwork :: P2PNetName -> CommandStart +enableNetwork netname@(P2PNetName name) + | name == "tor" = EnableTor.start Nothing + | otherwise = starting "p2p enable" ai si $ next $ do + addrs <- liftIO $ getAddressGenericP2P netname + when (null addrs) $ + giveup $ genericP2PCommand netname ++ " did not output any P2P addresses" + mapM_ storeP2PAddress addrs + return True + where + ai = ActionItemOther (Just (UnquotedString name)) + si = SeekInput [] diff --git a/P2P/Generic.hs b/P2P/Generic.hs index 9dc118f820..ac80f3eedf 100644 --- a/P2P/Generic.hs +++ b/P2P/Generic.hs @@ -25,18 +25,18 @@ connectGenericP2P netname (UnderlyingP2PAddress address) = socketGenericP2P :: P2PNetName -> UnderlyingP2PAddress -> CreateProcess socketGenericP2P netname (UnderlyingP2PAddress address) = (proc (genericP2PCommand netname) ["socket", address]) - { std_in = CreatePipe + { std_out = CreatePipe } addressGenericP2P :: P2PNetName -> CreateProcess addressGenericP2P netname = (proc (genericP2PCommand netname) ["address"]) - { std_in = CreatePipe + { std_out = CreatePipe } getSocketGenericP2P :: P2PNetName -> UnderlyingP2PAddress -> IO (Maybe (OsPath, ProcessHandle)) getSocketGenericP2P netname address = do - (Just hin, Nothing, Nothing, pid) <- createProcess $ + (Nothing, Just hin, Nothing, pid) <- createProcess $ socketGenericP2P netname address hGetLineUntilExitOrEOF pid hin >>= \case Just l | not (null l) -> return $ Just (toOsPath l, pid) @@ -44,7 +44,7 @@ getSocketGenericP2P netname address = do getAddressGenericP2P :: P2PNetName -> IO [P2PAddress] getAddressGenericP2P netname = do - (Just hin, Nothing, Nothing, pid) <- createProcess $ + (Nothing, Just hin, Nothing, pid) <- createProcess $ addressGenericP2P netname go [] hin pid where diff --git a/Remote/External.hs b/Remote/External.hs index 2b26e32239..dcfbaacbf2 100644 --- a/Remote/External.hs +++ b/Remote/External.hs @@ -673,7 +673,7 @@ startExternal' external = do n <- succ <$> readTVar (externalLastPid external) writeTVar (externalLastPid external) n return n - AddonProcess.startExternalAddonProcess externalcmd externalparams pid >>= \case + AddonProcess.startExternalAddonProcessProtocol externalcmd externalparams pid >>= \case Left (AddonProcess.ProgramFailure err) -> do unusable err Left (AddonProcess.ProgramNotInstalled err) -> diff --git a/doc/git-annex-p2p.mdwn b/doc/git-annex-p2p.mdwn index 7d4c6ee80a..deb79c89aa 100644 --- a/doc/git-annex-p2p.mdwn +++ b/doc/git-annex-p2p.mdwn @@ -25,7 +25,9 @@ for documentation about how to create such a program. * `--enable ` Enable using the P2P network with the specified name. - This needs the helper program `git-annex-p2p-` to be installed. + + For networks other than tor, this needs the helper program + `git-annex-p2p-` to be installed. After this command is run, `git annex remotedaemon` can be run to serve incoming connections from peers, and `git-annex p2p --pair` or -- 2.30.2