Merge branch 'ss/clone-guess-dir-name-simplify' into maint
authorJunio C Hamano <gitster@pobox.com>
Mon, 3 Aug 2015 17:41:33 +0000 (10:41 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 3 Aug 2015 17:41:33 +0000 (10:41 -0700)
Code simplification.

* ss/clone-guess-dir-name-simplify:
clone: simplify string handling in guess_dir_name()

45 files changed:
Documentation/RelNotes/2.4.6.txt [new file with mode: 0644]
Documentation/RelNotes/2.4.7.txt [new file with mode: 0644]
Documentation/git-branch.txt
Documentation/git-checkout.txt
Documentation/git-describe.txt
Documentation/git-format-patch.txt
Documentation/git-rev-list.txt
Documentation/git.txt
Documentation/pretty-options.txt
GIT-VERSION-GEN
RelNotes
builtin/for-each-ref.c
builtin/fsck.c
builtin/index-pack.c
builtin/log.c
builtin/rev-list.c
cache.h
config.c
contrib/completion/git-completion.bash
contrib/completion/git-completion.tcsh
contrib/completion/git-prompt.sh
contrib/hooks/pre-auto-gc-battery
ewah/bitmap.c
ewah/ewah_bitmap.c
ewah/ewok.h
fetch-pack.c
fsck.c
git-am.sh
git-rebase--am.sh
http.c
pack-bitmap.c
pager.c
refs.c
sha1_file.c
strbuf.c
strbuf.h
t/t0302-credential-store.sh
t/t4014-format-patch.sh
t/t4151-am-abort.sh
t/t5310-pack-bitmaps.sh
t/t6301-for-each-ref-errors.sh [new file with mode: 0755]
t/t7502-commit.sh
t/test-lib.sh
utf8.h
wt-status.c
diff --git a/Documentation/RelNotes/2.4.6.txt b/Documentation/RelNotes/2.4.6.txt
new file mode 100644 (file)
index 0000000..b53f353
--- /dev/null
@@ -0,0 +1,23 @@
+Git v2.4.6 Release Notes
+========================
+
+Fixes since v2.4.5
+------------------
+
+ * "git fetch --depth=<depth>" and "git clone --depth=<depth>" issued
+   a shallow transfer request even to an upload-pack that does not
+   support the capability.
+
+ * "git fsck" used to ignore missing or invalid objects recorded in reflog.
+
+ * The tcsh completion writes a bash scriptlet but that would have
+   failed for users with noclobber set.
+
+ * Recent Mac OS X updates breaks the logic to detect that the machine
+   is on the AC power in the sample pre-auto-gc script.
+
+ * "git format-patch --ignore-if-upstream A..B" did not like to be fed
+   tags as boundary commits.
+
+Also contains typofixes, documentation updates and trivial code
+clean-ups.
diff --git a/Documentation/RelNotes/2.4.7.txt b/Documentation/RelNotes/2.4.7.txt
new file mode 100644 (file)
index 0000000..b3ac412
--- /dev/null
@@ -0,0 +1,53 @@
+Git v2.4.7 Release Notes
+========================
+
+Fixes since v2.4.6
+------------------
+
+ * A minor regression to "git fsck" in v2.2 era was fixed; it
+   complained about a body-less tag object when it lacked a
+   separator empty line after its header to separate it with a
+   non-existent body.
+
+ * We used to ask libCURL to use the most secure authentication method
+   available when talking to an HTTP proxy only when we were told to
+   talk to one via configuration variables.  We now ask libCURL to
+   always use the most secure authentication method, because the user
+   can tell libCURL to use an HTTP proxy via an environment variable
+   without using configuration variables.
+
+ * When you say "!<ENTER>" while running say "git log", you'd confuse
+   yourself in the resulting shell, that may look as if you took
+   control back to the original shell you spawned "git log" from but
+   that isn't what is happening.  To that new shell, we leaked
+   GIT_PAGER_IN_USE environment variable that was meant as a local
+   communication between the original "Git" and subprocesses that was
+   spawned by it after we launched the pager, which caused many
+   "interesting" things to happen, e.g. "git diff | cat" still paints
+   its output in color by default.
+
+   Stop leaking that environment variable to the pager's half of the
+   fork; we only need it on "Git" side when we spawn the pager.
+
+ * Avoid possible ssize_t to int truncation.
+
+ * "git config" failed to update the configuration file when the
+   underlying filesystem is incapable of renaming a file that is still
+   open.
+
+ * A minor bugfix when pack bitmap is used with "rev-list --count".
+
+ * An ancient test framework enhancement to allow color was not
+   entirely correct; this makes it work even when tput needs to read
+   from the ~/.terminfo under the user's real HOME directory.
+
+ * Fix a small bug in our use of umask() return value.
+
+ * "git rebase" did not exit with failure when format-patch it invoked
+   failed for whatever reason.
+
+ * Disable "have we lost a race with competing repack?" check while
+   receiving a huge object transfer that runs index-pack.
+
+Also contains typofixes, documentation updates and trivial code
+clean-ups.
index 359619b5527a8211c71eca029d0341b7fe6d548f..a67138a022f1ba2e621601fda4852a6026d23f6f 100644 (file)
@@ -81,7 +81,7 @@ OPTIONS
        `--track` or `--set-upstream`.
 
 -D::
-       Delete a branch irrespective of its merged status.
+       Shortcut for `--delete --force`.
 
 -l::
 --create-reflog::
@@ -95,13 +95,17 @@ OPTIONS
 --force::
        Reset <branchname> to <startpoint> if <branchname> exists
        already. Without `-f` 'git branch' refuses to change an existing branch.
+       In combination with `-d` (or `--delete`), allow deleting the
+       branch irrespective of its merged status. In combination with
+       `-m` (or `--move`), allow renaming the branch even if the new
+       branch name already exists.
 
 -m::
 --move::
        Move/rename a branch and the corresponding reflog.
 
 -M::
-       Move/rename a branch even if the new branch name already exists.
+       Shortcut for `--move --force`.
 
 --color[=<when>]::
        Color branches to highlight current, local, and
index d5041082e88349d7c814ae1c036b15841f47a6d0..7540e026f5ad16c3e88437d0d50b8fabd88885a4 100644 (file)
@@ -3,7 +3,7 @@ git-checkout(1)
 
 NAME
 ----
-git-checkout - Checkout a branch or paths to the working tree
+git-checkout - Switch branches or restore working tree files
 
 SYNOPSIS
 --------
@@ -89,6 +89,10 @@ Omitting <branch> detaches HEAD at the tip of the current branch.
        (i.e.  commit, tag or tree) to update the index for the given
        paths before updating the working tree.
 +
+'git checkout' with <paths> or `--patch` is used to restore modified or
+deleted paths to their original contents from the index or replace paths
+with the contents from a named <tree-ish> (most often a commit-ish).
++
 The index may contain unmerged entries because of a previous failed merge.
 By default, if you try to check out such an entry from the index, the
 checkout operation will fail and nothing will be checked out.
index d20ca402a11d29cb35efa9d291755c4f9f08bf21..e045fc73f88ae63a20c18af1b146dc1211a266ec 100644 (file)
@@ -3,7 +3,7 @@ git-describe(1)
 
 NAME
 ----
-git-describe - Show the most recent tag that is reachable from a commit
+git-describe - Describe a commit using the most recent tag reachable from it
 
 
 SYNOPSIS
index bb3ea9372f873ee50c3c6fb4092cd95ebbba3312..0dac4e9b86150ef2546b9fca02e211db6e667dcc 100644 (file)
@@ -170,7 +170,7 @@ will want to ensure that threading is disabled for `git send-email`.
 -v <n>::
 --reroll-count=<n>::
        Mark the series as the <n>-th iteration of the topic. The
-       output filenames have `v<n>` pretended to them, and the
+       output filenames have `v<n>` prepended to them, and the
        subject prefix ("PATCH" by default, but configurable via the
        `--subject-prefix` option) has ` v<n>` appended to it.  E.g.
        `--reroll-count=4` may produce `v4-0001-add-makefile.patch`
index b10ea60833ca67ca1d3c5bd413958980405575d4..7b49c85347ec583c4d9849a3f0bc878d776e9519 100644 (file)
@@ -56,6 +56,7 @@ SYNOPSIS
             [ --reverse ]
             [ --walk-reflogs ]
             [ --no-walk ] [ --do-walk ]
+            [ --count ]
             [ --use-bitmap-index ]
             <commit>... [ \-- <paths>... ]
 
index a4a4cf39b2c07e17c5859afe5dcd8937504fa744..bd298a4d288319baf45563103f94d9d9959a045d 100644 (file)
@@ -43,9 +43,11 @@ 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.4.5/git.html[documentation for release 2.4.5]
+* link:v2.4.7/git.html[documentation for release 2.4.7]
 
 * release notes for
+  link:RelNotes/2.4.7.txt[2.4.7],
+  link:RelNotes/2.4.6.txt[2.4.6],
   link:RelNotes/2.4.5.txt[2.4.5],
   link:RelNotes/2.4.4.txt[2.4.4],
   link:RelNotes/2.4.3.txt[2.4.3],
index 74aa01a0ec27b6cc0fbb9763b8e583a3f996da25..642af6e42684602f5465fc3c61d83ca6309b34cb 100644 (file)
@@ -37,7 +37,10 @@ people using 80-column terminals.
        in their encoding header; this option can be used to tell the
        command to re-code the commit log message in the encoding
        preferred by the user.  For non plumbing commands this
-       defaults to UTF-8.
+       defaults to UTF-8. Note that if an object claims to be encoded
+       in `X` and we are outputting in `X`, we will output the object
+       verbatim; this means that invalid sequences in the original
+       commit may be copied to the output.
 
 --notes[=<ref>]::
        Show the notes (see linkgit:git-notes[1]) that annotate the
index 159d52645be19ba2f25e54dba12f5a90638d66c9..b767c3acc9ba35ff698b19b3c44b61e27263d21a 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v2.4.5
+DEF_VER=v2.4.7
 
 LF='
 '
index 7b5f2ec4d626ec0e07faa2fbdf19563174190ce9..ee13f439fb73598668f70c571c0df38e164b4d42 120000 (symlink)
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/2.4.5.txt
\ No newline at end of file
+Documentation/RelNotes/2.4.7.txt
\ No newline at end of file
index 83f9cf91633a514e9301762fe774ee91be092848..13d217240a641586f9dc48bb5d85ea8104224aba 100644 (file)
@@ -851,6 +851,11 @@ static int grab_single_ref(const char *refname, const unsigned char *sha1, int f
                  return 0;
        }
 
+       if (flag & REF_ISBROKEN) {
+                 warning("ignoring broken ref %s", refname);
+                 return 0;
+       }
+
        if (*cb->grab_pattern) {
                const char **pattern;
                int namelen = strlen(refname);
index 0c757862e8cd414c087b27a608281b66c8608a4b..6b6f31997ccb8b00d4bb7f1a41fb831238ee7554 100644 (file)
@@ -451,34 +451,40 @@ static void fsck_dir(int i, char *path)
 
 static int default_refs;
 
+static void fsck_handle_reflog_sha1(const char *refname, unsigned char *sha1)
+{
+       struct object *obj;
+
+       if (!is_null_sha1(sha1)) {
+               obj = lookup_object(sha1);
+               if (obj) {
+                       obj->used = 1;
+                       mark_object_reachable(obj);
+               } else {
+                       error("%s: invalid reflog entry %s", refname, sha1_to_hex(sha1));
+                       errors_found |= ERROR_REACHABLE;
+               }
+       }
+}
+
 static int fsck_handle_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
                const char *email, unsigned long timestamp, int tz,
                const char *message, void *cb_data)
 {
-       struct object *obj;
+       const char *refname = cb_data;
 
        if (verbose)
                fprintf(stderr, "Checking reflog %s->%s\n",
                        sha1_to_hex(osha1), sha1_to_hex(nsha1));
 
-       if (!is_null_sha1(osha1)) {
-               obj = lookup_object(osha1);
-               if (obj) {
-                       obj->used = 1;
-                       mark_object_reachable(obj);
-               }
-       }
-       obj = lookup_object(nsha1);
-       if (obj) {
-               obj->used = 1;
-               mark_object_reachable(obj);
-       }
+       fsck_handle_reflog_sha1(refname, osha1);
+       fsck_handle_reflog_sha1(refname, nsha1);
        return 0;
 }
 
 static int fsck_handle_reflog(const char *logname, const unsigned char *sha1, int flag, void *cb_data)
 {
-       for_each_reflog_ent(logname, fsck_handle_reflog_ent, NULL);
+       for_each_reflog_ent(logname, fsck_handle_reflog_ent, (void *)logname);
        return 0;
 }
 
index cf654df09b3734063f415b2b735f3062706f75a0..723fe8e11d1d494a82f50caac1434dba7682962c 100644 (file)
@@ -730,7 +730,7 @@ static void sha1_object(const void *data, struct object_entry *obj_entry,
        assert(data || obj_entry);
 
        read_lock();
-       collision_test_needed = has_sha1_file(sha1);
+       collision_test_needed = has_sha1_file_with_flags(sha1, HAS_SHA1_QUICK);
        read_unlock();
 
        if (collision_test_needed && !data) {
index 4c4e6be28c85756d73eaefa3c8be6264c795fdcc..7b343c1aaf03cbcf442217a46660f9297ae82263 100644 (file)
@@ -795,7 +795,7 @@ static int reopen_stdout(struct commit *commit, const char *subject,
 static void get_patch_ids(struct rev_info *rev, struct patch_ids *ids)
 {
        struct rev_info check_rev;
-       struct commit *commit;
+       struct commit *commit, *c1, *c2;
        struct object *o1, *o2;
        unsigned flags1, flags2;
 
@@ -803,9 +803,11 @@ static void get_patch_ids(struct rev_info *rev, struct patch_ids *ids)
                die(_("Need exactly one range."));
 
        o1 = rev->pending.objects[0].item;
-       flags1 = o1->flags;
        o2 = rev->pending.objects[1].item;
+       flags1 = o1->flags;
        flags2 = o2->flags;
+       c1 = lookup_commit_reference(o1->sha1);
+       c2 = lookup_commit_reference(o2->sha1);
 
        if ((flags1 & UNINTERESTING) == (flags2 & UNINTERESTING))
                die(_("Not a range."));
@@ -827,10 +829,8 @@ static void get_patch_ids(struct rev_info *rev, struct patch_ids *ids)
        }
 
        /* reset for next revision walk */
-       clear_commit_marks((struct commit *)o1,
-                       SEEN | UNINTERESTING | SHOWN | ADDED);
-       clear_commit_marks((struct commit *)o2,
-                       SEEN | UNINTERESTING | SHOWN | ADDED);
+       clear_commit_marks(c1, SEEN | UNINTERESTING | SHOWN | ADDED);
+       clear_commit_marks(c2, SEEN | UNINTERESTING | SHOWN | ADDED);
        o1->flags = flags1;
        o2->flags = flags2;
 }
index ff84a825ff776abc01087f37782223ee26a1af7a..c0b4b53652a39049ec06ba69f2dfc50a8c0873f7 100644 (file)
@@ -42,6 +42,7 @@ static const char rev_list_usage[] =
 "    --abbrev=<n> | --no-abbrev\n"
 "    --abbrev-commit\n"
 "    --left-right\n"
+"    --count\n"
 "  special purpose:\n"
 "    --bisect\n"
 "    --bisect-vars\n"
@@ -355,7 +356,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
        if (bisect_list)
                revs.limited = 1;
 
-       if (use_bitmap_index) {
+       if (use_bitmap_index && !revs.prune) {
                if (revs.count && !revs.left_right && !revs.cherry_mark) {
                        uint32_t commit_count;
                        if (!prepare_bitmap_walk(&revs)) {
diff --git a/cache.h b/cache.h
index badf3da3405dab75ecb03b6fa2e885182ba56475..4427945bc08be2d182b123ce5f684d23304582d9 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -901,8 +901,17 @@ extern int has_sha1_pack(const unsigned char *sha1);
  * Return true iff we have an object named sha1, whether local or in
  * an alternate object database, and whether packed or loose.  This
  * function does not respect replace references.
+ *
+ * If the QUICK flag is set, do not re-check the pack directory
+ * when we cannot find the object (this means we may give a false
+ * negative answer if another process is simultaneously repacking).
  */
-extern int has_sha1_file(const unsigned char *sha1);
+#define HAS_SHA1_QUICK 0x1
+extern int has_sha1_file_with_flags(const unsigned char *sha1, int flags);
+static inline int has_sha1_file(const unsigned char *sha1)
+{
+       return has_sha1_file_with_flags(sha1, 0);
+}
 
 /*
  * Return true iff an alternate object database has a loose object
index 27a73c85005fbf709d47adb1458bea688993eba2..69824ebddbdf46660fa6f1ef481add949820d52c 100644 (file)
--- a/config.c
+++ b/config.c
@@ -2116,6 +2116,9 @@ int git_config_set_multivar_in_file(const char *config_filename,
                                          contents_sz - copy_begin) <
                            contents_sz - copy_begin)
                                goto write_err_out;
+
+               munmap(contents, contents_sz);
+               contents = NULL;
        }
 
        if (commit_lock_file(lock) < 0) {
index eae9dce590e0000eb93e441106ef6538c07e86cc..3b1a9b1d4f60819a4009a320e0dde107ebab8365 100644 (file)
@@ -1114,7 +1114,7 @@ _git_commit ()
 
        case "$cur" in
        --cleanup=*)
-               __gitcomp "default strip verbatim whitespace
+               __gitcomp "default scissors strip verbatim whitespace
                        " "" "${cur##--cleanup=}"
                return
                ;;
index 6104a42a23c4f38848a34c5c212bd7b74de81ab4..4a790d8f4ec18e0bfedbc7f8ce9f2d4291c284e4 100644 (file)
@@ -41,7 +41,7 @@ if ( ! -e ${__git_tcsh_completion_original_script} ) then
        exit
 endif
 
-cat << EOF > ${__git_tcsh_completion_script}
+cat << EOF >! ${__git_tcsh_completion_script}
 #!bash
 #
 # This script is GENERATED and will be overwritten automatically.
index f18aedc73be9daf4aab564beecb7bae29ea759c9..366f0bc1e9b5597f1714574700452cd241c14f8d 100644 (file)
 #     git           always compare HEAD to @{upstream}
 #     svn           always compare HEAD to your SVN upstream
 #
+# You can change the separator between the branch name and the above
+# state symbols by setting GIT_PS1_STATESEPARATOR. The default separator
+# is SP.
+#
 # By default, __git_ps1 will compare HEAD to your SVN upstream if it can
 # find one, or @{upstream} otherwise.  Once you have set
 # GIT_PS1_SHOWUPSTREAM, you can override it on a per-repository basis by
index 9d0c2d1990f813da5e3c8ffa7328cce46c32aae7..6a2cdebdb78c5d9d5a507635f748bda7b2be676d 100755 (executable)
@@ -33,7 +33,7 @@ elif grep -q "AC Power \+: 1" /proc/pmu/info 2>/dev/null
 then
        exit 0
 elif test -x /usr/bin/pmset && /usr/bin/pmset -g batt |
-       grep -q "Currently drawing from 'AC Power'"
+       grep -q "drawing from 'AC Power'"
 then
        exit 0
 fi
index 710e58c1bfc652d5f01b47cba5016d2e2f91f590..47ad6747c415372da89fa7c88dd8ce03b2765676 100644 (file)
@@ -20,8 +20,8 @@
 #include "git-compat-util.h"
 #include "ewok.h"
 
-#define MASK(x) ((eword_t)1 << (x % BITS_IN_WORD))
-#define BLOCK(x) (x / BITS_IN_WORD)
+#define EWAH_MASK(x) ((eword_t)1 << (x % BITS_IN_EWORD))
+#define EWAH_BLOCK(x) (x / BITS_IN_EWORD)
 
 struct bitmap *bitmap_new(void)
 {
@@ -33,7 +33,7 @@ struct bitmap *bitmap_new(void)
 
 void bitmap_set(struct bitmap *self, size_t pos)
 {
-       size_t block = BLOCK(pos);
+       size_t block = EWAH_BLOCK(pos);
 
        if (block >= self->word_alloc) {
                size_t old_size = self->word_alloc;
@@ -45,22 +45,22 @@ void bitmap_set(struct bitmap *self, size_t pos)
                        (self->word_alloc - old_size) * sizeof(eword_t));
        }
 
-       self->words[block] |= MASK(pos);
+       self->words[block] |= EWAH_MASK(pos);
 }
 
 void bitmap_clear(struct bitmap *self, size_t pos)
 {
-       size_t block = BLOCK(pos);
+       size_t block = EWAH_BLOCK(pos);
 
        if (block < self->word_alloc)
-               self->words[block] &= ~MASK(pos);
+               self->words[block] &= ~EWAH_MASK(pos);
 }
 
 int bitmap_get(struct bitmap *self, size_t pos)
 {
-       size_t block = BLOCK(pos);
+       size_t block = EWAH_BLOCK(pos);
        return block < self->word_alloc &&
-               (self->words[block] & MASK(pos)) != 0;
+               (self->words[block] & EWAH_MASK(pos)) != 0;
 }
 
 struct ewah_bitmap *bitmap_to_ewah(struct bitmap *bitmap)
@@ -127,7 +127,7 @@ void bitmap_and_not(struct bitmap *self, struct bitmap *other)
 void bitmap_or_ewah(struct bitmap *self, struct ewah_bitmap *other)
 {
        size_t original_size = self->word_alloc;
-       size_t other_final = (other->bit_size / BITS_IN_WORD) + 1;
+       size_t other_final = (other->bit_size / BITS_IN_EWORD) + 1;
        size_t i = 0;
        struct ewah_iterator it;
        eword_t word;
@@ -155,17 +155,17 @@ void bitmap_each_bit(struct bitmap *self, ewah_callback callback, void *data)
                uint32_t offset;
 
                if (word == (eword_t)~0) {
-                       for (offset = 0; offset < BITS_IN_WORD; ++offset)
+                       for (offset = 0; offset < BITS_IN_EWORD; ++offset)
                                callback(pos++, data);
                } else {
-                       for (offset = 0; offset < BITS_IN_WORD; ++offset) {
+                       for (offset = 0; offset < BITS_IN_EWORD; ++offset) {
                                if ((word >> offset) == 0)
                                        break;
 
                                offset += ewah_bit_ctz64(word >> offset);
                                callback(pos + offset, data);
                        }
-                       pos += BITS_IN_WORD;
+                       pos += BITS_IN_EWORD;
                }
        }
 }
index fccb42b52cbcbbfd2b5ec9f7f535f2e82a327090..b522437c0a0b1ba4906feadeb734542ec941b49a 100644 (file)
@@ -102,7 +102,7 @@ size_t ewah_add_empty_words(struct ewah_bitmap *self, int v, size_t number)
        if (number == 0)
                return 0;
 
-       self->bit_size += number * BITS_IN_WORD;
+       self->bit_size += number * BITS_IN_EWORD;
        return add_empty_words(self, v, number);
 }
 
@@ -152,7 +152,7 @@ void ewah_add_dirty_words(
                        self->buffer_size += can_add;
                }
 
-               self->bit_size += can_add * BITS_IN_WORD;
+               self->bit_size += can_add * BITS_IN_EWORD;
 
                if (number - can_add == 0)
                        break;
@@ -197,7 +197,7 @@ static size_t add_empty_word(struct ewah_bitmap *self, int v)
 
 size_t ewah_add(struct ewah_bitmap *self, eword_t word)
 {
-       self->bit_size += BITS_IN_WORD;
+       self->bit_size += BITS_IN_EWORD;
 
        if (word == 0)
                return add_empty_word(self, 0);
@@ -211,8 +211,8 @@ size_t ewah_add(struct ewah_bitmap *self, eword_t word)
 void ewah_set(struct ewah_bitmap *self, size_t i)
 {
        const size_t dist =
-               (i + BITS_IN_WORD) / BITS_IN_WORD -
-               (self->bit_size + BITS_IN_WORD - 1) / BITS_IN_WORD;
+               (i + BITS_IN_EWORD) / BITS_IN_EWORD -
+               (self->bit_size + BITS_IN_EWORD - 1) / BITS_IN_EWORD;
 
        assert(i >= self->bit_size);
 
@@ -222,19 +222,19 @@ void ewah_set(struct ewah_bitmap *self, size_t i)
                if (dist > 1)
                        add_empty_words(self, 0, dist - 1);
 
-               add_literal(self, (eword_t)1 << (i % BITS_IN_WORD));
+               add_literal(self, (eword_t)1 << (i % BITS_IN_EWORD));
                return;
        }
 
        if (rlw_get_literal_words(self->rlw) == 0) {
                rlw_set_running_len(self->rlw,
                        rlw_get_running_len(self->rlw) - 1);
-               add_literal(self, (eword_t)1 << (i % BITS_IN_WORD));
+               add_literal(self, (eword_t)1 << (i % BITS_IN_EWORD));
                return;
        }
 
        self->buffer[self->buffer_size - 1] |=
-               ((eword_t)1 << (i % BITS_IN_WORD));
+               ((eword_t)1 << (i % BITS_IN_EWORD));
 
        /* check if we just completed a stream of 1s */
        if (self->buffer[self->buffer_size - 1] == (eword_t)(~0)) {
@@ -255,11 +255,11 @@ void ewah_each_bit(struct ewah_bitmap *self, void (*callback)(size_t, void*), vo
                eword_t *word = &self->buffer[pointer];
 
                if (rlw_get_run_bit(word)) {
-                       size_t len = rlw_get_running_len(word) * BITS_IN_WORD;
+                       size_t len = rlw_get_running_len(word) * BITS_IN_EWORD;
                        for (k = 0; k < len; ++k, ++pos)
                                callback(pos, payload);
                } else {
-                       pos += rlw_get_running_len(word) * BITS_IN_WORD;
+                       pos += rlw_get_running_len(word) * BITS_IN_EWORD;
                }
 
                ++pointer;
@@ -268,7 +268,7 @@ void ewah_each_bit(struct ewah_bitmap *self, void (*callback)(size_t, void*), vo
                        int c;
 
                        /* todo: zero count optimization */
-                       for (c = 0; c < BITS_IN_WORD; ++c, ++pos) {
+                       for (c = 0; c < BITS_IN_EWORD; ++c, ++pos) {
                                if ((self->buffer[pointer] & ((eword_t)1 << c)) != 0)
                                        callback(pos, payload);
                        }
index 13c6e20412591ed3bc56b38b17419a540264f6c5..16b7a795a0619fef02afb55f849dbedde2896c8f 100644 (file)
@@ -31,7 +31,7 @@
 #endif
 
 typedef uint64_t eword_t;
-#define BITS_IN_WORD (sizeof(eword_t) * 8)
+#define BITS_IN_EWORD (sizeof(eword_t) * 8)
 
 /**
  * Do not use __builtin_popcountll. The GCC implementation
index 48526aa54bbb8458a10fc178f4fa5a429b77bc87..849a9d627535a303d6db4a4f49a2af42fb89dffb 100644 (file)
@@ -790,7 +790,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
        sort_ref_list(&ref, ref_compare_name);
        qsort(sought, nr_sought, sizeof(*sought), cmp_ref_by_name);
 
-       if (is_repository_shallow() && !server_supports("shallow"))
+       if ((args->depth > 0 || is_repository_shallow()) && !server_supports("shallow"))
                die("Server does not support shallow clients");
        if (server_supports("multi_ack_detailed")) {
                if (args->verbose)
diff --git a/fsck.c b/fsck.c
index 10bcb651516e2c25979f8f5af62f87407289e8e6..24b2a5f36c0c04c8bd956777eb86b23dfb0ca7fc 100644 (file)
--- a/fsck.c
+++ b/fsck.c
@@ -241,8 +241,8 @@ static int fsck_tree(struct tree *item, int strict, fsck_error error_func)
        return retval;
 }
 
-static int require_end_of_header(const void *data, unsigned long size,
-       struct object *obj, fsck_error error_func)
+static int verify_headers(const void *data, unsigned long size,
+                         struct object *obj, fsck_error error_func)
 {
        const char *buffer = (const char *)data;
        unsigned long i;
@@ -258,6 +258,15 @@ static int require_end_of_header(const void *data, unsigned long size,
                }
        }
 
+       /*
+        * We did not find double-LF that separates the header
+        * and the body.  Not having a body is not a crime but
+        * we do want to see the terminating LF for the last header
+        * line.
+        */
+       if (size && buffer[size - 1] == '\n')
+               return 0;
+
        return error_func(obj, FSCK_ERROR, "unterminated header");
 }
 
@@ -308,7 +317,7 @@ static int fsck_commit_buffer(struct commit *commit, const char *buffer,
        unsigned parent_count, parent_line_count = 0;
        int err;
 
-       if (require_end_of_header(buffer, size, &commit->object, error_func))
+       if (verify_headers(buffer, size, &commit->object, error_func))
                return -1;
 
        if (!skip_prefix(buffer, "tree ", &buffer))
@@ -387,7 +396,7 @@ static int fsck_tag_buffer(struct tag *tag, const char *data,
                }
        }
 
-       if (require_end_of_header(buffer, size, &tag->object, error_func))
+       if (verify_headers(buffer, size, &tag->object, error_func))
                goto done;
 
        if (!skip_prefix(buffer, "object ", &buffer)) {
index a67d0f98989706fa69df4cf7d6242ad9531eb337..3103c0fc28910560d85f4c2cff2b6a0595848b16 100755 (executable)
--- a/git-am.sh
+++ b/git-am.sh
@@ -69,6 +69,8 @@ then
        cmdline="$cmdline -3"
 fi
 
+empty_tree=4b825dc642cb6eb9a060e54bf8d69288fbee4904
+
 sq () {
        git rev-parse --sq-quote "$@"
 }
@@ -85,7 +87,7 @@ safe_to_abort () {
                return 1
        fi
 
-       if ! test -s "$dotest/abort-safety"
+       if ! test -f "$dotest/abort-safety"
        then
                return 0
        fi
@@ -177,7 +179,8 @@ It does not apply to blobs recorded in its index.")"
     then
            GIT_MERGE_VERBOSITY=0 && export GIT_MERGE_VERBOSITY
     fi
-    git-merge-recursive $orig_tree -- HEAD $his_tree || {
+    our_tree=$(git rev-parse --verify -q HEAD || echo $empty_tree)
+    git-merge-recursive $orig_tree -- $our_tree $his_tree || {
            git rerere $allow_rerere_autoupdate
            die "$(gettext "Failed to merge in the changes.")"
     }
@@ -502,10 +505,11 @@ then
                ;;
        t,)
                git rerere clear
-               git read-tree --reset -u HEAD HEAD
-               orig_head=$(cat "$GIT_DIR/ORIG_HEAD")
-               git reset HEAD
-               git update-ref ORIG_HEAD $orig_head
+               head_tree=$(git rev-parse --verify -q HEAD || echo $empty_tree) &&
+               git read-tree --reset -u $head_tree $head_tree &&
+               index_tree=$(git write-tree) &&
+               git read-tree -m -u $index_tree $head_tree
+               git read-tree $head_tree
                ;;
        ,t)
                if test -f "$dotest/rebasing"
@@ -515,8 +519,19 @@ then
                git rerere clear
                if safe_to_abort
                then
-                       git read-tree --reset -u HEAD ORIG_HEAD
-                       git reset ORIG_HEAD
+                       head_tree=$(git rev-parse --verify -q HEAD || echo $empty_tree) &&
+                       git read-tree --reset -u $head_tree $head_tree &&
+                       index_tree=$(git write-tree) &&
+                       orig_head=$(git rev-parse --verify -q ORIG_HEAD || echo $empty_tree) &&
+                       git read-tree -m -u $index_tree $orig_head
+                       if git rev-parse --verify -q ORIG_HEAD >/dev/null 2>&1
+                       then
+                               git reset ORIG_HEAD
+                       else
+                               git read-tree $empty_tree
+                               curr_branch=$(git symbolic-ref HEAD 2>/dev/null) &&
+                               git update-ref -d $curr_branch
+                       fi
                fi
                rm -fr "$dotest"
                exit ;;
index f9237323331e992a58cee0af79090a7bbeec434c..9ae898bc1d7d301983893e6df404c696b80a87f5 100644 (file)
@@ -78,7 +78,7 @@ else
 
                As a result, git cannot rebase them.
                EOF
-               return $?
+               return $ret
        fi
 
        git am $git_am_opt --rebasing --resolvemsg="$resolvemsg" \
diff --git a/http.c b/http.c
index 4b179f6fc8f29c1683b187393203d20f95d29157..9a7e0892e479a977f575a549699bc76e969634be 100644 (file)
--- a/http.c
+++ b/http.c
@@ -406,10 +406,10 @@ static CURL *get_curl_handle(void)
 
        if (curl_http_proxy) {
                curl_easy_setopt(result, CURLOPT_PROXY, curl_http_proxy);
+       }
 #if LIBCURL_VERSION_NUM >= 0x070a07
-               curl_easy_setopt(result, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
+       curl_easy_setopt(result, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
 #endif
-       }
 
        set_curl_keepalive(result);
 
index 2b3ff2379747f7931167d3099c624113bf032536..637770af813eee643c8375051e419715f56a2db5 100644 (file)
@@ -622,7 +622,7 @@ static void show_objects_for_type(
        while (i < objects->word_alloc && ewah_iterator_next(&filter, &it)) {
                eword_t word = objects->words[i] & filter;
 
-               for (offset = 0; offset < BITS_IN_WORD; ++offset) {
+               for (offset = 0; offset < BITS_IN_EWORD; ++offset) {
                        const unsigned char *sha1;
                        struct revindex_entry *entry;
                        uint32_t hash = 0;
@@ -644,7 +644,7 @@ static void show_objects_for_type(
                        show_reach(sha1, object_type, 0, hash, bitmap_git.pack, entry->offset);
                }
 
-               pos += BITS_IN_WORD;
+               pos += BITS_IN_EWORD;
                i++;
        }
 }
@@ -776,7 +776,7 @@ int reuse_partial_packfile_from_bitmap(struct packed_git **packfile,
                        break;
                }
 
-               reuse_objects += BITS_IN_WORD;
+               reuse_objects += BITS_IN_EWORD;
        }
 
 #ifdef GIT_BITMAP_DEBUG
@@ -1001,7 +1001,7 @@ static int rebuild_bitmap(uint32_t *reposition,
        while (ewah_iterator_next(&word, &it)) {
                uint32_t offset, bit_pos;
 
-               for (offset = 0; offset < BITS_IN_WORD; ++offset) {
+               for (offset = 0; offset < BITS_IN_EWORD; ++offset) {
                        if ((word >> offset) == 0)
                                break;
 
@@ -1014,7 +1014,7 @@ static int rebuild_bitmap(uint32_t *reposition,
                                return -1;
                }
 
-               pos += BITS_IN_WORD;
+               pos += BITS_IN_EWORD;
        }
        return 0;
 }
diff --git a/pager.c b/pager.c
index 98b26823c9e0c0bd220a7a41a97675626c8e65ec..070dc11cb0c85abf07763de46a82e73dde6bded2 100644 (file)
--- a/pager.c
+++ b/pager.c
@@ -78,6 +78,7 @@ void setup_pager(void)
                argv_array_push(&pager_process.env_array, "LESS=FRX");
        if (!getenv("LV"))
                argv_array_push(&pager_process.env_array, "LV=-c");
+       argv_array_push(&pager_process.env_array, "GIT_PAGER_IN_USE");
        if (start_command(&pager_process))
                return;
 
diff --git a/refs.c b/refs.c
index 67d6745e28ca44be1042e0ac41f9577ae6f8619b..305bb54169b41cfb53c2eff260cb6cd80f1810c4 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -1374,19 +1374,34 @@ static void read_loose_refs(const char *dirname, struct ref_dir *dir)
                                         create_dir_entry(refs, refname.buf,
                                                          refname.len, 1));
                } else {
+                       int read_ok;
+
                        if (*refs->name) {
                                hashclr(sha1);
                                flag = 0;
-                               if (resolve_gitlink_ref(refs->name, refname.buf, sha1) < 0) {
-                                       hashclr(sha1);
-                                       flag |= REF_ISBROKEN;
-                               }
-                       } else if (read_ref_full(refname.buf,
-                                                RESOLVE_REF_READING,
-                                                sha1, &flag)) {
+                               read_ok = !resolve_gitlink_ref(refs->name,
+                                                              refname.buf, sha1);
+                       } else {
+                               read_ok = !read_ref_full(refname.buf,
+                                                        RESOLVE_REF_READING,
+                                                        sha1, &flag);
+                       }
+
+                       if (!read_ok) {
                                hashclr(sha1);
                                flag |= REF_ISBROKEN;
+                       } else if (is_null_sha1(sha1)) {
+                               /*
+                                * It is so astronomically unlikely
+                                * that NULL_SHA1 is the SHA-1 of an
+                                * actual object that we consider its
+                                * appearance in a loose reference
+                                * file to be repo corruption
+                                * (probably due to a software bug).
+                                */
+                               flag |= REF_ISBROKEN;
                        }
+
                        if (check_refname_format(refname.buf,
                                                 REFNAME_ALLOW_ONELEVEL)) {
                                hashclr(sha1);
index 56c69cebc80f57f26f9898fbbc6587176f915339..a68ae18dd8557e37dca82be3825cabe8f4cb53f4 100644 (file)
@@ -443,6 +443,7 @@ void prepare_alt_odb(void)
        read_info_alternates(get_object_directory(), 0);
 }
 
+/* Returns 1 if we have successfully freshened the file, 0 otherwise. */
 static int freshen_file(const char *fn)
 {
        struct utimbuf t;
@@ -450,11 +451,18 @@ static int freshen_file(const char *fn)
        return !utime(fn, &t);
 }
 
+/*
+ * All of the check_and_freshen functions return 1 if the file exists and was
+ * freshened (if freshening was requested), 0 otherwise. If they return
+ * 0, you should not assume that it is safe to skip a write of the object (it
+ * either does not exist on disk, or has a stale mtime and may be subject to
+ * pruning).
+ */
 static int check_and_freshen_file(const char *fn, int freshen)
 {
        if (access(fn, F_OK))
                return 0;
-       if (freshen && freshen_file(fn))
+       if (freshen && !freshen_file(fn))
                return 0;
        return 1;
 }
@@ -3084,7 +3092,7 @@ int has_sha1_pack(const unsigned char *sha1)
        return find_pack_entry(sha1, &e);
 }
 
-int has_sha1_file(const unsigned char *sha1)
+int has_sha1_file_with_flags(const unsigned char *sha1, int flags)
 {
        struct pack_entry e;
 
@@ -3092,6 +3100,8 @@ int has_sha1_file(const unsigned char *sha1)
                return 1;
        if (has_loose_object(sha1))
                return 1;
+       if (flags & HAS_SHA1_QUICK)
+               return 0;
        reprepare_packed_git();
        return find_pack_entry(sha1, &e);
 }
index 88cafd4a70b8179a4e911c18704fb4ab0f2a21f5..b4da9f5d05fc1f22f8910a21d8e352f2e5e9673f 100644 (file)
--- a/strbuf.c
+++ b/strbuf.c
@@ -481,9 +481,10 @@ int strbuf_getwholeline_fd(struct strbuf *sb, int fd, int term)
        return 0;
 }
 
-int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint)
+ssize_t strbuf_read_file(struct strbuf *sb, const char *path, size_t hint)
 {
-       int fd, len;
+       int fd;
+       ssize_t len;
 
        fd = open(path, O_RDONLY);
        if (fd < 0)
index 1883494ca3ad4931640c2a295c94800e287c1664..1ea9d0bdeb0980dcaa8670aa43e4ff703fd9d6b8 100644 (file)
--- a/strbuf.h
+++ b/strbuf.h
@@ -364,7 +364,7 @@ extern ssize_t strbuf_read(struct strbuf *, int fd, size_t hint);
  * Read the contents of a file, specified by its path. The third argument
  * can be used to give a hint about the file size, to avoid reallocs.
  */
-extern int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint);
+extern ssize_t strbuf_read_file(struct strbuf *sb, const char *path, size_t hint);
 
 /**
  * Read the target of a symbolic link, specified by its path.  The third
index 0979df93a1062020e92fa55a780678e20db4f9db..1d8d1f210b99e888fa39da14f73aef19eaf338b5 100755 (executable)
@@ -75,7 +75,7 @@ test_expect_success 'get: use xdg file if home file has no matches' '
        EOF
 '
 
-test_expect_success POSIXPERM 'get: use xdg file if home file is unreadable' '
+test_expect_success POSIXPERM,SANITY 'get: use xdg file if home file is unreadable' '
        echo "https://home-user:home-pass@example.com" >"$HOME/.git-credentials" &&
        chmod -r "$HOME/.git-credentials" &&
        mkdir -p "$HOME/.config/git" &&
index c39e50028f256b6850327b90aa1137bd8e35ef1a..890db1174f75172ee6b342e26cbbc58e3e4cd03f 100755 (executable)
@@ -57,6 +57,14 @@ test_expect_success "format-patch --ignore-if-in-upstream" '
 
 '
 
+test_expect_success "format-patch --ignore-if-in-upstream handles tags" '
+       git tag -a v1 -m tag side &&
+       git tag -a v2 -m tag master &&
+       git format-patch --stdout --ignore-if-in-upstream v2..v1 >patch1 &&
+       cnt=$(grep "^From " patch1 | wc -l) &&
+       test $cnt = 2
+'
+
 test_expect_success "format-patch doesn't consider merge commits" '
 
        git checkout -b slave master &&
index 8d90634ab81b3d24326c519a8bae52c2e2cb3ac0..833e7b2ceae99cbf53bac63e239b362e368ddf8f 100755 (executable)
@@ -14,6 +14,7 @@ test_expect_success setup '
        git add file-1 file-2 &&
        git commit -m initial &&
        git tag initial &&
+       git format-patch --stdout --root initial >initial.patch &&
        for i in 2 3 4 5 6
        do
                echo $i >>file-1 &&
@@ -63,6 +64,28 @@ do
 
 done
 
+test_expect_success 'am -3 --skip removes otherfile-4' '
+       git reset --hard initial &&
+       test_must_fail git am -3 0003-*.patch &&
+       test 3 -eq $(git ls-files -u | wc -l) &&
+       test 4 = "$(cat otherfile-4)" &&
+       git am --skip &&
+       test_cmp_rev initial HEAD &&
+       test -z "$(git ls-files -u)" &&
+       test_path_is_missing otherfile-4
+'
+
+test_expect_success 'am -3 --abort removes otherfile-4' '
+       git reset --hard initial &&
+       test_must_fail git am -3 0003-*.patch &&
+       test 3 -eq $(git ls-files -u | wc -l) &&
+       test 4 = "$(cat otherfile-4)" &&
+       git am --abort &&
+       test_cmp_rev initial HEAD &&
+       test -z $(git ls-files -u) &&
+       test_path_is_missing otherfile-4
+'
+
 test_expect_success 'am --abort will keep the local commits intact' '
        test_must_fail git am 0004-*.patch &&
        test_commit unrelated &&
@@ -72,4 +95,62 @@ test_expect_success 'am --abort will keep the local commits intact' '
        test_cmp expect actual
 '
 
+test_expect_success 'am -3 stops on conflict on unborn branch' '
+       git checkout -f --orphan orphan &&
+       git reset &&
+       rm -f otherfile-4 &&
+       test_must_fail git am -3 0003-*.patch &&
+       test 2 -eq $(git ls-files -u | wc -l) &&
+       test 4 = "$(cat otherfile-4)"
+'
+
+test_expect_success 'am -3 --skip clears index on unborn branch' '
+       test_path_is_dir .git/rebase-apply &&
+       echo tmpfile >tmpfile &&
+       git add tmpfile &&
+       git am --skip &&
+       test -z "$(git ls-files)" &&
+       test_path_is_missing otherfile-4 &&
+       test_path_is_missing tmpfile
+'
+
+test_expect_success 'am -3 --abort removes otherfile-4 on unborn branch' '
+       git checkout -f --orphan orphan &&
+       git reset &&
+       rm -f otherfile-4 file-1 &&
+       test_must_fail git am -3 0003-*.patch &&
+       test 2 -eq $(git ls-files -u | wc -l) &&
+       test 4 = "$(cat otherfile-4)" &&
+       git am --abort &&
+       test -z "$(git ls-files -u)" &&
+       test_path_is_missing otherfile-4
+'
+
+test_expect_success 'am -3 --abort on unborn branch removes applied commits' '
+       git checkout -f --orphan orphan &&
+       git reset &&
+       rm -f otherfile-4 otherfile-2 file-1 file-2 &&
+       test_must_fail git am -3 initial.patch 0003-*.patch &&
+       test 3 -eq $(git ls-files -u | wc -l) &&
+       test 4 = "$(cat otherfile-4)" &&
+       git am --abort &&
+       test -z "$(git ls-files -u)" &&
+       test_path_is_missing otherfile-4 &&
+       test_path_is_missing file-1 &&
+       test_path_is_missing file-2 &&
+       test 0 -eq $(git log --oneline 2>/dev/null | wc -l) &&
+       test refs/heads/orphan = "$(git symbolic-ref HEAD)"
+'
+
+test_expect_success 'am --abort on unborn branch will keep local commits intact' '
+       git checkout -f --orphan orphan &&
+       git reset &&
+       test_must_fail git am 0004-*.patch &&
+       test_commit unrelated2 &&
+       git rev-parse HEAD >expect &&
+       git am --abort &&
+       git rev-parse HEAD >actual &&
+       test_cmp expect actual
+'
+
 test_done
index 6003490192880802d866ec3788facaf4dcf17147..d446706e94fb878b471e6deaebba4ec7abc76930 100755 (executable)
@@ -53,6 +53,12 @@ rev_list_tests() {
                test_cmp expect actual
        '
 
+       test_expect_success "counting commits with limiting ($state)" '
+               git rev-list --count HEAD -- 1.t >expect &&
+               git rev-list --use-bitmap-index --count HEAD -- 1.t >actual &&
+               test_cmp expect actual
+       '
+
        test_expect_success "enumerate --objects ($state)" '
                git rev-list --objects --use-bitmap-index HEAD >tmp &&
                cut -d" " -f1 <tmp >tmp2 &&
diff --git a/t/t6301-for-each-ref-errors.sh b/t/t6301-for-each-ref-errors.sh
new file mode 100755 (executable)
index 0000000..cdb67a0
--- /dev/null
@@ -0,0 +1,56 @@
+#!/bin/sh
+
+test_description='for-each-ref errors for broken refs'
+
+. ./test-lib.sh
+
+ZEROS=$_z40
+MISSING=abababababababababababababababababababab
+
+test_expect_success setup '
+       git commit --allow-empty -m "Initial" &&
+       git tag testtag &&
+       git for-each-ref >full-list &&
+       git for-each-ref --format="%(objectname) %(refname)" >brief-list
+'
+
+test_expect_success 'Broken refs are reported correctly' '
+       r=refs/heads/bogus &&
+       : >.git/$r &&
+       test_when_finished "rm -f .git/$r" &&
+       echo "warning: ignoring broken ref $r" >broken-err &&
+       git for-each-ref >out 2>err &&
+       test_cmp full-list out &&
+       test_cmp broken-err err
+'
+
+test_expect_success 'NULL_SHA1 refs are reported correctly' '
+       r=refs/heads/zeros &&
+       echo $ZEROS >.git/$r &&
+       test_when_finished "rm -f .git/$r" &&
+       echo "warning: ignoring broken ref $r" >zeros-err &&
+       git for-each-ref >out 2>err &&
+       test_cmp full-list out &&
+       test_cmp zeros-err err &&
+       git for-each-ref --format="%(objectname) %(refname)" >brief-out 2>brief-err &&
+       test_cmp brief-list brief-out &&
+       test_cmp zeros-err brief-err
+'
+
+test_expect_success 'Missing objects are reported correctly' '
+       r=refs/heads/missing &&
+       echo $MISSING >.git/$r &&
+       test_when_finished "rm -f .git/$r" &&
+       echo "fatal: missing object $MISSING for $r" >missing-err &&
+       test_must_fail git for-each-ref 2>err &&
+       test_cmp missing-err err &&
+       (
+               cat brief-list &&
+               echo "$MISSING $r"
+       ) | sort -k 2 >missing-brief-expected &&
+       git for-each-ref --format="%(objectname) %(refname)" >brief-out 2>brief-err &&
+       test_cmp missing-brief-expected brief-out &&
+       test_must_be_empty brief-err
+'
+
+test_done
index 051489ea334c9693c2d19823ad23947703f66d90..31924b21a6145d7543de9236e42094c90d22268a 100755 (executable)
@@ -229,14 +229,36 @@ test_expect_success 'cleanup commit messages (scissors option,-F,-e)' '
        cat >text <<EOF &&
 
 # to be kept
+
+  # ------------------------ >8 ------------------------
+# to be kept, too
 # ------------------------ >8 ------------------------
 to be removed
+# ------------------------ >8 ------------------------
+to be removed, too
+EOF
+
+       cat >expect <<EOF &&
+# to be kept
+
+  # ------------------------ >8 ------------------------
+# to be kept, too
 EOF
-       echo "# to be kept" >expect &&
        git commit --cleanup=scissors -e -F text -a &&
        git cat-file -p HEAD |sed -e "1,/^\$/d">actual &&
        test_cmp expect actual
+'
 
+test_expect_success 'cleanup commit messages (scissors option,-F,-e, scissors on first line)' '
+
+       echo >>negative &&
+       cat >text <<EOF &&
+# ------------------------ >8 ------------------------
+to be removed
+EOF
+       git commit --cleanup=scissors -e -F text -a --allow-empty-message &&
+       git cat-file -p HEAD |sed -e "1,/^\$/d">actual &&
+       test_must_be_empty actual
 '
 
 test_expect_success 'cleanup commit messages (strip option,-F)' '
index 4ea99a209d74d7d052a880a2a69d99a65a9dd0a6..05efbad71c6121ea06f4855ee1fe4caf5bad3426 100644 (file)
@@ -15,9 +15,6 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see http://www.gnu.org/licenses/ .
 
-# Keep the original TERM for say_color
-ORIGINAL_TERM=$TERM
-
 # Test the binaries we have just built.  The tests are kept in
 # t/ subdirectory and are run in 'trash directory' subdirectory.
 if test -z "$TEST_DIRECTORY"
@@ -68,12 +65,12 @@ done,*)
 esac
 
 # For repeatability, reset the environment to known value.
+# TERM is sanitized below, after saving color control sequences.
 LANG=C
 LC_ALL=C
 PAGER=cat
 TZ=UTC
-TERM=dumb
-export LANG LC_ALL PAGER TERM TZ
+export LANG LC_ALL PAGER TZ
 EDITOR=:
 # A call to "unset" with no arguments causes at least Solaris 10
 # /usr/xpg4/bin/sh and /bin/ksh to bail out.  So keep the unsets
@@ -181,8 +178,14 @@ export _x05 _x40 _z40 LF u200c
 # This test checks if command xyzzy does the right thing...
 # '
 # . ./test-lib.sh
+test "x$TERM" != "xdumb" && (
+               test -t 1 &&
+               tput bold >/dev/null 2>&1 &&
+               tput setaf 1 >/dev/null 2>&1 &&
+               tput sgr0 >/dev/null 2>&1
+       ) &&
+       color=t
 
-unset color
 while test "$#" -ne 0
 do
        case "$1" in
@@ -253,6 +256,44 @@ then
        verbose=t
 fi
 
+if test -n "$color"
+then
+       # Save the color control sequences now rather than run tput
+       # each time say_color() is called.  This is done for two
+       # reasons:
+       #   * TERM will be changed to dumb
+       #   * HOME will be changed to a temporary directory and tput
+       #     might need to read ~/.terminfo from the original HOME
+       #     directory to get the control sequences
+       # Note:  This approach assumes the control sequences don't end
+       # in a newline for any terminal of interest (command
+       # substitutions strip trailing newlines).  Given that most
+       # (all?) terminals in common use are related to ECMA-48, this
+       # shouldn't be a problem.
+       say_color_error=$(tput bold; tput setaf 1) # bold red
+       say_color_skip=$(tput setaf 4) # blue
+       say_color_warn=$(tput setaf 3) # brown/yellow
+       say_color_pass=$(tput setaf 2) # green
+       say_color_info=$(tput setaf 6) # cyan
+       say_color_reset=$(tput sgr0)
+       say_color_="" # no formatting for normal text
+       say_color () {
+               test -z "$1" && test -n "$quiet" && return
+               eval "say_color_color=\$say_color_$1"
+               shift
+               printf "%s\\n" "$say_color_color$*$say_color_reset"
+       }
+else
+       say_color() {
+               test -z "$1" && test -n "$quiet" && return
+               shift
+               printf "%s\n" "$*"
+       }
+fi
+
+TERM=dumb
+export TERM
+
 error () {
        say_color error "error: $*"
        GIT_EXIT_OK=t
@@ -829,52 +870,6 @@ HOME="$TRASH_DIRECTORY"
 GNUPGHOME="$HOME/gnupg-home-not-used"
 export HOME GNUPGHOME
 
-# run the tput tests *after* changing HOME (in case ncurses needs
-# ~/.terminfo for $TERM)
-test -n "${color+set}" || test "x$ORIGINAL_TERM" != "xdumb" && (
-               TERM=$ORIGINAL_TERM &&
-               export TERM &&
-               test -t 1 &&
-               tput bold >/dev/null 2>&1 &&
-               tput setaf 1 >/dev/null 2>&1 &&
-               tput sgr0 >/dev/null 2>&1
-       ) &&
-       color=t
-
-if test -n "$color"
-then
-       say_color () {
-               (
-               TERM=$ORIGINAL_TERM
-               export TERM
-               case "$1" in
-               error)
-                       tput bold; tput setaf 1;; # bold red
-               skip)
-                       tput setaf 4;; # blue
-               warn)
-                       tput setaf 3;; # brown/yellow
-               pass)
-                       tput setaf 2;; # green
-               info)
-                       tput setaf 6;; # cyan
-               *)
-                       test -n "$quiet" && return;;
-               esac
-               shift
-               printf "%s" "$*"
-               tput sgr0
-               echo
-               )
-       }
-else
-       say_color() {
-               test -z "$1" && test -n "$quiet" && return
-               shift
-               printf "%s\n" "$*"
-       }
-fi
-
 if test -z "$TEST_NO_CREATE_REPO"
 then
        test_create_repo "$TRASH_DIRECTORY"
diff --git a/utf8.h b/utf8.h
index e7b2aa416844a0b2ccb2d2cf8a1bce68c4d60be1..5a9e94bee62fd2ed62dcbc82aee12bfc6d75e254 100644 (file)
--- a/utf8.h
+++ b/utf8.h
@@ -31,7 +31,9 @@ char *reencode_string_len(const char *in, int insz,
                          const char *in_encoding,
                          int *outsz);
 #else
-#define reencode_string_len(a,b,c,d,e) NULL
+static inline char *reencode_string_len(const char *a, int b,
+                                       const char *c, const char *d, int *e)
+{ if (e) *e = 0; return NULL; }
 #endif
 
 static inline char *reencode_string(const char *in,
index 38cb165f124d610c789a8d82de42281c795111f7..078a4727435b0c6b98cdc600773cb90e850e9a7f 100644 (file)
@@ -823,10 +823,11 @@ void wt_status_truncate_message_at_cut_line(struct strbuf *buf)
        const char *p;
        struct strbuf pattern = STRBUF_INIT;
 
-       strbuf_addf(&pattern, "%c %s", comment_line_char, cut_line);
-       p = strstr(buf->buf, pattern.buf);
-       if (p && (p == buf->buf || p[-1] == '\n'))
-               strbuf_setlen(buf, p - buf->buf);
+       strbuf_addf(&pattern, "\n%c %s", comment_line_char, cut_line);
+       if (starts_with(buf->buf, pattern.buf + 1))
+               strbuf_setlen(buf, 0);
+       else if ((p = strstr(buf->buf, pattern.buf)))
+               strbuf_setlen(buf, p - buf->buf + 1);
        strbuf_release(&pattern);
 }