Imported Upstream version 2.8.2 upstream/2.8.2
authorDongHun Kwak <dh0128.kwak@samsung.com>
Wed, 3 Mar 2021 06:15:45 +0000 (15:15 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Wed, 3 Mar 2021 06:15:45 +0000 (15:15 +0900)
72 files changed:
Documentation/RelNotes/2.8.2.txt [new file with mode: 0644]
Documentation/diff-options.txt
Documentation/git-apply.txt
Documentation/git-config.txt
Documentation/git-fetch-pack.txt
Documentation/git.txt
Documentation/technical/api-parse-options.txt
Documentation/technical/api-trace.txt
GIT-VERSION-GEN
Makefile
RelNotes
abspath.c
attr.c
builtin/blame.c
builtin/commit.c
builtin/config.c
builtin/fetch-pack.c
builtin/grep.c
builtin/index-pack.c
builtin/init-db.c
builtin/merge.c
builtin/rev-parse.c
builtin/send-pack.c
cache.h
compat/mingw.c
compat/mingw.h
compat/snprintf.c
compat/vcbuild/include/unistd.h
credential-cache--daemon.c
diffcore-rename.c
dir.c
dir.h
environment.c
git-mergetool.sh
git-send-email.perl
git.c
lockfile.c
mailmap.c
po/fr.po
remote.c
setup.c
sha1_name.c
strbuf.c
submodule-config.c
t/lib-httpd/apache.conf
t/t1300-repo-config.sh
t/t1506-rev-parse-diagnosis.sh
t/t1515-rev-parse-outside-repo.sh [new file with mode: 0755]
t/t4001-diff-rename.sh
t/t5300-pack-object.sh
t/t5400-send-pack.sh
t/t5500-fetch-pack.sh
t/t5604-clone-reference.sh [moved from t/t5700-clone-reference.sh with 100% similarity]
t/t5605-clone-local.sh [moved from t/t5701-clone-local.sh with 100% similarity]
t/t5606-clone-options.sh [moved from t/t5702-clone-options.sh with 100% similarity]
t/t5607-clone-bundle.sh [moved from t/t5704-bundle.sh with 100% similarity]
t/t5608-clone-2gb.sh [moved from t/t5705-clone-2gb.sh with 100% similarity]
t/t5609-clone-branch.sh [moved from t/t5706-clone-branch.sh with 100% similarity]
t/t5610-clone-detached.sh [moved from t/t5707-clone-detached.sh with 100% similarity]
t/t5611-clone-config.sh [moved from t/t5708-clone-config.sh with 100% similarity]
t/t5612-clone-refspec.sh [moved from t/t5709-clone-refspec.sh with 100% similarity]
t/t5613-info-alternate.sh [moved from t/t5710-info-alternate.sh with 100% similarity]
t/t7502-commit.sh
t/t7600-merge.sh
t/t7610-mergetool.sh
t/t7810-grep.sh
t/t8003-blame-corner-cases.sh
t/t9300-fast-import.sh
test-match-trees.c
test-revision-walking.c
upload-pack.c
xdiff/xprepare.c

diff --git a/Documentation/RelNotes/2.8.2.txt b/Documentation/RelNotes/2.8.2.txt
new file mode 100644 (file)
index 0000000..447b193
--- /dev/null
@@ -0,0 +1,70 @@
+Git v2.8.2 Release Notes
+========================
+
+Fixes since v2.8.1
+------------------
+
+ * The embedded args argv-array in the child process is used to build
+   the command line to run pack-objects instead of using a separate
+   array of strings.
+
+ * Bunch of tests on "git clone" has been renumbered for better
+   organization.
+
+ * The tests that involve running httpd leaked the system-wide
+   configuration in /etc/gitconfig to the tested environment.
+
+ * "index-pack --keep=<msg>" was broken since v2.1.0 timeframe.
+
+ * "git config --get-urlmatch", unlike other variants of the "git
+   config --get" family, did not signal error with its exit status
+   when there was no matching configuration.
+
+ * The "--local-env-vars" and "--resolve-git-dir" options of "git
+   rev-parse" failed to work outside a repository when the command's
+   option parsing was rewritten in 1.8.5 era.
+
+ * Fetching of history by naming a commit object name directly didn't
+   work across remote-curl transport.
+
+ * A small memory leak in an error codepath has been plugged in xdiff
+   code.
+
+ * strbuf_getwholeline() did not NUL-terminate the buffer on certain
+   corner cases in its error codepath.
+
+ * The startup_info data, which records if we are working inside a
+   repository (among other things), are now uniformly available to Git
+   subcommand implementations, and Git avoids attempting to touch
+   references when we are not in a repository.
+
+ * "git mergetool" did not work well with conflicts that both sides
+   deleted.
+
+ * "git send-email" had trouble parsing alias file in mailrc format
+   when lines in it had trailing whitespaces on them.
+
+ * When "git merge --squash" stopped due to conflict, the concluding
+   "git commit" failed to read in the SQUASH_MSG that shows the log
+   messages from all the squashed commits.
+
+ * "git merge FETCH_HEAD" dereferenced NULL pointer when merging
+   nothing into an unborn history (which is arguably unusual usage,
+   which perhaps was the reason why nobody noticed it).
+
+ * Build updates for MSVC.
+
+ * "git diff -M" used to work better when two originally identical
+   files A and B got renamed to X/A and X/B by pairing A to X/A and B
+   to X/B, but this was broken in the 2.0 timeframe.
+
+ * "git send-pack --all <there>" was broken when its command line
+   option parsing was written in the 2.6 timeframe.
+
+ * When running "git blame $path" with unnormalized data in the index
+   for the path, the data in the working tree was blamed, even though
+   "git add" would not have changed what is already in the index, due
+   to "safe crlf" that disables the line-end conversion.  It has been
+   corrected.
+
+Also contains minor documentation updates and code clean-ups.
index 306b7e3..32f48ed 100644 (file)
@@ -286,8 +286,8 @@ endif::git-format-patch[]
 
 ifndef::git-format-patch[]
 --check::
-       Warn if changes introduce whitespace errors.  What are
-       considered whitespace errors is controlled by `core.whitespace`
+       Warn if changes introduce conflict markers or whitespace errors.
+       What are considered whitespace errors is controlled by `core.whitespace`
        configuration.  By default, trailing whitespaces (including
        lines that solely consist of whitespaces) and a space character
        that is immediately followed by a tab character inside the
index d9ed6a1..8ddb207 100644 (file)
@@ -13,7 +13,7 @@ SYNOPSIS
          [--apply] [--no-add] [--build-fake-ancestor=<file>] [-R | --reverse]
          [--allow-binary-replacement | --binary] [--reject] [-z]
          [-p<n>] [-C<n>] [--inaccurate-eof] [--recount] [--cached]
-         [--ignore-space-change | --ignore-whitespace ]
+         [--ignore-space-change | --ignore-whitespace]
          [--whitespace=(nowarn|warn|fix|error|error-all)]
          [--exclude=<path>] [--include=<path>] [--directory=<root>]
          [--verbose] [--unsafe-paths] [<patch>...]
@@ -21,6 +21,8 @@ SYNOPSIS
 DESCRIPTION
 -----------
 Reads the supplied diff output (i.e. "a patch") and applies it to files.
+When running from a subdirectory in a repository, patched paths
+outside the directory are ignored.
 With the `--index` option the patch is also applied to the index, and
 with the `--cached` option the patch is only applied to the index.
 Without these options, the command applies the patch only to files,
index 153b2d8..6fc08e3 100644 (file)
@@ -58,13 +58,13 @@ that location (you can say '--local' but that is the default).
 This command will fail with non-zero status upon error.  Some exit
 codes are:
 
-. The config file is invalid (ret=3),
-. can not write to the config file (ret=4),
-. no section or name was provided (ret=2),
-. the section or key is invalid (ret=1),
-. you try to unset an option which does not exist (ret=5),
-. you try to unset/set an option for which multiple lines match (ret=5), or
-. you try to use an invalid regexp (ret=6).
+- The config file is invalid (ret=3),
+- can not write to the config file (ret=4),
+- no section or name was provided (ret=2),
+- the section or key is invalid (ret=1),
+- you try to unset an option which does not exist (ret=5),
+- you try to unset/set an option for which multiple lines match (ret=5), or
+- you try to use an invalid regexp (ret=6).
 
 On success, the command returns the exit code 0.
 
@@ -86,8 +86,7 @@ OPTIONS
        found and the last value if multiple key values were found.
 
 --get-all::
-       Like get, but does not fail if the number of values for the key
-       is not exactly one.
+       Like get, but returns all values for a multi-valued key.
 
 --get-regexp::
        Like --get-all, but interprets the name as a regular expression and
@@ -102,7 +101,7 @@ OPTIONS
        given URL is returned (if no such key exists, the value for
        section.key is used as a fallback).  When given just the
        section as name, do so for all the keys in the section and
-       list them.
+       list them.  Returns error code 1 if no value is found.
 
 --global::
        For writing options: write to global `~/.gitconfig` file
index 8680f45..239623c 100644 (file)
@@ -104,6 +104,10 @@ be in a separate packet, and the list must end with a flush packet.
        The remote heads to update from. This is relative to
        $GIT_DIR (e.g. "HEAD", "refs/heads/master").  When
        unspecified, update from all heads the remote side has.
++
+If the remote has enabled the options `uploadpack.allowTipSHA1InWant` or
+`uploadpack.allowReachableSHA1InWant`, they may alternatively be 40-hex
+sha1s present on the remote.
 
 SEE ALSO
 --------
index 8afe349..34ff007 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.8.1/git.html[documentation for release 2.8.1]
+* link:v2.8.2/git.html[documentation for release 2.8.2]
 
 * release notes for
+  link:RelNotes/2.8.2.txt[2.8.2].
   link:RelNotes/2.8.1.txt[2.8.1].
   link:RelNotes/2.8.0.txt[2.8].
 
index 5f0757d..695bd4b 100644 (file)
@@ -231,6 +231,13 @@ There are some macros to easily define options:
        pass the command-line option, which can be specified multiple times,
        to another command.
 
+`OPT_CMDMODE(short, long, &int_var, description, enum_val)`::
+       Define an "operation mode" option, only one of which in the same
+       group of "operating mode" options that share the same `int_var`
+       can be given by the user. `enum_val` is set to `int_var` when the
+       option is used, but an error is reported if other "operating mode"
+       option has already set its value to the same `int_var`.
+
 
 The last element of the array must be `OPT_END()`.
 
index 097a651..fadb597 100644 (file)
@@ -28,7 +28,7 @@ static struct trace_key trace_foo = TRACE_KEY_INIT(FOO);
 
 static void trace_print_foo(const char *message)
 {
-       trace_print_key(&trace_foo, message);
+       trace_printf_key(&trace_foo, "%s", message);
 }
 ------------
 +
@@ -95,3 +95,46 @@ for (;;) {
 }
 trace_performance(t, "frotz");
 ------------
+
+Bugs & Caveats
+--------------
+
+GIT_TRACE_* environment variables can be used to tell Git to show
+trace output to its standard error stream. Git can often spawn a pager
+internally to run its subcommand and send its standard output and
+standard error to it.
+
+Because GIT_TRACE_PERFORMANCE trace is generated only at the very end
+of the program with atexit(), which happens after the pager exits, it
+would not work well if you send its log to the standard error output
+and let Git spawn the pager at the same time.
+
+As a work around, you can for example use '--no-pager', or set
+GIT_TRACE_PERFORMANCE to another file descriptor which is redirected
+to stderr, or set GIT_TRACE_PERFORMANCE to a file specified by its
+absolute path.
+
+For example instead of the following command which by default may not
+print any performance information:
+
+------------
+GIT_TRACE_PERFORMANCE=2 git log -1
+------------
+
+you may want to use:
+
+------------
+GIT_TRACE_PERFORMANCE=2 git --no-pager log -1
+------------
+
+or:
+
+------------
+GIT_TRACE_PERFORMANCE=3 3>&2 git log -1
+------------
+
+or:
+
+------------
+GIT_TRACE_PERFORMANCE=/path/to/log/file git log -1
+------------
index 46595da..5f99f23 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v2.8.1
+DEF_VER=v2.8.2
 
 LF='
 '
index 2742a69..c7354bf 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2263,10 +2263,10 @@ sparse: $(SP_OBJ)
 check: common-cmds.h
        @if sparse; \
        then \
-               echo 2>&1 "Use 'make sparse' instead"; \
+               echo >&2 "Use 'make sparse' instead"; \
                $(MAKE) --no-print-directory sparse; \
        else \
-               echo 2>&1 "Did you mean 'make test'?"; \
+               echo >&2 "Did you mean 'make test'?"; \
                exit 1; \
        fi
 
index d40c3e1..04710da 120000 (symlink)
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/2.8.1.txt
\ No newline at end of file
+Documentation/RelNotes/2.8.2.txt
\ No newline at end of file
index 5edb4e7..2825de8 100644 (file)
--- a/abspath.c
+++ b/abspath.c
@@ -167,7 +167,6 @@ const char *prefix_filename(const char *pfx, int pfx_len, const char *arg)
        strbuf_add(&path, pfx, pfx_len);
        strbuf_addstr(&path, arg);
 #else
-       char *p;
        /* don't add prefix to absolute paths, but still replace '\' by '/' */
        strbuf_reset(&path);
        if (is_absolute_path(arg))
@@ -175,9 +174,7 @@ const char *prefix_filename(const char *pfx, int pfx_len, const char *arg)
        else if (pfx_len)
                strbuf_add(&path, pfx, pfx_len);
        strbuf_addstr(&path, arg);
-       for (p = path.buf + pfx_len; *p; p++)
-               if (*p == '\\')
-                       *p = '/';
+       convert_slashes(path.buf + pfx_len);
 #endif
        return path.buf;
 }
diff --git a/attr.c b/attr.c
index 6537a43..eec5d7d 100644 (file)
--- a/attr.c
+++ b/attr.c
@@ -122,7 +122,7 @@ struct pattern {
        const char *pattern;
        int patternlen;
        int nowildcardlen;
-       int flags;              /* EXC_FLAG_* */
+       unsigned flags;         /* EXC_FLAG_* */
 };
 
 /*
index e982fb8..21f42b0 100644 (file)
@@ -2307,6 +2307,7 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,
        unsigned mode;
        struct strbuf msg = STRBUF_INIT;
 
+       read_cache();
        time(&now);
        commit = alloc_commit_node();
        commit->object.parsed = 1;
index b3bd2d4..c733ec9 100644 (file)
@@ -726,9 +726,18 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
                                      &sb, &ctx);
                hook_arg1 = "message";
        } else if (!stat(git_path_merge_msg(), &statbuf)) {
+               /*
+                * prepend SQUASH_MSG here if it exists and a
+                * "merge --squash" was originally performed
+                */
+               if (!stat(git_path_squash_msg(), &statbuf)) {
+                       if (strbuf_read_file(&sb, git_path_squash_msg(), 0) < 0)
+                               die_errno(_("could not read SQUASH_MSG"));
+                       hook_arg1 = "squash";
+               } else
+                       hook_arg1 = "merge";
                if (strbuf_read_file(&sb, git_path_merge_msg(), 0) < 0)
                        die_errno(_("could not read MERGE_MSG"));
-               hook_arg1 = "merge";
        } else if (!stat(git_path_squash_msg(), &statbuf)) {
                if (strbuf_read_file(&sb, git_path_squash_msg(), 0) < 0)
                        die_errno(_("could not read SQUASH_MSG"));
index ca9f834..1d7c6ef 100644 (file)
@@ -417,6 +417,7 @@ static int urlmatch_collect_fn(const char *var, const char *value, void *cb)
 
 static int get_urlmatch(const char *var, const char *url)
 {
+       int ret;
        char *section_tail;
        struct string_list_item *item;
        struct urlmatch_config config = { STRING_LIST_INIT_DUP };
@@ -443,6 +444,8 @@ static int get_urlmatch(const char *var, const char *url)
        git_config_with_options(urlmatch_config_entry, &config,
                                &given_config_source, respect_includes);
 
+       ret = !values.nr;
+
        for_each_string_list_item(item, &values) {
                struct urlmatch_current_candidate_value *matched = item->util;
                struct strbuf buf = STRBUF_INIT;
@@ -459,7 +462,7 @@ static int get_urlmatch(const char *var, const char *url)
        free(config.url.url);
 
        free((void *)config.section);
-       return 0;
+       return ret;
 }
 
 static char *default_user_config(void)
index 79a611f..bfd0be4 100644 (file)
@@ -16,10 +16,20 @@ static void add_sought_entry(struct ref ***sought, int *nr, int *alloc,
        struct ref *ref;
        struct object_id oid;
 
-       if (!get_oid_hex(name, &oid) && name[GIT_SHA1_HEXSZ] == ' ')
-               name += GIT_SHA1_HEXSZ + 1;
-       else
+       if (!get_oid_hex(name, &oid)) {
+               if (name[GIT_SHA1_HEXSZ] == ' ') {
+                       /* <sha1> <ref>, find refname */
+                       name += GIT_SHA1_HEXSZ + 1;
+               } else if (name[GIT_SHA1_HEXSZ] == '\0') {
+                       ; /* <sha1>, leave sha1 as name */
+               } else {
+                       /* <ref>, clear cruft from oid */
+                       oidclr(&oid);
+               }
+       } else {
+               /* <ref>, clear cruft from get_oid_hex */
                oidclr(&oid);
+       }
 
        ref = alloc_ref(name);
        oidcpy(&ref->old_oid, &oid);
index aa7435f..111b6f6 100644 (file)
@@ -522,12 +522,14 @@ static int grep_objects(struct grep_opt *opt, const struct pathspec *pathspec,
 }
 
 static int grep_directory(struct grep_opt *opt, const struct pathspec *pathspec,
-                         int exc_std)
+                         int exc_std, int use_index)
 {
        struct dir_struct dir;
        int i, hit = 0;
 
        memset(&dir, 0, sizeof(dir));
+       if (!use_index)
+               dir.flags |= DIR_NO_GITLINKS;
        if (exc_std)
                setup_standard_excludes(&dir);
 
@@ -902,7 +904,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
                int use_exclude = (opt_exclude < 0) ? use_index : !!opt_exclude;
                if (list.nr)
                        die(_("--no-index or --untracked cannot be used with revs."));
-               hit = grep_directory(&opt, &pathspec, use_exclude);
+               hit = grep_directory(&opt, &pathspec, use_exclude, use_index);
        } else if (0 <= opt_exclude) {
                die(_("--[no-]exclude-standard cannot be used for tracked contents."));
        } else if (!list.nr) {
index 4524519..2d1eb8b 100644 (file)
@@ -1599,6 +1599,18 @@ static void show_pack_info(int stat_only)
        }
 }
 
+static const char *derive_filename(const char *pack_name, const char *suffix,
+                                  struct strbuf *buf)
+{
+       size_t len;
+       if (!strip_suffix(pack_name, ".pack", &len))
+               die(_("packfile name '%s' does not end with '.pack'"),
+                   pack_name);
+       strbuf_add(buf, pack_name, len);
+       strbuf_addstr(buf, suffix);
+       return buf->buf;
+}
+
 int cmd_index_pack(int argc, const char **argv, const char *prefix)
 {
        int i, fix_thin_pack = 0, verify = 0, stat_only = 0;
@@ -1707,24 +1719,11 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
                usage(index_pack_usage);
        if (fix_thin_pack && !from_stdin)
                die(_("--fix-thin cannot be used without --stdin"));
-       if (!index_name && pack_name) {
-               size_t len;
-               if (!strip_suffix(pack_name, ".pack", &len))
-                       die(_("packfile name '%s' does not end with '.pack'"),
-                           pack_name);
-               strbuf_add(&index_name_buf, pack_name, len);
-               strbuf_addstr(&index_name_buf, ".idx");
-               index_name = index_name_buf.buf;
-       }
-       if (keep_msg && !keep_name && pack_name) {
-               size_t len;
-               if (!strip_suffix(pack_name, ".pack", &len))
-                       die(_("packfile name '%s' does not end with '.pack'"),
-                           pack_name);
-               strbuf_add(&keep_name_buf, pack_name, len);
-               strbuf_addstr(&keep_name_buf, ".idx");
-               keep_name = keep_name_buf.buf;
-       }
+       if (!index_name && pack_name)
+               index_name = derive_filename(pack_name, ".idx", &index_name_buf);
+       if (keep_msg && !keep_name && pack_name)
+               keep_name = derive_filename(pack_name, ".keep", &keep_name_buf);
+
        if (verify) {
                if (!index_name)
                        die(_("--verify with no packfile name given"));
index 6223b7d..da531f6 100644 (file)
@@ -322,6 +322,7 @@ int set_git_dir_init(const char *git_dir, const char *real_git_dir,
                set_git_dir(real_path(git_dir));
                git_link = NULL;
        }
+       startup_info->have_repository = 1;
        return 0;
 }
 
index 101ffef..bf2f261 100644 (file)
@@ -1257,12 +1257,12 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
                        builtin_merge_options);
 
        if (!head_commit) {
-               struct commit *remote_head;
                /*
                 * If the merged head is a valid one there is no reason
                 * to forbid "git merge" into a branch yet to be born.
                 * We do the same for "git pull".
                 */
+               unsigned char *remote_head_sha1;
                if (squash)
                        die(_("Squash commit into empty head not supported yet"));
                if (fast_forward == FF_NO)
@@ -1270,13 +1270,13 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
                            "an empty head"));
                remoteheads = collect_parents(head_commit, &head_subsumed,
                                              argc, argv, NULL);
-               remote_head = remoteheads->item;
-               if (!remote_head)
+               if (!remoteheads)
                        die(_("%s - not something we can merge"), argv[0]);
                if (remoteheads->next)
                        die(_("Can merge only exactly one commit into empty head"));
-               read_empty(remote_head->object.oid.hash, 0);
-               update_ref("initial pull", "HEAD", remote_head->object.oid.hash,
+               remote_head_sha1 = remoteheads->item->object.oid.hash;
+               read_empty(remote_head_sha1, 0);
+               update_ref("initial pull", "HEAD", remote_head_sha1,
                           NULL, 0, UPDATE_REFS_DIE_ON_ERR);
                goto done;
        }
index cf8487b..c961b74 100644 (file)
@@ -505,6 +505,7 @@ N_("git rev-parse --parseopt [<options>] -- [<args>...]\n"
 int cmd_rev_parse(int argc, const char **argv, const char *prefix)
 {
        int i, as_is = 0, verify = 0, quiet = 0, revs_count = 0, type = 0;
+       int did_repo_setup = 0;
        int has_dashdash = 0;
        int output_prefix = 0;
        unsigned char sha1[20];
@@ -528,11 +529,40 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
                }
        }
 
-       prefix = setup_git_directory();
-       git_config(git_default_config, NULL);
+       /* No options; just report on whether we're in a git repo or not. */
+       if (argc == 1) {
+               setup_git_directory();
+               git_config(git_default_config, NULL);
+               return 0;
+       }
+
        for (i = 1; i < argc; i++) {
                const char *arg = argv[i];
 
+               if (!strcmp(arg, "--local-env-vars")) {
+                       int i;
+                       for (i = 0; local_repo_env[i]; i++)
+                               printf("%s\n", local_repo_env[i]);
+                       continue;
+               }
+               if (!strcmp(arg, "--resolve-git-dir")) {
+                       const char *gitdir = argv[++i];
+                       if (!gitdir)
+                               die("--resolve-git-dir requires an argument");
+                       gitdir = resolve_gitdir(gitdir);
+                       if (!gitdir)
+                               die("not a gitdir '%s'", argv[i]);
+                       puts(gitdir);
+                       continue;
+               }
+
+               /* The rest of the options require a git repository. */
+               if (!did_repo_setup) {
+                       prefix = setup_git_directory();
+                       git_config(git_default_config, NULL);
+                       did_repo_setup = 1;
+               }
+
                if (!strcmp(arg, "--git-path")) {
                        if (!argv[i + 1])
                                die("--git-path requires an argument");
@@ -706,12 +736,6 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
                                add_ref_exclusion(&ref_excludes, arg + 10);
                                continue;
                        }
-                       if (!strcmp(arg, "--local-env-vars")) {
-                               int i;
-                               for (i = 0; local_repo_env[i]; i++)
-                                       printf("%s\n", local_repo_env[i]);
-                               continue;
-                       }
                        if (!strcmp(arg, "--show-toplevel")) {
                                const char *work_tree = get_git_work_tree();
                                if (work_tree)
@@ -767,16 +791,6 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
                                puts(prefix_filename(pfx, strlen(pfx), get_git_common_dir()));
                                continue;
                        }
-                       if (!strcmp(arg, "--resolve-git-dir")) {
-                               const char *gitdir = argv[++i];
-                               if (!gitdir)
-                                       die("--resolve-git-dir requires an argument");
-                               gitdir = resolve_gitdir(gitdir);
-                               if (!gitdir)
-                                       die("not a gitdir '%s'", argv[i]);
-                               puts(gitdir);
-                               continue;
-                       }
                        if (!strcmp(arg, "--is-inside-git-dir")) {
                                printf("%s\n", is_inside_git_dir() ? "true"
                                                : "false");
index 5b9dd6a..1ff5a67 100644 (file)
@@ -225,7 +225,7 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
         * --all and --mirror are incompatible; neither makes sense
         * with any refspecs.
         */
-       if ((refspecs && (send_all || args.send_mirror)) ||
+       if ((nr_refspecs > 0 && (send_all || args.send_mirror)) ||
            (send_all && args.send_mirror))
                usage_with_options(send_pack_usage, options);
 
diff --git a/cache.h b/cache.h
index b829410..9f09540 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -1771,7 +1771,7 @@ int split_cmdline(char *cmdline, const char ***argv);
 /* Takes a negative value returned by split_cmdline */
 const char *split_cmdline_strerror(int cmdline_errno);
 
-/* git.c */
+/* setup.c */
 struct startup_info {
        int have_repository;
        const char *prefix;
index 54c82ec..0413d5c 100644 (file)
@@ -763,15 +763,12 @@ struct tm *localtime_r(const time_t *timep, struct tm *result)
 
 char *mingw_getcwd(char *pointer, int len)
 {
-       int i;
        wchar_t wpointer[MAX_PATH];
        if (!_wgetcwd(wpointer, ARRAY_SIZE(wpointer)))
                return NULL;
        if (xwcstoutf(pointer, wpointer, len) < 0)
                return NULL;
-       for (i = 0; pointer[i]; i++)
-               if (pointer[i] == '\\')
-                       pointer[i] = '/';
+       convert_slashes(pointer);
        return pointer;
 }
 
@@ -2112,9 +2109,7 @@ static void setup_windows_environment()
                 * executable (by not mistaking the dir separators
                 * for escape characters).
                 */
-               for (; *tmp; tmp++)
-                       if (*tmp == '\\')
-                               *tmp = '/';
+               convert_slashes(tmp);
        }
 
        /* simulate TERM to enable auto-color (see color.c) */
index c008694..1de70ff 100644 (file)
@@ -406,7 +406,7 @@ static inline void convert_slashes(char *path)
 int mingw_offset_1st_component(const char *path);
 #define offset_1st_component mingw_offset_1st_component
 #define PATH_SEP ';'
-#ifndef __MINGW64_VERSION_MAJOR
+#if !defined(__MINGW64_VERSION_MAJOR) && (!defined(_MSC_VER) || _MSC_VER < 1800)
 #define PRIuMAX "I64u"
 #define PRId64 "I64d"
 #else
index 42ea1ac..0b11688 100644 (file)
@@ -9,7 +9,7 @@
  * always have room for a trailing NUL byte.
  */
 #ifndef SNPRINTF_SIZE_CORR
-#if defined(WIN32) && (!defined(__GNUC__) || __GNUC__ < 4)
+#if defined(WIN32) && (!defined(__GNUC__) || __GNUC__ < 4) && (!defined(_MSC_VER) || _MSC_VER < 1900)
 #define SNPRINTF_SIZE_CORR 1
 #else
 #define SNPRINTF_SIZE_CORR 0
index c65c2cd..3a959d1 100644 (file)
@@ -45,11 +45,15 @@ typedef unsigned long long uintmax_t;
 
 typedef int64_t off64_t;
 
+#if !defined(_MSC_VER) || _MSC_VER < 1600
 #define INTMAX_MIN  _I64_MIN
 #define INTMAX_MAX  _I64_MAX
 #define UINTMAX_MAX _UI64_MAX
 
 #define UINT32_MAX 0xffffffff  /* 4294967295U */
+#else
+#include <stdint.h>
+#endif
 
 #define STDIN_FILENO  0
 #define STDOUT_FILENO 1
index caef21e..291c0fd 100644 (file)
@@ -126,8 +126,17 @@ static void serve_one_client(FILE *in, FILE *out)
                        fprintf(out, "password=%s\n", e->item.password);
                }
        }
-       else if (!strcmp(action.buf, "exit"))
+       else if (!strcmp(action.buf, "exit")) {
+               /*
+                * It's important that we clean up our socket first, and then
+                * signal the client only once we have finished the cleanup.
+                * Calling exit() directly does this, because we clean up in
+                * our atexit() handler, and then signal the client when our
+                * process actually ends, which closes the socket and gives
+                * them EOF.
+                */
                exit(0);
+       }
        else if (!strcmp(action.buf, "erase"))
                remove_credential(&c);
        else if (!strcmp(action.buf, "store")) {
index 3b3c1ed..7f03eb5 100644 (file)
@@ -340,9 +340,11 @@ static int find_exact_renames(struct diff_options *options)
        int i, renames = 0;
        struct hashmap file_table;
 
-       /* Add all sources to the hash table */
+       /* Add all sources to the hash table in reverse order, because
+        * later on they will be retrieved in LIFO order.
+        */
        hashmap_init(&file_table, NULL, rename_src_nr);
-       for (i = 0; i < rename_src_nr; i++)
+       for (i = rename_src_nr-1; i >= 0; i--)
                insert_file_table(&file_table, i, rename_src[i].p->one);
 
        /* Walk the destinations and find best source match */
diff --git a/dir.c b/dir.c
index a4a9d9f..996653b 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -457,7 +457,7 @@ int no_wildcard(const char *string)
 
 void parse_exclude_pattern(const char **pattern,
                           int *patternlen,
-                          int *flags,
+                          unsigned *flags,
                           int *nowildcardlen)
 {
        const char *p = *pattern;
@@ -498,7 +498,7 @@ void add_exclude(const char *string, const char *base,
 {
        struct exclude *x;
        int patternlen;
-       int flags;
+       unsigned flags;
        int nowildcardlen;
 
        parse_exclude_pattern(&string, &patternlen, &flags, &nowildcardlen);
@@ -798,7 +798,7 @@ void add_excludes_from_file(struct dir_struct *dir, const char *fname)
 
 int match_basename(const char *basename, int basenamelen,
                   const char *pattern, int prefix, int patternlen,
-                  int flags)
+                  unsigned flags)
 {
        if (prefix == patternlen) {
                if (patternlen == basenamelen &&
@@ -823,7 +823,7 @@ int match_basename(const char *basename, int basenamelen,
 int match_pathname(const char *pathname, int pathlen,
                   const char *base, int baselen,
                   const char *pattern, int prefix, int patternlen,
-                  int flags)
+                  unsigned flags)
 {
        const char *name;
        int namelen;
diff --git a/dir.h b/dir.h
index cd46f30..301b737 100644 (file)
--- a/dir.h
+++ b/dir.h
@@ -27,7 +27,7 @@ struct exclude {
        int nowildcardlen;
        const char *base;
        int baselen;
-       int flags;
+       unsigned flags;         /* EXC_FLAG_* */
 
        /*
         * Counting starts from 1 for line numbers in ignore files,
@@ -226,10 +226,10 @@ struct dir_entry *dir_add_ignored(struct dir_struct *dir, const char *pathname,
  * attr.c:path_matches()
  */
 extern int match_basename(const char *, int,
-                         const char *, int, int, int);
+                         const char *, int, int, unsigned);
 extern int match_pathname(const char *, int,
                          const char *, int,
-                         const char *, int, int, int);
+                         const char *, int, int, unsigned);
 
 extern struct exclude *last_exclude_matching(struct dir_struct *dir,
                                             const char *name, int *dtype);
@@ -241,7 +241,7 @@ extern struct exclude_list *add_exclude_list(struct dir_struct *dir,
 extern int add_excludes_from_file_to_list(const char *fname, const char *base, int baselen,
                                          struct exclude_list *el, int check_index);
 extern void add_excludes_from_file(struct dir_struct *, const char *fname);
-extern void parse_exclude_pattern(const char **string, int *patternlen, int *flags, int *nowildcardlen);
+extern void parse_exclude_pattern(const char **string, int *patternlen, unsigned *flags, int *nowildcardlen);
 extern void add_exclude(const char *string, const char *base,
                        int baselen, struct exclude_list *el, int srcpos);
 extern void clear_exclude_list(struct exclude_list *el);
index 6dec9d0..6cc0a77 100644 (file)
@@ -64,7 +64,6 @@ int grafts_replace_parents = 1;
 int core_apply_sparse_checkout;
 int merge_log_config = -1;
 int precomposed_unicode = -1; /* see probe_utf8_pathname_composition() */
-struct startup_info *startup_info;
 unsigned long pack_size_limit_cfg;
 
 #ifndef PROTECT_HFS_DEFAULT
index 9f77e3a..f67bab5 100755 (executable)
@@ -126,7 +126,12 @@ resolve_deleted_merge () {
                case "$ans" in
                [mMcC]*)
                        git add -- "$MERGED"
-                       cleanup_temp_files --save-backup
+                       if test "$merge_keep_backup" = "true"
+                       then
+                               cleanup_temp_files --save-backup
+                       else
+                               cleanup_temp_files
+                       fi
                        return 0
                        ;;
                [dD]*)
@@ -135,6 +140,10 @@ resolve_deleted_merge () {
                        return 0
                        ;;
                [aA]*)
+                       if test "$merge_keep_temporaries" = "false"
+                       then
+                               cleanup_temp_files
+                       fi
                        return 1
                        ;;
                esac
@@ -282,8 +291,14 @@ merge_file () {
                return
        fi
 
-       mv -- "$MERGED" "$BACKUP"
-       cp -- "$BACKUP" "$MERGED"
+       if test -f "$MERGED"
+       then
+               mv -- "$MERGED" "$BACKUP"
+               cp -- "$BACKUP" "$MERGED"
+       fi
+       # Create a parent directory to handle delete/delete conflicts
+       # where the base's directory no longer exists.
+       mkdir -p "$(dirname "$MERGED")"
 
        checkout_staged_file 1 "$MERGED" "$BASE"
        checkout_staged_file 2 "$MERGED" "$LOCAL"
@@ -295,7 +310,9 @@ merge_file () {
                describe_file "$local_mode" "local" "$LOCAL"
                describe_file "$remote_mode" "remote" "$REMOTE"
                resolve_deleted_merge
-               return
+               status=$?
+               rmdir -p "$(dirname "$MERGED")" 2>/dev/null
+               return $status
        fi
 
        if is_symlink "$local_mode" || is_symlink "$remote_mode"
index d356901..c45b22a 100755 (executable)
@@ -533,7 +533,7 @@ my %parse_alias = (
                        $aliases{$alias} = \@addr
                }}},
        mailrc => sub { my $fh = shift; while (<$fh>) {
-               if (/^alias\s+(\S+)\s+(.*)$/) {
+               if (/^alias\s+(\S+)\s+(.*?)\s*$/) {
                        # spaces delimit multiple addresses
                        $aliases{$1} = [ quotewords('\s+', 0, $2) ];
                }}},
diff --git a/git.c b/git.c
index 6cc0c07..968a8a4 100644 (file)
--- a/git.c
+++ b/git.c
@@ -15,7 +15,6 @@ const char git_more_info_string[] =
           "concept guides. See 'git help <command>' or 'git help <concept>'\n"
           "to read about a specific subcommand or concept.");
 
-static struct startup_info git_startup_info;
 static int use_pager = -1;
 static char *orig_cwd;
 static const char *env_names[] = {
@@ -637,8 +636,6 @@ int main(int argc, char **av)
        const char *cmd;
        int done_help = 0;
 
-       startup_info = &git_startup_info;
-
        cmd = git_extract_argv0_path(argv[0]);
        if (!cmd)
                cmd = "git-help";
index 80d056d..9268cdf 100644 (file)
@@ -149,13 +149,15 @@ static int lock_file_timeout(struct lock_file *lk, const char *path,
 void unable_to_lock_message(const char *path, int err, struct strbuf *buf)
 {
        if (err == EEXIST) {
-               strbuf_addf(buf, "Unable to create '%s.lock': %s.\n\n"
-                   "If no other git process is currently running, this probably means a\n"
-                   "git process crashed in this repository earlier. Make sure no other git\n"
-                   "process is running and remove the file manually to continue.",
+               strbuf_addf(buf, _("Unable to create '%s.lock': %s.\n\n"
+                   "Another git process seems to be running in this repository, e.g.\n"
+                   "an editor opened by 'git commit'. Please make sure all processes\n"
+                   "are terminated then try again. If it still fails, a git process\n"
+                   "may have crashed in this repository earlier:\n"
+                   "remove the file manually to continue."),
                            absolute_path(path), strerror(err));
        } else
-               strbuf_addf(buf, "Unable to create '%s.lock': %s",
+               strbuf_addf(buf, _("Unable to create '%s.lock': %s"),
                            absolute_path(path), strerror(err));
 }
 
index f4a0f1c..9726237 100644 (file)
--- a/mailmap.c
+++ b/mailmap.c
@@ -250,7 +250,8 @@ int read_mailmap(struct string_list *map, char **repo_abbrev)
                git_mailmap_blob = "HEAD:.mailmap";
 
        err |= read_mailmap_file(map, ".mailmap", repo_abbrev);
-       err |= read_mailmap_blob(map, git_mailmap_blob, repo_abbrev);
+       if (startup_info->have_repository)
+               err |= read_mailmap_blob(map, git_mailmap_blob, repo_abbrev);
        err |= read_mailmap_file(map, git_mailmap_file, repo_abbrev);
        return err;
 }
index 88b0b8a..55ca387 100644 (file)
--- a/po/fr.po
+++ b/po/fr.po
@@ -2945,7 +2945,7 @@ msgstr "utiliser l'horodatage actuel pour la date d'auteur"
 #: builtin/am.c:2321 builtin/commit.c:1593 builtin/merge.c:225
 #: builtin/pull.c:159 builtin/revert.c:92 builtin/tag.c:355
 msgid "key-id"
-msgstr "id de clé"
+msgstr "id-clé"
 
 #: builtin/am.c:2322
 msgid "GPG-sign commits"
@@ -4545,7 +4545,7 @@ msgstr "style"
 
 #: builtin/checkout.c:1154
 msgid "conflict style (merge or diff3)"
-msgstr "style de conflit (fusion ou diff3)"
+msgstr "style de conflit (merge (fusion) ou diff3)"
 
 #: builtin/checkout.c:1157
 msgid "do not limit pathspecs to sparse entries only"
@@ -6197,7 +6197,7 @@ msgstr "convertir en un dépôt complet"
 
 #: builtin/fetch.c:122 builtin/log.c:1236
 msgid "dir"
-msgstr "dir"
+msgstr "répertoire"
 
 #: builtin/fetch.c:123
 msgid "prepend this to submodule path output"
@@ -10809,11 +10809,11 @@ msgstr "git show-ref --exclude-existing[=<motif>]"
 
 #: builtin/show-ref.c:165
 msgid "only show tags (can be combined with heads)"
-msgstr "afficher seulement les Ã©tiquettes (peut Ãªtre combiné avec des têtes)"
+msgstr "afficher seulement les Ã©tiquettes (peut Ãªtre combiné avec heads)"
 
 #: builtin/show-ref.c:166
 msgid "only show heads (can be combined with tags)"
-msgstr "afficher seulement les têtes (peut Ãªtre combiné avec des Ã©tiquettes)"
+msgstr "afficher seulement les têtes (peut Ãªtre combiné avec tags)"
 
 #: builtin/show-ref.c:167
 msgid "stricter reference checking, requires exact ref path"
index fc02698..28fd676 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -455,7 +455,6 @@ static void read_config(void)
 {
        static int loaded;
        struct object_id oid;
-       const char *head_ref;
        int flag;
 
        if (loaded)
@@ -463,10 +462,12 @@ static void read_config(void)
        loaded = 1;
 
        current_branch = NULL;
-       head_ref = resolve_ref_unsafe("HEAD", 0, oid.hash, &flag);
-       if (head_ref && (flag & REF_ISSYMREF) &&
-           skip_prefix(head_ref, "refs/heads/", &head_ref)) {
-               current_branch = make_branch(head_ref, 0);
+       if (startup_info->have_repository) {
+               const char *head_ref = resolve_ref_unsafe("HEAD", 0, oid.hash, &flag);
+               if (head_ref && (flag & REF_ISSYMREF) &&
+                   skip_prefix(head_ref, "refs/heads/", &head_ref)) {
+                       current_branch = make_branch(head_ref, 0);
+               }
        }
        git_config(handle_config, NULL);
        alias_all_urls();
diff --git a/setup.c b/setup.c
index de1a2a7..3439ec6 100644 (file)
--- a/setup.c
+++ b/setup.c
@@ -7,6 +7,9 @@ static int inside_work_tree = -1;
 static int work_tree_config_is_bogus;
 static struct string_list unknown_extensions = STRING_LIST_INIT_DUP;
 
+static struct startup_info the_startup_info;
+struct startup_info *startup_info = &the_startup_info;
+
 /*
  * The input parameter must contain an absolute path, and it must already be
  * normalized.
@@ -905,10 +908,9 @@ const char *setup_git_directory_gently(int *nongit_ok)
        else
                setenv(GIT_PREFIX_ENVIRONMENT, "", 1);
 
-       if (startup_info) {
-               startup_info->have_repository = !nongit_ok || !*nongit_ok;
-               startup_info->prefix = prefix;
-       }
+       startup_info->have_repository = !nongit_ok || !*nongit_ok;
+       startup_info->prefix = prefix;
+
        return prefix;
 }
 
@@ -984,7 +986,9 @@ int check_repository_format_version(const char *var, const char *value, void *cb
 
 int check_repository_format(void)
 {
-       return check_repository_format_gently(get_git_dir(), NULL);
+       check_repository_format_gently(get_git_dir(), NULL);
+       startup_info->have_repository = 1;
+       return 0;
 }
 
 /*
index 3acf221..776101e 100644 (file)
@@ -1353,9 +1353,6 @@ static char *resolve_relative_path(const char *rel)
        if (!starts_with(rel, "./") && !starts_with(rel, "../"))
                return NULL;
 
-       if (!startup_info)
-               die("BUG: startup_info struct is not initialized.");
-
        if (!is_inside_work_tree())
                die("relative path syntax can't be used outside working tree.");
 
index f60e2ee..2c08dbb 100644 (file)
--- a/strbuf.c
+++ b/strbuf.c
@@ -481,9 +481,15 @@ int strbuf_getwholeline(struct strbuf *sb, FILE *fp, int term)
        if (errno == ENOMEM)
                die("Out of memory, getdelim failed");
 
-       /* Restore slopbuf that we moved out of the way before */
+       /*
+        * Restore strbuf invariants; if getdelim left us with a NULL pointer,
+        * we can just re-init, but otherwise we should make sure that our
+        * length is empty, and that the result is NUL-terminated.
+        */
        if (!sb->buf)
                strbuf_init(sb, 0);
+       else
+               strbuf_reset(sb);
        return EOF;
 }
 #else
index 92502b5..8476e0f 100644 (file)
@@ -392,8 +392,7 @@ static const struct submodule *config_from(struct submodule_cache *cache,
                struct hashmap_iter iter;
                struct submodule_entry *entry;
 
-               hashmap_iter_init(&cache->for_name, &iter);
-               entry = hashmap_iter_next(&iter);
+               entry = hashmap_iter_first(&cache->for_name, &iter);
                if (!entry)
                        return NULL;
                return entry->config;
index f667e7c..9317ba0 100644 (file)
@@ -74,6 +74,7 @@ PassEnv GIT_VALGRIND_OPTIONS
 PassEnv GNUPGHOME
 PassEnv ASAN_OPTIONS
 PassEnv GIT_TRACE
+PassEnv GIT_CONFIG_NOSYSTEM
 
 Alias /dumb/ www/
 Alias /auth/dumb/ www/auth/dumb/
index 6767da8..3d6f1db 100755 (executable)
@@ -1144,6 +1144,9 @@ test_expect_success 'urlmatch' '
                cookieFile = /tmp/cookie.txt
        EOF
 
+       test_expect_code 1 git config --bool --get-urlmatch doesnt.exist https://good.example.com >actual &&
+       test_must_be_empty actual &&
+
        echo true >expect &&
        git config --bool --get-urlmatch http.SSLverify https://good.example.com >actual &&
        test_cmp expect actual &&
index 613d9bf..86c2ff2 100755 (executable)
@@ -166,11 +166,6 @@ test_expect_success 'relative path when cwd is outside worktree' '
        grep "relative path syntax can.t be used outside working tree." error
 '
 
-test_expect_success 'relative path when startup_info is NULL' '
-       test_must_fail test-match-trees HEAD:./file.txt HEAD:./file.txt 2>error &&
-       grep "BUG: startup_info struct is not initialized." error
-'
-
 test_expect_success '<commit>:file correctly diagnosed after a pathname' '
        test_must_fail git rev-parse file.txt HEAD:file.txt 1>actual 2>error &&
        test_i18ngrep ! "exists on disk" error &&
diff --git a/t/t1515-rev-parse-outside-repo.sh b/t/t1515-rev-parse-outside-repo.sh
new file mode 100755 (executable)
index 0000000..3ec2971
--- /dev/null
@@ -0,0 +1,45 @@
+#!/bin/sh
+
+test_description='check that certain rev-parse options work outside repo'
+. ./test-lib.sh
+
+test_expect_success 'set up non-repo directory' '
+       GIT_CEILING_DIRECTORIES=$(pwd) &&
+       export GIT_CEILING_DIRECTORIES &&
+       mkdir non-repo &&
+       cd non-repo &&
+       # confirm that git does not find a repo
+       test_must_fail git rev-parse --git-dir
+'
+
+# Rather than directly test the output of sq-quote directly,
+# make sure the shell can read back a tricky case, since
+# that's what we really care about anyway.
+tricky="really tricky with \\ and \" and '"
+dump_args () {
+       for i in "$@"; do
+               echo "arg: $i"
+       done
+}
+test_expect_success 'rev-parse --sq-quote' '
+       dump_args "$tricky" easy >expect &&
+       eval "dump_args $(git rev-parse --sq-quote "$tricky" easy)" >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'rev-parse --local-env-vars' '
+       git rev-parse --local-env-vars >actual &&
+       # we do not want to depend on the complete list here,
+       # so just look for something plausible
+       grep ^GIT_DIR actual
+'
+
+test_expect_success 'rev-parse --resolve-git-dir' '
+       git init --separate-git-dir repo dir &&
+       test_must_fail git rev-parse --resolve-git-dir . &&
+       echo "$(pwd)/repo" >expect &&
+       git rev-parse --resolve-git-dir dir/.git >actual &&
+       test_cmp expect actual
+'
+
+test_done
index 2f327b7..ed90c6c 100755 (executable)
@@ -77,6 +77,17 @@ test_expect_success 'favour same basenames even with minor differences' '
        git show HEAD:path1 | sed "s/15/16/" > subdir/path1 &&
        git status | test_i18ngrep "renamed: .*path1 -> subdir/path1"'
 
+test_expect_success 'two files with same basename and same content' '
+       git reset --hard &&
+       mkdir -p dir/A dir/B &&
+       cp path1 dir/A/file &&
+       cp path1 dir/B/file &&
+       git add dir &&
+       git commit -m 2 &&
+       git mv dir other-dir &&
+       git status | test_i18ngrep "renamed: .*dir/A/file -> other-dir/A/file"
+'
+
 test_expect_success 'setup for many rename source candidates' '
        git reset --hard &&
        for i in 0 1 2 3 4 5 6 7 8 9;
index fc2be63..899e52d 100755 (executable)
@@ -284,6 +284,12 @@ test_expect_success \
      git index-pack test-3.pack &&
      cmp test-3.idx test-3-${packname_3}.idx &&
 
+     cat test-1-${packname_1}.pack >test-4.pack &&
+     rm -f test-4.keep &&
+     git index-pack --keep=why test-4.pack &&
+     cmp test-1-${packname_1}.idx test-4.idx &&
+     test -f test-4.keep &&
+
      :'
 
 test_expect_success 'unpacking with --strict' '
index 04cea97..305ca7a 100755 (executable)
@@ -128,6 +128,18 @@ test_expect_success 'denyNonFastforwards trumps --force' '
        test "$victim_orig" = "$victim_head"
 '
 
+test_expect_success 'send-pack --all sends all branches' '
+       # make sure we have at least 2 branches with different
+       # values, just to be thorough
+       git branch other-branch HEAD^ &&
+
+       git init --bare all.git &&
+       git send-pack --all all.git &&
+       git for-each-ref refs/heads >expect &&
+       git -C all.git for-each-ref refs/heads >actual &&
+       test_cmp expect actual
+'
+
 test_expect_success 'push --all excludes remote-tracking hierarchy' '
        mkdir parent &&
        (
index e5f83bf..9b9bec4 100755 (executable)
@@ -531,6 +531,20 @@ test_expect_success 'shallow fetch with tags does not break the repository' '
                git fsck
        )
 '
+
+test_expect_success 'fetch-pack can fetch a raw sha1' '
+       git init hidden &&
+       (
+               cd hidden &&
+               test_commit 1 &&
+               test_commit 2 &&
+               git update-ref refs/hidden/one HEAD^ &&
+               git config transfer.hiderefs refs/hidden &&
+               git config uploadpack.allowtipsha1inwant true
+       ) &&
+       git fetch-pack hidden $(git -C hidden rev-parse refs/hidden/one)
+'
+
 check_prot_path () {
        cat >expected <<-EOF &&
        Diag: url=$1
similarity index 100%
rename from t/t5704-bundle.sh
rename to t/t5607-clone-bundle.sh
similarity index 100%
rename from t/t5705-clone-2gb.sh
rename to t/t5608-clone-2gb.sh
index b39e313..725687d 100755 (executable)
@@ -527,11 +527,6 @@ try_commit_status_combo () {
                test_i18ngrep "^# Changes to be committed:" .git/COMMIT_EDITMSG
        '
 
-       test_expect_success 'commit' '
-               try_commit "" &&
-               test_i18ngrep "^# Changes to be committed:" .git/COMMIT_EDITMSG
-       '
-
        test_expect_success 'commit --status' '
                try_commit --status &&
                test_i18ngrep "^# Changes to be committed:" .git/COMMIT_EDITMSG
index 302e238..85248a1 100755 (executable)
@@ -33,9 +33,11 @@ printf '%s\n' 1 2 3 4 5 6 7 8 9 >file
 printf '%s\n' '1 X' 2 3 4 5 6 7 8 9 >file.1
 printf '%s\n' 1 2 3 4 '5 X' 6 7 8 9 >file.5
 printf '%s\n' 1 2 3 4 5 6 7 8 '9 X' >file.9
+printf '%s\n' 1 2 3 4 5 6 7 8 '9 Y' >file.9y
 printf '%s\n' '1 X' 2 3 4 5 6 7 8 9 >result.1
 printf '%s\n' '1 X' 2 3 4 '5 X' 6 7 8 9 >result.1-5
 printf '%s\n' '1 X' 2 3 4 '5 X' 6 7 8 '9 X' >result.1-5-9
+printf '%s\n' 1 2 3 4 5 6 7 8 '9 Z' >result.9z
 >empty
 
 create_merge_msgs () {
@@ -128,6 +130,12 @@ test_expect_success 'setup' '
        git tag c2 &&
        c2=$(git rev-parse HEAD) &&
        git reset --hard "$c0" &&
+       cp file.9y file &&
+       git add file &&
+       test_tick &&
+       git commit -m "commit 7" &&
+       git tag c7 &&
+       git reset --hard "$c0" &&
        cp file.9 file &&
        git add file &&
        test_tick &&
@@ -218,6 +226,26 @@ test_expect_success 'merge c1 with c2' '
        verify_parents $c1 $c2
 '
 
+test_expect_success 'merge --squash c3 with c7' '
+       git reset --hard c3 &&
+       test_must_fail git merge --squash c7 &&
+       cat result.9z >file &&
+       git commit --no-edit -a &&
+
+       {
+               cat <<-EOF
+               Squashed commit of the following:
+
+               $(git show -s c7)
+
+               # Conflicts:
+               #       file
+               EOF
+       } >expect &&
+       git cat-file commit HEAD | sed -e '1,/^$/d' >actual &&
+       test_cmp expect actual
+'
+
 test_debug 'git log --graph --decorate --oneline --all'
 
 test_expect_success 'merge c1 with c2 and c3' '
@@ -725,4 +753,14 @@ test_expect_success 'merge detects mod-256 conflicts (resolve)' '
        test_must_fail git merge -s resolve master
 '
 
+test_expect_success 'merge nothing into void' '
+       git init void &&
+       (
+               cd void &&
+               git remote add up .. &&
+               git fetch up &&
+               test_must_fail git merge FETCH_HEAD
+       )
+'
+
 test_done
index 6f12b23..76306cf 100755 (executable)
@@ -243,6 +243,70 @@ test_expect_success 'mergetool takes partial path' '
        git reset --hard
 '
 
+test_expect_success 'mergetool delete/delete conflict' '
+       git checkout -b delete-base branch1 &&
+       mkdir -p a/a &&
+       (echo one; echo two; echo 3; echo 4) >a/a/file.txt &&
+       git add a/a/file.txt &&
+       git commit -m"base file" &&
+       git checkout -b move-to-b delete-base &&
+       mkdir -p b/b &&
+       git mv a/a/file.txt b/b/file.txt &&
+       (echo one; echo two; echo 4) >b/b/file.txt &&
+       git commit -a -m"move to b" &&
+       git checkout -b move-to-c delete-base &&
+       mkdir -p c/c &&
+       git mv a/a/file.txt c/c/file.txt &&
+       (echo one; echo two; echo 3) >c/c/file.txt &&
+       git commit -a -m"move to c" &&
+       test_must_fail git merge move-to-b &&
+       echo d | git mergetool a/a/file.txt &&
+       ! test -f a/a/file.txt &&
+       git reset --hard HEAD &&
+       test_must_fail git merge move-to-b &&
+       echo m | git mergetool a/a/file.txt &&
+       test -f b/b/file.txt &&
+       git reset --hard HEAD &&
+       test_must_fail git merge move-to-b &&
+       ! echo a | git mergetool a/a/file.txt &&
+       ! test -f a/a/file.txt &&
+       git reset --hard HEAD
+'
+
+test_expect_success 'mergetool produces no errors when keepBackup is used' '
+       test_config mergetool.keepBackup true &&
+       test_must_fail git merge move-to-b &&
+       : >expect &&
+       echo d | git mergetool a/a/file.txt 2>actual &&
+       test_cmp expect actual &&
+       ! test -d a &&
+       git reset --hard HEAD
+'
+
+test_expect_success 'mergetool honors tempfile config for deleted files' '
+       test_config mergetool.keepTemporaries false &&
+       test_must_fail git merge move-to-b &&
+       echo d | git mergetool a/a/file.txt &&
+       ! test -d a &&
+       git reset --hard HEAD
+'
+
+test_expect_success 'mergetool keeps tempfiles when aborting delete/delete' '
+       test_config mergetool.keepTemporaries true &&
+       test_must_fail git merge move-to-b &&
+       ! (echo a; echo n) | git mergetool a/a/file.txt &&
+       test -d a/a &&
+       cat >expect <<-\EOF &&
+       file_BASE_.txt
+       file_LOCAL_.txt
+       file_REMOTE_.txt
+       EOF
+       ls -1 a/a | sed -e "s/[0-9]*//g" >actual &&
+       test_cmp expect actual &&
+       git clean -fdx &&
+       git reset --hard HEAD
+'
+
 test_expect_success 'deleted vs modified submodule' '
        git checkout -b test6 branch1 &&
        git submodule update -N &&
index b540944..1e72971 100755 (executable)
@@ -905,6 +905,33 @@ test_expect_success 'inside git repository but with --no-index' '
        )
 '
 
+test_expect_success 'grep --no-index descends into repos, but not .git' '
+       rm -fr non &&
+       mkdir -p non/git &&
+       (
+               GIT_CEILING_DIRECTORIES="$(pwd)/non" &&
+               export GIT_CEILING_DIRECTORIES &&
+               cd non/git &&
+
+               echo magic >file &&
+               git init repo &&
+               (
+                       cd repo &&
+                       echo magic >file &&
+                       git add file &&
+                       git commit -m foo &&
+                       echo magic >.git/file
+               ) &&
+
+               cat >expect <<-\EOF &&
+               file
+               repo/file
+               EOF
+               git grep -l --no-index magic >actual &&
+               test_cmp expect actual
+       )
+'
+
 test_expect_success 'setup double-dash tests' '
 cat >double-dash <<EOF &&
 --
index 6568429..a9b266f 100755 (executable)
@@ -212,4 +212,18 @@ test_expect_success 'blame file with CRLF attributes text' '
        grep "A U Thor" actual
 '
 
+test_expect_success 'blame file with CRLF core.autocrlf=true' '
+       git config core.autocrlf false &&
+       printf "testcase\r\n" >crlfinrepo &&
+       >.gitattributes &&
+       git add crlfinrepo &&
+       git commit -m "add crlfinrepo" &&
+       git config core.autocrlf true &&
+       mv crlfinrepo tmp &&
+       git checkout crlfinrepo &&
+       rm tmp &&
+       git blame crlfinrepo >actual &&
+       grep "A U Thor" actual
+'
+
 test_done
index 4c5f3c9..25bb60b 100755 (executable)
@@ -55,6 +55,10 @@ test_expect_success 'empty stream succeeds' '
        git fast-import </dev/null
 '
 
+test_expect_success 'truncated stream complains' '
+       echo "tag foo" | test_must_fail git fast-import
+'
+
 test_expect_success 'A: create pack from stdin' '
        test_tick &&
        cat >input <<-INPUT_END &&
index 109f03e..4dad709 100644 (file)
@@ -6,6 +6,8 @@ int main(int ac, char **av)
        unsigned char hash1[20], hash2[20], shifted[20];
        struct tree *one, *two;
 
+       setup_git_directory();
+
        if (get_sha1(av[1], hash1))
                die("cannot parse %s as an object name", av[1]);
        if (get_sha1(av[2], hash2))
index 285f06b..3d03133 100644 (file)
@@ -50,6 +50,8 @@ int main(int argc, char **argv)
        if (argc < 2)
                return 1;
 
+       setup_git_directory();
+
        if (!strcmp(argv[1], "run-twice")) {
                printf("1st\n");
                if (!run_revision_walk())
index b3f6653..dc802a0 100644 (file)
@@ -90,35 +90,32 @@ static void create_pack_file(void)
                "corruption on the remote side.";
        int buffered = -1;
        ssize_t sz;
-       const char *argv[13];
-       int i, arg = 0;
+       int i;
        FILE *pipe_fd;
 
        if (shallow_nr) {
-               argv[arg++] = "--shallow-file";
-               argv[arg++] = "";
+               argv_array_push(&pack_objects.args, "--shallow-file");
+               argv_array_push(&pack_objects.args, "");
        }
-       argv[arg++] = "pack-objects";
-       argv[arg++] = "--revs";
+       argv_array_push(&pack_objects.args, "pack-objects");
+       argv_array_push(&pack_objects.args, "--revs");
        if (use_thin_pack)
-               argv[arg++] = "--thin";
+               argv_array_push(&pack_objects.args, "--thin");
 
-       argv[arg++] = "--stdout";
+       argv_array_push(&pack_objects.args, "--stdout");
        if (shallow_nr)
-               argv[arg++] = "--shallow";
+               argv_array_push(&pack_objects.args, "--shallow");
        if (!no_progress)
-               argv[arg++] = "--progress";
+               argv_array_push(&pack_objects.args, "--progress");
        if (use_ofs_delta)
-               argv[arg++] = "--delta-base-offset";
+               argv_array_push(&pack_objects.args, "--delta-base-offset");
        if (use_include_tag)
-               argv[arg++] = "--include-tag";
-       argv[arg++] = NULL;
+               argv_array_push(&pack_objects.args, "--include-tag");
 
        pack_objects.in = -1;
        pack_objects.out = -1;
        pack_objects.err = -1;
        pack_objects.git_cmd = 1;
-       pack_objects.argv = argv;
 
        if (start_command(&pack_objects))
                die("git upload-pack: unable to fork git-pack-objects");
index 63a22c6..13b55ab 100644 (file)
@@ -301,10 +301,11 @@ int xdl_prepare_env(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
 
                xdl_free_ctx(&xe->xdf2);
                xdl_free_ctx(&xe->xdf1);
+               xdl_free_classifier(&cf);
                return -1;
        }
 
-       if (!(xpp->flags & XDF_HISTOGRAM_DIFF))
+       if (XDF_DIFF_ALG(xpp->flags) != XDF_HISTOGRAM_DIFF)
                xdl_free_classifier(&cf);
 
        return 0;