Code

Merge branch 'tr/maint-bundle-long-subject' into maint-1.7.8
authorJunio C Hamano <gitster@pobox.com>
Mon, 9 Apr 2012 20:36:20 +0000 (13:36 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 9 Apr 2012 20:36:20 +0000 (13:36 -0700)
* tr/maint-bundle-long-subject:
  t5704: match tests to modern style
  strbuf: improve strbuf_get*line documentation
  bundle: use a strbuf to scan the log for boundary commits
  bundle: put strbuf_readline_fd in strbuf.c with adjustments

Documentation/technical/api-strbuf.txt
bundle.c
strbuf.c
strbuf.h
t/t5704-bundle.sh

index afe27599511c5f6bab6e4f799fd18e7d83bdd454..95a8bf3846b30650f3ee089a4fbadfcc5a42da20 100644 (file)
@@ -255,8 +255,24 @@ same behaviour as well.
 
 `strbuf_getline`::
 
-       Read a line from a FILE* pointer. The second argument specifies the line
+       Read a line from a FILE *, overwriting the existing contents
+       of the strbuf. The second argument specifies the line
        terminator character, typically `'\n'`.
+       Reading stops after the terminator or at EOF.  The terminator
+       is removed from the buffer before returning.  Returns 0 unless
+       there was nothing left before EOF, in which case it returns `EOF`.
+
+`strbuf_getwholeline`::
+
+       Like `strbuf_getline`, but keeps the trailing terminator (if
+       any) in the buffer.
+
+`strbuf_getwholeline_fd`::
+
+       Like `strbuf_getwholeline`, but operates on a file descriptor.
+       It reads one character at a time, so it is very slow.  Do not
+       use it unless you need the correct position in the file
+       descriptor.
 
 `stripspace`::
 
index 8a1d53ba29a434139123bd7d4e37db47ba8728cb..4497343e561437ef98d9c45d83a312e942eeeade 100644 (file)
--- a/bundle.c
+++ b/bundle.c
@@ -23,23 +23,6 @@ static void add_to_ref_list(const unsigned char *sha1, const char *name,
        list->nr++;
 }
 
-/* Eventually this should go to strbuf.[ch] */
-static int strbuf_readline_fd(struct strbuf *sb, int fd)
-{
-       strbuf_reset(sb);
-
-       while (1) {
-               char ch;
-               ssize_t len = xread(fd, &ch, 1);
-               if (len <= 0)
-                       return len;
-               strbuf_addch(sb, ch);
-               if (ch == '\n')
-                       break;
-       }
-       return 0;
-}
-
 static int parse_bundle_header(int fd, struct bundle_header *header,
                               const char *report_path)
 {
@@ -47,7 +30,7 @@ static int parse_bundle_header(int fd, struct bundle_header *header,
        int status = 0;
 
        /* The bundle header begins with the signature */
-       if (strbuf_readline_fd(&buf, fd) ||
+       if (strbuf_getwholeline_fd(&buf, fd, '\n') ||
            strcmp(buf.buf, bundle_signature)) {
                if (report_path)
                        error("'%s' does not look like a v2 bundle file",
@@ -57,7 +40,7 @@ static int parse_bundle_header(int fd, struct bundle_header *header,
        }
 
        /* The bundle header ends with an empty line */
-       while (!strbuf_readline_fd(&buf, fd) &&
+       while (!strbuf_getwholeline_fd(&buf, fd, '\n') &&
               buf.len && buf.buf[0] != '\n') {
                unsigned char sha1[20];
                int is_prereq = 0;
@@ -251,7 +234,7 @@ int create_bundle(struct bundle_header *header, const char *path,
        const char **argv_boundary = xmalloc((argc + 4) * sizeof(const char *));
        const char **argv_pack = xmalloc(6 * sizeof(const char *));
        int i, ref_count = 0;
-       char buffer[1024];
+       struct strbuf buf = STRBUF_INIT;
        struct rev_info revs;
        struct child_process rls;
        FILE *rls_fout;
@@ -283,20 +266,21 @@ int create_bundle(struct bundle_header *header, const char *path,
        if (start_command(&rls))
                return -1;
        rls_fout = xfdopen(rls.out, "r");
-       while (fgets(buffer, sizeof(buffer), rls_fout)) {
+       while (strbuf_getwholeline(&buf, rls_fout, '\n') != EOF) {
                unsigned char sha1[20];
-               if (buffer[0] == '-') {
-                       write_or_die(bundle_fd, buffer, strlen(buffer));
-                       if (!get_sha1_hex(buffer + 1, sha1)) {
+               if (buf.len > 0 && buf.buf[0] == '-') {
+                       write_or_die(bundle_fd, buf.buf, buf.len);
+                       if (!get_sha1_hex(buf.buf + 1, sha1)) {
                                struct object *object = parse_object(sha1);
                                object->flags |= UNINTERESTING;
-                               add_pending_object(&revs, object, buffer);
+                               add_pending_object(&revs, object, buf.buf);
                        }
-               } else if (!get_sha1_hex(buffer, sha1)) {
+               } else if (!get_sha1_hex(buf.buf, sha1)) {
                        struct object *object = parse_object(sha1);
                        object->flags |= SHOWN;
                }
        }
+       strbuf_release(&buf);
        fclose(rls_fout);
        if (finish_command(&rls))
                return error("rev-list died");
index 3ad2cc00160fbf24e1e4904bb37ce44e8c414ce5..692cf1bd9a5e7d97d68eb44722afbdd1b59d2cda 100644 (file)
--- a/strbuf.c
+++ b/strbuf.c
@@ -383,6 +383,22 @@ int strbuf_getline(struct strbuf *sb, FILE *fp, int term)
        return 0;
 }
 
+int strbuf_getwholeline_fd(struct strbuf *sb, int fd, int term)
+{
+       strbuf_reset(sb);
+
+       while (1) {
+               char ch;
+               ssize_t len = xread(fd, &ch, 1);
+               if (len <= 0)
+                       return EOF;
+               strbuf_addch(sb, ch);
+               if (ch == term)
+                       break;
+       }
+       return 0;
+}
+
 int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint)
 {
        int fd, len;
index 46a33f8c46985c4377071011d6ea48d6d3fe5331..e42dbe5ac8e632d268916bfbfc2f830159f4a760 100644 (file)
--- a/strbuf.h
+++ b/strbuf.h
@@ -108,6 +108,7 @@ extern int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint);
 
 extern int strbuf_getwholeline(struct strbuf *, FILE *, int);
 extern int strbuf_getline(struct strbuf *, FILE *, int);
+extern int strbuf_getwholeline_fd(struct strbuf *, int, int);
 
 extern void stripspace(struct strbuf *buf, int skip_comments);
 extern int launch_editor(const char *path, struct strbuf *buffer, const char *const *env);
index 4ae127d106c4a8ada0cea928affeff933bf0dbaa..a51c8b0560f85d31dc73d40a58ae3e4c6655f140 100755 (executable)
@@ -4,59 +4,58 @@ test_description='some bundle related tests'
 . ./test-lib.sh
 
 test_expect_success 'setup' '
-
-       : > file &&
-       git add file &&
-       test_tick &&
-       git commit -m initial &&
+       test_commit initial &&
        test_tick &&
        git tag -m tag tag &&
-       : > file2 &&
-       git add file2 &&
-       : > file3 &&
-       test_tick &&
-       git commit -m second &&
-       git add file3 &&
-       test_tick &&
-       git commit -m third
-
+       test_commit second &&
+       test_commit third &&
+       git tag -d initial &&
+       git tag -d second &&
+       git tag -d third
 '
 
 test_expect_success 'tags can be excluded by rev-list options' '
-
        git bundle create bundle --all --since=7.Apr.2005.15:16:00.-0700 &&
        git ls-remote bundle > output &&
        ! grep tag output
-
 '
 
 test_expect_success 'die if bundle file cannot be created' '
-
        mkdir adir &&
        test_must_fail git bundle create adir --all
-
 '
 
 test_expect_failure 'bundle --stdin' '
-
        echo master | git bundle create stdin-bundle.bdl --stdin &&
        git ls-remote stdin-bundle.bdl >output &&
        grep master output
-
 '
 
 test_expect_failure 'bundle --stdin <rev-list options>' '
-
        echo master | git bundle create hybrid-bundle.bdl --stdin tag &&
        git ls-remote hybrid-bundle.bdl >output &&
        grep master output
-
 '
 
 test_expect_success 'empty bundle file is rejected' '
+       : >empty-bundle &&
+       test_must_fail git fetch empty-bundle
+'
 
-    >empty-bundle && test_must_fail git fetch empty-bundle
-
+# This triggers a bug in older versions where the resulting line (with
+# --pretty=oneline) was longer than a 1024-char buffer.
+test_expect_success 'ridiculously long subject in boundary' '
+       : >file4 &&
+       test_tick &&
+       git add file4 &&
+       printf "%01200d\n" 0 | git commit -F - &&
+       test_commit fifth &&
+       git bundle create long-subject-bundle.bdl HEAD^..HEAD &&
+       git bundle list-heads long-subject-bundle.bdl >heads &&
+       test -s heads &&
+       git fetch long-subject-bundle.bdl &&
+       sed -n "/^-/{p;q}" long-subject-bundle.bdl >boundary &&
+       grep "^-$_x40 " boundary
 '
 
 test_done