Git development
 help / color / mirror / Atom feed
* Re: [ANNOUNCE] Git 1.6.5.4
From: Junio C Hamano @ 2009-12-04 17:10 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: Todd Zullinger, Michael J Gruber, git
In-Reply-To: <m2r5rb9hes.fsf@igel.home>

Andreas Schwab <schwab@linux-m68k.org> writes:

> Junio C Hamano <gitster@pobox.com> writes:
>
>> I think it depends on the likelihood that a distro has xmlto so old that
>> it does not understand --stringparam yet it uses stylesheet so new that
>> setting the parameter makes a positive difference (either it gives the
>> full URL or at least squelches the "You should define the parameter"
>> noise) in the output.
>
> openSUSE 11.2, for example.  Its xmlto has a non-standard --xsltopts
> option that passes its argument down to xsltproc.

Ok, as I said that I've been wrong before in this area ;-)

I don't think I will have much time for git today, and it would be
appreciated if somebody can work on this and send a tested patch that
applies cleanly on top of 'maint' to implement the @@MAN_BASE_URL@@
replacement from manpage-base.xsl.in to manpage-base.xsl as Todd suggested
earlier.

^ permalink raw reply

* [PATCH v8 7/7] fast-import: add (non-)relative-marks feature
From: Sverre Rabbelier @ 2009-12-04 17:07 UTC (permalink / raw)
  To: Junio C Hamano, Shawn O. Pearce, Johannes Schindelin, Git List,
	vcs-fast-import-devs
  Cc: Sverre Rabbelier, Daniel Barkalow
In-Reply-To: <1259946420-8845-7-git-send-email-srabbelier@gmail.com>

After specifying 'feature relative-marks' the paths specified with
'feature import-marks' and 'feature export-marks' are relative to an
internal directory in the current repository.

In git-fast-import this means that the paths are relative to the
'.git/info/fast-import' directory. However, other importers may use a
different location.

Add 'feature non-relative-marks' to disable this behavior, this way
it is possible to, for example, specify the import-marks location as
relative, and the export-marks location as non-relative.

Also add tests to verify this behavior.

Cc: Daniel Barkalow <barkalow@iabervon.org>
Signed-off-by: Sverre Rabbelier <srabbelier@gmail.com>
---

	As requested by Daniel, it is now possible to have the marks be
	relative to a constant directory. We might want to consider making
	this the default at some point.

	This patch opens the way for remote-helpers to use the marks feature
	without poluting the work tree, which I think is very important.

 Documentation/git-fast-import.txt |   16 ++++++++++++++++
 fast-import.c                     |   19 +++++++++++++++++--
 t/t9300-fast-import.sh            |   25 +++++++++++++++++++++++++
 3 files changed, 58 insertions(+), 2 deletions(-)

diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt
index 752f85c..1a63835 100644
--- a/Documentation/git-fast-import.txt
+++ b/Documentation/git-fast-import.txt
@@ -75,6 +75,20 @@ OPTIONS
 	set of marks.  If a mark is defined to different values,
 	the last file wins.
 
+--relative-marks::
+	After specifying --relative-marks= the paths specified
+	with --import-marks= and --export-marks= are relative
+	to an internal directory in the current repository.
+	In git-fast-import this means that the paths are relative
+	to the .git/info/fast-import directory. However, other
+	importers may use a different location.
+
+--no-relative-marks::
+	Negates a previous --relative-marks. Allows for combining
+	relative and non-relative marks by interweaving
+	--(no-)-relative-marks= with the --(import|export)-marks=
+	options.
+
 --export-pack-edges=<file>::
 	After creating a packfile, print a line of data to
 	<file> listing the filename of the packfile and the last
@@ -875,6 +889,8 @@ The following features are currently supported:
 * date-format
 * import-marks
 * export-marks
+* relative-marks
+* no-relative-marks
 * force
 
 The import-marks behaves differently from when it is specified as
diff --git a/fast-import.c b/fast-import.c
index 4c3406e..8d50a1e 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -323,6 +323,7 @@ static struct mark_set *marks;
 static const char *export_marks_file;
 static const char *import_marks_file;
 static int import_marks_file_from_stream;
+static int relative_marks_paths;
 
 /* Our last blob */
 static struct last_object last_blob = { STRBUF_INIT, 0, 0, 0 };
@@ -2470,6 +2471,16 @@ static void parse_progress(void)
 	skip_optional_lf();
 }
 
+static char* make_fast_import_path(const char *path)
+{
+	if (!relative_marks_paths || is_absolute_path(path))
+		return xstrdup(path);
+
+	struct strbuf abs_path = STRBUF_INIT;
+	strbuf_addf(&abs_path, "%s/info/fast-import/%s", get_git_dir(), path);
+	return strbuf_detach(&abs_path, NULL);
+}
+
 static void option_import_marks(const char *marks, int from_stream)
 {
 	if (import_marks_file) {
@@ -2481,7 +2492,7 @@ static void option_import_marks(const char *marks, int from_stream)
 			read_marks();
 	}
 
-	import_marks_file = xstrdup(marks);
+	import_marks_file = make_fast_import_path(marks);
 	import_marks_file_from_stream = from_stream;
 }
 
@@ -2516,7 +2527,7 @@ static void option_active_branches(const char *branches)
 
 static void option_export_marks(const char *marks)
 {
-	export_marks_file = xstrdup(marks);
+	export_marks_file = make_fast_import_path(marks);
 }
 
 static void option_export_pack_edges(const char *edges)
@@ -2557,6 +2568,10 @@ static int parse_one_feature(const char *feature, int from_stream)
 		option_import_marks(feature + 13, from_stream);
 	} else if (!prefixcmp(feature, "export-marks=")) {
 		option_export_marks(feature + 13);
+	} else if (!prefixcmp(feature, "relative-marks")) {
+		relative_marks_paths = 1;
+	} else if (!prefixcmp(feature, "no-relative-marks")) {
+		relative_marks_paths = 0;
 	} else if (!prefixcmp(feature, "force")) {
 		force_update = 1;
 	} else {
diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh
index ba92775..a1b8c2b 100755
--- a/t/t9300-fast-import.sh
+++ b/t/t9300-fast-import.sh
@@ -1346,6 +1346,31 @@ test_expect_success 'R: multiple --import-marks= should be honoured' '
     test_cmp marks.out combined.marks
 '
 
+cat >input <<EOF
+feature relative-marks
+feature import-marks=relative.in
+feature export-marks=relative.out
+EOF
+
+test_expect_success 'R: feature relative-marks should be honoured' '
+    mkdir -p .git/info/fast-import/ &&
+    cp marks.new .git/info/fast-import/relative.in &&
+    git fast-import <input &&
+    test_cmp marks.new .git/info/fast-import/relative.out
+'
+
+cat >input <<EOF
+feature relative-marks
+feature import-marks=relative.in
+feature no-relative-marks
+feature export-marks=non-relative.out
+EOF
+
+test_expect_success 'R: feature no-relative-marks should be honoured' '
+    git fast-import <input &&
+    test_cmp marks.new non-relative.out
+'
+
 cat >input << EOF
 option git quiet
 blob
-- 
1.6.5.3.164.g07b0c

^ permalink raw reply related

* [PATCH v8 6/7] fast-import: allow for multiple --import-marks= arguments
From: Sverre Rabbelier @ 2009-12-04 17:06 UTC (permalink / raw)
  To: Junio C Hamano, Shawn O. Pearce, Johannes Schindelin, Git List,
	vcs-fast-import-devs
  Cc: Sverre Rabbelier
In-Reply-To: <1259946420-8845-6-git-send-email-srabbelier@gmail.com>

The --import-marks= option may be specified multiple times on the
commandline and should result in all marks being read in. Only one
import-marks feature may be specified in the stream, which is
overriden by any --import-marks= commandline options.

If one wishes to specify import-marks files in addition to the one
specified in the stream, it is easy to repeat the stream option as a
--import-marks= commandline option.

Also verify this behavior with tests.

Signed-off-by: Sverre Rabbelier <srabbelier@gmail.com>
---

	New in this series. Without this it is no longer possible to specify
	multiple --import-marks= options on the commandline.

 Documentation/git-fast-import.txt |    8 +++++++-
 fast-import.c                     |   21 ++++++++++++++++-----
 t/t9300-fast-import.sh            |   22 ++++++++++++++++++++++
 3 files changed, 45 insertions(+), 6 deletions(-)

diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt
index 2d5f533..752f85c 100644
--- a/Documentation/git-fast-import.txt
+++ b/Documentation/git-fast-import.txt
@@ -867,7 +867,8 @@ it does not.
 The <feature> part of the command may be any string matching
 ^[a-zA-Z][a-zA-Z-]*$ and should be understood by fast-import.
 
-Feature work identical as their option counterparts.
+Feature work identical as their option counterparts with the
+exception of the import-marks feature, see below.
 
 The following features are currently supported:
 
@@ -876,6 +877,11 @@ The following features are currently supported:
 * export-marks
 * force
 
+The import-marks behaves differently from when it is specified as
+commandline option in that only one "feature import-marks" is allowed
+per stream. Also, any --import-marks= specified on the commandline
+will override those from the stream (if any).
+
 `option`
 ~~~~~~~~
 Processes the specified option so that git fast-import behaves in a
diff --git a/fast-import.c b/fast-import.c
index ab099b6..4c3406e 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -322,6 +322,7 @@ static struct object_entry *object_table[1 << 16];
 static struct mark_set *marks;
 static const char *export_marks_file;
 static const char *import_marks_file;
+static int import_marks_file_from_stream;
 
 /* Our last blob */
 static struct last_object last_blob = { STRBUF_INIT, 0, 0, 0 };
@@ -2469,9 +2470,19 @@ static void parse_progress(void)
 	skip_optional_lf();
 }
 
-static void option_import_marks(const char *marks)
+static void option_import_marks(const char *marks, int from_stream)
 {
+	if (import_marks_file) {
+		if (from_stream)
+			die("Only one import-marks command allowed per stream");
+
+		/* read previous mark file */
+		if(!import_marks_file_from_stream)
+			read_marks();
+	}
+
 	import_marks_file = xstrdup(marks);
+	import_marks_file_from_stream = from_stream;
 }
 
 static void option_date_format(const char *fmt)
@@ -2538,12 +2549,12 @@ static int parse_one_option(const char *option)
 	return 1;
 }
 
-static int parse_one_feature(const char *feature)
+static int parse_one_feature(const char *feature, int from_stream)
 {
 	if (!prefixcmp(feature, "date-format=")) {
 		option_date_format(feature + 12);
 	} else if (!prefixcmp(feature, "import-marks=")) {
-		option_import_marks(feature + 13);
+		option_import_marks(feature + 13, from_stream);
 	} else if (!prefixcmp(feature, "export-marks=")) {
 		option_export_marks(feature + 13);
 	} else if (!prefixcmp(feature, "force")) {
@@ -2562,7 +2573,7 @@ static void parse_feature(void)
 	if (seen_data_command)
 		die("Got feature command '%s' after data command", feature);
 
-	if (parse_one_feature(feature))
+	if (parse_one_feature(feature, 1))
 		return;
 
 	die("This version of fast-import does not support feature %s.", feature);
@@ -2618,7 +2629,7 @@ static void parse_argv(void)
 		if (parse_one_option(a + 2))
 			continue;
 
-		if (parse_one_feature(a + 2))
+		if (parse_one_feature(a + 2, 0))
 			continue;
 
 		die("unknown option %s", a);
diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh
index 74dff11..ba92775 100755
--- a/t/t9300-fast-import.sh
+++ b/t/t9300-fast-import.sh
@@ -1286,6 +1286,15 @@ test_expect_success 'R: abort on receiving feature after data command' '
 '
 
 cat >input << EOF
+feature import-marks=git.marks
+feature import-marks=git2.marks
+EOF
+
+test_expect_success 'R: only one import-marks feature allowed per stream' '
+	test_must_fail git fast-import <input
+'
+
+cat >input << EOF
 feature export-marks=git.marks
 blob
 mark :1
@@ -1324,6 +1333,19 @@ test_expect_success \
     'cat input | git fast-import --import-marks=marks.out &&
     test_cmp marks.out marks.new'
 
+
+cat >input <<EOF
+feature import-marks=nonexistant.marks
+feature export-marks=combined.marks
+EOF
+
+test_expect_success 'R: multiple --import-marks= should be honoured' '
+    head -n2 marks.out > one.marks &&
+    tail -n +3 marks.out > two.marks &&
+    git fast-import --import-marks=one.marks --import-marks=two.marks <input &&
+    test_cmp marks.out combined.marks
+'
+
 cat >input << EOF
 option git quiet
 blob
-- 
1.6.5.3.164.g07b0c

^ permalink raw reply related

* [PATCH v8 5/7] fast-import: test the new option command
From: Sverre Rabbelier @ 2009-12-04 17:06 UTC (permalink / raw)
  To: Junio C Hamano, Shawn O. Pearce, Johannes Schindelin, Git List,
	vcs-fast-import-devs
  Cc: Sverre Rabbelier
In-Reply-To: <1259946420-8845-5-git-send-email-srabbelier@gmail.com>

Test the quiet option and verify that the commandline options
override it.

Also make sure that an unknown option command is rejected and that
non-git options are ignored.

Lastly, show that unknown options are rejected when parsed on the
commandline.

Signed-off-by: Sverre Rabbelier <srabbelier@gmail.com>
---

	Tests updated to match the new behavior.

 t/t9300-fast-import.sh |   37 ++++++++++++++++++++++++++++++++++++-
 1 files changed, 36 insertions(+), 1 deletions(-)

diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh
index b2c521f..74dff11 100755
--- a/t/t9300-fast-import.sh
+++ b/t/t9300-fast-import.sh
@@ -1255,7 +1255,7 @@ test_expect_success \
 	'git cat-file blob refs/notes/foobar:$commit3 >actual && test_cmp expect actual'
 
 ###
-### series R (feature)
+### series R (feature and option)
 ###
 
 cat >input <<EOF
@@ -1324,4 +1324,39 @@ test_expect_success \
     'cat input | git fast-import --import-marks=marks.out &&
     test_cmp marks.out marks.new'
 
+cat >input << EOF
+option git quiet
+blob
+data 3
+hi
+
+EOF
+
+touch empty
+
+test_expect_success 'R: quiet option results in no stats being output' '
+    cat input | git fast-import 2> output &&
+    test_cmp empty output
+'
+
+cat >input <<EOF
+option git non-existing-option
+EOF
+
+test_expect_success 'R: die on unknown option' '
+    test_must_fail git fast-import <input
+'
+
+test_expect_success 'R: unknown commandline options are rejected' '\
+    test_must_fail git fast-import --non-existing-option < /dev/null
+'
+
+cat >input <<EOF
+option non-existing-vcs non-existing-option
+EOF
+
+test_expect_success 'R: ignore non-git options' '
+    git fast-import <input
+'
+
 test_done
-- 
1.6.5.3.164.g07b0c

^ permalink raw reply related

* [PATCH v8 4/7] fast-import: add option command
From: Sverre Rabbelier @ 2009-12-04 17:06 UTC (permalink / raw)
  To: Junio C Hamano, Shawn O. Pearce, Johannes Schindelin, Git List,
	vcs-fast-import-devs
  Cc: Sverre Rabbelier
In-Reply-To: <1259946420-8845-4-git-send-email-srabbelier@gmail.com>

This allows the frontend to specify any of the supported options as
long as no non-option command has been given. This way the
user does not have to include any frontend-specific options, but
instead she can rely on the frontend to tell fast-import what it
needs.

Also factor out parsing of argv and have it execute when we reach the
first non-option command, or after all commands have been read and
no non-option command has been encountered.

Non-git options are ignored, unrecognised options result in an error.

Signed-off-by: Sverre Rabbelier <srabbelier@gmail.com>
---

	Reject unknown options, update documentation, and some style fixes.

 Documentation/git-fast-import.txt |   32 +++++++++++++
 fast-import.c                     |   87 ++++++++++++++++++++++++++-----------
 2 files changed, 94 insertions(+), 25 deletions(-)

diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt
index 4357c21..2d5f533 100644
--- a/Documentation/git-fast-import.txt
+++ b/Documentation/git-fast-import.txt
@@ -307,6 +307,11 @@ and control the current import process.  More detailed discussion
 	Require that fast-import supports the specified feature, or
 	abort if it does not.
 
+`option`::
+	Specify any of the options listed under OPTIONS that do not
+	change stream semantic to suit the frontend's needs. This
+	command is optional and is not needed to perform an import.
+
 `commit`
 ~~~~~~~~
 Create or update a branch with a new commit, recording one logical
@@ -871,6 +876,33 @@ The following features are currently supported:
 * export-marks
 * force
 
+`option`
+~~~~~~~~
+Processes the specified option so that git fast-import behaves in a
+way that suits the frontend's needs.
+Note that options specified by the frontend are overridden by any
+options the user may specify to git fast-import itself.
+
+....
+    'option' SP <option> LF
+....
+
+The `<option>` part of the command may contain any of the options
+listed in the OPTIONS section that do not change import semantics,
+without the leading '--' and is treated in the same way.
+
+Option commands must be the first commands on the input (not counting
+feature commands), to give an option command after any non-option
+command is an error.
+
+The following commandline options change import semantics and may therefore
+not be passed as option:
+
+* date-format
+* import-marks
+* export-marks
+* force
+
 Crash Reports
 -------------
 If fast-import is supplied invalid input it will terminate with a
diff --git a/fast-import.c b/fast-import.c
index ce0cd4e..ab099b6 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -296,6 +296,8 @@ static unsigned long branch_load_count;
 static int failure;
 static FILE *pack_edges;
 static unsigned int show_stats = 1;
+static int global_argc;
+static const char **global_argv;
 
 /* Memory pools */
 static size_t mem_pool_alloc = 2*1024*1024 - sizeof(struct mem_pool);
@@ -355,6 +357,8 @@ static uintmax_t next_mark;
 static struct strbuf new_data = STRBUF_INIT;
 static int seen_data_command;
 
+static void parse_argv(void);
+
 static void write_branch_report(FILE *rpt, struct branch *b)
 {
 	fprintf(rpt, "%s:\n", b->name);
@@ -1706,8 +1710,9 @@ static int read_next_command(void)
 				return EOF;
 
 			if (!seen_data_command
-				&& prefixcmp(command_buf.buf, "feature ")) {
-				seen_data_command = 1;
+				&& prefixcmp(command_buf.buf, "feature ")
+				&& prefixcmp(command_buf.buf, "option ")) {
+				parse_argv();
 			}
 
 			rc = rc_free;
@@ -2512,31 +2517,25 @@ static void option_export_pack_edges(const char *edges)
 		die_errno("Cannot open '%s'", edges);
 }
 
-static void parse_one_option(const char *option)
+static int parse_one_option(const char *option)
 {
-	if (!prefixcmp(option, "date-format=")) {
-		option_date_format(option + 12);
-	} else if (!prefixcmp(option, "max-pack-size=")) {
+	if (!prefixcmp(option, "max-pack-size=")) {
 		option_max_pack_size(option + 14);
 	} else if (!prefixcmp(option, "depth=")) {
 		option_depth(option + 6);
 	} else if (!prefixcmp(option, "active-branches=")) {
 		option_active_branches(option + 16);
-	} else if (!prefixcmp(option, "import-marks=")) {
-		option_import_marks(option + 13);
-	} else if (!prefixcmp(option, "export-marks=")) {
-		option_export_marks(option + 13);
 	} else if (!prefixcmp(option, "export-pack-edges=")) {
 		option_export_pack_edges(option + 18);
-	} else if (!prefixcmp(option, "force")) {
-		force_update = 1;
 	} else if (!prefixcmp(option, "quiet")) {
 		show_stats = 0;
 	} else if (!prefixcmp(option, "stats")) {
 		show_stats = 1;
 	} else {
-		die("Unsupported option: %s", option);
+		return 0;
 	}
+
+	return 1;
 }
 
 static int parse_one_feature(const char *feature)
@@ -2569,6 +2568,19 @@ static void parse_feature(void)
 	die("This version of fast-import does not support feature %s.", feature);
 }
 
+static void parse_option(void)
+{
+	char *option = command_buf.buf + 11;
+
+	if (seen_data_command)
+		die("Got option command '%s' after data command", option);
+
+	if (parse_one_option(option))
+		return;
+
+	die("This version of fast-import does not support option: %s", option);
+}
+
 static int git_pack_config(const char *k, const char *v, void *cb)
 {
 	if (!strcmp(k, "pack.depth")) {
@@ -2593,6 +2605,32 @@ static int git_pack_config(const char *k, const char *v, void *cb)
 static const char fast_import_usage[] =
 "git fast-import [--date-format=f] [--max-pack-size=n] [--depth=n] [--active-branches=n] [--export-marks=marks.file]";
 
+static void parse_argv(void)
+{
+	unsigned int i;
+
+	for (i = 1; i < global_argc; i++) {
+		const char *a = global_argv[i];
+
+		if (*a != '-' || !strcmp(a, "--"))
+			break;
+
+		if (parse_one_option(a + 2))
+			continue;
+
+		if (parse_one_feature(a + 2))
+			continue;
+
+		die("unknown option %s", a);
+	}
+	if (i != global_argc)
+		usage(fast_import_usage);
+
+	seen_data_command = 1;
+	if (import_marks_file)
+		read_marks();
+}
+
 int main(int argc, const char **argv)
 {
 	unsigned int i;
@@ -2614,18 +2652,8 @@ int main(int argc, const char **argv)
 	avail_tree_table = xcalloc(avail_tree_table_sz, sizeof(struct avail_tree_content*));
 	marks = pool_calloc(1, sizeof(struct mark_set));
 
-	for (i = 1; i < argc; i++) {
-		const char *a = argv[i];
-
-		if (*a != '-' || !strcmp(a, "--"))
-			break;
-
-		parse_one_option(a + 2);
-	}
-	if (i != argc)
-		usage(fast_import_usage);
-	if (import_marks_file)
-		read_marks();
+	global_argc = argc;
+	global_argv = argv;
 
 	rc_free = pool_alloc(cmd_save * sizeof(*rc_free));
 	for (i = 0; i < (cmd_save - 1); i++)
@@ -2650,9 +2678,18 @@ int main(int argc, const char **argv)
 			parse_progress();
 		else if (!prefixcmp(command_buf.buf, "feature "))
 			parse_feature();
+		else if (!prefixcmp(command_buf.buf, "option git "))
+			parse_option();
+		else if (!prefixcmp(command_buf.buf, "option "))
+			/* ignore non-git options*/;
 		else
 			die("Unsupported command: %s", command_buf.buf);
 	}
+
+	/* argv hasn't been parsed yet, do so */
+	if (!seen_data_command)
+		parse_argv();
+
 	end_packfile();
 
 	dump_branches();
-- 
1.6.5.3.164.g07b0c

^ permalink raw reply related

* [PATCH v8 3/7] fast-import: add feature command
From: Sverre Rabbelier @ 2009-12-04 17:06 UTC (permalink / raw)
  To: Junio C Hamano, Shawn O. Pearce, Johannes Schindelin, Git List,
	vcs-fast-import-devs
  Cc: Sverre Rabbelier
In-Reply-To: <1259946420-8845-3-git-send-email-srabbelier@gmail.com>

This allows the fronted to require a specific feature to be supported
by the frontend, or abort.

Also add support for four initial feature, date-format=, force=,
import-marks=, export-marks=.

Signed-off-by: Sverre Rabbelier <srabbelier@gmail.com>
---

	Updated documentation, reject feature commands after a data command,
	as per Shawn's comments. Also factor out parse_one_feature from
	parse_feature so that we can re-use it in patch 4/7.

	This also has the previous 4/6 squashed in (which added tests)

 Documentation/git-fast-import.txt |   25 +++++++++++++
 fast-import.c                     |   38 ++++++++++++++++++++
 t/t9300-fast-import.sh            |   70 +++++++++++++++++++++++++++++++++++++
 3 files changed, 133 insertions(+), 0 deletions(-)

diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt
index 288032c..4357c21 100644
--- a/Documentation/git-fast-import.txt
+++ b/Documentation/git-fast-import.txt
@@ -303,6 +303,10 @@ and control the current import process.  More detailed discussion
 	standard output.  This command is optional and is not needed
 	to perform an import.
 
+`feature`::
+	Require that fast-import supports the specified feature, or
+	abort if it does not.
+
 `commit`
 ~~~~~~~~
 Create or update a branch with a new commit, recording one logical
@@ -846,6 +850,27 @@ Placing a `progress` command immediately after a `checkpoint` will
 inform the reader when the `checkpoint` has been completed and it
 can safely access the refs that fast-import updated.
 
+`feature`
+~~~~~~~~~
+Require that fast-import supports the specified feature, or abort if
+it does not.
+
+....
+	'feature' SP <feature> LF
+....
+
+The <feature> part of the command may be any string matching
+^[a-zA-Z][a-zA-Z-]*$ and should be understood by fast-import.
+
+Feature work identical as their option counterparts.
+
+The following features are currently supported:
+
+* date-format
+* import-marks
+* export-marks
+* force
+
 Crash Reports
 -------------
 If fast-import is supplied invalid input it will terminate with a
diff --git a/fast-import.c b/fast-import.c
index 0458b03..ce0cd4e 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -353,6 +353,7 @@ static struct recent_command *rc_free;
 static unsigned int cmd_save = 100;
 static uintmax_t next_mark;
 static struct strbuf new_data = STRBUF_INIT;
+static int seen_data_command;
 
 static void write_branch_report(FILE *rpt, struct branch *b)
 {
@@ -1704,6 +1705,11 @@ static int read_next_command(void)
 			if (stdin_eof)
 				return EOF;
 
+			if (!seen_data_command
+				&& prefixcmp(command_buf.buf, "feature ")) {
+				seen_data_command = 1;
+			}
+
 			rc = rc_free;
 			if (rc)
 				rc_free = rc->next;
@@ -2533,6 +2539,36 @@ static void parse_one_option(const char *option)
 	}
 }
 
+static int parse_one_feature(const char *feature)
+{
+	if (!prefixcmp(feature, "date-format=")) {
+		option_date_format(feature + 12);
+	} else if (!prefixcmp(feature, "import-marks=")) {
+		option_import_marks(feature + 13);
+	} else if (!prefixcmp(feature, "export-marks=")) {
+		option_export_marks(feature + 13);
+	} else if (!prefixcmp(feature, "force")) {
+		force_update = 1;
+	} else {
+		return 0;
+	}
+
+	return 1;
+}
+
+static void parse_feature(void)
+{
+	char *feature = command_buf.buf + 8;
+
+	if (seen_data_command)
+		die("Got feature command '%s' after data command", feature);
+
+	if (parse_one_feature(feature))
+		return;
+
+	die("This version of fast-import does not support feature %s.", feature);
+}
+
 static int git_pack_config(const char *k, const char *v, void *cb)
 {
 	if (!strcmp(k, "pack.depth")) {
@@ -2612,6 +2648,8 @@ int main(int argc, const char **argv)
 			parse_checkpoint();
 		else if (!prefixcmp(command_buf.buf, "progress "))
 			parse_progress();
+		else if (!prefixcmp(command_buf.buf, "feature "))
+			parse_feature();
 		else
 			die("Unsupported command: %s", command_buf.buf);
 	}
diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh
index b49815d..b2c521f 100755
--- a/t/t9300-fast-import.sh
+++ b/t/t9300-fast-import.sh
@@ -1254,4 +1254,74 @@ test_expect_success \
 	'Q: verify note for third commit' \
 	'git cat-file blob refs/notes/foobar:$commit3 >actual && test_cmp expect actual'
 
+###
+### series R (feature)
+###
+
+cat >input <<EOF
+feature no-such-feature-exists
+EOF
+
+test_expect_success 'R: abort on unsupported feature' '
+	test_must_fail git fast-import <input
+'
+
+cat >input <<EOF
+feature date-format=now
+EOF
+
+test_expect_success 'R: supported feature is accepted' '
+	git fast-import <input
+'
+
+cat >input << EOF
+blob
+data 3
+hi
+feature date-format=now
+EOF
+
+test_expect_success 'R: abort on receiving feature after data command' '
+	test_must_fail git fast-import <input
+'
+
+cat >input << EOF
+feature export-marks=git.marks
+blob
+mark :1
+data 3
+hi
+
+EOF
+
+test_expect_success \
+    'R: export-marks feature results in a marks file being created' \
+    'cat input | git fast-import &&
+    grep :1 git.marks'
+
+test_expect_success \
+    'R: export-marks options can be overriden by commandline options' \
+    'cat input | git fast-import --export-marks=other.marks &&
+    grep :1 other.marks'
+
+cat >input << EOF
+feature import-marks=marks.out
+feature export-marks=marks.new
+EOF
+
+test_expect_success \
+    'R: import to output marks works without any content' \
+    'cat input | git fast-import &&
+    test_cmp marks.out marks.new'
+
+cat >input <<EOF
+feature import-marks=nonexistant.marks
+feature export-marks=marks.new
+EOF
+
+test_expect_success \
+    'R: import marks prefers commandline marks file over the stream' \
+    'cat input | git fast-import --import-marks=marks.out &&
+    test_cmp marks.out marks.new'
+
 test_done
-- 
1.6.5.3.164.g07b0c

^ permalink raw reply related

* [PATCH v8 1/7] fast-import: put option parsing code in separate functions
From: Sverre Rabbelier @ 2009-12-04 17:06 UTC (permalink / raw)
  To: Junio C Hamano, Shawn O. Pearce, Johannes Schindelin, Git List,
	vcs-fast-import-devs
  Cc: Sverre Rabbelier
In-Reply-To: <1259946420-8845-1-git-send-email-srabbelier@gmail.com>

Putting the options in their own functions increases readability of
the option parsing block and makes it easier to reuse the option
parsing code later on.

Signed-off-by: Sverre Rabbelier <srabbelier@gmail.com>
---

	Rebased against current master, no other changes.

 fast-import.c |  115 +++++++++++++++++++++++++++++++++++++--------------------
 1 files changed, 75 insertions(+), 40 deletions(-)

diff --git a/fast-import.c b/fast-import.c
index dd3c99d..fcd9e1e 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -295,6 +295,7 @@ static unsigned long branch_count;
 static unsigned long branch_load_count;
 static int failure;
 static FILE *pack_edges;
+static unsigned int show_stats = 1;
 
 /* Memory pools */
 static size_t mem_pool_alloc = 2*1024*1024 - sizeof(struct mem_pool);
@@ -2420,7 +2421,7 @@ static void parse_progress(void)
 	skip_optional_lf();
 }
 
-static void import_marks(const char *input_file)
+static void option_import_marks(const char *input_file)
 {
 	char line[512];
 	FILE *f = fopen(input_file, "r");
@@ -2455,6 +2456,76 @@ static void import_marks(const char *input_file)
 	fclose(f);
 }
 
+static void option_date_format(const char *fmt)
+{
+	if (!strcmp(fmt, "raw"))
+		whenspec = WHENSPEC_RAW;
+	else if (!strcmp(fmt, "rfc2822"))
+		whenspec = WHENSPEC_RFC2822;
+	else if (!strcmp(fmt, "now"))
+		whenspec = WHENSPEC_NOW;
+	else
+		die("unknown --date-format argument %s", fmt);
+}
+
+static void option_max_pack_size(const char *packsize)
+{
+	max_packsize = strtoumax(packsize, NULL, 0) * 1024 * 1024;
+}
+
+static void option_depth(const char *depth)
+{
+	max_depth = strtoul(depth, NULL, 0);
+	if (max_depth > MAX_DEPTH)
+		die("--depth cannot exceed %u", MAX_DEPTH);
+}
+
+static void option_active_branches(const char *branches)
+{
+	max_active_branches = strtoul(branches, NULL, 0);
+}
+
+static void option_export_marks(const char *marks)
+{
+	mark_file = xstrdup(marks);
+}
+
+static void option_export_pack_edges(const char *edges)
+{
+	if (pack_edges)
+		fclose(pack_edges);
+	pack_edges = fopen(edges, "a");
+	if (!pack_edges)
+		die_errno("Cannot open '%s'", edges);
+}
+
+static void parse_one_option(const char *option)
+{
+	if (!prefixcmp(option, "date-format=")) {
+		option_date_format(option + 12);
+	} else if (!prefixcmp(option, "max-pack-size=")) {
+		option_max_pack_size(option + 14);
+	} else if (!prefixcmp(option, "depth=")) {
+		option_depth(option + 6);
+	} else if (!prefixcmp(option, "active-branches=")) {
+		option_active_branches(option + 16);
+	} else if (!prefixcmp(option, "import-marks=")) {
+		option_import_marks(option + 13);
+	} else if (!prefixcmp(option, "export-marks=")) {
+		option_export_marks(option + 13);
+	} else if (!prefixcmp(option, "export-pack-edges=")) {
+		option_export_pack_edges(option + 18);
+	} else if (!prefixcmp(option, "force")) {
+		force_update = 1;
+	} else if (!prefixcmp(option, "quiet")) {
+		show_stats = 0;
+	} else if (!prefixcmp(option, "stats")) {
+		show_stats = 1;
+	} else {
+		die("Unsupported option: %s", option);
+	}
+}
+
 static int git_pack_config(const char *k, const char *v, void *cb)
 {
 	if (!strcmp(k, "pack.depth")) {
@@ -2481,7 +2552,7 @@ static const char fast_import_usage[] =
 
 int main(int argc, const char **argv)
 {
-	unsigned int i, show_stats = 1;
+	unsigned int i;
 
 	git_extract_argv0_path(argv[0]);
 
@@ -2505,44 +2576,8 @@ int main(int argc, const char **argv)
 
 		if (*a != '-' || !strcmp(a, "--"))
 			break;
-		else if (!prefixcmp(a, "--date-format=")) {
-			const char *fmt = a + 14;
-			if (!strcmp(fmt, "raw"))
-				whenspec = WHENSPEC_RAW;
-			else if (!strcmp(fmt, "rfc2822"))
-				whenspec = WHENSPEC_RFC2822;
-			else if (!strcmp(fmt, "now"))
-				whenspec = WHENSPEC_NOW;
-			else
-				die("unknown --date-format argument %s", fmt);
-		}
-		else if (!prefixcmp(a, "--max-pack-size="))
-			max_packsize = strtoumax(a + 16, NULL, 0) * 1024 * 1024;
-		else if (!prefixcmp(a, "--depth=")) {
-			max_depth = strtoul(a + 8, NULL, 0);
-			if (max_depth > MAX_DEPTH)
-				die("--depth cannot exceed %u", MAX_DEPTH);
-		}
-		else if (!prefixcmp(a, "--active-branches="))
-			max_active_branches = strtoul(a + 18, NULL, 0);
-		else if (!prefixcmp(a, "--import-marks="))
-			import_marks(a + 15);
-		else if (!prefixcmp(a, "--export-marks="))
-			mark_file = a + 15;
-		else if (!prefixcmp(a, "--export-pack-edges=")) {
-			if (pack_edges)
-				fclose(pack_edges);
-			pack_edges = fopen(a + 20, "a");
-			if (!pack_edges)
-				die_errno("Cannot open '%s'", a + 20);
-		} else if (!strcmp(a, "--force"))
-			force_update = 1;
-		else if (!strcmp(a, "--quiet"))
-			show_stats = 0;
-		else if (!strcmp(a, "--stats"))
-			show_stats = 1;
-		else
-			die("unknown option %s", a);
+
+		parse_one_option(a + 2);
 	}
 	if (i != argc)
 		usage(fast_import_usage);
-- 
1.6.5.3.164.g07b0c

^ permalink raw reply related

* [PATCH v8 2/7] fast-import: put marks reading in it's own function
From: Sverre Rabbelier @ 2009-12-04 17:06 UTC (permalink / raw)
  To: Junio C Hamano, Shawn O. Pearce, Johannes Schindelin, Git List,
	vcs-fast-import-devs
  Cc: Sverre Rabbelier
In-Reply-To: <1259946420-8845-2-git-send-email-srabbelier@gmail.com>

All options do nothing but set settings, with the exception of the
--input-marks option. Delay the reading of the marks file till after
all options have been parsed.

Also, rename mark_file to export_marks_file as it is now ambiguous.

Signed-off-by: Sverre Rabbelier <srabbelier@gmail.com>
---

	Renamed mark_fiel to export_marks_file and added import_marks_file as
	per Shawn's comments.

 fast-import.c |   93 +++++++++++++++++++++++++++++++-------------------------
 1 files changed, 51 insertions(+), 42 deletions(-)

diff --git a/fast-import.c b/fast-import.c
index fcd9e1e..0458b03 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -318,7 +318,8 @@ static unsigned int object_entry_alloc = 5000;
 static struct object_entry_pool *blocks;
 static struct object_entry *object_table[1 << 16];
 static struct mark_set *marks;
-static const char *mark_file;
+static const char *export_marks_file;
+static const char *import_marks_file;
 
 /* Our last blob */
 static struct last_object last_blob = { STRBUF_INIT, 0, 0, 0 };
@@ -455,8 +456,8 @@ static void write_crash_report(const char *err)
 	fputc('\n', rpt);
 	fputs("Marks\n", rpt);
 	fputs("-----\n", rpt);
-	if (mark_file)
-		fprintf(rpt, "  exported to %s\n", mark_file);
+	if (export_marks_file)
+		fprintf(rpt, "  exported to %s\n", export_marks_file);
 	else
 		dump_marks_helper(rpt, 0, marks);
 
@@ -1603,13 +1604,13 @@ static void dump_marks(void)
 	int mark_fd;
 	FILE *f;
 
-	if (!mark_file)
+	if (!export_marks_file)
 		return;
 
-	mark_fd = hold_lock_file_for_update(&mark_lock, mark_file, 0);
+	mark_fd = hold_lock_file_for_update(&mark_lock, export_marks_file, 0);
 	if (mark_fd < 0) {
 		failure |= error("Unable to write marks file %s: %s",
-			mark_file, strerror(errno));
+			export_marks_file, strerror(errno));
 		return;
 	}
 
@@ -1618,7 +1619,7 @@ static void dump_marks(void)
 		int saved_errno = errno;
 		rollback_lock_file(&mark_lock);
 		failure |= error("Unable to write marks file %s: %s",
-			mark_file, strerror(saved_errno));
+			export_marks_file, strerror(saved_errno));
 		return;
 	}
 
@@ -1634,7 +1635,7 @@ static void dump_marks(void)
 		int saved_errno = errno;
 		rollback_lock_file(&mark_lock);
 		failure |= error("Unable to write marks file %s: %s",
-			mark_file, strerror(saved_errno));
+			export_marks_file, strerror(saved_errno));
 		return;
 	}
 
@@ -1642,11 +1643,47 @@ static void dump_marks(void)
 		int saved_errno = errno;
 		rollback_lock_file(&mark_lock);
 		failure |= error("Unable to commit marks file %s: %s",
-			mark_file, strerror(saved_errno));
+			export_marks_file, strerror(saved_errno));
 		return;
 	}
 }
 
+static void read_marks(void)
+{
+	char line[512];
+	FILE *f = fopen(import_marks_file, "r");
+	if (!f)
+		die_errno("cannot read '%s'", import_marks_file);
+	while (fgets(line, sizeof(line), f)) {
+		uintmax_t mark;
+		char *end;
+		unsigned char sha1[20];
+		struct object_entry *e;
+
+		end = strchr(line, '\n');
+		if (line[0] != ':' || !end)
+			die("corrupt mark line: %s", line);
+		*end = 0;
+		mark = strtoumax(line + 1, &end, 10);
+		if (!mark || end == line + 1
+			|| *end != ' ' || get_sha1(end + 1, sha1))
+			die("corrupt mark line: %s", line);
+		e = find_object(sha1);
+		if (!e) {
+			enum object_type type = sha1_object_info(sha1, NULL);
+			if (type < 0)
+				die("object not found: %s", sha1_to_hex(sha1));
+			e = insert_object(sha1);
+			e->type = type;
+			e->pack_id = MAX_PACK_ID;
+			e->offset = 1; /* just not zero! */
+		}
+		insert_mark(mark, e);
+	}
+	fclose(f);
+}
+
+
 static int read_next_command(void)
 {
 	static int stdin_eof = 0;
@@ -2421,39 +2458,9 @@ static void parse_progress(void)
 	skip_optional_lf();
 }
 
-static void option_import_marks(const char *input_file)
+static void option_import_marks(const char *marks)
 {
-	char line[512];
-	FILE *f = fopen(input_file, "r");
-	if (!f)
-		die_errno("cannot read '%s'", input_file);
-	while (fgets(line, sizeof(line), f)) {
-		uintmax_t mark;
-		char *end;
-		unsigned char sha1[20];
-		struct object_entry *e;
-
-		end = strchr(line, '\n');
-		if (line[0] != ':' || !end)
-			die("corrupt mark line: %s", line);
-		*end = 0;
-		mark = strtoumax(line + 1, &end, 10);
-		if (!mark || end == line + 1
-			|| *end != ' ' || get_sha1(end + 1, sha1))
-			die("corrupt mark line: %s", line);
-		e = find_object(sha1);
-		if (!e) {
-			enum object_type type = sha1_object_info(sha1, NULL);
-			if (type < 0)
-				die("object not found: %s", sha1_to_hex(sha1));
-			e = insert_object(sha1);
-			e->type = type;
-			e->pack_id = MAX_PACK_ID;
-			e->offset = 1; /* just not zero! */
-		}
-		insert_mark(mark, e);
-	}
-	fclose(f);
+	import_marks_file = xstrdup(marks);
 }
 
 static void option_date_format(const char *fmt)
@@ -2487,7 +2494,7 @@ static void option_active_branches(const char *branches)
 
 static void option_export_marks(const char *marks)
 {
-	mark_file = xstrdup(marks);
+	export_marks_file = xstrdup(marks);
 }
 
 static void option_export_pack_edges(const char *edges)
@@ -2581,6 +2588,8 @@ int main(int argc, const char **argv)
 	}
 	if (i != argc)
 		usage(fast_import_usage);
+	if (import_marks_file)
+		read_marks();
 
 	rc_free = pool_alloc(cmd_save * sizeof(*rc_free));
 	for (i = 0; i < (cmd_save - 1); i++)
-- 
1.6.5.3.164.g07b0c

^ permalink raw reply related

* [PATCH v8 0/7] fast-import: add new feature and option command
From: Sverre Rabbelier @ 2009-12-04 17:06 UTC (permalink / raw)
  To: Junio C Hamano, Shawn O. Pearce, Johannes Schindelin, Git List,
	vcs-fast-import-devs

This reroll addressess comments from Shawn and the fast-import
mailing list. It also adds a new feature, "relative-marks", which
will be very useful for remote helpers.

Apologies for taking so long with the reroll, hopefully this version
is good for next and I can finish my git-remote-hg work :).

Sverre Rabbelier (7):
      fast-import: put option parsing code in separate functions
      fast-import: put marks reading in it's own function
      fast-import: add feature command
      fast-import: add option command
      fast-import: test the new option command
      fast-import: allow for multiple --import-marks= arguments
      fast-import: add (non-)relative-marks feature

 Documentation/git-fast-import.txt |   79 +++++++++
 fast-import.c                     |  317 +++++++++++++++++++++++++++----------
 t/t9300-fast-import.sh            |  152 ++++++++++++++++++
 3 files changed, 462 insertions(+), 86 deletions(-)

^ permalink raw reply

* Re: git-blame.el: what is format-spec?
From: Sergei Organov @ 2009-12-04 16:59 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: git
In-Reply-To: <m2fx7qae49.fsf@igel.home>

Andreas Schwab <schwab@linux-m68k.org> writes:
> 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.
>

Thanks, I now see it in Gnus on my own computer, in
lisp/gnus/format-spec.el.gz.

GNU Emacs 22.2.1 (i486-pc-linux-gnu, GTK+ Version 2.12.11) of 2008-11-10
on raven, modified by Debian 

However, isn't it a bad idea to require Gnus(!) for git-blame to run? Gnus
is not installed on our server where I've encountered the problem. Was
format-spec actually moved to core emacs recently?

-- Sergei.

^ permalink raw reply

* Re: git gsoc money
From: Brandon Casey @ 2009-12-04 16:57 UTC (permalink / raw)
  To: Jeff King; +Cc: git
In-Reply-To: <20091204121417.GA20682@coredump.intra.peff.net>

Jeff King wrote:
> On Thu, Dec 03, 2009 at 07:39:35AM -0800, Shawn O. Pearce wrote:
> 
>>>   1. Become an affiliated project of an organization like The Software
>>>      Freedom Conservancy or Software in the Public Interest.
>> Try to join the Software Freedom Conservancy and retain the funds
>> for Git's use?  Maybe you can slide in before the Dec 31st deadline.
> 
> Everybody who responded seems to think that is a good idea, so I've
> contacted the SFC about joining. I'll keep the list up to date as things
> develop there.
> 
> I expect they'll need a liaison from the project. I can do that, but if
> somebody else is interested, let me know.

Now that I've read the links that you mentioned, I too think this is a
good idea.  I haven't been involved in SoC (though I benefited and much
appreciated having my travel expenses reimbursed), so my opinion should
be weighted accordingly.

If there's anything I can do to help, Jeff, please let me know.

-brandon

^ 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

* 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 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: 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

* 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: [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

* 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 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: [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

* [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

* [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 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 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 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


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