]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Merge branch 'zh/arg-help-format' into maint
authorJunio C Hamano <gitster@pobox.com>
Mon, 8 Feb 2021 22:05:54 +0000 (14:05 -0800)
committerJunio C Hamano <gitster@pobox.com>
Mon, 8 Feb 2021 22:05:54 +0000 (14:05 -0800)
Clean up option descriptions in "git cmd --help".

* zh/arg-help-format:
  builtin/*: update usage format
  parse-options: format argh like error messages

46 files changed:
Documentation/RelNotes/2.30.1.txt [new file with mode: 0644]
Documentation/SubmittingPatches
Documentation/config/http.txt
Documentation/config/trace2.txt
Documentation/git-clone.txt
Documentation/git-fsck.txt
Documentation/git-ls-files.txt
Documentation/git-maintenance.txt
Documentation/git-p4.txt
Documentation/git-send-email.txt
Documentation/git-status.txt
Documentation/git-update-index.txt
Documentation/githooks.txt
Documentation/gitmodules.txt
Documentation/technical/pack-format.txt
Documentation/technical/packfile-uri.txt
Documentation/technical/reftable.txt
GIT-VERSION-GEN
Makefile
RelNotes
builtin/for-each-repo.c
builtin/rebase.c
builtin/stash.c
ci/install-dependencies.sh
connect.c
fsck.c
gettext.c
git-mergetool--lib.sh
patch-ids.c
patch-ids.h
revision.c
submodule.c
t/lib-submodule-update.sh
t/perf/p7519-fsmonitor.sh
t/t0068-for-each-repo.sh
t/t1300-config.sh
t/t4129-apply-samemode.sh
t/t5516-fetch-push.sh
t/t5526-fetch-submodules.sh
t/t5570-git-daemon.sh
t/t6007-rev-list-cherry-pick-file.sh
t/t6030-bisect-porcelain.sh
t/t7012-skip-worktree-writing.sh
t/t7416-submodule-dash-url.sh
t/t7610-mergetool.sh
t/test-lib-functions.sh

diff --git a/Documentation/RelNotes/2.30.1.txt b/Documentation/RelNotes/2.30.1.txt
new file mode 100644 (file)
index 0000000..3760bd1
--- /dev/null
@@ -0,0 +1,47 @@
+Git v2.30.1 Release Notes
+=========================
+
+This release is primarily to merge fixes accumulated on the 'master'
+front to prepare for 2.31 release that are still relevant to 2.30.x
+maintenance track.
+
+Fixes since v2.30
+-----------------
+
+ * "git fetch --recurse-submodules" failed to update a submodule
+   when it has an uninitialized (hence of no interest to the user)
+   sub-submodule, which has been corrected.
+
+ * Command line error of "git rebase" are diagnosed earlier.
+
+ * "git stash" did not work well in a sparsely checked out working
+   tree.
+
+ * Some tests expect that "ls -l" output has either '-' or 'x' for
+   group executable bit, but setgid bit can be inherited from parent
+   directory and make these fields 'S' or 's' instead, causing test
+   failures.
+
+ * "git for-each-repo --config=<var> <cmd>" should not run <cmd> for
+   any repository when the configuration variable <var> is not defined
+   even once.
+
+ * "git mergetool --tool-help" was broken in 2.29 and failed to list
+   all the available tools.
+
+ * Fix for procedure to building CI test environment for mac.
+
+ * Newline characters in the host and path part of git:// URL are
+   now forbidden.
+
+ * When more than one commit with the same patch ID appears on one
+   side, "git log --cherry-pick A...B" did not exclude them all when a
+   commit with the same patch ID appears on the other side.  Now it
+   does.
+
+ * Documentation for "git fsck" lost stale bits that has become
+   incorrect.
+
+ * Doc for packfile URI feature has been clarified.
+
+Also contains minor documentation updates and code clean-ups.
index d12094bac5f46a3d8df1aee0b380e563a51dad47..0452db2e67d1959ce08683e5fa5416f5bdaa5cb4 100644 (file)
@@ -307,7 +307,7 @@ wrote the patch or have the right to pass it on under the same license
 as ours, by "signing off" your patch.  Without sign-off, we cannot
 accept your patches.
 
-If you can certify the below D-C-O:
+If (and only if) you certify the below D-C-O:
 
 [[dco]]
 .Developer's Certificate of Origin 1.1
index 3968fbb697aea209affaf7f22594c598bb698ae1..7003661c0dba393778c0df03d2f26e121392c545 100644 (file)
@@ -42,12 +42,12 @@ http.proxySSLKey::
 http.proxySSLCertPasswordProtected::
        Enable Git's password prompt for the proxy SSL certificate.  Otherwise OpenSSL
        will prompt the user, possibly many times, if the certificate or private key
-       is encrypted. Can be overriden by the `GIT_PROXY_SSL_CERT_PASSWORD_PROTECTED`
+       is encrypted. Can be overridden by the `GIT_PROXY_SSL_CERT_PASSWORD_PROTECTED`
        environment variable.
 
 http.proxySSLCAInfo::
        Pathname to the file containing the certificate bundle that should be used to
-       verify the proxy with when using an HTTPS proxy. Can be overriden by the
+       verify the proxy with when using an HTTPS proxy. Can be overridden by the
        `GIT_PROXY_SSL_CAINFO` environment variable.
 
 http.emptyAuth::
index 01d3afd8a8b38d3e6a722018be2fc4544907bf16..fe1642f0d40251d466c78639fff44475edb6b25b 100644 (file)
@@ -54,7 +54,7 @@ trace2.envVars::
        `GIT_HTTP_USER_AGENT,GIT_CONFIG` would cause the trace2 output to
        contain events listing the overrides for HTTP user agent and the
        location of the Git configuration file (assuming any are set).  May be
-       overriden by the `GIT_TRACE2_ENV_VARS` environment variable.  Unset by
+       overridden by the `GIT_TRACE2_ENV_VARS` environment variable.  Unset by
        default.
 
 trace2.destinationDebug::
index 876aedcd472a4b04ee28f3cc524195a701222db5..02d9c19cec7531db4ac9b592030a602d752bedcd 100644 (file)
@@ -57,6 +57,10 @@ repository is specified as a URL, then this flag is ignored (and we
 never use the local optimizations).  Specifying `--no-local` will
 override the default when `/path/to/repo` is given, using the regular
 Git transport instead.
++
+*NOTE*: this operation can race with concurrent modification to the
+source repository, similar to running `cp -r src dst` while modifying
+`src`.
 
 --no-hardlinks::
        Force the cloning process from a repository on a local
index d72d15be5babb2a108cf37e8ae396ae587baf1cf..bd596619c0d3d8a841bc3e033e9a3ff14c11a514 100644 (file)
@@ -129,14 +129,6 @@ using 'git commit-graph verify'. See linkgit:git-commit-graph[1].
 Extracted Diagnostics
 ---------------------
 
-expect dangling commits - potential heads - due to lack of head information::
-       You haven't specified any nodes as heads so it won't be
-       possible to differentiate between un-parented commits and
-       root nodes.
-
-missing sha1 directory '<dir>'::
-       The directory holding the sha1 objects is missing.
-
 unreachable <type> <object>::
        The <type> object <object>, isn't actually referred to directly
        or indirectly in any of the trees or commits seen. This can
index cbcf5263dd01b88537563a97bd1977bf52c3b88c..0a3b5265b3457988bfad25b6b89c7622dd726760 100644 (file)
@@ -23,9 +23,8 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
-This merges the file listing in the directory cache index with the
-actual working directory list, and shows different combinations of the
-two.
+This merges the file listing in the index with the actual working
+directory list, and shows different combinations of the two.
 
 One or more of the options below may be used to determine the files
 shown:
index d1f9b5172dffb5fd72643ea2aa429c28dc0c4354..6fe1e5e10554989941827a1a92be1f9128df1404 100644 (file)
@@ -38,7 +38,7 @@ register::
        for running in the background without disrupting foreground
        processes.
 +
-The `register` subcomand will also set the `maintenance.strategy` config
+The `register` subcommand will also set the `maintenance.strategy` config
 value to `incremental`, if this value is not previously set. The
 `incremental` strategy uses the following schedule for each maintenance
 task:
index ec233ac0c1c1568a5516aa3bfe6a9c1fc4dcc0e4..f89e68b424c3b229d77a9495839f8ee0a2dad1c5 100644 (file)
@@ -397,7 +397,7 @@ changelist text. Exiting with a non-zero status from the script
 will abort the process.
 
 The purpose of the hook is to edit the message file in place,
-and it is not supressed by the `--no-verify` option. This hook
+and it is not suppressed by the `--no-verify` option. This hook
 is called even if `--prepare-p4-only` is set.
 
 p4-changelist
index b7bbbeadef6df43a9497cbbfad1f8cbf8213cd6f..93708aefeaef339b28ff6257fb8780a5393478bd 100644 (file)
@@ -494,10 +494,14 @@ edit ~/.gitconfig to specify your account settings:
        smtpServerPort = 587
 ----
 
-If you have multifactor authentication setup on your gmail account, you will
+If you have multi-factor authentication set up on your Gmail account, you will
 need to generate an app-specific password for use with 'git send-email'. Visit
 https://security.google.com/settings/security/apppasswords to create it.
 
+If you do not have multi-factor authentication set up on your Gmail account,
+you will need to allow less secure app access. Visit
+https://myaccount.google.com/lesssecureapps to enable it.
+
 Once your commits are ready to be sent to the mailing list, run the
 following commands:
 
index 7731b45f078e92e01df48d47d9f9abf9d1d931c1..c0764e850a44adde9499c6e601dace9320116f38 100644 (file)
@@ -184,11 +184,26 @@ characters, that field will be quoted in the manner of a C string
 literal: surrounded by ASCII double quote (34) characters, and with
 interior special characters backslash-escaped.
 
-For paths with merge conflicts, `X` and `Y` show the modification
-states of each side of the merge. For paths that do not have merge
-conflicts, `X` shows the status of the index, and `Y` shows the status
-of the work tree.  For untracked paths, `XY` are `??`.  Other status
-codes can be interpreted as follows:
+There are three different types of states that are shown using this format, and
+each one uses the `XY` syntax differently:
+
+* When a merge is occurring and the merge was successful, or outside of a merge
+       situation, `X` shows the status of the index and `Y` shows the status of the
+       working tree.
+* When a merge conflict has occurred and has not yet been resolved, `X` and `Y`
+       show the state introduced by each head of the merge, relative to the common
+       ancestor. These paths are said to be _unmerged_.
+* When a path is untracked, `X` and `Y` are always the same, since they are
+       unknown to the index. `??` is used for untracked paths. Ignored files are
+       not listed unless `--ignored` is used; if it is, ignored files are indicated
+       by `!!`.
+
+Note that the term _merge_ here also includes rebases using the default
+`--merge` strategy, cherry-picks, and anything else using the merge machinery.
+
+In the following table, these three classes are shown in separate sections, and
+these characters are used for `X` and `Y` fields for the first two sections that
+show tracked paths:
 
 * ' ' = unmodified
 * 'M' = modified
@@ -198,9 +213,6 @@ codes can be interpreted as follows:
 * 'C' = copied
 * 'U' = updated but unmerged
 
-Ignored files are not listed, unless `--ignored` option is in effect,
-in which case `XY` are `!!`.
-
 ....
 X          Y     Meaning
 -------------------------------------------------
index 1489cb09a09997a64a102b58a8bf2b890640d6df..2853f168d976857581163f2ac057110ddb501829 100644 (file)
@@ -30,9 +30,8 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
-Modifies the index or directory cache. Each file mentioned is updated
-into the index and any 'unmerged' or 'needs updating' state is
-cleared.
+Modifies the index. Each file mentioned is updated into the index and
+any 'unmerged' or 'needs updating' state is cleared.
 
 See also linkgit:git-add[1] for a more user-friendly way to do some of
 the most common operations on the index.
index ffccfc776080241e733b6675f02b2dca9c6c9341..1f3b57d04db6ca3b98e720b83362610b9198fbac 100644 (file)
@@ -644,7 +644,7 @@ changelist text. Exiting with a non-zero status from the script
 will abort the process.
 
 The purpose of the hook is to edit the message file in place,
-and it is not supressed by the `--no-verify` option. This hook
+and it is not suppressed by the `--no-verify` option. This hook
 is called even if `--prepare-p4-only` is set.
 
 Run `git-p4 submit --help` for details.
index 539b4e1997e62c741ba4cd68ab28fcab534380ec..8e333dde1baeeadcf877bbb266606049a65639dd 100644 (file)
@@ -7,7 +7,7 @@ gitmodules - Defining submodule properties
 
 SYNOPSIS
 --------
-$GIT_WORK_DIR/.gitmodules
+$GIT_WORK_TREE/.gitmodules
 
 
 DESCRIPTION
@@ -27,19 +27,19 @@ submodule.<name>.path::
        Defines the path, relative to the top-level directory of the Git
        working tree, where the submodule is expected to be checked out.
        The path name must not end with a `/`. All submodule paths must
-       be unique within the .gitmodules file.
+       be unique within the `.gitmodules` file.
 
 submodule.<name>.url::
        Defines a URL from which the submodule repository can be cloned.
        This may be either an absolute URL ready to be passed to
-       linkgit:git-clone[1] or (if it begins with ./ or ../) a location
+       linkgit:git-clone[1] or (if it begins with `./` or `../`) a location
        relative to the superproject's origin repository.
 
 In addition, there are a number of optional keys:
 
 submodule.<name>.update::
        Defines the default update procedure for the named submodule,
-       i.e. how the submodule is updated by "git submodule update"
+       i.e. how the submodule is updated by the `git submodule update`
        command in the superproject. This is only used by `git
        submodule init` to initialize the configuration variable of
        the same name. Allowed values here are 'checkout', 'rebase',
@@ -49,7 +49,7 @@ submodule.<name>.update::
 
 submodule.<name>.branch::
        A remote branch name for tracking updates in the upstream submodule.
-       If the option is not specified, it defaults to the remote 'HEAD'.
+       If the option is not specified, it defaults to the remote `HEAD`.
        A special value of `.` is used to indicate that the name of the branch
        in the submodule should be the same name as the current branch in the
        current repository.  See the `--remote` documentation in
@@ -57,14 +57,14 @@ submodule.<name>.branch::
 
 submodule.<name>.fetchRecurseSubmodules::
        This option can be used to control recursive fetching of this
-       submodule. If this option is also present in the submodules entry in
-       .git/config of the superproject, the setting there will override the
-       one found in .gitmodules.
+       submodule. If this option is also present in the submodule's entry in
+       `.git/config` of the superproject, the setting there will override the
+       one found in `.gitmodules`.
        Both settings can be overridden on the command line by using the
-       "--[no-]recurse-submodules" option to "git fetch" and "git pull".
+       `--[no-]recurse-submodules` option to `git fetch` and `git pull`.
 
 submodule.<name>.ignore::
-       Defines under what circumstances "git status" and the diff family show
+       Defines under what circumstances `git status` and the diff family show
        a submodule as modified. The following values are supported:
 +
 --
@@ -73,7 +73,7 @@ submodule.<name>.ignore::
            been staged).
 
        dirty;; All changes to the submodule's work tree will be ignored, only
-           committed differences between the HEAD of the submodule and its
+           committed differences between the `HEAD` of the submodule and its
            recorded state in the superproject are taken into account.
 
        untracked;; Only untracked files in submodules will be ignored.
@@ -84,12 +84,12 @@ submodule.<name>.ignore::
            differences, and modifications to tracked and untracked files are
            shown. This is the default option.
 
-If this option is also present in the submodules entry in .git/config
+If this option is also present in the submodule's entry in `.git/config`
 of the superproject, the setting there will override the one found in
-.gitmodules.
+`.gitmodules`.
 
 Both settings can be overridden on the command line by using the
-"--ignore-submodules" option. The 'git submodule' commands are not
+`--ignore-submodules` option. The `git submodule` commands are not
 affected by this setting.
 --
 
@@ -102,7 +102,7 @@ submodule.<name>.shallow::
 EXAMPLES
 --------
 
-Consider the following .gitmodules file:
+Consider the following `.gitmodules` file:
 
 ----
 [submodule "libfoo"]
index f96b2e605f3486d389c0bb0674c060d7f52fe38a..96d2fc589f817afe9cccffc01fb45e423eacfb9c 100644 (file)
@@ -55,6 +55,18 @@ Valid object types are:
 
 Type 5 is reserved for future expansion. Type 0 is invalid.
 
+=== Size encoding
+
+This document uses the following "size encoding" of non-negative
+integers: From each byte, the seven least significant bits are
+used to form the resulting integer. As long as the most significant
+bit is 1, this process continues; the byte with MSB 0 provides the
+last seven bits.  The seven-bit chunks are concatenated. Later
+values are more significant.
+
+This size encoding should not be confused with the "offset encoding",
+which is also used in this document.
+
 === Deltified representation
 
 Conceptually there are only four object types: commit, tree, tag and
@@ -73,7 +85,10 @@ Ref-delta can also refer to an object outside the pack (i.e. the
 so-called "thin pack"). When stored on disk however, the pack should
 be self contained to avoid cyclic dependency.
 
-The delta data is a sequence of instructions to reconstruct an object
+The delta data starts with the size of the base object and the
+size of the object to be reconstructed. These sizes are
+encoded using the size encoding from above.  The remainder of
+the delta data is a sequence of instructions to reconstruct the object
 from the base object. If the base object is deltified, it must be
 converted to canonical form first. Each instruction appends more and
 more data to the target object until it's complete. There are two
index 318713abc37199826aa97eb1a040465c4dddf230..f7eabc6c76838d6577d14058c3ad43b69f3cf4f4 100644 (file)
@@ -37,8 +37,11 @@ at least so that we can test the client.
 This is the implementation: a feature, marked experimental, that allows the
 server to be configured by one or more `uploadpack.blobPackfileUri=<sha1>
 <uri>` entries. Whenever the list of objects to be sent is assembled, all such
-blobs are excluded, replaced with URIs. The client will download those URIs,
-expecting them to each point to packfiles containing single blobs.
+blobs are excluded, replaced with URIs. As noted in "Future work" below, the
+server can evolve in the future to support excluding other objects (or other
+implementations of servers could be made that support excluding other objects)
+without needing a protocol change, so clients should not expect that packfiles
+downloaded in this way only contain single blobs.
 
 Client design
 -------------
index 2951840e9c9bd2cea6d1a2589c2d2daf53f501d9..8095ab2590c87810fe2e95e8bfa56eef9f1caa42 100644 (file)
@@ -446,7 +446,7 @@ especially if readers will not use the object name to ref mapping.
 Object blocks use unique, abbreviated 2-32 object name keys, mapping to
 ref blocks containing references pointing to that object directly, or as
 the peeled value of an annotated tag. Like ref blocks, object blocks use
-the file's standard block size. The abbrevation length is available in
+the file's standard block size. The abbreviation length is available in
 the footer as `obj_id_len`.
 
 To save space in small files, object blocks may be omitted if the ref
index 5085ef1390ca5589f6e553aacb177e7336504de6..224ae5b61f16af539ff8f9f7618fed6c6aa0a2d5 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v2.30.0
+DEF_VER=v2.30.1pre
 
 LF='
 '
index 7b64106930a615c2e867a061f94cd6d3ea834641..4128b457e14bda2a1b03bc439f413e82cf7f691a 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -777,20 +777,6 @@ BUILT_INS += git-status$X
 BUILT_INS += git-switch$X
 BUILT_INS += git-whatchanged$X
 
-# what 'all' will build and 'install' will install in gitexecdir,
-# excluding programs for built-in commands
-ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS)
-ALL_COMMANDS_TO_INSTALL = $(ALL_PROGRAMS)
-ifeq (,$(SKIP_DASHED_BUILT_INS))
-ALL_COMMANDS_TO_INSTALL += $(BUILT_INS)
-else
-# git-upload-pack, git-receive-pack and git-upload-archive are special: they
-# are _expected_ to be present in the `bin/` directory in their dashed form.
-ALL_COMMANDS_TO_INSTALL += git-receive-pack$(X)
-ALL_COMMANDS_TO_INSTALL += git-upload-archive$(X)
-ALL_COMMANDS_TO_INSTALL += git-upload-pack$(X)
-endif
-
 # what 'all' will build but not install in gitexecdir
 OTHER_PROGRAMS = git$X
 
@@ -1226,6 +1212,20 @@ ifdef DEVELOPER
 include config.mak.dev
 endif
 
+# what 'all' will build and 'install' will install in gitexecdir,
+# excluding programs for built-in commands
+ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS)
+ALL_COMMANDS_TO_INSTALL = $(ALL_PROGRAMS)
+ifeq (,$(SKIP_DASHED_BUILT_INS))
+ALL_COMMANDS_TO_INSTALL += $(BUILT_INS)
+else
+# git-upload-pack, git-receive-pack and git-upload-archive are special: they
+# are _expected_ to be present in the `bin/` directory in their dashed form.
+ALL_COMMANDS_TO_INSTALL += git-receive-pack$(X)
+ALL_COMMANDS_TO_INSTALL += git-upload-archive$(X)
+ALL_COMMANDS_TO_INSTALL += git-upload-pack$(X)
+endif
+
 ALL_CFLAGS = $(DEVELOPER_CFLAGS) $(CPPFLAGS) $(CFLAGS)
 ALL_LDFLAGS = $(LDFLAGS)
 
@@ -1554,9 +1554,6 @@ endif
 ifdef NO_SYMLINK_HEAD
        BASIC_CFLAGS += -DNO_SYMLINK_HEAD
 endif
-ifdef GETTEXT_POISON
-$(warning The GETTEXT_POISON option has been removed in favor of runtime GIT_TEST_GETTEXT_POISON. See t/README!)
-endif
 ifdef NO_GETTEXT
        BASIC_CFLAGS += -DNO_GETTEXT
        USE_GETTEXT_SCHEME ?= fallthrough
index dc8c04b4f4aed68baeccc7a7bbafad37e52c8320..679c2062ba755d5a810dc4db2bc8c25626ae5f92 120000 (symlink)
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/2.30.0.txt
\ No newline at end of file
+Documentation/RelNotes/2.30.1.txt
\ No newline at end of file
index 5bba623ff12787c31912191835141cee0068d87c..52be64a4373a3a4fb992662aaee54e17c9d03b46 100644 (file)
@@ -51,6 +51,13 @@ int cmd_for_each_repo(int argc, const char **argv, const char *prefix)
        values = repo_config_get_value_multi(the_repository,
                                             config_key);
 
+       /*
+        * Do nothing on an empty list, which is equivalent to the case
+        * where the config variable does not exist at all.
+        */
+       if (!values)
+               return 0;
+
        for (i = 0; !result && i < values->nr; i++)
                result = run_command_on_repo(values->items[i].string, &args);
 
index 19c7b377aa3fc603c63ad0abedd0ed643bce146f..840dbd7eb7772e47f408f05468f21df153e9cc20 100644 (file)
@@ -1917,7 +1917,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
                        die_if_checked_out(buf.buf, 1);
                        options.head_name = xstrdup(buf.buf);
                /* If not is it a valid ref (branch or commit)? */
-               } else if (!get_oid(branch_name, &options.orig_head))
+               } else if (!get_oid(branch_name, &options.orig_head) &&
+                          lookup_commit_reference(the_repository,
+                                                  &options.orig_head))
                        options.head_name = NULL;
                else
                        die(_("fatal: no such branch/commit '%s'"),
index e1f8235fdd399977033296b75a0676cf7f109c4a..9bc85f91cd004024b5bba9bf9cb587101e9dedce 100644 (file)
@@ -325,35 +325,6 @@ static void add_diff_to_buf(struct diff_queue_struct *q,
        }
 }
 
-static int get_newly_staged(struct strbuf *out, struct object_id *c_tree)
-{
-       struct child_process cp = CHILD_PROCESS_INIT;
-       const char *c_tree_hex = oid_to_hex(c_tree);
-
-       /*
-        * diff-index is very similar to diff-tree above, and should be
-        * converted together with update_index.
-        */
-       cp.git_cmd = 1;
-       strvec_pushl(&cp.args, "diff-index", "--cached", "--name-only",
-                    "--diff-filter=A", NULL);
-       strvec_push(&cp.args, c_tree_hex);
-       return pipe_command(&cp, NULL, 0, out, 0, NULL, 0);
-}
-
-static int update_index(struct strbuf *out)
-{
-       struct child_process cp = CHILD_PROCESS_INIT;
-
-       /*
-        * Update-index is very complicated and may need to have a public
-        * function exposed in order to remove this forking.
-        */
-       cp.git_cmd = 1;
-       strvec_pushl(&cp.args, "update-index", "--add", "--stdin", NULL);
-       return pipe_command(&cp, out->buf, out->len, NULL, 0, NULL, 0);
-}
-
 static int restore_untracked(struct object_id *u_tree)
 {
        int res;
@@ -385,6 +356,121 @@ static int restore_untracked(struct object_id *u_tree)
        return res;
 }
 
+static void unstage_changes_unless_new(struct object_id *orig_tree)
+{
+       /*
+        * When we enter this function, there has been a clean merge of
+        * relevant trees, and the merge logic always stages whatever merges
+        * cleanly.  We want to unstage those changes, unless it corresponds
+        * to a file that didn't exist as of orig_tree.
+        *
+        * However, if any SKIP_WORKTREE path is modified relative to
+        * orig_tree, then we want to clear the SKIP_WORKTREE bit and write
+        * it to the worktree before unstaging.
+        */
+
+       struct checkout state = CHECKOUT_INIT;
+       struct diff_options diff_opts;
+       struct lock_file lock = LOCK_INIT;
+       int i;
+
+       /* If any entries have skip_worktree set, we'll have to check 'em out */
+       state.force = 1;
+       state.quiet = 1;
+       state.refresh_cache = 1;
+       state.istate = &the_index;
+
+       /*
+        * Step 1: get a difference between orig_tree (which corresponding
+        * to the index before a merge was run) and the current index
+        * (reflecting the changes brought in by the merge).
+        */
+       diff_setup(&diff_opts);
+       diff_opts.flags.recursive = 1;
+       diff_opts.detect_rename = 0;
+       diff_opts.output_format = DIFF_FORMAT_NO_OUTPUT;
+       diff_setup_done(&diff_opts);
+
+       do_diff_cache(orig_tree, &diff_opts);
+       diffcore_std(&diff_opts);
+
+       /* Iterate over the paths that changed due to the merge... */
+       for (i = 0; i < diff_queued_diff.nr; i++) {
+               struct diff_filepair *p;
+               struct cache_entry *ce;
+               int pos;
+
+               /* Look up the path's position in the current index. */
+               p = diff_queued_diff.queue[i];
+               pos = index_name_pos(&the_index, p->two->path,
+                                    strlen(p->two->path));
+
+               /*
+                * Step 2: Place changes in the working tree
+                *
+                * Stash is about restoring changes *to the working tree*.
+                * So if the merge successfully got a new version of some
+                * path, but left it out of the working tree, then clear the
+                * SKIP_WORKTREE bit and write it to the working tree.
+                */
+               if (pos >= 0 && ce_skip_worktree(active_cache[pos])) {
+                       struct stat st;
+
+                       ce = active_cache[pos];
+                       if (!lstat(ce->name, &st)) {
+                               /* Conflicting path present; relocate it */
+                               struct strbuf new_path = STRBUF_INIT;
+                               int fd;
+
+                               strbuf_addf(&new_path,
+                                           "%s.stash.XXXXXX", ce->name);
+                               fd = xmkstemp(new_path.buf);
+                               close(fd);
+                               printf(_("WARNING: Untracked file in way of "
+                                        "tracked file!  Renaming\n "
+                                        "           %s -> %s\n"
+                                        "         to make room.\n"),
+                                      ce->name, new_path.buf);
+                               if (rename(ce->name, new_path.buf))
+                                       die("Failed to move %s to %s\n",
+                                           ce->name, new_path.buf);
+                               strbuf_release(&new_path);
+                       }
+                       checkout_entry(ce, &state, NULL, NULL);
+                       ce->ce_flags &= ~CE_SKIP_WORKTREE;
+               }
+
+               /*
+                * Step 3: "unstage" changes, as long as they are still tracked
+                */
+               if (p->one->oid_valid) {
+                       /*
+                        * Path existed in orig_tree; restore index entry
+                        * from that tree in order to "unstage" the changes.
+                        */
+                       int option = ADD_CACHE_OK_TO_REPLACE;
+                       if (pos < 0)
+                               option = ADD_CACHE_OK_TO_ADD;
+
+                       ce = make_cache_entry(&the_index,
+                                             p->one->mode,
+                                             &p->one->oid,
+                                             p->one->path,
+                                             0, 0);
+                       add_index_entry(&the_index, ce, option);
+               }
+       }
+       diff_flush(&diff_opts);
+
+       /*
+        * Step 4: write the new index to disk
+        */
+       repo_hold_locked_index(the_repository, &lock, LOCK_DIE_ON_ERROR);
+       if (write_locked_index(&the_index, &lock,
+                              COMMIT_LOCK | SKIP_IF_UNCHANGED))
+               die(_("Unable to write index."));
+}
+
 static int do_apply_stash(const char *prefix, struct stash_info *info,
                          int index, int quiet)
 {
@@ -467,26 +553,7 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,
                if (reset_tree(&index_tree, 0, 0))
                        return -1;
        } else {
-               struct strbuf out = STRBUF_INIT;
-
-               if (get_newly_staged(&out, &c_tree)) {
-                       strbuf_release(&out);
-                       return -1;
-               }
-
-               if (reset_tree(&c_tree, 0, 1)) {
-                       strbuf_release(&out);
-                       return -1;
-               }
-
-               ret = update_index(&out);
-               strbuf_release(&out);
-               if (ret)
-                       return -1;
-
-               /* read back the result of update_index() back from the disk */
-               discard_cache();
-               read_cache();
+               unstage_changes_unless_new(&c_tree);
        }
 
        if (!quiet) {
index 0229a77f7d281fa9717e359f34c634f118035a62..0b1184e04adedb1eba415a401c93331cdc139d6a 100755 (executable)
@@ -44,13 +44,13 @@ osx-clang|osx-gcc)
        test -z "$BREW_INSTALL_PACKAGES" ||
        brew install $BREW_INSTALL_PACKAGES
        brew link --force gettext
-       brew cask install --no-quarantine perforce || {
+       brew install --cask --no-quarantine perforce || {
                # Update the definitions and try again
                cask_repo="$(brew --repository)"/Library/Taps/homebrew/homebrew-cask &&
-               git -C "$cask_repo" pull --no-stat &&
-               brew cask install --no-quarantine perforce
+               git -C "$cask_repo" pull --no-stat --ff-only &&
+               brew install --cask --no-quarantine perforce
        } ||
-       brew install caskroom/cask/perforce
+       brew install homebrew/cask/perforce
        case "$jobname" in
        osx-gcc)
                brew install gcc@9
index 8b8f56cf6d230b23c46bb980755cb6d1fc3684ef..9c97fee43031056dff2beb2a8fe9ed882e476c2d 100644 (file)
--- a/connect.c
+++ b/connect.c
@@ -1160,6 +1160,8 @@ static struct child_process *git_connect_git(int fd[2], char *hostandport,
                target_host = xstrdup(hostandport);
 
        transport_check_allowed("git");
+       if (strchr(target_host, '\n') || strchr(path, '\n'))
+               die(_("newline is forbidden in git:// hosts and repo paths"));
 
        /*
         * These underlying connection commands die() if they
diff --git a/fsck.c b/fsck.c
index f82e2fe9e302fed2e9ebf44c0323628cb94576f0..5e282b3b6b25d514d2e82bdd6b29c9c17da580a5 100644 (file)
--- a/fsck.c
+++ b/fsck.c
@@ -1082,7 +1082,7 @@ static int check_submodule_url(const char *url)
        if (looks_like_command_line_option(url))
                return -1;
 
-       if (submodule_url_is_relative(url)) {
+       if (submodule_url_is_relative(url) || starts_with(url, "git://")) {
                char *decoded;
                const char *next;
                int has_nl;
index 35d2c1218db2e27a6ac07fbf3c1244987e3e3021..1b564216d03f6a7bb75fb4c867ad1b0e5cfbecd0 100644 (file)
--- a/gettext.c
+++ b/gettext.c
@@ -87,88 +87,24 @@ static int test_vsnprintf(const char *fmt, ...)
 
 static void init_gettext_charset(const char *domain)
 {
-       /*
-          This trick arranges for messages to be emitted in the user's
-          requested encoding, but avoids setting LC_CTYPE from the
-          environment for the whole program.
-
-          This primarily done to avoid a bug in vsnprintf in the GNU C
-          Library [1]. which triggered a "your vsnprintf is broken" error
-          on Git's own repository when inspecting v0.99.6~1 under a UTF-8
-          locale.
-
-          That commit contains a ISO-8859-1 encoded author name, which
-          the locale aware vsnprintf(3) won't interpolate in the format
-          argument, due to mismatch between the data encoding and the
-          locale.
-
-          Even if it wasn't for that bug we wouldn't want to use LC_CTYPE at
-          this point, because it'd require auditing all the code that uses C
-          functions whose semantics are modified by LC_CTYPE.
-
-          But only setting LC_MESSAGES as we do creates a problem, since
-          we declare the encoding of our PO files[2] the gettext
-          implementation will try to recode it to the user's locale, but
-          without LC_CTYPE it'll emit something like this on 'git init'
-          under the Icelandic locale:
-
-              Bj? til t?ma Git lind ? /hlagh/.git/
-
-          Gettext knows about the encoding of our PO file, but we haven't
-          told it about the user's encoding, so all the non-US-ASCII
-          characters get encoded to question marks.
-
-          But we're in luck! We can set LC_CTYPE from the environment
-          only while we call nl_langinfo and
-          bind_textdomain_codeset. That suffices to tell gettext what
-          encoding it should emit in, so it'll now say:
-
-              Bjó til tóma Git lind Ã­ /hlagh/.git/
-
-          And the equivalent ISO-8859-1 string will be emitted under a
-          ISO-8859-1 locale.
-
-          With this change way we get the advantages of setting LC_CTYPE
-          (talk to the user in his language/encoding), without the major
-          drawbacks (changed semantics for C functions we rely on).
-
-          However foreign functions using other message catalogs that
-          aren't using our neat trick will still have a problem, e.g. if
-          we have to call perror(3):
-
-          #include <stdio.h>
-          #include <locale.h>
-          #include <errno.h>
-
-          int main(void)
-          {
-                  setlocale(LC_MESSAGES, "");
-                  setlocale(LC_CTYPE, "C");
-                  errno = ENODEV;
-                  perror("test");
-                  return 0;
-          }
-
-          Running that will give you a message with question marks:
-
-          $ LANGUAGE= LANG=de_DE.utf8 ./test
-          test: Kein passendes Ger?t gefunden
-
-          The vsnprintf bug has been fixed since glibc 2.17.
-
-          Then we could simply set LC_CTYPE from the environment, which would
-          make things like the external perror(3) messages work.
-
-          See t/t0203-gettext-setlocale-sanity.sh's "gettext.c" tests for
-          regression tests.
-
-          1. http://sourceware.org/bugzilla/show_bug.cgi?id=6530
-          2. E.g. "Content-Type: text/plain; charset=UTF-8\n" in po/is.po
-       */
        setlocale(LC_CTYPE, "");
        charset = locale_charset();
        bind_textdomain_codeset(domain, charset);
-       /* the string is taken from v0.99.6~1 */
+
+       /*
+        * Work around an old bug fixed in glibc 2.17 (released on
+        * 2012-12-24), at the cost of potentially making translated
+        * messages from external functions like perror() emitted in
+        * the wrong encoding.
+        *
+        * The bug affected e.g. git.git's own 7eb93c89651 ([PATCH]
+        * Simplify git script, 2005-09-07), which is the origin of
+        * the "David_K\345gedal" test string.
+        *
+        * See a much longer comment added to this file in 5e9637c6297
+        * (i18n: add infrastructure for translating Git with gettext,
+        * 2011-11-18) for more details.
+        */
        if (test_vsnprintf("%.*s", 13, "David_K\345gedal") < 0)
                setlocale(LC_CTYPE, "C");
 }
index 7225abd81122e6bd798989d6e21fae1279cf3929..78f3647ed974b025ff87eaada0c2880723f074df 100644 (file)
@@ -46,9 +46,11 @@ show_tool_names () {
                while read scriptname
                do
                        setup_tool "$scriptname" 2>/dev/null
-                       variants="$variants$(list_tool_variants)\n"
+                       # We need an actual line feed here
+                       variants="$variants
+$(list_tool_variants)"
                done
-               variants="$(echo "$variants" | sort | uniq)"
+               variants="$(echo "$variants" | sort -u)"
 
                for toolname in $variants
                do
index 21973e49332c36532438bb067c8821a0e377baf9..f51021a0cb391d213ca63e5ccfde86c50d7c8164 100644 (file)
@@ -89,7 +89,7 @@ static int init_patch_id_entry(struct patch_id *patch,
        return 0;
 }
 
-struct patch_id *has_commit_patch_id(struct commit *commit,
+struct patch_id *patch_id_iter_first(struct commit *commit,
                                     struct patch_ids *ids)
 {
        struct patch_id patch;
@@ -104,6 +104,18 @@ struct patch_id *has_commit_patch_id(struct commit *commit,
        return hashmap_get_entry(&ids->patches, &patch, ent, NULL);
 }
 
+struct patch_id *patch_id_iter_next(struct patch_id *cur,
+                                   struct patch_ids *ids)
+{
+       return hashmap_get_next_entry(&ids->patches, cur, ent);
+}
+
+int has_commit_patch_id(struct commit *commit,
+                       struct patch_ids *ids)
+{
+       return !!patch_id_iter_first(commit, ids);
+}
+
 struct patch_id *add_commit_patch_id(struct commit *commit,
                                     struct patch_ids *ids)
 {
index 03bb04e7071f5f65a3b09f138aa4473fa0a0a655..ab6c6a680474c9b2a37725fc9392683ac5a33083 100644 (file)
@@ -23,7 +23,25 @@ int commit_patch_id(struct commit *commit, struct diff_options *options,
                    struct object_id *oid, int, int);
 int init_patch_ids(struct repository *, struct patch_ids *);
 int free_patch_ids(struct patch_ids *);
+
+/* Add a patch_id for a single commit to the set. */
 struct patch_id *add_commit_patch_id(struct commit *, struct patch_ids *);
-struct patch_id *has_commit_patch_id(struct commit *, struct patch_ids *);
+
+/* Returns true if the patch-id of "commit" is present in the set. */
+int has_commit_patch_id(struct commit *commit, struct patch_ids *);
+
+/*
+ * Iterate over all commits in the set whose patch id matches that of
+ * "commit", like:
+ *
+ *   struct patch_id *cur;
+ *   for (cur = patch_id_iter_first(commit, ids);
+ *        cur;
+ *        cur = patch_id_iter_next(cur, ids) {
+ *           ... look at cur->commit
+ *   }
+ */
+struct patch_id *patch_id_iter_first(struct commit *commit, struct patch_ids *);
+struct patch_id *patch_id_iter_next(struct patch_id *cur, struct patch_ids *);
 
 #endif /* PATCH_IDS_H */
index 9dff845bed6baa21c6d540657356d37710a7a433..7ec9b634e36ca42d5275815739ea68d390e629a0 100644 (file)
@@ -1241,12 +1241,14 @@ static void cherry_pick_list(struct commit_list *list, struct rev_info *revs)
                /*
                 * Have we seen the same patch id?
                 */
-               id = has_commit_patch_id(commit, &ids);
+               id = patch_id_iter_first(commit, &ids);
                if (!id)
                        continue;
 
                commit->object.flags |= cherry_flag;
-               id->commit->object.flags |= cherry_flag;
+               do {
+                       id->commit->object.flags |= cherry_flag;
+               } while ((id = patch_id_iter_next(id, &ids)));
        }
 
        free_patch_ids(&ids);
index b3bb59f06644739c859adb22836e2761da2a91be..b561445329204f20a326cf7f7a5b897ca28d0934 100644 (file)
@@ -1477,6 +1477,7 @@ static int get_next_submodule(struct child_process *cp,
                        strbuf_release(&submodule_prefix);
                        return 1;
                } else {
+                       struct strbuf empty_submodule_path = STRBUF_INIT;
 
                        fetch_task_release(task);
                        free(task);
@@ -1485,13 +1486,17 @@ static int get_next_submodule(struct child_process *cp,
                         * An empty directory is normal,
                         * the submodule is not initialized
                         */
+                       strbuf_addf(&empty_submodule_path, "%s/%s/",
+                                                       spf->r->worktree,
+                                                       ce->name);
                        if (S_ISGITLINK(ce->ce_mode) &&
-                           !is_empty_dir(ce->name)) {
+                           !is_empty_dir(empty_submodule_path.buf)) {
                                spf->result = 1;
                                strbuf_addf(err,
                                            _("Could not access submodule '%s'\n"),
                                            ce->name);
                        }
+                       strbuf_release(&empty_submodule_path);
                }
        }
 
index bd3fa3c6da40d7018baf56b3360ed68f046eca48..4b714e93083f128ba7130b3a6df8da887cfa1184 100644 (file)
@@ -316,14 +316,7 @@ test_submodule_switch_common () {
        command="$1"
        ######################### Appearing submodule #########################
        # Switching to a commit letting a submodule appear creates empty dir ...
-       if test "$KNOWN_FAILURE_STASH_DOES_IGNORE_SUBMODULE_CHANGES" = 1
-       then
-               # Restoring stash fails to restore submodule index entry
-               RESULT="failure"
-       else
-               RESULT="success"
-       fi
-       test_expect_$RESULT "$command: added submodule creates empty directory" '
+       test_expect_success "$command: added submodule creates empty directory" '
                prolog &&
                reset_work_tree_to no_submodule &&
                (
@@ -337,6 +330,13 @@ test_submodule_switch_common () {
                )
        '
        # ... and doesn't care if it already exists.
+       if test "$KNOWN_FAILURE_STASH_DOES_IGNORE_SUBMODULE_CHANGES" = 1
+       then
+               # Restoring stash fails to restore submodule index entry
+               RESULT="failure"
+       else
+               RESULT="success"
+       fi
        test_expect_$RESULT "$command: added submodule leaves existing empty directory alone" '
                prolog &&
                reset_work_tree_to no_submodule &&
index 9b43342806b9e0243ccb81a60931abdf36034337..1e20a184c70e67c51a5feb41baed92b987394173 100755 (executable)
@@ -129,7 +129,12 @@ setup_for_fsmonitor() {
 
        git config core.fsmonitor "$INTEGRATION_SCRIPT" &&
        git update-index --fsmonitor 2>error &&
-       test_must_be_empty error  # ensure no silent error
+       if test_have_prereq WATCHMAN
+       then
+               test_must_be_empty error  # ensure no silent error
+       else
+               grep "Empty last update token" error
+       fi
 }
 
 test_perf_w_drop_caches () {
index 136b4ec8392817eec21153b37f94ab3167f5f106..4675e852517688179c2783803ebfa56e730cd24c 100755 (executable)
@@ -27,4 +27,10 @@ test_expect_success 'run based on configured value' '
        grep again message
 '
 
+test_expect_success 'do nothing on empty config' '
+       # the whole thing would fail if for-each-ref iterated even
+       # once, because "git help --no-such-option" would fail
+       git for-each-repo --config=bogus.config -- help --no-such-option
+'
+
 test_done
index 97a04c6cc26fda58417c9242d690e68148a3d9cc..1a4156c70434f34ef7693d60b5932d92d18845b0 100755 (executable)
@@ -12,75 +12,75 @@ test_expect_success 'clear default config' '
 '
 
 cat > expect << EOF
-[core]
+[section]
        penguin = little blue
 EOF
 test_expect_success 'initial' '
-       git config core.penguin "little blue" &&
+       git config section.penguin "little blue" &&
        test_cmp expect .git/config
 '
 
 cat > expect << EOF
-[core]
+[section]
        penguin = little blue
        Movie = BadPhysics
 EOF
 test_expect_success 'mixed case' '
-       git config Core.Movie BadPhysics &&
+       git config Section.Movie BadPhysics &&
        test_cmp expect .git/config
 '
 
 cat > expect << EOF
-[core]
+[section]
        penguin = little blue
        Movie = BadPhysics
-[Cores]
+[Sections]
        WhatEver = Second
 EOF
 test_expect_success 'similar section' '
-       git config Cores.WhatEver Second &&
+       git config Sections.WhatEver Second &&
        test_cmp expect .git/config
 '
 
 cat > expect << EOF
-[core]
+[section]
        penguin = little blue
        Movie = BadPhysics
        UPPERCASE = true
-[Cores]
+[Sections]
        WhatEver = Second
 EOF
 test_expect_success 'uppercase section' '
-       git config CORE.UPPERCASE true &&
+       git config SECTION.UPPERCASE true &&
        test_cmp expect .git/config
 '
 
 test_expect_success 'replace with non-match' '
-       git config core.penguin kingpin !blue
+       git config section.penguin kingpin !blue
 '
 
 test_expect_success 'replace with non-match (actually matching)' '
-       git config core.penguin "very blue" !kingpin
+       git config section.penguin "very blue" !kingpin
 '
 
 cat > expect << EOF
-[core]
+[section]
        penguin = very blue
        Movie = BadPhysics
        UPPERCASE = true
        penguin = kingpin
-[Cores]
+[Sections]
        WhatEver = Second
 EOF
 
 test_expect_success 'non-match result' 'test_cmp expect .git/config'
 
 test_expect_success 'find mixed-case key by canonical name' '
-       test_cmp_config Second cores.whatever
+       test_cmp_config Second sections.whatever
 '
 
 test_expect_success 'find mixed-case key by non-canonical name' '
-       test_cmp_config Second CoReS.WhAtEvEr
+       test_cmp_config Second SeCtIoNs.WhAtEvEr
 '
 
 test_expect_success 'subsections are not canonicalized by git-config' '
@@ -469,7 +469,8 @@ test_expect_success 'new variable inserts into proper section' '
 '
 
 test_expect_success 'alternative --file (non-existing file should fail)' '
-       test_must_fail git config --file non-existing-config -l
+       test_must_fail git config --file non-existing-config -l &&
+       test_must_fail git config --file non-existing-config test.xyzzy
 '
 
 cat > other-config << EOF
@@ -506,10 +507,6 @@ test_expect_success 'editing stdin is an error' '
 
 test_expect_success 'refer config from subdirectory' '
        mkdir x &&
-       test_cmp_config -C x strasse --get --file ../other-config ein.bahn
-'
-
-test_expect_success 'refer config from subdirectory via --file' '
        test_cmp_config -C x strasse --file=../other-config --get ein.bahn
 '
 
@@ -1036,11 +1033,6 @@ test_expect_success SYMLINKS 'symlinked configuration' '
        test_cmp expect actual
 '
 
-test_expect_success 'nonexistent configuration' '
-       test_must_fail git config --file=doesnotexist --list &&
-       test_must_fail git config --file=doesnotexist test.xyzzy
-'
-
 test_expect_success SYMLINKS 'symlink to nonexistent configuration' '
        ln -s doesnotexist linktonada &&
        ln -s linktonada linktolinktonada &&
@@ -1065,12 +1057,12 @@ test_expect_success 'git -c "key=value" support' '
        true
        EOF
        {
-               git -c core.name=value config core.name &&
+               git -c section.name=value config section.name &&
                git -c foo.CamelCase=value config foo.camelcase &&
                git -c foo.flag config --bool foo.flag
        } >actual &&
        test_cmp expect actual &&
-       test_must_fail git -c name=value config core.name
+       test_must_fail git -c name=value config section.name
 '
 
 # We just need a type-specifier here that cares about the
@@ -1115,7 +1107,7 @@ test_expect_success 'aliases can be CamelCased' '
 
 test_expect_success 'git -c does not split values on equals' '
        echo "value with = in it" >expect &&
-       git -c core.foo="value with = in it" config core.foo >actual &&
+       git -c section.foo="value with = in it" config section.foo >actual &&
        test_cmp expect actual
 '
 
@@ -1846,53 +1838,53 @@ do
 done
 
 cat >.git/config <<-\EOF &&
-[core]
+[section]
 foo = true
 number = 10
 big = 1M
 EOF
 
 test_expect_success 'identical modern --type specifiers are allowed' '
-       test_cmp_config 1048576 --type=int --type=int core.big
+       test_cmp_config 1048576 --type=int --type=int section.big
 '
 
 test_expect_success 'identical legacy --type specifiers are allowed' '
-       test_cmp_config 1048576 --int --int core.big
+       test_cmp_config 1048576 --int --int section.big
 '
 
 test_expect_success 'identical mixed --type specifiers are allowed' '
-       test_cmp_config 1048576 --int --type=int core.big
+       test_cmp_config 1048576 --int --type=int section.big
 '
 
 test_expect_success 'non-identical modern --type specifiers are not allowed' '
-       test_must_fail git config --type=int --type=bool core.big 2>error &&
+       test_must_fail git config --type=int --type=bool section.big 2>error &&
        test_i18ngrep "only one type at a time" error
 '
 
 test_expect_success 'non-identical legacy --type specifiers are not allowed' '
-       test_must_fail git config --int --bool core.big 2>error &&
+       test_must_fail git config --int --bool section.big 2>error &&
        test_i18ngrep "only one type at a time" error
 '
 
 test_expect_success 'non-identical mixed --type specifiers are not allowed' '
-       test_must_fail git config --type=int --bool core.big 2>error &&
+       test_must_fail git config --type=int --bool section.big 2>error &&
        test_i18ngrep "only one type at a time" error
 '
 
 test_expect_success '--type allows valid type specifiers' '
-       test_cmp_config true  --type=bool core.foo
+       test_cmp_config true  --type=bool section.foo
 '
 
 test_expect_success '--no-type unsets type specifiers' '
-       test_cmp_config 10 --type=bool --no-type core.number
+       test_cmp_config 10 --type=bool --no-type section.number
 '
 
 test_expect_success 'unset type specifiers may be reset to conflicting ones' '
-       test_cmp_config 1048576 --type=bool --no-type --type=int core.big
+       test_cmp_config 1048576 --type=bool --no-type --type=int section.big
 '
 
 test_expect_success '--type rejects unknown specifiers' '
-       test_must_fail git config --type=nonsense core.foo 2>error &&
+       test_must_fail git config --type=nonsense section.foo 2>error &&
        test_i18ngrep "unrecognized --type argument" error
 '
 
index 41818d8315f32359b0eabd1cb91684c90c070098..576632f8681e76032c0f87ac0b65833314058035 100755 (executable)
@@ -78,7 +78,7 @@ test_expect_success POSIXPERM 'do not use core.sharedRepository for working tree
        test_config core.sharedRepository 0666 &&
        (
                # Remove a default ACL if possible.
-               (setfacl -k newdir 2>/dev/null || true) &&
+               (setfacl -k . 2>/dev/null || true) &&
                umask 0077 &&
 
                # Test both files (f1) and leading dirs (d)
index 01004ff6802070ea5b06d82e13eb0350a0cf78f0..3ed121d0cefe95e18fe4af3489dbbe909fa4a212 100755 (executable)
@@ -1260,7 +1260,9 @@ do
                        git cat-file commit $SHA1_2 &&
                        test_must_fail env GIT_TEST_PROTOCOL_VERSION=0 \
                                git fetch ../testrepo/.git $SHA1_3 2>err &&
-                       test_i18ngrep "remote error:.*not our ref.*$SHA1_3\$" err
+                       # ideally we would insist this be on a "remote error:"
+                       # line, but it is racy; see the commit message
+                       test_i18ngrep "not our ref.*$SHA1_3\$" err
                )
        '
 done
index a877dd145e24c56e7197251ebccaa5804ed40522..53d7b8ed7571f54d4c714f6945a62ab8ced3d86f 100755 (executable)
@@ -722,4 +722,121 @@ test_expect_success 'fetch new submodule commit intermittently referenced by sup
        )
 '
 
+add_commit_push () {
+       dir="$1" &&
+       msg="$2" &&
+       shift 2 &&
+       git -C "$dir" add "$@" &&
+       git -C "$dir" commit -a -m "$msg" &&
+       git -C "$dir" push
+}
+
+compare_refs_in_dir () {
+       fail= &&
+       if test "x$1" = 'x!'
+       then
+               fail='!' &&
+               shift
+       fi &&
+       git -C "$1" rev-parse --verify "$2" >expect &&
+       git -C "$3" rev-parse --verify "$4" >actual &&
+       eval $fail test_cmp expect actual
+}
+
+
+test_expect_success 'setup nested submodule fetch test' '
+       # does not depend on any previous test setups
+
+       for repo in outer middle inner
+       do
+               git init --bare $repo &&
+               git clone $repo ${repo}_content &&
+               echo "$repo" >"${repo}_content/file" &&
+               add_commit_push ${repo}_content "initial" file ||
+               return 1
+       done &&
+
+       git clone outer A &&
+       git -C A submodule add "$pwd/middle" &&
+       git -C A/middle/ submodule add "$pwd/inner" &&
+       add_commit_push A/middle/ "adding inner sub" .gitmodules inner &&
+       add_commit_push A/ "adding middle sub" .gitmodules middle &&
+
+       git clone outer B &&
+       git -C B/ submodule update --init middle &&
+
+       compare_refs_in_dir A HEAD B HEAD &&
+       compare_refs_in_dir A/middle HEAD B/middle HEAD &&
+       test_path_is_file B/file &&
+       test_path_is_file B/middle/file &&
+       test_path_is_missing B/middle/inner/file &&
+
+       echo "change on inner repo of A" >"A/middle/inner/file" &&
+       add_commit_push A/middle/inner "change on inner" file &&
+       add_commit_push A/middle "change on inner" inner &&
+       add_commit_push A "change on inner" middle
+'
+
+test_expect_success 'fetching a superproject containing an uninitialized sub/sub project' '
+       # depends on previous test for setup
+
+       git -C B/ fetch &&
+       compare_refs_in_dir A origin/HEAD B origin/HEAD
+'
+
+fetch_with_recursion_abort () {
+       # In a regression the following git call will run into infinite recursion.
+       # To handle that, we connect the sed command to the git call by a pipe
+       # so that sed can kill the infinite recursion when detected.
+       # The recursion creates git output like:
+       # Fetching submodule sub
+       # Fetching submodule sub/sub              <-- [1]
+       # Fetching submodule sub/sub/sub
+       # ...
+       # [1] sed will stop reading and cause git to eventually stop and die
+
+       git -C "$1" fetch --recurse-submodules 2>&1 |
+               sed "/Fetching submodule $2[^$]/q" >out &&
+       ! grep "Fetching submodule $2[^$]" out
+}
+
+test_expect_success 'setup recursive fetch with uninit submodule' '
+       # does not depend on any previous test setups
+
+       test_create_repo super &&
+       test_commit -C super initial &&
+       test_create_repo sub &&
+       test_commit -C sub initial &&
+       git -C sub rev-parse HEAD >expect &&
+
+       git -C super submodule add ../sub &&
+       git -C super commit -m "add sub" &&
+
+       git clone super superclone &&
+       git -C superclone submodule status >out &&
+       sed -e "s/^-//" -e "s/ sub.*$//" out >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'recursive fetch with uninit submodule' '
+       # depends on previous test for setup
+
+       fetch_with_recursion_abort superclone sub &&
+       git -C superclone submodule status >out &&
+       sed -e "s/^-//" -e "s/ sub$//" out >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'recursive fetch after deinit a submodule' '
+       # depends on previous test for setup
+
+       git -C superclone submodule update --init sub &&
+       git -C superclone submodule deinit -f sub &&
+
+       fetch_with_recursion_abort superclone sub &&
+       git -C superclone submodule status >out &&
+       sed -e "s/^-//" -e "s/ sub$//" out >actual &&
+       test_cmp expect actual
+'
+
 test_done
index 8f69a7854fb3108e1301f4b90961b3f6a1dc9e98..0fbb194810764f654903528b335afe328c64f5f0 100755 (executable)
@@ -103,6 +103,11 @@ test_expect_success 'fetch notices corrupt idx' '
        )
 '
 
+test_expect_success 'client refuses to ask for repo with newline' '
+       test_must_fail git clone "$GIT_DAEMON_URL/repo$LF.git" dst 2>stderr &&
+       test_i18ngrep newline.is.forbidden stderr
+'
+
 test_remote_error()
 {
        do_export=YesPlease
index f0268372d25e562ad8fc5c347b376b88a62d8803..8bf5ae23c2ac350b43bfa66ffd01db2731531e53 100755 (executable)
@@ -245,6 +245,18 @@ test_expect_success '--count --left-right' '
        test_cmp expect actual
 '
 
+test_expect_success '--cherry-pick with duplicates on each side' '
+       git checkout -b dup-orig &&
+       test_commit dup-base &&
+       git revert dup-base &&
+       git cherry-pick dup-base &&
+       git checkout -b dup-side HEAD~3 &&
+       test_tick &&
+       git cherry-pick -3 dup-orig &&
+       git rev-list --cherry-pick dup-orig...dup-side >actual &&
+       test_must_be_empty actual
+'
+
 # Corrupt the object store deliberately to make sure
 # the object is not even checked for its existence.
 remove_loose_object () {
index aa226381be214a43e7a07aa2ffe897314938184a..52614eefc7e766b0c236526a5ee9bca1815241a5 100755 (executable)
@@ -926,14 +926,14 @@ test_expect_success 'git bisect reset cleans bisection state properly' '
        git bisect bad $HASH4 &&
        git bisect reset &&
        test -z "$(git for-each-ref "refs/bisect/*")" &&
-       test_path_is_missing "$GIT_DIR/BISECT_EXPECTED_REV" &&
-       test_path_is_missing "$GIT_DIR/BISECT_ANCESTORS_OK" &&
-       test_path_is_missing "$GIT_DIR/BISECT_LOG" &&
-       test_path_is_missing "$GIT_DIR/BISECT_RUN" &&
-       test_path_is_missing "$GIT_DIR/BISECT_TERMS" &&
-       test_path_is_missing "$GIT_DIR/head-name" &&
-       test_path_is_missing "$GIT_DIR/BISECT_HEAD" &&
-       test_path_is_missing "$GIT_DIR/BISECT_START"
+       test_path_is_missing ".git/BISECT_EXPECTED_REV" &&
+       test_path_is_missing ".git/BISECT_ANCESTORS_OK" &&
+       test_path_is_missing ".git/BISECT_LOG" &&
+       test_path_is_missing ".git/BISECT_RUN" &&
+       test_path_is_missing ".git/BISECT_TERMS" &&
+       test_path_is_missing ".git/head-name" &&
+       test_path_is_missing ".git/BISECT_HEAD" &&
+       test_path_is_missing ".git/BISECT_START"
 '
 
 test_done
index 7476781979c3ff164ce9eeba1079d41f15bdaa5c..e5c6a038fbfccb3da7c3c179fa0c6c186de68d40 100755 (executable)
@@ -149,6 +149,94 @@ test_expect_success '--ignore-skip-worktree-entries leaves worktree alone' '
                --diff-filter=D -- keep-me.t
 '
 
+test_expect_success 'stash restore in sparse checkout' '
+       test_create_repo stash-restore &&
+       (
+               cd stash-restore &&
+
+               mkdir subdir &&
+               echo A >subdir/A &&
+               echo untouched >untouched &&
+               echo removeme >removeme &&
+               echo modified >modified &&
+               git add . &&
+               git commit -m Initial &&
+
+               echo AA >>subdir/A &&
+               echo addme >addme &&
+               echo tweaked >>modified &&
+               rm removeme &&
+               git add addme &&
+
+               git stash push &&
+
+               git sparse-checkout set subdir &&
+
+               # Ensure after sparse-checkout we only have expected files
+               cat >expect <<-EOF &&
+               S modified
+               S removeme
+               H subdir/A
+               S untouched
+               EOF
+               git ls-files -t >actual &&
+               test_cmp expect actual &&
+
+               test_path_is_missing addme &&
+               test_path_is_missing modified &&
+               test_path_is_missing removeme &&
+               test_path_is_file    subdir/A &&
+               test_path_is_missing untouched &&
+
+               # Put a file in the working directory in the way
+               echo in the way >modified &&
+               git stash apply &&
+
+               # Ensure stash vivifies modifies paths...
+               cat >expect <<-EOF &&
+               H addme
+               H modified
+               H removeme
+               H subdir/A
+               S untouched
+               EOF
+               git ls-files -t >actual &&
+               test_cmp expect actual &&
+
+               # ...and that the paths show up in status as changed...
+               cat >expect <<-EOF &&
+               A  addme
+                M modified
+                D removeme
+                M subdir/A
+               ?? actual
+               ?? expect
+               ?? modified.stash.XXXXXX
+               EOF
+               git status --porcelain | \
+                       sed -e s/stash......./stash.XXXXXX/ >actual &&
+               test_cmp expect actual &&
+
+               # ...and that working directory reflects the files correctly
+               test_path_is_file    addme &&
+               test_path_is_file    modified &&
+               test_path_is_missing removeme &&
+               test_path_is_file    subdir/A &&
+               test_path_is_missing untouched &&
+
+               # ...including that we have the expected "modified" file...
+               cat >expect <<-EOF &&
+               modified
+               tweaked
+               EOF
+               test_cmp expect modified &&
+
+               # ...and that the other "modified" file is still present...
+               echo in the way >expect &&
+               test_cmp expect modified.stash.*
+       )
+'
+
 #TODO test_expect_failure 'git-apply adds file' false
 #TODO test_expect_failure 'git-apply updates file' false
 #TODO test_expect_failure 'git-apply removes file' false
index eec96e0ba9e371e9603bd47ad5e13f0e547d7b5a..d21dc8b009f6d0d8e75368d01a984ac350155ba3 100755 (executable)
@@ -201,4 +201,19 @@ test_expect_success 'fsck rejects embedded newline in relative url' '
        grep gitmodulesUrl err
 '
 
+test_expect_success 'fsck rejects embedded newline in git url' '
+       git checkout --orphan git-newline &&
+       cat >.gitmodules <<-\EOF &&
+       [submodule "foo"]
+       url = "git://example.com:1234/repo%0a.git"
+       EOF
+       git add .gitmodules &&
+       git commit -m "git url with newline" &&
+       test_when_finished "rm -rf dst" &&
+       git init --bare dst &&
+       git -C dst config transfer.fsckObjects true &&
+       test_must_fail git push dst HEAD 2>err &&
+       grep gitmodulesUrl err
+'
+
 test_done
index 70afdd06fa7208a20ac66f1eb6e9e3690d5fe528..6ac75b5d4c0a40ca4a6b8ed8a24fed646689b99f 100755 (executable)
@@ -828,4 +828,15 @@ test_expect_success 'mergetool -Oorder-file is honored' '
        test_cmp expect actual
 '
 
+test_expect_success 'mergetool --tool-help shows recognized tools' '
+       # Check a few known tools are correctly shown
+       git mergetool --tool-help >mergetools &&
+       grep vimdiff mergetools &&
+       grep vimdiff3 mergetools &&
+       grep gvimdiff2 mergetools &&
+       grep araxis mergetools &&
+       grep xxdiff mergetools &&
+       grep meld mergetools
+'
+
 test_done
index 999982fe4a9bd6714bf466c59f3627bafe142405..2f08ce7cba57ae59770cf56b06dfed9ffc72253e 100644 (file)
@@ -367,9 +367,14 @@ test_chmod () {
        git update-index --add "--chmod=$@"
 }
 
-# Get the modebits from a file or directory.
+# Get the modebits from a file or directory, ignoring the setgid bit (g+s).
+# This bit is inherited by subdirectories at their creation. So we remove it
+# from the returning string to prevent callers from having to worry about the
+# state of the bit in the test directory.
+#
 test_modebits () {
-       ls -ld "$1" | sed -e 's|^\(..........\).*|\1|'
+       ls -ld "$1" | sed -e 's|^\(..........\).*|\1|' \
+                         -e 's|^\(......\)S|\1-|' -e 's|^\(......\)s|\1x|'
 }
 
 # Unset a configuration variable, but don't fail if it doesn't exist.