192 lines
5.4 KiB
Haskell
192 lines
5.4 KiB
Haskell
{- git-annex command
|
|
-
|
|
- Copyright 2011-2024 Joey Hess <id@joeyh.name>
|
|
-
|
|
- Licensed under the GNU AGPL version 3 or higher.
|
|
-}
|
|
|
|
{-# LANGUAGE OverloadedStrings #-}
|
|
|
|
module Command.InitRemote where
|
|
|
|
import Command
|
|
import Annex.SpecialRemote
|
|
import qualified Remote
|
|
import qualified Types.Remote as R
|
|
import Types.RemoteConfig
|
|
import Annex.UUID
|
|
import Logs.UUID
|
|
import Logs.Remote
|
|
import Types.GitConfig
|
|
import Types.ProposedAccepted
|
|
import Config
|
|
import Git.Config
|
|
import Git.Types
|
|
|
|
import qualified Data.Map as M
|
|
import qualified Data.Text as T
|
|
|
|
cmd :: Command
|
|
cmd = withAnnexOptions [jsonOptions] $
|
|
command "initremote" SectionSetup
|
|
"creates a special (non-git) remote"
|
|
(paramPair paramName $ paramOptional $ paramRepeating paramParamValue)
|
|
(seek <$$> optParser)
|
|
|
|
data InitRemoteOptions = InitRemoteOptions
|
|
{ cmdparams :: CmdParams
|
|
, sameas :: Maybe (DeferredParse UUID)
|
|
, withUrl :: Bool
|
|
, whatElse :: Bool
|
|
, privateRemote :: Bool
|
|
}
|
|
|
|
optParser :: CmdParamsDesc -> Parser InitRemoteOptions
|
|
optParser desc = InitRemoteOptions
|
|
<$> cmdParams desc
|
|
<*> optional parseSameasOption
|
|
<*> switch
|
|
( long "with-url"
|
|
<> short 'u'
|
|
<> help "configure remote with an annex:: url"
|
|
)
|
|
<*> switch
|
|
( long "whatelse"
|
|
<> short 'w'
|
|
<> help "describe other configuration parameters for a special remote"
|
|
)
|
|
<*> switch
|
|
( long "private"
|
|
<> help "keep special remote information out of git-annex branch"
|
|
)
|
|
|
|
parseSameasOption :: Parser (DeferredParse UUID)
|
|
parseSameasOption = parseUUIDOption <$> strOption
|
|
( long "sameas"
|
|
<> metavar (paramRemote `paramOr` paramDesc `paramOr` paramUUID)
|
|
<> help "new remote that accesses the same data"
|
|
<> completeRemotes
|
|
)
|
|
|
|
seek :: InitRemoteOptions -> CommandSeek
|
|
seek o = withWords (commandAction . (start o)) (cmdparams o)
|
|
|
|
start :: InitRemoteOptions -> [String] -> CommandStart
|
|
start _ [] = giveup "Specify a name for the remote."
|
|
start o (name:ws) = do
|
|
if whatElse o
|
|
then ifM jsonOutputEnabled
|
|
( starting "initremote" ai si $ prep $ \c t ->
|
|
describeOtherParamsFor c t
|
|
, startingCustomOutput (ActionItemOther Nothing) $ prep $ \c t ->
|
|
describeOtherParamsFor c t
|
|
)
|
|
else starting "initremote" ai si $ prep $ \c t ->
|
|
perform t name c o
|
|
where
|
|
prep a = do
|
|
whenM (not . null <$> findExisting name) $
|
|
giveup $ "There is already a special remote named \"" ++ name ++
|
|
"\". (Use enableremote to enable an existing special remote.)"
|
|
whenM (isJust <$> Remote.byNameOnly name) $
|
|
giveup $ "There is already a remote named \"" ++ name ++ "\""
|
|
sameasuuid <- maybe
|
|
(pure Nothing)
|
|
(Just . Sameas <$$> getParsed)
|
|
(sameas o)
|
|
c <- newConfig name sameasuuid
|
|
(Logs.Remote.keyValToConfig Proposed ws)
|
|
<$> remoteConfigMap
|
|
t <- either giveup return (findType c)
|
|
a c t
|
|
|
|
si = SeekInput (name:ws)
|
|
ai = ActionItemOther (Just (UnquotedString name))
|
|
|
|
perform :: RemoteType -> String -> R.RemoteConfig -> InitRemoteOptions -> CommandPerform
|
|
perform t name c o = do
|
|
when (privateRemote o) $
|
|
setConfig (remoteAnnexConfig c "private") (boolConfig True)
|
|
dummycfg <- liftIO dummyRemoteGitConfig
|
|
let c' = M.delete uuidField c
|
|
(c'', u) <- R.setup t R.Init (sameasu <|> uuidfromuser) Nothing c' dummycfg
|
|
next $ cleanup t u name c'' o
|
|
where
|
|
uuidfromuser = case fromProposedAccepted <$> M.lookup uuidField c of
|
|
Just s
|
|
| isUUID s -> Just (toUUID s)
|
|
| otherwise -> giveup "invalid uuid"
|
|
Nothing -> Nothing
|
|
sameasu = toUUID . fromProposedAccepted <$> M.lookup sameasUUIDField c
|
|
|
|
uuidField :: R.RemoteConfigField
|
|
uuidField = Accepted "uuid"
|
|
|
|
cleanup :: RemoteType -> UUID -> String -> R.RemoteConfig -> InitRemoteOptions -> CommandCleanup
|
|
cleanup t u name c o = do
|
|
case sameas o of
|
|
Nothing -> do
|
|
describeUUID u (toUUIDDesc name)
|
|
Logs.Remote.configSet u c
|
|
Just _ -> do
|
|
cu <- liftIO genUUID
|
|
setConfig (remoteAnnexConfig c "config-uuid") (fromUUID cu)
|
|
Logs.Remote.configSet cu c
|
|
when (withUrl o) $
|
|
setAnnexUrl c
|
|
unless (Remote.gitSyncableRemoteType t || withUrl o) $
|
|
setConfig (remoteConfig c "skipFetchAll") (boolConfig True)
|
|
return True
|
|
|
|
setAnnexUrl :: R.RemoteConfig -> Annex ()
|
|
setAnnexUrl c =
|
|
getConfigMaybe (remoteConfig c "url") >>= \case
|
|
Just (ConfigValue _) -> noop
|
|
_ -> do
|
|
setConfig (remoteConfig c "url") "annex::"
|
|
setConfig (remoteConfig c "fetch") $
|
|
"+refs/heads/*:refs/remotes/" ++
|
|
getRemoteName c ++ "/*"
|
|
|
|
describeOtherParamsFor :: RemoteConfig -> RemoteType -> CommandPerform
|
|
describeOtherParamsFor c t = do
|
|
cp <- R.configParser t c
|
|
let l = map mk (filter notinconfig $ remoteConfigFieldParsers cp)
|
|
++ map mk' (maybe [] snd (remoteConfigRestPassthrough cp))
|
|
ifM jsonOutputEnabled
|
|
( maybeAddJSONField "whatelse" $ M.fromList $ mkjson l
|
|
, liftIO $ forM_ l $ \(p, fd, vd) -> case fd of
|
|
HiddenField -> return ()
|
|
DeprecatedField -> return ()
|
|
FieldDesc d -> do
|
|
putStrLn p
|
|
putStrLn ("\t" ++ d)
|
|
case vd of
|
|
Nothing -> return ()
|
|
Just (ValueDesc d') ->
|
|
putStrLn $ "\t(" ++ d' ++ ")"
|
|
|
|
)
|
|
next $ return True
|
|
where
|
|
mkjson = mapMaybe $ \(p, fd, vd) ->
|
|
case fd of
|
|
HiddenField -> Nothing
|
|
DeprecatedField -> Nothing
|
|
FieldDesc d -> Just
|
|
( T.pack p
|
|
, M.fromList
|
|
[ ("description" :: T.Text, d)
|
|
, ("valuedescription", case vd of
|
|
Nothing -> ""
|
|
Just (ValueDesc d') -> d')
|
|
]
|
|
)
|
|
|
|
notinconfig fp = not (M.member (parserForField fp) c)
|
|
|
|
mk fp = ( fromProposedAccepted (parserForField fp)
|
|
, fieldDesc fp
|
|
, valueDesc fp
|
|
)
|
|
mk' (k, v) = (k, v, Nothing)
|