git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 4/7] fast-import: Allow cat requests at arbitrary points in stream

From
David Barr <david.barr@cordelta.com>
Date
Oct 12, 2010, 13:50 UTC
Message-ID
<1286891424-2067-5-git-send-email-david.barr@cordelta.com>
In-Reply-To
<1286891424-2067-1-git-send-email-david.barr@cordelta.com>
From: Jonathan Nieder <jrnieder@gmail.com>

Rather than planning in advance and saving up a bunch of objects before a "commit" command, frontends might want to wait until the middle of a commit and request objects then.

Allow them to.

The new rule: a "cat" request can be inserted wherever a comment is allowed, which means at the start of any line except in the middle of a "data" command.

Cc: Ramkumar Ramachandra <artagnon@gmail.com>
Cc: David Barr <david.barr@cordelta.com>
Cc: Sverre Rabbelier <srabbelier@gmail.com>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
---
 Documentation/git-fast-import.txt |    4 ++
 fast-import.c                     |   27 ++++++++------
 t/t9300-fast-import.sh            |   72 +++++++++++++++++++++++++++++++++++++
 3 files changed, 92 insertions(+), 11 deletions(-)
diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt
index 2cf48f5..b670c7d 100644
--- a/Documentation/git-fast-import.txt
+++ b/Documentation/git-fast-import.txt
@@ -920,6 +920,10 @@ a path within that tree to retrieve a subtree or blob.
 A `<path>` string should be surrounded with quotation marks and
 use C-style escaping.
 
+The `cat` command can be used anywhere that comments are
+acceptable.  In particular, the `cat` command can be used in the
+middle of a commit, but not in the middle of a `data` stream.
+
 `feature`
 ~~~~~~~~~
 Require that fast-import supports the specified feature, or abort if
diff --git a/fast-import.c b/fast-import.c
index f3c4123..87246d5 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -55,9 +55,6 @@ Format of STDIN stream:
     ('from' sp committish lf)?
     lf?;
 
-  cat_request ::= 'cat' sp (hexsha1 | idnum) lf
-    | 'cat' sp hexsha1 sp path_str lf;
-
   checkpoint ::= 'checkpoint' lf
     lf?;
 
@@ -135,14 +132,18 @@ Format of STDIN stream:
   ts    ::= # time since the epoch in seconds, ascii base10 notation;
   tz    ::= # GIT style timezone;
 
-     # note: comments may appear anywhere in the input, except
-     # within a data command.  Any form of the data command
-     # always escapes the related input from comment processing.
+     # note: comments and cat requests may appear anywhere
+     # in the input, except within a data command.  Any form
+     # of the data command always escapes the related input
+     # from comment processing.
      #
      # In case it is not clear, the '#' that starts the comment
      # must be the first character on that line (an lf
      # preceded it).
      #
+  cat_request ::= 'cat' sp (hexsha1 | idnum) lf
+    | 'cat' sp hexsha1 sp path_str lf;
+
   comment ::= '#' not_lf* lf;
   not_lf  ::= # Any byte that is not ASCII newline (LF);
 */
@@ -368,6 +369,7 @@ static int seen_data_command;
 static int report_fd = -1;
 
 static void parse_argv(void);
+static void parse_cat_request(void);
 
 static void write_branch_report(FILE *rpt, struct branch *b)
 {
@@ -1777,7 +1779,6 @@ static void read_marks(void)
 	fclose(f);
 }
 
-
 static int read_next_command(void)
 {
 	static int stdin_eof = 0;
@@ -1787,7 +1788,7 @@ static int read_next_command(void)
 		return EOF;
 	}
 
-	do {
+	for (;;) {
 		if (unread_command_buf) {
 			unread_command_buf = 0;
 		} else {
@@ -1820,7 +1821,13 @@ static int read_next_command(void)
 			rc->prev->next = rc;
 			cmd_tail = rc;
 		}
-	} while (command_buf.buf[0] == '#');
+		if (!prefixcmp(command_buf.buf, "cat ")) {
+			parse_cat_request();
+			continue;
+		}
+		if (command_buf.buf[0] != '#')
+			return 0;
+	}
 
 	return 0;
 }
@@ -3081,8 +3088,6 @@ int main(int argc, const char **argv)
 			parse_new_tag();
 		else if (!prefixcmp(command_buf.buf, "reset "))
 			parse_reset_branch();
-		else if (!prefixcmp(command_buf.buf, "cat "))
-			parse_cat_request();
 		else if (!strcmp("checkpoint", command_buf.buf))
 			parse_checkpoint();
 		else if (!prefixcmp(command_buf.buf, "progress "))
diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh
index 8155b85..a85d068 100755
--- a/t/t9300-fast-import.sh
+++ b/t/t9300-fast-import.sh
@@ -1749,6 +1749,78 @@ test_expect_success PIPE 'R: report-fd: can feed back printed blob' '
 	compare_diff_raw expect actual
 '
 
+test_expect_success PIPE 'R: report-fd: cat commands mid-commit' '
+	file4_id=$(
+		printf "%s" "$file4_data" |
+		git hash-object --stdin
+	) &&
+	cat >expect <<-EOF &&
+	:100755 100644 $file4_id $file4_id C100 file4	file4-copy
+	EOF
+	git cat-file commit refs/heads/branch >expect.commit &&
+	echo tree >expect.type &&
+	git cat-file tree refs/heads/branch >expect.tree &&
+
+	cat >frontend <<-\FRONTEND_END &&
+	#!/bin/sh
+
+	branch=$(git rev-parse --verify refs/heads/branch) &&
+	cat <<EOF &&
+	feature report-fd=3
+	commit refs/heads/catdemo
+	cat $branch
+	EOF
+
+	read commit_id type size <&3 &&
+	dd if=/dev/stdin of=commit bs=1 count=$size <&3 &&
+	read newline <&3 &&
+	read tree tree_id <commit &&
+
+	echo "cat $tree_id" &&
+
+	read tree_id2 type size <&3 &&
+	dd if=/dev/stdin of=tree bs=1 count=$size <&3 &&
+	read newline <&3 &&
+	echo $type >type &&
+
+	grep ^committer commit &&
+	cat <<EOF &&
+	data <<COMMIT
+	copy file4 as file4-copy
+	COMMIT
+
+	from refs/heads/branch^0
+	cat $tree_id "file4"
+	EOF
+
+	read blob_id type size <&3 &&
+	dd if=/dev/stdin of=/dev/null bs=1 count=$size <&3 &&
+	read newline <&3 &&
+
+	cat <<EOF &&
+	M 644 $blob_id "file4-copy"
+	cat $tree_id ""
+
+	EOF
+
+	read tree_id3 type size <&3 &&
+	dd if=/dev/stdin of=tree2 bs=1 count=$size <&3 &&
+	read newline <&3 &&
+	read cid <&3
+	FRONTEND_END
+
+	mkfifo commits &&
+	test_when_finished "rm -f commits" &&
+	sh frontend 3<commits |
+	git fast-import 3>commits &&
+	git diff-tree -C catdemo^ catdemo >actual &&
+	compare_diff_raw expect actual
+	test_cmp expect.commit commit &&
+	test_cmp expect.type type &&
+	test_cmp expect.tree tree &&
+	test_cmp expect.tree tree2
+'
+
 cat >input << EOF
 option git quiet
 blob
-- 
1.7.3.1
Previous: Jonathan NiederNext: Jonathan Nieder
Message 16 of 28 in “Add support for subversion dump format v3”
  1. Add support for subversion dump format v3David Barr, Oct 12, 2010
  2. 1/7 Teach fast-import to print the id of each imported commitDavid Barr, Oct 12, 2010
  3. Sverre RabbelierOct 12, 2010
  4. Jonathan NiederOct 12, 2010
  5. Sverre RabbelierOct 12, 2010
  6. Jonathan NiederOct 12, 2010
  7. Jonathan NiederOct 12, 2010
  8. Sverre RabbelierOct 12, 2010
  9. 2/7 fast-import: Let importers retrieve the objects being writtenDavid Barr, Oct 12, 2010
  10. Jonathan NiederOct 12, 2010
  11. Sverre RabbelierOct 12, 2010
  12. Jonathan NiederOct 13, 2010
  13. Sverre RabbelierOct 13, 2010
  14. 3/7 fast-import: Allow cat command with empty pathDavid Barr, Oct 12, 2010
  15. Jonathan NiederOct 12, 2010
  16. 4/7 fast-import: Allow cat requests at arbitrary points in streamDavid Barr, Oct 12, 2010
  17. Jonathan NiederOct 12, 2010
  18. 5/7 vcs-svn: extend svndump to parse version 3 formatDavid Barr, Oct 12, 2010
  19. Jonathan NiederOct 12, 2010
  20. 6/7 vcs-svn: implement prop-delta handling.David Barr, Oct 12, 2010
  21. Jonathan NiederOct 12, 2010
  22. 7/7 svn-fe: Use the --report-fd featureDavid Barr, Oct 12, 2010
  23. Sverre RabbelierOct 12, 2010
  24. Jonathan NiederOct 12, 2010
  25. Sverre RabbelierOct 12, 2010
  26. Jonathan NiederOct 12, 2010
  27. Jonathan NiederOct 12, 2010
  28. Jonathan NiederOct 13, 2010

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.