Remove the line length limit for graft files

Support for grafts predates Git's strbuf, and hence it is understandable that there was a hard-coded line length limit of 1023 characters (which was chosen a bit awkwardly, given that it is *exactly* one byte short of aligning with the 41 bytes occupied by a commit name and the following space or new-line character). While regular commit histories hardly win comprehensibility in general if they merge more than twenty-two branches in one go, it is not Git's business to limit grafts in such a way. In this particular developer's case, the use case that requires substantially longer graft lines to be supported is the visualization of the commits' order implied by their changes: commits are considered to have an implicit relationship iff exchanging them in an interactive rebase would result in merge conflicts. Thusly implied branches tend to be very shallow in general, and the resulting thicket of implied branches is usually very wide; It is actually quite common that *most* of the commits in a topic branch have not even one implied parent, so that a final merge commit has about as many implied parents as there are commits in said branch. [jc: squashed in tests by Jonathan] Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Reviewed-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Johannes Schindelin committed Dec 27, 2013 at 21:49 UTC e228c1736f25c59cd6da51ed97e03ecd80a935e6
4 files changed +45 -10
builtin/blame.c
+4 -4
@@ -1804,17 +1804,17 @@ static int prepare_lines(struct scoreboard *sb)
1804 static int read_ancestry(const char *graft_file)
1805 {
1806 FILE *fp = fopen(graft_file, "r");
1807 - char buf[1024];
1807 + struct strbuf buf = STRBUF_INIT;
1808 if (!fp)
1809 return -1;
1810 - while (fgets(buf, sizeof(buf), fp)) {
1810 + while (!strbuf_getwholeline(&buf, fp, '\n')) {
1811 /* The format is just "Commit Parent1 Parent2 ...\n" */
1812 - int len = strlen(buf);
1813 - struct commit_graft *graft = read_graft_line(buf, len);
1812 + struct commit_graft *graft = read_graft_line(buf.buf, buf.len);
1813 if (graft)
1814 register_commit_graft(graft, 0);
1815 }
1816 fclose(fp);
1817 + strbuf_release(&buf);
1818 return 0;
1819 }
1820
commit.c
+5 -5
@@ -196,19 +196,19 @@ bad_graft_data:
196 static int read_graft_file(const char *graft_file)
197 {
198 FILE *fp = fopen(graft_file, "r");
199 - char buf[1024];
199 + struct strbuf buf = STRBUF_INIT;
200 if (!fp)
201 return -1;
202 - while (fgets(buf, sizeof(buf), fp)) {
202 + while (!strbuf_getwholeline(&buf, fp, '\n')) {
203 /* The format is just "Commit Parent1 Parent2 ...\n" */
204 - int len = strlen(buf);
205 - struct commit_graft *graft = read_graft_line(buf, len);
204 + struct commit_graft *graft = read_graft_line(buf.buf, buf.len);
205 if (!graft)
206 continue;
207 if (register_commit_graft(graft, 1))
209 - error("duplicate graft data: %s", buf);
208 + error("duplicate graft data: %s", buf.buf);
209 }
210 fclose(fp);
211 + strbuf_release(&buf);
212 return 0;
213 }
214
t/annotate-tests.sh
+21
@@ -116,6 +116,27 @@ test_expect_success 'blame evil merge' '
116 check_count A 2 B 1 B1 2 B2 1 "A U Thor" 1
117 '
118
119 +test_expect_success 'blame huge graft' '
120 + test_when_finished "git checkout branch2" &&
121 + test_when_finished "rm -f .git/info/grafts" &&
122 + graft= &&
123 + for i in 0 1 2
124 + do
125 + for j in 0 1 2 3 4 5 6 7 8 9
126 + do
127 + git checkout --orphan "$i$j" &&
128 + printf "%s\n" "$i" "$j" >file &&
129 + test_tick &&
130 + GIT_AUTHOR_NAME=$i$j GIT_AUTHOR_EMAIL=$i$j@test.git \
131 + git commit -a -m "$i$j" &&
132 + commit=$(git rev-parse --verify HEAD) &&
133 + graft="$graft$commit "
134 + done
135 + done &&
136 + printf "%s " $graft >.git/info/grafts &&
137 + check_count -h 00 01 1 10 1
138 +'
139 +
140 test_expect_success 'setup incomplete line' '
141 echo "incomplete" | tr -d "\\012" >>file &&
142 GIT_AUTHOR_NAME="C" GIT_AUTHOR_EMAIL="C@test.git" \
t/t6101-rev-parse-parents.sh
+15 -1
@@ -20,7 +20,17 @@ test_expect_success 'setup' '
20 test_commit start2 &&
21 git checkout master &&
22 git merge -m next start2 &&
23 - test_commit final
23 + test_commit final &&
24 +
25 + test_seq 40 |
26 + while read i
27 + do
28 + git checkout --orphan "b$i" &&
29 + test_tick &&
30 + git commit --allow-empty -m "$i" &&
31 + commit=$(git rev-parse --verify HEAD) &&
32 + printf "$commit " >>.git/info/grafts
33 + done
34 '
35
36 test_expect_success 'start is valid' '
@@ -79,6 +89,10 @@ test_expect_success 'final^1^! = final^1 ^final^1^1 ^final^1^2' '
89 test_cmp expect actual
90 '
91
92 +test_expect_success 'large graft octopus' '
93 + test_cmp_rev_output b31 "git rev-parse --verify b1^30"
94 +'
95 +
96 test_expect_success 'repack for next test' '
97 git repack -a -d
98 '