From: Shawn O. Pearce <spearce@spearce.org>
Date: Thu, 18 Jan 2007 20:17:58 +0000 (-0500)
Subject: Accept 'inline' file data in fast-import commit structure.
X-Git-Tag: v1.5.0-rc4~14^2~14
X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/b715cfbba4083d25ec0d0f94e440ad734607ddb0?hp=--cc

Accept 'inline' file data in fast-import commit structure.

Its very annoying to need to specify the file content ahead of a
commit and use marks to connect the individual blobs to the commit's
file modification entry, especially if the frontend can't/won't
generate the blob SHA1s itself.  Instead it would much easier to
use if we can accept the blob data at the same time as we receive
each file_change line.

Now fast-import accepts 'inline' instead of a mark idnum or blob
SHA1 within the 'M' type file_change command.  If an inline is
detected the very next line must be a 'data n' command, supplying
the file data.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---

b715cfbba4083d25ec0d0f94e440ad734607ddb0
diff --git a/fast-import.c b/fast-import.c
index 90adc68042..487a91a4ee 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -25,10 +25,11 @@ Format of STDIN stream:
     lf;
   commit_msg ::= data;
 
-  file_change ::= 'M' sp mode sp (hexsha1 | idnum) sp path_str lf
-                | 'D' sp path_str lf
-                ;
-  mode ::= '644' | '755';
+  file_change ::= file_del | file_obm | file_inm;
+  file_del ::= 'D' sp path_str lf;
+  file_obm ::= 'M' sp mode sp (hexsha1 | idnum) sp path_str lf;
+  file_inm ::= 'M' sp mode sp 'inline' sp path_str lf
+    data;
 
   new_tag ::= 'tag' sp tag_str lf
     'from' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf
@@ -77,6 +78,10 @@ Format of STDIN stream:
   sha1exp_str ::= sha1exp | '"' quoted(sha1exp) '"' ;
   tag_str     ::= tag     | '"' quoted(tag)     '"' ;
   path_str    ::= path    | '"' quoted(path)    '"' ;
+  mode        ::= '100644' | '644'
+                | '100755' | '755'
+                | '140000'
+                ;
 
   declen ::= # unsigned 32 bit value, ascii base10 notation;
   bigint ::= # unsigned integer value, ascii base10 notation;
@@ -1452,7 +1457,7 @@ static void file_change_m(struct branch *b)
 	const char *endp;
 	struct object_entry *oe;
 	unsigned char sha1[20];
-	unsigned int mode;
+	unsigned int mode, inline_data = 0;
 	char type[20];
 
 	p = get_mode(p, &mode);
@@ -1475,6 +1480,9 @@ static void file_change_m(struct branch *b)
 		oe = find_mark(strtoumax(p + 1, &x, 10));
 		hashcpy(sha1, oe->sha1);
 		p = x;
+	} else if (!strncmp("inline", p, 6)) {
+		inline_data = 1;
+		p += 6;
 	} else {
 		if (get_sha1_hex(p, sha1))
 			die("Invalid SHA1: %s", command_buf.buf);
@@ -1491,7 +1499,16 @@ static void file_change_m(struct branch *b)
 		p = p_uq;
 	}
 
-	if (oe) {
+	if (inline_data) {
+		size_t l;
+		void *d;
+		if (!p_uq)
+			p = p_uq = xstrdup(p);
+		read_next_command();
+		d = cmd_data(&l);
+		if (store_object(OBJ_BLOB, d, l, &last_blob, sha1, 0))
+			free(d);
+	} else if (oe) {
 		if (oe->type != OBJ_BLOB)
 			die("Not a blob (actually a %s): %s",
 				command_buf.buf, type_names[oe->type]);
diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh
index 40b8c073bd..a5cc846b34 100755
--- a/t/t9300-fast-import.sh
+++ b/t/t9300-fast-import.sh
@@ -17,6 +17,12 @@ in 3rd file
 file4_data=abcd
 file4_len=4
 
+file5_data='an inline file.
+  we should see it later.'
+
+file6_data='#!/bin/sh
+echo "$@"'
+
 ###
 ### series A
 ###
@@ -181,4 +187,57 @@ test_expect_success \
 	'C: validate rename result' \
 	'compare_diff_raw expect actual'
 
+###
+### series D
+###
+
+test_tick
+cat >input <<INPUT_END
+commit refs/heads/branch
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+third
+COMMIT
+
+from refs/heads/branch^0
+M 644 inline newdir/interesting
+data <<EOF
+$file5_data
+EOF
+
+M 755 inline newdir/exec.sh
+data <<EOF
+$file6_data
+EOF
+
+INPUT_END
+test_expect_success \
+    'D: inline data in commit' \
+    'git-fast-import <input &&
+	 git-whatchanged branch'
+test_expect_success \
+	'D: verify pack' \
+	'for p in .git/objects/pack/*.pack;do git-verify-pack $p||exit;done'
+
+cat >expect <<EOF
+:000000 100755 0000000000000000000000000000000000000000 35a59026a33beac1569b1c7f66f3090ce9c09afc A	newdir/exec.sh
+:000000 100644 0000000000000000000000000000000000000000 046d0371e9220107917db0d0e030628de8a1de9b A	newdir/interesting
+EOF
+git-diff-tree -M -r branch^ branch >actual
+test_expect_success \
+	'D: validate new files added' \
+	'compare_diff_raw expect actual'
+
+echo "$file5_data" >expect
+test_expect_success \
+	'D: verify file5' \
+	'git-cat-file blob branch:newdir/interesting >actual &&
+	 diff -u expect actual'
+
+echo "$file6_data" >expect
+test_expect_success \
+	'D: verify file6' \
+	'git-cat-file blob branch:newdir/exec.sh >actual &&
+	 diff -u expect actual'
+
 test_done