Merge branch 'jk/pack-protocol-doc'
authorJunio C Hamano <gitster@pobox.com>
Mon, 14 Sep 2015 18:46:59 +0000 (11:46 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 14 Sep 2015 18:46:59 +0000 (11:46 -0700)
Streamline documentation of the pkt-line protocol.

* jk/pack-protocol-doc:
pack-protocol: clarify LF-handling in PKT-LINE()

19 files changed:
Documentation/RelNotes/2.2.3.txt [new file with mode: 0644]
Documentation/RelNotes/2.3.9.txt [new file with mode: 0644]
Documentation/RelNotes/2.4.9.txt [new file with mode: 0644]
Documentation/RelNotes/2.5.2.txt [new file with mode: 0644]
Documentation/RelNotes/2.6.0.txt
Documentation/git.txt
GIT-VERSION-GEN
builtin/am.c
builtin/apply.c
builtin/rerere.c
builtin/show-branch.c
git-svn.perl
notes.c
rerere.c
rerere.h
sha1_file.c
t/t4150-am.sh
t/t7060-wtstatus.sh
unpack-trees.c
diff --git a/Documentation/RelNotes/2.2.3.txt b/Documentation/RelNotes/2.2.3.txt
new file mode 100644 (file)
index 0000000..5bfffa4
--- /dev/null
@@ -0,0 +1,9 @@
+Git v2.2.3 Release Notes
+========================
+
+Fixes since v2.2.2
+------------------
+
+ * A handful of codepaths that used to use fixed-sized arrays to hold
+   pathnames have been corrected to use strbuf and other mechanisms to
+   allow longer pathnames without fearing overflows.
diff --git a/Documentation/RelNotes/2.3.9.txt b/Documentation/RelNotes/2.3.9.txt
new file mode 100644 (file)
index 0000000..1a2ad32
--- /dev/null
@@ -0,0 +1,9 @@
+Git v2.3.9 Release Notes
+========================
+
+Fixes since v2.3.8
+------------------
+
+ * A handful of codepaths that used to use fixed-sized arrays to hold
+   pathnames have been corrected to use strbuf and other mechanisms to
+   allow longer pathnames without fearing overflows.
diff --git a/Documentation/RelNotes/2.4.9.txt b/Documentation/RelNotes/2.4.9.txt
new file mode 100644 (file)
index 0000000..09af9dd
--- /dev/null
@@ -0,0 +1,9 @@
+Git v2.4.9 Release Notes
+========================
+
+Fixes since v2.4.9
+------------------
+
+ * A handful of codepaths that used to use fixed-sized arrays to hold
+   pathnames have been corrected to use strbuf and other mechanisms to
+   allow longer pathnames without fearing overflows.
diff --git a/Documentation/RelNotes/2.5.2.txt b/Documentation/RelNotes/2.5.2.txt
new file mode 100644 (file)
index 0000000..3f74939
--- /dev/null
@@ -0,0 +1,63 @@
+Git v2.5.2 Release Notes
+========================
+
+Fixes since v2.5.1
+------------------
+
+ * "git init empty && git -C empty log" said "bad default revision 'HEAD'",
+   which was found to be a bit confusing to new users.
+
+ * The "interpret-trailers" helper mistook a multi-paragraph title of
+   a commit log message with a colon in it as the end of the trailer
+   block.
+
+ * When re-priming the cache-tree opportunistically while committing
+   the in-core index as-is, we mistakenly invalidated the in-core
+   index too aggressively, causing the experimental split-index code
+   to unnecessarily rewrite the on-disk index file(s).
+
+ * "git archive" did not use zip64 extension when creating an archive
+   with more than 64k entries, which nobody should need, right ;-)?
+
+ * The code in "multiple-worktree" support that attempted to recover
+   from an inconsistent state updated an incorrect file.
+
+ * "git rev-list" does not take "--notes" option, but did not complain
+   when one is given.
+
+ * Because the configuration system does not allow "alias.0foo" and
+   "pager.0foo" as the configuration key, the user cannot use '0foo'
+   as a custom command name anyway, but "git 0foo" tried to look these
+   keys up and emitted useless warnings before saying '0foo is not a
+   git command'.  These warning messages have been squelched.
+
+ * We recently rewrote one of the build scripts in Perl, which made it
+   necessary to have Perl to build Git.  Reduced Perl dependency by
+   rewriting it again using sed.
+
+ * t1509 test that requires a dedicated VM environment had some
+   bitrot, which has been corrected.
+
+ * strbuf_read() used to have one extra iteration (and an unnecessary
+   strbuf_grow() of 8kB), which was eliminated.
+
+ * The codepath to produce error messages had a hard-coded limit to
+   the size of the message, primarily to avoid memory allocation while
+   calling die().
+
+ * When trying to see that an object does not exist, a state errno
+   leaked from our "first try to open a packfile with O_NOATIME and
+   then if it fails retry without it" logic on a system that refuses
+   O_NOATIME.  This confused us and caused us to die, saying that the
+   packfile is unreadable, when we should have just reported that the
+   object does not exist in that packfile to the caller.
+
+ * An off-by-one error made "git remote" to mishandle a remote with a
+   single letter nickname.
+
+ * A handful of codepaths that used to use fixed-sized arrays to hold
+   pathnames have been corrected to use strbuf and other mechanisms to
+   allow longer pathnames without fearing overflows.
+
+Also contains typofixes, documentation updates and trivial code
+clean-ups.
index eb79a1815d2f4d5e5474af374d73a3481d80fe38..870df859748de1526982661846978a52808cefc9 100644 (file)
@@ -56,7 +56,7 @@ UI, Workflows & Features
  * A negative !ref entry in multi-value transfer.hideRefs
    configuration can be used to say "don't hide this one".
 
- * After "git am" without "-3" stops, running "git am -" pays attention
+ * After "git am" without "-3" stops, running "git am -3" pays attention
    to "-3" only for the patch that caused the original invocation
    to stop.
 
index 4e5d55be6a2b5db801e651b054160b393e148576..75ffb16d965d7c5f5b04c8aa342e940566bf8d3c 100644 (file)
@@ -43,15 +43,17 @@ unreleased) version of Git, that is available from the 'master'
 branch of the `git.git` repository.
 Documentation for older releases are available here:
 
-* link:v2.5.1/git.html[documentation for release 2.5.1]
+* link:v2.5.2/git.html[documentation for release 2.5.2]
 
 * release notes for
+  link:RelNotes/2.5.2.txt[2.5.2],
   link:RelNotes/2.5.1.txt[2.5.1],
   link:RelNotes/2.5.0.txt[2.5].
 
-* link:v2.4.8/git.html[documentation for release 2.4.8]
+* link:v2.4.9/git.html[documentation for release 2.4.9]
 
 * release notes for
+  link:RelNotes/2.4.9.txt[2.4.9],
   link:RelNotes/2.4.8.txt[2.4.8],
   link:RelNotes/2.4.7.txt[2.4.7],
   link:RelNotes/2.4.6.txt[2.4.6],
@@ -62,9 +64,10 @@ Documentation for older releases are available here:
   link:RelNotes/2.4.1.txt[2.4.1],
   link:RelNotes/2.4.0.txt[2.4].
 
-* link:v2.3.8/git.html[documentation for release 2.3.8]
+* link:v2.3.9/git.html[documentation for release 2.3.9]
 
 * release notes for
+  link:RelNotes/2.3.9.txt[2.3.9],
   link:RelNotes/2.3.8.txt[2.3.8],
   link:RelNotes/2.3.7.txt[2.3.7],
   link:RelNotes/2.3.6.txt[2.3.6],
@@ -75,9 +78,10 @@ Documentation for older releases are available here:
   link:RelNotes/2.3.1.txt[2.3.1],
   link:RelNotes/2.3.0.txt[2.3].
 
-* link:v2.2.2/git.html[documentation for release 2.2.2]
+* link:v2.2.3/git.html[documentation for release 2.2.3]
 
 * release notes for
+  link:RelNotes/2.2.3.txt[2.2.3],
   link:RelNotes/2.2.2.txt[2.2.2],
   link:RelNotes/2.2.1.txt[2.2.1],
   link:RelNotes/2.2.0.txt[2.2].
index e19205a3f6b5fc3b0063edba0a22d7fb8cc8c3cb..181f397bd4537988fe68e997fb95279e86838ebc 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v2.6.0-rc0
+DEF_VER=v2.6.0-rc1
 
 LF='
 '
index 27165a6730ef04da2b4c22ee03eccadfa2e517b6..4f77e07b9549f8ff144d770fb0b66e9124ae4dc6 100644 (file)
@@ -1207,6 +1207,33 @@ static void NORETURN die_user_resolve(const struct am_state *state)
        exit(128);
 }
 
+static void am_signoff(struct strbuf *sb)
+{
+       char *cp;
+       struct strbuf mine = STRBUF_INIT;
+
+       /* Does it end with our own sign-off? */
+       strbuf_addf(&mine, "\n%s%s\n",
+                   sign_off_header,
+                   fmt_name(getenv("GIT_COMMITTER_NAME"),
+                            getenv("GIT_COMMITTER_EMAIL")));
+       if (mine.len < sb->len &&
+           !strcmp(mine.buf, sb->buf + sb->len - mine.len))
+               goto exit; /* no need to duplicate */
+
+       /* Does it have any Signed-off-by: in the text */
+       for (cp = sb->buf;
+            cp && *cp && (cp = strstr(cp, sign_off_header)) != NULL;
+            cp = strchr(cp, '\n')) {
+               if (sb->buf == cp || cp[-1] == '\n')
+                       break;
+       }
+
+       strbuf_addstr(sb, mine.buf + !!cp);
+exit:
+       strbuf_release(&mine);
+}
+
 /**
  * Appends signoff to the "msg" field of the am_state.
  */
@@ -1215,7 +1242,7 @@ static void am_append_signoff(struct am_state *state)
        struct strbuf sb = STRBUF_INIT;
 
        strbuf_attach(&sb, state->msg, state->msg_len, state->msg_len);
-       append_signoff(&sb, 0, 0);
+       am_signoff(&sb);
        state->msg = strbuf_detach(&sb, &state->msg_len);
 }
 
@@ -1319,7 +1346,7 @@ static int parse_mail(struct am_state *state, const char *mail)
        stripspace(&msg, 0);
 
        if (state->signoff)
-               append_signoff(&msg, 0, 0);
+               am_signoff(&msg);
 
        assert(!state->author_name);
        state->author_name = strbuf_detach(&author_name, NULL);
@@ -2057,11 +2084,6 @@ static int clean_index(const unsigned char *head, const unsigned char *remote)
 static void am_rerere_clear(void)
 {
        struct string_list merge_rr = STRING_LIST_INIT_DUP;
-       int fd = setup_rerere(&merge_rr, 0);
-
-       if (fd < 0)
-               return;
-
        rerere_clear(&merge_rr);
        string_list_clear(&merge_rr, 1);
 }
index 54aba4e351257f8bc4b46d3f507c1ed9525ec7fc..4aa53f7fd87d5fd23c0929360b6746f48e8e3e73 100644 (file)
@@ -785,7 +785,7 @@ static int guess_p_value(const char *nameline)
 }
 
 /*
- * Does the ---/+++ line has the POSIX timestamp after the last HT?
+ * Does the ---/+++ line have the POSIX timestamp after the last HT?
  * GNU diff puts epoch there to signal a creation/deletion event.  Is
  * this such a timestamp?
  */
index 7afadd2eadd59d8d3f4b77ad902bc24c94af9ec6..12535c9b4f48cd196943c1914fefee7c47cecec2 100644 (file)
@@ -50,7 +50,7 @@ static int diff_two(const char *file1, const char *label1,
 int cmd_rerere(int argc, const char **argv, const char *prefix)
 {
        struct string_list merge_rr = STRING_LIST_INIT_DUP;
-       int i, fd, autoupdate = -1, flags = 0;
+       int i, autoupdate = -1, flags = 0;
 
        struct option options[] = {
                OPT_SET_INT(0, "rerere-autoupdate", &autoupdate,
@@ -79,18 +79,16 @@ int cmd_rerere(int argc, const char **argv, const char *prefix)
                return rerere_forget(&pathspec);
        }
 
-       fd = setup_rerere(&merge_rr, flags);
-       if (fd < 0)
-               return 0;
-
        if (!strcmp(argv[0], "clear")) {
                rerere_clear(&merge_rr);
        } else if (!strcmp(argv[0], "gc"))
                rerere_gc(&merge_rr);
-       else if (!strcmp(argv[0], "status"))
+       else if (!strcmp(argv[0], "status")) {
+               if (setup_rerere(&merge_rr, flags | RERERE_READONLY) < 0)
+                       return 0;
                for (i = 0; i < merge_rr.nr; i++)
                        printf("%s\n", merge_rr.items[i].string);
-       else if (!strcmp(argv[0], "remaining")) {
+       else if (!strcmp(argv[0], "remaining")) {
                rerere_remaining(&merge_rr);
                for (i = 0; i < merge_rr.nr; i++) {
                        if (merge_rr.items[i].util != RERERE_RESOLVED)
@@ -100,13 +98,15 @@ int cmd_rerere(int argc, const char **argv, const char *prefix)
                                 * string_list_clear() */
                                merge_rr.items[i].util = NULL;
                }
-       } else if (!strcmp(argv[0], "diff"))
+       } else if (!strcmp(argv[0], "diff")) {
+               if (setup_rerere(&merge_rr, flags | RERERE_READONLY) < 0)
+                       return 0;
                for (i = 0; i < merge_rr.nr; i++) {
                        const char *path = merge_rr.items[i].string;
                        const char *name = (const char *)merge_rr.items[i].util;
                        diff_two(rerere_path(name, "preimage"), path, path, path);
                }
-       else
+       else
                usage_with_options(rerere_usage, options);
 
        string_list_clear(&merge_rr, 1);
index c87c46eb387a8093af92864081673be1a36b5999..408ce7030731f765228de93066a815bd4db59e30 100644 (file)
@@ -730,7 +730,6 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
 
        if (reflog) {
                struct object_id oid;
-               char nth_desc[256];
                char *ref;
                int base = 0;
                unsigned int flags = 0;
@@ -769,6 +768,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
 
                for (i = 0; i < reflog; i++) {
                        char *logmsg;
+                       char *nth_desc;
                        const char *msg;
                        unsigned long timestamp;
                        int tz;
@@ -788,8 +788,10 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
                                                          DATE_MODE(RELATIVE)),
                                                msg);
                        free(logmsg);
-                       sprintf(nth_desc, "%s@{%d}", *av, base+i);
+
+                       nth_desc = xstrfmt("%s@{%d}", *av, base+i);
                        append_ref(nth_desc, &oid, 1);
+                       free(nth_desc);
                }
                free(ref);
        }
index 36f7240c99249198512689ffecdd9c95f06b8eff..fa5f253065307499642cae63d93cdd5b5e16db0a 100755 (executable)
@@ -1924,7 +1924,7 @@ sub load_authors {
        my $log = $cmd eq 'log';
        while (<$authors>) {
                chomp;
-               next unless /^(.+?|\(no author\))\s*=\s*(.+?)\s*<(.+)>\s*$/;
+               next unless /^(.+?|\(no author\))\s*=\s*(.+?)\s*<(.*)>\s*$/;
                my ($user, $name, $email) = ($1, $2, $3);
                if ($log) {
                        $Git::SVN::Log::rusers{"$name <$email>"} = $user;
diff --git a/notes.c b/notes.c
index df08209dee498d624817f071d7e9ac5194d2334f..eacd2a61daf9b4133e81a936340abc63c1078a48 100644 (file)
--- a/notes.c
+++ b/notes.c
@@ -362,13 +362,14 @@ static int non_note_cmp(const struct non_note *a, const struct non_note *b)
        return strcmp(a->path, b->path);
 }
 
-static void add_non_note(struct notes_tree *t, const char *path,
+/* note: takes ownership of path string */
+static void add_non_note(struct notes_tree *t, char *path,
                unsigned int mode, const unsigned char *sha1)
 {
        struct non_note *p = t->prev_non_note, *n;
        n = (struct non_note *) xmalloc(sizeof(struct non_note));
        n->next = NULL;
-       n->path = xstrdup(path);
+       n->path = path;
        n->mode = mode;
        hashcpy(n->sha1, sha1);
        t->prev_non_note = n;
@@ -482,17 +483,17 @@ static void load_subtree(struct notes_tree *t, struct leaf_node *subtree,
                 * component.
                 */
                {
-                       char non_note_path[PATH_MAX];
-                       char *p = non_note_path;
+                       struct strbuf non_note_path = STRBUF_INIT;
                        const char *q = sha1_to_hex(subtree->key_sha1);
                        int i;
                        for (i = 0; i < prefix_len; i++) {
-                               *p++ = *q++;
-                               *p++ = *q++;
-                               *p++ = '/';
+                               strbuf_addch(&non_note_path, *q++);
+                               strbuf_addch(&non_note_path, *q++);
+                               strbuf_addch(&non_note_path, '/');
                        }
-                       strcpy(p, entry.path);
-                       add_non_note(t, non_note_path, entry.mode, entry.sha1);
+                       strbuf_addstr(&non_note_path, entry.path);
+                       add_non_note(t, strbuf_detach(&non_note_path, NULL),
+                                    entry.mode, entry.sha1);
                }
        }
        free(buf);
index 6a517aa383b75512ba77592616e084d74647b491..d90057b7695918e260e1778a522011dabaa3a37b 100644 (file)
--- a/rerere.c
+++ b/rerere.c
@@ -409,6 +409,8 @@ static int find_conflict(struct string_list *conflict)
 int rerere_remaining(struct string_list *merge_rr)
 {
        int i;
+       if (setup_rerere(merge_rr, RERERE_READONLY))
+               return 0;
        if (read_cache() < 0)
                return error("Could not read index");
 
@@ -603,8 +605,11 @@ int setup_rerere(struct string_list *merge_rr, int flags)
 
        if (flags & (RERERE_AUTOUPDATE|RERERE_NOAUTOUPDATE))
                rerere_autoupdate = !!(flags & RERERE_AUTOUPDATE);
-       fd = hold_lock_file_for_update(&write_lock, git_path_merge_rr(),
-                                      LOCK_DIE_ON_ERROR);
+       if (flags & RERERE_READONLY)
+               fd = 0;
+       else
+               fd = hold_lock_file_for_update(&write_lock, git_path_merge_rr(),
+                                              LOCK_DIE_ON_ERROR);
        read_rr(merge_rr);
        return fd;
 }
@@ -701,6 +706,9 @@ void rerere_gc(struct string_list *rr)
        int cutoff_noresolve = 15;
        int cutoff_resolve = 60;
 
+       if (setup_rerere(rr, 0) < 0)
+               return;
+
        git_config_get_int("gc.rerereresolved", &cutoff_resolve);
        git_config_get_int("gc.rerereunresolved", &cutoff_noresolve);
        git_config(git_default_config, NULL);
@@ -727,16 +735,21 @@ void rerere_gc(struct string_list *rr)
        for (i = 0; i < to_remove.nr; i++)
                unlink_rr_item(to_remove.items[i].string);
        string_list_clear(&to_remove, 0);
+       rollback_lock_file(&write_lock);
 }
 
 void rerere_clear(struct string_list *merge_rr)
 {
        int i;
 
+       if (setup_rerere(merge_rr, 0) < 0)
+               return;
+
        for (i = 0; i < merge_rr->nr; i++) {
                const char *name = (const char *)merge_rr->items[i].util;
                if (!has_rerere_resolution(name))
                        unlink_rr_item(name);
        }
        unlink_or_warn(git_path_merge_rr());
+       rollback_lock_file(&write_lock);
 }
index 2956c2edf2f0f88bd9fb15682e31e3478df44a03..407d59996d97ae307d5b4a124f78ef79666e1feb 100644 (file)
--- a/rerere.h
+++ b/rerere.h
@@ -7,6 +7,7 @@ struct pathspec;
 
 #define RERERE_AUTOUPDATE   01
 #define RERERE_NOAUTOUPDATE 02
+#define RERERE_READONLY     04
 
 /*
  * Marks paths that have been hand-resolved and added to the
index 08302f5857b8ad298809adf04a6bffc136f843a4..d295a3225a1e083708812f99746773d0ec8fdff4 100644 (file)
@@ -377,15 +377,12 @@ void read_info_alternates(const char * relative_base, int depth)
        char *map;
        size_t mapsz;
        struct stat st;
-       const char alt_file_name[] = "info/alternates";
-       /* Given that relative_base is no longer than PATH_MAX,
-          ensure that "path" has enough space to append "/", the
-          file name, "info/alternates", and a trailing NUL.  */
-       char path[PATH_MAX + 1 + sizeof alt_file_name];
+       char *path;
        int fd;
 
-       sprintf(path, "%s/%s", relative_base, alt_file_name);
+       path = xstrfmt("%s/info/alternates", relative_base);
        fd = git_open_noatime(path);
+       free(path);
        if (fd < 0)
                return;
        if (fstat(fd, &st) || (st.st_size == 0)) {
index dd627c42d3f5b73a088f91dd6ab8c1ce9ddcb88c..b41bd17264f93d54d5aa280fbc305cebb18950a0 100755 (executable)
@@ -873,4 +873,88 @@ test_expect_success 'am --message-id -s signs off after the message id' '
        test_cmp expected actual
 '
 
+test_expect_success 'am -3 works with rerere' '
+       rm -fr .git/rebase-apply &&
+       git reset --hard &&
+
+       # make patches one->two and two->three...
+       test_commit one file &&
+       test_commit two file &&
+       test_commit three file &&
+       git format-patch -2 --stdout >seq.patch &&
+
+       # and create a situation that conflicts...
+       git reset --hard one &&
+       test_commit other file &&
+
+       # enable rerere...
+       test_config rerere.enabled true &&
+       test_when_finished "rm -rf .git/rr-cache" &&
+
+       # ...and apply. Our resolution is to skip the first
+       # patch, and the rerere the second one.
+       test_must_fail git am -3 seq.patch &&
+       test_must_fail git am --skip &&
+       echo resolved >file &&
+       git add file &&
+       git am --resolved &&
+
+       # now apply again, and confirm that rerere engaged (we still
+       # expect failure from am because rerere does not auto-commit
+       # for us).
+       git reset --hard other &&
+       test_must_fail git am -3 seq.patch &&
+       test_must_fail git am --skip &&
+       echo resolved >expect &&
+       test_cmp expect file
+'
+
+test_expect_success 'am -s unexpected trailer block' '
+       rm -fr .git/rebase-apply &&
+       git reset --hard &&
+       echo signed >file &&
+       git add file &&
+       cat >msg <<-EOF &&
+       subject here
+
+       Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>
+       [jc: tweaked log message]
+       Signed-off-by: J C H <j@c.h>
+       EOF
+       git commit -F msg &&
+       git cat-file commit HEAD | sed -e '1,/^$/d' >original &&
+       git format-patch --stdout -1 >patch &&
+
+       git reset --hard HEAD^ &&
+       git am -s patch &&
+       (
+               cat original &&
+               echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
+       ) >expect &&
+       git cat-file commit HEAD | sed -e '1,/^$/d' >actual &&
+       test_cmp expect actual &&
+
+       cat >msg <<-\EOF &&
+       subject here
+
+       We make sure that there is a blank line between the log
+       message proper and Signed-off-by: line added.
+       EOF
+       git reset HEAD^ &&
+       git commit -F msg file &&
+       git cat-file commit HEAD | sed -e '1,/^$/d' >original &&
+       git format-patch --stdout -1 >patch &&
+
+       git reset --hard HEAD^ &&
+       git am -s patch &&
+
+       (
+               cat original &&
+               echo &&
+               echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
+       ) >expect &&
+       git cat-file commit HEAD | sed -e '1,/^$/d' >actual &&
+       test_cmp expect actual
+'
+
 test_done
index 741ec085767c9469f8ba15408af37cd558df1559..32d81765cb53718e5d26092ccfe970a503edfa02 100755 (executable)
@@ -106,7 +106,7 @@ test_expect_success 'git diff-index --cached -M shows 2 added + 1 unmerged' '
        A       THREE
        A       TWO
        EOF
-       git diff-index --cached --name-status HEAD >actual &&
+       git diff-index --cached -M --name-status HEAD >actual &&
        test_cmp expected actual
 '
 
index bb09b1ed27a6c973c93f5ec855973e277279549f..f932e80e862cfafb7b909059b460dcb688c6dc0b 100644 (file)
@@ -1451,15 +1451,18 @@ static int verify_absent_1(const struct cache_entry *ce,
        if (!len)
                return 0;
        else if (len > 0) {
-               char path[PATH_MAX + 1];
-               memcpy(path, ce->name, len);
-               path[len] = 0;
+               char *path;
+               int ret;
+
+               path = xmemdupz(ce->name, len);
                if (lstat(path, &st))
-                       return error("cannot stat '%s': %s", path,
+                       ret = error("cannot stat '%s': %s", path,
                                        strerror(errno));
-
-               return check_ok_to_remove(path, len, DT_UNKNOWN, NULL, &st,
-                               error_type, o);
+               else
+                       ret = check_ok_to_remove(path, len, DT_UNKNOWN, NULL,
+                                                &st, error_type, o);
+               free(path);
+               return ret;
        } else if (lstat(ce->name, &st)) {
                if (errno != ENOENT)
                        return error("cannot stat '%s': %s", ce->name,