2014-04-06 23:06:03 +00:00
|
|
|
{- git-remote-daemon, git-annex-shell over ssh transport
|
|
|
|
-
|
2015-01-21 16:50:09 +00:00
|
|
|
- Copyright 2014 Joey Hess <id@joeyh.name>
|
2014-04-06 23:06:03 +00:00
|
|
|
-
|
2019-03-13 19:48:14 +00:00
|
|
|
- Licensed under the GNU AGPL version 3 or higher.
|
2014-04-06 23:06:03 +00:00
|
|
|
-}
|
|
|
|
|
2015-03-16 19:28:29 +00:00
|
|
|
module RemoteDaemon.Transport.Ssh (transport, transportUsingCmd) where
|
2014-04-06 23:06:03 +00:00
|
|
|
|
2016-01-20 20:36:33 +00:00
|
|
|
import Annex.Common
|
2014-04-12 19:59:34 +00:00
|
|
|
import Annex.Ssh
|
2014-04-06 23:06:03 +00:00
|
|
|
import RemoteDaemon.Types
|
2014-04-08 17:41:36 +00:00
|
|
|
import RemoteDaemon.Common
|
2014-04-06 23:06:03 +00:00
|
|
|
import Remote.Helper.Ssh
|
2014-04-08 17:41:36 +00:00
|
|
|
import qualified RemoteDaemon.Transport.Ssh.Types as SshRemote
|
2014-04-06 23:06:03 +00:00
|
|
|
import Utility.SimpleProtocol
|
2014-04-09 18:10:29 +00:00
|
|
|
import qualified Git
|
2014-04-06 23:06:03 +00:00
|
|
|
import Git.Command
|
2016-12-09 18:52:38 +00:00
|
|
|
import Annex.ChangedRefs
|
2014-04-06 23:06:03 +00:00
|
|
|
|
2015-01-15 19:37:48 +00:00
|
|
|
import Control.Concurrent.STM
|
2014-04-06 23:06:03 +00:00
|
|
|
import Control.Concurrent.Async
|
|
|
|
|
|
|
|
transport :: Transport
|
2015-03-16 19:28:29 +00:00
|
|
|
transport rr@(RemoteRepo r _) url h ichan ochan = do
|
2017-02-15 19:08:46 +00:00
|
|
|
v <- liftAnnex h $ git_annex_shell ConsumeStdin r "notifychanges" [] []
|
2015-03-16 19:28:29 +00:00
|
|
|
case v of
|
|
|
|
Nothing -> noop
|
|
|
|
Just (cmd, params) -> transportUsingCmd cmd params rr url h ichan ochan
|
|
|
|
|
|
|
|
transportUsingCmd :: FilePath -> [CommandParam] -> Transport
|
2016-06-02 20:34:52 +00:00
|
|
|
transportUsingCmd cmd params rr@(RemoteRepo r gc) url h@(TransportHandle (LocalRepo g) s) ichan ochan = do
|
2014-04-12 19:59:34 +00:00
|
|
|
-- enable ssh connection caching wherever inLocalRepo is called
|
2015-02-12 20:12:32 +00:00
|
|
|
g' <- liftAnnex h $ sshOptionsTo r gc g
|
2016-06-02 20:34:52 +00:00
|
|
|
let transporthandle = TransportHandle (LocalRepo g') s
|
2015-03-16 19:28:29 +00:00
|
|
|
transportUsingCmd' cmd params rr url transporthandle ichan ochan
|
2014-04-12 19:59:34 +00:00
|
|
|
|
2015-03-16 19:28:29 +00:00
|
|
|
transportUsingCmd' :: FilePath -> [CommandParam] -> Transport
|
Added remote.<name>.annex-push and remote.<name>.annex-pull
The former can be useful to make remotes that don't get fully synced with
local changes, which comes up in a lot of situations.
The latter was mostly added for symmetry, but could be useful (though less
likely to be).
Implementing `remote.<name>.annex-pull` was a bit tricky, as there's no one
place where git-annex pulls/fetches from remotes. I audited all
instances of "fetch" and "pull". A few cases were left not checking this
config:
* Git.Repair can try to pull missing refs from a remote, and if the local
repo is corrupted, that seems a reasonable thing to do even though
the config would normally prevent it.
* Assistant.WebApp.Gpg and Remote.Gcrypt and Remote.Git do fetches
as part of the setup process of a remote. The config would probably not
be set then, and having the setup fail seems worse than honoring it if it
is already set.
I have not prevented all the code that does a "merge" from merging branches
from remotes with remote.<name>.annex-pull=false. That could perhaps
be done, but it would need a way to map from branch name to remote name,
and the way refspecs work makes that hard to get really correct. So if the
user fetches manually, the git-annex branch will get merged, for example.
Anther way of looking at/justifying this is that the setting is called
"annex-pull", not "annex-merge".
This commit was supported by the NSF-funded DataLad project.
2017-04-05 17:04:02 +00:00
|
|
|
transportUsingCmd' cmd params (RemoteRepo r gc) url transporthandle ichan ochan =
|
2016-12-09 20:02:43 +00:00
|
|
|
robustConnection 1 $ do
|
2014-04-09 18:10:29 +00:00
|
|
|
(Just toh, Just fromh, Just errh, pid) <-
|
2015-03-16 19:28:29 +00:00
|
|
|
createProcess (proc cmd (toCommand params))
|
2014-04-06 23:06:03 +00:00
|
|
|
{ std_in = CreatePipe
|
|
|
|
, std_out = CreatePipe
|
2014-04-09 18:10:29 +00:00
|
|
|
, std_err = CreatePipe
|
2014-04-06 23:06:03 +00:00
|
|
|
}
|
|
|
|
|
2014-04-09 18:10:29 +00:00
|
|
|
-- Run all threads until one finishes and get the status
|
|
|
|
-- of the first to finish. Cancel the rest.
|
|
|
|
status <- catchDefaultIO (Right ConnectionClosed) $
|
|
|
|
handlestderr errh
|
|
|
|
`race` handlestdout fromh
|
|
|
|
`race` handlecontrol
|
2014-04-06 23:06:03 +00:00
|
|
|
|
2014-04-09 18:10:29 +00:00
|
|
|
send (DISCONNECTED url)
|
|
|
|
hClose toh
|
|
|
|
hClose fromh
|
|
|
|
void $ waitForProcess pid
|
2014-04-06 23:06:03 +00:00
|
|
|
|
2014-04-09 18:10:29 +00:00
|
|
|
return $ either (either id id) id status
|
2015-03-16 19:28:29 +00:00
|
|
|
where
|
2015-01-15 19:37:48 +00:00
|
|
|
send msg = atomically $ writeTChan ochan msg
|
2014-04-08 17:41:36 +00:00
|
|
|
|
|
|
|
fetch = do
|
2014-04-09 18:10:29 +00:00
|
|
|
send (SYNCING url)
|
2014-04-08 17:41:36 +00:00
|
|
|
ok <- inLocalRepo transporthandle $
|
2014-04-09 18:10:29 +00:00
|
|
|
runBool [Param "fetch", Param $ Git.repoDescribe r]
|
|
|
|
send (DONESYNCING url ok)
|
|
|
|
|
|
|
|
handlestdout fromh = do
|
2016-12-09 17:34:00 +00:00
|
|
|
ml <- getProtocolLine fromh
|
|
|
|
case parseMessage =<< ml of
|
2014-04-09 18:10:29 +00:00
|
|
|
Just SshRemote.READY -> do
|
|
|
|
send (CONNECTED url)
|
|
|
|
handlestdout fromh
|
2016-12-09 18:52:38 +00:00
|
|
|
Just (SshRemote.CHANGED (ChangedRefs shas)) -> do
|
Added remote.<name>.annex-push and remote.<name>.annex-pull
The former can be useful to make remotes that don't get fully synced with
local changes, which comes up in a lot of situations.
The latter was mostly added for symmetry, but could be useful (though less
likely to be).
Implementing `remote.<name>.annex-pull` was a bit tricky, as there's no one
place where git-annex pulls/fetches from remotes. I audited all
instances of "fetch" and "pull". A few cases were left not checking this
config:
* Git.Repair can try to pull missing refs from a remote, and if the local
repo is corrupted, that seems a reasonable thing to do even though
the config would normally prevent it.
* Assistant.WebApp.Gpg and Remote.Gcrypt and Remote.Git do fetches
as part of the setup process of a remote. The config would probably not
be set then, and having the setup fail seems worse than honoring it if it
is already set.
I have not prevented all the code that does a "merge" from merging branches
from remotes with remote.<name>.annex-pull=false. That could perhaps
be done, but it would need a way to map from branch name to remote name,
and the way refspecs work makes that hard to get really correct. So if the
user fetches manually, the git-annex branch will get merged, for example.
Anther way of looking at/justifying this is that the setting is called
"annex-pull", not "annex-merge".
This commit was supported by the NSF-funded DataLad project.
2017-04-05 17:04:02 +00:00
|
|
|
whenM (checkShouldFetch gc transporthandle shas) $
|
2014-04-09 18:10:29 +00:00
|
|
|
fetch
|
|
|
|
handlestdout fromh
|
|
|
|
-- avoid reconnect on protocol error
|
2016-12-09 20:02:43 +00:00
|
|
|
Nothing -> return ConnectionStopping
|
2014-04-09 18:10:29 +00:00
|
|
|
|
|
|
|
handlecontrol = do
|
2015-01-15 19:37:48 +00:00
|
|
|
msg <- atomically $ readTChan ichan
|
2014-04-09 18:10:29 +00:00
|
|
|
case msg of
|
2016-12-09 20:02:43 +00:00
|
|
|
STOP -> return ConnectionStopping
|
|
|
|
LOSTNET -> return ConnectionStopping
|
2014-04-09 18:10:29 +00:00
|
|
|
_ -> handlecontrol
|
|
|
|
|
|
|
|
-- Old versions of git-annex-shell that do not support
|
|
|
|
-- the notifychanges command will exit with a not very useful
|
|
|
|
-- error message. Detect that error, and avoid reconnecting.
|
|
|
|
-- Propigate all stderr.
|
|
|
|
handlestderr errh = do
|
|
|
|
s <- hGetSomeString errh 1024
|
|
|
|
hPutStr stderr s
|
|
|
|
hFlush stderr
|
|
|
|
if "git-annex-shell: git-shell failed" `isInfixOf` s
|
|
|
|
then do
|
|
|
|
send $ WARNING url $ unwords
|
|
|
|
[ "Remote", Git.repoDescribe r
|
|
|
|
, "needs its git-annex upgraded"
|
|
|
|
, "to 5.20140405 or newer"
|
|
|
|
]
|
2016-12-09 20:02:43 +00:00
|
|
|
return ConnectionStopping
|
2014-04-09 18:10:29 +00:00
|
|
|
else handlestderr errh
|