git-remote-annex: Display full url when using remote with the shorthand url

This commit is contained in:
Joey Hess 2024-05-24 17:15:31 -04:00
parent 04a256a0f8
commit 19418e81ee
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
7 changed files with 76 additions and 20 deletions

View file

@ -107,17 +107,23 @@ commonFieldParsers =
(FieldDesc "name for the special remote")
, optionalStringParser sameasNameField HiddenField
, optionalStringParser sameasUUIDField HiddenField
, optionalStringParser typeField
(FieldDesc "type of special remote")
, autoEnableFieldParser
, costParser costField
(FieldDesc "default cost of this special remote")
, optionalStringParser preferreddirField
(FieldDesc "directory whose content is preferred")
] ++ essentialFieldParsers
{- Parsers for fields that are common to all special remotes, and are
- also essential to include in eg, annex:: urls. -}
essentialFieldParsers :: [RemoteConfigFieldParser]
essentialFieldParsers =
[ optionalStringParser typeField
(FieldDesc "type of special remote")
, yesNoParser exportTreeField (Just False)
(FieldDesc "export trees of files to this remote")
, yesNoParser importTreeField (Just False)
(FieldDesc "import trees of files from this remote")
, optionalStringParser preferreddirField
(FieldDesc "directory whose content is preferred")
]
autoEnableFieldParser :: RemoteConfigFieldParser

View file

@ -22,10 +22,12 @@ import qualified Git.Remote
import qualified Git.Remote.Remove
import qualified Git.Version
import qualified Annex.SpecialRemote as SpecialRemote
import qualified Annex.SpecialRemote.Config as SpecialRemote
import qualified Annex.Branch
import qualified Annex.BranchState
import qualified Types.Remote as Remote
import qualified Logs.Remote
import qualified Remote.External
import Remote.Helper.Encryptable (parseEncryptionMethod)
import Annex.Transfer
import Backend.GitRemoteAnnex
@ -72,17 +74,18 @@ run (remotename:url:[]) =
Right src -> do
repo <- getRepo
state <- Annex.new repo
Annex.eval state (run' src)
Annex.eval state (run' src url')
run (_remotename:[]) = giveup "remote url not configured"
run _ = giveup "expected remote name and url parameters"
run' :: SpecialRemoteConfig -> Annex ()
run' src = do
run' :: SpecialRemoteConfig -> String -> Annex ()
run' src url = do
sab <- startAnnexBranch
-- Prevent any usual git-annex output to stdout, because
-- the output of this command is being parsed by git.
doQuietAction $
withSpecialRemote src sab $ \rmt -> do
reportFullUrl url rmt
ls <- lines <$> liftIO getContents
go rmt ls emptyState
where
@ -463,6 +466,50 @@ parseSpecialRemoteUrl url remotename = case parseURI url of
let (k, sv) = break (== '=') kv
v = if null sv then sv else drop 1 sv
in (Proposed (unEscapeString k), Proposed (unEscapeString v))
getSpecialRemoteUrl :: Remote -> Annex (Maybe String)
getSpecialRemoteUrl rmt = do
rcp <- Remote.configParser (Remote.remotetype rmt)
(unparsedRemoteConfig (Remote.config rmt))
return $ genSpecialRemoteUrl rmt rcp
genSpecialRemoteUrl :: Remote -> RemoteConfigParser -> Maybe String
genSpecialRemoteUrl rmt rcp
-- Fields that are accepted by remoteConfigRestPassthrough
-- are not necessary to include in the url, except perhaps for
-- external special remotes. If an external special remote sets
-- some such fields, cannot generate an url.
| Remote.typename (Remote.remotetype rmt) == Remote.typename Remote.External.remote
&& any (`notElem` knownfields) (M.keys c) = Nothing
| otherwise = Just $
"annex::" ++ fromUUID (Remote.uuid rmt) ++ "?" ++
intercalate "&" (map configpair cs)
where
configpair (k, v) = conv k ++ "=" ++ conv v
conv = escapeURIString isUnescapedInURIComponent
. fromProposedAccepted
cs = M.toList $ M.filterWithKey (\k _ -> k `elem` safefields) c
c = unparsedRemoteConfig $ Remote.config rmt
-- Hidden fields are used for internal stuff like ciphers
-- that should not be included in the url.
safefields = map parserForField $
filter (\p -> fieldDesc p /= HiddenField) ps
knownfields = map parserForField ps
ps = SpecialRemote.essentialFieldParsers
++ remoteConfigFieldParsers rcp
reportFullUrl :: String -> Remote -> Annex ()
reportFullUrl url rmt =
when (url == "annex::") $
getSpecialRemoteUrl rmt >>= \case
Nothing -> noop
Just fullurl ->
liftIO $ hPutStrLn stderr $
"Full remote url: " ++ fullurl
-- Runs an action with a Remote as specified by the SpecialRemoteConfig.
withSpecialRemote :: SpecialRemoteConfig -> StartAnnexBranch -> (Remote -> Annex a) -> Annex a

View file

@ -157,6 +157,7 @@ describeOtherParamsFor c t = do
( 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)
@ -171,6 +172,7 @@ describeOtherParamsFor c t = do
mkjson = mapMaybe $ \(p, fd, vd) ->
case fd of
HiddenField -> Nothing
DeprecatedField -> Nothing
FieldDesc d -> Just
( T.pack p
, M.fromList

View file

@ -58,7 +58,7 @@ noChunks _ = False
chunkConfigParsers :: [RemoteConfigFieldParser]
chunkConfigParsers =
[ optionalStringParser chunksizeField HiddenField -- deprecated
[ optionalStringParser chunksizeField DeprecatedField
, optionalStringParser chunkField
(FieldDesc "size of chunks (eg, 1MiB)")
]

View file

@ -51,6 +51,8 @@ data RemoteConfigFieldParser = RemoteConfigFieldParser
data FieldDesc
= FieldDesc String
| HiddenField
| DeprecatedField
deriving (Eq)
newtype ValueDesc = ValueDesc String

View file

@ -20,8 +20,8 @@ For example, to clone from a directory special remote:
git clone annex::358ff77e-0bc3-11ef-bc49-872e6695c0e3?type=directory&encryption=none&directory=/mnt/foo/
When configuring the url of an existing special remote, a
shorter url of "annex::" is sufficient. For example:
But you don't need to generate such an url yourself. Instead, you can use
the shorthand url of "annex::" with an existing special remote.
git-annex initremote foo type=directory encryption=none directory=/mnt/foo
git config remote.foo.url annex::
@ -32,6 +32,10 @@ special remote. To make [[git-annex-initremote]](1) and
[[git-annex-enableremote]](1) configure the url, pass them the `--with-url`
option.
When using the shorthand "annex::" url, the full url will be displayed
each time you git pull or push, when it's possible for git-annex to
determine it.
When a special remote needs some additional credentials to be provided,
they are not included in the URL, and need to be provided when cloning from
the special remote. That is typically done by setting environment

View file

@ -10,20 +10,15 @@ will be available to users who don't use datalad.
This is implememented and working. Remaining todo list for it:
* When git clone is used with an annex:: url that is for a directory
special remote and is missing directory=, for example, it does
not display any useful error message. git fetch does, but it seems
git clone eats git-remote-annex stderr.
* Cloning from an annex:: url with importtree=yes doesn't work
(with or without exporttree=yes). This is because the ContentIdentifier
db is not populated. It should be possible to work around this.
* It would be nice if git-annex could generate an annex:: url
for a special remote and show it to the user, eg when
they have set the shorthand "annex::" url, so they know the full url.
`git-annex info $remote` could also display it.
Currently, the user has to remember how the special remote was
configured and replicate it all in the url.
There are some difficulties to doing this, including that
RemoteConfig can have hidden fields that should be omitted.
* datalad-annex supports cloning from the web special remote,
using an url that contains the result of pushing to eg, a directory
special remote.