sync: Fix parsing of gcrypt::rsync:// urls that use a relative path

Such an url is not valid; parseURI will fail on it. But git-annex doesn't
actually need to parse the url, because all it needs to do to support
syncing with it is know that it's not a local path, and use git pull and
push.

(Note that there is no good reason for the user to use such an url. An
absolute url is valid and I patched git-remote-gcrypt to support them
years ago. Still, users gonna do anything that tools allow, and
git-remote-gcrypt still supports them.)

Sponsored-by: Jack Hill on Patreon
This commit is contained in:
Joey Hess 2023-03-23 15:19:04 -04:00
parent 0e18bf029e
commit a0badc5069
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
12 changed files with 45 additions and 22 deletions

View file

@ -140,7 +140,7 @@ fromRemotes repo = catMaybes <$> mapM construct remotepairs
filterkeys f = filterconfig (\(k,_) -> f k)
remotepairs = filterkeys isRemoteUrlKey
construct (k,v) = remoteNamedFromKey k $
fromRemoteLocation (fromConfigValue v) repo
fromRemoteLocation (fromConfigValue v) False repo
{- Sets the name of a remote when constructing the Repo to represent it. -}
remoteNamed :: String -> IO Repo -> IO Repo
@ -156,9 +156,15 @@ remoteNamedFromKey k r = case remoteKeyToRemoteName k of
Just n -> Just <$> remoteNamed n r
{- Constructs a new Repo for one of a Repo's remotes using a given
- location (ie, an url). -}
fromRemoteLocation :: String -> Repo -> IO Repo
fromRemoteLocation s repo = gen $ parseRemoteLocation s repo
- location (ie, an url).
-
- knownurl can be true if the location is known to be an url. This allows
- urls that don't parse as urls to be used, returning UnparseableUrl.
- If knownurl is false, the location may still be an url, if it parses as
- one.
-}
fromRemoteLocation :: String -> Bool -> Repo -> IO Repo
fromRemoteLocation s knownurl repo = gen $ parseRemoteLocation s knownurl repo
where
gen (RemotePath p) = fromRemotePath p repo
gen (RemoteUrl u) = fromUrl u

View file

@ -55,7 +55,15 @@ encryptedRemote baserepo = go
-- allows them); need to de-escape any such
-- to get back the path to the repository.
l' = Network.URI.unEscapeString l
in fromRemoteLocation l' baserepo
-- gcrypt supports relative urls for rsync
-- like "rsync://host:relative/path"
-- but that does not parse as a valid url
-- (while the absolute urls it supports are
-- valid).
-- In order to support it, force treating it as
-- an url.
knownurl = "rsync://" `isPrefixOf` l'
in fromRemoteLocation l' knownurl baserepo
| otherwise = notencrypted
notencrypted = giveup "not a gcrypt encrypted repository"

View file

@ -63,7 +63,7 @@ makeLegalName s = case filter legal $ replace "/" "_" s of
legal c = isAlphaNum c
data RemoteLocation = RemoteUrl String | RemotePath FilePath
deriving (Eq)
deriving (Eq, Show)
remoteLocationIsUrl :: RemoteLocation -> Bool
remoteLocationIsUrl (RemoteUrl _) = True
@ -75,16 +75,18 @@ remoteLocationIsSshUrl _ = False
{- Determines if a given remote location is an url, or a local
- path. Takes the repository's insteadOf configuration into account. -}
parseRemoteLocation :: String -> Repo -> RemoteLocation
parseRemoteLocation s repo = ret $ calcloc s
parseRemoteLocation :: String -> Bool -> Repo -> RemoteLocation
parseRemoteLocation s knownurl repo = go
where
ret v
s' = calcloc s
go
#ifdef mingw32_HOST_OS
| dosstyle v = RemotePath (dospath v)
| dosstyle s' = RemotePath (dospath s')
#endif
| scpstyle v = RemoteUrl (scptourl v)
| urlstyle v = RemoteUrl v
| otherwise = RemotePath v
| scpstyle s' = RemoteUrl (scptourl s')
| urlstyle s' = RemoteUrl s'
| knownurl && s' == s = RemoteUrl s'
| otherwise = RemotePath s'
-- insteadof config can rewrite remote location
calcloc l
| null insteadofs = l