2012-09-11 01:55:59 +00:00
|
|
|
{- git-annex assistant remote creation utilities
|
|
|
|
-
|
2013-04-27 19:16:06 +00:00
|
|
|
- Copyright 2012, 2013 Joey Hess <joey@kitenet.net>
|
2012-09-11 01:55:59 +00:00
|
|
|
-
|
|
|
|
- Licensed under the GNU GPL version 3 or higher.
|
|
|
|
-}
|
|
|
|
|
|
|
|
module Assistant.MakeRemote where
|
|
|
|
|
|
|
|
import Assistant.Common
|
|
|
|
import Assistant.Ssh
|
|
|
|
import Assistant.Sync
|
|
|
|
import qualified Types.Remote as R
|
|
|
|
import qualified Remote
|
|
|
|
import Remote.List
|
|
|
|
import qualified Remote.Rsync as Rsync
|
|
|
|
import qualified Git
|
|
|
|
import qualified Git.Command
|
|
|
|
import qualified Command.InitRemote
|
|
|
|
import Logs.UUID
|
|
|
|
import Logs.Remote
|
2012-10-31 19:17:00 +00:00
|
|
|
import Git.Remote
|
2013-03-13 18:10:29 +00:00
|
|
|
import Config
|
2013-03-13 20:16:01 +00:00
|
|
|
import Config.Cost
|
2013-04-27 19:16:06 +00:00
|
|
|
import Creds
|
2012-09-11 01:55:59 +00:00
|
|
|
|
|
|
|
import qualified Data.Text as T
|
|
|
|
import qualified Data.Map as M
|
|
|
|
|
|
|
|
{- Sets up and begins syncing with a new ssh or rsync remote. -}
|
2013-03-13 20:16:01 +00:00
|
|
|
makeSshRemote :: Bool -> SshData -> Maybe Cost -> Assistant Remote
|
2013-03-13 18:10:29 +00:00
|
|
|
makeSshRemote forcersync sshdata mcost = do
|
2012-10-29 20:22:14 +00:00
|
|
|
r <- liftAnnex $
|
2012-09-11 01:55:59 +00:00
|
|
|
addRemote $ maker (sshRepoName sshdata) sshurl
|
2013-03-13 18:10:29 +00:00
|
|
|
liftAnnex $ maybe noop (setRemoteCost r) mcost
|
2013-04-08 19:36:09 +00:00
|
|
|
syncRemote r
|
2012-10-09 18:24:17 +00:00
|
|
|
return r
|
2012-10-31 06:34:03 +00:00
|
|
|
where
|
|
|
|
rsync = forcersync || rsyncOnly sshdata
|
|
|
|
maker
|
|
|
|
| rsync = makeRsyncRemote
|
|
|
|
| otherwise = makeGitRemote
|
|
|
|
sshurl = T.unpack $ T.concat $
|
|
|
|
if rsync
|
|
|
|
then [u, h, T.pack ":", sshDirectory sshdata, T.pack "/"]
|
|
|
|
else [T.pack "ssh://", u, h, d, T.pack "/"]
|
|
|
|
where
|
|
|
|
u = maybe (T.pack "") (\v -> T.concat [v, T.pack "@"]) $ sshUserName sshdata
|
|
|
|
h = sshHostName sshdata
|
|
|
|
d
|
2012-11-05 16:35:11 +00:00
|
|
|
| T.pack "/" `T.isPrefixOf` sshDirectory sshdata = sshDirectory sshdata
|
2012-10-31 06:34:03 +00:00
|
|
|
| otherwise = T.concat [T.pack "/~/", sshDirectory sshdata]
|
2012-09-11 01:55:59 +00:00
|
|
|
|
|
|
|
{- Runs an action that returns a name of the remote, and finishes adding it. -}
|
|
|
|
addRemote :: Annex String -> Annex Remote
|
|
|
|
addRemote a = do
|
|
|
|
name <- a
|
2012-09-13 04:57:52 +00:00
|
|
|
void remoteListRefresh
|
2013-03-05 19:39:42 +00:00
|
|
|
maybe (error "failed to add remote") return
|
|
|
|
=<< Remote.byName (Just name)
|
2012-09-11 01:55:59 +00:00
|
|
|
|
2012-09-26 18:44:07 +00:00
|
|
|
{- Inits a rsync special remote, and returns its name. -}
|
2012-09-11 01:55:59 +00:00
|
|
|
makeRsyncRemote :: String -> String -> Annex String
|
2012-09-26 18:44:07 +00:00
|
|
|
makeRsyncRemote name location = makeRemote name location $
|
2012-09-26 19:24:23 +00:00
|
|
|
const $ makeSpecialRemote name Rsync.remote config
|
2012-10-31 06:34:03 +00:00
|
|
|
where
|
|
|
|
config = M.fromList
|
|
|
|
[ ("encryption", "shared")
|
|
|
|
, ("rsyncurl", location)
|
|
|
|
, ("type", "rsync")
|
|
|
|
]
|
2012-09-11 01:55:59 +00:00
|
|
|
|
2013-04-26 22:22:44 +00:00
|
|
|
{- Inits a new special remote, or enables an existing one.
|
|
|
|
-
|
|
|
|
- Currently, only 'weak' ciphers can be generated from the assistant,
|
|
|
|
- because otherwise GnuPG may block once the entropy pool is drained,
|
|
|
|
- and as of now there's no way to tell the user to perform IO actions
|
|
|
|
- to refill the pool. -}
|
2012-09-26 19:24:23 +00:00
|
|
|
makeSpecialRemote :: String -> RemoteType -> R.RemoteConfig -> Annex ()
|
2013-04-26 22:22:44 +00:00
|
|
|
makeSpecialRemote name remotetype config =
|
|
|
|
go =<< Command.InitRemote.findExisting name
|
|
|
|
where
|
|
|
|
go Nothing = go =<< Just <$> Command.InitRemote.generateNew name
|
|
|
|
go (Just (u, c)) = do
|
|
|
|
c' <- R.setup remotetype u $
|
|
|
|
M.insert "highRandomQuality" "false" $ M.union config c
|
|
|
|
describeUUID u name
|
|
|
|
configSet u c'
|
2012-09-26 18:44:07 +00:00
|
|
|
|
2012-09-11 01:55:59 +00:00
|
|
|
{- Returns the name of the git remote it created. If there's already a
|
|
|
|
- remote at the location, returns its name. -}
|
|
|
|
makeGitRemote :: String -> String -> Annex String
|
|
|
|
makeGitRemote basename location = makeRemote basename location $ \name ->
|
2013-03-03 17:39:07 +00:00
|
|
|
void $ inRepo $ Git.Command.runBool
|
|
|
|
[Param "remote", Param "add", Param name, Param location]
|
2012-09-11 01:55:59 +00:00
|
|
|
|
|
|
|
{- If there's not already a remote at the location, adds it using the
|
|
|
|
- action, which is passed the name of the remote to make.
|
|
|
|
-
|
|
|
|
- Returns the name of the remote. -}
|
|
|
|
makeRemote :: String -> String -> (String -> Annex ()) -> Annex String
|
|
|
|
makeRemote basename location a = do
|
2012-10-12 05:17:45 +00:00
|
|
|
g <- gitRepo
|
|
|
|
if not (any samelocation $ Git.remotes g)
|
2012-09-11 01:55:59 +00:00
|
|
|
then do
|
2012-10-14 20:32:55 +00:00
|
|
|
|
2012-10-12 05:17:45 +00:00
|
|
|
let name = uniqueRemoteName basename 0 g
|
2012-09-11 01:55:59 +00:00
|
|
|
a name
|
|
|
|
return name
|
|
|
|
else return basename
|
2012-10-31 06:34:03 +00:00
|
|
|
where
|
|
|
|
samelocation x = Git.repoLocation x == location
|
2012-09-11 01:55:59 +00:00
|
|
|
|
|
|
|
{- Generate an unused name for a remote, adding a number if
|
2012-09-29 16:27:43 +00:00
|
|
|
- necessary.
|
|
|
|
-
|
|
|
|
- Ensures that the returned name is a legal git remote name. -}
|
2012-09-26 18:44:07 +00:00
|
|
|
uniqueRemoteName :: String -> Int -> Git.Repo -> String
|
|
|
|
uniqueRemoteName basename n r
|
2012-09-11 01:55:59 +00:00
|
|
|
| null namecollision = name
|
2012-09-29 16:27:43 +00:00
|
|
|
| otherwise = uniqueRemoteName legalbasename (succ n) r
|
2012-10-31 06:34:03 +00:00
|
|
|
where
|
|
|
|
namecollision = filter samename (Git.remotes r)
|
|
|
|
samename x = Git.remoteName x == Just name
|
|
|
|
name
|
|
|
|
| n == 0 = legalbasename
|
|
|
|
| otherwise = legalbasename ++ show n
|
2012-10-31 19:17:00 +00:00
|
|
|
legalbasename = makeLegalName basename
|
2013-04-27 19:16:06 +00:00
|
|
|
|
|
|
|
{- Finds a CredPair belonging to any Remote that is of a given type
|
|
|
|
- and matches some other criteria.
|
|
|
|
-
|
|
|
|
- This can be used as a default when another repository is being set up
|
|
|
|
- using the same service.
|
|
|
|
-
|
|
|
|
- A function must be provided that returns the CredPairStorage
|
|
|
|
- to use for a particular Remote's uuid.
|
|
|
|
-}
|
|
|
|
previouslyUsedCredPair
|
|
|
|
:: (UUID -> CredPairStorage)
|
|
|
|
-> RemoteType
|
|
|
|
-> (Remote -> Bool)
|
|
|
|
-> Annex (Maybe CredPair)
|
|
|
|
previouslyUsedCredPair getstorage remotetype criteria =
|
|
|
|
getM fromstorage =<< filter criteria . filter sametype <$> remoteList
|
|
|
|
where
|
|
|
|
sametype r = R.typename (R.remotetype r) == R.typename remotetype
|
|
|
|
fromstorage r = do
|
|
|
|
let storage = getstorage (R.uuid r)
|
|
|
|
getRemoteCredPair (R.config r) storage
|