Re: [PATCH/RFC] git clone: is an URL local or ssh

2013-10-27 Thread Eric Sunshine
On Saturday, October 26, 2013, Torsten Bögershausen wrote:
> diff --git a/connect.c b/connect.c
> index 06e88b0..903063e 100644
> --- a/connect.c
> +++ b/connect.c
> @@ -564,9 +574,9 @@ struct child_process *git_connect(int fd[2], const char 
> *url_orig,
> char *url;
> char *host, *path;
> char *end;
> -   int c;
> +   int seperator;

s/seperator/separator/g

> struct child_process *conn = &no_fork;
> -   enum protocol protocol = PROTO_LOCAL;
> +   enum protocol protocol = PROTO_LOCAL_OR_SSH;
> int free_path = 0;
> char *port = NULL;
> const char **arg;
> diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh
> index 1d1c875..69af007 100755
> --- a/t/t5601-clone.sh
> +++ b/t/t5601-clone.sh
> @@ -294,39 +294,93 @@ test_expect_success 'setup ssh wrapper' '
> export TRASH_DIRECTORY
>  '
>
> -clear_ssh () {
> -   >"$TRASH_DIRECTORY/ssh-output"
> -}
> -
> -expect_ssh () {
> +i6501=0

Is this variable meant to be named after the test script t5601? If so:
s/i6501/i5601/g

> +# $1 url
> +# $2 none|host
> +# $3 path
> +test_clone_url () {
> +   i6501=$(($i6501 + 1))
> +   >"$TRASH_DIRECTORY/ssh-output" &&
> +   test_might_fail git clone "$1" tmp$i6501 &&
> {
> -   case "$1" in
> +   case "$2" in
> none)
> ;;
> *)
> -   echo "ssh: $1 git-upload-pack '$2'"
> +   echo "ssh: $2 git-upload-pack '$3'"
> esac
> } >"$TRASH_DIRECTORY/ssh-expect" &&
> -   (cd "$TRASH_DIRECTORY" && test_cmp ssh-expect ssh-output)
> +   (cd "$TRASH_DIRECTORY" && test_cmp ssh-expect ssh-output) && {
> +   rm -rf ssh-expect ssh-output
> +   }

Should the 'rm' be inside the (cd...) subshell? If not, are the braces
wrapping 'rm' needed, and wouldn't you want to prefix the paths with
$TRASH_DIRECTORY/?

>  }
>
> -test_expect_success 'cloning myhost:src uses ssh' '
> -   clear_ssh &&
> -   git clone myhost:src ssh-clone &&
> -   expect_ssh myhost src
> -'
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH/RFC] git clone: is an URL local or ssh

2013-10-26 Thread Torsten Bögershausen
Commit 8d3d28f5 added test cases for URLs which should be ssh.

Add more tests testing all the combinations:
 -IPv4 or IPv6
 -path starting with "/" or with "/~"
 -with and without the ssh:// scheme

Add tests for ssh:// with port number.

When a git repository "foo:bar" exist, git clone will call
absolute_path() and git_connect() will be called with
something like "/home/user/projects/foo:bar"

Tighten the test and use "foo:bar" instead of "./foo:bar",
refactor clear_ssh() and expect_ssh() into test_clone_url().

"git clone foo/bar:baz" should not be ssh:
  Make the rule
  "if there is a slash before the first colon, it is not ssh"
  more strict by using the same is_local() in both connect.c
  and transport.c. Add a test case.

Bug fixes for corner cases:
- Handle clone of [::1]:/~repo correctly (2e7766655):
  Git should call "ssh ::1 ~repo", not ssh ::1 /~repo
  This was caused by looking at (host != url), which never
  worked for host names with literal IPv6 adresses, embedded by []
  Support for the [] URLs was introduced in 356bece0a.

- Do not tamper local URLs starting with '[' which have a ']'

Signed-off-by: Torsten Bögershausen 
---
(This does apply on pu, not on master.
 I'm almost sure there are more corner cases, but the
 most important things should be covered)

 connect.c| 47 +--
 connect.h|  1 +
 t/t5601-clone.sh | 96 +++-
 transport.c  |  8 -
 4 files changed, 106 insertions(+), 46 deletions(-)

diff --git a/connect.c b/connect.c
index 06e88b0..903063e 100644
--- a/connect.c
+++ b/connect.c
@@ -231,6 +231,7 @@ int server_supports(const char *feature)
 }
 
 enum protocol {
+   PROTO_LOCAL_OR_SSH = 0,
PROTO_LOCAL = 1,
PROTO_SSH,
PROTO_GIT
@@ -547,6 +548,15 @@ static char *get_port(char *host)
 
 static struct child_process no_fork;
 
+int is_local(const char *url)
+{
+   const char *colon = strchr(url, ':');
+   const char *slash = strchr(url, '/');
+   return !colon || (slash && slash < colon) ||
+   has_dos_drive_prefix(url);
+}
+
+
 /*
  * This returns a dummy child_process if the transport protocol does not
  * need fork(2), or a struct child_process object if it does.  Once done,
@@ -564,9 +574,9 @@ struct child_process *git_connect(int fd[2], const char 
*url_orig,
char *url;
char *host, *path;
char *end;
-   int c;
+   int seperator;
struct child_process *conn = &no_fork;
-   enum protocol protocol = PROTO_LOCAL;
+   enum protocol protocol = PROTO_LOCAL_OR_SSH;
int free_path = 0;
char *port = NULL;
const char **arg;
@@ -587,20 +597,23 @@ struct child_process *git_connect(int fd[2], const char 
*url_orig,
*host = '\0';
protocol = get_protocol(url);
host += 3;
-   c = '/';
+   seperator = '/';
} else {
host = url;
-   c = ':';
+   seperator = ':';
+   if (is_local(url))
+   protocol = PROTO_LOCAL;
}
 
/*
 * Don't do destructive transforms with git:// as that
 * protocol code does '[]' unwrapping of its own.
+* Don't change local URLs
 */
if (host[0] == '[') {
end = strchr(host + 1, ']');
if (end) {
-   if (protocol != PROTO_GIT) {
+   if (protocol != PROTO_GIT && protocol != PROTO_LOCAL) {
*end = 0;
host++;
}
@@ -610,17 +623,17 @@ struct child_process *git_connect(int fd[2], const char 
*url_orig,
} else
end = host;
 
-   path = strchr(end, c);
-   if (path && !has_dos_drive_prefix(end)) {
-   if (c == ':') {
-   if (host != url || path < strchrnul(host, '/')) {
-   protocol = PROTO_SSH;
-   *path++ = '\0';
-   } else /* '/' in the host part, assume local path */
-   path = end;
+   path = strchr(end, seperator);
+   if (seperator == ':') {
+   if (path && protocol == PROTO_LOCAL_OR_SSH) {
+   /* We have a ':' */
+   protocol = PROTO_SSH;
+   *path++ = '\0';
+   } else {/* assume local path */
+   protocol = PROTO_LOCAL;
+   path = end;
}
-   } else
-   path = end;
+   }
 
if (!path || !*path)
die("No path specified. See 'man git-pull' for valid url 
syntax");
@@ -629,7 +642,7 @@ struct child_process *git_connect(int fd[2], const char 
*url_orig,
 * null-terminate hostname and point path to ~ for URL's like this:
 *ssh://host.xz/~use