use xmpp::user@host for xmpp remotes
Inject the required git-remote-xmpp into PATH when running xmpp git push. Rest of the time it will not be in PATH, and git won't be able to talk to xmpp remotes.
This commit is contained in:
parent
de7b8ed6b0
commit
82ccb385e3
3 changed files with 44 additions and 19 deletions
|
@ -24,6 +24,7 @@ import qualified Git.Branch
|
||||||
import qualified Annex.Branch
|
import qualified Annex.Branch
|
||||||
import Locations.UserConfig
|
import Locations.UserConfig
|
||||||
import qualified Types.Remote as Remote
|
import qualified Types.Remote as Remote
|
||||||
|
import Utility.FileMode
|
||||||
|
|
||||||
import Network.Protocol.XMPP
|
import Network.Protocol.XMPP
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
|
@ -43,15 +44,9 @@ finishXMPPPairing jid u = void $ alertWhile alert $
|
||||||
buddy = T.unpack $ buddyName jid
|
buddy = T.unpack $ buddyName jid
|
||||||
alert = pairRequestAcknowledgedAlert buddy Nothing
|
alert = pairRequestAcknowledgedAlert buddy Nothing
|
||||||
|
|
||||||
{- A git remote for an XMPP user? This is represented as a git remote
|
|
||||||
- that has no location set. The user's XMPP address is stored in the
|
|
||||||
- xmppaddress setting.
|
|
||||||
-
|
|
||||||
- The UUID of their remote is also stored as usual.
|
|
||||||
-}
|
|
||||||
makeXMPPGitRemote :: String -> JID -> UUID -> Assistant Bool
|
makeXMPPGitRemote :: String -> JID -> UUID -> Assistant Bool
|
||||||
makeXMPPGitRemote buddyname jid u = do
|
makeXMPPGitRemote buddyname jid u = do
|
||||||
remote <- liftAnnex $ addRemote $ makeGitRemote buddyname "" -- no location
|
remote <- liftAnnex $ addRemote $ makeGitRemote buddyname xmppaddress
|
||||||
liftAnnex $ do
|
liftAnnex $ do
|
||||||
let r = Remote.repo remote
|
let r = Remote.repo remote
|
||||||
storeUUID (remoteConfig r "uuid") u
|
storeUUID (remoteConfig r "uuid") u
|
||||||
|
@ -59,15 +54,15 @@ makeXMPPGitRemote buddyname jid u = do
|
||||||
syncNewRemote remote
|
syncNewRemote remote
|
||||||
return True
|
return True
|
||||||
where
|
where
|
||||||
xmppaddress = T.unpack $ formatJID $ baseJID jid
|
xmppaddress = "xmpp::" ++ T.unpack (formatJID $ baseJID jid)
|
||||||
|
|
||||||
{- Pushes the named refs to the remote, over XMPP, communicating with a
|
{- Pushes the named refs to the remote, over XMPP, communicating with a
|
||||||
- specific client that either requested the push, or responded to our
|
- specific client that either requested the push, or responded to our
|
||||||
- StartingPush message.
|
- message.
|
||||||
-
|
-
|
||||||
- Strategy: Set GIT_SSH to run git-annex. By setting the remote url
|
- To handle xmpp:: urls, git push will run git-remote-xmpp, which is
|
||||||
- to "xmppgit:dummy", "git-annex xmppgit" will be run locally by
|
- injected into its PATH, and in turn runs git-annex xmppgit. The
|
||||||
- "git push". The dataflow them becomes:
|
- dataflow them becomes:
|
||||||
-
|
-
|
||||||
- git push <--> git-annex xmppgit <--> xmppPush <-------> xmpp
|
- git push <--> git-annex xmppgit <--> xmppPush <-------> xmpp
|
||||||
- |
|
- |
|
||||||
|
@ -85,22 +80,25 @@ makeXMPPGitRemote buddyname jid u = do
|
||||||
xmppPush :: ClientID -> Remote -> [Ref] -> Assistant Bool
|
xmppPush :: ClientID -> Remote -> [Ref] -> Assistant Bool
|
||||||
xmppPush cid remote refs = runPush (SendPushRunning cid) handleDeferred $ do
|
xmppPush cid remote refs = runPush (SendPushRunning cid) handleDeferred $ do
|
||||||
sendNetMessage $ StartingPush cid
|
sendNetMessage $ StartingPush cid
|
||||||
program <- liftIO readProgramFile
|
|
||||||
|
|
||||||
(Fd inf, writepush) <- liftIO createPipe
|
(Fd inf, writepush) <- liftIO createPipe
|
||||||
(readpush, Fd outf) <- liftIO createPipe
|
(readpush, Fd outf) <- liftIO createPipe
|
||||||
(Fd controlf, writecontrol) <- liftIO createPipe
|
(Fd controlf, writecontrol) <- liftIO createPipe
|
||||||
|
|
||||||
|
tmp <- liftAnnex $ fromRepo gitAnnexTmpDir
|
||||||
|
let tmpdir = tmp </> "xmppgit"
|
||||||
|
installwrapper tmpdir
|
||||||
|
|
||||||
env <- liftIO getEnvironment
|
env <- liftIO getEnvironment
|
||||||
|
path <- liftIO getSearchPath
|
||||||
let myenv =
|
let myenv =
|
||||||
[ ("GIT_SSH", program)
|
[ ("PATH", join [searchPathSeparator] $ tmpdir:path)
|
||||||
, (relayIn, show inf)
|
, (relayIn, show inf)
|
||||||
, (relayOut, show outf)
|
, (relayOut, show outf)
|
||||||
, (relayControl, show controlf)
|
, (relayControl, show controlf)
|
||||||
]
|
]
|
||||||
g <- liftAnnex gitRepo
|
g <- liftAnnex gitRepo
|
||||||
let name = Remote.name remote
|
let name = Remote.name remote
|
||||||
let mainparams = [Param "-c", Param $ "remote."++name++".url=xmpp:client"]
|
|
||||||
let params = Param "push" : Param name : map (Param . show) refs
|
let params = Param "push" : Param name : map (Param . show) refs
|
||||||
|
|
||||||
inh <- liftIO $ fdToHandle readpush
|
inh <- liftIO $ fdToHandle readpush
|
||||||
|
@ -112,7 +110,7 @@ xmppPush cid remote refs = runPush (SendPushRunning cid) handleDeferred $ do
|
||||||
t2 <- forkIO <~> fromxmpp outh controlh
|
t2 <- forkIO <~> fromxmpp outh controlh
|
||||||
|
|
||||||
ok <- liftIO $ boolSystemEnv "git"
|
ok <- liftIO $ boolSystemEnv "git"
|
||||||
(mainparams ++ gitCommandLine params g)
|
(gitCommandLine params g)
|
||||||
(Just $ env ++ myenv)
|
(Just $ env ++ myenv)
|
||||||
liftIO $ mapM_ killThread [t1, t2]
|
liftIO $ mapM_ killThread [t1, t2]
|
||||||
return ok
|
return ok
|
||||||
|
@ -129,6 +127,15 @@ xmppPush cid remote refs = runPush (SendPushRunning cid) handleDeferred $ do
|
||||||
(ReceivePackDone _ exitcode) -> do
|
(ReceivePackDone _ exitcode) -> do
|
||||||
liftIO $ hPutStrLn controlh (show exitcode)
|
liftIO $ hPutStrLn controlh (show exitcode)
|
||||||
_ -> noop
|
_ -> noop
|
||||||
|
installwrapper tmpdir = liftIO $ do
|
||||||
|
createDirectoryIfMissing True tmpdir
|
||||||
|
let wrapper = tmpdir </> "git-remote-xmpp"
|
||||||
|
program <- readProgramFile
|
||||||
|
writeFile wrapper $ unlines
|
||||||
|
[ "#!/bin/sh"
|
||||||
|
, "exec " ++ program ++ " xmppgit"
|
||||||
|
]
|
||||||
|
modifyFileMode wrapper $ addModes executeModes
|
||||||
|
|
||||||
relayIn :: String
|
relayIn :: String
|
||||||
relayIn = "GIT_ANNEX_XMPPGIT_IN"
|
relayIn = "GIT_ANNEX_XMPPGIT_IN"
|
||||||
|
|
|
@ -20,5 +20,22 @@ seek = [withWords start]
|
||||||
|
|
||||||
start :: [String] -> CommandStart
|
start :: [String] -> CommandStart
|
||||||
start _ = do
|
start _ = do
|
||||||
|
liftIO gitRemoteHelper
|
||||||
liftIO xmppGitRelay
|
liftIO xmppGitRelay
|
||||||
stop
|
stop
|
||||||
|
|
||||||
|
{- A basic implementation of the git-remote-helpers protocol. -}
|
||||||
|
gitRemoteHelper :: IO ()
|
||||||
|
gitRemoteHelper = do
|
||||||
|
expect "capabilities"
|
||||||
|
respond ["connect"]
|
||||||
|
expect "connect git-receive-pack"
|
||||||
|
respond []
|
||||||
|
where
|
||||||
|
expect s = do
|
||||||
|
cmd <- getLine
|
||||||
|
unless (cmd == s) $
|
||||||
|
error $ "git-remote-helpers protocol error: expected: " ++ s ++ ", but got: " ++ cmd
|
||||||
|
respond l = do
|
||||||
|
mapM_ putStrLn l
|
||||||
|
putStrLn ""
|
||||||
|
|
|
@ -48,6 +48,9 @@ writeModes = [ownerWriteMode, groupWriteMode, otherWriteMode]
|
||||||
readModes :: [FileMode]
|
readModes :: [FileMode]
|
||||||
readModes = [ownerReadMode, groupReadMode, otherReadMode]
|
readModes = [ownerReadMode, groupReadMode, otherReadMode]
|
||||||
|
|
||||||
|
executeModes :: [FileMode]
|
||||||
|
executeModes = [ownerExecuteMode, groupExecuteMode, otherExecuteMode]
|
||||||
|
|
||||||
{- Removes the write bits from a file. -}
|
{- Removes the write bits from a file. -}
|
||||||
preventWrite :: FilePath -> IO ()
|
preventWrite :: FilePath -> IO ()
|
||||||
preventWrite f = modifyFileMode f $ removeModes writeModes
|
preventWrite f = modifyFileMode f $ removeModes writeModes
|
||||||
|
@ -72,9 +75,7 @@ isSymLink = checkMode symbolicLinkMode
|
||||||
|
|
||||||
{- Checks if a file has any executable bits set. -}
|
{- Checks if a file has any executable bits set. -}
|
||||||
isExecutable :: FileMode -> Bool
|
isExecutable :: FileMode -> Bool
|
||||||
isExecutable mode = combineModes ebits `intersectFileModes` mode /= 0
|
isExecutable mode = combineModes executeModes `intersectFileModes` mode /= 0
|
||||||
where
|
|
||||||
ebits = [ownerExecuteMode, groupExecuteMode, otherExecuteMode]
|
|
||||||
|
|
||||||
{- Runs an action without that pesky umask influencing it, unless the
|
{- Runs an action without that pesky umask influencing it, unless the
|
||||||
- passed FileMode is the standard one. -}
|
- passed FileMode is the standard one. -}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue