support more standard rsync URIs
authorJoey Hess <id@joeyh.name>
Wed, 20 Jan 2021 15:23:01 +0000 (11:23 -0400)
committerSean Whitton <spwhitton@spwhitton.name>
Wed, 20 Jan 2021 20:25:58 +0000 (13:25 -0700)
This adds support for "rsync://user@host/path", which is a valid URI,
and will be parseable by URI parsers, unlike the old "rsync://user@host:path",
which at least some URI parsers will reject due to the ":path" looking
like an unparseable port number. The old nonstandard URI form is also
still accepted.

Note that, the path in the new URI form is not relative to the home
directory, but absolute. This is necessary because "/path" looks like an
absolute directory, and there needs to be a way to specify an absolute
directory. Something like "/~/path" could be added to specify the home
directory, but seems like an unncessary complication.

Note that rsync supports rsync:// URIs itself, but those communicate
with a rsync daemon on its own port, rather than via ssh. gcrypt already
was using rsync:// to denote rsync over ssh, and this does not change
that. So, the url has to be rewritten from "rsync://user@host/path"
to the rsync location "user@host:/path"

I used this test suite while developing the rather complicated sed
expression, to make sure I did not break handling of the old URI form.

set -e
test $(rsynclocation "rsync://host/path/foo") = host:/path/foo
test $(rsynclocation "rsync://host:path/foo") = host:path/foo
test $(rsynclocation "rsync://user@host/path/foo") = user@host:/path/foo
test $(rsynclocation "rsync://user@host:path/foo") = user@host:path/foo
test $(rsynclocation "rsync://user@host/path:foo") = user@host:/path:foo
test $(rsynclocation "rsync://user@host:path:foo") = user@host:path:foo
test $(rsynclocation "rsync://user@host/path:foo/bar") = user@host:/path:foo/bar
test $(rsynclocation "rsync://user@host:path:foo/bar") = user@host:path:foo/bar
test $(rsynclocation "rsync://user@host/path/foo/bar") = user@host:/path/foo/bar
test $(rsynclocation "rsync://user@host:path/foo/bar") = user@host:path/foo/bar

Signed-off-by: Joey Hess <id@joeyh.name>
README.rst
git-remote-gcrypt

index 097c05c47ee6cb1888fff3e1bcfa29f79ffd9dfc..a86d567c53eb4186b43a128c1310b0f780c50265 100644 (file)
@@ -40,7 +40,7 @@ Quickstart
 
 Create an encrypted remote by pushing to it::
 
-    git remote add cryptremote gcrypt::rsync://example.com:repo
+    git remote add cryptremote gcrypt::rsync://example.com/repo
     git push cryptremote master
     > gcrypt: Setting up new repository
     > gcrypt: Remote ID is :id:7VigUnLVYVtZx8oir34R
@@ -116,7 +116,7 @@ Examples
 
 How to set up a remote for two participants::
 
-    git remote add cryptremote gcrypt::rsync://example.com:repo
+    git remote add cryptremote gcrypt::rsync://example.com/repo
     git config remote.cryptremote.gcrypt-participants "KEY1 KEY2"
     git push cryptremote master
 
@@ -163,10 +163,12 @@ Performance
     repository hosting service like Gitolite, GitHub or GitLab.
 
 rsync URIs
-    Note that the URI format for the rsync backend is, regretably,
-    non-standard.  git-remote-gcrypt uses ``rsync://user@host:path``
-    whereas plain rsync uses either ``user@host:path`` or
-    ``rsync://user@host/path``.
+    The URI format for the rsync backend is ``rsync://user@host/path``,
+    which translates to the rsync location ``user@host:/path``,
+    accessed over ssh. Note that the path is absolute, not relative to the
+    home directory. An earlier non-standard URI format is also supported:
+    ``rsync://user@host:path``, which translates to the rsync location
+    ``user@host:path``
 
 rclone backend
     In addition to adding the rclone backend as a remote with URI like
index 5c15b609841b5d127c7b54a3d8a9268c1a086f32..c519bf855f441670d948678155ac2add8cf8ac52 100755 (executable)
@@ -149,6 +149,12 @@ line_count()
        xecho "$#"
 }
 
+# Convert URI in standard or nonstandard form to rsync's user@host:path
+rsynclocation ()
+{
+       echo "${1#rsync://}" | sed 's/\(^[^:/]*\)\//\1:\//'
+}
+
 
 ## gitception part
 # Fetch giturl $1, file $2
@@ -229,7 +235,7 @@ GET()
                (exec 0>&-; curl -s -S -k "$1/$2") > "$3"
        elif isurl rsync "$1"
        then
-               (exec 0>&-; rsync -I -W "${1#rsync://}"/"$2" "$3" >&2)
+               (exec 0>&-; rsync -I -W "$(rsynclocation "$1")"/"$2" "$3" >&2)
        elif isurl rclone "$1"
        then
                (exec 0>&-; rclone copyto "${1#rclone://}"/"$2" "$3" >&2)
@@ -249,7 +255,7 @@ PUT()
                curl -s -S -k --ftp-create-dirs -T "$3" "$1/$2"
        elif isurl rsync "$1"
        then
-               rsync $Conf_rsync_put_flags -I -W "$3" "${1#rsync://}"/"$2" >&2
+               rsync $Conf_rsync_put_flags -I -W "$3" "$(rsynclocation "$1")"/"$2" >&2
        elif isurl rclone "$1"
        then
                rclone copyto "$3" "${1#rclone://}"/"$2" >&2
@@ -281,7 +287,7 @@ PUTREPO()
        elif isurl rsync "$1"
        then
                rsync $Conf_rsync_put_flags -q -r --exclude='*' \
-                       "$Localdir/" "${1#rsync://}" >&2
+                       "$Localdir/" "$(rsynclocation "$1")" >&2
        elif isurl rclone "$1"
        then
                rclone mkdir "${1#rclone://}" >&2
@@ -304,7 +310,7 @@ REMOVE()
        elif isurl rsync "$1"
        then
                xfeed "$2" rsync -I -W -v -r --delete --include-from=- \
-                       --exclude='*' "$Localdir"/ "${1#rsync://}/" >&2
+                       --exclude='*' "$Localdir"/ "$(rsynclocation "$1")/" >&2
        elif isurl rclone "$1"
        then
                xfeed "$2" rclone delete -v --include-from=/dev/stdin "${1#rclone://}/" >&2