Merge branch 'merge' of https://github.com/ChrisADR/git-po into maint
authorJiang Xin <worldhello.net@gmail.com>
Wed, 21 Feb 2018 14:22:51 +0000 (22:22 +0800)
committerJiang Xin <worldhello.net@gmail.com>
Wed, 21 Feb 2018 14:22:51 +0000 (22:22 +0800)
* 'merge' of https://github.com/ChrisADR/git-po:
l10n: es.po: fixes to Spanish translation

32 files changed:
Documentation/RelNotes/2.16.0.txt
Documentation/RelNotes/2.16.1.txt [new file with mode: 0644]
Documentation/RelNotes/2.16.2.txt [new file with mode: 0644]
Documentation/git-cat-file.txt
Documentation/git-read-tree.txt
GIT-VERSION-GEN
RelNotes
bisect.c
builtin/checkout.c
builtin/clone.c
builtin/describe.c
bundle.c
commit.c
commit.h
git-add--interactive.perl
git-stash.sh
git-svn.perl
merge-recursive.c
object.c
object.h
ref-filter.c
repository.c
revision.c
revision.h
t/perf/p7820-grep-engines.sh
t/perf/p7821-grep-engines-fixed.sh
t/t3701-add-interactive.sh
t/t3903-stash.sh
t/t5600-clone-fail-cleanup.sh
t/t5601-clone.sh
t/t6037-merge-ours-theirs.sh
t/t6120-describe.sh
index 919f3eb3ea66f4620d8b6dbf92cab25d45c50ecb..0c81c5915fdbdbb9f9225211f7558954c1aa242d 100644 (file)
@@ -62,8 +62,11 @@ UI, Workflows & Features
  * The SubmittingPatches document has been converted to produce an
    HTML version via AsciiDoc/Asciidoctor.
 
- * We learned to talk to watchman to speed up "git status" and other
-   operations that need to see which paths have been modified.
+ * We learned to optionally talk to a file system monitor via new
+   fsmonitor extension to speed up "git status" and other operations
+   that need to see which paths have been modified.  Currently we only
+   support "watchman".  See File System Monitor section of
+   git-update-index(1) for more detail.
 
  * The "diff" family of commands learned to ignore differences in
    carriage return at the end of line.
diff --git a/Documentation/RelNotes/2.16.1.txt b/Documentation/RelNotes/2.16.1.txt
new file mode 100644 (file)
index 0000000..66e6436
--- /dev/null
@@ -0,0 +1,11 @@
+Git v2.16.1 Release Notes
+=========================
+
+Fixes since v2.16
+-----------------
+
+ * "git clone" segfaulted when cloning a project that happens to
+   track two paths that differ only in case on a case insensitive
+   filesystem.
+
+Does not contain any other documentation updates or code clean-ups.
diff --git a/Documentation/RelNotes/2.16.2.txt b/Documentation/RelNotes/2.16.2.txt
new file mode 100644 (file)
index 0000000..a216466
--- /dev/null
@@ -0,0 +1,30 @@
+Git v2.16.2 Release Notes
+=========================
+
+Fixes since v2.16.1
+-------------------
+
+ * An old regression in "git describe --all $annotated_tag^0" has been
+   fixed.
+
+ * "git svn dcommit" did not take into account the fact that a
+   svn+ssh:// URL with a username@ (typically used for pushing) refers
+   to the same SVN repository without the username@ and failed when
+   svn.pushmergeinfo option is set.
+
+ * "git merge -Xours/-Xtheirs" learned to use our/their version when
+   resolving a conflicting updates to a symbolic link.
+
+ * "git clone $there $here" is allowed even when here directory exists
+   as long as it is an empty directory, but the command incorrectly
+   removed it upon a failure of the operation.
+
+ * "git stash -- <pathspec>" incorrectly blew away untracked files in
+   the directory that matched the pathspec, which has been corrected.
+
+ * "git add -p" was taught to ignore local changes to submodules as
+   they do not interfere with the partial addition of regular changes
+   anyway.
+
+
+Also contains various documentation updates and code clean-ups.
index fb09cd69d63fec03ad1987970fdbdffe8d8a4339..f90f09b03fae578e867335d1be3ab85d83195f27 100644 (file)
@@ -42,8 +42,9 @@ OPTIONS
        <object>.
 
 -e::
-       Suppress all output; instead exit with zero status if <object>
-       exists and is a valid object.
+       Exit with zero status if <object> exists and is a valid
+       object. If <object> is of an invalid format exit with non-zero and
+       emits an error on stderr.
 
 -p::
        Pretty-print the contents of <object> based on its type.
@@ -168,7 +169,7 @@ If `-t` is specified, one of the <type>.
 
 If `-s` is specified, the size of the <object> in bytes.
 
-If `-e` is specified, no output.
+If `-e` is specified, no output, unless the <object> is malformed.
 
 If `-p` is specified, the contents of <object> are pretty-printed.
 
index 72bd809fb8d59812d79e402f6b9608d09f0d52ec..f2a07d54d694b42657aa38e71dc0eeb5fc94e9a0 100644 (file)
@@ -81,12 +81,11 @@ OPTIONS
 * when both sides add a path identically.  The resolution
   is to add that path.
 
---prefix=<prefix>/::
+--prefix=<prefix>::
        Keep the current index contents, and read the contents
        of the named tree-ish under the directory at `<prefix>`.
        The command will refuse to overwrite entries that already
-       existed in the original index file. Note that the `<prefix>/`
-       value must end with a slash.
+       existed in the original index file.
 
 --exclude-per-directory=<gitignore>::
        When running the command with `-u` and `-m` options, the
index 258aff35cd8e59b5756ba83c6ecfb6acef194d82..19e45a7d30213821f873b912f52b9c34153ce1e8 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v2.16.0-rc2
+DEF_VER=v2.16.2
 
 LF='
 '
index bec73d6767c965a8cfa684c96eaa8eefb66901d3..35c3c3221ac3ea4aca948fafbf56352bc3611d91 120000 (symlink)
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/2.16.0.txt
\ No newline at end of file
+Documentation/RelNotes/2.16.2.txt
\ No newline at end of file
index 2f3008b07866fb7bda6c0e0bbb089b1be1271a1a..0d9e731b72692103aa17ee2e28e0126fcdf32228 100644 (file)
--- a/bisect.c
+++ b/bisect.c
@@ -792,11 +792,9 @@ static void handle_skipped_merge_base(const struct object_id *mb)
  * - If one is "skipped", we can't know but we should warn.
  * - If we don't know, we should check it out and ask the user to test.
  */
-static void check_merge_bases(int no_checkout)
+static void check_merge_bases(int rev_nr, struct commit **rev, int no_checkout)
 {
        struct commit_list *result;
-       int rev_nr;
-       struct commit **rev = get_bad_and_good_commits(&rev_nr);
 
        result = get_merge_bases_many(rev[0], rev_nr - 1, rev + 1);
 
@@ -814,34 +812,21 @@ static void check_merge_bases(int no_checkout)
                }
        }
 
-       free(rev);
        free_commit_list(result);
 }
 
-static int check_ancestors(const char *prefix)
+static int check_ancestors(int rev_nr, struct commit **rev, const char *prefix)
 {
        struct rev_info revs;
-       struct object_array pending_copy;
        int res;
 
        bisect_rev_setup(&revs, prefix, "^%s", "%s", 0);
 
-       /* Save pending objects, so they can be cleaned up later. */
-       pending_copy = revs.pending;
-       revs.leak_pending = 1;
-
-       /*
-        * bisect_common calls prepare_revision_walk right away, which
-        * (together with .leak_pending = 1) makes us the sole owner of
-        * the list of pending objects.
-        */
        bisect_common(&revs);
        res = (revs.commits != NULL);
 
        /* Clean up objects used, as they will be reused. */
-       clear_commit_marks_for_object_array(&pending_copy, ALL_REV_FLAGS);
-
-       object_array_clear(&pending_copy);
+       clear_commit_marks_many(rev_nr, rev, ALL_REV_FLAGS);
 
        return res;
 }
@@ -858,7 +843,8 @@ static void check_good_are_ancestors_of_bad(const char *prefix, int no_checkout)
 {
        char *filename = git_pathdup("BISECT_ANCESTORS_OK");
        struct stat st;
-       int fd;
+       int fd, rev_nr;
+       struct commit **rev;
 
        if (!current_bad_oid)
                die(_("a %s revision is needed"), term_bad);
@@ -872,8 +858,10 @@ static void check_good_are_ancestors_of_bad(const char *prefix, int no_checkout)
                goto done;
 
        /* Check if all good revs are ancestor of the bad rev. */
-       if (check_ancestors(prefix))
-               check_merge_bases(no_checkout);
+       rev = get_bad_and_good_commits(&rev_nr);
+       if (check_ancestors(rev_nr, rev, prefix))
+               check_merge_bases(rev_nr, rev, no_checkout);
+       free(rev);
 
        /* Create file BISECT_ANCESTORS_OK. */
        fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY, 0600);
index 8bdc927d3f561e62802ab53be0b3029325e6ebcd..c54c78df547c8c66377f023730958f7a95d3aea1 100644 (file)
@@ -791,7 +791,6 @@ static void orphaned_commit_warning(struct commit *old, struct commit *new)
 {
        struct rev_info revs;
        struct object *object = &old->object;
-       struct object_array refs;
 
        init_revisions(&revs, NULL);
        setup_revisions(0, NULL, &revs, NULL);
@@ -802,14 +801,6 @@ static void orphaned_commit_warning(struct commit *old, struct commit *new)
        for_each_ref(add_pending_uninteresting_ref, &revs);
        add_pending_oid(&revs, "HEAD", &new->object.oid, UNINTERESTING);
 
-       /* Save pending objects, so they can be cleaned up later. */
-       refs = revs.pending;
-       revs.leak_pending = 1;
-
-       /*
-        * prepare_revision_walk (together with .leak_pending = 1) makes us
-        * the sole owner of the list of pending objects.
-        */
        if (prepare_revision_walk(&revs))
                die(_("internal error in revision walk"));
        if (!(old->object.flags & UNINTERESTING))
@@ -818,9 +809,7 @@ static void orphaned_commit_warning(struct commit *old, struct commit *new)
                describe_detached_head(_("Previous HEAD position was"), old);
 
        /* Clean up objects used, as they will be reused. */
-       clear_commit_marks_for_object_array(&refs, ALL_REV_FLAGS);
-
-       object_array_clear(&refs);
+       clear_commit_marks_all(ALL_REV_FLAGS);
 }
 
 static int switch_branches(const struct checkout_opts *opts,
index 2da71db10752bf95647052dcd5b7c4b28e7a50ac..284651797e5402c9f7ef85003d7d1c4ea944e2d7 100644 (file)
@@ -473,7 +473,9 @@ static void clone_local(const char *src_repo, const char *dest_repo)
 }
 
 static const char *junk_work_tree;
+static int junk_work_tree_flags;
 static const char *junk_git_dir;
+static int junk_git_dir_flags;
 static enum {
        JUNK_LEAVE_NONE,
        JUNK_LEAVE_REPO,
@@ -502,12 +504,12 @@ static void remove_junk(void)
 
        if (junk_git_dir) {
                strbuf_addstr(&sb, junk_git_dir);
-               remove_dir_recursively(&sb, 0);
+               remove_dir_recursively(&sb, junk_git_dir_flags);
                strbuf_reset(&sb);
        }
        if (junk_work_tree) {
                strbuf_addstr(&sb, junk_work_tree);
-               remove_dir_recursively(&sb, 0);
+               remove_dir_recursively(&sb, junk_work_tree_flags);
        }
        strbuf_release(&sb);
 }
@@ -863,10 +865,15 @@ static void dissociate_from_references(void)
        free(alternates);
 }
 
+static int dir_exists(const char *path)
+{
+       struct stat sb;
+       return !stat(path, &sb);
+}
+
 int cmd_clone(int argc, const char **argv, const char *prefix)
 {
        int is_bundle = 0, is_local;
-       struct stat buf;
        const char *repo_name, *repo, *work_tree, *git_dir;
        char *path, *dir;
        int dest_exists;
@@ -938,7 +945,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
                dir = guess_dir_name(repo_name, is_bundle, option_bare);
        strip_trailing_slashes(dir);
 
-       dest_exists = !stat(dir, &buf);
+       dest_exists = dir_exists(dir);
        if (dest_exists && !is_empty_dir(dir))
                die(_("destination path '%s' already exists and is not "
                        "an empty directory."), dir);
@@ -949,7 +956,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
                work_tree = NULL;
        else {
                work_tree = getenv("GIT_WORK_TREE");
-               if (work_tree && !stat(work_tree, &buf))
+               if (work_tree && dir_exists(work_tree))
                        die(_("working tree '%s' already exists."), work_tree);
        }
 
@@ -967,14 +974,24 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
                if (safe_create_leading_directories_const(work_tree) < 0)
                        die_errno(_("could not create leading directories of '%s'"),
                                  work_tree);
-               if (!dest_exists && mkdir(work_tree, 0777))
+               if (dest_exists)
+                       junk_work_tree_flags |= REMOVE_DIR_KEEP_TOPLEVEL;
+               else if (mkdir(work_tree, 0777))
                        die_errno(_("could not create work tree dir '%s'"),
                                  work_tree);
                junk_work_tree = work_tree;
                set_git_work_tree(work_tree);
        }
 
-       junk_git_dir = real_git_dir ? real_git_dir : git_dir;
+       if (real_git_dir) {
+               if (dir_exists(real_git_dir))
+                       junk_git_dir_flags |= REMOVE_DIR_KEEP_TOPLEVEL;
+               junk_git_dir = real_git_dir;
+       } else {
+               if (dest_exists)
+                       junk_git_dir_flags |= REMOVE_DIR_KEEP_TOPLEVEL;
+               junk_git_dir = git_dir;
+       }
        if (safe_create_leading_directories_const(git_dir) < 0)
                die(_("could not create leading directories of '%s'"), git_dir);
 
index 3b0b204b1e495626f3490d62f281291ee039ba42..6fe1c51281bf1bb6a92f00d837fecf60fe38ca31 100644 (file)
@@ -274,10 +274,13 @@ static void append_name(struct commit_name *n, struct strbuf *dst)
                n->name_checked = 1;
        }
 
-       if (n->tag)
+       if (n->tag) {
+               if (all)
+                       strbuf_addstr(dst, "tags/");
                strbuf_addstr(dst, n->tag->tag);
-       else
+       } else {
                strbuf_addstr(dst, n->path);
+       }
 }
 
 static void append_suffix(int depth, const struct object_id *oid, struct strbuf *dst)
index 93290962c95e6c27732f121f980d03289ac1ea6d..efe547e25fe2a53bd0ef7954cf3bec6d55218365 100644 (file)
--- a/bundle.c
+++ b/bundle.c
@@ -134,7 +134,6 @@ int verify_bundle(struct bundle_header *header, int verbose)
        struct ref_list *p = &header->prerequisites;
        struct rev_info revs;
        const char *argv[] = {NULL, "--all", NULL};
-       struct object_array refs;
        struct commit *commit;
        int i, ret = 0, req_nr;
        const char *message = _("Repository lacks these prerequisite commits:");
@@ -157,14 +156,6 @@ int verify_bundle(struct bundle_header *header, int verbose)
        req_nr = revs.pending.nr;
        setup_revisions(2, argv, &revs, NULL);
 
-       /* Save pending objects, so they can be cleaned up later. */
-       refs = revs.pending;
-       revs.leak_pending = 1;
-
-       /*
-        * prepare_revision_walk (together with .leak_pending = 1) makes us
-        * the sole owner of the list of pending objects.
-        */
        if (prepare_revision_walk(&revs))
                die(_("revision walk setup failed"));
 
@@ -173,18 +164,24 @@ int verify_bundle(struct bundle_header *header, int verbose)
                if (commit->object.flags & PREREQ_MARK)
                        i--;
 
-       for (i = 0; i < req_nr; i++)
-               if (!(refs.objects[i].item->flags & SHOWN)) {
-                       if (++ret == 1)
-                               error("%s", message);
-                       error("%s %s", oid_to_hex(&refs.objects[i].item->oid),
-                               refs.objects[i].name);
-               }
+       for (i = 0; i < p->nr; i++) {
+               struct ref_list_entry *e = p->list + i;
+               struct object *o = parse_object(&e->oid);
+               assert(o); /* otherwise we'd have returned early */
+               if (o->flags & SHOWN)
+                       continue;
+               if (++ret == 1)
+                       error("%s", message);
+               error("%s %s", oid_to_hex(&e->oid), e->name);
+       }
 
        /* Clean up objects used, as they will be reused. */
-       clear_commit_marks_for_object_array(&refs, ALL_REV_FLAGS);
-
-       object_array_clear(&refs);
+       for (i = 0; i < p->nr; i++) {
+               struct ref_list_entry *e = p->list + i;
+               commit = lookup_commit_reference_gently(&e->oid, 1);
+               if (commit)
+                       clear_commit_marks(commit, ALL_REV_FLAGS);
+       }
 
        if (verbose) {
                struct ref_list *r;
index cab8d4455bdbd6e4b87031613300be1112a19df5..ff51c9f34a975fdd3320f8c185f6e3c8b5176e81 100644 (file)
--- a/commit.c
+++ b/commit.c
@@ -547,7 +547,7 @@ void clear_commit_marks_many(int nr, struct commit **commit, unsigned int mark)
        struct commit_list *list = NULL;
 
        while (nr--) {
-               commit_list_insert(*commit, &list);
+               clear_commit_marks_1(&list, *commit, mark);
                commit++;
        }
        while (list)
@@ -559,20 +559,6 @@ void clear_commit_marks(struct commit *commit, unsigned int mark)
        clear_commit_marks_many(1, &commit, mark);
 }
 
-void clear_commit_marks_for_object_array(struct object_array *a, unsigned mark)
-{
-       struct object *object;
-       struct commit *commit;
-       unsigned int i;
-
-       for (i = 0; i < a->nr; i++) {
-               object = a->objects[i].item;
-               commit = lookup_commit_reference_gently(&object->oid, 1);
-               if (commit)
-                       clear_commit_marks(commit, mark);
-       }
-}
-
 struct commit *pop_commit(struct commit_list **stack)
 {
        struct commit_list *top = *stack;
@@ -929,8 +915,7 @@ static int remove_redundant(struct commit **array, int cnt)
                        if (work[j]->object.flags & PARENT1)
                                redundant[filled_index[j]] = 1;
                clear_commit_marks(array[i], all_flags);
-               for (j = 0; j < filled; j++)
-                       clear_commit_marks(work[j], all_flags);
+               clear_commit_marks_many(filled, work, all_flags);
                free_commit_list(common);
        }
 
index 8c68ca1a5a18721538bb44fe37cdf94223f2a5b5..425f4027752fb47190a53ddc72a64ebf9d928633 100644 (file)
--- a/commit.h
+++ b/commit.h
@@ -140,7 +140,6 @@ struct commit *pop_commit(struct commit_list **stack);
 
 void clear_commit_marks(struct commit *commit, unsigned int mark);
 void clear_commit_marks_many(int nr, struct commit **commit, unsigned int mark);
-void clear_commit_marks_for_object_array(struct object_array *a, unsigned mark);
 
 
 enum rev_sort_order {
index 28b325d75481b74e8f7b16485e1fc18ad854161c..964c3a75420db4751cf11125b68b6904112632f1 100755 (executable)
@@ -262,7 +262,7 @@ sub list_modified {
                }
        }
 
-       for (run_cmd_pipe(qw(git diff-files --numstat --summary --raw --), @ARGV)) {
+       for (run_cmd_pipe(qw(git diff-files --ignore-submodules=dirty --numstat --summary --raw --), @ARGV)) {
                if (($add, $del, $file) =
                    /^([-\d]+)  ([-\d]+)        (.*)/) {
                        $file = unquote_path($file);
index 1114005ce2829011cde2e6de608a2b90df355fc9..fc8f8ae6401dddcceaa82f9e9c748f5c185536d6 100755 (executable)
@@ -322,10 +322,9 @@ push_stash () {
 
                if test $# != 0
                then
-                       git reset -q -- "$@"
-                       git ls-files -z --modified -- "$@" |
+                       git add -u -- "$@" |
                        git checkout-index -z --force --stdin
-                       git clean --force -q -d -- "$@"
+                       git diff-index -p --cached --binary HEAD -- "$@" | git apply --index -R
                else
                        git reset --hard -q
                fi
index aa242d4f4f4363736730ccfcb4c2694d5be9a670..76a75d0b3dfe36f0c82c3951f8b7b04849f808e1 100755 (executable)
@@ -931,6 +931,7 @@ sub cmd_dcommit {
                # information from different SVN repos, and paths
                # which are not underneath this repository root.
                my $rooturl = $gs->repos_root;
+               Git::SVN::remove_username($rooturl);
                foreach my $d (@$linear_refs) {
                        my %parentshash;
                        read_commit_parents(\%parentshash, $d);
index 0fc580d8ca97c77d436f3351993300d19acd1ccc..cc5fa0a94965fad8821cdf81dfe84737f4dee043 100644 (file)
@@ -1026,10 +1026,19 @@ static int merge_file_1(struct merge_options *o,
                                                       &b->oid,
                                                       !o->call_depth);
                } else if (S_ISLNK(a->mode)) {
-                       oidcpy(&result->oid, &a->oid);
-
-                       if (!oid_eq(&a->oid, &b->oid))
-                               result->clean = 0;
+                       switch (o->recursive_variant) {
+                       case MERGE_RECURSIVE_NORMAL:
+                               oidcpy(&result->oid, &a->oid);
+                               if (!oid_eq(&a->oid, &b->oid))
+                                       result->clean = 0;
+                               break;
+                       case MERGE_RECURSIVE_OURS:
+                               oidcpy(&result->oid, &a->oid);
+                               break;
+                       case MERGE_RECURSIVE_THEIRS:
+                               oidcpy(&result->oid, &b->oid);
+                               break;
+                       }
                } else
                        die("BUG: unsupported object type in the tree");
        }
index b9a4a0e50172fb169226786b17134c6ab0627333..0afdfd19b784a541ad6d7237add2fbb1c9ec91ab 100644 (file)
--- a/object.c
+++ b/object.c
@@ -434,3 +434,14 @@ void clear_object_flags(unsigned flags)
                        obj->flags &= ~flags;
        }
 }
+
+void clear_commit_marks_all(unsigned int flags)
+{
+       int i;
+
+       for (i = 0; i < obj_hash_size; i++) {
+               struct object *obj = obj_hash[i];
+               if (obj && obj->type == OBJ_COMMIT)
+                       obj->flags &= ~flags;
+       }
+}
index f34461d4afde1b25c30fa8ac72428955c475c5b5..87563d90562b51859da8313b105a3e7785ed9d26 100644 (file)
--- a/object.h
+++ b/object.h
@@ -149,4 +149,9 @@ void object_array_clear(struct object_array *array);
 
 void clear_object_flags(unsigned flags);
 
+/*
+ * Clear the specified object flags from all in-core commit objects.
+ */
+extern void clear_commit_marks_all(unsigned int flags);
+
 #endif /* OBJECT_H */
index 3f9161707e66be86eabaf7347da23a2450ffdd9f..f9e25aea7a97e18b5723c8fa379da859d6dc9fcf 100644 (file)
@@ -1995,8 +1995,7 @@ static void do_merge_filter(struct ref_filter_cbdata *ref_cbdata)
                        free_array_item(item);
        }
 
-       for (i = 0; i < old_nr; i++)
-               clear_commit_marks(to_clear[i], ALL_REV_FLAGS);
+       clear_commit_marks_many(old_nr, to_clear, ALL_REV_FLAGS);
        clear_commit_marks(filter->merge_commit, ALL_REV_FLAGS);
        free(to_clear);
 }
index 998413b8bb8deaddef76d93f67be4a1435c9e3a7..f66fcb13425ab53e15ca47407e7c54be5dcdfc8b 100644 (file)
@@ -5,7 +5,7 @@
 
 /* The main repository */
 static struct repository the_repo = {
-       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &the_index, NULL, 0, 0
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &the_index, &hash_algos[GIT_HASH_SHA1], 0, 0
 };
 struct repository *the_repository = &the_repo;
 
index 72f2b4572ee798f9e17d6f4fbc0d12cfcd2fe221..1f7454c947a683eb2df28e51504bf67ebe8379cd 100644 (file)
@@ -2862,8 +2862,7 @@ int prepare_revision_walk(struct rev_info *revs)
                        }
                }
        }
-       if (!revs->leak_pending)
-               object_array_clear(&old_pending);
+       object_array_clear(&old_pending);
 
        /* Signal whether we need per-parent treesame decoration */
        if (revs->simplify_merges ||
index 19dc9bdddba20dfa6ef1bdaaee0e82db3bdf8bd8..d7a35c8c9e752cea0ea05ee7e13d696814470a83 100644 (file)
@@ -151,18 +151,6 @@ struct rev_info {
                        date_mode_explicit:1,
                        preserve_subject:1;
        unsigned int    disable_stdin:1;
-       /*
-        * Set `leak_pending` to prevent `prepare_revision_walk()` from clearing
-        * the array of pending objects (`pending`). It will still forget about
-        * the array and its entries, so they really are leaked. This can be
-        * useful if the `struct object_array` `pending` is copied before
-        * calling `prepare_revision_walk()`. By setting `leak_pending`, you
-        * effectively claim ownership of the old array, so you should most
-        * likely call `object_array_clear(&pending_copy)` once you are done.
-        * Observe that this is about ownership of the array and its entries,
-        * not the commits referenced by those entries.
-        */
-       unsigned int    leak_pending:1;
        /* --show-linear-break */
        unsigned int    track_linear:1,
                        track_first_time:1,
index 62aba19e7609678795d632d402dfd047d61d60bb..8b09c5bf328b880b7bbe10f37c7356b785473384 100755 (executable)
@@ -12,6 +12,9 @@ e.g. GIT_PERF_7820_GREP_OPTS=' -i'. Some options to try:
        -vi
        -vw
        -viw
+
+If GIT_PERF_GREP_THREADS is set to a list of threads (e.g. '1 4 8'
+etc.) we will test the patterns under those numbers of threads.
 "
 
 . ./perf-lib.sh
@@ -19,6 +22,11 @@ e.g. GIT_PERF_7820_GREP_OPTS=' -i'. Some options to try:
 test_perf_large_repo
 test_checkout_worktree
 
+if test -n "$GIT_PERF_GREP_THREADS"
+then
+       test_set_prereq PERF_GREP_ENGINES_THREADS
+fi
+
 for pattern in \
        'how.to' \
        '^how to' \
@@ -39,18 +47,42 @@ do
                else
                        prereq=""
                fi
-               test_perf $prereq "$engine grep$GIT_PERF_7820_GREP_OPTS '$pattern'" "
-                       git -c grep.patternType=$engine grep$GIT_PERF_7820_GREP_OPTS -- '$pattern' >'out.$engine' || :
-               "
-       done
-
-       test_expect_success "assert that all engines found the same for$GIT_PERF_7820_GREP_OPTS '$pattern'" '
-               test_cmp out.basic out.extended &&
-               if test_have_prereq PCRE
+               if ! test_have_prereq PERF_GREP_ENGINES_THREADS
                then
-                       test_cmp out.basic out.perl
+                       test_perf $prereq "$engine grep$GIT_PERF_7820_GREP_OPTS '$pattern'" "
+                               git -c grep.patternType=$engine grep$GIT_PERF_7820_GREP_OPTS -- '$pattern' >'out.$engine' || :
+                       "
+               else
+                       for threads in $GIT_PERF_GREP_THREADS
+                       do
+                               test_perf PTHREADS,$prereq "$engine grep$GIT_PERF_7820_GREP_OPTS '$pattern' with $threads threads" "
+                                       git -c grep.patternType=$engine -c grep.threads=$threads grep$GIT_PERF_7820_GREP_OPTS -- '$pattern' >'out.$engine.$threads' || :
+                               "
+                       done
                fi
-       '
+       done
+
+       if ! test_have_prereq PERF_GREP_ENGINES_THREADS
+       then
+               test_expect_success "assert that all engines found the same for$GIT_PERF_7820_GREP_OPTS '$pattern'" '
+                       test_cmp out.basic out.extended &&
+                       if test_have_prereq PCRE
+                       then
+                               test_cmp out.basic out.perl
+                       fi
+               '
+       else
+               for threads in $GIT_PERF_GREP_THREADS
+               do
+                       test_expect_success PTHREADS "assert that all engines found the same for$GIT_PERF_7820_GREP_OPTS '$pattern' under threading" "
+                               test_cmp out.basic.$threads out.extended.$threads &&
+                               if test_have_prereq PCRE
+                               then
+                                       test_cmp out.basic.$threads out.perl.$threads
+                               fi
+                       "
+               done
+       fi
 done
 
 test_done
index c7ef1e198fb9b803bcc5ed08fa553736ce5442d0..61e41b82cffa3721fbbc724fc699055c9457453a 100755 (executable)
@@ -6,6 +6,9 @@ Set GIT_PERF_7821_GREP_OPTS in the environment to pass options to
 git-grep. Make sure to include a leading space,
 e.g. GIT_PERF_7821_GREP_OPTS=' -w'. See p7820-grep-engines.sh for more
 options to try.
+
+If GIT_PERF_7821_THREADS is set to a list of threads (e.g. '1 4 8'
+etc.) we will test the patterns under those numbers of threads.
 "
 
 . ./perf-lib.sh
@@ -13,6 +16,11 @@ options to try.
 test_perf_large_repo
 test_checkout_worktree
 
+if test -n "$GIT_PERF_GREP_THREADS"
+then
+       test_set_prereq PERF_GREP_ENGINES_THREADS
+fi
+
 for pattern in 'int' 'uncommon' 'æ'
 do
        for engine in fixed basic extended perl
@@ -23,19 +31,44 @@ do
                else
                        prereq=""
                fi
-               test_perf $prereq "$engine grep$GIT_PERF_7821_GREP_OPTS $pattern" "
-                       git -c grep.patternType=$engine grep$GIT_PERF_7821_GREP_OPTS $pattern >'out.$engine' || :
-               "
-       done
-
-       test_expect_success "assert that all engines found the same for$GIT_PERF_7821_GREP_OPTS $pattern" '
-               test_cmp out.fixed out.basic &&
-               test_cmp out.fixed out.extended &&
-               if test_have_prereq PCRE
+               if ! test_have_prereq PERF_GREP_ENGINES_THREADS
                then
-                       test_cmp out.fixed out.perl
+                       test_perf $prereq "$engine grep$GIT_PERF_7821_GREP_OPTS $pattern" "
+                               git -c grep.patternType=$engine grep$GIT_PERF_7821_GREP_OPTS $pattern >'out.$engine' || :
+                       "
+               else
+                       for threads in $GIT_PERF_GREP_THREADS
+                       do
+                               test_perf PTHREADS,$prereq "$engine grep$GIT_PERF_7821_GREP_OPTS $pattern with $threads threads" "
+                                       git -c grep.patternType=$engine -c grep.threads=$threads grep$GIT_PERF_7821_GREP_OPTS $pattern >'out.$engine.$threads' || :
+                               "
+                       done
                fi
-       '
+       done
+
+       if ! test_have_prereq PERF_GREP_ENGINES_THREADS
+       then
+               test_expect_success "assert that all engines found the same for$GIT_PERF_7821_GREP_OPTS $pattern" '
+                       test_cmp out.fixed out.basic &&
+                       test_cmp out.fixed out.extended &&
+                       if test_have_prereq PCRE
+                       then
+                               test_cmp out.fixed out.perl
+                       fi
+               '
+       else
+               for threads in $GIT_PERF_GREP_THREADS
+               do
+                       test_expect_success PTHREADS "assert that all engines found the same for$GIT_PERF_7821_GREP_OPTS $pattern under threading" "
+                               test_cmp out.fixed.$threads out.basic.$threads &&
+                               test_cmp out.fixed.$threads out.extended.$threads &&
+                               if test_have_prereq PCRE
+                               then
+                                       test_cmp out.fixed.$threads out.perl.$threads
+                               fi
+                       "
+               done
+       fi
 done
 
 test_done
index a49c12c79b28fac8545dffcbaba8e8905c8d6222..058698df6a4a9811b9db84fb5900472c47c61798 100755 (executable)
@@ -493,4 +493,52 @@ test_expect_success 'add -p works even with color.ui=always' '
        test_cmp expect actual
 '
 
+test_expect_success 'setup different kinds of dirty submodules' '
+       test_create_repo for-submodules &&
+       (
+               cd for-submodules &&
+               test_commit initial &&
+               test_create_repo dirty-head &&
+               (
+                       cd dirty-head &&
+                       test_commit initial
+               ) &&
+               cp -R dirty-head dirty-otherwise &&
+               cp -R dirty-head dirty-both-ways &&
+               git add dirty-head &&
+               git add dirty-otherwise dirty-both-ways &&
+               git commit -m initial &&
+
+               cd dirty-head &&
+               test_commit updated &&
+               cd ../dirty-both-ways &&
+               test_commit updated &&
+               echo dirty >>initial &&
+               : >untracked &&
+               cd ../dirty-otherwise &&
+               echo dirty >>initial &&
+               : >untracked
+       ) &&
+       git -C for-submodules diff-files --name-only >actual &&
+       cat >expected <<-\EOF &&
+       dirty-both-ways
+       dirty-head
+       dirty-otherwise
+       EOF
+       test_cmp expected actual &&
+       git -C for-submodules diff-files --name-only --ignore-submodules=dirty >actual &&
+       cat >expected <<-\EOF &&
+       dirty-both-ways
+       dirty-head
+       EOF
+       test_cmp expected actual
+'
+
+test_expect_success 'status ignores dirty submodules (except HEAD)' '
+       git -C for-submodules add -i </dev/null >output &&
+       grep dirty-head output &&
+       grep dirty-both-ways output &&
+       ! grep dirty-otherwise output
+'
+
 test_done
index 39c7f2ebd740db097d67b12a68fa35f3fa884fc8..aefde7b1726bdc8d71d2b78e313e29daa2b31a24 100755 (executable)
@@ -1064,4 +1064,36 @@ test_expect_success 'stash -k -- <pathspec> leaves unstaged files intact' '
        test foo,bar = $(cat foo),$(cat bar)
 '
 
+test_expect_success 'stash -- <subdir> leaves untracked files in subdir intact' '
+       git reset &&
+       >subdir/untracked &&
+       >subdir/tracked1 &&
+       >subdir/tracked2 &&
+       git add subdir/tracked* &&
+       git stash -- subdir/ &&
+       test_path_is_missing subdir/tracked1 &&
+       test_path_is_missing subdir/tracked2 &&
+       test_path_is_file subdir/untracked &&
+       git stash pop &&
+       test_path_is_file subdir/tracked1 &&
+       test_path_is_file subdir/tracked2 &&
+       test_path_is_file subdir/untracked
+'
+
+test_expect_success 'stash -- <subdir> works with binary files' '
+       git reset &&
+       >subdir/untracked &&
+       >subdir/tracked &&
+       cp "$TEST_DIRECTORY"/test-binary-1.png subdir/tracked-binary &&
+       git add subdir/tracked* &&
+       git stash -- subdir/ &&
+       test_path_is_missing subdir/tracked &&
+       test_path_is_missing subdir/tracked-binary &&
+       test_path_is_file subdir/untracked &&
+       git stash pop &&
+       test_path_is_file subdir/tracked &&
+       test_path_is_file subdir/tracked-binary &&
+       test_path_is_file subdir/untracked
+'
+
 test_done
index 4435693bb2ca48d053003c87fccd8f8612d8b4a9..4a1a912e032983383a3449d60753ced741680153 100755 (executable)
@@ -7,46 +7,94 @@ test_description='test git clone to cleanup after failure
 
 This test covers the fact that if git clone fails, it should remove
 the directory it created, to avoid the user having to manually
-remove the directory before attempting a clone again.'
+remove the directory before attempting a clone again.
+
+Unless the directory already exists, in which case we clean up only what we
+wrote.
+'
 
 . ./test-lib.sh
 
-test_expect_success \
-    'clone of non-existent source should fail' \
-    'test_must_fail git clone foo bar'
+corrupt_repo () {
+       test_when_finished "rmdir foo/.git/objects.bak" &&
+       mkdir foo/.git/objects.bak/ &&
+       test_when_finished "mv foo/.git/objects.bak/* foo/.git/objects/" &&
+       mv foo/.git/objects/* foo/.git/objects.bak/
+}
 
-test_expect_success \
-    'failed clone should not leave a directory' \
-    '! test -d bar'
+test_expect_success 'clone of non-existent source should fail' '
+       test_must_fail git clone foo bar
+'
 
-# Need a repo to clone
-test_create_repo foo
+test_expect_success 'failed clone should not leave a directory' '
+       test_path_is_missing bar
+'
 
-# clone doesn't like it if there is no HEAD. Is that a bug?
-(cd foo && touch file && git add file && git commit -m 'add file' >/dev/null 2>&1)
+test_expect_success 'create a repo to clone' '
+       test_create_repo foo
+'
+
+test_expect_success 'create objects in repo for later corruption' '
+       test_commit -C foo file
+'
 
 # source repository given to git clone should be relative to the
 # current path not to the target dir
-test_expect_success \
-    'clone of non-existent (relative to $PWD) source should fail' \
-    'test_must_fail git clone ../foo baz'
+test_expect_success 'clone of non-existent (relative to $PWD) source should fail' '
+       test_must_fail git clone ../foo baz
+'
 
-test_expect_success \
-    'clone should work now that source exists' \
-    'git clone foo bar'
+test_expect_success 'clone should work now that source exists' '
+       git clone foo bar
+'
 
-test_expect_success \
-    'successful clone must leave the directory' \
-    'test -d bar'
+test_expect_success 'successful clone must leave the directory' '
+       test_path_is_dir bar
+'
 
 test_expect_success 'failed clone --separate-git-dir should not leave any directories' '
-       mkdir foo/.git/objects.bak/ &&
-       mv foo/.git/objects/* foo/.git/objects.bak/ &&
+       corrupt_repo &&
        test_must_fail git clone --separate-git-dir gitdir foo worktree &&
-       test_must_fail test -e gitdir &&
-       test_must_fail test -e worktree &&
-       mv foo/.git/objects.bak/* foo/.git/objects/ &&
-       rmdir foo/.git/objects.bak
+       test_path_is_missing gitdir &&
+       test_path_is_missing worktree
+'
+
+test_expect_success 'failed clone into empty leaves directory (vanilla)' '
+       mkdir -p empty &&
+       corrupt_repo &&
+       test_must_fail git clone foo empty &&
+       test_dir_is_empty empty
+'
+
+test_expect_success 'failed clone into empty leaves directory (bare)' '
+       mkdir -p empty &&
+       corrupt_repo &&
+       test_must_fail git clone --bare foo empty &&
+       test_dir_is_empty empty
+'
+
+test_expect_success 'failed clone into empty leaves directory (separate)' '
+       mkdir -p empty-git empty-wt &&
+       corrupt_repo &&
+       test_must_fail git clone --separate-git-dir empty-git foo empty-wt &&
+       test_dir_is_empty empty-git &&
+       test_dir_is_empty empty-wt
+'
+
+test_expect_success 'failed clone into empty leaves directory (separate, git)' '
+       mkdir -p empty-git &&
+       corrupt_repo &&
+       test_must_fail git clone --separate-git-dir empty-git foo no-wt &&
+       test_dir_is_empty empty-git &&
+       test_path_is_missing no-wt
+'
+
+test_expect_success 'failed clone into empty leaves directory (separate, wt)' '
+       mkdir -p empty-wt &&
+       corrupt_repo &&
+       test_must_fail git clone --separate-git-dir no-git foo empty-wt &&
+       test_path_is_missing no-git &&
+       test_dir_is_empty empty-wt
 '
 
 test_done
index 0f895478f02bcf4cc4408ce065e79e0314b66793..8c437bf8721f929155fa2ddab1677c050ae5caca 100755 (executable)
@@ -611,4 +611,21 @@ test_expect_success 'GIT_TRACE_PACKFILE produces a usable pack' '
        git -C replay.git index-pack -v --stdin <tmp.pack
 '
 
+hex2oct () {
+       perl -ne 'printf "\\%03o", hex for /../g'
+}
+
+test_expect_success 'clone on case-insensitive fs' '
+       git init icasefs &&
+       (
+               cd icasefs
+               o=$(git hash-object -w --stdin </dev/null | hex2oct) &&
+               t=$(printf "100644 X\0${o}100644 x\0${o}" |
+                       git hash-object -w -t tree --stdin) &&
+               c=$(git commit-tree -m bogus $t) &&
+               git update-ref refs/heads/bogus $c &&
+               git clone -b bogus . bogus
+       )
+'
+
 test_done
index 3889eca4ae8524cd62eaf45b4d7a2394e53da429..0aebc6c028e06c8d98600ecbe37c0b0989a89bd8 100755 (executable)
@@ -73,4 +73,36 @@ test_expect_success 'pull passes -X to underlying merge' '
        git reset --hard master && test_must_fail git pull -s recursive -X bork . side
 '
 
+test_expect_success SYMLINKS 'symlink with -Xours/-Xtheirs' '
+       git reset --hard master &&
+       git checkout -b two master &&
+       ln -s target-zero link &&
+       git add link &&
+       git commit -m "add link pointing to zero" &&
+
+       ln -f -s target-two link &&
+       git commit -m "add link pointing to two" link &&
+
+       git checkout -b one HEAD^ &&
+       ln -f -s target-one link &&
+       git commit -m "add link pointing to one" link &&
+
+       # we expect symbolic links not to resolve automatically, of course
+       git checkout one^0 &&
+       test_must_fail git merge -s recursive two &&
+
+       # favor theirs to resolve to target-two?
+       git reset --hard &&
+       git checkout one^0 &&
+       git merge -s recursive -X theirs two &&
+       git diff --exit-code two HEAD link &&
+
+       # favor ours to resolve to target-one?
+       git reset --hard &&
+       git checkout one^0 &&
+       git merge -s recursive -X ours two &&
+       git diff --exit-code one HEAD link
+
+'
+
 test_done
index 3e3fb462a098c01c72270acbb276abd2df225a66..a5d901502414f25616a474152ee0f5816465bd37 100755 (executable)
@@ -122,7 +122,7 @@ test_expect_success 'describe --contains defaults to HEAD without commit-ish' '
 '
 
 : >err.expect
-check_describe A --all A^0
+check_describe tags/A --all A^0
 test_expect_success 'no warning was displayed for A' '
        test_cmp err.expect err.actual
 '
@@ -374,4 +374,8 @@ test_expect_success ULIMIT_STACK_SIZE 'describe works in a deep repo' '
        test_cmp expect actual
 '
 
+check_describe tags/A --all A
+check_describe tags/c --all c
+check_describe heads/branch_A --all --match='branch_*' branch_A
+
 test_done