Merge branch 'ky/branch-m-worktree' into maint
authorJunio C Hamano <gitster@pobox.com>
Mon, 2 May 2016 21:24:05 +0000 (14:24 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 2 May 2016 21:24:05 +0000 (14:24 -0700)
When "git worktree" feature is in use, "git branch -m" renamed a
branch that is checked out in another worktree without adjusting
the HEAD symbolic ref for the worktree.

* ky/branch-m-worktree:
set_worktree_head_symref(): fix error message
branch -m: update all per-worktree HEADs
refs: add a new function set_worktree_head_symref

90 files changed:
Documentation/RelNotes/2.8.0.txt
Documentation/RelNotes/2.8.1.txt [new file with mode: 0644]
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-config.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/branch.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
config.c
credential-cache--daemon.c
diffcore-rename.c
dir.c
dir.h
environment.c
git-mergetool.sh
git-send-email.perl
git.c
git.spec.in
lockfile.c
mailmap.c
path.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/t3200-branch.sh
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 [new file with mode: 0755]
t/t5605-clone-local.sh [new file with mode: 0755]
t/t5606-clone-options.sh [new file with mode: 0755]
t/t5607-clone-bundle.sh [new file with mode: 0755]
t/t5608-clone-2gb.sh [new file with mode: 0755]
t/t5609-clone-branch.sh [new file with mode: 0755]
t/t5610-clone-detached.sh [new file with mode: 0755]
t/t5611-clone-config.sh [new file with mode: 0755]
t/t5612-clone-refspec.sh [new file with mode: 0755]
t/t5613-info-alternate.sh [new file with mode: 0755]
t/t5700-clone-reference.sh [deleted file]
t/t5701-clone-local.sh [deleted file]
t/t5702-clone-options.sh [deleted file]
t/t5704-bundle.sh [deleted file]
t/t5705-clone-2gb.sh [deleted file]
t/t5706-clone-branch.sh [deleted file]
t/t5707-clone-detached.sh [deleted file]
t/t5708-clone-config.sh [deleted file]
t/t5709-clone-refspec.sh [deleted file]
t/t5710-info-alternate.sh [deleted file]
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
index 5ec39bc300998a1d3add97026a46030cbc4b1926..25079710fa28155cf8d2747d9cbca14fcd84f360 100644 (file)
@@ -34,7 +34,7 @@ UI, Workflows & Features
    have a place to store the updated notes tree, iow, a ref).
 
  * "git grep" by default does not fall back to its "--no-index"
-   behaviour outside a directory under Git's control (otherwise the
+   behavior outside a directory under Git's control (otherwise the
    user may by mistake end up running a huge recursive search); with a
    new configuration (set in $HOME/.gitconfig--by definition this
    cannot be set in the config file per project), this safety can be
@@ -55,7 +55,7 @@ UI, Workflows & Features
 
  * Many commands that read files that are expected to contain text
    that is generated (or can be edited) by the end user to control
-   their behaviour (e.g. "git grep -f <filename>") have been updated
+   their behavior (e.g. "git grep -f <filename>") have been updated
    to be more tolerant to lines that are terminated with CRLF (they
    used to treat such a line to contain payload that ends with CR,
    which is usually not what the users expect).
@@ -187,7 +187,7 @@ Performance, Internal Implementation, Development Support etc.
    with expectations that are not satisfiable on Git for Windows.
 
  * Some calls to strcpy(3) triggers a false warning from static
-   analysers that are less intelligent than humans, and reducing the
+   analyzers that are less intelligent than humans, and reducing the
    number of these false hits helps us notice real issues.  A few
    calls to strcpy(3) in a couple of protrams that are already safe
    has been rewritten to avoid false warnings.
@@ -281,7 +281,7 @@ notes for details).
  * "git send-email" was confused by escaped quotes stored in the alias
    files saved by "mutt", which has been corrected.
 
- * A few unportable C construct have been spotted by clang compiler
+ * A few non-portable C construct have been spotted by clang compiler
    and have been fixed.
 
  * The documentation has been updated to hint the connection between
@@ -349,10 +349,10 @@ notes for details).
  * "git worktree" had a broken code that attempted to auto-fix
    possible inconsistency that results from end-users moving a
    worktree to different places without telling Git (the original
-   repository needs to maintain backpointers to its worktrees, but
-   "mv" run by end-users who are not familiar with that fact will
-   obviously not adjust them), which actually made things worse
-   when triggered.
+   repository needs to maintain back-pointers to its worktrees,
+   but "mv" run by end-users who are not familiar with that fact
+   will obviously not adjust them), which actually made things
+   worse when triggered.
 
  * The low-level merge machinery has been taught to use CRLF line
    termination when inserting conflict markers to merged contents that
diff --git a/Documentation/RelNotes/2.8.1.txt b/Documentation/RelNotes/2.8.1.txt
new file mode 100644 (file)
index 0000000..ef6d80b
--- /dev/null
@@ -0,0 +1,9 @@
+Git v2.8.1 Release Notes
+========================
+
+Fixes since v2.8
+----------------
+
+ * "make rpmbuild" target was broken as its input, git.spec.in, was
+   not updated to match a file it describes that has been renamed
+   recently.  This has been fixed.
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 306b7e360409255a7aafaa3860d6d6c0412fb870..32f48ed6471946aa8baf2d51113834804cd09b47 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 d9ed6a1a4ea6dc0068144eac4c5e0f5ef33a04cb..8ddb207409df99825b561be42234e9c23707287d 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 153b2d89b551b5c249c6a56604726f8175b0b7c6..6fc08e3d890007238528e60f843b6e01cda4f1fa 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 8680f45f8d635253576499453588308618afdc5f..239623cc24f11eb30a896f1e306d489a857109fa 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 a9120a8779ce8c4a9e2fda781add92eaec60d055..34ff007a98156162431d5dd03abaaffe5d0c29a0 100644 (file)
@@ -43,6 +43,13 @@ 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.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].
+
 * link:v2.7.3/git.html[documentation for release 2.7.3]
 
 * release notes for
index 0d8b99b368aea13a322382314d88229acda0b1db..20741f345e459f41d357039496f7d6be30edab06 100644 (file)
@@ -63,13 +63,6 @@ parse for configuration, rather than looking in the usual files. Regular
 Specify whether include directives should be followed in parsed files.
 Regular `git_config` defaults to `1`.
 
-There is a special version of `git_config` called `git_config_early`.
-This version takes an additional parameter to specify the repository
-config, instead of having it looked up via `git_path`. This is useful
-early in a Git program before the repository has been found. Unless
-you're working with early setup code, you probably don't want to use
-this.
-
 Reading Specific Files
 ----------------------
 
index 5f0757dcc965fc89b96f18e31732390b1afeb84e..695bd4bf43255e42ef26d29a5c6dff35217f220d 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 097a651d9680ea31c1a5a0e522a77ccec96c6b69..fadb5979c48b6c128f71db1588412bf0a8204677 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 b5072a28ed488a2d0a1da85d04d7ae93e1a39105..5f99f23cadea4d17d88331871fa428a0c50c9811 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v2.8.0-rc4
+DEF_VER=v2.8.2
 
 LF='
 '
index 2742a6977c6ad871897bc758ea2a7d76359b1eee..c7354bf2adc626926a276fd49e874dbfa1081ad8 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 7db30403c3471e15f4f15a5e68016d7926b3e3de..04710daa9567fb905c8213deb8634558d9d0a7aa 120000 (symlink)
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/2.8.0.txt
\ No newline at end of file
+Documentation/RelNotes/2.8.2.txt
\ No newline at end of file
index 5edb4e78162ca6646ef42ad2c8abc36872cd75a5..2825de85912fc730d9a40fa66f4f83b6250a4171 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 6537a433da201e866208ab23bf32bcafee037683..eec5d7d15a48fb9ca2fdd43d94ae515191d573f1 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 e982fb81379f57152e34eeda706a57fa1ea4c143..21f42b0b62b81b637f1cc9589cd6c0306a93d05e 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 b1738313175ca8566e9a06b2826a0425c9422a46..de6df09ed30df11ea853b5d815f22d9859ac24cc 100644 (file)
@@ -20,6 +20,7 @@
 #include "utf8.h"
 #include "wt-status.h"
 #include "ref-filter.h"
+#include "worktree.h"
 
 static const char * const builtin_branch_usage[] = {
        N_("git branch [<options>] [-r | -a] [--merged | --no-merged]"),
@@ -215,16 +216,21 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
                int flags = 0;
 
                strbuf_branchname(&bname, argv[i]);
-               if (kinds == FILTER_REFS_BRANCHES && !strcmp(head, bname.buf)) {
-                       error(_("Cannot delete the branch '%s' "
-                             "which you are currently on."), bname.buf);
-                       ret = 1;
-                       continue;
-               }
-
                free(name);
-
                name = mkpathdup(fmt, bname.buf);
+
+               if (kinds == FILTER_REFS_BRANCHES) {
+                       char *worktree = find_shared_symref("HEAD", name);
+                       if (worktree) {
+                               error(_("Cannot delete branch '%s' "
+                                       "checked out at '%s'"),
+                                     bname.buf, worktree);
+                               free(worktree);
+                               ret = 1;
+                               continue;
+                       }
+               }
+
                target = resolve_ref_unsafe(name,
                                            RESOLVE_REF_READING
                                            | RESOLVE_REF_NO_RECURSE
index b3bd2d41813f80d848afc199c2fae92cae6b6c11..c733ec98b7057b6310db6b364d5780170455dbaa 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 ca9f834ae648177a67e1c9fea9481dfe58ff3972..1d7c6ef558bf7adcfb94ea454966667f987f7701 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 79a611fda1f8b344ce619dd9318695a69eebb695..bfd0be44a91f66034c98361dc713cc0883693a69 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 aa7435f380e95d87982cd1ae71e91bc53e77af50..111b6f6cf1a61b0fb481101fcdc5a9f3f48c4650 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 45245199aebafc7fdb8eb96197dacd86c422c413..2d1eb8bb8a433e6bda50e93e3001ae6d43db093f 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 6223b7d46af346b0d96870ee0c647ab9a5440b33..b2d8d40a6750e5794dd9bfbfbcb31924a7eec4ba 100644 (file)
@@ -95,6 +95,8 @@ static void copy_templates(const char *template_dir)
        struct strbuf path = STRBUF_INIT;
        struct strbuf template_path = STRBUF_INIT;
        size_t template_len;
+       struct repository_format template_format;
+       struct strbuf err = STRBUF_INIT;
        DIR *dir;
        char *to_free = NULL;
 
@@ -121,17 +123,18 @@ static void copy_templates(const char *template_dir)
 
        /* Make sure that template is from the correct vintage */
        strbuf_addstr(&template_path, "config");
-       repository_format_version = 0;
-       git_config_from_file(check_repository_format_version,
-                            template_path.buf, NULL);
+       read_repository_format(&template_format, template_path.buf);
        strbuf_setlen(&template_path, template_len);
 
-       if (repository_format_version &&
-           repository_format_version != GIT_REPO_VERSION) {
-               warning(_("not copying templates of "
-                       "a wrong format version %d from '%s'"),
-                       repository_format_version,
-                       template_dir);
+       /*
+        * No mention of version at all is OK, but anything else should be
+        * verified.
+        */
+       if (template_format.version >= 0 &&
+           verify_repository_format(&template_format, &err) < 0) {
+               warning(_("not copying templates from '%s': %s"),
+                         template_dir, err.buf);
+               strbuf_release(&err);
                goto close_free_return;
        }
 
@@ -199,13 +202,13 @@ static int create_default_files(const char *template_path)
 
        /* reading existing config may have overwrote it */
        if (init_shared_repository != -1)
-               shared_repository = init_shared_repository;
+               set_shared_repository(init_shared_repository);
 
        /*
         * We would have created the above under user's umask -- under
         * shared-repository settings, we would need to fix them up.
         */
-       if (shared_repository) {
+       if (get_shared_repository()) {
                adjust_shared_perm(get_git_dir());
                adjust_shared_perm(git_path_buf(&buf, "refs"));
                adjust_shared_perm(git_path_buf(&buf, "refs/heads"));
@@ -322,6 +325,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;
 }
 
@@ -369,7 +373,7 @@ int init_db(const char *template_dir, unsigned int flags)
 
        create_object_directory();
 
-       if (shared_repository) {
+       if (get_shared_repository()) {
                char buf[10];
                /* We do not spell "group" and such, so that
                 * the configuration can be read by older version
@@ -377,12 +381,12 @@ int init_db(const char *template_dir, unsigned int flags)
                 * and compatibility values for PERM_GROUP and
                 * PERM_EVERYBODY.
                 */
-               if (shared_repository < 0)
+               if (get_shared_repository() < 0)
                        /* force to the mode value */
-                       xsnprintf(buf, sizeof(buf), "0%o", -shared_repository);
-               else if (shared_repository == PERM_GROUP)
+                       xsnprintf(buf, sizeof(buf), "0%o", -get_shared_repository());
+               else if (get_shared_repository() == PERM_GROUP)
                        xsnprintf(buf, sizeof(buf), "%d", OLD_PERM_GROUP);
-               else if (shared_repository == PERM_EVERYBODY)
+               else if (get_shared_repository() == PERM_EVERYBODY)
                        xsnprintf(buf, sizeof(buf), "%d", OLD_PERM_EVERYBODY);
                else
                        die("BUG: invalid value for shared_repository");
@@ -398,7 +402,7 @@ int init_db(const char *template_dir, unsigned int flags)
                   "", and the last '%s%s' is the verbatim directory name. */
                printf(_("%s%s Git repository in %s%s\n"),
                       reinit ? _("Reinitialized existing") : _("Initialized empty"),
-                      shared_repository ? _(" shared") : "",
+                      get_shared_repository() ? _(" shared") : "",
                       git_dir, len && git_dir[len-1] != '/' ? "/" : "");
        }
 
@@ -493,8 +497,8 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
                                 * and we know shared_repository should always be 0;
                                 * but just in case we play safe.
                                 */
-                               saved = shared_repository;
-                               shared_repository = 0;
+                               saved = get_shared_repository();
+                               set_shared_repository(0);
                                switch (safe_create_leading_directories_const(argv[0])) {
                                case SCLD_OK:
                                case SCLD_PERMS:
@@ -506,7 +510,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
                                        die_errno(_("cannot mkdir %s"), argv[0]);
                                        break;
                                }
-                               shared_repository = saved;
+                               set_shared_repository(saved);
                                if (mkdir(argv[0], 0777) < 0)
                                        die_errno(_("cannot mkdir %s"), argv[0]);
                                mkdir_tried = 1;
@@ -524,7 +528,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
        }
 
        if (init_shared_repository != -1)
-               shared_repository = init_shared_repository;
+               set_shared_repository(init_shared_repository);
 
        /*
         * GIT_WORK_TREE makes sense only in conjunction with GIT_DIR
index 101ffeff4c942636e0ca688357a4b8ec8aa2a431..bf2f2614fbb5ba82df3dca5cad8f79dbe605feff 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 cf8487b3b95fcca9a8a96a1562646ee8ddd5b354..c961b74c5aaae41153b89f4e877437ba7f0d70c7 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 5b9dd6a9d8ebe888c2fc912af3590b92737e7a99..1ff5a6753803f8c2ccb5e66dcb926582bd25fd37 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 b829410f6da0afc14353b4621d2fdf874181a9f7..2711048cad7d5c7bba04c5737aa6142caf49d023 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -651,7 +651,6 @@ extern int prefer_symlink_refs;
 extern int log_all_ref_updates;
 extern int warn_ambiguous_refs;
 extern int warn_on_object_refname_ambiguity;
-extern int shared_repository;
 extern const char *apply_default_whitespace;
 extern const char *apply_default_ignorewhitespace;
 extern const char *git_attributes_file;
@@ -664,6 +663,9 @@ extern size_t delta_base_cache_limit;
 extern unsigned long big_file_threshold;
 extern unsigned long pack_size_limit_cfg;
 
+void set_shared_repository(int value);
+int get_shared_repository(void);
+
 /*
  * Do replace refs need to be checked this run?  This variable is
  * initialized to true unless --no-replace-object is used or
@@ -745,9 +747,39 @@ extern int grafts_replace_parents;
  */
 #define GIT_REPO_VERSION 0
 #define GIT_REPO_VERSION_READ 1
-extern int repository_format_version;
 extern int repository_format_precious_objects;
-extern int check_repository_format(void);
+
+struct repository_format {
+       int version;
+       int precious_objects;
+       int is_bare;
+       char *work_tree;
+       struct string_list unknown_extensions;
+};
+
+/*
+ * Read the repository format characteristics from the config file "path" into
+ * "format" struct. Returns the numeric version. On error, -1 is returned,
+ * format->version is set to -1, and all other fields in the struct are
+ * undefined.
+ */
+int read_repository_format(struct repository_format *format, const char *path);
+
+/*
+ * Verify that the repository described by repository_format is something we
+ * can read. If it is, return 0. Otherwise, return -1, and "err" will describe
+ * any errors encountered.
+ */
+int verify_repository_format(const struct repository_format *format,
+                            struct strbuf *err);
+
+/*
+ * Check the repository format version in the path found in get_git_dir(),
+ * and die if it is a version we don't understand. Generally one would
+ * set_git_dir() before calling this, and use it only for "are we in a valid
+ * repo?".
+ */
+extern void check_repository_format(void);
 
 #define MTIME_CHANGED  0x0001
 #define CTIME_CHANGED  0x0002
@@ -1526,7 +1558,6 @@ extern void git_config(config_fn_t fn, void *);
 extern int git_config_with_options(config_fn_t fn, void *,
                                   struct git_config_source *config_source,
                                   int respect_includes);
-extern int git_config_early(config_fn_t fn, void *, const char *repo_config);
 extern int git_parse_ulong(const char *, unsigned long *);
 extern int git_parse_maybe_bool(const char *);
 extern int git_config_int(const char *, const char *);
@@ -1550,7 +1581,6 @@ extern void git_config_set_multivar_in_file(const char *, const char *, const ch
 extern int git_config_rename_section(const char *, const char *);
 extern int git_config_rename_section_in_file(const char *, const char *, const char *);
 extern const char *git_etc_gitconfig(void);
-extern int check_repository_format_version(const char *var, const char *value, void *cb);
 extern int git_env_bool(const char *, int);
 extern unsigned long git_env_ulong(const char *, unsigned long);
 extern int git_config_system(void);
@@ -1771,7 +1801,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 54c82ecf201dde2c317efe6862173c1b40f2552d..0413d5c3cdd128ca721c75b588dc557bdbb1f949 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 c008694639a654e6a04e541af70e90a5fa4da9e0..1de70ffd62a63070ca79d27ad0b323dfbcacb5aa 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 42ea1ac110813bbd16e77cfbc36f16e6a5e9ddb2..0b1168853778810d385c84625ad643587537913b 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 c65c2cd566b51473da12786f28074040c410f343..3a959d124ca794446800653e9c033b883d8d7b8f 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 9ba40bc1b039b9b65425dc4fa1bd9c7f1fcb0868..7ddb28754cc6592fa349b2bfa3816085c9644261 100644 (file)
--- a/config.c
+++ b/config.c
@@ -1188,11 +1188,12 @@ int git_config_system(void)
        return !git_env_bool("GIT_CONFIG_NOSYSTEM", 0);
 }
 
-int git_config_early(config_fn_t fn, void *data, const char *repo_config)
+static int do_git_config_sequence(config_fn_t fn, void *data)
 {
        int ret = 0, found = 0;
        char *xdg_config = xdg_config_home("config");
        char *user_config = expand_user_path("~/.gitconfig");
+       char *repo_config = git_pathdup("config");
 
        if (git_config_system() && !access_or_die(git_etc_gitconfig(), R_OK, 0)) {
                ret += git_config_from_file(fn, git_etc_gitconfig(),
@@ -1228,6 +1229,7 @@ int git_config_early(config_fn_t fn, void *data, const char *repo_config)
 
        free(xdg_config);
        free(user_config);
+       free(repo_config);
        return ret == 0 ? found : ret;
 }
 
@@ -1235,8 +1237,6 @@ int git_config_with_options(config_fn_t fn, void *data,
                            struct git_config_source *config_source,
                            int respect_includes)
 {
-       char *repo_config = NULL;
-       int ret;
        struct config_include_data inc = CONFIG_INCLUDE_INIT;
 
        if (respect_includes) {
@@ -1257,11 +1257,7 @@ int git_config_with_options(config_fn_t fn, void *data,
        else if (config_source && config_source->blob)
                return git_config_from_blob_ref(fn, config_source->blob, data);
 
-       repo_config = git_pathdup("config");
-       ret = git_config_early(fn, data, repo_config);
-       if (repo_config)
-               free(repo_config);
-       return ret;
+       return do_git_config_sequence(fn, data);
 }
 
 static void git_config_raw(config_fn_t fn, void *data)
index caef21e4fc91898f209709f723de1df5afc66a66..291c0fd5e935b5abedc629697d44e5a9f57727bd 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 3b3c1ed535e7c8b17947d69dbe0bd5c8f115cf2d..7f03eb5a0404d4b44f292fba76433dfec74dcd44 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 a4a9d9fae154849fe38b153af9b16e00ef401f60..996653b0d3b6d81b15a3185d8d63314de647c53d 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 cd46f30017ce239720926afdad4301b2ac402ccf..301b737a37236c1d61d109b29fa556143c28df46 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 6dec9d0403f11579a7ab316db87a1dbbc58e71b2..57acb2fe2aee79a30c4c956dcececd6a7122aeb6 100644 (file)
@@ -25,11 +25,9 @@ int log_all_ref_updates = -1; /* unspecified */
 int warn_ambiguous_refs = 1;
 int warn_on_object_refname_ambiguity = 1;
 int ref_paranoia = -1;
-int repository_format_version;
 int repository_format_precious_objects;
 const char *git_commit_encoding;
 const char *git_log_output_encoding;
-int shared_repository = PERM_UMASK;
 const char *apply_default_whitespace;
 const char *apply_default_ignorewhitespace;
 const char *git_attributes_file;
@@ -64,7 +62,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
@@ -325,3 +322,24 @@ const char *get_commit_output_encoding(void)
 {
        return git_commit_encoding ? git_commit_encoding : "UTF-8";
 }
+
+static int the_shared_repository = PERM_UMASK;
+static int need_shared_repository_from_config = 1;
+
+void set_shared_repository(int value)
+{
+       the_shared_repository = value;
+       need_shared_repository_from_config = 0;
+}
+
+int get_shared_repository(void)
+{
+       if (need_shared_repository_from_config) {
+               const char *var = "core.sharedrepository";
+               const char *value;
+               if (!git_config_get_value(var, &value))
+                       the_shared_repository = git_config_perm(var, value);
+               need_shared_repository_from_config = 0;
+       }
+       return the_shared_repository;
+}
index 9f77e3a8bb0b1197f860912b6d0e56b40b607cb9..f67bab55e85d00b06601fa488ba01975eb865359 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 d356901348042a7f2ec67211857e4d551d169d52..bc74ec979eb58754c47a5645f35f02c465d0ec54 100755 (executable)
@@ -19,6 +19,7 @@
 use 5.008;
 use strict;
 use warnings;
+use POSIX qw/strftime/;
 use Term::ReadLine;
 use Getopt::Long;
 use Text::ParseWords;
@@ -533,7 +534,7 @@ sub parse_sendmail_aliases {
                        $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) ];
                }}},
@@ -949,7 +950,7 @@ sub validate_address_list {
 sub make_message_id {
        my $uniq;
        if (!defined $message_id_stamp) {
-               $message_id_stamp = sprintf("%s-%s", time, $$);
+               $message_id_stamp = strftime("%Y%m%d%H%M%S.$$", gmtime(time));
                $message_id_serial = 0;
        }
        $message_id_serial++;
@@ -964,7 +965,7 @@ sub make_message_id {
                require Sys::Hostname;
                $du_part = 'user@' . Sys::Hostname::hostname();
        }
-       my $message_id_template = "<%s-git-send-email-%s>";
+       my $message_id_template = "<%s-%s>";
        $message_id = sprintf($message_id_template, $uniq, $du_part);
        #print "new message id = $message_id\n"; # Was useful for debugging
 }
diff --git a/git.c b/git.c
index 6cc0c077f9761f9b56e5fb7e666722b437c4fae4..968a8a464588f10c5c1564440e06d5e5afe8d37a 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 d61d537ef0cbdfa9d4a719ca622e148bbe436fd1..bfd1cfb63fa4c883af60d5086f66709965d4ec67 100644 (file)
@@ -146,7 +146,7 @@ rm -rf $RPM_BUILD_ROOT
 %files -f bin-man-doc-files
 %defattr(-,root,root)
 %{_datadir}/git-core/
-%doc README COPYING Documentation/*.txt
+%doc README.md COPYING Documentation/*.txt
 %{!?_without_docs: %doc Documentation/*.html Documentation/howto}
 %{!?_without_docs: %doc Documentation/technical}
 %{_sysconfdir}/bash_completion.d
index 80d056d2ede0a5279c0b5c05c35b46336f564533..9268cdf325f3881104d6d12ef31639536b15dcb2 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 f4a0f1cf27bf0a10626cc5b1fd628e12cbda3a7e..972623709fdac5503328f7e252d5334dfcb461c6 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;
 }
diff --git a/path.c b/path.c
index 969b494d72dff1439150e7bb945339be07c4d475..bbaea5ab0bf73056dfa74063474f62685fda1d5e 100644 (file)
--- a/path.c
+++ b/path.c
@@ -702,17 +702,17 @@ static int calc_shared_perm(int mode)
 {
        int tweak;
 
-       if (shared_repository < 0)
-               tweak = -shared_repository;
+       if (get_shared_repository() < 0)
+               tweak = -get_shared_repository();
        else
-               tweak = shared_repository;
+               tweak = get_shared_repository();
 
        if (!(mode & S_IWUSR))
                tweak &= ~0222;
        if (mode & S_IXUSR)
                /* Copy read bits to execute bits */
                tweak |= (tweak & 0444) >> 2;
-       if (shared_repository < 0)
+       if (get_shared_repository() < 0)
                mode = (mode & ~0777) | tweak;
        else
                mode |= tweak;
@@ -725,7 +725,7 @@ int adjust_shared_perm(const char *path)
 {
        int old_mode, new_mode;
 
-       if (!shared_repository)
+       if (!get_shared_repository())
                return 0;
        if (get_st_mode_bits(path, &old_mode) < 0)
                return -1;
index 88b0b8a78ad7da5dd488a015c450455d94ce3eca..55ca387ba4bf3fc174baf4cd72e70455180cf05b 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 fc02698587c61d230200272ce4704403e1a6741f..28fd676acbbf4985422d74c9f1987dd0a5765039 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 de1a2a7ea5973fef256328a26730117466c15172..1563cd42df2865d9f4390c9e68cdc666b45fcf96 100644 (file)
--- a/setup.c
+++ b/setup.c
@@ -5,7 +5,9 @@
 static int inside_git_dir = -1;
 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
@@ -370,14 +372,13 @@ void setup_work_tree(void)
        initialized = 1;
 }
 
-static int check_repo_format(const char *var, const char *value, void *cb)
+static int check_repo_format(const char *var, const char *value, void *vdata)
 {
+       struct repository_format *data = vdata;
        const char *ext;
 
        if (strcmp(var, "core.repositoryformatversion") == 0)
-               repository_format_version = git_config_int(var, value);
-       else if (strcmp(var, "core.sharedrepository") == 0)
-               shared_repository = git_config_perm(var, value);
+               data->version = git_config_int(var, value);
        else if (skip_prefix(var, "extensions.", &ext)) {
                /*
                 * record any known extensions here; otherwise,
@@ -387,9 +388,15 @@ static int check_repo_format(const char *var, const char *value, void *cb)
                if (!strcmp(ext, "noop"))
                        ;
                else if (!strcmp(ext, "preciousobjects"))
-                       repository_format_precious_objects = git_config_bool(var, value);
+                       data->precious_objects = git_config_bool(var, value);
                else
-                       string_list_append(&unknown_extensions, ext);
+                       string_list_append(&data->unknown_extensions, ext);
+       } else if (strcmp(var, "core.bare") == 0) {
+               data->is_bare = git_config_bool(var, value);
+       } else if (strcmp(var, "core.worktree") == 0) {
+               if (!value)
+                       return config_error_nonbool(var);
+               data->work_tree = xstrdup(value);
        }
        return 0;
 }
@@ -397,56 +404,84 @@ static int check_repo_format(const char *var, const char *value, void *cb)
 static int check_repository_format_gently(const char *gitdir, int *nongit_ok)
 {
        struct strbuf sb = STRBUF_INIT;
-       const char *repo_config;
-       config_fn_t fn;
-       int ret = 0;
-
-       string_list_clear(&unknown_extensions, 0);
+       struct strbuf err = STRBUF_INIT;
+       struct repository_format candidate;
+       int has_common;
 
-       if (get_common_dir(&sb, gitdir))
-               fn = check_repo_format;
-       else
-               fn = check_repository_format_version;
+       has_common = get_common_dir(&sb, gitdir);
        strbuf_addstr(&sb, "/config");
-       repo_config = sb.buf;
+       read_repository_format(&candidate, sb.buf);
+       strbuf_release(&sb);
 
        /*
-        * git_config() can't be used here because it calls git_pathdup()
-        * to get $GIT_CONFIG/config. That call will make setup_git_env()
-        * set git_dir to ".git".
-        *
-        * We are in gitdir setup, no git dir has been found useable yet.
-        * Use a gentler version of git_config() to check if this repo
-        * is a good one.
+        * For historical use of check_repository_format() in git-init,
+        * we treat a missing config as a silent "ok", even when nongit_ok
+        * is unset.
         */
-       git_config_early(fn, NULL, repo_config);
-       if (GIT_REPO_VERSION_READ < repository_format_version) {
-               if (!nongit_ok)
-                       die ("Expected git repo version <= %d, found %d",
-                            GIT_REPO_VERSION_READ, repository_format_version);
-               warning("Expected git repo version <= %d, found %d",
-                       GIT_REPO_VERSION_READ, repository_format_version);
-               warning("Please upgrade Git");
-               *nongit_ok = -1;
-               ret = -1;
+       if (candidate.version < 0)
+               return 0;
+
+       if (verify_repository_format(&candidate, &err) < 0) {
+               if (nongit_ok) {
+                       warning("%s", err.buf);
+                       strbuf_release(&err);
+                       *nongit_ok = -1;
+                       return -1;
+               }
+               die("%s", err.buf);
        }
 
-       if (repository_format_version >= 1 && unknown_extensions.nr) {
+       repository_format_precious_objects = candidate.precious_objects;
+       string_list_clear(&candidate.unknown_extensions, 0);
+       if (!has_common) {
+               if (candidate.is_bare != -1) {
+                       is_bare_repository_cfg = candidate.is_bare;
+                       if (is_bare_repository_cfg == 1)
+                               inside_work_tree = -1;
+               }
+               if (candidate.work_tree) {
+                       free(git_work_tree_cfg);
+                       git_work_tree_cfg = candidate.work_tree;
+                       inside_work_tree = -1;
+               }
+       } else {
+               free(candidate.work_tree);
+       }
+
+       return 0;
+}
+
+int read_repository_format(struct repository_format *format, const char *path)
+{
+       memset(format, 0, sizeof(*format));
+       format->version = -1;
+       format->is_bare = -1;
+       string_list_init(&format->unknown_extensions, 1);
+       git_config_from_file(check_repo_format, path, format);
+       return format->version;
+}
+
+int verify_repository_format(const struct repository_format *format,
+                            struct strbuf *err)
+{
+       if (GIT_REPO_VERSION_READ < format->version) {
+               strbuf_addf(err, _("Expected git repo version <= %d, found %d"),
+                           GIT_REPO_VERSION_READ, format->version);
+               return -1;
+       }
+
+       if (format->version >= 1 && format->unknown_extensions.nr) {
                int i;
 
-               if (!nongit_ok)
-                       die("unknown repository extension: %s",
-                           unknown_extensions.items[0].string);
+               strbuf_addstr(err, _("unknown repository extensions found:"));
 
-               for (i = 0; i < unknown_extensions.nr; i++)
-                       warning("unknown repository extension: %s",
-                               unknown_extensions.items[i].string);
-               *nongit_ok = -1;
-               ret = -1;
+               for (i = 0; i < format->unknown_extensions.nr; i++)
+                       strbuf_addf(err, "\n\t%s",
+                                   format->unknown_extensions.items[i].string);
+               return -1;
        }
 
-       strbuf_release(&sb);
-       return ret;
+       return 0;
 }
 
 /*
@@ -905,10 +940,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;
 }
 
@@ -963,28 +997,10 @@ int git_config_perm(const char *var, const char *value)
        return -(i & 0666);
 }
 
-int check_repository_format_version(const char *var, const char *value, void *cb)
-{
-       int ret = check_repo_format(var, value, cb);
-       if (ret)
-               return ret;
-       if (strcmp(var, "core.bare") == 0) {
-               is_bare_repository_cfg = git_config_bool(var, value);
-               if (is_bare_repository_cfg == 1)
-                       inside_work_tree = -1;
-       } else if (strcmp(var, "core.worktree") == 0) {
-               if (!value)
-                       return config_error_nonbool(var);
-               free(git_work_tree_cfg);
-               git_work_tree_cfg = xstrdup(value);
-               inside_work_tree = -1;
-       }
-       return 0;
-}
-
-int check_repository_format(void)
+void 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;
 }
 
 /*
index 3acf221f92f7a0857f17c0210044cacc325c8ce0..776101e8d709b924033a141efa38e3f734837c79 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 f60e2ee72ba86cbd6c66622366af4a7faf25e1a0..2c08dbb15381351ede663c1d41ebf3b6838a0c12 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 92502b594d055bbf99fd203175d7dffaf8dfb732..8476e0fa0f89c968e95182fd44211c0018a4b1f8 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 f667e7ce2f33dba0c10764f2f62101685d74cf3d..9317ba08582d2a5d06ef5a2a8d8e63c72a146b3b 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 6767da87cba9589222b033c80b605b832f708baf..3d6f1db9da95cefa02391792500b9577d4ca9902 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 613d9bfe1bbb153d1c2e647aee26a60e07a6af86..86c2ff255d43d644caf81e6258d29dcea1db8e53 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 f7d438bd7d1db0f55e5730480adfee42fd15addf..f3e3b6cf2eabf0d57f64d794dba9a6195e8da246 100755 (executable)
@@ -424,6 +424,12 @@ test_expect_success 'test deleting branch without config' '
        test_i18ncmp expect actual
 '
 
+test_expect_success 'deleting currently checked out branch fails' '
+       git worktree add -b my7 my7 &&
+       test_must_fail git -C my7 branch -d my7 &&
+       test_must_fail git branch -d my7
+'
+
 test_expect_success 'test --track without .fetch entries' '
        git branch --track my8 &&
        test "$(git config branch.my8.remote)" &&
index 2f327b749588af7eda57187cba4d365233a25ef9..ed90c6c6f984979bfc250d277486550cb5129e30 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 fc2be63e02d85682cd24457ee646c8c626ca967a..899e52d50f0d73e4a755c4f7991364f34912b336 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 04cea97f87784bfb9a9a04fdb7341478e64fd5b6..305ca7a9308685c7d040ac254fd34cebbbc86cc8 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 e5f83bf5e412bc3304009408a58663d7b94dac02..9b9bec468a849cec0344a4b735f7fcdb4f6f888d 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
diff --git a/t/t5604-clone-reference.sh b/t/t5604-clone-reference.sh
new file mode 100755 (executable)
index 0000000..4320082
--- /dev/null
@@ -0,0 +1,224 @@
+#!/bin/sh
+#
+# Copyright (C) 2006 Martin Waitz <tali@admingilde.org>
+#
+
+test_description='test clone --reference'
+. ./test-lib.sh
+
+base_dir=$(pwd)
+
+U=$base_dir/UPLOAD_LOG
+
+# create a commit in repo $1 with name $2
+commit_in () {
+       (
+               cd "$1" &&
+               echo "$2" >"$2" &&
+               git add "$2" &&
+               git commit -m "$2"
+       )
+}
+
+# check that there are $2 loose objects in repo $1
+test_objcount () {
+       echo "$2" >expect &&
+       git -C "$1" count-objects >actual.raw &&
+       cut -d' ' -f1 <actual.raw >actual &&
+       test_cmp expect actual
+}
+
+test_expect_success 'preparing first repository' '
+       test_create_repo A &&
+       commit_in A file1
+'
+
+test_expect_success 'preparing second repository' '
+       git clone A B &&
+       commit_in B file2 &&
+       git -C B repack -ad &&
+       git -C B prune
+'
+
+test_expect_success 'cloning with reference (-l -s)' '
+       git clone -l -s --reference B A C
+'
+
+test_expect_success 'existence of info/alternates' '
+       test_line_count = 2 C/.git/objects/info/alternates
+'
+
+test_expect_success 'pulling from reference' '
+       git -C C pull ../B master
+'
+
+test_expect_success 'that reference gets used' '
+       test_objcount C 0
+'
+
+test_expect_success 'cloning with reference (no -l -s)' '
+       GIT_TRACE_PACKET=$U.D git clone --reference B "file://$(pwd)/A" D
+'
+
+test_expect_success 'fetched no objects' '
+       test -s "$U.D" &&
+       ! grep " want" "$U.D"
+'
+
+test_expect_success 'existence of info/alternates' '
+       test_line_count = 1 D/.git/objects/info/alternates
+'
+
+test_expect_success 'pulling from reference' '
+       git -C D pull ../B master
+'
+
+test_expect_success 'that reference gets used' '
+       test_objcount D 0
+'
+
+test_expect_success 'updating origin' '
+       commit_in A file3 &&
+       git -C A repack -ad &&
+       git -C A prune
+'
+
+test_expect_success 'pulling changes from origin' '
+       git -C C pull origin
+'
+
+# the 2 local objects are commit and tree from the merge
+test_expect_success 'that alternate to origin gets used' '
+       test_objcount C 2
+'
+
+test_expect_success 'pulling changes from origin' '
+       git -C D pull origin
+'
+
+# the 5 local objects are expected; file3 blob, commit in A to add it
+# and its tree, and 2 are our tree and the merge commit.
+test_expect_success 'check objects expected to exist locally' '
+       test_objcount D 5
+'
+
+test_expect_success 'preparing alternate repository #1' '
+       test_create_repo F &&
+       commit_in F file1
+'
+
+test_expect_success 'cloning alternate repo #2 and adding changes to repo #1' '
+       git clone F G &&
+       commit_in F file2
+'
+
+test_expect_success 'cloning alternate repo #1, using #2 as reference' '
+       git clone --reference G F H
+'
+
+test_expect_success 'cloning with reference being subset of source (-l -s)' '
+       git clone -l -s --reference A B E
+'
+
+test_expect_success 'cloning with multiple references drops duplicates' '
+       git clone -s --reference B --reference A --reference B A dups &&
+       test_line_count = 2 dups/.git/objects/info/alternates
+'
+
+test_expect_success 'clone with reference from a tagged repository' '
+       (
+               cd A && git tag -a -m tagged HEAD
+       ) &&
+       git clone --reference=A A I
+'
+
+test_expect_success 'prepare branched repository' '
+       git clone A J &&
+       (
+               cd J &&
+               git checkout -b other master^ &&
+               echo other >otherfile &&
+               git add otherfile &&
+               git commit -m other &&
+               git checkout master
+       )
+'
+
+test_expect_success 'fetch with incomplete alternates' '
+       git init K &&
+       echo "$base_dir/A/.git/objects" >K/.git/objects/info/alternates &&
+       (
+               cd K &&
+               git remote add J "file://$base_dir/J" &&
+               GIT_TRACE_PACKET=$U.K git fetch J
+       ) &&
+       master_object=$(cd A && git for-each-ref --format="%(objectname)" refs/heads/master) &&
+       test -s "$U.K" &&
+       ! grep " want $master_object" "$U.K" &&
+       tag_object=$(cd A && git for-each-ref --format="%(objectname)" refs/tags/HEAD) &&
+       ! grep " want $tag_object" "$U.K"
+'
+
+test_expect_success 'clone using repo with gitfile as a reference' '
+       git clone --separate-git-dir=L A M &&
+       git clone --reference=M A N &&
+       echo "$base_dir/L/objects" >expected &&
+       test_cmp expected "$base_dir/N/.git/objects/info/alternates"
+'
+
+test_expect_success 'clone using repo pointed at by gitfile as reference' '
+       git clone --reference=M/.git A O &&
+       echo "$base_dir/L/objects" >expected &&
+       test_cmp expected "$base_dir/O/.git/objects/info/alternates"
+'
+
+test_expect_success 'clone and dissociate from reference' '
+       git init P &&
+       (
+               cd P && test_commit one
+       ) &&
+       git clone P Q &&
+       (
+               cd Q && test_commit two
+       ) &&
+       git clone --no-local --reference=P Q R &&
+       git clone --no-local --reference=P --dissociate Q S &&
+       # removing the reference P would corrupt R but not S
+       rm -fr P &&
+       test_must_fail git -C R fsck &&
+       git -C S fsck
+'
+test_expect_success 'clone, dissociate from partial reference and repack' '
+       rm -fr P Q R &&
+       git init P &&
+       (
+               cd P &&
+               test_commit one &&
+               git repack &&
+               test_commit two &&
+               git repack
+       ) &&
+       git clone --bare P Q &&
+       (
+               cd P &&
+               git checkout -b second &&
+               test_commit three &&
+               git repack
+       ) &&
+       git clone --bare --dissociate --reference=P Q R &&
+       ls R/objects/pack/*.pack >packs.txt &&
+       test_line_count = 1 packs.txt
+'
+
+test_expect_success 'clone, dissociate from alternates' '
+       rm -fr A B C &&
+       test_create_repo A &&
+       commit_in A file1 &&
+       git clone --reference=A A B &&
+       test_line_count = 1 B/.git/objects/info/alternates &&
+       git clone --local --dissociate B C &&
+       ! test -f C/.git/objects/info/alternates &&
+       ( cd C && git fsck )
+'
+
+test_done
diff --git a/t/t5605-clone-local.sh b/t/t5605-clone-local.sh
new file mode 100755 (executable)
index 0000000..3c087e9
--- /dev/null
@@ -0,0 +1,141 @@
+#!/bin/sh
+
+test_description='test local clone'
+. ./test-lib.sh
+
+repo_is_hardlinked() {
+       find "$1/objects" -type f -links 1 >output &&
+       test_line_count = 0 output
+}
+
+test_expect_success 'preparing origin repository' '
+       : >file && git add . && git commit -m1 &&
+       git clone --bare . a.git &&
+       git clone --bare . x &&
+       test "$(cd a.git && git config --bool core.bare)" = true &&
+       test "$(cd x && git config --bool core.bare)" = true &&
+       git bundle create b1.bundle --all &&
+       git bundle create b2.bundle master &&
+       mkdir dir &&
+       cp b1.bundle dir/b3 &&
+       cp b1.bundle b4
+'
+
+test_expect_success 'local clone without .git suffix' '
+       git clone -l -s a b &&
+       (cd b &&
+       test "$(git config --bool core.bare)" = false &&
+       git fetch)
+'
+
+test_expect_success 'local clone with .git suffix' '
+       git clone -l -s a.git c &&
+       (cd c && git fetch)
+'
+
+test_expect_success 'local clone from x' '
+       git clone -l -s x y &&
+       (cd y && git fetch)
+'
+
+test_expect_success 'local clone from x.git that does not exist' '
+       test_must_fail git clone -l -s x.git z
+'
+
+test_expect_success 'With -no-hardlinks, local will make a copy' '
+       git clone --bare --no-hardlinks x w &&
+       ! repo_is_hardlinked w
+'
+
+test_expect_success 'Even without -l, local will make a hardlink' '
+       rm -fr w &&
+       git clone -l --bare x w &&
+       repo_is_hardlinked w
+'
+
+test_expect_success 'local clone of repo with nonexistent ref in HEAD' '
+       echo "ref: refs/heads/nonexistent" > a.git/HEAD &&
+       git clone a d &&
+       (cd d &&
+       git fetch &&
+       test ! -e .git/refs/remotes/origin/HEAD)
+'
+
+test_expect_success 'bundle clone without .bundle suffix' '
+       git clone dir/b3 &&
+       (cd b3 && git fetch)
+'
+
+test_expect_success 'bundle clone with .bundle suffix' '
+       git clone b1.bundle &&
+       (cd b1 && git fetch)
+'
+
+test_expect_success 'bundle clone from b4' '
+       git clone b4 bdl &&
+       (cd bdl && git fetch)
+'
+
+test_expect_success 'bundle clone from b4.bundle that does not exist' '
+       test_must_fail git clone b4.bundle bb
+'
+
+test_expect_success 'bundle clone with nonexistent HEAD' '
+       git clone b2.bundle b2 &&
+       (cd b2 &&
+       git fetch &&
+       test_must_fail git rev-parse --verify refs/heads/master)
+'
+
+test_expect_success 'clone empty repository' '
+       mkdir empty &&
+       (cd empty &&
+        git init &&
+        git config receive.denyCurrentBranch warn) &&
+       git clone empty empty-clone &&
+       test_tick &&
+       (cd empty-clone
+        echo "content" >> foo &&
+        git add foo &&
+        git commit -m "Initial commit" &&
+        git push origin master &&
+        expected=$(git rev-parse master) &&
+        actual=$(git --git-dir=../empty/.git rev-parse master) &&
+        test $actual = $expected)
+'
+
+test_expect_success 'clone empty repository, and then push should not segfault.' '
+       rm -fr empty/ empty-clone/ &&
+       mkdir empty &&
+       (cd empty && git init) &&
+       git clone empty empty-clone &&
+       (cd empty-clone &&
+       test_must_fail git push)
+'
+
+test_expect_success 'cloning non-existent directory fails' '
+       rm -rf does-not-exist &&
+       test_must_fail git clone does-not-exist
+'
+
+test_expect_success 'cloning non-git directory fails' '
+       rm -rf not-a-git-repo not-a-git-repo-clone &&
+       mkdir not-a-git-repo &&
+       test_must_fail git clone not-a-git-repo not-a-git-repo-clone
+'
+
+test_expect_success 'cloning file:// does not hardlink' '
+       git clone --bare file://"$(pwd)"/a non-local &&
+       ! repo_is_hardlinked non-local
+'
+
+test_expect_success 'cloning a local path with --no-local does not hardlink' '
+       git clone --bare --no-local a force-nonlocal &&
+       ! repo_is_hardlinked force-nonlocal
+'
+
+test_expect_success 'cloning locally respects "-u" for fetching refs' '
+       test_must_fail git clone --bare -u false a should_not_work.git
+'
+
+test_done
diff --git a/t/t5606-clone-options.sh b/t/t5606-clone-options.sh
new file mode 100755 (executable)
index 0000000..9e24ec8
--- /dev/null
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+test_description='basic clone options'
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+
+       mkdir parent &&
+       (cd parent && git init &&
+        echo one >file && git add file &&
+        git commit -m one)
+
+'
+
+test_expect_success 'clone -o' '
+
+       git clone -o foo parent clone-o &&
+       (cd clone-o && git rev-parse --verify refs/remotes/foo/master)
+
+'
+
+test_expect_success 'redirected clone does not show progress' '
+
+       git clone "file://$(pwd)/parent" clone-redirected >out 2>err &&
+       ! grep % err &&
+       test_i18ngrep ! "Checking connectivity" err
+
+'
+
+test_expect_success 'redirected clone -v does show progress' '
+
+       git clone --progress "file://$(pwd)/parent" clone-redirected-progress \
+               >out 2>err &&
+       grep % err
+
+'
+
+test_done
diff --git a/t/t5607-clone-bundle.sh b/t/t5607-clone-bundle.sh
new file mode 100755 (executable)
index 0000000..348d9b3
--- /dev/null
@@ -0,0 +1,74 @@
+#!/bin/sh
+
+test_description='some bundle related tests'
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+       test_commit initial &&
+       test_tick &&
+       git tag -m tag tag &&
+       test_commit second &&
+       test_commit third &&
+       git tag -d initial &&
+       git tag -d second &&
+       git tag -d third
+'
+
+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
+'
+
+test_expect_success 'die if bundle file cannot be created' '
+       mkdir adir &&
+       test_must_fail git bundle create adir --all
+'
+
+test_expect_failure 'bundle --stdin' '
+       echo master | git bundle create stdin-bundle.bdl --stdin &&
+       git ls-remote stdin-bundle.bdl >output &&
+       grep master output
+'
+
+test_expect_failure 'bundle --stdin <rev-list options>' '
+       echo master | git bundle create hybrid-bundle.bdl --stdin tag &&
+       git ls-remote hybrid-bundle.bdl >output &&
+       grep master output
+'
+
+test_expect_success 'empty bundle file is rejected' '
+       : >empty-bundle &&
+       test_must_fail git fetch empty-bundle
+'
+
+# This triggers a bug in older versions where the resulting line (with
+# --pretty=oneline) was longer than a 1024-char buffer.
+test_expect_success 'ridiculously long subject in boundary' '
+       : >file4 &&
+       test_tick &&
+       git add file4 &&
+       printf "%01200d\n" 0 | git commit -F - &&
+       test_commit fifth &&
+       git bundle create long-subject-bundle.bdl HEAD^..HEAD &&
+       git bundle list-heads long-subject-bundle.bdl >heads &&
+       test -s heads &&
+       git fetch long-subject-bundle.bdl &&
+       sed -n "/^-/{p;q;}" long-subject-bundle.bdl >boundary &&
+       grep "^-[0-9a-f]\\{40\\} " boundary
+'
+
+test_expect_success 'prerequisites with an empty commit message' '
+       : >file1 &&
+       git add file1 &&
+       test_tick &&
+       git commit --allow-empty-message -m "" &&
+       test_commit file2 &&
+       git bundle create bundle HEAD^.. &&
+       git bundle verify bundle
+'
+
+test_done
diff --git a/t/t5608-clone-2gb.sh b/t/t5608-clone-2gb.sh
new file mode 100755 (executable)
index 0000000..191d6d3
--- /dev/null
@@ -0,0 +1,53 @@
+#!/bin/sh
+
+test_description='Test cloning a repository larger than 2 gigabyte'
+. ./test-lib.sh
+
+if test -z "$GIT_TEST_CLONE_2GB"
+then
+       say 'Skipping expensive 2GB clone test; enable it with GIT_TEST_CLONE_2GB=t'
+else
+       test_set_prereq CLONE_2GB
+fi
+
+test_expect_success CLONE_2GB 'setup' '
+
+       git config pack.compression 0 &&
+       git config pack.depth 0 &&
+       blobsize=$((100*1024*1024)) &&
+       blobcount=$((2*1024*1024*1024/$blobsize+1)) &&
+       i=1 &&
+       (while test $i -le $blobcount
+        do
+               printf "Generating blob $i/$blobcount\r" >&2 &&
+               printf "blob\nmark :$i\ndata $blobsize\n" &&
+               #test-genrandom $i $blobsize &&
+               printf "%-${blobsize}s" $i &&
+               echo "M 100644 :$i $i" >> commit
+               i=$(($i+1)) ||
+               echo $? > exit-status
+        done &&
+        echo "commit refs/heads/master" &&
+        echo "author A U Thor <author@email.com> 123456789 +0000" &&
+        echo "committer C O Mitter <committer@email.com> 123456789 +0000" &&
+        echo "data 5" &&
+        echo ">2gb" &&
+        cat commit) |
+       git fast-import --big-file-threshold=2 &&
+       test ! -f exit-status
+
+'
+
+test_expect_success CLONE_2GB 'clone - bare' '
+
+       git clone --bare --no-hardlinks . clone-bare
+
+'
+
+test_expect_success CLONE_2GB 'clone - with worktree, file:// protocol' '
+
+       git clone "file://$(pwd)" clone-wt
+
+'
+
+test_done
diff --git a/t/t5609-clone-branch.sh b/t/t5609-clone-branch.sh
new file mode 100755 (executable)
index 0000000..6e7a7be
--- /dev/null
@@ -0,0 +1,70 @@
+#!/bin/sh
+
+test_description='clone --branch option'
+. ./test-lib.sh
+
+check_HEAD() {
+       echo refs/heads/"$1" >expect &&
+       git symbolic-ref HEAD >actual &&
+       test_cmp expect actual
+}
+
+check_file() {
+       echo "$1" >expect &&
+       test_cmp expect file
+}
+
+test_expect_success 'setup' '
+       mkdir parent &&
+       (cd parent && git init &&
+        echo one >file && git add file && git commit -m one &&
+        git checkout -b two &&
+        echo two >file && git add file && git commit -m two &&
+        git checkout master) &&
+       mkdir empty &&
+       (cd empty && git init)
+'
+
+test_expect_success 'vanilla clone chooses HEAD' '
+       git clone parent clone &&
+       (cd clone &&
+        check_HEAD master &&
+        check_file one
+       )
+'
+
+test_expect_success 'clone -b chooses specified branch' '
+       git clone -b two parent clone-two &&
+       (cd clone-two &&
+        check_HEAD two &&
+        check_file two
+       )
+'
+
+test_expect_success 'clone -b sets up tracking' '
+       (cd clone-two &&
+        echo origin >expect &&
+        git config branch.two.remote >actual &&
+        echo refs/heads/two >>expect &&
+        git config branch.two.merge >>actual &&
+        test_cmp expect actual
+       )
+'
+
+test_expect_success 'clone -b does not munge remotes/origin/HEAD' '
+       (cd clone-two &&
+        echo refs/remotes/origin/master >expect &&
+        git symbolic-ref refs/remotes/origin/HEAD >actual &&
+        test_cmp expect actual
+       )
+'
+
+test_expect_success 'clone -b with bogus branch' '
+       test_must_fail git clone -b bogus parent clone-bogus
+'
+
+test_expect_success 'clone -b not allowed with empty repos' '
+       test_must_fail git clone -b branch empty clone-branch-empty
+'
+
+test_done
diff --git a/t/t5610-clone-detached.sh b/t/t5610-clone-detached.sh
new file mode 100755 (executable)
index 0000000..8b0d607
--- /dev/null
@@ -0,0 +1,76 @@
+#!/bin/sh
+
+test_description='test cloning a repository with detached HEAD'
+. ./test-lib.sh
+
+head_is_detached() {
+       git --git-dir=$1/.git rev-parse --verify HEAD &&
+       test_must_fail git --git-dir=$1/.git symbolic-ref HEAD
+}
+
+test_expect_success 'setup' '
+       echo one >file &&
+       git add file &&
+       git commit -m one &&
+       echo two >file &&
+       git commit -a -m two &&
+       git tag two &&
+       echo three >file &&
+       git commit -a -m three
+'
+
+test_expect_success 'clone repo (detached HEAD points to branch)' '
+       git checkout master^0 &&
+       git clone "file://$PWD" detached-branch
+'
+test_expect_success 'cloned HEAD matches' '
+       echo three >expect &&
+       git --git-dir=detached-branch/.git log -1 --format=%s >actual &&
+       test_cmp expect actual
+'
+test_expect_failure 'cloned HEAD is detached' '
+       head_is_detached detached-branch
+'
+
+test_expect_success 'clone repo (detached HEAD points to tag)' '
+       git checkout two^0 &&
+       git clone "file://$PWD" detached-tag
+'
+test_expect_success 'cloned HEAD matches' '
+       echo two >expect &&
+       git --git-dir=detached-tag/.git log -1 --format=%s >actual &&
+       test_cmp expect actual
+'
+test_expect_success 'cloned HEAD is detached' '
+       head_is_detached detached-tag
+'
+
+test_expect_success 'clone repo (detached HEAD points to history)' '
+       git checkout two^ &&
+       git clone "file://$PWD" detached-history
+'
+test_expect_success 'cloned HEAD matches' '
+       echo one >expect &&
+       git --git-dir=detached-history/.git log -1 --format=%s >actual &&
+       test_cmp expect actual
+'
+test_expect_success 'cloned HEAD is detached' '
+       head_is_detached detached-history
+'
+
+test_expect_success 'clone repo (orphan detached HEAD)' '
+       git checkout master^0 &&
+       echo four >file &&
+       git commit -a -m four &&
+       git clone "file://$PWD" detached-orphan
+'
+test_expect_success 'cloned HEAD matches' '
+       echo four >expect &&
+       git --git-dir=detached-orphan/.git log -1 --format=%s >actual &&
+       test_cmp expect actual
+'
+test_expect_success 'cloned HEAD is detached' '
+       head_is_detached detached-orphan
+'
+
+test_done
diff --git a/t/t5611-clone-config.sh b/t/t5611-clone-config.sh
new file mode 100755 (executable)
index 0000000..27d730c
--- /dev/null
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+test_description='tests for git clone -c key=value'
+. ./test-lib.sh
+
+test_expect_success 'clone -c sets config in cloned repo' '
+       rm -rf child &&
+       git clone -c core.foo=bar . child &&
+       echo bar >expect &&
+       git --git-dir=child/.git config core.foo >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'clone -c can set multi-keys' '
+       rm -rf child &&
+       git clone -c core.foo=bar -c core.foo=baz . child &&
+       { echo bar; echo baz; } >expect &&
+       git --git-dir=child/.git config --get-all core.foo >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'clone -c without a value is boolean true' '
+       rm -rf child &&
+       git clone -c core.foo . child &&
+       echo true >expect &&
+       git --git-dir=child/.git config --bool core.foo >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'clone -c config is available during clone' '
+       echo content >file &&
+       git add file &&
+       git commit -m one &&
+       rm -rf child &&
+       git clone -c core.autocrlf . child &&
+       printf "content\\r\\n" >expect &&
+       test_cmp expect child/file
+'
+
+test_done
diff --git a/t/t5612-clone-refspec.sh b/t/t5612-clone-refspec.sh
new file mode 100755 (executable)
index 0000000..7ace253
--- /dev/null
@@ -0,0 +1,156 @@
+#!/bin/sh
+
+test_description='test refspec written by clone-command'
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+       # Make two branches, "master" and "side"
+       echo one >file &&
+       git add file &&
+       git commit -m one &&
+       echo two >file &&
+       git commit -a -m two &&
+       git tag two &&
+       echo three >file &&
+       git commit -a -m three &&
+       git checkout -b side &&
+       echo four >file &&
+       git commit -a -m four &&
+       git checkout master &&
+
+       # default clone
+       git clone . dir_all &&
+
+       # default --single that follows HEAD=master
+       git clone --single-branch . dir_master &&
+
+       # default --single that follows HEAD=side
+       git checkout side &&
+       git clone --single-branch . dir_side &&
+
+       # explicit --single that follows side
+       git checkout master &&
+       git clone --single-branch --branch side . dir_side2 &&
+
+       # default --single with --mirror
+       git clone --single-branch --mirror . dir_mirror &&
+
+       # default --single with --branch and --mirror
+       git clone --single-branch --mirror --branch side . dir_mirror_side &&
+
+       # --single that does not know what branch to follow
+       git checkout two^ &&
+       git clone --single-branch . dir_detached &&
+
+       # explicit --single with tag
+       git clone --single-branch --branch two . dir_tag &&
+
+       # advance both "master" and "side" branches
+       git checkout side &&
+       echo five >file &&
+       git commit -a -m five &&
+       git checkout master &&
+       echo six >file &&
+       git commit -a -m six &&
+
+       # update tag
+       git tag -d two && git tag two
+'
+
+test_expect_success 'by default all branches will be kept updated' '
+       (
+               cd dir_all && git fetch &&
+               git for-each-ref refs/remotes/origin |
+               sed -e "/HEAD$/d" \
+                   -e "s|/remotes/origin/|/heads/|" >../actual
+       ) &&
+       # follow both master and side
+       git for-each-ref refs/heads >expect &&
+       test_cmp expect actual
+'
+
+test_expect_success 'by default no tags will be kept updated' '
+       (
+               cd dir_all && git fetch &&
+               git for-each-ref refs/tags >../actual
+       ) &&
+       git for-each-ref refs/tags >expect &&
+       test_must_fail test_cmp expect actual
+'
+
+test_expect_success '--single-branch while HEAD pointing at master' '
+       (
+               cd dir_master && git fetch &&
+               git for-each-ref refs/remotes/origin |
+               sed -e "/HEAD$/d" \
+                   -e "s|/remotes/origin/|/heads/|" >../actual
+       ) &&
+       # only follow master
+       git for-each-ref refs/heads/master >expect &&
+       test_cmp expect actual
+'
+
+test_expect_success '--single-branch while HEAD pointing at side' '
+       (
+               cd dir_side && git fetch &&
+               git for-each-ref refs/remotes/origin |
+               sed -e "/HEAD$/d" \
+                   -e "s|/remotes/origin/|/heads/|" >../actual
+       ) &&
+       # only follow side
+       git for-each-ref refs/heads/side >expect &&
+       test_cmp expect actual
+'
+
+test_expect_success '--single-branch with explicit --branch side' '
+       (
+               cd dir_side2 && git fetch &&
+               git for-each-ref refs/remotes/origin |
+               sed -e "/HEAD$/d" \
+                   -e "s|/remotes/origin/|/heads/|" >../actual
+       ) &&
+       # only follow side
+       git for-each-ref refs/heads/side >expect &&
+       test_cmp expect actual
+'
+
+test_expect_success '--single-branch with explicit --branch with tag fetches updated tag' '
+       (
+               cd dir_tag && git fetch &&
+               git for-each-ref refs/tags >../actual
+       ) &&
+       git for-each-ref refs/tags >expect &&
+       test_cmp expect actual
+'
+
+test_expect_success '--single-branch with --mirror' '
+       (
+               cd dir_mirror && git fetch &&
+               git for-each-ref refs > ../actual
+       ) &&
+       git for-each-ref refs >expect &&
+       test_cmp expect actual
+'
+
+test_expect_success '--single-branch with explicit --branch and --mirror' '
+       (
+               cd dir_mirror_side && git fetch &&
+               git for-each-ref refs > ../actual
+       ) &&
+       git for-each-ref refs >expect &&
+       test_cmp expect actual
+'
+
+test_expect_success '--single-branch with detached' '
+       (
+               cd dir_detached && git fetch &&
+               git for-each-ref refs/remotes/origin |
+               sed -e "/HEAD$/d" \
+                   -e "s|/remotes/origin/|/heads/|" >../actual
+       ) &&
+       # nothing
+       >expect &&
+       test_cmp expect actual
+'
+
+test_done
diff --git a/t/t5613-info-alternate.sh b/t/t5613-info-alternate.sh
new file mode 100755 (executable)
index 0000000..9cd2626
--- /dev/null
@@ -0,0 +1,112 @@
+#!/bin/sh
+#
+# Copyright (C) 2006 Martin Waitz <tali@admingilde.org>
+#
+
+test_description='test transitive info/alternate entries'
+. ./test-lib.sh
+
+# test that a file is not reachable in the current repository
+# but that it is after creating a info/alternate entry
+reachable_via() {
+       alternate="$1"
+       file="$2"
+       if git cat-file -e "HEAD:$file"; then return 1; fi
+       echo "$alternate" >> .git/objects/info/alternate
+       git cat-file -e "HEAD:$file"
+}
+
+test_valid_repo() {
+       git fsck --full > fsck.log &&
+       test_line_count = 0 fsck.log
+}
+
+base_dir=$(pwd)
+
+test_expect_success 'preparing first repository' \
+'test_create_repo A && cd A &&
+echo "Hello World" > file1 &&
+git add file1 &&
+git commit -m "Initial commit" file1 &&
+git repack -a -d &&
+git prune'
+
+cd "$base_dir"
+
+test_expect_success 'preparing second repository' \
+'git clone -l -s A B && cd B &&
+echo "foo bar" > file2 &&
+git add file2 &&
+git commit -m "next commit" file2 &&
+git repack -a -d -l &&
+git prune'
+
+cd "$base_dir"
+
+test_expect_success 'preparing third repository' \
+'git clone -l -s B C && cd C &&
+echo "Goodbye, cruel world" > file3 &&
+git add file3 &&
+git commit -m "one more" file3 &&
+git repack -a -d -l &&
+git prune'
+
+cd "$base_dir"
+
+test_expect_success 'creating too deep nesting' \
+'git clone -l -s C D &&
+git clone -l -s D E &&
+git clone -l -s E F &&
+git clone -l -s F G &&
+git clone --bare -l -s G H'
+
+test_expect_success 'invalidity of deepest repository' \
+'cd H && {
+       test_valid_repo
+       test $? -ne 0
+}'
+
+cd "$base_dir"
+
+test_expect_success 'validity of third repository' \
+'cd C &&
+test_valid_repo'
+
+cd "$base_dir"
+
+test_expect_success 'validity of fourth repository' \
+'cd D &&
+test_valid_repo'
+
+cd "$base_dir"
+
+test_expect_success 'breaking of loops' \
+'echo "$base_dir"/B/.git/objects >> "$base_dir"/A/.git/objects/info/alternates&&
+cd C &&
+test_valid_repo'
+
+cd "$base_dir"
+
+test_expect_success 'that info/alternates is necessary' \
+'cd C &&
+rm -f .git/objects/info/alternates &&
+! (test_valid_repo)'
+
+cd "$base_dir"
+
+test_expect_success 'that relative alternate is possible for current dir' \
+'cd C &&
+echo "../../../B/.git/objects" > .git/objects/info/alternates &&
+test_valid_repo'
+
+cd "$base_dir"
+
+test_expect_success \
+    'that relative alternate is only possible for current dir' '
+    cd D &&
+    ! (test_valid_repo)
+'
+
+cd "$base_dir"
+
+test_done
diff --git a/t/t5700-clone-reference.sh b/t/t5700-clone-reference.sh
deleted file mode 100755 (executable)
index 4320082..0000000
+++ /dev/null
@@ -1,224 +0,0 @@
-#!/bin/sh
-#
-# Copyright (C) 2006 Martin Waitz <tali@admingilde.org>
-#
-
-test_description='test clone --reference'
-. ./test-lib.sh
-
-base_dir=$(pwd)
-
-U=$base_dir/UPLOAD_LOG
-
-# create a commit in repo $1 with name $2
-commit_in () {
-       (
-               cd "$1" &&
-               echo "$2" >"$2" &&
-               git add "$2" &&
-               git commit -m "$2"
-       )
-}
-
-# check that there are $2 loose objects in repo $1
-test_objcount () {
-       echo "$2" >expect &&
-       git -C "$1" count-objects >actual.raw &&
-       cut -d' ' -f1 <actual.raw >actual &&
-       test_cmp expect actual
-}
-
-test_expect_success 'preparing first repository' '
-       test_create_repo A &&
-       commit_in A file1
-'
-
-test_expect_success 'preparing second repository' '
-       git clone A B &&
-       commit_in B file2 &&
-       git -C B repack -ad &&
-       git -C B prune
-'
-
-test_expect_success 'cloning with reference (-l -s)' '
-       git clone -l -s --reference B A C
-'
-
-test_expect_success 'existence of info/alternates' '
-       test_line_count = 2 C/.git/objects/info/alternates
-'
-
-test_expect_success 'pulling from reference' '
-       git -C C pull ../B master
-'
-
-test_expect_success 'that reference gets used' '
-       test_objcount C 0
-'
-
-test_expect_success 'cloning with reference (no -l -s)' '
-       GIT_TRACE_PACKET=$U.D git clone --reference B "file://$(pwd)/A" D
-'
-
-test_expect_success 'fetched no objects' '
-       test -s "$U.D" &&
-       ! grep " want" "$U.D"
-'
-
-test_expect_success 'existence of info/alternates' '
-       test_line_count = 1 D/.git/objects/info/alternates
-'
-
-test_expect_success 'pulling from reference' '
-       git -C D pull ../B master
-'
-
-test_expect_success 'that reference gets used' '
-       test_objcount D 0
-'
-
-test_expect_success 'updating origin' '
-       commit_in A file3 &&
-       git -C A repack -ad &&
-       git -C A prune
-'
-
-test_expect_success 'pulling changes from origin' '
-       git -C C pull origin
-'
-
-# the 2 local objects are commit and tree from the merge
-test_expect_success 'that alternate to origin gets used' '
-       test_objcount C 2
-'
-
-test_expect_success 'pulling changes from origin' '
-       git -C D pull origin
-'
-
-# the 5 local objects are expected; file3 blob, commit in A to add it
-# and its tree, and 2 are our tree and the merge commit.
-test_expect_success 'check objects expected to exist locally' '
-       test_objcount D 5
-'
-
-test_expect_success 'preparing alternate repository #1' '
-       test_create_repo F &&
-       commit_in F file1
-'
-
-test_expect_success 'cloning alternate repo #2 and adding changes to repo #1' '
-       git clone F G &&
-       commit_in F file2
-'
-
-test_expect_success 'cloning alternate repo #1, using #2 as reference' '
-       git clone --reference G F H
-'
-
-test_expect_success 'cloning with reference being subset of source (-l -s)' '
-       git clone -l -s --reference A B E
-'
-
-test_expect_success 'cloning with multiple references drops duplicates' '
-       git clone -s --reference B --reference A --reference B A dups &&
-       test_line_count = 2 dups/.git/objects/info/alternates
-'
-
-test_expect_success 'clone with reference from a tagged repository' '
-       (
-               cd A && git tag -a -m tagged HEAD
-       ) &&
-       git clone --reference=A A I
-'
-
-test_expect_success 'prepare branched repository' '
-       git clone A J &&
-       (
-               cd J &&
-               git checkout -b other master^ &&
-               echo other >otherfile &&
-               git add otherfile &&
-               git commit -m other &&
-               git checkout master
-       )
-'
-
-test_expect_success 'fetch with incomplete alternates' '
-       git init K &&
-       echo "$base_dir/A/.git/objects" >K/.git/objects/info/alternates &&
-       (
-               cd K &&
-               git remote add J "file://$base_dir/J" &&
-               GIT_TRACE_PACKET=$U.K git fetch J
-       ) &&
-       master_object=$(cd A && git for-each-ref --format="%(objectname)" refs/heads/master) &&
-       test -s "$U.K" &&
-       ! grep " want $master_object" "$U.K" &&
-       tag_object=$(cd A && git for-each-ref --format="%(objectname)" refs/tags/HEAD) &&
-       ! grep " want $tag_object" "$U.K"
-'
-
-test_expect_success 'clone using repo with gitfile as a reference' '
-       git clone --separate-git-dir=L A M &&
-       git clone --reference=M A N &&
-       echo "$base_dir/L/objects" >expected &&
-       test_cmp expected "$base_dir/N/.git/objects/info/alternates"
-'
-
-test_expect_success 'clone using repo pointed at by gitfile as reference' '
-       git clone --reference=M/.git A O &&
-       echo "$base_dir/L/objects" >expected &&
-       test_cmp expected "$base_dir/O/.git/objects/info/alternates"
-'
-
-test_expect_success 'clone and dissociate from reference' '
-       git init P &&
-       (
-               cd P && test_commit one
-       ) &&
-       git clone P Q &&
-       (
-               cd Q && test_commit two
-       ) &&
-       git clone --no-local --reference=P Q R &&
-       git clone --no-local --reference=P --dissociate Q S &&
-       # removing the reference P would corrupt R but not S
-       rm -fr P &&
-       test_must_fail git -C R fsck &&
-       git -C S fsck
-'
-test_expect_success 'clone, dissociate from partial reference and repack' '
-       rm -fr P Q R &&
-       git init P &&
-       (
-               cd P &&
-               test_commit one &&
-               git repack &&
-               test_commit two &&
-               git repack
-       ) &&
-       git clone --bare P Q &&
-       (
-               cd P &&
-               git checkout -b second &&
-               test_commit three &&
-               git repack
-       ) &&
-       git clone --bare --dissociate --reference=P Q R &&
-       ls R/objects/pack/*.pack >packs.txt &&
-       test_line_count = 1 packs.txt
-'
-
-test_expect_success 'clone, dissociate from alternates' '
-       rm -fr A B C &&
-       test_create_repo A &&
-       commit_in A file1 &&
-       git clone --reference=A A B &&
-       test_line_count = 1 B/.git/objects/info/alternates &&
-       git clone --local --dissociate B C &&
-       ! test -f C/.git/objects/info/alternates &&
-       ( cd C && git fsck )
-'
-
-test_done
diff --git a/t/t5701-clone-local.sh b/t/t5701-clone-local.sh
deleted file mode 100755 (executable)
index 3c087e9..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-#!/bin/sh
-
-test_description='test local clone'
-. ./test-lib.sh
-
-repo_is_hardlinked() {
-       find "$1/objects" -type f -links 1 >output &&
-       test_line_count = 0 output
-}
-
-test_expect_success 'preparing origin repository' '
-       : >file && git add . && git commit -m1 &&
-       git clone --bare . a.git &&
-       git clone --bare . x &&
-       test "$(cd a.git && git config --bool core.bare)" = true &&
-       test "$(cd x && git config --bool core.bare)" = true &&
-       git bundle create b1.bundle --all &&
-       git bundle create b2.bundle master &&
-       mkdir dir &&
-       cp b1.bundle dir/b3 &&
-       cp b1.bundle b4
-'
-
-test_expect_success 'local clone without .git suffix' '
-       git clone -l -s a b &&
-       (cd b &&
-       test "$(git config --bool core.bare)" = false &&
-       git fetch)
-'
-
-test_expect_success 'local clone with .git suffix' '
-       git clone -l -s a.git c &&
-       (cd c && git fetch)
-'
-
-test_expect_success 'local clone from x' '
-       git clone -l -s x y &&
-       (cd y && git fetch)
-'
-
-test_expect_success 'local clone from x.git that does not exist' '
-       test_must_fail git clone -l -s x.git z
-'
-
-test_expect_success 'With -no-hardlinks, local will make a copy' '
-       git clone --bare --no-hardlinks x w &&
-       ! repo_is_hardlinked w
-'
-
-test_expect_success 'Even without -l, local will make a hardlink' '
-       rm -fr w &&
-       git clone -l --bare x w &&
-       repo_is_hardlinked w
-'
-
-test_expect_success 'local clone of repo with nonexistent ref in HEAD' '
-       echo "ref: refs/heads/nonexistent" > a.git/HEAD &&
-       git clone a d &&
-       (cd d &&
-       git fetch &&
-       test ! -e .git/refs/remotes/origin/HEAD)
-'
-
-test_expect_success 'bundle clone without .bundle suffix' '
-       git clone dir/b3 &&
-       (cd b3 && git fetch)
-'
-
-test_expect_success 'bundle clone with .bundle suffix' '
-       git clone b1.bundle &&
-       (cd b1 && git fetch)
-'
-
-test_expect_success 'bundle clone from b4' '
-       git clone b4 bdl &&
-       (cd bdl && git fetch)
-'
-
-test_expect_success 'bundle clone from b4.bundle that does not exist' '
-       test_must_fail git clone b4.bundle bb
-'
-
-test_expect_success 'bundle clone with nonexistent HEAD' '
-       git clone b2.bundle b2 &&
-       (cd b2 &&
-       git fetch &&
-       test_must_fail git rev-parse --verify refs/heads/master)
-'
-
-test_expect_success 'clone empty repository' '
-       mkdir empty &&
-       (cd empty &&
-        git init &&
-        git config receive.denyCurrentBranch warn) &&
-       git clone empty empty-clone &&
-       test_tick &&
-       (cd empty-clone
-        echo "content" >> foo &&
-        git add foo &&
-        git commit -m "Initial commit" &&
-        git push origin master &&
-        expected=$(git rev-parse master) &&
-        actual=$(git --git-dir=../empty/.git rev-parse master) &&
-        test $actual = $expected)
-'
-
-test_expect_success 'clone empty repository, and then push should not segfault.' '
-       rm -fr empty/ empty-clone/ &&
-       mkdir empty &&
-       (cd empty && git init) &&
-       git clone empty empty-clone &&
-       (cd empty-clone &&
-       test_must_fail git push)
-'
-
-test_expect_success 'cloning non-existent directory fails' '
-       rm -rf does-not-exist &&
-       test_must_fail git clone does-not-exist
-'
-
-test_expect_success 'cloning non-git directory fails' '
-       rm -rf not-a-git-repo not-a-git-repo-clone &&
-       mkdir not-a-git-repo &&
-       test_must_fail git clone not-a-git-repo not-a-git-repo-clone
-'
-
-test_expect_success 'cloning file:// does not hardlink' '
-       git clone --bare file://"$(pwd)"/a non-local &&
-       ! repo_is_hardlinked non-local
-'
-
-test_expect_success 'cloning a local path with --no-local does not hardlink' '
-       git clone --bare --no-local a force-nonlocal &&
-       ! repo_is_hardlinked force-nonlocal
-'
-
-test_expect_success 'cloning locally respects "-u" for fetching refs' '
-       test_must_fail git clone --bare -u false a should_not_work.git
-'
-
-test_done
diff --git a/t/t5702-clone-options.sh b/t/t5702-clone-options.sh
deleted file mode 100755 (executable)
index 9e24ec8..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/bin/sh
-
-test_description='basic clone options'
-. ./test-lib.sh
-
-test_expect_success 'setup' '
-
-       mkdir parent &&
-       (cd parent && git init &&
-        echo one >file && git add file &&
-        git commit -m one)
-
-'
-
-test_expect_success 'clone -o' '
-
-       git clone -o foo parent clone-o &&
-       (cd clone-o && git rev-parse --verify refs/remotes/foo/master)
-
-'
-
-test_expect_success 'redirected clone does not show progress' '
-
-       git clone "file://$(pwd)/parent" clone-redirected >out 2>err &&
-       ! grep % err &&
-       test_i18ngrep ! "Checking connectivity" err
-
-'
-
-test_expect_success 'redirected clone -v does show progress' '
-
-       git clone --progress "file://$(pwd)/parent" clone-redirected-progress \
-               >out 2>err &&
-       grep % err
-
-'
-
-test_done
diff --git a/t/t5704-bundle.sh b/t/t5704-bundle.sh
deleted file mode 100755 (executable)
index 348d9b3..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-#!/bin/sh
-
-test_description='some bundle related tests'
-. ./test-lib.sh
-
-test_expect_success 'setup' '
-       test_commit initial &&
-       test_tick &&
-       git tag -m tag tag &&
-       test_commit second &&
-       test_commit third &&
-       git tag -d initial &&
-       git tag -d second &&
-       git tag -d third
-'
-
-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
-'
-
-test_expect_success 'die if bundle file cannot be created' '
-       mkdir adir &&
-       test_must_fail git bundle create adir --all
-'
-
-test_expect_failure 'bundle --stdin' '
-       echo master | git bundle create stdin-bundle.bdl --stdin &&
-       git ls-remote stdin-bundle.bdl >output &&
-       grep master output
-'
-
-test_expect_failure 'bundle --stdin <rev-list options>' '
-       echo master | git bundle create hybrid-bundle.bdl --stdin tag &&
-       git ls-remote hybrid-bundle.bdl >output &&
-       grep master output
-'
-
-test_expect_success 'empty bundle file is rejected' '
-       : >empty-bundle &&
-       test_must_fail git fetch empty-bundle
-'
-
-# This triggers a bug in older versions where the resulting line (with
-# --pretty=oneline) was longer than a 1024-char buffer.
-test_expect_success 'ridiculously long subject in boundary' '
-       : >file4 &&
-       test_tick &&
-       git add file4 &&
-       printf "%01200d\n" 0 | git commit -F - &&
-       test_commit fifth &&
-       git bundle create long-subject-bundle.bdl HEAD^..HEAD &&
-       git bundle list-heads long-subject-bundle.bdl >heads &&
-       test -s heads &&
-       git fetch long-subject-bundle.bdl &&
-       sed -n "/^-/{p;q;}" long-subject-bundle.bdl >boundary &&
-       grep "^-[0-9a-f]\\{40\\} " boundary
-'
-
-test_expect_success 'prerequisites with an empty commit message' '
-       : >file1 &&
-       git add file1 &&
-       test_tick &&
-       git commit --allow-empty-message -m "" &&
-       test_commit file2 &&
-       git bundle create bundle HEAD^.. &&
-       git bundle verify bundle
-'
-
-test_done
diff --git a/t/t5705-clone-2gb.sh b/t/t5705-clone-2gb.sh
deleted file mode 100755 (executable)
index 191d6d3..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-#!/bin/sh
-
-test_description='Test cloning a repository larger than 2 gigabyte'
-. ./test-lib.sh
-
-if test -z "$GIT_TEST_CLONE_2GB"
-then
-       say 'Skipping expensive 2GB clone test; enable it with GIT_TEST_CLONE_2GB=t'
-else
-       test_set_prereq CLONE_2GB
-fi
-
-test_expect_success CLONE_2GB 'setup' '
-
-       git config pack.compression 0 &&
-       git config pack.depth 0 &&
-       blobsize=$((100*1024*1024)) &&
-       blobcount=$((2*1024*1024*1024/$blobsize+1)) &&
-       i=1 &&
-       (while test $i -le $blobcount
-        do
-               printf "Generating blob $i/$blobcount\r" >&2 &&
-               printf "blob\nmark :$i\ndata $blobsize\n" &&
-               #test-genrandom $i $blobsize &&
-               printf "%-${blobsize}s" $i &&
-               echo "M 100644 :$i $i" >> commit
-               i=$(($i+1)) ||
-               echo $? > exit-status
-        done &&
-        echo "commit refs/heads/master" &&
-        echo "author A U Thor <author@email.com> 123456789 +0000" &&
-        echo "committer C O Mitter <committer@email.com> 123456789 +0000" &&
-        echo "data 5" &&
-        echo ">2gb" &&
-        cat commit) |
-       git fast-import --big-file-threshold=2 &&
-       test ! -f exit-status
-
-'
-
-test_expect_success CLONE_2GB 'clone - bare' '
-
-       git clone --bare --no-hardlinks . clone-bare
-
-'
-
-test_expect_success CLONE_2GB 'clone - with worktree, file:// protocol' '
-
-       git clone "file://$(pwd)" clone-wt
-
-'
-
-test_done
diff --git a/t/t5706-clone-branch.sh b/t/t5706-clone-branch.sh
deleted file mode 100755 (executable)
index 6e7a7be..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/bin/sh
-
-test_description='clone --branch option'
-. ./test-lib.sh
-
-check_HEAD() {
-       echo refs/heads/"$1" >expect &&
-       git symbolic-ref HEAD >actual &&
-       test_cmp expect actual
-}
-
-check_file() {
-       echo "$1" >expect &&
-       test_cmp expect file
-}
-
-test_expect_success 'setup' '
-       mkdir parent &&
-       (cd parent && git init &&
-        echo one >file && git add file && git commit -m one &&
-        git checkout -b two &&
-        echo two >file && git add file && git commit -m two &&
-        git checkout master) &&
-       mkdir empty &&
-       (cd empty && git init)
-'
-
-test_expect_success 'vanilla clone chooses HEAD' '
-       git clone parent clone &&
-       (cd clone &&
-        check_HEAD master &&
-        check_file one
-       )
-'
-
-test_expect_success 'clone -b chooses specified branch' '
-       git clone -b two parent clone-two &&
-       (cd clone-two &&
-        check_HEAD two &&
-        check_file two
-       )
-'
-
-test_expect_success 'clone -b sets up tracking' '
-       (cd clone-two &&
-        echo origin >expect &&
-        git config branch.two.remote >actual &&
-        echo refs/heads/two >>expect &&
-        git config branch.two.merge >>actual &&
-        test_cmp expect actual
-       )
-'
-
-test_expect_success 'clone -b does not munge remotes/origin/HEAD' '
-       (cd clone-two &&
-        echo refs/remotes/origin/master >expect &&
-        git symbolic-ref refs/remotes/origin/HEAD >actual &&
-        test_cmp expect actual
-       )
-'
-
-test_expect_success 'clone -b with bogus branch' '
-       test_must_fail git clone -b bogus parent clone-bogus
-'
-
-test_expect_success 'clone -b not allowed with empty repos' '
-       test_must_fail git clone -b branch empty clone-branch-empty
-'
-
-test_done
diff --git a/t/t5707-clone-detached.sh b/t/t5707-clone-detached.sh
deleted file mode 100755 (executable)
index 8b0d607..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-#!/bin/sh
-
-test_description='test cloning a repository with detached HEAD'
-. ./test-lib.sh
-
-head_is_detached() {
-       git --git-dir=$1/.git rev-parse --verify HEAD &&
-       test_must_fail git --git-dir=$1/.git symbolic-ref HEAD
-}
-
-test_expect_success 'setup' '
-       echo one >file &&
-       git add file &&
-       git commit -m one &&
-       echo two >file &&
-       git commit -a -m two &&
-       git tag two &&
-       echo three >file &&
-       git commit -a -m three
-'
-
-test_expect_success 'clone repo (detached HEAD points to branch)' '
-       git checkout master^0 &&
-       git clone "file://$PWD" detached-branch
-'
-test_expect_success 'cloned HEAD matches' '
-       echo three >expect &&
-       git --git-dir=detached-branch/.git log -1 --format=%s >actual &&
-       test_cmp expect actual
-'
-test_expect_failure 'cloned HEAD is detached' '
-       head_is_detached detached-branch
-'
-
-test_expect_success 'clone repo (detached HEAD points to tag)' '
-       git checkout two^0 &&
-       git clone "file://$PWD" detached-tag
-'
-test_expect_success 'cloned HEAD matches' '
-       echo two >expect &&
-       git --git-dir=detached-tag/.git log -1 --format=%s >actual &&
-       test_cmp expect actual
-'
-test_expect_success 'cloned HEAD is detached' '
-       head_is_detached detached-tag
-'
-
-test_expect_success 'clone repo (detached HEAD points to history)' '
-       git checkout two^ &&
-       git clone "file://$PWD" detached-history
-'
-test_expect_success 'cloned HEAD matches' '
-       echo one >expect &&
-       git --git-dir=detached-history/.git log -1 --format=%s >actual &&
-       test_cmp expect actual
-'
-test_expect_success 'cloned HEAD is detached' '
-       head_is_detached detached-history
-'
-
-test_expect_success 'clone repo (orphan detached HEAD)' '
-       git checkout master^0 &&
-       echo four >file &&
-       git commit -a -m four &&
-       git clone "file://$PWD" detached-orphan
-'
-test_expect_success 'cloned HEAD matches' '
-       echo four >expect &&
-       git --git-dir=detached-orphan/.git log -1 --format=%s >actual &&
-       test_cmp expect actual
-'
-test_expect_success 'cloned HEAD is detached' '
-       head_is_detached detached-orphan
-'
-
-test_done
diff --git a/t/t5708-clone-config.sh b/t/t5708-clone-config.sh
deleted file mode 100755 (executable)
index 27d730c..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/bin/sh
-
-test_description='tests for git clone -c key=value'
-. ./test-lib.sh
-
-test_expect_success 'clone -c sets config in cloned repo' '
-       rm -rf child &&
-       git clone -c core.foo=bar . child &&
-       echo bar >expect &&
-       git --git-dir=child/.git config core.foo >actual &&
-       test_cmp expect actual
-'
-
-test_expect_success 'clone -c can set multi-keys' '
-       rm -rf child &&
-       git clone -c core.foo=bar -c core.foo=baz . child &&
-       { echo bar; echo baz; } >expect &&
-       git --git-dir=child/.git config --get-all core.foo >actual &&
-       test_cmp expect actual
-'
-
-test_expect_success 'clone -c without a value is boolean true' '
-       rm -rf child &&
-       git clone -c core.foo . child &&
-       echo true >expect &&
-       git --git-dir=child/.git config --bool core.foo >actual &&
-       test_cmp expect actual
-'
-
-test_expect_success 'clone -c config is available during clone' '
-       echo content >file &&
-       git add file &&
-       git commit -m one &&
-       rm -rf child &&
-       git clone -c core.autocrlf . child &&
-       printf "content\\r\\n" >expect &&
-       test_cmp expect child/file
-'
-
-test_done
diff --git a/t/t5709-clone-refspec.sh b/t/t5709-clone-refspec.sh
deleted file mode 100755 (executable)
index 7ace253..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-#!/bin/sh
-
-test_description='test refspec written by clone-command'
-. ./test-lib.sh
-
-test_expect_success 'setup' '
-       # Make two branches, "master" and "side"
-       echo one >file &&
-       git add file &&
-       git commit -m one &&
-       echo two >file &&
-       git commit -a -m two &&
-       git tag two &&
-       echo three >file &&
-       git commit -a -m three &&
-       git checkout -b side &&
-       echo four >file &&
-       git commit -a -m four &&
-       git checkout master &&
-
-       # default clone
-       git clone . dir_all &&
-
-       # default --single that follows HEAD=master
-       git clone --single-branch . dir_master &&
-
-       # default --single that follows HEAD=side
-       git checkout side &&
-       git clone --single-branch . dir_side &&
-
-       # explicit --single that follows side
-       git checkout master &&
-       git clone --single-branch --branch side . dir_side2 &&
-
-       # default --single with --mirror
-       git clone --single-branch --mirror . dir_mirror &&
-
-       # default --single with --branch and --mirror
-       git clone --single-branch --mirror --branch side . dir_mirror_side &&
-
-       # --single that does not know what branch to follow
-       git checkout two^ &&
-       git clone --single-branch . dir_detached &&
-
-       # explicit --single with tag
-       git clone --single-branch --branch two . dir_tag &&
-
-       # advance both "master" and "side" branches
-       git checkout side &&
-       echo five >file &&
-       git commit -a -m five &&
-       git checkout master &&
-       echo six >file &&
-       git commit -a -m six &&
-
-       # update tag
-       git tag -d two && git tag two
-'
-
-test_expect_success 'by default all branches will be kept updated' '
-       (
-               cd dir_all && git fetch &&
-               git for-each-ref refs/remotes/origin |
-               sed -e "/HEAD$/d" \
-                   -e "s|/remotes/origin/|/heads/|" >../actual
-       ) &&
-       # follow both master and side
-       git for-each-ref refs/heads >expect &&
-       test_cmp expect actual
-'
-
-test_expect_success 'by default no tags will be kept updated' '
-       (
-               cd dir_all && git fetch &&
-               git for-each-ref refs/tags >../actual
-       ) &&
-       git for-each-ref refs/tags >expect &&
-       test_must_fail test_cmp expect actual
-'
-
-test_expect_success '--single-branch while HEAD pointing at master' '
-       (
-               cd dir_master && git fetch &&
-               git for-each-ref refs/remotes/origin |
-               sed -e "/HEAD$/d" \
-                   -e "s|/remotes/origin/|/heads/|" >../actual
-       ) &&
-       # only follow master
-       git for-each-ref refs/heads/master >expect &&
-       test_cmp expect actual
-'
-
-test_expect_success '--single-branch while HEAD pointing at side' '
-       (
-               cd dir_side && git fetch &&
-               git for-each-ref refs/remotes/origin |
-               sed -e "/HEAD$/d" \
-                   -e "s|/remotes/origin/|/heads/|" >../actual
-       ) &&
-       # only follow side
-       git for-each-ref refs/heads/side >expect &&
-       test_cmp expect actual
-'
-
-test_expect_success '--single-branch with explicit --branch side' '
-       (
-               cd dir_side2 && git fetch &&
-               git for-each-ref refs/remotes/origin |
-               sed -e "/HEAD$/d" \
-                   -e "s|/remotes/origin/|/heads/|" >../actual
-       ) &&
-       # only follow side
-       git for-each-ref refs/heads/side >expect &&
-       test_cmp expect actual
-'
-
-test_expect_success '--single-branch with explicit --branch with tag fetches updated tag' '
-       (
-               cd dir_tag && git fetch &&
-               git for-each-ref refs/tags >../actual
-       ) &&
-       git for-each-ref refs/tags >expect &&
-       test_cmp expect actual
-'
-
-test_expect_success '--single-branch with --mirror' '
-       (
-               cd dir_mirror && git fetch &&
-               git for-each-ref refs > ../actual
-       ) &&
-       git for-each-ref refs >expect &&
-       test_cmp expect actual
-'
-
-test_expect_success '--single-branch with explicit --branch and --mirror' '
-       (
-               cd dir_mirror_side && git fetch &&
-               git for-each-ref refs > ../actual
-       ) &&
-       git for-each-ref refs >expect &&
-       test_cmp expect actual
-'
-
-test_expect_success '--single-branch with detached' '
-       (
-               cd dir_detached && git fetch &&
-               git for-each-ref refs/remotes/origin |
-               sed -e "/HEAD$/d" \
-                   -e "s|/remotes/origin/|/heads/|" >../actual
-       ) &&
-       # nothing
-       >expect &&
-       test_cmp expect actual
-'
-
-test_done
diff --git a/t/t5710-info-alternate.sh b/t/t5710-info-alternate.sh
deleted file mode 100755 (executable)
index 9cd2626..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-#!/bin/sh
-#
-# Copyright (C) 2006 Martin Waitz <tali@admingilde.org>
-#
-
-test_description='test transitive info/alternate entries'
-. ./test-lib.sh
-
-# test that a file is not reachable in the current repository
-# but that it is after creating a info/alternate entry
-reachable_via() {
-       alternate="$1"
-       file="$2"
-       if git cat-file -e "HEAD:$file"; then return 1; fi
-       echo "$alternate" >> .git/objects/info/alternate
-       git cat-file -e "HEAD:$file"
-}
-
-test_valid_repo() {
-       git fsck --full > fsck.log &&
-       test_line_count = 0 fsck.log
-}
-
-base_dir=$(pwd)
-
-test_expect_success 'preparing first repository' \
-'test_create_repo A && cd A &&
-echo "Hello World" > file1 &&
-git add file1 &&
-git commit -m "Initial commit" file1 &&
-git repack -a -d &&
-git prune'
-
-cd "$base_dir"
-
-test_expect_success 'preparing second repository' \
-'git clone -l -s A B && cd B &&
-echo "foo bar" > file2 &&
-git add file2 &&
-git commit -m "next commit" file2 &&
-git repack -a -d -l &&
-git prune'
-
-cd "$base_dir"
-
-test_expect_success 'preparing third repository' \
-'git clone -l -s B C && cd C &&
-echo "Goodbye, cruel world" > file3 &&
-git add file3 &&
-git commit -m "one more" file3 &&
-git repack -a -d -l &&
-git prune'
-
-cd "$base_dir"
-
-test_expect_success 'creating too deep nesting' \
-'git clone -l -s C D &&
-git clone -l -s D E &&
-git clone -l -s E F &&
-git clone -l -s F G &&
-git clone --bare -l -s G H'
-
-test_expect_success 'invalidity of deepest repository' \
-'cd H && {
-       test_valid_repo
-       test $? -ne 0
-}'
-
-cd "$base_dir"
-
-test_expect_success 'validity of third repository' \
-'cd C &&
-test_valid_repo'
-
-cd "$base_dir"
-
-test_expect_success 'validity of fourth repository' \
-'cd D &&
-test_valid_repo'
-
-cd "$base_dir"
-
-test_expect_success 'breaking of loops' \
-'echo "$base_dir"/B/.git/objects >> "$base_dir"/A/.git/objects/info/alternates&&
-cd C &&
-test_valid_repo'
-
-cd "$base_dir"
-
-test_expect_success 'that info/alternates is necessary' \
-'cd C &&
-rm -f .git/objects/info/alternates &&
-! (test_valid_repo)'
-
-cd "$base_dir"
-
-test_expect_success 'that relative alternate is possible for current dir' \
-'cd C &&
-echo "../../../B/.git/objects" > .git/objects/info/alternates &&
-test_valid_repo'
-
-cd "$base_dir"
-
-test_expect_success \
-    'that relative alternate is only possible for current dir' '
-    cd D &&
-    ! (test_valid_repo)
-'
-
-cd "$base_dir"
-
-test_done
index b39e313ac2a7393899e2fbaa5bc860c4d95c68ee..725687d5d5f26d6535b3f26d1fa221a8c567d57c 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 302e23826341bce6c3797330b5f2996877dc5baf..85248a14b61d68b61932d595eb0fa8fcaa8506b1 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 6f12b235b3a9330497e814d5e8f564aec94d0c44..76306cf268a18b7c086cf871f39adf9247f07e32 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 b540944408a6feb35f28ff7e18601db7a29f8635..1e72971a165efc127e6bda24fb0e4a3852d3c543 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 6568429753d5f90426ad6acc0703b79e9f7a3284..a9b266f0d3d029229a346fb21c703acb84e4c37d 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 4c5f3c9d418bf6f85f1067b2cb1481bf941ff954..25bb60b2814320b628d3d12af88ee1d394a94217 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 109f03e711803251b5b5d06bc42579784a326ba8..4dad7095f10bb324f043ff8132678488b65d4537 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 285f06b7ff262378150be80f2a09b4162ae3a564..3d0313354b3e100fe3624b58c61af7cc7e0f8e7b 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 b3f6653ffda1a3d6d319752676511307d9cd032b..dc802a07c2225463c2e4ee923b9cf144d57a00cc 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 63a22c630e521969b08c8ecb1ce9fa3e0f3ff513..13b55aba7441bc84d2c5c075110e9ef798ba18f8 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;