Merge branch 'maint' of git://github.com/git-l10n/git-po into maint
authorJunio C Hamano <gitster@pobox.com>
Sun, 28 Sep 2014 07:02:57 +0000 (00:02 -0700)
committerJunio C Hamano <gitster@pobox.com>
Sun, 28 Sep 2014 07:02:57 +0000 (00:02 -0700)
* 'maint' of git://github.com/git-l10n/git-po:
l10n: de.po: use comma before "um"
l10n: de.po: change Email to E-Mail
po/TEAMS: add new member to German translation team

27 files changed:
Documentation/RelNotes/2.1.1.txt [new file with mode: 0644]
Documentation/git.txt
Documentation/technical/pack-protocol.txt
GIT-VERSION-GEN
RelNotes
builtin/apply.c
builtin/fetch.c
bundle.c
combine-diff.c
commit.h
config.c
contrib/completion/git-prompt.sh
fast-import.c
log-tree.c
pretty.c
read-cache.c
refs.c
revision.c
t/t1300-repo-config.sh
t/t3210-pack-refs.sh
t/t4119-apply-config.sh
t/t4124-apply-ws-rule.sh
t/t5704-bundle.sh
t/t7201-co.sh
t/t7515-status-symlinks.sh [new file with mode: 0755]
unpack-trees.c
upload-pack.c
diff --git a/Documentation/RelNotes/2.1.1.txt b/Documentation/RelNotes/2.1.1.txt
new file mode 100644 (file)
index 0000000..830fc3c
--- /dev/null
@@ -0,0 +1,44 @@
+Git v2.1.1 Release Notes
+========================
+
+ * Git 2.0 had a regression where "git fetch" into a shallowly
+   cloned repository from a repository with bitmap object index
+   enabled did not work correctly.  This has been corrected.
+
+ * Git 2.0 had a regression which broke (rarely used) "git diff-tree
+   -t".  This has been corrected.
+
+ * "git log --pretty/format=" with an empty format string did not
+   mean the more obvious "No output whatsoever" but "Use default
+   format", which was counterintuitive.  Now it means "nothing shown
+   for the log message part".
+
+ * "git -c section.var command" and "git -c section.var= command"
+   should pass the configuration differently (the former should be a
+   boolean true, the latter should be an empty string), but they
+   didn't work that way.  Now it does.
+
+ * Applying a patch not generated by Git in a subdirectory used to
+   check the whitespace breakage using the attributes for incorrect
+   paths. Also whitespace checks were performed even for paths
+   excluded via "git apply --exclude=<path>" mechanism.
+
+ * "git bundle create" with date-range specification were meant to
+   exclude tags outside the range, but it did not work correctly.
+
+ * "git add x" where x that used to be a directory has become a
+   symbolic link to a directory misbehaved.
+
+ * The prompt script checked $GIT_DIR/ref/stash file to see if there
+   is a stash, which was a no-no.
+
+ * "git checkout -m" did not switch to another branch while carrying
+   the local changes forward when a path was deleted from the index.
+
+ * With sufficiently long refnames, fast-import could have overflown
+   an on-stack buffer.
+
+ * After "pack-refs --prune" packed refs at the top-level, it failed
+   to prune them.
+
+ * "git gc --auto" triggered from "git fetch --quiet" was not quiet.
index de7b870a35e63e43652be6468e6e5a17d2708a14..8b2c5424c4243f3d9cb791dcc47f3989006b688d 100644 (file)
@@ -43,9 +43,10 @@ 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.1.0/git.html[documentation for release 2.1]
+* link:v2.1.1/git.html[documentation for release 2.1.1]
 
 * release notes for
+  link:RelNotes/2.1.1.txt[2.1.1],
   link:RelNotes/2.1.0.txt[2.1].
 
 * link:v2.0.4/git.html[documentation for release 2.0.4]
@@ -452,6 +453,11 @@ example the following invocations are equivalent:
        given will override values from configuration files.
        The <name> is expected in the same format as listed by
        'git config' (subkeys separated by dots).
++
+Note that omitting the `=` in `git -c foo.bar ...` is allowed and sets
+`foo.bar` to the boolean true value (just like `[foo]bar` would in a
+config file). Including the equals but with an empty value (like `git -c
+foo.bar= ...`) sets `foo.bar` to the empty string.
 
 --exec-path[=<path>]::
        Path to wherever your core Git programs are installed.
index 18dea8d15fa159b719a38588a0a346e58120ac61..569c48a352b76ab3fc0d31f21f0f1a1bd654f41d 100644 (file)
@@ -467,7 +467,7 @@ references.
 ----
   update-request    =  *shallow command-list [pack-file]
 
-  shallow           =  PKT-LINE("shallow" SP obj-id)
+  shallow           =  PKT-LINE("shallow" SP obj-id LF)
 
   command-list      =  PKT-LINE(command NUL capability-list LF)
                       *PKT-LINE(command LF)
index a4cdfbf7f6b547a45c9c561757c1588fe0fba369..c76c8d6dfd0226743d108f5a9327562dd8a5dc6d 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v2.1.0
+DEF_VER=v2.1.1
 
 LF='
 '
index bf760914010786c830233effc8b96ddacfb114fd..12cca326305836cae65aafea3e0dc824abfa932a 120000 (symlink)
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/2.1.0.txt
\ No newline at end of file
+Documentation/RelNotes/2.1.1.txt
\ No newline at end of file
index be2b4ce2fd91640379b0a65d0aa90238d7edfd64..6b7c764918cff18957f67a2e345c0610e459859d 100644 (file)
@@ -1920,6 +1920,66 @@ static int parse_binary(char *buffer, unsigned long size, struct patch *patch)
        return used;
 }
 
+static void prefix_one(char **name)
+{
+       char *old_name = *name;
+       if (!old_name)
+               return;
+       *name = xstrdup(prefix_filename(prefix, prefix_length, *name));
+       free(old_name);
+}
+
+static void prefix_patch(struct patch *p)
+{
+       if (!prefix || p->is_toplevel_relative)
+               return;
+       prefix_one(&p->new_name);
+       prefix_one(&p->old_name);
+}
+
+/*
+ * include/exclude
+ */
+
+static struct string_list limit_by_name;
+static int has_include;
+static void add_name_limit(const char *name, int exclude)
+{
+       struct string_list_item *it;
+
+       it = string_list_append(&limit_by_name, name);
+       it->util = exclude ? NULL : (void *) 1;
+}
+
+static int use_patch(struct patch *p)
+{
+       const char *pathname = p->new_name ? p->new_name : p->old_name;
+       int i;
+
+       /* Paths outside are not touched regardless of "--include" */
+       if (0 < prefix_length) {
+               int pathlen = strlen(pathname);
+               if (pathlen <= prefix_length ||
+                   memcmp(prefix, pathname, prefix_length))
+                       return 0;
+       }
+
+       /* See if it matches any of exclude/include rule */
+       for (i = 0; i < limit_by_name.nr; i++) {
+               struct string_list_item *it = &limit_by_name.items[i];
+               if (!wildmatch(it->string, pathname, 0, NULL))
+                       return (it->util != NULL);
+       }
+
+       /*
+        * If we had any include, a path that does not match any rule is
+        * not used.  Otherwise, we saw bunch of exclude rules (or none)
+        * and such a path is used.
+        */
+       return !has_include;
+}
+
+
 /*
  * Read the patch text in "buffer" that extends for "size" bytes; stop
  * reading after seeing a single patch (i.e. changes to a single file).
@@ -1935,9 +1995,14 @@ static int parse_chunk(char *buffer, unsigned long size, struct patch *patch)
        if (offset < 0)
                return offset;
 
-       patch->ws_rule = whitespace_rule(patch->new_name
-                                        ? patch->new_name
-                                        : patch->old_name);
+       prefix_patch(patch);
+
+       if (!use_patch(patch))
+               patch->ws_rule = 0;
+       else
+               patch->ws_rule = whitespace_rule(patch->new_name
+                                                ? patch->new_name
+                                                : patch->old_name);
 
        patchsize = parse_single_patch(buffer + offset + hdrsize,
                                       size - offset - hdrsize, patch);
@@ -4127,64 +4192,6 @@ static int write_out_results(struct patch *list)
 
 static struct lock_file lock_file;
 
-static struct string_list limit_by_name;
-static int has_include;
-static void add_name_limit(const char *name, int exclude)
-{
-       struct string_list_item *it;
-
-       it = string_list_append(&limit_by_name, name);
-       it->util = exclude ? NULL : (void *) 1;
-}
-
-static int use_patch(struct patch *p)
-{
-       const char *pathname = p->new_name ? p->new_name : p->old_name;
-       int i;
-
-       /* Paths outside are not touched regardless of "--include" */
-       if (0 < prefix_length) {
-               int pathlen = strlen(pathname);
-               if (pathlen <= prefix_length ||
-                   memcmp(prefix, pathname, prefix_length))
-                       return 0;
-       }
-
-       /* See if it matches any of exclude/include rule */
-       for (i = 0; i < limit_by_name.nr; i++) {
-               struct string_list_item *it = &limit_by_name.items[i];
-               if (!wildmatch(it->string, pathname, 0, NULL))
-                       return (it->util != NULL);
-       }
-
-       /*
-        * If we had any include, a path that does not match any rule is
-        * not used.  Otherwise, we saw bunch of exclude rules (or none)
-        * and such a path is used.
-        */
-       return !has_include;
-}
-
-
-static void prefix_one(char **name)
-{
-       char *old_name = *name;
-       if (!old_name)
-               return;
-       *name = xstrdup(prefix_filename(prefix, prefix_length, *name));
-       free(old_name);
-}
-
-static void prefix_patches(struct patch *p)
-{
-       if (!prefix || p->is_toplevel_relative)
-               return;
-       for ( ; p; p = p->next) {
-               prefix_one(&p->new_name);
-               prefix_one(&p->old_name);
-       }
-}
-
 #define INACCURATE_EOF (1<<0)
 #define RECOUNT                (1<<1)
 
@@ -4210,8 +4217,6 @@ static int apply_patch(int fd, const char *filename, int options)
                        break;
                if (apply_in_reverse)
                        reverse_patches(patch);
-               if (prefix)
-                       prefix_patches(patch);
                if (use_patch(patch)) {
                        patch_stats(patch);
                        *listp = patch;
index e8d0cca3e4110e1ae6db82f21c899c44460cb849..159fb7e91614253cf7820b0c4cd7d07407c76762 100644 (file)
@@ -1110,9 +1110,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
        struct string_list list = STRING_LIST_INIT_NODUP;
        struct remote *remote;
        int result = 0;
-       static const char *argv_gc_auto[] = {
-               "gc", "--auto", NULL,
-       };
+       struct argv_array argv_gc_auto = ARGV_ARRAY_INIT;
 
        packet_trace_identity("fetch");
 
@@ -1198,7 +1196,11 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
        list.strdup_strings = 1;
        string_list_clear(&list, 0);
 
-       run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);
+       argv_array_pushl(&argv_gc_auto, "gc", "--auto", NULL);
+       if (verbosity < 0)
+               argv_array_push(&argv_gc_auto, "--quiet");
+       run_command_v_opt(argv_gc_auto.argv, RUN_GIT_CMD);
+       argv_array_clear(&argv_gc_auto);
 
        return result;
 }
index 71a21a67fa6bc5ce718dfc6593035f577b2dbc15..b708906cdbd2a14d0e5bcd1e1288c78777cf6a5e 100644 (file)
--- a/bundle.c
+++ b/bundle.c
@@ -221,8 +221,8 @@ static int is_tag_in_date_range(struct object *tag, struct rev_info *revs)
        line = memmem(buf, size, "\ntagger ", 8);
        if (!line++)
                return 1;
-       lineend = memchr(line, buf + size - line, '\n');
-       line = memchr(line, lineend ? lineend - line : buf + size - line, '>');
+       lineend = memchr(line, '\n', buf + size - line);
+       line = memchr(line, '>', lineend ? lineend - line : buf + size - line);
        if (!line++)
                return 1;
        date = strtoul(line, NULL, 10);
index 60cb4f81f9788efeff21d05d48f2183e94765385..91edce58e15b82428fcc5f3b006e23bf5380d38c 100644 (file)
@@ -1407,7 +1407,8 @@ void diff_tree_combined(const unsigned char *sha1,
                show_log(rev);
 
                if (rev->verbose_header && opt->output_format &&
-                   opt->output_format != DIFF_FORMAT_NO_OUTPUT)
+                   opt->output_format != DIFF_FORMAT_NO_OUTPUT &&
+                   !commit_format_is_empty(rev->commit_format))
                        printf("%s%c", diff_line_prefix(opt),
                               opt->line_termination);
        }
index a8cbf52f15ff01778ba61a5a888263d424b2d8d2..aa8c3ca50af42375caf954e309d76731b4a9295e 100644 (file)
--- a/commit.h
+++ b/commit.h
@@ -159,6 +159,7 @@ extern void get_commit_format(const char *arg, struct rev_info *);
 extern const char *format_subject(struct strbuf *sb, const char *msg,
                                  const char *line_separator);
 extern void userformat_find_requirements(const char *fmt, struct userformat_want *w);
+extern int commit_format_is_empty(enum cmit_fmt);
 extern void format_commit_message(const struct commit *commit,
                                  const char *format, struct strbuf *sb,
                                  const struct pretty_print_context *context);
index 058505cb8d8d8bb531527b620125b0204732458a..6cbf701a8f3e8837dac9c308cc19a1483114879d 100644 (file)
--- a/config.c
+++ b/config.c
@@ -162,19 +162,27 @@ void git_config_push_parameter(const char *text)
 int git_config_parse_parameter(const char *text,
                               config_fn_t fn, void *data)
 {
+       const char *value;
        struct strbuf **pair;
+
        pair = strbuf_split_str(text, '=', 2);
        if (!pair[0])
                return error("bogus config parameter: %s", text);
-       if (pair[0]->len && pair[0]->buf[pair[0]->len - 1] == '=')
+
+       if (pair[0]->len && pair[0]->buf[pair[0]->len - 1] == '=') {
                strbuf_setlen(pair[0], pair[0]->len - 1);
+               value = pair[1] ? pair[1]->buf : "";
+       } else {
+               value = NULL;
+       }
+
        strbuf_trim(pair[0]);
        if (!pair[0]->len) {
                strbuf_list_free(pair);
                return error("bogus config parameter: %s", text);
        }
        strbuf_tolower(pair[0]);
-       if (fn(pair[0]->buf, pair[1] ? pair[1]->buf : NULL, data) < 0) {
+       if (fn(pair[0]->buf, value, data) < 0) {
                strbuf_list_free(pair);
                return -1;
        }
index 9d684b10a67ea663410db3ba68482c1a52bbc367..c5473dc8dba78b372fd95ef2bf5257ff5cdc3baf 100644 (file)
@@ -468,7 +468,8 @@ __git_ps1 ()
                        fi
                fi
                if [ -n "${GIT_PS1_SHOWSTASHSTATE-}" ] &&
-                  [ -r "$g/refs/stash" ]; then
+                  git rev-parse --verify --quiet refs/stash >/dev/null
+               then
                        s="$"
                fi
 
index d73f58cbe3fe4522fa24d47f9086d927b3296c8b..a1479e980da154f9179d71aeeda7746770686baa 100644 (file)
@@ -946,10 +946,12 @@ static void unkeep_all_packs(void)
 
 static void end_packfile(void)
 {
-       struct packed_git *old_p = pack_data, *new_p;
+       if (!pack_data)
+               return;
 
        clear_delta_base_cache();
        if (object_count) {
+               struct packed_git *new_p;
                unsigned char cur_pack_sha1[20];
                char *idx_name;
                int i;
@@ -991,10 +993,11 @@ static void end_packfile(void)
                pack_id++;
        }
        else {
-               close(old_p->pack_fd);
-               unlink_or_warn(old_p->pack_name);
+               close(pack_data->pack_fd);
+               unlink_or_warn(pack_data->pack_name);
        }
-       free(old_p);
+       free(pack_data);
+       pack_data = NULL;
 
        /* We can't carry a delta across packfiles. */
        strbuf_release(&last_blob.data);
@@ -1731,14 +1734,16 @@ static void dump_tags(void)
        static const char *msg = "fast-import";
        struct tag *t;
        struct ref_lock *lock;
-       char ref_name[PATH_MAX];
+       struct strbuf ref_name = STRBUF_INIT;
 
        for (t = first_tag; t; t = t->next_tag) {
-               sprintf(ref_name, "tags/%s", t->name);
-               lock = lock_ref_sha1(ref_name, NULL);
+               strbuf_reset(&ref_name);
+               strbuf_addf(&ref_name, "tags/%s", t->name);
+               lock = lock_ref_sha1(ref_name.buf, NULL);
                if (!lock || write_ref_sha1(lock, t->sha1, msg) < 0)
-                       failure |= error("Unable to update %s", ref_name);
+                       failure |= error("Unable to update %s", ref_name.buf);
        }
+       strbuf_release(&ref_name);
 }
 
 static void dump_marks_helper(FILE *f,
index 0c53dc11abf5aa10c83b35f07452f3c00a2998d4..95e9b1da259ef33a1c5bc7f7d07e853ebc5dbcec 100644 (file)
@@ -649,7 +649,7 @@ void show_log(struct rev_info *opt)
                graph_show_commit_msg(opt->graph, &msgbuf);
        else
                fwrite(msgbuf.buf, sizeof(char), msgbuf.len, stdout);
-       if (opt->use_terminator) {
+       if (opt->use_terminator && !commit_format_is_empty(opt->commit_format)) {
                if (!opt->missing_newline)
                        graph_show_padding(opt->graph);
                putchar(opt->diffopt.line_termination);
@@ -676,7 +676,8 @@ int log_tree_diff_flush(struct rev_info *opt)
                show_log(opt);
                if ((opt->diffopt.output_format & ~DIFF_FORMAT_NO_OUTPUT) &&
                    opt->verbose_header &&
-                   opt->commit_format != CMIT_FMT_ONELINE) {
+                   opt->commit_format != CMIT_FMT_ONELINE &&
+                   !commit_format_is_empty(opt->commit_format)) {
                        /*
                         * When showing a verbose header (i.e. log message),
                         * and not in --pretty=oneline format, we would want
index 3a1da6fd329efe1723bdb906a907ce4160c4633a..31fc76b2fde8297298a7d9ffd38ea7f00eede2fa 100644 (file)
--- a/pretty.c
+++ b/pretty.c
@@ -24,6 +24,11 @@ static size_t commit_formats_len;
 static size_t commit_formats_alloc;
 static struct cmt_fmt_map *find_commit_format(const char *sought);
 
+int commit_format_is_empty(enum cmit_fmt fmt)
+{
+       return fmt == CMIT_FMT_USERFORMAT && !*user_format;
+}
+
 static void save_user_format(struct rev_info *rev, const char *cp, int is_tformat)
 {
        free(user_format);
@@ -146,7 +151,7 @@ void get_commit_format(const char *arg, struct rev_info *rev)
        struct cmt_fmt_map *commit_format;
 
        rev->use_terminator = 0;
-       if (!arg || !*arg) {
+       if (!arg) {
                rev->commit_format = CMIT_FMT_DEFAULT;
                return;
        }
@@ -155,7 +160,7 @@ void get_commit_format(const char *arg, struct rev_info *rev)
                return;
        }
 
-       if (strchr(arg, '%')) {
+       if (!*arg || strchr(arg, '%')) {
                save_user_format(rev, arg, 1);
                return;
        }
index 5d3c8bd4aaffda9915a3fd62d9d9800f4ac8baff..6f0057fe66a59e1239703ee4458de200304f727a 100644 (file)
@@ -1064,6 +1064,14 @@ static struct cache_entry *refresh_cache_ent(struct index_state *istate,
                return ce;
        }
 
+       if (has_symlink_leading_path(ce->name, ce_namelen(ce))) {
+               if (ignore_missing)
+                       return ce;
+               if (err)
+                       *err = ENOENT;
+               return NULL;
+       }
+
        if (lstat(ce->name, &st) < 0) {
                if (ignore_missing && errno == ENOENT)
                        return ce;
diff --git a/refs.c b/refs.c
index 27927f2319130cc0575817542dfd47c37cc5149b..82e5b1b14f7a6e7341dfcf8fbf61ae3982851e18 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -2387,7 +2387,8 @@ static void try_remove_empty_parents(char *name)
 /* make sure nobody touched the ref, and unlink */
 static void prune_ref(struct ref_to_prune *r)
 {
-       struct ref_lock *lock = lock_ref_sha1(r->name + 5, r->sha1);
+       struct ref_lock *lock = lock_any_ref_for_update(r->name, r->sha1,
+                                                       0, NULL);
 
        if (lock) {
                unlink_or_warn(git_path("%s", r->name));
index 2571ada6bf66ce6e945c539be4b0123e5b9648a9..615535c98453336323a437530132f27824b51ac2 100644 (file)
@@ -1825,7 +1825,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
        } else if (!strcmp(arg, "--pretty")) {
                revs->verbose_header = 1;
                revs->pretty_given = 1;
-               get_commit_format(arg+8, revs);
+               get_commit_format(NULL, revs);
        } else if (starts_with(arg, "--pretty=") || starts_with(arg, "--format=")) {
                /*
                 * Detached form ("--pretty X" as opposed to "--pretty=X")
index 3f80ff0c14c47b87bbbecb74d1951a1abe6bc5ba..46f6ae25714d55066159d96f4a496f60a10790da 100755 (executable)
@@ -1010,6 +1010,17 @@ test_expect_success 'git -c "key=value" support' '
        test_must_fail git -c name=value config core.name
 '
 
+# We just need a type-specifier here that cares about the
+# distinction internally between a NULL boolean and a real
+# string (because most of git's internal parsers do care).
+# Using "--path" works, but we do not otherwise care about
+# its semantics.
+test_expect_success 'git -c can represent empty string' '
+       echo >expect &&
+       git -c foo.empty= config --path foo.empty >actual &&
+       test_cmp expect actual
+'
+
 test_expect_success 'key sanity-checking' '
        test_must_fail git config foo=bar &&
        test_must_fail git config foo=.bar &&
index 1a2080e3dca272b6ed40739a7539f01f4f6ae65c..3a017bf437395526cf54403d4ea1db36a3cff0b3 100755 (executable)
@@ -151,4 +151,11 @@ test_expect_success 'delete ref while another dangling packed ref' '
        test_cmp /dev/null result
 '
 
+test_expect_success 'pack ref directly below refs/' '
+       git update-ref refs/top HEAD &&
+       git pack-refs --all --prune &&
+       grep refs/top .git/packed-refs &&
+       test_path_is_missing .git/refs/top
+'
+
 test_done
index c393be691be42a0b0a982c07ffeee489d4075bce..a9a05838119c85bc017f1404b134d393029843b2 100755 (executable)
@@ -159,4 +159,21 @@ test_expect_success 'same but with traditional patch input of depth 2' '
        check_result sub/file1
 '
 
+test_expect_success 'in subdir with traditional patch input' '
+       cd "$D" &&
+       git config apply.whitespace strip &&
+       cat >.gitattributes <<-EOF &&
+       /* whitespace=blank-at-eol
+       sub/* whitespace=-blank-at-eol
+       EOF
+       rm -f sub/file1 &&
+       cp saved sub/file1 &&
+       git update-index --refresh &&
+
+       cd sub &&
+       git apply ../gpatch.file &&
+       echo "B " >expect &&
+       test_cmp expect file1
+'
+
 test_done
index 5d0c5983381b4072d915de0f8d75053b19172d66..c6474de4c8c30eba9b5375f6c4e176e67c1fd001 100755 (executable)
@@ -512,4 +512,15 @@ test_expect_success 'whitespace=fix to expand' '
        git -c core.whitespace=tab-in-indent apply --whitespace=fix patch
 '
 
+test_expect_success 'whitespace check skipped for excluded paths' '
+       git config core.whitespace blank-at-eol &&
+       >used &&
+       >unused &&
+       git add used unused &&
+       echo "used" >used &&
+       echo "unused " >unused &&
+       git diff-files -p used unused >patch &&
+       git apply --include=used --stat --whitespace=error <patch
+'
+
 test_done
index a45c31692e17218988e6619742c366043e426039..348d9b3bc7ad3ea512f68b6200481c9f6b90d792 100755 (executable)
@@ -14,7 +14,10 @@ test_expect_success 'setup' '
        git tag -d third
 '
 
-test_expect_success 'tags can be excluded by rev-list options' '
+test_expect_success 'annotated tags can be excluded by rev-list options' '
+       git bundle create bundle --all --since=7.Apr.2005.15:14:00.-0700 &&
+       git ls-remote bundle > output &&
+       grep tag output &&
        git bundle create bundle --all --since=7.Apr.2005.15:16:00.-0700 &&
        git ls-remote bundle > output &&
        ! grep tag output
index 0c9ec0ad44ef4e3239e67a0c9e9ecc1340dcee8a..eae9e5a937150d60002620c8b29293f4d7ed122f 100755 (executable)
@@ -223,6 +223,23 @@ test_expect_success 'checkout --merge --conflict=diff3 <branch>' '
        test_cmp two expect
 '
 
+test_expect_success 'switch to another branch while carrying a deletion' '
+
+       git checkout -f master && git reset --hard && git clean -f &&
+       git rm two &&
+
+       test_must_fail git checkout simple 2>errs &&
+       test_i18ngrep overwritten errs &&
+
+       git checkout --merge simple 2>errs &&
+       test_i18ngrep ! overwritten errs &&
+       git ls-files -u &&
+       test_must_fail git cat-file -t :0:two &&
+       test "$(git cat-file -t :1:two)" = blob &&
+       test "$(git cat-file -t :2:two)" = blob &&
+       test_must_fail git cat-file -t :3:two
+'
+
 test_expect_success 'checkout to detach HEAD (with advice declined)' '
 
        git config advice.detachedHead false &&
diff --git a/t/t7515-status-symlinks.sh b/t/t7515-status-symlinks.sh
new file mode 100755 (executable)
index 0000000..9f989be
--- /dev/null
@@ -0,0 +1,43 @@
+#!/bin/sh
+
+test_description='git status and symlinks'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+       echo .gitignore >.gitignore &&
+       echo actual >>.gitignore &&
+       echo expect >>.gitignore &&
+       mkdir dir &&
+       echo x >dir/file1 &&
+       echo y >dir/file2 &&
+       git add dir &&
+       git commit -m initial &&
+       git tag initial
+'
+
+test_expect_success SYMLINKS 'symlink to a directory' '
+       test_when_finished "rm symlink" &&
+       ln -s dir symlink &&
+       echo "?? symlink" >expect &&
+       git status --porcelain >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success SYMLINKS 'symlink replacing a directory' '
+       test_when_finished "rm -rf copy && git reset --hard initial" &&
+       mkdir copy &&
+       cp dir/file1 copy/file1 &&
+       echo "changed in copy" >copy/file2 &&
+       git add copy &&
+       git commit -m second &&
+       rm -rf copy &&
+       ln -s dir copy &&
+       echo " D copy/file1" >expect &&
+       echo " D copy/file2" >>expect &&
+       echo "?? copy" >>expect &&
+       git status --porcelain >actual &&
+       test_cmp expect actual
+'
+
+test_done
index c6aa8fb993aa4bd92e4269d7a85c6b45fe9801e8..629c658c46a1b4f4bcd8bbe9770d7fd767ae2216 100644 (file)
@@ -1176,7 +1176,8 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
 static int reject_merge(const struct cache_entry *ce,
                        struct unpack_trees_options *o)
 {
-       return add_rejected_path(o, ERROR_WOULD_OVERWRITE, ce->name);
+       return o->gently ? -1 :
+               add_rejected_path(o, ERROR_WOULD_OVERWRITE, ce->name);
 }
 
 static int same(const struct cache_entry *a, const struct cache_entry *b)
@@ -1631,7 +1632,7 @@ int threeway_merge(const struct cache_entry * const *stages,
        /* #14, #14ALT, #2ALT */
        if (remote && !df_conflict_head && head_match && !remote_match) {
                if (index && !same(index, remote) && !same(index, head))
-                       return o->gently ? -1 : reject_merge(index, o);
+                       return reject_merge(index, o);
                return merged_entry(remote, index, o);
        }
        /*
@@ -1639,7 +1640,7 @@ int threeway_merge(const struct cache_entry * const *stages,
         * make sure that it matches head.
         */
        if (index && !same(index, head))
-               return o->gently ? -1 : reject_merge(index, o);
+               return reject_merge(index, o);
 
        if (head) {
                /* #5ALT, #15 */
@@ -1768,9 +1769,8 @@ int twoway_merge(const struct cache_entry * const *src,
                                else
                                        return merged_entry(newtree, current, o);
                        }
-                       return o->gently ? -1 : reject_merge(current, o);
-               }
-               else if ((!oldtree && !newtree) || /* 4 and 5 */
+                       return reject_merge(current, o);
+               } else if ((!oldtree && !newtree) || /* 4 and 5 */
                         (!oldtree && newtree &&
                          same(current, newtree)) || /* 6 and 7 */
                         (oldtree && newtree &&
@@ -1779,26 +1779,15 @@ int twoway_merge(const struct cache_entry * const *src,
                          !same(oldtree, newtree) && /* 18 and 19 */
                          same(current, newtree))) {
                        return keep_entry(current, o);
-               }
-               else if (oldtree && !newtree && same(current, oldtree)) {
+               } else if (oldtree && !newtree && same(current, oldtree)) {
                        /* 10 or 11 */
                        return deleted_entry(oldtree, current, o);
-               }
-               else if (oldtree && newtree &&
+               } else if (oldtree && newtree &&
                         same(current, oldtree) && !same(current, newtree)) {
                        /* 20 or 21 */
                        return merged_entry(newtree, current, o);
-               }
-               else {
-                       /* all other failures */
-                       if (oldtree)
-                               return o->gently ? -1 : reject_merge(oldtree, o);
-                       if (current)
-                               return o->gently ? -1 : reject_merge(current, o);
-                       if (newtree)
-                               return o->gently ? -1 : reject_merge(newtree, o);
-                       return -1;
-               }
+               } else
+                       return reject_merge(current, o);
        }
        else if (newtree) {
                if (oldtree && !o->initial_checkout) {
index 01de944a0a23f752364de51d7f5a5be6480575e8..433211a238cfee261e6e1f9e73d14df9178f004a 100644 (file)
@@ -167,7 +167,9 @@ static void create_pack_file(void)
                if (!pollsize)
                        break;
 
-               ret = poll(pfd, pollsize, 1000 * keepalive);
+               ret = poll(pfd, pollsize,
+                       keepalive < 0 ? -1 : 1000 * keepalive);
+
                if (ret < 0) {
                        if (errno != EINTR) {
                                error("poll failed, resuming: %s",