]> Pileus Git - ~andy/git/commitdiff
Remove the line length limit for graft files
authorJohannes Schindelin <Johannes.Schindelin@gmx.de>
Fri, 27 Dec 2013 20:49:57 +0000 (21:49 +0100)
committerJunio C Hamano <gitster@pobox.com>
Sat, 28 Dec 2013 00:46:25 +0000 (16:46 -0800)
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>
builtin/blame.c
commit.c
t/annotate-tests.sh
t/t6101-rev-parse-parents.sh

index 1407ae7eb291ab7c0d00984d18820c955703e17f..9047b6ef4caa0aa5ca964cdfafdbc19985a3cb25 100644 (file)
@@ -1804,17 +1804,17 @@ static int prepare_lines(struct scoreboard *sb)
 static int read_ancestry(const char *graft_file)
 {
        FILE *fp = fopen(graft_file, "r");
-       char buf[1024];
+       struct strbuf buf = STRBUF_INIT;
        if (!fp)
                return -1;
-       while (fgets(buf, sizeof(buf), fp)) {
+       while (!strbuf_getwholeline(&buf, fp, '\n')) {
                /* The format is just "Commit Parent1 Parent2 ...\n" */
-               int len = strlen(buf);
-               struct commit_graft *graft = read_graft_line(buf, len);
+               struct commit_graft *graft = read_graft_line(buf.buf, buf.len);
                if (graft)
                        register_commit_graft(graft, 0);
        }
        fclose(fp);
+       strbuf_release(&buf);
        return 0;
 }
 
index de16a3c0a2d6693173678247ba0755e4d7483a1c..57ebea2aee30b00e86a620f7efc793420f214185 100644 (file)
--- a/commit.c
+++ b/commit.c
@@ -196,19 +196,19 @@ bad_graft_data:
 static int read_graft_file(const char *graft_file)
 {
        FILE *fp = fopen(graft_file, "r");
-       char buf[1024];
+       struct strbuf buf = STRBUF_INIT;
        if (!fp)
                return -1;
-       while (fgets(buf, sizeof(buf), fp)) {
+       while (!strbuf_getwholeline(&buf, fp, '\n')) {
                /* The format is just "Commit Parent1 Parent2 ...\n" */
-               int len = strlen(buf);
-               struct commit_graft *graft = read_graft_line(buf, len);
+               struct commit_graft *graft = read_graft_line(buf.buf, buf.len);
                if (!graft)
                        continue;
                if (register_commit_graft(graft, 1))
-                       error("duplicate graft data: %s", buf);
+                       error("duplicate graft data: %s", buf.buf);
        }
        fclose(fp);
+       strbuf_release(&buf);
        return 0;
 }
 
index c9d105d70725b9a97d5a9518e83c615821e91c23..304c7b7d8714f9f985cddcc91ba3006f668de127 100644 (file)
@@ -116,6 +116,27 @@ test_expect_success 'blame evil merge' '
        check_count A 2 B 1 B1 2 B2 1 "A U Thor" 1
 '
 
+test_expect_success 'blame huge graft' '
+       test_when_finished "git checkout branch2" &&
+       test_when_finished "rm -f .git/info/grafts" &&
+       graft= &&
+       for i in 0 1 2
+       do
+               for j in 0 1 2 3 4 5 6 7 8 9
+               do
+                       git checkout --orphan "$i$j" &&
+                       printf "%s\n" "$i" "$j" >file &&
+                       test_tick &&
+                       GIT_AUTHOR_NAME=$i$j GIT_AUTHOR_EMAIL=$i$j@test.git \
+                       git commit -a -m "$i$j" &&
+                       commit=$(git rev-parse --verify HEAD) &&
+                       graft="$graft$commit "
+               done
+       done &&
+       printf "%s " $graft >.git/info/grafts &&
+       check_count -h 00 01 1 10 1
+'
+
 test_expect_success 'setup incomplete line' '
        echo "incomplete" | tr -d "\\012" >>file &&
        GIT_AUTHOR_NAME="C" GIT_AUTHOR_EMAIL="C@test.git" \
index 7ea14ced313d3f0dd20d4afd2fc2a0d3309b938f..10b1452766b613932f66421f6c9bfafecc093177 100755 (executable)
@@ -20,7 +20,17 @@ test_expect_success 'setup' '
        test_commit start2 &&
        git checkout master &&
        git merge -m next start2 &&
-       test_commit final
+       test_commit final &&
+
+       test_seq 40 |
+       while read i
+       do
+               git checkout --orphan "b$i" &&
+               test_tick &&
+               git commit --allow-empty -m "$i" &&
+               commit=$(git rev-parse --verify HEAD) &&
+               printf "$commit " >>.git/info/grafts
+       done
 '
 
 test_expect_success 'start is valid' '
@@ -79,6 +89,10 @@ test_expect_success 'final^1^! = final^1 ^final^1^1 ^final^1^2' '
        test_cmp expect actual
 '
 
+test_expect_success 'large graft octopus' '
+       test_cmp_rev_output b31 "git rev-parse --verify b1^30"
+'
+
 test_expect_success 'repack for next test' '
        git repack -a -d
 '