From f4ba6e0c1e4eac8ab95bc9fc1449f1c51cf962b5 Mon Sep 17 00:00:00 2001 From: Joey Hess Date: Mon, 6 May 2024 14:50:41 -0400 Subject: [PATCH] add annex: url parser Changed the format of the url to use annex: rather than annex:: The reason is that in the future, might want to support an url that includes an uriAuthority part, eg: annex://foo@example.com:42/358ff77e-0bc3-11ef-bc49-872e6695c0e3?type=directory&encryption=none&directory=/mnt/foo/" To parse that foo@example.com:42 as an uriAuthority it needs to start with annex: rather than annex:: That would also need something to be done with uriAuthority, and also the uriPath (the UUID) is prefixed with "/" in that example. So the current parser won't handle that example currently. But this leaves the possibility for expansion. Sponsored-by: Joshua Antonishen on Patreon --- CmdLine/GitRemoteAnnex.hs | 36 +++++++++++++++++++++++++++++++++--- doc/git-remote-annex.mdwn | 10 +++++----- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/CmdLine/GitRemoteAnnex.hs b/CmdLine/GitRemoteAnnex.hs index 84ce91b1eb..2d3a506a3c 100644 --- a/CmdLine/GitRemoteAnnex.hs +++ b/CmdLine/GitRemoteAnnex.hs @@ -11,11 +11,14 @@ import Annex.Common import qualified Annex import qualified Git.CurrentRepo import Annex.UUID +import Network.URI run :: [String] -> IO () -run (_remotename:url:[]) = do - state <- Annex.new =<< Git.CurrentRepo.get - Annex.eval state (run' url) +run (_remotename:url:[]) = case parseSpecialRemoteUrl url of + Left e -> giveup e + Right src -> do + state <- Annex.new =<< Git.CurrentRepo.get + Annex.eval state (run' url) run (_remotename:[]) = giveup "remote url not configured" run _ = giveup "expected remote name and url parameters" @@ -109,3 +112,30 @@ splitLine l = let (c, sv) = break (== ' ') l v = if null sv then sv else drop 1 sv in (c, v) + +data SpecialRemoteConfig = SpecialRemoteConfig + { specialRemoteUUID :: UUID + , specialRemoteParams :: [(String, String)] + } + deriving (Show) + +-- The url for a special remote looks like +-- annex:uuid?param=value¶m=value... +parseSpecialRemoteUrl :: String -> Either String SpecialRemoteConfig +parseSpecialRemoteUrl s = case parseURI s of + Nothing -> Left "URL parse failed" + Just u -> case uriScheme u of + "annex:" -> case uriPath u of + "" -> Left "annex: URL did not include a UUID" + (':':_) -> Left "annex: URL malformed" + p -> Right $ SpecialRemoteConfig + { specialRemoteUUID = toUUID p + , specialRemoteParams = parsequery u + } + _ -> Left "Not an annex: URL" + where + parsequery u = map parsekv $ splitc '&' (drop 1 (uriQuery u)) + parsekv s = + let (k, sv) = break (== '=') s + v = if null sv then sv else drop 1 sv + in (unEscapeString k, unEscapeString v) diff --git a/doc/git-remote-annex.mdwn b/doc/git-remote-annex.mdwn index ab0f8a930e..74b946ebac 100644 --- a/doc/git-remote-annex.mdwn +++ b/doc/git-remote-annex.mdwn @@ -4,7 +4,7 @@ git-remote-annex - remote helper program to store a git repository in a git-anne # SYNOPSIS -git fetch annex::uuid?param=value¶m=value... +git fetch annex:uuid?param=value¶m=value... # DESCRIPTION @@ -17,13 +17,13 @@ encryption=shared or encryption=hybrid. (Since those types of encryption rely on a cipher that is checked into the git repository, cloning from such a special remote would present a chicken and egg problem.) -The format of the remote URL is "annex::" followed by the UUID of the +The format of the remote URL is "annex:" followed by the UUID of the special remote, and then followed by all of the configuration parameters of the special remote. For example, to clone from a directory special remote: - git clone annex::358ff77e-0bc3-11ef-bc49-872e6695c0e3?type=directory&encryption=none&directory=/mnt/foo/ + git clone annex:358ff77e-0bc3-11ef-bc49-872e6695c0e3?type=directory&encryption=none&directory=/mnt/foo/ 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 @@ -34,12 +34,12 @@ set when pulling or pushing. As a useful shorthand, when the special remote has already been enabled, the configuration parameters can be omitted. For example: - git push annex::358ff77e-0bc3-11ef-bc49-872e6695c0e3 master + git push annex:358ff77e-0bc3-11ef-bc49-872e6695c0e3 master This also makes it easy to configure the url for an existing special remote, making it usable by git: - git config remote.foo.url annex::358ff77e-0bc3-11ef-bc49-872e6695c0e3 + git config remote.foo.url annex:358ff77e-0bc3-11ef-bc49-872e6695c0e3 git fetch foo master Configuring the url like that is automatically done when cloning from a