]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Merge branch 'dt/submodule-rm-with-stale-cache' into maint
authorJunio C Hamano <gitster@pobox.com>
Tue, 17 Mar 2020 22:02:21 +0000 (15:02 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 17 Mar 2020 22:02:21 +0000 (15:02 -0700)
Running "git rm" on a submodule failed unnecessarily when
.gitmodules is only cache-dirty, which has been corrected.

* dt/submodule-rm-with-stale-cache:
  git rm submodule: succeed if .gitmodules index stat info is zero

51 files changed:
.mailmap
Documentation/RelNotes/2.25.1.txt [new file with mode: 0644]
Documentation/config/http.txt
Documentation/config/user.txt
Documentation/diff-options.txt
Documentation/fetch-options.txt
Documentation/git-commit-tree.txt
Documentation/git-commit.txt
Documentation/git-filter-branch.txt
Documentation/git-grep.txt
Documentation/git-submodule.txt
Documentation/git-update-index.txt
Documentation/git.txt
Documentation/gitcore-tutorial.txt
Documentation/technical/bundle-format.txt [new file with mode: 0644]
Documentation/technical/pack-format.txt
GIT-VERSION-GEN
Makefile
RelNotes
add-interactive.c
builtin/checkout.c
builtin/commit.c
builtin/grep.c
ci/test-documentation.sh
compat/regex/regex.h
convert.c
dir.c
object-store.h
parse-options.c
pathspec.c
run-command.c
setup.c
sha1-file.c
string-list.h
submodule.c
t/t0040-parse-options.sh
t/t2070-restore.sh
t/t2405-worktree-submodule.sh [new file with mode: 0755]
t/t3701-add-interactive.sh
t/t4018-diff-funcname.sh
t/t5510-fetch.sh
t/t5616-partial-clone.sh
t/t5702-protocol-v2.sh
t/t6136-pathspec-in-bare.sh [new file with mode: 0755]
t/t7300-clean.sh
t/t7410-submodule-checkout-to.sh [deleted file]
t/t7500-commit-template-squash-signoff.sh
t/t7800-difftool.sh
t/t7814-grep-recurse-submodules.sh
transport.c
unpack-trees.c

index fbef813f24f13dfff55a4859017009a58fbb77c6..73fd92e192bd348dd64965fd33feb9d61b11b957 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -59,6 +59,7 @@ David S. Miller <davem@davemloft.net>
 David Turner <novalis@novalis.org> <dturner@twopensource.com>
 David Turner <novalis@novalis.org> <dturner@twosigma.com>
 Derrick Stolee <dstolee@microsoft.com> <stolee@gmail.com>
+Derrick Stolee <dstolee@microsoft.com> Derrick Stolee via GitGitGadget <gitgitgadget@gmail.com>
 Deskin Miller <deskinm@umich.edu>
 Đoàn Trần Công Danh <congdanhqx@gmail.com> Doan Tran Cong Danh
 Dirk Süsserott <newsletter@dirk.my1.cc>
@@ -288,6 +289,7 @@ William Pursell <bill.pursell@gmail.com>
 YONETANI Tomokazu <y0n3t4n1@gmail.com> <qhwt+git@les.ath.cx>
 YONETANI Tomokazu <y0n3t4n1@gmail.com> <y0netan1@dragonflybsd.org>
 YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
+Yi-Jyun Pan <pan93412@gmail.com>
 # the two anonymous contributors are different persons:
 anonymous <linux@horizon.com>
 anonymous <linux@horizon.net>
diff --git a/Documentation/RelNotes/2.25.1.txt b/Documentation/RelNotes/2.25.1.txt
new file mode 100644 (file)
index 0000000..cd869b0
--- /dev/null
@@ -0,0 +1,55 @@
+Git 2.25.1 Release Notes
+========================
+
+Fixes since v2.25
+-----------------
+
+ * "git commit" gives output similar to "git status" when there is
+   nothing to commit, but without honoring the advise.statusHints
+   configuration variable, which has been corrected.
+
+ * has_object_file() said "no" given an object registered to the
+   system via pretend_object_file(), making it inconsistent with
+   read_object_file(), causing lazy fetch to attempt fetching an
+   empty tree from promisor remotes.
+
+ * The code that tries to skip over the entries for the paths in a
+   single directory using the cache-tree was not careful enough
+   against corrupt index file.
+
+ * Complete an update to tutorial that encourages "git switch" over
+   "git checkout" that was done only half-way.
+
+ * Reduce unnecessary round-trip when running "ls-remote" over the
+   stateless RPC mechanism.
+
+ * "git restore --staged" did not correctly update the cache-tree
+   structure, resulting in bogus trees to be written afterwards, which
+   has been corrected.
+
+ * The code recently added to move to the entry beyond the ones in the
+   same directory in the index in the sparse-cone mode did not count
+   the number of entries to skip over incorrectly, which has been
+   corrected.
+
+ * Work around test breakages caused by custom regex engine used in
+   libasan, when address sanitizer is used with more recent versions
+   of gcc and clang.
+
+ * "git fetch --refmap=" option has got a better documentation.
+
+ * Corner case bugs in "git clean" that stems from a (necessarily for
+   performance reasons) awkward calling convention in the directory
+   enumeration API has been corrected.
+
+ * "git grep --no-index" should not get affected by the contents of
+   the .gitmodules file but when "--recurse-submodules" is given or
+   the "submodule.recurse" variable is set, it did.  Now these
+   settings are ignored in the "--no-index" mode.
+
+ * Technical details of the bundle format has been documented.
+
+ * Unhelpful warning messages during documentation build have been
+   squelched.
+
+Also contains various documentation updates, code clean-ups and minor fixups.
index 5a32f5b0a5a9c312bb414d0405cab0f97e826a01..e806033aab86ae7efd52a26a1efd2067178c28dc 100644 (file)
@@ -71,7 +71,7 @@ http.saveCookies::
 http.version::
        Use the specified HTTP protocol version when communicating with a server.
        If you want to force the default. The available and default version depend
-       on libcurl. Actually the possible values of
+       on libcurl. Currently the possible values of
        this option are:
 
        - HTTP/2
@@ -84,7 +84,7 @@ http.sslVersion::
        particular configuration of the crypto library in use. Internally
        this sets the 'CURLOPT_SSL_VERSION' option; see the libcurl
        documentation for more details on the format of this option and
-       for the ssl version supported. Actually the possible values of
+       for the ssl version supported. Currently the possible values of
        this option are:
 
        - sslv2
@@ -199,6 +199,14 @@ http.postBuffer::
        Transfer-Encoding: chunked is used to avoid creating a
        massive pack file locally.  Default is 1 MiB, which is
        sufficient for most requests.
++
+Note that raising this limit is only effective for disabling chunked
+transfer encoding and therefore should be used only where the remote
+server or a proxy only supports HTTP/1.0 or is noncompliant with the
+HTTP standard.  Raising this is not, in general, an effective solution
+for most push problems, but can increase memory consumption
+significantly since the entire buffer is allocated even for small
+pushes.
 
 http.lowSpeedLimit, http.lowSpeedTime::
        If the HTTP transfer speed is less than 'http.lowSpeedLimit'
index 0557cbbceb8159148e8d0e7ab4771a8f53a67c0a..59aec7c3aed32aac0a8d7e015c0602705e4ccc6d 100644 (file)
@@ -13,7 +13,12 @@ committer.email::
        Also, all of these can be overridden by the `GIT_AUTHOR_NAME`,
        `GIT_AUTHOR_EMAIL`, `GIT_COMMITTER_NAME`,
        `GIT_COMMITTER_EMAIL` and `EMAIL` environment variables.
-       See linkgit:git-commit-tree[1] for more information.
++
+Note that the `name` forms of these variables conventionally refer to
+some form of a personal name.  See linkgit:git-commit[1] and the
+environment variables section of linkgit:git[1] for more information on
+these settings and the `credential.username` option if you're looking
+for authentication credentials instead.
 
 user.useConfigOnly::
        Instruct Git to avoid trying to guess defaults for `user.email`
index 09faee3b44db2e78ba909d30c62ff105255c7832..bb31f0c42b3f8a7b26f6eb01e7e1ad7c0b0fa008 100644 (file)
@@ -567,13 +567,13 @@ To illustrate the difference between `-S<regex> --pickaxe-regex` and
 file:
 +
 ----
-+    return !regexec(regexp, two->ptr, 1, &regmatch, 0);
++    return frotz(nitfol, two->ptr, 1, 0);
 ...
--    hit = !regexec(regexp, mf2.ptr, 1, &regmatch, 0);
+-    hit = frotz(nitfol, mf2.ptr, 1, 0);
 ----
 +
-While `git log -G"regexec\(regexp"` will show this commit, `git log
--S"regexec\(regexp" --pickaxe-regex` will not (because the number of
+While `git log -G"frotz\(nitfol"` will show this commit, `git log
+-S"frotz\(nitfol" --pickaxe-regex` will not (because the number of
 occurrences of that string did not change).
 +
 Unless `--text` is supplied patches of binary files without a textconv
index a2f78624a27e68dfe5a97adcac9cd67c109d1f52..a115a1ae0e973dc0375e82cbc1de5eff182aa9a1 100644 (file)
@@ -139,7 +139,10 @@ ifndef::git-pull[]
        specified refspec (can be given more than once) to map the
        refs to remote-tracking branches, instead of the values of
        `remote.*.fetch` configuration variables for the remote
-       repository.  See section on "Configured Remote-tracking
+       repository.  Providing an empty `<refspec>` to the
+       `--refmap` option causes Git to ignore the configured
+       refspecs and rely entirely on the refspecs supplied as
+       command-line arguments. See section on "Configured Remote-tracking
        Branches" for details.
 
 -t::
index 4b90b9c12a4a87fe563d367ab8252750021969d7..ec15ee8d6fad83d5dfe7d019cbb5984303552d9e 100644 (file)
@@ -69,7 +69,6 @@ OPTIONS
        Do not GPG-sign commit, to countermand a `--gpg-sign` option
        given earlier on the command line.
 
-
 Commit Information
 ------------------
 
@@ -79,26 +78,6 @@ A commit encapsulates:
 - author name, email and date
 - committer name and email and the commit time.
 
-While parent object ids are provided on the command line, author and
-committer information is taken from the following environment variables,
-if set:
-
-       GIT_AUTHOR_NAME
-       GIT_AUTHOR_EMAIL
-       GIT_AUTHOR_DATE
-       GIT_COMMITTER_NAME
-       GIT_COMMITTER_EMAIL
-       GIT_COMMITTER_DATE
-
-(nb "<", ">" and "\n"s are stripped)
-
-In case (some of) these environment variables are not set, the information
-is taken from the configuration items user.name and user.email, or, if not
-present, the environment variable EMAIL, or, if that is not set,
-system user name and the hostname used for outgoing mail (taken
-from `/etc/mailname` and falling back to the fully qualified hostname when
-that file does not exist).
-
 A commit comment is read from stdin. If a changelog
 entry is not provided via "<" redirection, 'git commit-tree' will just wait
 for one to be entered and terminated with ^D.
@@ -117,6 +96,7 @@ FILES
 SEE ALSO
 --------
 linkgit:git-write-tree[1]
+linkgit:git-commit[1]
 
 GIT
 ---
index ced5a9beab159de86148b94bc1825247ead79390..13f653989f32f1231030d8e89a70cb6a96c9955f 100644 (file)
@@ -367,9 +367,6 @@ changes to tracked files.
 +
 For more details, see the 'pathspec' entry in linkgit:gitglossary[7].
 
-:git-commit: 1
-include::date-formats.txt[]
-
 EXAMPLES
 --------
 When recording your own work, the contents of modified files in
@@ -463,6 +460,43 @@ alter the order the changes are committed, because the merge
 should be recorded as a single commit.  In fact, the command
 refuses to run when given pathnames (but see `-i` option).
 
+COMMIT INFORMATION
+------------------
+
+Author and committer information is taken from the following environment
+variables, if set:
+
+       GIT_AUTHOR_NAME
+       GIT_AUTHOR_EMAIL
+       GIT_AUTHOR_DATE
+       GIT_COMMITTER_NAME
+       GIT_COMMITTER_EMAIL
+       GIT_COMMITTER_DATE
+
+(nb "<", ">" and "\n"s are stripped)
+
+The author and committer names are by convention some form of a personal name
+(that is, the name by which other humans refer to you), although Git does not
+enforce or require any particular form. Arbitrary Unicode may be used, subject
+to the constraints listed above. This name has no effect on authentication; for
+that, see the `credential.username` variable in linkgit:git-config[1].
+
+In case (some of) these environment variables are not set, the information
+is taken from the configuration items `user.name` and `user.email`, or, if not
+present, the environment variable EMAIL, or, if that is not set,
+system user name and the hostname used for outgoing mail (taken
+from `/etc/mailname` and falling back to the fully qualified hostname when
+that file does not exist).
+
+The `author.name` and `committer.name` and their corresponding email options
+override `user.name` and `user.email` if set and are overridden themselves by
+the environment variables.
+
+The typical usage is to set just the `user.name` and `user.email` variables;
+the other options are provided for more complex use cases.
+
+:git-commit: 1
+include::date-formats.txt[]
 
 DISCUSSION
 ----------
index a530fef7e5c08bf4bf01942ddbf1bcf10daa0b57..40ba4aa3e65b4c33886ba4334e5d3c84e979853e 100644 (file)
@@ -467,9 +467,9 @@ impossible for a backward-compatible implementation to ever be fast:
 
 * In editing files, git-filter-branch by design checks out each and
   every commit as it existed in the original repo.  If your repo has
-  10\^5 files and 10\^5 commits, but each commit only modifies 5
-  files, then git-filter-branch will make you do 10\^10 modifications,
-  despite only having (at most) 5*10^5 unique blobs.
+  `10^5` files and `10^5` commits, but each commit only modifies five
+  files, then git-filter-branch will make you do `10^10` modifications,
+  despite only having (at most) `5*10^5` unique blobs.
 
 * If you try and cheat and try to make git-filter-branch only work on
   files modified in a commit, then two things happen
index c89fb569e35855e79a43ee3cde784df5b7cb269c..ffc3a6efdc10f0bcf1a95a07f1dcf365ea41ddf7 100644 (file)
@@ -96,7 +96,8 @@ OPTIONS
        Recursively search in each submodule that has been initialized and
        checked out in the repository.  When used in combination with the
        <tree> option the prefix of all submodule output will be the name of
-       the parent project's <tree> object.
+       the parent project's <tree> object. This option has no effect
+       if `--no-index` is given.
 
 -a::
 --text::
index 5232407f68331618e5c509b91aef30ce6c6dbecd..218942acd11ffff39230a71617d119d323795299 100644 (file)
@@ -229,7 +229,7 @@ As an example, the command below will show the path and currently
 checked out commit for each submodule:
 +
 --------------
-git submodule foreach 'echo $path `git rev-parse HEAD`'
+git submodule foreach 'echo $sm_path `git rev-parse HEAD`'
 --------------
 
 sync [--recursive] [--] [<path>...]::
index c7a6271daf61507459fe3bb1a0bf494def4f994f..1489cb09a09997a64a102b58a8bf2b890640d6df 100644 (file)
@@ -549,6 +549,22 @@ The untracked cache extension can be enabled by the
 `core.untrackedCache` configuration variable (see
 linkgit:git-config[1]).
 
+NOTES
+-----
+
+Users often try to use the assume-unchanged and skip-worktree bits
+to tell Git to ignore changes to files that are tracked.  This does not
+work as expected, since Git may still check working tree files against
+the index when performing certain operations.  In general, Git does not
+provide a way to ignore changes to tracked files, so alternate solutions
+are recommended.
+
+For example, if the file you want to change is some sort of config file,
+the repository can include a sample config file that can then be copied
+into the ignored name and modified.  The repository can even include a
+script to treat the sample file as a template, modifying and copying it
+automatically.
+
 SEE ALSO
 --------
 linkgit:git-config[1],
index b1597ac002f15492b861b332519cf8b5ea2d9228..0093c647bf64bc5a42d32b948e2d342c0ce61a49 100644 (file)
@@ -482,13 +482,36 @@ double-quotes and respecting backslash escapes. E.g., the value
 Git Commits
 ~~~~~~~~~~~
 `GIT_AUTHOR_NAME`::
+       The human-readable name used in the author identity when creating commit or
+       tag objects, or when writing reflogs. Overrides the `user.name` and
+       `author.name` configuration settings.
+
 `GIT_AUTHOR_EMAIL`::
+       The email address used in the author identity when creating commit or
+       tag objects, or when writing reflogs. Overrides the `user.email` and
+       `author.email` configuration settings.
+
 `GIT_AUTHOR_DATE`::
+       The date used for the author identity when creating commit or tag objects, or
+       when writing reflogs. See linkgit:git-commit[1] for valid formats.
+
 `GIT_COMMITTER_NAME`::
+       The human-readable name used in the committer identity when creating commit or
+       tag objects, or when writing reflogs. Overrides the `user.name` and
+       `committer.name` configuration settings.
+
 `GIT_COMMITTER_EMAIL`::
+       The email address used in the author identity when creating commit or
+       tag objects, or when writing reflogs. Overrides the `user.email` and
+       `committer.email` configuration settings.
+
 `GIT_COMMITTER_DATE`::
-'EMAIL'::
-       see linkgit:git-commit-tree[1]
+       The date used for the committer identity when creating commit or tag objects, or
+       when writing reflogs. See linkgit:git-commit[1] for valid formats.
+
+`EMAIL`::
+       The email address used in the author and committer identities if no other
+       relevant environment variable or configuration setting has been set.
 
 Git Diffs
 ~~~~~~~~~
index f880d21dfb520c4a7bed90ccd0f2cc9d3961ecf7..c0b95256cc8c8d640d284f77b23d63c8785601d1 100644 (file)
@@ -751,7 +751,7 @@ to it.
 ================================================
 If you make the decision to start your new branch at some
 other point in the history than the current `HEAD`, you can do so by
-just telling 'git checkout' what the base of the checkout would be.
+just telling 'git switch' what the base of the checkout would be.
 In other words, if you have an earlier tag or branch, you'd just do
 
 ------------
diff --git a/Documentation/technical/bundle-format.txt b/Documentation/technical/bundle-format.txt
new file mode 100644 (file)
index 0000000..0e82815
--- /dev/null
@@ -0,0 +1,48 @@
+= Git bundle v2 format
+
+The Git bundle format is a format that represents both refs and Git objects.
+
+== Format
+
+We will use ABNF notation to define the Git bundle format. See
+protocol-common.txt for the details.
+
+----
+bundle    = signature *prerequisite *reference LF pack
+signature = "# v2 git bundle" LF
+
+prerequisite = "-" obj-id SP comment LF
+comment      = *CHAR
+reference    = obj-id SP refname LF
+
+pack         = ... ; packfile
+----
+
+== Semantics
+
+A Git bundle consists of three parts.
+
+* "Prerequisites" lists the objects that are NOT included in the bundle and the
+  reader of the bundle MUST already have, in order to use the data in the
+  bundle. The objects stored in the bundle may refer to prerequisite objects and
+  anything reachable from them (e.g. a tree object in the bundle can reference
+  a blob that is reachable from a prerequisite) and/or expressed as a delta
+  against prerequisite objects.
+
+* "References" record the tips of the history graph, iow, what the reader of the
+  bundle CAN "git fetch" from it.
+
+* "Pack" is the pack data stream "git fetch" would send, if you fetch from a
+  repository that has the references recorded in the "References" above into a
+  repository that has references pointing at the objects listed in
+  "Prerequisites" above.
+
+In the bundle format, there can be a comment following a prerequisite obj-id.
+This is a comment and it has no specific meaning. The writer of the bundle MAY
+put any string here. The reader of the bundle MUST ignore the comment.
+
+=== Note on the shallow clone and a Git bundle
+
+Note that the prerequisites does not represent a shallow-clone boundary. The
+semantics of the prerequisites and the shallow-clone boundaries are different,
+and the Git bundle v2 format cannot represent a shallow clone repository.
index cab5bdd2ff0f887cb991e2dc9ba3cccec34f8a0a..d3a142c6520258033f95b7e427be41f930883f99 100644 (file)
@@ -315,10 +315,11 @@ CHUNK DATA:
            Stores two 4-byte values for every object.
            1: The pack-int-id for the pack storing this object.
            2: The offset within the pack.
-               If all offsets are less than 2^31, then the large offset chunk
+               If all offsets are less than 2^32, then the large offset chunk
                will not exist and offsets are stored as in IDX v1.
                If there is at least one offset value larger than 2^32-1, then
-               the large offset chunk must exist. If the large offset chunk
+               the large offset chunk must exist, and offsets larger than
+               2^31-1 must be stored in it instead. If the large offset chunk
                exists and the 31st bit is on, then removing that bit reveals
                the row in the large offsets containing the 8-byte offset of
                this object.
index 2b7f62b8bfa042f10c5a0a76bdf33e002e7ff586..2a8e7099164496c92ac92af0ce5fb025c908b38e 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v2.25.0
+DEF_VER=v2.25.1
 
 LF='
 '
index 09f98b777cae1dc9226f13c182011adacfd8b2fc..9cd9826800bc9077b74a0bc5bf0097117212dd73 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1220,6 +1220,9 @@ endif
 ifneq ($(filter leak,$(SANITIZERS)),)
 BASIC_CFLAGS += -DSUPPRESS_ANNOTATED_LEAKS
 endif
+ifneq ($(filter address,$(SANITIZERS)),)
+NO_REGEX = NeededForASAN
+endif
 endif
 
 ifndef sysconfdir
index 091dd024b349d6bc908371eddb7c594059c4fd70..c63ee7dc7064c850ed6ba0ecf80f69511c901e48 120000 (symlink)
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/2.25.0.txt
\ No newline at end of file
+Documentation/RelNotes/2.25.1.txt
\ No newline at end of file
index 6a5048c83e4d6f08ae3ecfdb6beab125cde10a05..143e6947242115d75c2225c6771455111349cea7 100644 (file)
@@ -326,7 +326,10 @@ static ssize_t list_and_choose(struct add_i_state *s,
                                if (endp == p + sep)
                                        to = from + 1;
                                else if (*endp == '-') {
-                                       to = strtoul(++endp, &endp, 10);
+                                       if (isdigit(*(++endp)))
+                                               to = strtoul(endp, &endp, 10);
+                                       else
+                                               to = items->items.nr;
                                        /* extra characters after the range? */
                                        if (endp != p + sep)
                                                from = -1;
@@ -913,7 +916,7 @@ static int run_patch(struct add_i_state *s, const struct pathspec *ps,
 
        opts->prompt = N_("Patch update");
        count = list_and_choose(s, files, opts);
-       if (count >= 0) {
+       if (count > 0) {
                struct argv_array args = ARGV_ARRAY_INIT;
                struct pathspec ps_selected = { 0 };
 
@@ -954,7 +957,7 @@ static int run_diff(struct add_i_state *s, const struct pathspec *ps,
        opts->flags = IMMEDIATE;
        count = list_and_choose(s, files, opts);
        opts->flags = 0;
-       if (count >= 0) {
+       if (count > 0) {
                struct argv_array args = ARGV_ARRAY_INIT;
 
                argv_array_pushl(&args, "git", "diff", "-p", "--cached",
index b52c490c8f5404e24c05db289fc22539faf276e3..18ef5fb975eafa40de1de28a9eafeddfc46bd30a 100644 (file)
@@ -524,6 +524,8 @@ static int checkout_paths(const struct checkout_opts *opts,
        /* Now we are committed to check them out */
        if (opts->checkout_worktree)
                errs |= checkout_worktree(opts);
+       else
+               remove_marked_cache_entries(&the_index, 1);
 
        /*
         * Allow updating the index when checking out from the index.
index aa1332308a243802f2fb8bc98d276fd66510949b..646e84547d2e2e6419a9dbe2385feeffc25a1b24 100644 (file)
@@ -964,6 +964,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
         */
        if (!committable && whence != FROM_MERGE && !allow_empty &&
            !(amend && is_a_merge(current_head))) {
+               s->hints = advice_status_hints;
                s->display_comment_prefix = old_display_comment_prefix;
                run_status(stdout, index_file, prefix, 0, s);
                if (amend)
index 50ce8d946128c9f54d43d234a2117f3dba6d2299..ae2d5bbafcae263e91cd7f9ea7a97dc7a874d4aa 100644 (file)
@@ -958,6 +958,9 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
                        /* die the same way as if we did it at the beginning */
                        setup_git_directory();
        }
+       /* Ignore --recurse-submodules if --no-index is given or implied */
+       if (!use_index)
+               recurse_submodules = 0;
 
        /*
         * skip a -- separator; we know it cannot be
@@ -1115,8 +1118,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
                }
        }
 
-       if (recurse_submodules && (!use_index || untracked))
-               die(_("option not supported with --recurse-submodules"));
+       if (recurse_submodules && untracked)
+               die(_("--untracked not supported with --recurse-submodules"));
 
        if (!show_in_pager && !opt.status_only)
                setup_pager();
index b3e76ef8634820646f2e2fc4b4e9b5cc2d4b97ce..de41888430a260630650341371f9fa6216a4bcbe 100755 (executable)
@@ -7,6 +7,7 @@
 
 filter_log () {
        sed -e '/^GIT_VERSION = /d' \
+           -e "/constant Gem::ConfigMap is deprecated/d" \
            -e '/^    \* new asciidoc flags$/d' \
            -e '/stripped namespace before processing/d' \
            -e '/Attributed.*IDs for element/d' \
index 08a26096637712689a071bf58586939bb6ff7c75..2d3412860d4d3a10cb989a769260496326055924 100644 (file)
 extern "C" {
 #endif
 
+#define regcomp git_regcomp
+#define regexec git_regexec
+#define regerror git_regerror
+#define regfree git_regfree
+
 /* The following two types have to be signed and unsigned integer type
    wide enough to hold a value of a pointer.  For most ANSI compilers
    ptrdiff_t and size_t should be likely OK.  Still size of these two
index 797e0bd0b14cbd665a638cf0a22ca7f9f3df04d3..2b8549e5f1937632bcc9c61abc21892ddb70e49f 100644 (file)
--- a/convert.c
+++ b/convert.c
@@ -1940,7 +1940,7 @@ static struct stream_filter *ident_filter(const struct object_id *oid)
  * the contents cannot be filtered without reading the whole thing
  * in-core.
  *
- * Note that you would be crazy to set CRLF, smuge/clean or ident to a
+ * Note that you would be crazy to set CRLF, smudge/clean or ident to a
  * large binary blob you would want us not to slurp into the memory!
  */
 struct stream_filter *get_stream_filter(const struct index_state *istate,
diff --git a/dir.c b/dir.c
index 7d255227b130d7729747fe1a86c8efc04eee9f7e..b460211e6149707b813d9354154233272cdfd87d 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -41,7 +41,8 @@ struct cached_dir {
        int nr_files;
        int nr_dirs;
 
-       struct dirent *de;
+       const char *d_name;
+       int d_type;
        const char *file;
        struct untracked_cache_dir *ucd;
 };
@@ -50,8 +51,8 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir,
        struct index_state *istate, const char *path, int len,
        struct untracked_cache_dir *untracked,
        int check_only, int stop_at_first_file, const struct pathspec *pathspec);
-static int get_dtype(struct dirent *de, struct index_state *istate,
-                    const char *path, int len);
+static int resolve_dtype(int dtype, struct index_state *istate,
+                        const char *path, int len);
 
 int count_slashes(const char *s)
 {
@@ -1215,8 +1216,7 @@ static struct path_pattern *last_matching_pattern_from_list(const char *pathname
                int prefix = pattern->nowildcardlen;
 
                if (pattern->flags & PATTERN_FLAG_MUSTBEDIR) {
-                       if (*dtype == DT_UNKNOWN)
-                               *dtype = get_dtype(NULL, istate, pathname, pathlen);
+                       *dtype = resolve_dtype(*dtype, istate, pathname, pathlen);
                        if (*dtype != DT_DIR)
                                continue;
                }
@@ -1842,10 +1842,9 @@ static int get_index_dtype(struct index_state *istate,
        return DT_UNKNOWN;
 }
 
-static int get_dtype(struct dirent *de, struct index_state *istate,
-                    const char *path, int len)
+static int resolve_dtype(int dtype, struct index_state *istate,
+                        const char *path, int len)
 {
-       int dtype = de ? DTYPE(de) : DT_UNKNOWN;
        struct stat st;
 
        if (dtype != DT_UNKNOWN)
@@ -1870,14 +1869,13 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
                                          struct strbuf *path,
                                          int baselen,
                                          const struct pathspec *pathspec,
-                                         int dtype, struct dirent *de)
+                                         int dtype)
 {
        int exclude;
        int has_path_in_index = !!index_file_exists(istate, path->buf, path->len, ignore_case);
        enum path_treatment path_treatment;
 
-       if (dtype == DT_UNKNOWN)
-               dtype = get_dtype(de, istate, path->buf, path->len);
+       dtype = resolve_dtype(dtype, istate, path->buf, path->len);
 
        /* Always exclude indexed files */
        if (dtype != DT_DIR && has_path_in_index)
@@ -1985,21 +1983,18 @@ static enum path_treatment treat_path(struct dir_struct *dir,
                                      int baselen,
                                      const struct pathspec *pathspec)
 {
-       int dtype;
-       struct dirent *de = cdir->de;
-
-       if (!de)
+       if (!cdir->d_name)
                return treat_path_fast(dir, untracked, cdir, istate, path,
                                       baselen, pathspec);
-       if (is_dot_or_dotdot(de->d_name) || !fspathcmp(de->d_name, ".git"))
+       if (is_dot_or_dotdot(cdir->d_name) || !fspathcmp(cdir->d_name, ".git"))
                return path_none;
        strbuf_setlen(path, baselen);
-       strbuf_addstr(path, de->d_name);
+       strbuf_addstr(path, cdir->d_name);
        if (simplify_away(path->buf, path->len, pathspec))
                return path_none;
 
-       dtype = DTYPE(de);
-       return treat_one_path(dir, untracked, istate, path, baselen, pathspec, dtype, de);
+       return treat_one_path(dir, untracked, istate, path, baselen, pathspec,
+                             cdir->d_type);
 }
 
 static void add_untracked(struct untracked_cache_dir *dir, const char *name)
@@ -2087,10 +2082,17 @@ static int open_cached_dir(struct cached_dir *cdir,
 
 static int read_cached_dir(struct cached_dir *cdir)
 {
+       struct dirent *de;
+
        if (cdir->fdir) {
-               cdir->de = readdir(cdir->fdir);
-               if (!cdir->de)
+               de = readdir(cdir->fdir);
+               if (!de) {
+                       cdir->d_name = NULL;
+                       cdir->d_type = DT_UNKNOWN;
                        return -1;
+               }
+               cdir->d_name = de->d_name;
+               cdir->d_type = DTYPE(de);
                return 0;
        }
        while (cdir->nr_dirs < cdir->untracked->dirs_nr) {
@@ -2216,7 +2218,7 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir,
                /* recurse into subdir if instructed by treat_path */
                if ((state == path_recurse) ||
                        ((state == path_untracked) &&
-                        (get_dtype(cdir.de, istate, path.buf, path.len) == DT_DIR) &&
+                        (resolve_dtype(cdir.d_type, istate, path.buf, path.len) == DT_DIR) &&
                         ((dir->flags & DIR_SHOW_IGNORED_TOO) ||
                          (pathspec &&
                           do_match_pathspec(istate, pathspec, path.buf, path.len,
@@ -2308,16 +2310,16 @@ static int treat_leading_path(struct dir_struct *dir,
         * WARNING WARNING WARNING:
         *
         * Any updates to the traversal logic here may need corresponding
-        * updates in treat_leading_path().  See the commit message for the
-        * commit adding this warning as well as the commit preceding it
-        * for details.
+        * updates in read_directory_recursive().  See 777b420347 (dir:
+        * synchronize treat_leading_path() and read_directory_recursive(),
+        * 2019-12-19) and its parent commit for details.
         */
 
        struct strbuf sb = STRBUF_INIT;
+       struct strbuf subdir = STRBUF_INIT;
        int prevlen, baselen;
        const char *cp;
        struct cached_dir cdir;
-       struct dirent *de;
        enum path_treatment state = path_none;
 
        /*
@@ -2342,22 +2344,8 @@ static int treat_leading_path(struct dir_struct *dir,
        if (!len)
                return 1;
 
-       /*
-        * We need a manufactured dirent with sufficient space to store a
-        * leading directory component of path in its d_name.  Here, we
-        * assume that the dirent's d_name is either declared as
-        *    char d_name[BIG_ENOUGH]
-        * or that it is declared at the end of the struct as
-        *    char d_name[]
-        * For either case, padding with len+1 bytes at the end will ensure
-        * sufficient storage space.
-        */
-       de = xcalloc(1, st_add3(sizeof(struct dirent), len, 1));
        memset(&cdir, 0, sizeof(cdir));
-       cdir.de = de;
-#if defined(DT_UNKNOWN) && !defined(NO_D_TYPE_IN_DIRENT)
-       de->d_type = DT_DIR;
-#endif
+       cdir.d_type = DT_DIR;
        baselen = 0;
        prevlen = 0;
        while (1) {
@@ -2374,15 +2362,20 @@ static int treat_leading_path(struct dir_struct *dir,
                        break;
                strbuf_reset(&sb);
                strbuf_add(&sb, path, prevlen);
-               memcpy(de->d_name, path+prevlen, baselen-prevlen);
-               de->d_name[baselen-prevlen] = '\0';
+               strbuf_reset(&subdir);
+               strbuf_add(&subdir, path+prevlen, baselen-prevlen);
+               cdir.d_name = subdir.buf;
                state = treat_path(dir, NULL, &cdir, istate, &sb, prevlen,
                                    pathspec);
                if (state == path_untracked &&
-                   get_dtype(cdir.de, istate, sb.buf, sb.len) == DT_DIR &&
+                   resolve_dtype(cdir.d_type, istate, sb.buf, sb.len) == DT_DIR &&
                    (dir->flags & DIR_SHOW_IGNORED_TOO ||
                     do_match_pathspec(istate, pathspec, sb.buf, sb.len,
                                       baselen, NULL, DO_MATCH_LEADING_PATHSPEC) == MATCHED_RECURSIVELY_LEADING_PATHSPEC)) {
+                       if (!match_pathspec(istate, pathspec, sb.buf, sb.len,
+                                           0 /* prefix */, NULL,
+                                           0 /* do NOT special case dirs */))
+                               state = path_none;
                        add_path_to_appropriate_result_list(dir, NULL, &cdir,
                                                            istate,
                                                            &sb, baselen,
@@ -2399,7 +2392,7 @@ static int treat_leading_path(struct dir_struct *dir,
                                            &sb, baselen, pathspec,
                                            state);
 
-       free(de);
+       strbuf_release(&subdir);
        strbuf_release(&sb);
        return state == path_recurse;
 }
index 55ee63935073e2b2790d82e52399aaa1638f9e8f..61b8b13e3b21bbcafc1f88aa5f6cdb24fcb4d1dd 100644 (file)
@@ -292,8 +292,6 @@ struct object_info {
 #define OBJECT_INFO_LOOKUP_REPLACE 1
 /* Allow reading from a loose object file of unknown/bogus type */
 #define OBJECT_INFO_ALLOW_UNKNOWN_TYPE 2
-/* Do not check cached storage */
-#define OBJECT_INFO_SKIP_CACHED 4
 /* Do not retry packed storage after checking packed and loose storage */
 #define OBJECT_INFO_QUICK 8
 /* Do not check loose object */
index 60fae3ad213782dffa82e3c7dd246b47c566bf56..c278aff3a65a2d5e9e2be79596cdcd14d50e2a17 100644 (file)
@@ -420,7 +420,7 @@ static void check_typos(const char *arg, const struct option *options)
                return;
 
        if (starts_with(arg, "no-")) {
-               error(_("did you mean `--%s` (with two dashes ?)"), arg);
+               error(_("did you mean `--%s` (with two dashes)?"), arg);
                exit(129);
        }
 
@@ -428,7 +428,7 @@ static void check_typos(const char *arg, const struct option *options)
                if (!options->long_name)
                        continue;
                if (starts_with(options->long_name, arg)) {
-                       error(_("did you mean `--%s` (with two dashes ?)"), arg);
+                       error(_("did you mean `--%s` (with two dashes)?"), arg);
                        exit(129);
                }
        }
index 128f27fcb7ae8c88b0f7143943ea8a7171a83c5d..8243e06eab48373d12729959fde8fe666eb312b2 100644 (file)
@@ -438,8 +438,13 @@ static void init_pathspec_item(struct pathspec_item *item, unsigned flags,
        } else {
                match = prefix_path_gently(prefix, prefixlen,
                                           &prefixlen, copyfrom);
-               if (!match)
-                       die(_("%s: '%s' is outside repository"), elt, copyfrom);
+               if (!match) {
+                       const char *hint_path = get_git_work_tree();
+                       if (!hint_path)
+                               hint_path = get_git_dir();
+                       die(_("%s: '%s' is outside repository at '%s'"), elt,
+                           copyfrom, absolute_path(hint_path));
+               }
        }
 
        item->match = match;
index 9942f120a9b928831008a561ce6f09b60fa5b0e0..f5e1149f9b395e77c3d55a147332c1117746d7b1 100644 (file)
@@ -213,8 +213,9 @@ static char *locate_in_PATH(const char *file)
 static int exists_in_PATH(const char *file)
 {
        char *r = locate_in_PATH(file);
+       int found = r != NULL;
        free(r);
-       return r != NULL;
+       return found;
 }
 
 int sane_execvp(const char *file, char * const argv[])
diff --git a/setup.c b/setup.c
index e2a479a64fa4076bad8eaf6cf0949d0ae263da9d..f4897287f768b0ab9d247b757a04ec63e463b4e0 100644 (file)
--- a/setup.c
+++ b/setup.c
@@ -120,8 +120,13 @@ char *prefix_path_gently(const char *prefix, int len,
 char *prefix_path(const char *prefix, int len, const char *path)
 {
        char *r = prefix_path_gently(prefix, len, NULL, path);
-       if (!r)
-               die(_("'%s' is outside repository"), path);
+       if (!r) {
+               const char *hint_path = get_git_work_tree();
+               if (!hint_path)
+                       hint_path = get_git_dir();
+               die(_("'%s' is outside repository at '%s'"), path,
+                   absolute_path(hint_path));
+       }
        return r;
 }
 
index 188de57634bb1b0b15fbe3ab97f062bed7927763..03ae9ae93a53d911137a8f06aa687472c73806c9 100644 (file)
@@ -1417,6 +1417,7 @@ int oid_object_info_extended(struct repository *r, const struct object_id *oid,
                             struct object_info *oi, unsigned flags)
 {
        static struct object_info blank_oi = OBJECT_INFO_INIT;
+       struct cached_object *co;
        struct pack_entry e;
        int rtype;
        const struct object_id *real = oid;
@@ -1431,24 +1432,22 @@ int oid_object_info_extended(struct repository *r, const struct object_id *oid,
        if (!oi)
                oi = &blank_oi;
 
-       if (!(flags & OBJECT_INFO_SKIP_CACHED)) {
-               struct cached_object *co = find_cached_object(real);
-               if (co) {
-                       if (oi->typep)
-                               *(oi->typep) = co->type;
-                       if (oi->sizep)
-                               *(oi->sizep) = co->size;
-                       if (oi->disk_sizep)
-                               *(oi->disk_sizep) = 0;
-                       if (oi->delta_base_sha1)
-                               hashclr(oi->delta_base_sha1);
-                       if (oi->type_name)
-                               strbuf_addstr(oi->type_name, type_name(co->type));
-                       if (oi->contentp)
-                               *oi->contentp = xmemdupz(co->buf, co->size);
-                       oi->whence = OI_CACHED;
-                       return 0;
-               }
+       co = find_cached_object(real);
+       if (co) {
+               if (oi->typep)
+                       *(oi->typep) = co->type;
+               if (oi->sizep)
+                       *(oi->sizep) = co->size;
+               if (oi->disk_sizep)
+                       *(oi->disk_sizep) = 0;
+               if (oi->delta_base_sha1)
+                       hashclr(oi->delta_base_sha1);
+               if (oi->type_name)
+                       strbuf_addstr(oi->type_name, type_name(co->type));
+               if (oi->contentp)
+                       *oi->contentp = xmemdupz(co->buf, co->size);
+               oi->whence = OI_CACHED;
+               return 0;
        }
 
        while (1) {
@@ -1932,8 +1931,7 @@ int repo_has_object_file_with_flags(struct repository *r,
 {
        if (!startup_info->have_repository)
                return 0;
-       return oid_object_info_extended(r, oid, NULL,
-                                       flags | OBJECT_INFO_SKIP_CACHED) >= 0;
+       return oid_object_info_extended(r, oid, NULL, flags) >= 0;
 }
 
 int repo_has_object_file(struct repository *r,
index 7bb0ad07e61774b595b6b448a15a5d36a5cc8877..6c5d274126ac6c5e1b796f0a33fb33fba3ebda2a 100644 (file)
@@ -4,7 +4,8 @@
 /**
  * The string_list API offers a data structure and functions to handle
  * sorted and unsorted arrays of strings.  A "sorted" list is one whose
- * entries are sorted by string value in `strcmp()` order.
+ * entries are sorted by string value in the order specified by the `cmp`
+ * member (`strcmp()` by default).
  *
  * The caller:
  *
@@ -209,7 +210,8 @@ struct string_list_item *string_list_append(struct string_list *list, const char
 struct string_list_item *string_list_append_nodup(struct string_list *list, char *string);
 
 /**
- * Sort the list's entries by string value in `strcmp()` order.
+ * Sort the list's entries by string value in order specified by list->cmp
+ * (strcmp() if list->cmp is NULL).
  */
 void string_list_sort(struct string_list *list);
 
index 86e46d3dcee603524de01522be88a52cd0a3854d..9f4c4c08d1306550dcb5544e5541487371868e4e 100644 (file)
@@ -431,7 +431,7 @@ void handle_ignore_submodules_arg(struct diff_options *diffopt,
        else if (!strcmp(arg, "dirty"))
                diffopt->flags.ignore_dirty_submodules = 1;
        else if (strcmp(arg, "none"))
-               die("bad --ignore-submodules argument: %s", arg);
+               die(_("bad --ignore-submodules argument: %s"), arg);
        /*
         * Please update _git_status() in git-completion.bash when you
         * add new options
@@ -812,9 +812,9 @@ static void collect_changed_submodules_cb(struct diff_queue_struct *q,
                                submodule = submodule_from_name(me->repo,
                                                                commit_oid, name);
                        if (submodule) {
-                               warning("Submodule in commit %s at path: "
+                               warning(_("Submodule in commit %s at path: "
                                        "'%s' collides with a submodule named "
-                                       "the same. Skipping it.",
+                                       "the same. Skipping it."),
                                        oid_to_hex(commit_oid), p->two->path);
                                name = NULL;
                        }
@@ -844,7 +844,7 @@ static void collect_changed_submodules(struct repository *r,
        repo_init_revisions(r, &rev, NULL);
        setup_revisions(argv->argc, argv->argv, &rev, NULL);
        if (prepare_revision_walk(&rev))
-               die("revision walk setup failed");
+               die(_("revision walk setup failed"));
 
        while ((commit = get_revision(&rev))) {
                struct rev_info diff_rev;
@@ -992,7 +992,7 @@ static int submodule_needs_pushing(struct repository *r,
                cp.out = -1;
                cp.dir = path;
                if (start_command(&cp))
-                       die("Could not run 'git rev-list <commits> --not --remotes -n 1' command in submodule %s",
+                       die(_("Could not run 'git rev-list <commits> --not --remotes -n 1' command in submodule %s"),
                                        path);
                if (strbuf_read(&buf, cp.out, the_hash_algo->hexsz + 1))
                        needs_pushing = 1;
@@ -1115,7 +1115,7 @@ static void submodule_push_check(const char *path, const char *head,
         * child process.
         */
        if (run_command(&cp))
-               die("process for submodule '%s' failed", path);
+               die(_("process for submodule '%s' failed"), path);
 }
 
 int push_unpushed_submodules(struct repository *r,
@@ -1155,10 +1155,10 @@ int push_unpushed_submodules(struct repository *r,
        /* Actually push the submodules */
        for (i = 0; i < needs_pushing.nr; i++) {
                const char *path = needs_pushing.items[i].string;
-               fprintf(stderr, "Pushing submodule '%s'\n", path);
+               fprintf(stderr, _("Pushing submodule '%s'\n"), path);
                if (!push_submodule(path, remote, rs,
                                    push_options, dry_run)) {
-                       fprintf(stderr, "Unable to push submodule '%s'\n", path);
+                       fprintf(stderr, _("Unable to push submodule '%s'\n"), path);
                        ret = 0;
                }
        }
@@ -1448,7 +1448,7 @@ static int get_next_submodule(struct child_process *cp,
                        prepare_submodule_repo_env_in_gitdir(&cp->env_array);
                        cp->git_cmd = 1;
                        if (!spf->quiet)
-                               strbuf_addf(err, "Fetching submodule %s%s\n",
+                               strbuf_addf(err, _("Fetching submodule %s%s\n"),
                                            spf->prefix, ce->name);
                        argv_array_init(&cp->args);
                        argv_array_pushv(&cp->args, spf->args.argv);
@@ -1478,7 +1478,7 @@ static int get_next_submodule(struct child_process *cp,
                            !is_empty_dir(ce->name)) {
                                spf->result = 1;
                                strbuf_addf(err,
-                                           _("Could not access submodule '%s'"),
+                                           _("Could not access submodule '%s'\n"),
                                            ce->name);
                        }
                }
@@ -1610,7 +1610,7 @@ int fetch_populated_submodules(struct repository *r,
                goto out;
 
        if (repo_read_index(r) < 0)
-               die("index file corrupt");
+               die(_("index file corrupt"));
 
        argv_array_push(&spf.args, "fetch");
        for (i = 0; i < options->argc; i++)
@@ -1665,7 +1665,7 @@ unsigned is_submodule_modified(const char *path, int ignore_untracked)
        cp.out = -1;
        cp.dir = path;
        if (start_command(&cp))
-               die("Could not run 'git status --porcelain=2' in submodule %s", path);
+               die(_("Could not run 'git status --porcelain=2' in submodule %s"), path);
 
        fp = xfdopen(cp.out, "r");
        while (strbuf_getwholeline(&buf, fp, '\n') != EOF) {
@@ -1706,7 +1706,7 @@ unsigned is_submodule_modified(const char *path, int ignore_untracked)
        fclose(fp);
 
        if (finish_command(&cp) && !ignore_cp_exit_code)
-               die("'git status --porcelain=2' failed in submodule %s", path);
+               die(_("'git status --porcelain=2' failed in submodule %s"), path);
 
        strbuf_release(&buf);
        return dirty_submodule;
@@ -1811,7 +1811,7 @@ out:
 void submodule_unset_core_worktree(const struct submodule *sub)
 {
        char *config_path = xstrfmt("%s/modules/%s/config",
-                                   get_git_common_dir(), sub->name);
+                                   get_git_dir(), sub->name);
 
        if (git_config_set_in_file_gently(config_path, "core.worktree", NULL))
                warning(_("Could not unset core.worktree setting in submodule '%s'"),
@@ -1841,7 +1841,7 @@ static int submodule_has_dirty_index(const struct submodule *sub)
        cp.no_stdout = 1;
        cp.dir = sub->path;
        if (start_command(&cp))
-               die("could not recurse into submodule '%s'", sub->path);
+               die(_("could not recurse into submodule '%s'"), sub->path);
 
        return finish_command(&cp);
 }
@@ -1862,7 +1862,7 @@ static void submodule_reset_index(const char *path)
        argv_array_push(&cp.args, empty_tree_oid_hex());
 
        if (run_command(&cp))
-               die("could not reset submodule index");
+               die(_("could not reset submodule index"));
 }
 
 /**
@@ -1914,7 +1914,7 @@ int submodule_move_head(const char *path,
                                        ABSORB_GITDIR_RECURSE_SUBMODULES);
                } else {
                        char *gitdir = xstrfmt("%s/modules/%s",
-                                   get_git_common_dir(), sub->name);
+                                   get_git_dir(), sub->name);
                        connect_work_tree_and_git_dir(path, gitdir, 0);
                        free(gitdir);
 
@@ -1924,7 +1924,7 @@ int submodule_move_head(const char *path,
 
                if (old_head && (flags & SUBMODULE_MOVE_HEAD_FORCE)) {
                        char *gitdir = xstrfmt("%s/modules/%s",
-                                   get_git_common_dir(), sub->name);
+                                   get_git_dir(), sub->name);
                        connect_work_tree_and_git_dir(path, gitdir, 1);
                        free(gitdir);
                }
index 705a136ed92c99cda688f5e267204e59b0e532a9..9d7c7fdaa2af1d1f3b6119b4a88827fa5d4c06b6 100755 (executable)
@@ -242,7 +242,7 @@ test_expect_success 'Alias options do not contribute to abbreviation' '
 '
 
 cat >typo.err <<\EOF
-error: did you mean `--boolean` (with two dashes ?)
+error: did you mean `--boolean` (with two dashes)?
 EOF
 
 test_expect_success 'detect possible typos' '
@@ -252,7 +252,7 @@ test_expect_success 'detect possible typos' '
 '
 
 cat >typo.err <<\EOF
-error: did you mean `--ambiguous` (with two dashes ?)
+error: did you mean `--ambiguous` (with two dashes)?
 EOF
 
 test_expect_success 'detect possible typos' '
index 21c3f84459dfe29053bbb0d9a43160a6df33f737..076d0df7fc0602e8d47c03ffa6ddb6dff0b985a9 100755 (executable)
@@ -106,4 +106,21 @@ test_expect_success 'restore --staged adds deleted intent-to-add file back to in
        git diff --cached --exit-code
 '
 
+test_expect_success 'restore --staged invalidates cache tree for deletions' '
+       test_when_finished git reset --hard &&
+       >new1 &&
+       >new2 &&
+       git add new1 new2 &&
+
+       # It is important to commit and then reset here, so that the index
+       # contains a valid cache-tree for the "both" tree.
+       git commit -m both &&
+       git reset --soft HEAD^ &&
+
+       git restore --staged new1 &&
+       git commit -m "just new2" &&
+       git rev-parse HEAD:new2 &&
+       test_must_fail git rev-parse HEAD:new1
+'
+
 test_done
diff --git a/t/t2405-worktree-submodule.sh b/t/t2405-worktree-submodule.sh
new file mode 100755 (executable)
index 0000000..e1b2bfd
--- /dev/null
@@ -0,0 +1,90 @@
+#!/bin/sh
+
+test_description='Combination of submodules and multiple worktrees'
+
+. ./test-lib.sh
+
+base_path=$(pwd -P)
+
+test_expect_success 'setup: create origin repos'  '
+       git init origin/sub &&
+       test_commit -C origin/sub file1 &&
+       git init origin/main &&
+       test_commit -C origin/main first &&
+       git -C origin/main submodule add ../sub &&
+       git -C origin/main commit -m "add sub" &&
+       test_commit -C origin/sub "file1 updated" file1 file1updated file1updated &&
+       git -C origin/main/sub pull &&
+       git -C origin/main add sub &&
+       git -C origin/main commit -m "sub updated"
+'
+
+test_expect_success 'setup: clone superproject to create main worktree' '
+       git clone --recursive "$base_path/origin/main" main
+'
+
+rev1_hash_main=$(git --git-dir=origin/main/.git show --pretty=format:%h -q "HEAD~1")
+rev1_hash_sub=$(git --git-dir=origin/sub/.git show --pretty=format:%h -q "HEAD~1")
+
+test_expect_success 'add superproject worktree' '
+       git -C main worktree add "$base_path/worktree" "$rev1_hash_main"
+'
+
+test_expect_failure 'submodule is checked out just after worktree add' '
+       git -C worktree diff --submodule master"^!" >out &&
+       grep "file1 updated" out
+'
+
+test_expect_success 'add superproject worktree and initialize submodules' '
+       git -C main worktree add "$base_path/worktree-submodule-update" "$rev1_hash_main" &&
+       git -C worktree-submodule-update submodule update
+'
+
+test_expect_success 'submodule is checked out just after submodule update in linked worktree' '
+       git -C worktree-submodule-update diff --submodule master"^!" >out &&
+       grep "file1 updated" out
+'
+
+test_expect_success 'add superproject worktree and manually add submodule worktree' '
+       git -C main worktree add "$base_path/linked_submodule" "$rev1_hash_main" &&
+       git -C main/sub worktree add "$base_path/linked_submodule/sub" "$rev1_hash_sub"
+'
+
+test_expect_success 'submodule is checked out after manually adding submodule worktree' '
+       git -C linked_submodule diff --submodule master"^!" >out &&
+       grep "file1 updated" out
+'
+
+test_expect_success 'checkout --recurse-submodules uses $GIT_DIR for submodules in a linked worktree' '
+       git -C main worktree add "$base_path/checkout-recurse" --detach  &&
+       git -C checkout-recurse submodule update --init &&
+       echo "gitdir: ../../main/.git/worktrees/checkout-recurse/modules/sub" >expect-gitfile &&
+       cat checkout-recurse/sub/.git >actual-gitfile &&
+       test_cmp expect-gitfile actual-gitfile &&
+       git -C main/sub rev-parse HEAD >expect-head-main &&
+       git -C checkout-recurse checkout --recurse-submodules HEAD~1 &&
+       cat checkout-recurse/sub/.git >actual-gitfile &&
+       git -C main/sub rev-parse HEAD >actual-head-main &&
+       test_cmp expect-gitfile actual-gitfile &&
+       test_cmp expect-head-main actual-head-main
+'
+
+test_expect_success 'core.worktree is removed in $GIT_DIR/modules/<name>/config, not in $GIT_COMMON_DIR/modules/<name>/config' '
+       echo "../../../sub" >expect-main &&
+       git -C main/sub config --get core.worktree >actual-main &&
+       test_cmp expect-main actual-main &&
+       echo "../../../../../../checkout-recurse/sub" >expect-linked &&
+       git -C checkout-recurse/sub config --get core.worktree >actual-linked &&
+       test_cmp expect-linked actual-linked &&
+       git -C checkout-recurse checkout --recurse-submodules first &&
+       test_expect_code 1 git -C main/.git/worktrees/checkout-recurse/modules/sub config --get core.worktree >linked-config &&
+       test_must_be_empty linked-config &&
+       git -C main/sub config --get core.worktree >actual-main &&
+       test_cmp expect-main actual-main
+'
+
+test_expect_success 'unsetting core.worktree does not prevent running commands directly against the submodule repository' '
+       git -C main/.git/worktrees/checkout-recurse/modules/sub log
+'
+
+test_done
index 12ee321707a33bd8455fb30ea24c57d002c13b68..2182b1c030b81ea45e439510a452d3e74250cae0 100755 (executable)
@@ -68,6 +68,15 @@ test_expect_success 'revert works (initial)' '
        ! grep . output
 '
 
+test_expect_success 'add untracked (multiple)' '
+       test_when_finished "git reset && rm [1-9]" &&
+       touch $(test_seq 9) &&
+       test_write_lines a "2-5 8-" | git add -i -- [1-9] &&
+       test_write_lines 2 3 4 5 8 9 >expected &&
+       git ls-files [1-9] >output &&
+       test_cmp expected output
+'
+
 test_expect_success 'setup (commit)' '
        echo baseline >file &&
        git add file &&
index c0f48395432539f807dd9474d71529378f71306b..02255a08bf1718659f9815e37644c07a196ab850 100755 (executable)
@@ -106,7 +106,6 @@ do
                result=success
        fi
        test_expect_$result "hunk header: $i" "
-               test_when_finished 'cat actual' &&      # for debugging only
                git diff -U1 $i >actual &&
                grep '@@ .* @@.*RIGHT' actual
        "
index 4b602826895e21154376391333c6517b4ec1ec54..5f8f1c287f417cb9a30d7e4db71bfb5ba4ef91ce 100755 (executable)
@@ -174,6 +174,30 @@ test_expect_success 'fetch --prune --tags with refspec prunes based on refspec'
        git rev-parse sometag
 '
 
+test_expect_success '--refmap="" ignores configured refspec' '
+       cd "$TRASH_DIRECTORY" &&
+       git clone "$D" remote-refs &&
+       git -C remote-refs rev-parse remotes/origin/master >old &&
+       git -C remote-refs update-ref refs/remotes/origin/master master~1 &&
+       git -C remote-refs rev-parse remotes/origin/master >new &&
+       git -C remote-refs fetch --refmap= origin "+refs/heads/*:refs/hidden/origin/*" &&
+       git -C remote-refs rev-parse remotes/origin/master >actual &&
+       test_cmp new actual &&
+       git -C remote-refs fetch origin &&
+       git -C remote-refs rev-parse remotes/origin/master >actual &&
+       test_cmp old actual
+'
+
+test_expect_success '--refmap="" and --prune' '
+       git -C remote-refs update-ref refs/remotes/origin/foo/otherbranch master &&
+       git -C remote-refs update-ref refs/hidden/foo/otherbranch master &&
+       git -C remote-refs fetch --prune --refmap="" origin +refs/heads/*:refs/hidden/* &&
+       git -C remote-refs rev-parse remotes/origin/foo/otherbranch &&
+       test_must_fail git -C remote-refs rev-parse refs/hidden/foo/otherbranch &&
+       git -C remote-refs fetch --prune origin &&
+       test_must_fail git -C remote-refs rev-parse remotes/origin/foo/otherbranch
+'
+
 test_expect_success 'fetch tags when there is no tags' '
 
     cd "$D" &&
index fea56cda6d3a256161a21cb7e79e6e96f328bf17..9a9178fd2810025322d1ad3048a09a661eaac110 100755 (executable)
@@ -309,26 +309,36 @@ setup_triangle () {
 
        printf "line %d\n" $(test_seq 1 100) >big-blob.txt &&
 
-       # Create a server with 2 commits: a commit with a big blob and a child
+       # Create a server with 2 commits: a commit with a big tree and a child
        # commit with an incremental change. Also, create a partial clone
        # client that only contains the first commit.
        git init server &&
        git -C server config --local uploadpack.allowfilter 1 &&
-       cp big-blob.txt server &&
-       git -C server add big-blob.txt &&
+       for i in $(test_seq 1 100)
+       do
+               echo "make the tree big" >server/file$i &&
+               git -C server add file$i
+       done &&
        git -C server commit -m "initial" &&
        git clone --bare --filter=tree:0 "file://$(pwd)/server" client &&
-       echo another line >>server/big-blob.txt &&
-       git -C server commit -am "append line to big blob" &&
+       echo another line >>server/file1 &&
+       git -C server commit -am "incremental change" &&
 
-       # Create a promisor remote that only contains the blob from the first
-       # commit, and set it as the promisor remote of client. Thus, whenever
-       # the client lazy fetches, the lazy fetch will succeed only if it is
-       # for this blob.
+       # Create a promisor remote that only contains the tree and blob from
+       # the first commit.
        git init promisor-remote &&
+       git -C server config --local uploadpack.allowanysha1inwant 1 &&
+       TREE_HASH=$(git -C server rev-parse HEAD~1^{tree}) &&
+       git -C promisor-remote fetch --keep "file://$(pwd)/server" "$TREE_HASH" &&
+       git -C promisor-remote count-objects -v >object-count &&
+       test_i18ngrep "count: 0" object-count &&
+       test_i18ngrep "in-pack: 2" object-count &&
+
+       # Set it as the promisor remote of client. Thus, whenever
+       # the client lazy fetches, the lazy fetch will succeed only if it is
+       # for this tree or blob.
        test_commit -C promisor-remote one && # so that ref advertisement is not empty
        git -C promisor-remote config --local uploadpack.allowanysha1inwant 1 &&
-       git -C promisor-remote hash-object -w --stdin <big-blob.txt &&
        git -C client remote set-url origin "file://$(pwd)/promisor-remote"
 }
 
@@ -341,14 +351,14 @@ test_expect_success 'fetch lazy-fetches only to resolve deltas' '
        setup_triangle &&
 
        # Exercise to make sure it works. Git will not fetch anything from the
-       # promisor remote other than for the big blob (because it needs to
+       # promisor remote other than for the big tree (because it needs to
        # resolve the delta).
        GIT_TRACE_PACKET="$(pwd)/trace" git -C client \
                fetch "file://$(pwd)/server" master &&
 
        # Verify the assumption that the client needed to fetch the delta base
        # to resolve the delta.
-       git hash-object big-blob.txt >hash &&
+       git -C server rev-parse HEAD~1^{tree} >hash &&
        grep "want $(cat hash)" trace
 '
 
@@ -370,7 +380,7 @@ test_expect_success 'fetch lazy-fetches only to resolve deltas, protocol v2' '
 
        # Verify the assumption that the client needed to fetch the delta base
        # to resolve the delta.
-       git hash-object big-blob.txt >hash &&
+       git -C server rev-parse HEAD~1^{tree} >hash &&
        grep "want $(cat hash)" trace
 '
 
index e73067d23fe747210f0ea767a7e8952b81ed3d30..7fd7102c8741f3a6c426d3f84b6556b9bbe9a861 100755 (executable)
@@ -665,6 +665,18 @@ test_expect_success 'fetch from namespaced repo respects namespaces' '
        test_cmp expect actual
 '
 
+test_expect_success 'ls-remote with v2 http sends only one POST' '
+       test_when_finished "rm -f log" &&
+
+       git ls-remote "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" >expect &&
+       GIT_TRACE_CURL="$(pwd)/log" git -c protocol.version=2 \
+               ls-remote "$HTTPD_URL/smart/http_parent" >actual &&
+       test_cmp expect actual &&
+
+       grep "Send header: POST" log >posts &&
+       test_line_count = 1 posts
+'
+
 test_expect_success 'push with http:// and a config of v2 does not request v2' '
        test_when_finished "rm -f log" &&
        # Till v2 for push is designed, make sure that if a client has
diff --git a/t/t6136-pathspec-in-bare.sh b/t/t6136-pathspec-in-bare.sh
new file mode 100755 (executable)
index 0000000..b117251
--- /dev/null
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+test_description='diagnosing out-of-scope pathspec'
+
+. ./test-lib.sh
+
+test_expect_success 'setup a bare and non-bare repository' '
+       test_commit file1 &&
+       git clone --bare . bare
+'
+
+test_expect_success 'log and ls-files in a bare repository' '
+       (
+               cd bare &&
+               test_must_fail git log -- .. >out 2>err &&
+               test_must_be_empty out &&
+               test_i18ngrep "outside repository" err &&
+
+               test_must_fail git ls-files -- .. >out 2>err &&
+               test_must_be_empty out &&
+               test_i18ngrep "outside repository" err
+       )
+'
+
+test_expect_success 'log and ls-files in .git directory' '
+       (
+               cd .git &&
+               test_must_fail git log -- .. >out 2>err &&
+               test_must_be_empty out &&
+               test_i18ngrep "outside repository" err &&
+
+               test_must_fail git ls-files -- .. >out 2>err &&
+               test_must_be_empty out &&
+               test_i18ngrep "outside repository" err
+       )
+'
+
+test_done
index 6e6d24c1c3a5c5397241e266c09fe214ec14d53f..cb5e34d94c3a163ecc3785d4b3afdeeb98c60ec6 100755 (executable)
@@ -737,4 +737,13 @@ test_expect_success MINGW 'handle clean & core.longpaths = false nicely' '
        test_i18ngrep "too long" .git/err
 '
 
+test_expect_success 'clean untracked paths by pathspec' '
+       git init untracked &&
+       mkdir untracked/dir &&
+       echo >untracked/dir/file.txt &&
+       git -C untracked clean -f dir/file.txt &&
+       ls untracked/dir >actual &&
+       test_must_be_empty actual
+'
+
 test_done
diff --git a/t/t7410-submodule-checkout-to.sh b/t/t7410-submodule-checkout-to.sh
deleted file mode 100755 (executable)
index f1b492e..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-#!/bin/sh
-
-test_description='Combination of submodules and multiple workdirs'
-
-. ./test-lib.sh
-
-base_path=$(pwd -P)
-
-test_expect_success 'setup: make origin'  '
-       mkdir -p origin/sub &&
-       (
-               cd origin/sub && git init &&
-               echo file1 >file1 &&
-               git add file1 &&
-               git commit -m file1
-       ) &&
-       mkdir -p origin/main &&
-       (
-               cd origin/main && git init &&
-               git submodule add ../sub &&
-               git commit -m "add sub"
-       ) &&
-       (
-               cd origin/sub &&
-               echo file1updated >file1 &&
-               git add file1 &&
-               git commit -m "file1 updated"
-       ) &&
-       git -C origin/main/sub pull &&
-       (
-               cd origin/main &&
-               git add sub &&
-               git commit -m "sub updated"
-       )
-'
-
-test_expect_success 'setup: clone' '
-       mkdir clone &&
-       git -C clone clone --recursive "$base_path/origin/main"
-'
-
-rev1_hash_main=$(git --git-dir=origin/main/.git show --pretty=format:%h -q "HEAD~1")
-rev1_hash_sub=$(git --git-dir=origin/sub/.git show --pretty=format:%h -q "HEAD~1")
-
-test_expect_success 'checkout main' '
-       mkdir default_checkout &&
-       git -C clone/main worktree add "$base_path/default_checkout/main" "$rev1_hash_main"
-'
-
-test_expect_failure 'can see submodule diffs just after checkout' '
-       git -C default_checkout/main diff --submodule master"^!" >out &&
-       grep "file1 updated" out
-'
-
-test_expect_success 'checkout main and initialize independent clones' '
-       mkdir fully_cloned_submodule &&
-       git -C clone/main worktree add "$base_path/fully_cloned_submodule/main" "$rev1_hash_main" &&
-       git -C fully_cloned_submodule/main submodule update
-'
-
-test_expect_success 'can see submodule diffs after independent cloning' '
-       git -C fully_cloned_submodule/main diff --submodule master"^!" >out &&
-       grep "file1 updated" out
-'
-
-test_expect_success 'checkout sub manually' '
-       mkdir linked_submodule &&
-       git -C clone/main worktree add "$base_path/linked_submodule/main" "$rev1_hash_main" &&
-       git -C clone/main/sub worktree add "$base_path/linked_submodule/main/sub" "$rev1_hash_sub"
-'
-
-test_expect_success 'can see submodule diffs after manual checkout of linked submodule' '
-       git -C linked_submodule/main diff --submodule master"^!" >out &&
-       grep "file1 updated" out
-'
-
-test_done
index 46a5cd4b7395ce8bba29763644a6fbd6739c929e..6d19ece05dd320b970492daf015b874eee0d391f 100755 (executable)
@@ -382,4 +382,13 @@ test_expect_success 'check commit with unstaged rename and copy' '
        )
 '
 
+test_expect_success 'commit without staging files fails and displays hints' '
+       echo "initial" >file &&
+       git add file &&
+       git commit -m initial &&
+       echo "changes" >>file &&
+       test_must_fail git commit -m update >actual &&
+       test_i18ngrep "no changes added to commit (use \"git add\" and/or \"git commit -a\")" actual
+'
+
 test_done
index 6bac9ed180e7342b34401b2d6af9e83b4472f08d..29b92907e2ad850514fe970ca1adeeda8d0697c8 100755 (executable)
@@ -125,15 +125,14 @@ test_expect_success 'difftool stops on error with --trust-exit-code' '
        test_when_finished "rm -f for-diff .git/fail-right-file" &&
        test_when_finished "git reset -- for-diff" &&
        write_script .git/fail-right-file <<-\EOF &&
-       echo "$2"
+       echo failed
        exit 1
        EOF
        >for-diff &&
        git add for-diff &&
-       echo file >expect &&
        test_must_fail git difftool -y --trust-exit-code \
                --extcmd .git/fail-right-file branch >actual &&
-       test_cmp expect actual
+       test_line_count = 1 actual
 '
 
 test_expect_success 'difftool honors exit status if command not found' '
index 946f91fa5782f2810b1286427359c06b64273b3a..828cb3ba5818fd47b6466fd52235e1d5a54cb333 100755 (executable)
@@ -345,7 +345,16 @@ test_incompatible_with_recurse_submodules ()
 }
 
 test_incompatible_with_recurse_submodules --untracked
-test_incompatible_with_recurse_submodules --no-index
+
+test_expect_success 'grep --recurse-submodules --no-index ignores --recurse-submodules' '
+       git grep --recurse-submodules --no-index -e "^(.|.)[\d]" >actual &&
+       cat >expect <<-\EOF &&
+       a:(1|2)d(3|4)
+       submodule/a:(1|2)d(3|4)
+       submodule/sub/a:(1|2)d(3|4)
+       EOF
+       test_cmp expect actual
+'
 
 test_expect_success 'grep --recurse-submodules should pass the pattern type along' '
        # Fixed
index 83379a037d69c2f6d97004d41b96f82f10d209dc..1fdc7dac1a6230bdf3492cbebd6642fc825dac5f 100644 (file)
@@ -737,7 +737,7 @@ static int disconnect_git(struct transport *transport)
 {
        struct git_transport_data *data = transport->data;
        if (data->conn) {
-               if (data->got_remote_heads)
+               if (data->got_remote_heads && !transport->stateless_rpc)
                        packet_flush(data->fd[1]);
                close(data->fd[0]);
                close(data->fd[1]);
index 2399b6818be6ddb9a6f4103cec667b2e2a9c24d0..191e738143171a08b11cfd87aac0de0246ab4d4d 100644 (file)
@@ -694,9 +694,11 @@ static int index_pos_by_traverse_info(struct name_entry *names,
        if (pos >= 0)
                BUG("This is a directory and should not exist in index");
        pos = -pos - 1;
-       if (!starts_with(o->src_index->cache[pos]->name, name.buf) ||
+       if (pos >= o->src_index->cache_nr ||
+           !starts_with(o->src_index->cache[pos]->name, name.buf) ||
            (pos > 0 && starts_with(o->src_index->cache[pos-1]->name, name.buf)))
-               BUG("pos must point at the first entry in this directory");
+               BUG("pos %d doesn't point to the first entry of %s in index",
+                   pos, name.buf);
        strbuf_release(&name);
        return pos;
 }
@@ -1305,14 +1307,14 @@ static int clear_ce_flags_dir(struct index_state *istate,
 
        if (pl->use_cone_patterns && orig_ret == MATCHED_RECURSIVE) {
                struct cache_entry **ce = cache;
-               rc = (cache_end - cache) / sizeof(struct cache_entry *);
+               rc = cache_end - cache;
 
                while (ce < cache_end) {
                        (*ce)->ce_flags &= ~clear_mask;
                        ce++;
                }
        } else if (pl->use_cone_patterns && orig_ret == NOT_MATCHED) {
-               rc = (cache_end - cache) / sizeof(struct cache_entry *);
+               rc = cache_end - cache;
        } else {
                rc = clear_ce_flags_1(istate, cache, cache_end - cache,
                                      prefix,