Support git remotes that use a IPV6 link-local address with a zone ID
authorJoey Hess <joeyh@joeyh.name>
Wed, 2 Apr 2025 19:11:54 +0000 (15:11 -0400)
committerJoey Hess <joeyh@joeyh.name>
Wed, 2 Apr 2025 19:11:54 +0000 (15:11 -0400)
Fixed 3 problems, and it seems to work now for both forms:

ssh://[fe80::7697:xxx:xxxx:xxxx%wlp3s0]/foo
fe80::7697:xxx:xxxx:xxxx%wlp3s0:foo

Annex/Ssh.hs
CHANGELOG
Git/Remote.hs
Git/Url.hs
doc/bugs/IPv6_link-local_address_as_remote.mdwn

index 07519d03904bb702e51215de4c612db39dc00660..a0e4ff9319c18c39c443eda5b9dfb0a1f3c3f630 100644 (file)
@@ -351,10 +351,15 @@ hostport2socket host (Just port) = hostport2socket' $
        fromSshHost host ++ "!" ++ show port
 hostport2socket' :: String -> OsPath
 hostport2socket' s
-       | length s > lengthofmd5s = toOsPath $ show $ md5 $ encodeBL s
-       | otherwise = toOsPath s
+       | length s' > lengthofmd5s = toOsPath $ show $ md5 $ encodeBL s'
+       | otherwise = toOsPath s'
   where
        lengthofmd5s = 32
+       -- ssh parses the socket filename as a ControlPath, so it can
+       -- contain eg "%h". We don't want that here, and it's possible
+       -- for a hostname to itself contain a '%', eg a IPV6 link-local
+       -- address with a zone ID.
+       s' = filter (/= '%') s
 
 socket2lock :: OsPath -> OsPath
 socket2lock socket = socket <> lockExt
index aa6dc06ea82a886996fe21b9db23626865526974..d172c1b8976290aeb6fd45c754ff12bf52aa0621 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -11,6 +11,7 @@ git-annex (10.20250321) UNRELEASED; urgency=medium
     version of the annex.web-options config.
   * migrate: Fix --remove-size to work when a file is not present.
     Fixes reversion introduced in version 10.20231129.
+  * Support git remotes that use a IPV6 link-local address with a zone ID.
 
  -- Joey Hess <id@joeyh.name>  Fri, 21 Mar 2025 12:27:11 -0400
 
index eb4d78e88ded88387f57fd6f5e4079c9563b89d7..b0a31314ce02cd63b41b6c2f89dd103efffdc329 100644 (file)
@@ -103,9 +103,10 @@ parseRemoteLocation s knownurl repo = go
        urlstyle v = isURI (escapeURIString isUnescapedInURI v)
        -- git remotes can be written scp style -- [user@]host:dir
        -- but foo::bar is a git-remote-helper location instead
+       -- (although '::' can also be part of an IPV6 address)
        scpstyle v = ":" `isInfixOf` v 
                && not ("//" `isInfixOf` v)
-               && not ("::" `isInfixOf` v)
+               && not ("::" `isInfixOf` (takeWhile (/= '[') v))
        scptourl v = "ssh://" ++ host ++ slash dir
          where
                (host, dir)
index ad0e61b648d6c3d9be986f290c5a8b7e9ccbe724..af13f5839187260b2e1ef780ef08710f9bcef473 100644 (file)
@@ -36,9 +36,14 @@ uriRegName' a = fixup $ uriRegName a
                len  = length rest - 1
        fixup x = x
 
-{- Hostname of an URL repo. -}
+{- Hostname of an URL repo. 
+ -
+ - An IPV6 link-local address in an url can include a
+ - scope, eg "%wlan0". The "%" is necessarily URI-encoded
+ - as "%25" in the URI. So the hostname gets URI-decoded here.
+ -}
 host :: Repo -> Maybe String
-host = authpart uriRegName'
+host = authpart (unEscapeString . uriRegName')
 
 {- Port of an URL repo, if it has a nonstandard one. -}
 port :: Repo -> Maybe Integer
@@ -53,7 +58,7 @@ port r =
 hostuser :: Repo -> Maybe String
 hostuser r = (++)
        <$> authpart uriUserInfo r
-       <*> authpart uriRegName' r
+       <*> host r
 
 {- The full authority portion an URL repo. (ie, "user@host:port") -}
 authority :: Repo -> Maybe String
index d2c43ba221cc615d750863eec7fd9b31f92890ff..d56686d73f0e6f27d0959139c14ebb516c477702 100644 (file)
@@ -31,3 +31,5 @@ There is no problem with global IPv6 addresses, so it is likely that the percent
 ### Have you had any luck using git-annex before? (Sometimes we get tired of reading bug reports all day and a lil' positive end note does wonders)
 
 Yes, I have successfully used git-annex with a local remote (same computer), ssh over IPv4, and ssh to a globally visible IPv6 address.
+
+> [[fixed|done]] --[[Joey]]