Git development
 help / color / mirror / Atom feed
* [PATCH 2/3] Set a couple more tags in the original repository.
From: Michael Haggerty @ 2009-12-04 14:36 UTC (permalink / raw)
  To: git; +Cc: gitster, Johannes.Schindelin, Michael Haggerty
In-Reply-To: <cover.1259934977.git.mhagger@alum.mit.edu>


Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
 t/t3404-rebase-interactive.sh |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index 073674f..236d698 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -23,7 +23,7 @@ set_fake_editor
 #         I             (branch2)
 #
 # where B, D and G touch the same file.  In addition, set tags at
-# points A, F, and I.
+# points A, E, F, H, and I.
 
 test_expect_success 'setup' '
 	: > file1 &&
@@ -45,6 +45,7 @@ test_expect_success 'setup' '
 	git add file3 &&
 	test_tick &&
 	git commit -m E &&
+	git tag E &&
 	git checkout -b branch1 A &&
 	: > file4 &&
 	git add file4 &&
@@ -58,6 +59,7 @@ test_expect_success 'setup' '
 	git add file5 &&
 	test_tick &&
 	git commit -m H &&
+	git tag H &&
 	git checkout -b branch2 F &&
 	: > file6 &&
 	git add file6 &&
-- 
1.6.5.4

^ permalink raw reply related

* Re: [PATCH 1/3] Better document the original repository layout.
From: Michael J Gruber @ 2009-12-04 14:52 UTC (permalink / raw)
  To: Michael Haggerty; +Cc: git, gitster, Johannes.Schindelin
In-Reply-To: <91462ec5e4409e558ec5158b7dea33ebf0081d3e.1259934977.git.mhagger@alum.mit.edu>

Michael Haggerty venit, vidit, dixit 04.12.2009 15:36:
> Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
> ---
>  t/t3404-rebase-interactive.sh |    9 +++++----
>  1 files changed, 5 insertions(+), 4 deletions(-)
> 
> diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
> index 3a37793..073674f 100755
> --- a/t/t3404-rebase-interactive.sh
> +++ b/t/t3404-rebase-interactive.sh
> @@ -16,13 +16,14 @@ set_fake_editor
>  
>  # set up two branches like this:
>  #
> -# A - B - C - D - E
> +# A - B - C - D - E     (master)
>  #   \
> -#     F - G - H
> +#     F - G - H         (branch1)
>  #       \
> -#         I
> +#         I             (branch2)
>  #
> -# where B, D and G touch the same file.
> +# where B, D and G touch the same file.  In addition, set tags at
> +# points A, F, and I.
>  
>  test_expect_success 'setup' '
>  	: > file1 &&

My first reaction to the subject was "Huh? What repository?". So I
suggest something like

t3404: Better document the original repository layout

as a more descriptive subject.

Michael

^ permalink raw reply

* Re: [PATCH 0/3] Add a "fix" command to "rebase --interactive"
From: Michael J Gruber @ 2009-12-04 15:13 UTC (permalink / raw)
  To: Michael Haggerty; +Cc: git, gitster, Johannes.Schindelin
In-Reply-To: <cover.1259934977.git.mhagger@alum.mit.edu>

Michael Haggerty venit, vidit, dixit 04.12.2009 15:36:
> This patch series adds "fix" to the commands that can be used within
> the "rebase --interactive" patch editor.  "fix" is like "squash"
> except that it discards the log message of the corresponding commit.
> 
> Why I would like this feature:
> 
> One of my favorite aliases is
> 
>     fix = commit --amend -C HEAD
> 
> which I use in those all-too-frequent head-slapping "I just committed
> something with a minor typo" moments.  It amends the last commit with
> whatever is staged, reusing the same commit message.  It can also be
> used with the "-a" option, a list of filenames, etc.
> 
> But sometimes I don't have my head-slapping moments until a few
> commits later.  In this case, my usual practice is to commit the
> trivial typo change on top of the current branch, then "rebase
> --interactive" to move the typo fix on top of the erroneous commit and
> squash it:
> 
> pick 05d3b81 Commit with typo
> pick c29114a Good commit 1
> pick 250b013 Good commit 2
> pick 5eb3299 Fix for typo
> 
>         |
>         V
> 
> pick 05d3b81 Commit with typo
> squash 5eb3299 Fix for typo
> pick c29114a Good commit 1
> pick 250b013 Good commit 2
> 
> But then it is necessary to go into the commit message editor, move
> the cursor down past the first commit message, delete the "Fix for
> typo" commit message, save, and quit.
> 
> This patch implements a "fix" command, similar to "squash", except
> that the corresponding log message is not included in the log message
> suggested for the combined commit.  (In fact, it includes the log
> message, but commented out.)  It therefore saves the editor chores.
> 
> "fix" and "squash" can be used in the same group, in which case the
> "squash" commit messages are preserved and the "fix" commit messages
> are skipped.
> 
> If the idea of a "fix" command is acceptable, then I would like to
> implement a further convenience: if a group of commits to be folded
> together includes *only* "fix" commits, then the first log message
> should be used without even opening an editor.  But I would like to
> get a reaction to the "fix" command in general before doing so.

I'd say that would make a useful command ("fix") even more useful, being
just the right counterpart to "reword" for trivial commit message fixes.

OTOH, it would not be possible any more to squash in a few fixes and
then edit the message. Maybe having to quit the editor is not that much
work after all.

As a bike-shedding side note: So far, all commands are verbs which
describe actions to take on that commit. In that sense a "fix deadbeef"
would be confusing: You don't fix deadbeef, you fix the predecessor
using deadbeef.

A bit of brainstorming (suck/use/smash/apply/join) does not convince me
of any of my alternatives, but maybe they convince someone else :)

Michael

P.S.: I thought there's some heavy rb-i rewrite in progress (sequencer
based or not?), but you cc'ed Dscho anyway who knows best.

> Michael Haggerty (3):
>   Better document the original repository layout.
>   Set a couple more tags in the original repository.
>   Add a command "fix" to rebase --interactive.
> 
>  Documentation/git-rebase.txt  |   13 ++++++++-----
>  git-rebase--interactive.sh    |   39 +++++++++++++++++++++++++++++----------
>  t/lib-rebase.sh               |    7 ++++---
>  t/t3404-rebase-interactive.sh |   41 +++++++++++++++++++++++++++++++++++++----
>  4 files changed, 78 insertions(+), 22 deletions(-)
> 

^ permalink raw reply

* rev-parse --show-cdup in .git
From: Michael J Gruber @ 2009-12-04 15:45 UTC (permalink / raw)
  To: Git Mailing List

I'm sure this was discussed somewhere, but I can't find it:

When called from within .git, git rev-parse --show-cdup returns nothing
rather than "..", not even an error code. Is this intended?

This is all the more disturbing since the cwd of hooks seems to be
GIT_DIR. Is that something one can rely upon? In that case one can
simply use ".." for cdup.

Michael

P.S.: The use case is a simple post-receive-hook that fast forwards a
checked out branch on receiving refs in refs/remotes/incoming/, but
needs to check the worktree against the index etc. 1.7.0 may be an
opportunity to encourage usage of this rather than restoring the old
behavior through options.

^ permalink raw reply

* Re: [PATCH 0/3] Add a "fix" command to "rebase --interactive"
From: Shawn O. Pearce @ 2009-12-04 15:50 UTC (permalink / raw)
  To: Michael Haggerty; +Cc: git, gitster, Johannes.Schindelin
In-Reply-To: <cover.1259934977.git.mhagger@alum.mit.edu>

Michael Haggerty <mhagger@alum.mit.edu> wrote:
> This patch series adds "fix" to the commands that can be used within
> the "rebase --interactive" patch editor.  "fix" is like "squash"
> except that it discards the log message of the corresponding commit.
...
> But sometimes I don't have my head-slapping moments until a few
> commits later.  In this case, my usual practice is to commit the
> trivial typo change on top of the current branch, then "rebase
> --interactive" to move the typo fix on top of the erroneous commit and
> squash it:
...
> pick 05d3b81 Commit with typo
> squash 5eb3299 Fix for typo
> pick c29114a Good commit 1
> pick 250b013 Good commit 2

+1 for fix.  Totally.

When developing I *often* have not just 1 to squash, but 10 or so
in a single rebase -i session, all with useless commit messages like
"a", "s", or "foo".  Given that I also have a commit-msg hook which
injects additional lines into each of those messages, squash can be
annoying to use...

fix would be really cool.  To be honest, its my most common use
of squash... to use the first commit's message, but combine in the
misc. idiot fixes I've collected since I wrote that commit.

-- 
Shawn.

^ permalink raw reply

* [RFC PATCH v2 0/8] Remote helpers smart transport extensions
From: Ilari Liusvaara @ 2009-12-04 15:55 UTC (permalink / raw)
  To: git
In-Reply-To: <1259942168-24869-1-git-send-email-ilari.liusvaara@elisanet.fi>

This series is reroll of previous version of smart transport extensions,
with various technical nits addressed and some errors fixed. Also rebased
on top of latest next.

Major changes:
- Service names now have 'git-' prefix.
- Successful response to <connect> is "", not "OK".
- Removed <connect> "ERROR" response.
- <connect-r> renamed to <connect>.
- <invoke-r> removed. Pass service executable as option "servpath" instead.
- HTTP helpers are now hardlinked if possible (copied if not).
- Revert the changes to way helpers are invoked.[1]
- Actually test that all intermediate states compile.

[1] The current way seems to have all sorts of funky failure cases, but
I'm not touching it without fixing it properly.

Known issues (not caused by this code and does not need this code to be
visible):
- Segfaults when closing transports, caused by double-frees
- Funky error message if trying to use not-present helper.

Ilari Liusvaara (8):
  Pass unknown protocols to external protocol handlers
  Refactor git transport options parsing
  Support taking over transports
  Support remote helpers implementing smart transports
  Support remote archive from external protocol helpers
  Remove special casing of http, https and ftp
  Add remote helper debug mode
  Support mandatory capabilities

 .gitignore                           |    4 +
 Documentation/git-remote-helpers.txt |   33 ++++-
 Makefile                             |   24 +++-
 builtin-archive.c                    |   17 ++-
 transport-helper.c                   |  257 +++++++++++++++++++++++++++++-----
 transport.c                          |  258 +++++++++++++++++++++++++++------
 transport.h                          |   32 ++++
 7 files changed, 533 insertions(+), 92 deletions(-)

^ permalink raw reply

* [RFC PATCH v2 0/8] Remote helpers smart transport extensions
From: Ilari Liusvaara @ 2009-12-04 15:55 UTC (permalink / raw)
  To: git

This series is reroll of previous version of smart transport extensions,
with various technical nits addressed and some errors fixed. Also rebased
on top of latest next.

Major changes:
- Service names now have 'git-' prefix.
- Successful response to <connect> is "", not "OK".
- Removed <connect> "ERROR" response.
- <connect-r> renamed to <connect>.
- <invoke-r> removed. Pass service executable as option "servpath" instead.
- HTTP helpers are now hardlinked if possible (copied if not).
- Revert the changes to way helpers are invoked.[1]
- Actually test the intermediate states for gross errors.

[1] The current way seems to have all sorts of funky failure cases, but
I'm not touching it without fixing it properly.

Known issues (not caused by this code and does not need this code to be
visible):
- Segfaults when closing transports, caused by double-frees
- Funky error message if trying to use not-present helper.

Ilari Liusvaara (8):
  Pass unknown protocols to external protocol handlers
  Refactor git transport options parsing
  Support taking over transports
  Support remote helpers implementing smart transports
  Support remote archive from external protocol helpers
  Remove special casing of http, https and ftp
  Add remote helper debug mode
  Support mandatory capabilities

 .gitignore                           |    4 +
 Documentation/git-remote-helpers.txt |   33 ++++-
 Makefile                             |   24 +++-
 builtin-archive.c                    |   17 ++-
 transport-helper.c                   |  258 +++++++++++++++++++++++++++++-----
 transport.c                          |  258 +++++++++++++++++++++++++++------
 transport.h                          |   32 ++++
 7 files changed, 534 insertions(+), 92 deletions(-)

^ permalink raw reply

* [RFC PATCH v2 0/8] Remote helpers smart transport extensions
From: Ilari Liusvaara @ 2009-12-04 15:56 UTC (permalink / raw)
  To: git
In-Reply-To: <1259942168-24869-1-git-send-email-ilari.liusvaara@elisanet.fi>

This series is reroll of previous version of smart transport extensions,
with various technical nits addressed and some errors fixed. Also rebased
on top of latest next.

Major changes:
- Service names now have 'git-' prefix.
- Successful response to <connect> is "", not "OK".
- Removed <connect> "ERROR" response.
- <connect-r> renamed to <connect>.
- <invoke-r> removed. Pass service executable as option "servpath" instead.
- HTTP helpers are now hardlinked if possible (copied if not).
- Revert the changes to invoking helpers (see known issues)


Known issues (not caused by this code and does not need this code to be
visible):
- Segfaults when closing transports, caused by double-frees
- Funky error message if trying to use not-present helper.


Ilari Liusvaara (8):
  Pass unknown protocols to external protocol handlers
  Refactor git transport options parsing
  Support taking over transports
  Support remote helpers implementing smart transports
  Support remote archive from external protocol helpers
  Remove special casing of http, https and ftp
  Add remote helper debug mode
  Support mandatory capabilities

 .gitignore                           |    4 +
 Documentation/git-remote-helpers.txt |   36 +++++-
 Makefile                             |   24 +++-
 builtin-archive.c                    |   17 ++-
 transport-helper.c                   |  261 +++++++++++++++++++++++++++++-----
 transport.c                          |  258 +++++++++++++++++++++++++++------
 transport.h                          |   32 ++++
 7 files changed, 540 insertions(+), 92 deletions(-)

^ permalink raw reply

* [RFC PATCH v2 1/8] Pass unknown protocols to external protocol handlers
From: Ilari Liusvaara @ 2009-12-04 15:56 UTC (permalink / raw)
  To: git
In-Reply-To: <1259942168-24869-1-git-send-email-ilari.liusvaara@elisanet.fi>

Change URL handling to allow external protocol handlers to implement
new protocols without the '::' syntax if helper name does not conflict
with any built-in protocol.

foo:// now invokes git-remote-foo with foo:// URL.

Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
---
 transport-helper.c |   37 ++++++++++++++++++++++-
 transport.c        |   82 +++++++++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 106 insertions(+), 13 deletions(-)

diff --git a/transport-helper.c b/transport-helper.c
index 11f3d7e..d3aad5c 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -22,6 +22,26 @@ struct helper_data
 	int refspec_nr;
 };
 
+const char* remove_ext_force(const char* url)
+{
+	const char* url2 = url;
+	const char* first_colon = NULL;
+
+	if(!url)
+		return NULL;
+
+	while(*url2 && !first_colon)
+		if(*url2 == ':')
+			first_colon = url2;
+		else
+			url2++;
+
+	if(first_colon && first_colon[1] == ':')
+		return first_colon + 2;
+	else
+		return url;
+}
+
 static struct child_process *get_helper(struct transport *transport)
 {
 	struct helper_data *data = transport->data;
@@ -30,6 +50,7 @@ static struct child_process *get_helper(struct transport *transport)
 	const char **refspecs = NULL;
 	int refspec_nr = 0;
 	int refspec_alloc = 0;
+	int duped;
 
 	if (data->helper)
 		return data->helper;
@@ -42,15 +63,26 @@ static struct child_process *get_helper(struct transport *transport)
 	strbuf_addf(&buf, "remote-%s", data->name);
 	helper->argv[0] = strbuf_detach(&buf, NULL);
 	helper->argv[1] = transport->remote->name;
-	helper->argv[2] = transport->url;
+	helper->argv[2] = remove_ext_force(transport->url);
 	helper->git_cmd = 1;
 	if (start_command(helper))
 		die("Unable to run helper: git %s", helper->argv[0]);
 	data->helper = helper;
 
+	/* Open the output as FILE* so strbuf_getline() can be used.
+	   Do this with duped fd because fclose() will close the fd,
+	   and stuff like disowning will require the fd to remain.
+
+	   Set the stream to unbuffered because some reads are critical
+	   in sense that any overreading will cause deadlocks.
+	*/
+	if((duped = dup(helper->out)) < 0)
+		die_errno("Can't dup helper output fd");
+	data->out = xfdopen(duped, "r");
+	setvbuf(data->out, NULL, _IONBF, 0);
+
 	write_str_in_full(helper->in, "capabilities\n");
 
-	data->out = xfdopen(helper->out, "r");
 	while (1) {
 		if (strbuf_getline(&buf, data->out, '\n') == EOF)
 			exit(128); /* child died, message supplied already */
@@ -91,6 +123,7 @@ static int disconnect_helper(struct transport *transport)
 	if (data->helper) {
 		write_str_in_full(data->helper->in, "\n");
 		close(data->helper->in);
+		close(data->helper->out);
 		fclose(data->out);
 		finish_command(data->helper);
 		free((char *)data->helper->argv[0]);
diff --git a/transport.c b/transport.c
index 3eea836..162d022 100644
--- a/transport.c
+++ b/transport.c
@@ -780,6 +780,55 @@ static int is_file(const char *url)
 	return S_ISREG(buf.st_mode);
 }
 
+static const char* strchrc(const char* str, int c)
+{
+	while(*str)
+		if(*str == c)
+			return str;
+		else
+			str++;
+	return NULL;
+}
+
+static int is_url(const char* url)
+{
+	if(!url)
+		return 0;
+
+	const char* url2 = url;
+	const char* first_slash = strchrc(url, '/');
+
+	/* Input with no slash at all or slash first can't be URL. */
+	if(!first_slash || first_slash == url)
+		return 0;
+	/* Character before must be : and next must be /. */
+	if(first_slash[-1] != ':' || first_slash[1] != '/')
+		return 0;
+	/* There must be something before the :// */
+	if(first_slash == url + 1)
+		return 0;
+	/* Check all characters up to first slash. Only alpha, num and
+	   : are allowed. : must be followed by : or / */
+	url2 = url;
+	while(url2 < first_slash) {
+		if(*url2 != ':' && !isalnum((unsigned char)*url2))
+			return 0;
+		if(*url2 == ':' && url2[1] != ':' && url2[1] != '/')
+			return 0;
+		if(*url2 == ':')
+			url2++;		/* Skip second : */
+		url2++;
+	}
+
+	/* Valid enough. */
+	return 1;
+}
+
+static int external_specification_len(const char* url)
+{
+	return strchrc(url, ':') - url;
+}
+
 struct transport *transport_get(struct remote *remote, const char *url)
 {
 	struct transport *ret = xcalloc(1, sizeof(*ret));
@@ -812,23 +861,19 @@ struct transport *transport_get(struct remote *remote, const char *url)
 		ret->get_refs_list = get_refs_via_rsync;
 		ret->fetch = fetch_objs_via_rsync;
 		ret->push = rsync_transport_push;
-
-	} else if (!prefixcmp(url, "http://")
-	        || !prefixcmp(url, "https://")
-	        || !prefixcmp(url, "ftp://")) {
-		transport_helper_init(ret, "curl");
-#ifdef NO_CURL
-		error("git was compiled without libcurl support.");
-#endif
-
 	} else if (is_local(url) && is_file(url)) {
 		struct bundle_transport_data *data = xcalloc(1, sizeof(*data));
 		ret->data = data;
 		ret->get_refs_list = get_refs_from_bundle;
 		ret->fetch = fetch_refs_from_bundle;
 		ret->disconnect = close_bundle;
-
-	} else {
+	} else if(!is_url(url)
+		|| !prefixcmp(url, "file://")
+		|| !prefixcmp(url, "git://")
+		|| !prefixcmp(url, "ssh://")
+		|| !prefixcmp(url, "git+ssh://")
+		|| !prefixcmp(url, "ssh+git://")) {
+		/* These are builtin smart transports. */
 		struct git_transport_data *data = xcalloc(1, sizeof(*data));
 		ret->data = data;
 		ret->set_option = set_git_option;
@@ -845,6 +890,21 @@ struct transport *transport_get(struct remote *remote, const char *url)
 		data->receivepack = "git-receive-pack";
 		if (remote->receivepack)
 			data->receivepack = remote->receivepack;
+	} else if (!prefixcmp(url, "http://")
+		|| !prefixcmp(url, "https://")
+		|| !prefixcmp(url, "ftp://")) {
+		/* These three are just plain special. */
+		transport_helper_init(ret, "curl");
+#ifdef NO_CURL
+		error("git was compiled without libcurl support.");
+#endif
+	} else {
+		/* Unknown protocol in URL. Pass to external handler. */
+		int len = external_specification_len(url);
+		char* handler = xmalloc(len + 1);
+		handler[len] = 0;
+		strncpy(handler, url, len);
+		transport_helper_init(ret, handler);
 	}
 
 	return ret;
-- 
1.6.6.rc1.288.g40e67

^ permalink raw reply related

* [RFC PATCH v2 2/8] Refactor git transport options parsing
From: Ilari Liusvaara @ 2009-12-04 15:56 UTC (permalink / raw)
  To: git
In-Reply-To: <1259942168-24869-1-git-send-email-ilari.liusvaara@elisanet.fi>

Refactor the transport options parsing so that protocols that aren't
directly smart transports (file://, git://, ssh:// & co) can record
the smart transport options for the case if it turns that transport
can actually be smart.

Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
---
 transport.c |   78 +++++++++++++++++++++++++++++++++++-----------------------
 transport.h |   12 +++++++++
 2 files changed, 59 insertions(+), 31 deletions(-)

diff --git a/transport.c b/transport.c
index 162d022..21310c5 100644
--- a/transport.c
+++ b/transport.c
@@ -395,41 +395,35 @@ static int close_bundle(struct transport *transport)
 }
 
 struct git_transport_data {
-	unsigned thin : 1;
-	unsigned keep : 1;
-	unsigned followtags : 1;
-	int depth;
+	struct git_transport_options options;
 	struct child_process *conn;
 	int fd[2];
-	const char *uploadpack;
-	const char *receivepack;
 	struct extra_have_objects extra_have;
 };
 
-static int set_git_option(struct transport *connection,
+static int set_git_option(struct git_transport_options *opts,
 			  const char *name, const char *value)
 {
-	struct git_transport_data *data = connection->data;
 	if (!strcmp(name, TRANS_OPT_UPLOADPACK)) {
-		data->uploadpack = value;
+		opts->uploadpack = value;
 		return 0;
 	} else if (!strcmp(name, TRANS_OPT_RECEIVEPACK)) {
-		data->receivepack = value;
+		opts->receivepack = value;
 		return 0;
 	} else if (!strcmp(name, TRANS_OPT_THIN)) {
-		data->thin = !!value;
+		opts->thin = !!value;
 		return 0;
 	} else if (!strcmp(name, TRANS_OPT_FOLLOWTAGS)) {
-		data->followtags = !!value;
+		opts->followtags = !!value;
 		return 0;
 	} else if (!strcmp(name, TRANS_OPT_KEEP)) {
-		data->keep = !!value;
+		opts->keep = !!value;
 		return 0;
 	} else if (!strcmp(name, TRANS_OPT_DEPTH)) {
 		if (!value)
-			data->depth = 0;
+			opts->depth = 0;
 		else
-			data->depth = atoi(value);
+			opts->depth = atoi(value);
 		return 0;
 	}
 	return 1;
@@ -439,7 +433,8 @@ static int connect_setup(struct transport *transport, int for_push, int verbose)
 {
 	struct git_transport_data *data = transport->data;
 	data->conn = git_connect(data->fd, transport->url,
-				 for_push ? data->receivepack : data->uploadpack,
+				 for_push ? data->options.receivepack :
+				 data->options.uploadpack,
 				 verbose ? CONNECT_VERBOSE : 0);
 	return 0;
 }
@@ -469,15 +464,15 @@ static int fetch_refs_via_pack(struct transport *transport,
 	struct ref *refs_tmp = NULL;
 
 	memset(&args, 0, sizeof(args));
-	args.uploadpack = data->uploadpack;
-	args.keep_pack = data->keep;
+	args.uploadpack = data->options.uploadpack;
+	args.keep_pack = data->options.keep;
 	args.lock_pack = 1;
-	args.use_thin_pack = data->thin;
-	args.include_tag = data->followtags;
+	args.use_thin_pack = data->options.thin;
+	args.include_tag = data->options.followtags;
 	args.verbose = (transport->verbose > 0);
 	args.quiet = (transport->verbose < 0);
 	args.no_progress = args.quiet || (!transport->progress && !isatty(1));
-	args.depth = data->depth;
+	args.depth = data->options.depth;
 
 	for (i = 0; i < nr_heads; i++)
 		origh[i] = heads[i] = xstrdup(to_fetch[i]->name);
@@ -734,7 +729,7 @@ static int git_transport_push(struct transport *transport, struct ref *remote_re
 	memset(&args, 0, sizeof(args));
 	args.send_mirror = !!(flags & TRANSPORT_PUSH_MIRROR);
 	args.force_update = !!(flags & TRANSPORT_PUSH_FORCE);
-	args.use_thin_pack = data->thin;
+	args.use_thin_pack = data->options.thin;
 	args.verbose = !!(flags & TRANSPORT_PUSH_VERBOSE);
 	args.quiet = !!(flags & TRANSPORT_PUSH_QUIET);
 	args.dry_run = !!(flags & TRANSPORT_PUSH_DRY_RUN);
@@ -861,12 +856,14 @@ struct transport *transport_get(struct remote *remote, const char *url)
 		ret->get_refs_list = get_refs_via_rsync;
 		ret->fetch = fetch_objs_via_rsync;
 		ret->push = rsync_transport_push;
+		ret->smart_options = NULL;
 	} else if (is_local(url) && is_file(url)) {
 		struct bundle_transport_data *data = xcalloc(1, sizeof(*data));
 		ret->data = data;
 		ret->get_refs_list = get_refs_from_bundle;
 		ret->fetch = fetch_refs_from_bundle;
 		ret->disconnect = close_bundle;
+		ret->smart_options = NULL;
 	} else if(!is_url(url)
 		|| !prefixcmp(url, "file://")
 		|| !prefixcmp(url, "git://")
@@ -876,20 +873,14 @@ struct transport *transport_get(struct remote *remote, const char *url)
 		/* These are builtin smart transports. */
 		struct git_transport_data *data = xcalloc(1, sizeof(*data));
 		ret->data = data;
-		ret->set_option = set_git_option;
+		ret->set_option = NULL;
 		ret->get_refs_list = get_refs_via_connect;
 		ret->fetch = fetch_refs_via_pack;
 		ret->push_refs = git_transport_push;
 		ret->disconnect = disconnect_git;
+		ret->smart_options = &(data->options);
 
-		data->thin = 1;
 		data->conn = NULL;
-		data->uploadpack = "git-upload-pack";
-		if (remote->uploadpack)
-			data->uploadpack = remote->uploadpack;
-		data->receivepack = "git-receive-pack";
-		if (remote->receivepack)
-			data->receivepack = remote->receivepack;
 	} else if (!prefixcmp(url, "http://")
 		|| !prefixcmp(url, "https://")
 		|| !prefixcmp(url, "ftp://")) {
@@ -907,14 +898,39 @@ struct transport *transport_get(struct remote *remote, const char *url)
 		transport_helper_init(ret, handler);
 	}
 
+	if(ret->smart_options) {
+		ret->smart_options->thin = 1;
+		ret->smart_options->uploadpack = "git-upload-pack";
+		if (remote->uploadpack)
+			ret->smart_options->uploadpack = remote->uploadpack;
+		ret->smart_options->receivepack = "git-receive-pack";
+		if (remote->receivepack)
+			ret->smart_options->receivepack = remote->receivepack;
+	}
+
 	return ret;
 }
 
 int transport_set_option(struct transport *transport,
 			 const char *name, const char *value)
 {
+	int git_reports = 1, protocol_reports = 1;
+
+	if (transport->smart_options)
+		git_reports = set_git_option(transport->smart_options,
+					     name, value);
+
 	if (transport->set_option)
-		return transport->set_option(transport, name, value);
+		protocol_reports = transport->set_option(transport, name,
+							value);
+
+	/* If either report is 0, report 0 (success). */
+	if(!git_reports || !protocol_reports)
+		return 0;
+	/* If either reports -1 (invalid value), report -1. */
+	if((git_reports == -1) || (protocol_reports == -1))
+		return -1;
+	/* Otherwise if both report unknown, report unknown. */
 	return 1;
 }
 
diff --git a/transport.h b/transport.h
index 9e74406..5949132 100644
--- a/transport.h
+++ b/transport.h
@@ -4,6 +4,15 @@
 #include "cache.h"
 #include "remote.h"
 
+struct git_transport_options {
+	unsigned thin : 1;
+	unsigned keep : 1;
+	unsigned followtags : 1;
+	int depth;
+	const char *uploadpack;
+	const char *receivepack;
+};
+
 struct transport {
 	struct remote *remote;
 	const char *url;
@@ -65,6 +74,9 @@ struct transport {
 	signed verbose : 3;
 	/* Force progress even if the output is not a tty */
 	unsigned progress : 1;
+	/* If transport is at least potentially smart, this points to git_transport_options
+	   structure to use in case transport actually turns out to be smart. */
+	struct git_transport_options* smart_options;
 };
 
 #define TRANSPORT_PUSH_ALL 1
-- 
1.6.6.rc1.288.g40e67

^ permalink raw reply related

* [RFC PATCH v2 3/8] Support taking over transports
From: Ilari Liusvaara @ 2009-12-04 15:56 UTC (permalink / raw)
  To: git
In-Reply-To: <1259942168-24869-1-git-send-email-ilari.liusvaara@elisanet.fi>

Add support for taking over transports that turn out to be smart.

Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
---
 transport-helper.c |   12 +++++++
 transport.c        |   89 +++++++++++++++++++++++++++++++++++++++++++++++----
 transport.h        |   15 +++++++++
 3 files changed, 109 insertions(+), 7 deletions(-)

diff --git a/transport-helper.c b/transport-helper.c
index d3aad5c..5d17fb5 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -20,8 +20,18 @@ struct helper_data
 	/* These go from remote name (as in "list") to private name */
 	struct refspec *refspecs;
 	int refspec_nr;
+	struct git_transport_options gitoptions;
 };
 
+static struct child_process* helper_disown(struct transport *transport)
+{
+	struct helper_data *data = transport->data;
+	struct child_process *child = data->helper;
+	fclose(data->out);
+	free(data);
+	return child;
+}
+
 const char* remove_ext_force(const char* url)
 {
 	const char* url2 = url;
@@ -549,5 +559,7 @@ int transport_helper_init(struct transport *transport, const char *name)
 	transport->fetch = fetch;
 	transport->push_refs = push_refs;
 	transport->disconnect = release_helper;
+	transport->disown = helper_disown;
+	transport->smart_options = &(data->gitoptions);
 	return 0;
 }
diff --git a/transport.c b/transport.c
index 21310c5..7e6ef2b 100644
--- a/transport.c
+++ b/transport.c
@@ -9,6 +9,8 @@
 #include "dir.h"
 #include "refs.h"
 
+struct ref special_transport_layer6_ready;
+
 /* rsync support */
 
 /*
@@ -398,6 +400,8 @@ struct git_transport_data {
 	struct git_transport_options options;
 	struct child_process *conn;
 	int fd[2];
+	/* Connection is fully up. */
+	unsigned virtual_connected : 1;
 	struct extra_have_objects extra_have;
 };
 
@@ -432,10 +436,21 @@ static int set_git_option(struct git_transport_options *opts,
 static int connect_setup(struct transport *transport, int for_push, int verbose)
 {
 	struct git_transport_data *data = transport->data;
+
+	if(!data->virtual_connected && data->conn) {
+		/* Just mark it connected. */
+		data->virtual_connected = 1;
+		return 0;
+	}
+
 	data->conn = git_connect(data->fd, transport->url,
 				 for_push ? data->options.receivepack :
 				 data->options.uploadpack,
 				 verbose ? CONNECT_VERBOSE : 0);
+
+	if(data->conn)
+		data->virtual_connected = 1;
+
 	return 0;
 }
 
@@ -477,7 +492,7 @@ static int fetch_refs_via_pack(struct transport *transport,
 	for (i = 0; i < nr_heads; i++)
 		origh[i] = heads[i] = xstrdup(to_fetch[i]->name);
 
-	if (!data->conn) {
+	if (!data->virtual_connected) {
 		connect_setup(transport, 0, 0);
 		get_remote_heads(data->fd[0], &refs_tmp, 0, NULL, 0, NULL);
 	}
@@ -490,6 +505,7 @@ static int fetch_refs_via_pack(struct transport *transport,
 	if (finish_connect(data->conn))
 		refs = NULL;
 	data->conn = NULL;
+	data->virtual_connected = 0;
 
 	free_refs(refs_tmp);
 
@@ -718,7 +734,7 @@ static int git_transport_push(struct transport *transport, struct ref *remote_re
 	struct send_pack_args args;
 	int ret;
 
-	if (!data->conn) {
+	if (!data->virtual_connected) {
 		struct ref *tmp_refs;
 		connect_setup(transport, 1, 0);
 
@@ -741,6 +757,7 @@ static int git_transport_push(struct transport *transport, struct ref *remote_re
 	close(data->fd[0]);
 	ret |= finish_connect(data->conn);
 	data->conn = NULL;
+	data->virtual_connected = 0;
 
 	return ret;
 }
@@ -749,7 +766,8 @@ static int disconnect_git(struct transport *transport)
 {
 	struct git_transport_data *data = transport->data;
 	if (data->conn) {
-		packet_flush(data->fd[1]);
+		if(data->virtual_connected)
+			packet_flush(data->fd[1]);
 		close(data->fd[0]);
 		close(data->fd[1]);
 		finish_connect(data->conn);
@@ -759,6 +777,35 @@ static int disconnect_git(struct transport *transport)
 	return 0;
 }
 
+static void git_take_over_transport(struct transport *transport)
+{
+	struct git_transport_data *data;
+
+	if(!transport->disown)
+		die("Bug detected: Taking over transport requires non-NULL "
+		    "disown method.");
+	if(!transport->smart_options)
+		die("Bug detected: Taking over transport requires non-NULL "
+		    "smart_options field.");
+
+	data = xcalloc(1, sizeof(*data));
+	data->options = *transport->smart_options;
+	data->conn = transport->disown(transport);
+	data->fd[0] = data->conn->out;
+	data->fd[1] = data->conn->in;
+	data->virtual_connected = 0;
+	transport->data = data;
+
+	transport->set_option = NULL;
+	transport->get_refs_list = get_refs_via_connect;
+	transport->fetch = fetch_refs_via_pack;
+	transport->push = NULL;
+	transport->push_refs = git_transport_push;
+	transport->disconnect = disconnect_git;
+	transport->smart_options = &(data->options);
+	transport->disown = NULL;
+}
+
 static int is_local(const char *url)
 {
 	const char *colon = strchr(url, ':');
@@ -857,6 +904,7 @@ struct transport *transport_get(struct remote *remote, const char *url)
 		ret->fetch = fetch_objs_via_rsync;
 		ret->push = rsync_transport_push;
 		ret->smart_options = NULL;
+		ret->disown = NULL;
 	} else if (is_local(url) && is_file(url)) {
 		struct bundle_transport_data *data = xcalloc(1, sizeof(*data));
 		ret->data = data;
@@ -864,6 +912,7 @@ struct transport *transport_get(struct remote *remote, const char *url)
 		ret->fetch = fetch_refs_from_bundle;
 		ret->disconnect = close_bundle;
 		ret->smart_options = NULL;
+		ret->disown = NULL;
 	} else if(!is_url(url)
 		|| !prefixcmp(url, "file://")
 		|| !prefixcmp(url, "git://")
@@ -879,8 +928,10 @@ struct transport *transport_get(struct remote *remote, const char *url)
 		ret->push_refs = git_transport_push;
 		ret->disconnect = disconnect_git;
 		ret->smart_options = &(data->options);
+		ret->disown = NULL;
 
 		data->conn = NULL;
+		data->virtual_connected = 0;
 	} else if (!prefixcmp(url, "http://")
 		|| !prefixcmp(url, "https://")
 		|| !prefixcmp(url, "ftp://")) {
@@ -938,14 +989,25 @@ int transport_push(struct transport *transport,
 		   int refspec_nr, const char **refspec, int flags,
 		   int *nonfastforward)
 {
+	int rc = 0;
 	*nonfastforward = 0;
 	verify_remote_names(refspec_nr, refspec);
 
-	if (transport->push)
-		return transport->push(transport, refspec_nr, refspec, flags);
-	if (transport->push_refs) {
+retry:
+	if (transport->push) {
+		rc = transport->push(transport, refspec_nr, refspec, flags);
+		if(rc == TRANSPORT_LAYER6_READY) {
+			git_take_over_transport(transport);
+			goto retry;
+		}
+		return rc;
+	} else if (transport->push_refs) {
 		struct ref *remote_refs =
 			transport->get_refs_list(transport, 1);
+		if(remote_refs == &special_transport_layer6_ready) {
+			git_take_over_transport(transport);
+			goto retry;
+		}
 		struct ref *local_refs = get_local_heads();
 		int match_flags = MATCH_REFS_NONE;
 		int verbose = flags & TRANSPORT_PUSH_VERBOSE;
@@ -985,8 +1047,15 @@ int transport_push(struct transport *transport,
 
 const struct ref *transport_get_remote_refs(struct transport *transport)
 {
-	if (!transport->remote_refs)
+	if (!transport->remote_refs) {
+retry:
 		transport->remote_refs = transport->get_refs_list(transport, 0);
+		if(transport->remote_refs == &special_transport_layer6_ready) {
+			git_take_over_transport(transport);
+			goto retry;
+		}
+	}
+
 	return transport->remote_refs;
 }
 
@@ -1020,7 +1089,13 @@ int transport_fetch_refs(struct transport *transport, struct ref *refs)
 			heads[nr_heads++] = rm;
 	}
 
+retry:
 	rc = transport->fetch(transport, nr_heads, heads);
+	if(rc == TRANSPORT_LAYER6_READY) {
+		git_take_over_transport(transport);
+		goto retry;
+	}
+
 	free(heads);
 	return rc;
 }
diff --git a/transport.h b/transport.h
index 5949132..f3ee890 100644
--- a/transport.h
+++ b/transport.h
@@ -65,6 +65,15 @@ struct transport {
 	int (*push_refs)(struct transport *transport, struct ref *refs, int flags);
 	int (*push)(struct transport *connection, int refspec_nr, const char **refspec, int flags);
 
+	/**
+	 * Disown the transport helper. Releases all resources used
+	 * by field pointed by member data, except that the child
+	 * process is not released but returned and whatever is pointed
+	 * by smart transport options structure is not freed (but the
+	 * smart transport options structure itself is).
+	 **/
+	struct child_process* (*disown)(struct transport* connection);
+
 	/** get_refs_list(), fetch(), and push_refs() can keep
 	 * resources (such as a connection) reserved for futher
 	 * use. disconnect() releases these resources.
@@ -79,6 +88,12 @@ struct transport {
 	struct git_transport_options* smart_options;
 };
 
+/* Returned by get_refs_list, fetch or push methods of struct transport: Layer 6 is ready,
+   take over the transport and retry operation. */
+#define TRANSPORT_LAYER6_READY -42
+extern struct ref special_transport_layer6_ready;
+
+
 #define TRANSPORT_PUSH_ALL 1
 #define TRANSPORT_PUSH_FORCE 2
 #define TRANSPORT_PUSH_DRY_RUN 4
-- 
1.6.6.rc1.288.g40e67

^ permalink raw reply related

* [RFC PATCH v2 4/8] Support remote helpers implementing smart transports
From: Ilari Liusvaara @ 2009-12-04 15:56 UTC (permalink / raw)
  To: git
In-Reply-To: <1259942168-24869-1-git-send-email-ilari.liusvaara@elisanet.fi>

Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
---
 Documentation/git-remote-helpers.txt |   28 ++++++++++-
 transport-helper.c                   |   96 +++++++++++++++++++++++++++++++++-
 transport.c                          |   21 +++++++
 transport.h                          |    5 ++
 4 files changed, 147 insertions(+), 3 deletions(-)

diff --git a/Documentation/git-remote-helpers.txt b/Documentation/git-remote-helpers.txt
index 5cfdc0c..91cd9eb 100644
--- a/Documentation/git-remote-helpers.txt
+++ b/Documentation/git-remote-helpers.txt
@@ -90,6 +90,23 @@ Supported if the helper has the "push" capability.
 +
 Supported if the helper has the "import" capability.
 
+'connect' <service>::
+	Connects to given service. Stdin and stdout of helper are
+	connected to specified service (git prefix is included in service
+	name so e.g. fetching uses 'git-upload-pack' as service) on
+	remote side. Valid replies to this command are empty line
+	(connection established), 'FALLBACK' (no smart transport support,
+	fall back to dumb transports) and just exiting with error message
+	printed (can't connect, don't bother trying to fall back). After
+	line feed terminating the positive (empty) response, the output
+	of service starts. After the connection ends, the remote
+	helper exits. Note that to prevent deadlocking, all read data
+	should be immediately flushed to outgoing connection (excepting
+	remote initial advertisments, which should be flushed on first
+	flush packet (0000 as length) encountered.
++
+Supported if the helper has the "connect" capability.
+
 If a fatal error occurs, the program writes the error message to
 stderr and exits. The caller should expect that a suitable error
 message has been printed if the child closes the connection without
@@ -123,6 +140,9 @@ CAPABILITIES
 	all, it must cover all refs reported by the list command; if
 	it is not used, it is effectively "*:*"
 
+'connect'::
+	This helper supports the 'connect' command.
+
 REF LIST ATTRIBUTES
 -------------------
 
@@ -165,9 +185,15 @@ OPTIONS
 	but don't actually change any repository data.	For most
 	helpers this only applies to the 'push', if supported.
 
+'option servpath <c-style-quoted-path>'::
+	Set service path (--upload-pack, --receive-pack etc.) for
+	next connect. Remote helper MAY support this option. Remote
+	helper MUST NOT rely on this option being set before
+	connect request occurs.
+
 Documentation
 -------------
-Documentation by Daniel Barkalow.
+Documentation by Daniel Barkalow and Ilari Liusvaara
 
 GIT
 ---
diff --git a/transport-helper.c b/transport-helper.c
index 5d17fb5..21aa4ab 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -16,7 +16,8 @@ struct helper_data
 	unsigned fetch : 1,
 		import : 1,
 		option : 1,
-		push : 1;
+		push : 1,
+		connect : 1;
 	/* These go from remote name (as in "list") to private name */
 	struct refspec *refspecs;
 	int refspec_nr;
@@ -72,7 +73,10 @@ static struct child_process *get_helper(struct transport *transport)
 	helper->argv = xcalloc(4, sizeof(*helper->argv));
 	strbuf_addf(&buf, "remote-%s", data->name);
 	helper->argv[0] = strbuf_detach(&buf, NULL);
-	helper->argv[1] = transport->remote->name;
+	if(transport->remote)
+		helper->argv[1] = transport->remote->name;
+	else
+		helper->argv[1] = "";
 	helper->argv[2] = remove_ext_force(transport->url);
 	helper->git_cmd = 1;
 	if (start_command(helper))
@@ -113,6 +117,8 @@ static struct child_process *get_helper(struct transport *transport)
 				   refspec_alloc);
 			refspecs[refspec_nr++] = strdup(buf.buf + strlen("refspec "));
 		}
+		if (!strcmp(buf.buf, "connect"))
+			data->connect = 1;
 	}
 	if (refspecs) {
 		int i;
@@ -331,12 +337,91 @@ static int fetch_with_import(struct transport *transport,
 	return 0;
 }
 
+static int _process_connect(struct transport *transport,
+				      const char *name, const char *exec)
+{
+	struct helper_data *data = transport->data;
+	struct strbuf cmdbuf = STRBUF_INIT;
+	struct child_process *helper;
+	int r;
+
+	helper = get_helper(transport);
+
+	/* Handle --upload-pack and friends. This is fire and forget...
+	   just warn if it fails. */
+	if(exec && strcmp(name, exec)) {
+		r = set_helper_option(transport, "servpath", exec);
+		if(r > 0)
+			fprintf(stderr, "Warning: Setting remote service path "
+				"not supported by protocol.\n");
+		else if(r < 0)
+			fprintf(stderr, "Warning: Invalid remote service "
+				"path.\n");
+	}
+
+	if(data->connect) {
+		strbuf_addf(&cmdbuf, "connect %s\n", name);
+	} else
+		return 0;
+
+	write_in_full(helper->in, cmdbuf.buf, cmdbuf.len);
+	strbuf_reset(&cmdbuf);
+	if (strbuf_getline(&cmdbuf, data->out, '\n') == EOF)
+		exit(128); /* child died, message supplied already */
+	if(!strcmp(cmdbuf.buf, ""))
+		return 1;
+	else if(!strcmp(cmdbuf.buf, "FALLBACK"))
+		return 0;
+	else
+		die("Unknown response to connect: %s",
+			cmdbuf.buf);
+
+	return 0;	/* Shouldn't be here. */
+}
+
+static int process_connect(struct transport* transport,
+				     int for_push)
+{
+	struct helper_data *data = transport->data;
+	const char *name;
+	const char *exec;
+
+	name = for_push ? "git-receive-pack" : "git-upload-pack";
+	if(for_push)
+		exec = data->gitoptions.receivepack;
+	else
+		exec = data->gitoptions.uploadpack;
+
+	return _process_connect(transport, name, exec);
+}
+
+static int connect_helper(struct transport *transport, const char *name,
+		   const char *exec, int fd[2])
+{
+	struct helper_data *data = transport->data;
+
+	/* Get_helper so connect is inited. */
+	get_helper(transport);
+	if(!data->connect)
+		die("Operation not supported by protocol.");
+
+	if(!_process_connect(transport, name, exec))
+		die("Can't connect to subservice %s.", name);
+
+	fd[0] = data->helper->out;
+	fd[1] = data->helper->in;
+	return 0;
+}
+
 static int fetch(struct transport *transport,
 		 int nr_heads, struct ref **to_fetch)
 {
 	struct helper_data *data = transport->data;
 	int i, count;
 
+	if(process_connect(transport, 0))
+		return TRANSPORT_LAYER6_READY;
+
 	count = 0;
 	for (i = 0; i < nr_heads; i++)
 		if (!(to_fetch[i]->status & REF_STATUS_UPTODATE))
@@ -364,6 +449,9 @@ static int push_refs(struct transport *transport,
 	struct child_process *helper;
 	struct ref *ref;
 
+	if(process_connect(transport, 1))
+		return TRANSPORT_LAYER6_READY;
+
 	if (!remote_refs)
 		return 0;
 
@@ -507,6 +595,9 @@ static struct ref *get_refs_list(struct transport *transport, int for_push)
 
 	helper = get_helper(transport);
 
+	if(process_connect(transport, for_push))
+		return &special_transport_layer6_ready;
+
 	if (data->push && for_push)
 		write_str_in_full(helper->in, "list for-push\n");
 	else
@@ -559,6 +650,7 @@ int transport_helper_init(struct transport *transport, const char *name)
 	transport->fetch = fetch;
 	transport->push_refs = push_refs;
 	transport->disconnect = release_helper;
+	transport->connect = connect_helper;
 	transport->disown = helper_disown;
 	transport->smart_options = &(data->gitoptions);
 	return 0;
diff --git a/transport.c b/transport.c
index 7e6ef2b..1488cfe 100644
--- a/transport.c
+++ b/transport.c
@@ -762,6 +762,17 @@ static int git_transport_push(struct transport *transport, struct ref *remote_re
 	return ret;
 }
 
+static int connect_git(struct transport *transport, const char* name,
+		       const char* executable, int fd[2])
+{
+	struct git_transport_data *data = transport->data;
+	data->conn = git_connect(data->fd, transport->url,
+				 executable, 0);
+	fd[0] = data->fd[0];
+	fd[1] = data->fd[1];
+	return 0;
+}
+
 static int disconnect_git(struct transport *transport)
 {
 	struct git_transport_data *data = transport->data;
@@ -926,6 +937,7 @@ struct transport *transport_get(struct remote *remote, const char *url)
 		ret->get_refs_list = get_refs_via_connect;
 		ret->fetch = fetch_refs_via_pack;
 		ret->push_refs = git_transport_push;
+		ret->connect = connect_git;
 		ret->disconnect = disconnect_git;
 		ret->smart_options = &(data->options);
 		ret->disown = NULL;
@@ -1109,6 +1121,15 @@ void transport_unlock_pack(struct transport *transport)
 	}
 }
 
+int transport_connect(struct transport *transport, const char *name,
+		      const char* exec, int fd[2])
+{
+	if(transport->connect) {
+		return transport->connect(transport, name, exec, fd);
+	} else
+		die("Operation not supported by protocol");
+}
+
 int transport_disconnect(struct transport *transport)
 {
 	int ret = 0;
diff --git a/transport.h b/transport.h
index f3ee890..c86329a 100644
--- a/transport.h
+++ b/transport.h
@@ -64,6 +64,8 @@ struct transport {
 	 **/
 	int (*push_refs)(struct transport *transport, struct ref *refs, int flags);
 	int (*push)(struct transport *connection, int refspec_nr, const char **refspec, int flags);
+	int (*connect)(struct transport *connection, const char* name, const char* executable,
+		       int fd[2]);
 
 	/**
 	 * Disown the transport helper. Releases all resources used
@@ -143,6 +145,9 @@ void transport_unlock_pack(struct transport *transport);
 int transport_disconnect(struct transport *transport);
 char *transport_anonymize_url(const char *url);
 
+int transport_connect(struct transport *transport, const char *name,
+		      const char* exec, int fd[2]);
+
 /* Transport methods defined outside transport.c */
 int transport_helper_init(struct transport *transport, const char *name);
 
-- 
1.6.6.rc1.288.g40e67

^ permalink raw reply related

* [RFC PATCH v2 5/8] Support remote archive from external protocol helpers
From: Ilari Liusvaara @ 2009-12-04 15:56 UTC (permalink / raw)
  To: git
In-Reply-To: <1259942168-24869-1-git-send-email-ilari.liusvaara@elisanet.fi>

Helpers which support invoke/connect also should support remote archive
snapshot (or at least there's only one way to attempt it). So support
remote snapshotting for protocol helpers.

Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
---
 builtin-archive.c |   17 ++++++++++-------
 1 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/builtin-archive.c b/builtin-archive.c
index 12351e9..d34b3fd 100644
--- a/builtin-archive.c
+++ b/builtin-archive.c
@@ -5,6 +5,7 @@
 #include "cache.h"
 #include "builtin.h"
 #include "archive.h"
+#include "transport.h"
 #include "parse-options.h"
 #include "pkt-line.h"
 #include "sideband.h"
@@ -25,12 +26,16 @@ static void create_output_file(const char *output_file)
 static int run_remote_archiver(int argc, const char **argv,
 			       const char *remote, const char *exec)
 {
-	char *url, buf[LARGE_PACKET_MAX];
+	char buf[LARGE_PACKET_MAX];
 	int fd[2], i, len, rv;
-	struct child_process *conn;
+	struct transport *transport;
+	struct remote *_remote;
 
-	url = xstrdup(remote);
-	conn = git_connect(fd, url, exec, 0);
+	_remote = remote_get(remote);
+	if (!_remote->url[0])
+		die("git archive: Remote with no URL");
+	transport = transport_get(_remote, _remote->url[0]);
+	transport_connect(transport, "git-upload-archive", exec, fd);
 
 	for (i = 1; i < argc; i++)
 		packet_write(fd[1], "argument %s\n", argv[i]);
@@ -53,9 +58,7 @@ static int run_remote_archiver(int argc, const char **argv,
 
 	/* Now, start reading from fd[0] and spit it out to stdout */
 	rv = recv_sideband("archive", fd[0], 1);
-	close(fd[0]);
-	close(fd[1]);
-	rv |= finish_connect(conn);
+	rv |= transport_disconnect(transport);
 
 	return !!rv;
 }
-- 
1.6.6.rc1.288.g40e67

^ permalink raw reply related

* [RFC PATCH v2 6/8] Remove special casing of http, https and ftp
From: Ilari Liusvaara @ 2009-12-04 15:56 UTC (permalink / raw)
  To: git
In-Reply-To: <1259942168-24869-1-git-send-email-ilari.liusvaara@elisanet.fi>

HTTP, HTTPS and FTP are no longer special to transport code. Also
add support for FTPS (curl supports it so it is easy).

Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
---
 .gitignore  |    4 ++++
 Makefile    |   24 ++++++++++++++++++++++--
 transport.c |    8 --------
 3 files changed, 26 insertions(+), 10 deletions(-)

diff --git a/.gitignore b/.gitignore
index 7cc54b4..7c79f97 100644
--- a/.gitignore
+++ b/.gitignore
@@ -107,6 +107,10 @@
 /git-relink
 /git-remote
 /git-remote-curl
+/git-remote-http
+/git-remote-https
+/git-remote-ftp
+/git-remote-ftps
 /git-repack
 /git-replace
 /git-repo-config
diff --git a/Makefile b/Makefile
index 42744a4..1332225 100644
--- a/Makefile
+++ b/Makefile
@@ -424,6 +424,13 @@ BUILT_INS += git-stage$X
 BUILT_INS += git-status$X
 BUILT_INS += git-whatchanged$X
 
+#ifdef NO_CURL
+REMOTE_CURL_NAMES =
+#else
+# Yes, this is missing git-remote-http intentionally!
+REMOTE_CURL_NAMES = git-remote-https git-remote-ftp git-remote-ftps
+#endif
+
 # what 'all' will build and 'install' will install in gitexecdir,
 # excluding programs for built-in commands
 ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS)
@@ -1097,7 +1104,7 @@ else
 	else
 		CURL_LIBCURL = -lcurl
 	endif
-	PROGRAMS += git-remote-curl$X git-http-fetch$X
+	PROGRAMS += git-remote-http$X git-remote-https$X git-remote-ftp$X git-remote-ftps$X git-http-fetch$X
 	curl_check := $(shell (echo 070908; curl-config --vernum) | sort -r | sed -ne 2p)
 	ifeq "$(curl_check)" "070908"
 		ifndef NO_EXPAT
@@ -1676,7 +1683,13 @@ git-http-push$X: revision.o http.o http-push.o $(GITLIBS)
 	$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
 		$(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
 
-git-remote-curl$X: remote-curl.o http.o http-walker.o $(GITLIBS)
+$(REMOTE_CURL_NAMES): git-remote-http$X
+	$(QUIET_LNCP)$(RM) $@ && \
+	ln $< $@ 2>/dev/null || \
+	ln -s $< $@ 2>/dev/null || \
+	cp $< $@
+
+git-remote-http$X: remote-curl.o http.o http-walker.o $(GITLIBS)
 	$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
 		$(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
 
@@ -1853,6 +1866,7 @@ endif
 ifneq (,$X)
 	$(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) git$X)), test '$(DESTDIR_SQ)$(gitexec_instdir_SQ)/$p' -ef '$(DESTDIR_SQ)$(gitexec_instdir_SQ)/$p$X' || $(RM) '$(DESTDIR_SQ)$(gitexec_instdir_SQ)/$p';)
 endif
+
 	bindir=$$(cd '$(DESTDIR_SQ)$(bindir_SQ)' && pwd) && \
 	execdir=$$(cd '$(DESTDIR_SQ)$(gitexec_instdir_SQ)' && pwd) && \
 	{ test "$$bindir/" = "$$execdir/" || \
@@ -1866,6 +1880,12 @@ endif
 		ln -s "git$X" "$$execdir/$$p" 2>/dev/null || \
 		cp "$$execdir/git$X" "$$execdir/$$p" || exit; \
 	  done; } && \
+	{ for p in $(REMOTE_CURL_NAMES); do \
+		$(RM) "$$execdir/$$p" && \
+		ln "$$execdir/git-remote-http$X" "$$execdir/$$p" 2>/dev/null || \
+		ln -s "git-remote-http$X" "$$execdir/$$p" 2>/dev/null || \
+		cp "$$execdir/git-remote-http$X" "$$execdir/$$p" || exit; \
+	  done; } && \
 	./check_bindir "z$$bindir" "z$$execdir" "$$bindir/git-add$X"
 
 install-doc:
diff --git a/transport.c b/transport.c
index 1488cfe..872cc30 100644
--- a/transport.c
+++ b/transport.c
@@ -944,14 +944,6 @@ struct transport *transport_get(struct remote *remote, const char *url)
 
 		data->conn = NULL;
 		data->virtual_connected = 0;
-	} else if (!prefixcmp(url, "http://")
-		|| !prefixcmp(url, "https://")
-		|| !prefixcmp(url, "ftp://")) {
-		/* These three are just plain special. */
-		transport_helper_init(ret, "curl");
-#ifdef NO_CURL
-		error("git was compiled without libcurl support.");
-#endif
 	} else {
 		/* Unknown protocol in URL. Pass to external handler. */
 		int len = external_specification_len(url);
-- 
1.6.6.rc1.288.g40e67

^ permalink raw reply related

* [RFC PATCH v2 7/8] Add remote helper debug mode
From: Ilari Liusvaara @ 2009-12-04 15:56 UTC (permalink / raw)
  To: git
In-Reply-To: <1259942168-24869-1-git-send-email-ilari.liusvaara@elisanet.fi>

Remote helpers deadlock easily, so support debug mode which shows the
interaction steps.

Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
---
 transport-helper.c |   96 ++++++++++++++++++++++++++++++++++++----------------
 1 files changed, 67 insertions(+), 29 deletions(-)

diff --git a/transport-helper.c b/transport-helper.c
index 21aa4ab..03920bb 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -8,6 +8,8 @@
 #include "quote.h"
 #include "remote.h"
 
+static int debug = 0;
+
 struct helper_data
 {
 	const char *name;
@@ -24,6 +26,46 @@ struct helper_data
 	struct git_transport_options gitoptions;
 };
 
+static void sendline(struct helper_data *helper, struct strbuf *buffer)
+{
+	if(debug)
+		fprintf(stderr, "Debug: Remote helper: -> %s", buffer->buf);
+	if(write_in_full(helper->helper->in, buffer->buf, buffer->len)
+		!= buffer->len) {
+		die_errno("Full write to remote helper failed");
+	}
+}
+
+static int recvline(struct helper_data *helper, struct strbuf *buffer)
+{
+	strbuf_reset(buffer);
+	if(debug)
+		fprintf(stderr, "Debug: Remote helper: Waiting...\n");
+	if (strbuf_getline(buffer, helper->out, '\n') == EOF) {
+		if(debug)
+			fprintf(stderr, "Debug: Remote helper quit.\n");
+		exit(128);
+	}
+
+	if(debug)
+		fprintf(stderr, "Debug: Remote helper: <- %s\n", buffer->buf);
+	return 0;
+}
+
+static void xchgline(struct helper_data *helper, struct strbuf *buffer)
+{
+	sendline(helper, buffer);
+	recvline(helper, buffer);
+}
+
+static void write_constant(int fd, const char *str)
+{
+	if(debug)
+		fprintf(stderr, "Debug: Remote helper: -> %s", str);
+	if(write_in_full(fd, str, strlen(str)) != strlen(str))
+		die_errno("Full write to remote helper failed");
+}
+
 static struct child_process* helper_disown(struct transport *transport)
 {
 	struct helper_data *data = transport->data;
@@ -95,14 +137,14 @@ static struct child_process *get_helper(struct transport *transport)
 	data->out = xfdopen(duped, "r");
 	setvbuf(data->out, NULL, _IONBF, 0);
 
-	write_str_in_full(helper->in, "capabilities\n");
+	write_constant(helper->in, "capabilities\n");
 
 	while (1) {
-		if (strbuf_getline(&buf, data->out, '\n') == EOF)
-			exit(128); /* child died, message supplied already */
+		recvline(data, &buf);
 
 		if (!*buf.buf)
 			break;
+		if(debug) fprintf(stderr, "Debug: Got cap %s\n", buf.buf);
 		if (!strcmp(buf.buf, "fetch"))
 			data->fetch = 1;
 		if (!strcmp(buf.buf, "option"))
@@ -130,14 +172,19 @@ static struct child_process *get_helper(struct transport *transport)
 		free(refspecs);
 	}
 	strbuf_release(&buf);
+	if(debug) fprintf(stderr, "Debug: Capabilities complete.\n");
 	return data->helper;
 }
 
 static int disconnect_helper(struct transport *transport)
 {
 	struct helper_data *data = transport->data;
+	struct strbuf buf = STRBUF_INIT;
+
 	if (data->helper) {
-		write_str_in_full(data->helper->in, "\n");
+		if(debug) fprintf(stderr, "Debug: Disconnecting.\n");
+		strbuf_addf(&buf, "\n");
+		sendline(data, &buf);
 		close(data->helper->in);
 		close(data->helper->out);
 		fclose(data->out);
@@ -166,10 +213,11 @@ static int set_helper_option(struct transport *transport,
 			  const char *name, const char *value)
 {
 	struct helper_data *data = transport->data;
-	struct child_process *helper = get_helper(transport);
 	struct strbuf buf = STRBUF_INIT;
 	int i, ret, is_bool = 0;
 
+	get_helper(transport);
+
 	if (!data->option)
 		return 1;
 
@@ -192,12 +240,7 @@ static int set_helper_option(struct transport *transport,
 		quote_c_style(value, &buf, NULL, 0);
 	strbuf_addch(&buf, '\n');
 
-	if (write_in_full(helper->in, buf.buf, buf.len) != buf.len)
-		die_errno("cannot send option to %s", data->name);
-
-	strbuf_reset(&buf);
-	if (strbuf_getline(&buf, data->out, '\n') == EOF)
-		exit(128); /* child died, message supplied already */
+	xchgline(data, &buf);
 
 	if (!strcmp(buf.buf, "ok"))
 		ret = 0;
@@ -257,13 +300,10 @@ static int fetch_with_fetch(struct transport *transport,
 	}
 
 	strbuf_addch(&buf, '\n');
-	if (write_in_full(data->helper->in, buf.buf, buf.len) != buf.len)
-		die_errno("cannot send fetch to %s", data->name);
+	sendline(data, &buf);
 
 	while (1) {
-		strbuf_reset(&buf);
-		if (strbuf_getline(&buf, data->out, '\n') == EOF)
-			exit(128); /* child died, message supplied already */
+		recvline(data, &buf);
 
 		if (!prefixcmp(buf.buf, "lock ")) {
 			const char *name = buf.buf + 5;
@@ -298,12 +338,13 @@ static int fetch_with_import(struct transport *transport,
 			     int nr_heads, struct ref **to_fetch)
 {
 	struct child_process fastimport;
-	struct child_process *helper = get_helper(transport);
 	struct helper_data *data = transport->data;
 	int i;
 	struct ref *posn;
 	struct strbuf buf = STRBUF_INIT;
 
+	get_helper(transport);
+
 	if (get_importer(transport, &fastimport))
 		die("Couldn't run fast-import");
 
@@ -313,7 +354,7 @@ static int fetch_with_import(struct transport *transport,
 			continue;
 
 		strbuf_addf(&buf, "import %s\n", posn->name);
-		write_in_full(helper->in, buf.buf, buf.len);
+		sendline(data, &buf);
 		strbuf_reset(&buf);
 	}
 	disconnect_helper(transport);
@@ -364,10 +405,7 @@ static int _process_connect(struct transport *transport,
 	} else
 		return 0;
 
-	write_in_full(helper->in, cmdbuf.buf, cmdbuf.len);
-	strbuf_reset(&cmdbuf);
-	if (strbuf_getline(&cmdbuf, data->out, '\n') == EOF)
-		exit(128); /* child died, message supplied already */
+	xchgline(data, &cmdbuf);
 	if(!strcmp(cmdbuf.buf, ""))
 		return 1;
 	else if(!strcmp(cmdbuf.buf, "FALLBACK"))
@@ -500,17 +538,14 @@ static int push_refs(struct transport *transport,
 	}
 
 	strbuf_addch(&buf, '\n');
-	if (write_in_full(helper->in, buf.buf, buf.len) != buf.len)
-		exit(128);
+	sendline(data, &buf);
 
 	ref = remote_refs;
 	while (1) {
 		char *refname, *msg;
 		int status;
 
-		strbuf_reset(&buf);
-		if (strbuf_getline(&buf, data->out, '\n') == EOF)
-			exit(128); /* child died, message supplied already */
+		recvline(data, &buf);
 		if (!buf.len)
 			break;
 
@@ -605,8 +640,7 @@ static struct ref *get_refs_list(struct transport *transport, int for_push)
 
 	while (1) {
 		char *eov, *eon;
-		if (strbuf_getline(&buf, data->out, '\n') == EOF)
-			exit(128); /* child died, message supplied already */
+		recvline(data, &buf);
 
 		if (!*buf.buf)
 			break;
@@ -631,6 +665,7 @@ static struct ref *get_refs_list(struct transport *transport, int for_push)
 		}
 		tail = &((*tail)->next);
 	}
+	if(debug) fprintf(stderr, "Debug: Read ref listing.\n");
 	strbuf_release(&buf);
 
 	for (posn = ret; posn; posn = posn->next)
@@ -644,6 +679,9 @@ int transport_helper_init(struct transport *transport, const char *name)
 	struct helper_data *data = xcalloc(sizeof(*data), 1);
 	data->name = name;
 
+	if(getenv("GIT_TRANSPORT_HELPER_DEBUG"))
+		debug = 1;
+
 	transport->data = data;
 	transport->set_option = set_helper_option;
 	transport->get_refs_list = get_refs_list;
-- 
1.6.6.rc1.288.g40e67

^ permalink raw reply related

* [RFC PATCH v2 8/8] Support mandatory capabilities
From: Ilari Liusvaara @ 2009-12-04 15:56 UTC (permalink / raw)
  To: git
In-Reply-To: <1259942168-24869-1-git-send-email-ilari.liusvaara@elisanet.fi>

Add support for marking capability as mandatory for hosting git version
to understand. This is useful for helpers which require various types
of assistance from main git binary.

Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
---
 Documentation/git-remote-helpers.txt |    5 ++++-
 transport-helper.c                   |   29 ++++++++++++++++++++++-------
 2 files changed, 26 insertions(+), 8 deletions(-)

diff --git a/Documentation/git-remote-helpers.txt b/Documentation/git-remote-helpers.txt
index 91cd9eb..6af6824 100644
--- a/Documentation/git-remote-helpers.txt
+++ b/Documentation/git-remote-helpers.txt
@@ -25,7 +25,10 @@ Commands are given by the caller on the helper's standard input, one per line.
 
 'capabilities'::
 	Lists the capabilities of the helper, one per line, ending
-	with a blank line.
+	with a blank line. Each capability may be preceeded with '*'.
+	This marks them mandatory for git version using the remote
+	helper to understand (unknown mandatory capability is fatal
+	error).
 
 'list'::
 	Lists the refs, one per line, in the format "<value> <name>
diff --git a/transport-helper.c b/transport-helper.c
index 03920bb..9ddcdc3 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -140,27 +140,42 @@ static struct child_process *get_helper(struct transport *transport)
 	write_constant(helper->in, "capabilities\n");
 
 	while (1) {
+		const char* capname;
+		int mandatory = 0;
 		recvline(data, &buf);
 
 		if (!*buf.buf)
 			break;
-		if(debug) fprintf(stderr, "Debug: Got cap %s\n", buf.buf);
-		if (!strcmp(buf.buf, "fetch"))
+
+		if(*buf.buf == '*') {
+			capname = buf.buf + 1;
+			mandatory = 1;
+		} else
+			capname = buf.buf;
+
+		if(debug) fprintf(stderr, "Debug: Got cap %s\n", capname);
+		if (!strcmp(capname, "fetch"))
 			data->fetch = 1;
-		if (!strcmp(buf.buf, "option"))
+		else if (!strcmp(capname, "option"))
 			data->option = 1;
-		if (!strcmp(buf.buf, "push"))
+		else if (!strcmp(capname, "push"))
 			data->push = 1;
-		if (!strcmp(buf.buf, "import"))
+		else if (!strcmp(capname, "import"))
 			data->import = 1;
-		if (!data->refspecs && !prefixcmp(buf.buf, "refspec ")) {
+		else if (!data->refspecs && !prefixcmp(capname, "refspec ")) {
 			ALLOC_GROW(refspecs,
 				   refspec_nr + 1,
 				   refspec_alloc);
 			refspecs[refspec_nr++] = strdup(buf.buf + strlen("refspec "));
 		}
-		if (!strcmp(buf.buf, "connect"))
+		else if (!strcmp(capname, "connect"))
 			data->connect = 1;
+		else if (mandatory) {
+			fflush(stderr);
+			die("Unknown madatory capability %s. This remote "
+			    "helper probably needs newer version of Git.\n",
+			    capname);
+		}
 	}
 	if (refspecs) {
 		int i;
-- 
1.6.6.rc1.288.g40e67

^ permalink raw reply related

* Re: [PATCH] git-gui: suppress the X error on exit
From: Shawn O. Pearce @ 2009-12-04 15:57 UTC (permalink / raw)
  To: Jindrich Makovicka; +Cc: git
In-Reply-To: <20091204102844.3c720b21@starbug.prg01.itonis.net>

Jindrich Makovicka <makovick@gmail.com> wrote:
> Due to a bug in Tk, git-gui almost always (unless git-gui is closed
> right after starting) produces an X window error message on exit,
> something like

Thanks.  I've wrapped it up into the following commit.  Can I get
a Signed-off-by line from you?

--8<--
[PATCH] git-gui: suppress RenderBadPicture X error caused by Tk bug

Due to a bug in Tk, git-gui almost always (unless git-gui is closed
right after starting) produces an X window error message on exit,
something like:

X Error of failed request:  RenderBadPicture (invalid Picture parameter)
  Major opcode of failed request:  150 (RENDER)
  Minor opcode of failed request:  7 (RenderFreePicture)
  Picture id in failed request: 0x3a000dc
  Serial number of failed request:  1965
  Current serial number in output stream:  1980

Respective Tk bug report is here:

http://sourceforge.net/tracker/?func=detail&atid=112997&aid=1821174&group_id=12997

This bug is triggered only when the send command is blocked via
rename send {} . The following patch re-enables send just before
quiting git-gui to suppress the error.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 git-gui.sh |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/git-gui.sh b/git-gui.sh
index 037a1f2..718277a 100755
--- a/git-gui.sh
+++ b/git-gui.sh
@@ -2052,6 +2052,11 @@ proc do_quit {{rc {1}}} {
 	}
 
 	set ret_code $rc
+
+	# Briefly enable send again, working around Tk bug
+	# http://sourceforge.net/tracker/?func=detail&atid=112997&aid=1821174&group_id=12997
+	tk appname [appname]
+
 	destroy .
 }
 
-- 
1.6.6.rc0.324.gb5bf2

-- 
Shawn.

^ permalink raw reply related

* Re: [RFC PATCH v2 1/8] Pass unknown protocols to external protocol  handlers
From: Sverre Rabbelier @ 2009-12-04 16:01 UTC (permalink / raw)
  To: Ilari Liusvaara; +Cc: git
In-Reply-To: <1259942168-24869-4-git-send-email-ilari.liusvaara@elisanet.fi>

Heya,

On Fri, Dec 4, 2009 at 16:56, Ilari Liusvaara
<ilari.liusvaara@elisanet.fi> wrote:
> Change URL handling to allow external protocol handlers to implement
> new protocols without the '::' syntax if helper name does not conflict
> with any built-in protocol.

Haven't looked at the patch itself, but I like the idea, a lot.

-- 
Cheers,

Sverre Rabbelier

^ permalink raw reply

* Re: [RFC PATCH v2 7/8] Add remote helper debug mode
From: Sverre Rabbelier @ 2009-12-04 16:03 UTC (permalink / raw)
  To: Ilari Liusvaara; +Cc: git
In-Reply-To: <1259942168-24869-10-git-send-email-ilari.liusvaara@elisanet.fi>

Heya,

On Fri, Dec 4, 2009 at 16:56, Ilari Liusvaara
<ilari.liusvaara@elisanet.fi> wrote:
> Remote helpers deadlock easily, so support debug mode which shows the
> interaction steps.

You should move this to the beginning of the series, so that it can be
merged even if your other patches are not :).

-- 
Cheers,

Sverre Rabbelier

^ permalink raw reply

* Re: [RFC PATCH v2 6/8] Remove special casing of http, https and ftp
From: Sverre Rabbelier @ 2009-12-04 16:05 UTC (permalink / raw)
  To: Ilari Liusvaara; +Cc: git
In-Reply-To: <1259942168-24869-9-git-send-email-ilari.liusvaara@elisanet.fi>

Heya,

On Fri, Dec 4, 2009 at 16:56, Ilari Liusvaara
<ilari.liusvaara@elisanet.fi> wrote:
> HTTP, HTTPS and FTP are no longer special to transport code. Also
> add support for FTPS (curl supports it so it is easy).

As I said earlier, I like this idea, again, without having looked at
the patch itself so I cannot comment on the implementation :).

-- 
Cheers,

Sverre Rabbelier

^ permalink raw reply

* git-blame.el: what is format-spec?
From: Sergei Organov @ 2009-12-04 16:21 UTC (permalink / raw)
  To: git

Hello,

What is format-spec function in current git-blame.el? Neither my GNU
Emacs 22.2.1 nor Google knows anything about it.

-- Sergei.

^ permalink raw reply

* Re: git-blame.el: what is format-spec?
From: Andreas Schwab @ 2009-12-04 16:38 UTC (permalink / raw)
  To: Sergei Organov; +Cc: git
In-Reply-To: <87vdgm3e1k.fsf@osv.gnss.ru>

Sergei Organov <osv@javad.com> writes:

> What is format-spec function in current git-blame.el? Neither my GNU
> Emacs 22.2.1 nor Google knows anything about it.

It's part of Emacs since more than 9 years, imported from Gnus.

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ permalink raw reply

* Re: [PATCH 1/3] Better document the original repository layout.
From: Johannes Schindelin @ 2009-12-04 16:51 UTC (permalink / raw)
  To: Michael J Gruber; +Cc: Michael Haggerty, git, gitster
In-Reply-To: <4B192210.908@drmicha.warpmail.net>

Hi,

On Fri, 4 Dec 2009, Michael J Gruber wrote:

> Michael Haggerty venit, vidit, dixit 04.12.2009 15:36:
> > Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
> > ---
> >  t/t3404-rebase-interactive.sh |    9 +++++----
> >  1 files changed, 5 insertions(+), 4 deletions(-)
> > 
> > diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
> > index 3a37793..073674f 100755
> > --- a/t/t3404-rebase-interactive.sh
> > +++ b/t/t3404-rebase-interactive.sh
> > @@ -16,13 +16,14 @@ set_fake_editor
> >  
> >  # set up two branches like this:
> >  #
> > -# A - B - C - D - E
> > +# A - B - C - D - E     (master)
> >  #   \
> > -#     F - G - H
> > +#     F - G - H         (branch1)
> >  #       \
> > -#         I
> > +#         I             (branch2)
> >  #
> > -# where B, D and G touch the same file.
> > +# where B, D and G touch the same file.  In addition, set tags at
> > +# points A, F, and I.
> >  
> >  test_expect_success 'setup' '
> >  	: > file1 &&
> 
> My first reaction to the subject was "Huh? What repository?". So I
> suggest something like
> 
> t3404: Better document the original repository layout
> 
> as a more descriptive subject.

That would be good, the patch itself is already good.

ACK

^ permalink raw reply

* Re: [PATCH 2/3] Set a couple more tags in the original repository.
From: Johannes Schindelin @ 2009-12-04 16:52 UTC (permalink / raw)
  To: Michael Haggerty; +Cc: git, gitster
In-Reply-To: <5482fe5eb1141d925dd4df20cc00416e09813ff7.1259934977.git.mhagger@alum.mit.edu>

Hi,

On Fri, 4 Dec 2009, Michael Haggerty wrote:

> 
> Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>

Alternatively, one could use the test_commit function, I guess.  But the 
patch is good as it is.

ACK.

^ permalink raw reply

* Re: [PATCH 3/3] Add a command "fix" to rebase --interactive.
From: Johannes Schindelin @ 2009-12-04 16:57 UTC (permalink / raw)
  To: Michael Haggerty; +Cc: git, gitster
In-Reply-To: <6d779d2c244bf5d5b7924cdc5daf66a8186e4bc7.1259934977.git.mhagger@alum.mit.edu>

Hi,

On Fri, 4 Dec 2009, Michael Haggerty wrote:

> The command is like "squash", except that it discards the commit message
> of the corresponding commit.
> 
> Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>

The only part which made me a bit uneasy was this one:

> diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
> index 0bd3bf7..539413d 100755
> --- a/git-rebase--interactive.sh
> +++ b/git-rebase--interactive.sh
> @@ -302,7 +302,7 @@ nth_string () {
>  
>  make_squash_message () {
>  	if test -f "$SQUASH_MSG"; then
> -		COUNT=$(($(sed -n "s/^# This is [^0-9]*\([1-9][0-9]*\).*/\1/p" \
> +		COUNT=$(($(sed -n "s/^# Th[^0-9]*\([1-9][0-9]*\)\(th\|st\|nd\|rd\) commit message.*:/\1/p" \
>  			< "$SQUASH_MSG" | sed -ne '$p')+1))
>  		echo "# This is a combination of $COUNT commits."
>  		sed -e 1d -e '2,/^./{

But it is fine.  (Took this idiot a couple of seconds to figure out why; 
I'd have put "th" last, being a mathematician instead of a computer 
scientist, so my natural numbers start with 1, not 0 ;-)

To be honest, I never thought of "fix" as something I want, but patiently 
deleted the respective commit messages of my fixup commits (usually called 
"amend" or "amend.<something helpful>").

This is brilliant.

ACK

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox