OSDN Git Service

clone: tighten "local paths with colons" check a bit
authorNguyễn Thái Ngọc Duy <pclouds@gmail.com>
Fri, 27 Sep 2013 13:48:13 +0000 (20:48 +0700)
committerJonathan Nieder <jrnieder@gmail.com>
Fri, 27 Sep 2013 21:47:49 +0000 (14:47 -0700)
commit 6000334 (clone: allow cloning local paths with colons in them -
2013-05-04) made it possible to specify a path that has colons in it
without file://, e.g. ../foo:bar/somewhere. But the check was a bit
sloppy.

Consider the url '[foo]:bar'. The '[]' unwrapping code will turn the
string to 'foo\0:bar'. In effect this new string is the same as
'foo/:bar' in the check "path < strchrnul(host, '/')", which mistakes
it for a local path (with '/' before the first ':') when it's actually
not.

So disable the check for '/' before ':' when the URL has been mangled
by '[]' unwrapping.

[jn: with tests from Jeff King]

Noticed-by: Morten Stenshorne <mstensho@opera.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
connect.c
t/t5601-clone.sh

index 715a309..3c6300a 100644 (file)
--- a/connect.c
+++ b/connect.c
@@ -550,7 +550,7 @@ struct child_process *git_connect(int fd[2], const char *url_orig,
        path = strchr(end, c);
        if (path && !has_dos_drive_prefix(end)) {
                if (c == ':') {
-                       if (path < strchrnul(host, '/')) {
+                       if (host != url || path < strchrnul(host, '/')) {
                                protocol = PROTO_SSH;
                                *path++ = '\0';
                        } else /* '/' in the host part, assume local path */
index 0629149..a3e3d48 100755 (executable)
@@ -280,9 +280,53 @@ test_expect_success 'clone checking out a tag' '
        test_cmp fetch.expected fetch.actual
 '
 
+test_expect_success 'setup ssh wrapper' '
+       write_script "$TRASH_DIRECTORY/ssh-wrapper" <<-\EOF &&
+       echo >>"$TRASH_DIRECTORY/ssh-output" "ssh: $*" &&
+       # throw away all but the last argument, which should be the
+       # command
+       while test $# -gt 1; do shift; done
+       eval "$1"
+       EOF
+
+       GIT_SSH="$TRASH_DIRECTORY/ssh-wrapper" &&
+       export GIT_SSH &&
+       export TRASH_DIRECTORY
+'
+
+clear_ssh () {
+       >"$TRASH_DIRECTORY/ssh-output"
+}
+
+expect_ssh () {
+       {
+               case "$1" in
+               none)
+                       ;;
+               *)
+                       echo "ssh: $1 git-upload-pack '$2'"
+               esac
+       } >"$TRASH_DIRECTORY/ssh-expect" &&
+       (cd "$TRASH_DIRECTORY" && test_cmp ssh-expect ssh-output)
+}
+
+test_expect_success 'cloning myhost:src uses ssh' '
+       clear_ssh &&
+       git clone myhost:src ssh-clone &&
+       expect_ssh myhost src
+'
+
 test_expect_success NOT_MINGW,NOT_CYGWIN 'clone local path foo:bar' '
+       clear_ssh &&
        cp -R src "foo:bar" &&
-       git clone "./foo:bar" foobar
+       git clone "./foo:bar" foobar &&
+       expect_ssh none
+'
+
+test_expect_success 'bracketed hostnames are still ssh' '
+       clear_ssh &&
+       git clone "[myhost:123]:src" ssh-bracket-clone &&
+       expect_ssh myhost:123 src
 '
 
 test_done