aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/CodingGuidelines2
-rw-r--r--Documentation/MyFirstContribution.txt7
-rw-r--r--Documentation/RelNotes/2.42.1.txt88
-rw-r--r--Documentation/RelNotes/2.43.0.txt19
-rw-r--r--Documentation/SubmittingPatches12
-rw-r--r--Documentation/config.txt2
-rw-r--r--Documentation/config/attr.txt7
-rw-r--r--Documentation/config/transfer.txt2
-rw-r--r--Documentation/diff-options.txt4
-rw-r--r--Documentation/git-am.txt4
-rw-r--r--Documentation/git-bisect.txt4
-rw-r--r--Documentation/git-branch.txt2
-rw-r--r--Documentation/git-push.txt2
-rw-r--r--Documentation/git-range-diff.txt2
-rw-r--r--Documentation/git-rebase.txt4
-rw-r--r--Documentation/git-repack.txt9
-rw-r--r--Documentation/git-send-email.txt11
-rw-r--r--Documentation/git.txt6
-rw-r--r--Documentation/gitattributes.txt4
-rw-r--r--Documentation/giteveryday.txt2
-rw-r--r--Documentation/gitk.txt2
-rwxr-xr-xGIT-VERSION-GEN2
-rw-r--r--attr.c21
-rw-r--r--attr.h2
-rw-r--r--builtin/add.c10
-rw-r--r--builtin/am.c114
-rw-r--r--builtin/bisect.c4
-rw-r--r--builtin/branch.c66
-rw-r--r--builtin/commit.c8
-rw-r--r--builtin/grep.c13
-rw-r--r--builtin/rebase.c46
-rw-r--r--builtin/reflog.c6
-rw-r--r--config.c16
-rw-r--r--contrib/README4
-rwxr-xr-xcontrib/git-jump/git-jump2
-rw-r--r--fsmonitor--daemon.h2
-rwxr-xr-xgit-p4.py4
-rwxr-xr-xgit-send-email.perl192
-rw-r--r--merge-ort.c2
-rw-r--r--parse-options.c144
-rw-r--r--parse-options.h3
-rw-r--r--pathspec.c7
-rw-r--r--strbuf.h8
-rw-r--r--t/README33
-rw-r--r--t/helper/test-parse-options.c16
-rwxr-xr-xt/t0003-attributes.sh72
-rwxr-xr-xt/t0040-parse-options.sh33
-rwxr-xr-xt/t1410-reflog.sh23
-rwxr-xr-xt/t2407-worktree-heads.sh2
-rwxr-xr-xt/t3200-branch.sh16
-rwxr-xr-xt/t3202-show-branch.sh10
-rwxr-xr-xt/t5001-archive-attr.sh2
-rwxr-xr-xt/t7601-merge-pull-config.sh24
-rwxr-xr-xt/t7810-grep.sh40
-rwxr-xr-xt/t9001-send-email.sh60
55 files changed, 791 insertions, 411 deletions
diff --git a/Documentation/CodingGuidelines b/Documentation/CodingGuidelines
index c494e07460..8d3a467c01 100644
--- a/Documentation/CodingGuidelines
+++ b/Documentation/CodingGuidelines
@@ -24,7 +24,7 @@ Git in general, a few rough rules are:
"Once it _is_ in the tree, it's not really worth the patch noise to
go and fix it up."
- Cf. http://lkml.iu.edu/hypermail/linux/kernel/1001.3/01069.html
+ Cf. https://lore.kernel.org/all/20100126160632.3bdbe172.akpm@linux-foundation.org/
- Log messages to explain your changes are as important as the
changes themselves. Clearly written code and in-code comments
diff --git a/Documentation/MyFirstContribution.txt b/Documentation/MyFirstContribution.txt
index 62d11a5cd7..7cfed60c2e 100644
--- a/Documentation/MyFirstContribution.txt
+++ b/Documentation/MyFirstContribution.txt
@@ -160,10 +160,11 @@ in order to keep the declarations alphabetically sorted:
int cmd_psuh(int argc, const char **argv, const char *prefix);
----
-Be sure to `#include "builtin.h"` in your `psuh.c`.
+Be sure to `#include "builtin.h"` in your `psuh.c`. You'll also need to
+`#include "gettext.h"` to use functions related to printing output text.
-Go ahead and add some throwaway printf to that function. This is a decent
-starting point as we can now add build rules and register the command.
+Go ahead and add some throwaway printf to the `cmd_psuh` function. This is a
+decent starting point as we can now add build rules and register the command.
NOTE: Your throwaway text, as well as much of the text you will be adding over
the course of this tutorial, is user-facing. That means it needs to be
diff --git a/Documentation/RelNotes/2.42.1.txt b/Documentation/RelNotes/2.42.1.txt
new file mode 100644
index 0000000000..3d391b7dcd
--- /dev/null
+++ b/Documentation/RelNotes/2.42.1.txt
@@ -0,0 +1,88 @@
+Git 2.42.1 Release Notes
+========================
+
+There is nothing exciting to see here. Relative to Git 2.42, this
+release contains the fixes that have already been merged to the
+'master' branch of the development towards Git 2.43 that has been
+tagged as Git 2.43.0-rc0.
+
+Fixes since Git 2.42.0
+----------------------
+
+ * Tests that are known to pass with LSan are now marked as such.
+
+ * Flaky "git p4" tests, as well as "git svn" tests, are now skipped
+ in the (rather expensive) sanitizer CI job.
+
+ * Tests with LSan from time to time seem to emit harmless message
+ that makes our tests unnecessarily flaky; we work it around by
+ filtering the uninteresting output.
+
+ * GitHub CI workflow has learned to trigger Coverity check.
+
+ * Overly long label names used in the sequencer machinery are now
+ chopped to fit under filesystem limitation.
+
+ * Scalar updates.
+
+ * Tweak GitHub Actions CI so that pushing the same commit to multiple
+ branch tips at the same time will not waste building and testing
+ the same thing twice.
+
+ * The commit-graph verification code that detects mixture of zero and
+ non-zero generation numbers has been updated.
+
+ * "git diff -w --exit-code" with various options did not work
+ correctly, which is being addressed.
+
+ * transfer.unpackLimit ought to be used as a fallback, but overrode
+ fetch.unpackLimit and receive.unpackLimit instead.
+
+ * The use of API between two calls to require_clean_work_tree() from
+ the sequencer code has been cleaned up for consistency.
+
+ * "git diff --no-such-option" and other corner cases around the exit
+ status of the "diff" command has been corrected.
+
+ * "git for-each-ref --sort='contents:size'" sorts the refs according
+ to size numerically, giving a ref that points at a blob twelve-byte
+ (12) long before showing a blob hundred-byte (100) long.
+
+ * Various fixes to the behavior of "rebase -i" when the command got
+ interrupted by conflicting changes.
+
+ * References from description of the `--patch` option in various
+ manual pages have been simplified and improved.
+
+ * "git grep -e A --no-or -e B" is accepted, even though the negation
+ of "or" did not mean anything, which has been tightened.
+
+ * The completion script (in contrib/) has been taught to treat the
+ "-t" option to "git checkout" and "git switch" just like the
+ "--track" option, to complete remote-tracking branches.
+
+ * "git diff --no-index -R <(one) <(two)" did not work correctly,
+ which has been corrected.
+
+ * Update "git maintenance" timers' implementation based on systemd
+ timers to work with WSL.
+
+ * "git diff --cached" codepath did not fill the necessary stat
+ information for a file when fsmonitor knows it is clean and ended
+ up behaving as if it is not clean, which has been corrected.
+
+ * Clarify how "alias.foo = : git cmd ; aliased-command-string" should
+ be spelled with necessary whitespaces around punctuation marks to
+ work.
+
+ * HTTP Header redaction code has been adjusted for a newer version of
+ cURL library that shows its traces differently from earlier
+ versions.
+
+ * An error message given by "git send-email" when given a malformed
+ address did not give correct information, which has been corrected.
+
+ * UBSan options were not propagated through the test framework to git
+ run via the httpd, unlike ASan options, which has been corrected.
+
+Also contains various documentation updates, code clean-ups and minor fixups.
diff --git a/Documentation/RelNotes/2.43.0.txt b/Documentation/RelNotes/2.43.0.txt
index a3644aba44..ad3b82fe0a 100644
--- a/Documentation/RelNotes/2.43.0.txt
+++ b/Documentation/RelNotes/2.43.0.txt
@@ -95,6 +95,9 @@ UI, Workflows & Features
* "git log" and friends learned "--dd" that is a short-hand for
"--diff-merges=first-parent -p".
+ * The attribute subsystem learned to honor `attr.tree` configuration
+ that specifies which tree to read the .gitattributes files from.
+
Performance, Internal Implementation, Development Support etc.
@@ -278,6 +281,15 @@ Fixes since v2.42
storing a bogus sd_size value instead for such files.
(merge 5143ac07b1 bc/racy-4gb-files later to maint).
+ * "git p4" tried to store symlinks to LFS when told, but has been
+ fixed not to do so, because it does not make sense.
+ (merge 10c89a02b0 mm/p4-symlink-with-lfs later to maint).
+
+ * The codepath to handle recipient addresses `git send-email
+ --compose` learns from the user was completely broken, which has
+ been corrected.
+ (merge 3ec6167567 jk/send-email-fix-addresses-from-composed-messages later to maint).
+
* Other code cleanup, docfix, build fix, etc.
(merge fd3ba590d8 ws/git-push-doc-grammofix later to maint).
(merge 5f33a843de ds/upload-pack-error-sequence-fix later to maint).
@@ -303,3 +315,10 @@ Fixes since v2.42
(merge badf2fe1c3 jk/decoration-and-other-leak-fixes later to maint).
(merge cebfaaa333 sn/cat-file-doc-update later to maint).
(merge 8b3aa36f5a ps/rewritten-is-per-worktree-doc later to maint).
+ (merge ffbf6a748d jc/update-list-references-to-lore later to maint).
+ (merge 14d569b1a7 jc/am-doc-whitespace-action-fix later to maint).
+ (merge 48399e9cf0 ni/die-message-fix-for-git-add later to maint).
+ (merge ca3285dd69 ps/git-repack-doc-fixes later to maint).
+ (merge 243c79fdc7 wx/merge-ort-comment-typofix later to maint).
+ (merge a060705d94 jc/commit-new-underscore-index-fix later to maint).
+ (merge f6d83e2115 ms/doc-push-fix later to maint).
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index 0e2d3fbb9c..bce7f97815 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -266,7 +266,7 @@ date)", like this:
noticed that ...
....
-The "Copy commit summary" command of gitk can be used to obtain this
+The "Copy commit reference" command of gitk can be used to obtain this
format (with the subject enclosed in a pair of double-quotes), or this
invocation of `git show`:
@@ -393,8 +393,8 @@ mailing list{security-ml}, instead of the public mailing list.
Learn to use format-patch and send-email if possible. These commands
are optimized for the workflow of sending patches, avoiding many ways
-your existing e-mail client that is optimized for "multipart/*" mime
-type e-mails to corrupt and render your patches unusable.
+your existing e-mail client (often optimized for "multipart/*" MIME
+type e-mails) might render your patches unusable.
People on the Git mailing list need to be able to read and
comment on the changes you are submitting. It is important for
@@ -515,8 +515,8 @@ repositories.
git://git.ozlabs.org/~paulus/gitk
- Those who are interested in improve gitk can volunteer to help Paul
- in maintaining it cf. <YntxL/fTplFm8lr6@cleo>.
+ Those who are interested in improving gitk can volunteer to help Paul
+ maintain it, cf. <YntxL/fTplFm8lr6@cleo>.
- `po/` comes from the localization coordinator, Jiang Xin:
@@ -556,7 +556,7 @@ help you find out who they are.
In any time between the (2)-(3) cycle, the maintainer may pick it up
from the list and queue it to `seen`, in order to make it easier for
-people play with it without having to pick up and apply the patch to
+people to play with it without having to pick up and apply the patch to
their trees themselves.
[[patch-status]]
diff --git a/Documentation/config.txt b/Documentation/config.txt
index b1dba1ae85..e3a74dd1c1 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -371,6 +371,8 @@ other popular tools, and describe them in your documentation.
include::config/advice.txt[]
+include::config/attr.txt[]
+
include::config/core.txt[]
include::config/add.txt[]
diff --git a/Documentation/config/attr.txt b/Documentation/config/attr.txt
new file mode 100644
index 0000000000..1a482d6af2
--- /dev/null
+++ b/Documentation/config/attr.txt
@@ -0,0 +1,7 @@
+attr.tree::
+ A reference to a tree in the repository from which to read attributes,
+ instead of the `.gitattributes` file in the working tree. In a bare
+ repository, this defaults to `HEAD:.gitattributes`. If the value does
+ not resolve to a valid tree object, an empty tree is used instead.
+ When the `GIT_ATTR_SOURCE` environment variable or `--attr-source`
+ command line option are used, this configuration variable has no effect.
diff --git a/Documentation/config/transfer.txt b/Documentation/config/transfer.txt
index 55e13428db..a9cbdb88a1 100644
--- a/Documentation/config/transfer.txt
+++ b/Documentation/config/transfer.txt
@@ -21,7 +21,7 @@ exposure, e.g. because:
system.
* The git programs will pass the full URL to one another as arguments
on the command-line, meaning the credentials will be exposed to other
- users on OS's or systems that allow other users to see the full
+ unprivileged users on systems that allow them to see the full
process list of other users. On linux the "hidepid" setting
documented in procfs(5) allows for configuring this behavior.
+
diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt
index 1a75c28bca..53ec3c9a34 100644
--- a/Documentation/diff-options.txt
+++ b/Documentation/diff-options.txt
@@ -76,7 +76,7 @@ off, none::
+
on, m::
Make diff output for merge commits to be shown in the default
- format. The default format could be changed using
+ format. The default format can be changed using
`log.diffMerges` configuration variable, whose default value
is `separate`.
+
@@ -314,7 +314,7 @@ ifndef::git-format-patch[]
-z::
ifdef::git-log[]
- Separate the commits with NULs instead of with new newlines.
+ Separate the commits with NULs instead of newlines.
+
Also, when `--raw` or `--numstat` has been given, do not munge
pathnames and use NULs as output field terminators.
diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt
index 0390dab20f..e080458d6c 100644
--- a/Documentation/git-am.txt
+++ b/Documentation/git-am.txt
@@ -12,7 +12,7 @@ SYNOPSIS
'git am' [--signoff] [--keep] [--[no-]keep-cr] [--[no-]utf8] [--no-verify]
[--[no-]3way] [--interactive] [--committer-date-is-author-date]
[--ignore-date] [--ignore-space-change | --ignore-whitespace]
- [--whitespace=<option>] [-C<n>] [-p<n>] [--directory=<dir>]
+ [--whitespace=<action>] [-C<n>] [-p<n>] [--directory=<dir>]
[--exclude=<path>] [--include=<path>] [--reject] [-q | --quiet]
[--[no-]scissors] [-S[<keyid>]] [--patch-format=<format>]
[--quoted-cr=<action>]
@@ -118,7 +118,7 @@ include::rerere-options.txt[]
--ignore-space-change::
--ignore-whitespace::
---whitespace=<option>::
+--whitespace=<action>::
-C<n>::
-p<n>::
--directory=<dir>::
diff --git a/Documentation/git-bisect.txt b/Documentation/git-bisect.txt
index 7872dba3ae..191b4a42b6 100644
--- a/Documentation/git-bisect.txt
+++ b/Documentation/git-bisect.txt
@@ -16,7 +16,7 @@ DESCRIPTION
The command takes various subcommands, and different options depending
on the subcommand:
- git bisect start [--term-{new,bad}=<term> --term-{old,good}=<term>]
+ git bisect start [--term-(new|bad)=<term-new> --term-(old|good)=<term-old>]
[--no-checkout] [--first-parent] [<bad> [<good>...]] [--] [<paths>...]
git bisect (bad|new|<term-new>) [<rev>]
git bisect (good|old|<term-old>) [<rev>...]
@@ -26,7 +26,7 @@ on the subcommand:
git bisect (visualize|view)
git bisect replay <logfile>
git bisect log
- git bisect run <cmd>...
+ git bisect run <cmd> [<arg>...]
git bisect help
This command uses a binary search algorithm to find which commit in
diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt
index d207da9101..4395aa9354 100644
--- a/Documentation/git-branch.txt
+++ b/Documentation/git-branch.txt
@@ -324,7 +324,7 @@ superproject's "origin/main", but tracks the submodule's "origin/main".
multiple times, in which case the last key becomes the primary
key. The keys supported are the same as those in `git
for-each-ref`. Sort order defaults to the value configured for the
- `branch.sort` variable if exists, or to sorting based on the
+ `branch.sort` variable if it exists, or to sorting based on the
full refname (including `refs/...` prefix). This lists
detached HEAD (if present) first, then local branches and
finally remote-tracking branches. See linkgit:git-config[1].
diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
index c12caedbb1..9b7cfbc5c1 100644
--- a/Documentation/git-push.txt
+++ b/Documentation/git-push.txt
@@ -10,7 +10,7 @@ SYNOPSIS
--------
[verse]
'git push' [--all | --branches | --mirror | --tags] [--follow-tags] [--atomic] [-n | --dry-run] [--receive-pack=<git-receive-pack>]
- [--repo=<repository>] [-f | --force] [-d | --delete] [--prune] [-v | --verbose]
+ [--repo=<repository>] [-f | --force] [-d | --delete] [--prune] [-q | --quiet] [-v | --verbose]
[-u | --set-upstream] [-o <string> | --push-option=<string>]
[--[no-]signed|--signed=(true|false|if-asked)]
[--force-with-lease[=<refname>[:<expect>]] [--force-if-includes]]
diff --git a/Documentation/git-range-diff.txt b/Documentation/git-range-diff.txt
index 605a92e224..fbdbe0befe 100644
--- a/Documentation/git-range-diff.txt
+++ b/Documentation/git-range-diff.txt
@@ -166,7 +166,7 @@ A typical output of `git range-diff` would look like this:
In this example, there are 3 old and 3 new commits, where the developer
removed the 3rd, added a new one before the first two, and modified the
-commit message of the 2nd commit as well its diff.
+commit message of the 2nd commit as well as its diff.
When the output goes to a terminal, it is color-coded by default, just
like regular `git diff`'s output. In addition, the first line (adding a
diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index e7b39ad244..b4526ca246 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -289,7 +289,7 @@ See also INCOMPATIBLE OPTIONS below.
+
See also INCOMPATIBLE OPTIONS below.
---empty={drop,keep,ask}::
+--empty=(drop|keep|ask)::
How to handle commits that are not empty to start and are not
clean cherry-picks of any upstream commit, but which become
empty after rebasing (because they contain a subset of already
@@ -695,7 +695,7 @@ be dropped automatically with `--no-keep-empty`).
Similar to the apply backend, by default the merge backend drops
commits that become empty unless `-i`/`--interactive` is specified (in
which case it stops and asks the user what to do). The merge backend
-also has an `--empty={drop,keep,ask}` option for changing the behavior
+also has an `--empty=(drop|keep|ask)` option for changing the behavior
of handling commits that become empty.
Directory rename detection
diff --git a/Documentation/git-repack.txt b/Documentation/git-repack.txt
index c338329089..c902512a9e 100644
--- a/Documentation/git-repack.txt
+++ b/Documentation/git-repack.txt
@@ -220,7 +220,7 @@ depth is 4095.
Pass the `--delta-islands` option to `git-pack-objects`, see
linkgit:git-pack-objects[1].
--g=<factor>::
+-g<factor>::
--geometric=<factor>::
Arrange resulting pack structure so that each successive pack
contains at least `<factor>` times the number of objects as the
@@ -237,11 +237,8 @@ uniquely by the set of packs being "rolled-up"; in other words, the
packs determined to need to be combined in order to restore a geometric
progression.
+
-When `--unpacked` is specified, loose objects are implicitly included in
-this "roll-up", without respect to their reachability. This is subject
-to change in the future. This option (implying a drastically different
-repack mode) is not guaranteed to work with all other combinations of
-options to `git repack`.
+Loose objects are implicitly included in this "roll-up", without respect to
+their reachability. This is subject to change in the future.
+
When writing a multi-pack bitmap, `git repack` selects the largest resulting
pack as the preferred pack for object selection by the MIDX (see
diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt
index e90d041817..465011bad5 100644
--- a/Documentation/git-send-email.txt
+++ b/Documentation/git-send-email.txt
@@ -68,11 +68,12 @@ This option may be specified multiple times.
Invoke a text editor (see GIT_EDITOR in linkgit:git-var[1])
to edit an introductory message for the patch series.
+
-When `--compose` is used, git send-email will use the From, Subject, and
-In-Reply-To headers specified in the message. If the body of the message
-(what you type after the headers and a blank line) only contains blank
-(or Git: prefixed) lines, the summary won't be sent, but From, Subject,
-and In-Reply-To headers will be used unless they are removed.
+When `--compose` is used, git send-email will use the From, To, Cc, Bcc,
+Subject, Reply-To, and In-Reply-To headers specified in the message. If
+the body of the message (what you type after the headers and a blank
+line) only contains blank (or Git: prefixed) lines, the summary won't be
+sent, but the headers mentioned above will be used unless they are
+removed.
+
Missing From or In-Reply-To headers will be prompted for.
+
diff --git a/Documentation/git.txt b/Documentation/git.txt
index 11228956cd..9aeabde262 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -96,9 +96,9 @@ foo.bar= ...`) sets `foo.bar` to the empty string which `git config
to avoid ambiguity with `<name>` containing one.
+
This is useful for cases where you want to pass transitory
-configuration options to git, but are doing so on OS's where
-other processes might be able to read your cmdline
-(e.g. `/proc/self/cmdline`), but not your environ
+configuration options to git, but are doing so on operating systems
+where other processes might be able to read your command line
+(e.g. `/proc/self/cmdline`), but not your environment
(e.g. `/proc/self/environ`). That behavior is the default on
Linux, but may not be on your system.
+
diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt
index 6deb89a296..8c1793c148 100644
--- a/Documentation/gitattributes.txt
+++ b/Documentation/gitattributes.txt
@@ -1151,8 +1151,8 @@ will be stored via placeholder `%P`.
^^^^^^^^^^^^^^^^^^^^^^
This attribute controls the length of conflict markers left in
-the work tree file during a conflicted merge. Only setting to
-the value to a positive integer has any meaningful effect.
+the work tree file during a conflicted merge. Only a positive
+integer has a meaningful effect.
For example, this line in `.gitattributes` can be used to tell the merge
machinery to leave much longer (instead of the usual 7-character-long)
diff --git a/Documentation/giteveryday.txt b/Documentation/giteveryday.txt
index 12b62b9125..6cfdd0e07b 100644
--- a/Documentation/giteveryday.txt
+++ b/Documentation/giteveryday.txt
@@ -229,7 +229,7 @@ without a formal "merging". Or longhand +
git am -3 -k`
An alternate participant submission mechanism is using the
-`git request-pull` or pull-request mechanisms (e.g as used on
+`git request-pull` or pull-request mechanisms (e.g. as used on
GitHub (www.github.com) to notify your upstream of your
contribution.
diff --git a/Documentation/gitk.txt b/Documentation/gitk.txt
index d50e9ed10e..c2213bb77b 100644
--- a/Documentation/gitk.txt
+++ b/Documentation/gitk.txt
@@ -26,7 +26,7 @@ changes each commit introduces are shown. Finally, it supports some
gitk-specific options.
gitk generally only understands options with arguments in the
-'sticked' form (see linkgit:gitcli[7]) due to limitations in the
+'stuck' form (see linkgit:gitcli[7]) due to limitations in the
command-line parser.
rev-list options and arguments
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index 9f0307d364..7e71bb3800 100755
--- a/GIT-VERSION-GEN
+++ b/GIT-VERSION-GEN
@@ -1,7 +1,7 @@
#!/bin/sh
GVF=GIT-VERSION-FILE
-DEF_VER=v2.42.GIT
+DEF_VER=v2.43.0-rc0
LF='
'
diff --git a/attr.c b/attr.c
index 3c0b4fb3d9..e62876dfd3 100644
--- a/attr.c
+++ b/attr.c
@@ -7,7 +7,7 @@
*/
#include "git-compat-util.h"
-#include "parse.h"
+#include "config.h"
#include "environment.h"
#include "exec-cmd.h"
#include "attr.h"
@@ -24,6 +24,8 @@
#include "tree-walk.h"
#include "object-name.h"
+const char *git_attr_tree;
+
const char git_attr__true[] = "(builtin)true";
const char git_attr__false[] = "\0(builtin)false";
static const char git_attr__unknown[] = "(builtin)unknown";
@@ -1194,6 +1196,7 @@ static void collect_some_attrs(struct index_state *istate,
}
static const char *default_attr_source_tree_object_name;
+static int ignore_bad_attr_tree;
void set_git_attr_source(const char *tree_object_name)
{
@@ -1205,10 +1208,24 @@ static void compute_default_attr_source(struct object_id *attr_source)
if (!default_attr_source_tree_object_name)
default_attr_source_tree_object_name = getenv(GIT_ATTR_SOURCE_ENVIRONMENT);
+ if (!default_attr_source_tree_object_name && git_attr_tree) {
+ default_attr_source_tree_object_name = git_attr_tree;
+ ignore_bad_attr_tree = 1;
+ }
+
+ if (!default_attr_source_tree_object_name &&
+ startup_info->have_repository &&
+ is_bare_repository()) {
+ default_attr_source_tree_object_name = "HEAD";
+ ignore_bad_attr_tree = 1;
+ }
+
if (!default_attr_source_tree_object_name || !is_null_oid(attr_source))
return;
- if (repo_get_oid_treeish(the_repository, default_attr_source_tree_object_name, attr_source))
+ if (repo_get_oid_treeish(the_repository,
+ default_attr_source_tree_object_name,
+ attr_source) && !ignore_bad_attr_tree)
die(_("bad --attr-source or GIT_ATTR_SOURCE"));
}
diff --git a/attr.h b/attr.h
index 2b745df405..127998ae01 100644
--- a/attr.h
+++ b/attr.h
@@ -236,4 +236,6 @@ const char *git_attr_global_file(void);
/* Return whether the system gitattributes file is enabled and should be used. */
int git_attr_system_is_enabled(void);
+extern const char *git_attr_tree;
+
#endif /* ATTR_H */
diff --git a/builtin/add.c b/builtin/add.c
index c27254a5cd..5126d2ede3 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -182,7 +182,7 @@ static int edit_patch(int argc, const char **argv, const char *prefix)
git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
if (repo_read_index(the_repository) < 0)
- die(_("Could not read the index"));
+ die(_("could not read the index"));
repo_init_revisions(the_repository, &rev, prefix);
rev.diffopt.context = 7;
@@ -200,15 +200,15 @@ static int edit_patch(int argc, const char **argv, const char *prefix)
die(_("editing patch failed"));
if (stat(file, &st))
- die_errno(_("Could not stat '%s'"), file);
+ die_errno(_("could not stat '%s'"), file);
if (!st.st_size)
- die(_("Empty patch. Aborted."));
+ die(_("empty patch. aborted"));
child.git_cmd = 1;
strvec_pushl(&child.args, "apply", "--recount", "--cached", file,
NULL);
if (run_command(&child))
- die(_("Could not apply '%s'"), file);
+ die(_("could not apply '%s'"), file);
unlink(file);
free(file);
@@ -568,7 +568,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
finish:
if (write_locked_index(&the_index, &lock_file,
COMMIT_LOCK | SKIP_IF_UNCHANGED))
- die(_("Unable to write new index file"));
+ die(_("unable to write new index file"));
dir_clear(&dir);
clear_pathspec(&pathspec);
diff --git a/builtin/am.c b/builtin/am.c
index 6655059a57..9f084d58bc 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -92,9 +92,16 @@ enum signoff_type {
SIGNOFF_EXPLICIT /* --signoff was set on the command-line */
};
-enum show_patch_type {
- SHOW_PATCH_RAW = 0,
- SHOW_PATCH_DIFF = 1,
+enum resume_type {
+ RESUME_FALSE = 0,
+ RESUME_APPLY,
+ RESUME_RESOLVED,
+ RESUME_SKIP,
+ RESUME_ABORT,
+ RESUME_QUIT,
+ RESUME_SHOW_PATCH_RAW,
+ RESUME_SHOW_PATCH_DIFF,
+ RESUME_ALLOW_EMPTY,
};
enum empty_action {
@@ -2191,7 +2198,7 @@ static void am_abort(struct am_state *state)
am_destroy(state);
}
-static int show_patch(struct am_state *state, enum show_patch_type sub_mode)
+static int show_patch(struct am_state *state, enum resume_type resume_mode)
{
struct strbuf sb = STRBUF_INIT;
const char *patch_path;
@@ -2206,11 +2213,11 @@ static int show_patch(struct am_state *state, enum show_patch_type sub_mode)
return run_command(&cmd);
}
- switch (sub_mode) {
- case SHOW_PATCH_RAW:
+ switch (resume_mode) {
+ case RESUME_SHOW_PATCH_RAW:
patch_path = am_path(state, msgnum(state));
break;
- case SHOW_PATCH_DIFF:
+ case RESUME_SHOW_PATCH_DIFF:
patch_path = am_path(state, "patch");
break;
default:
@@ -2257,57 +2264,25 @@ static int parse_opt_patchformat(const struct option *opt, const char *arg, int
return 0;
}
-enum resume_type {
- RESUME_FALSE = 0,
- RESUME_APPLY,
- RESUME_RESOLVED,
- RESUME_SKIP,
- RESUME_ABORT,
- RESUME_QUIT,
- RESUME_SHOW_PATCH,
- RESUME_ALLOW_EMPTY,
-};
-
-struct resume_mode {
- enum resume_type mode;
- enum show_patch_type sub_mode;
-};
-
static int parse_opt_show_current_patch(const struct option *opt, const char *arg, int unset)
{
int *opt_value = opt->value;
- struct resume_mode *resume = container_of(opt_value, struct resume_mode, mode);
+ BUG_ON_OPT_NEG(unset);
+
+ if (!arg)
+ *opt_value = opt->defval;
+ else if (!strcmp(arg, "raw"))
+ *opt_value = RESUME_SHOW_PATCH_RAW;
+ else if (!strcmp(arg, "diff"))
+ *opt_value = RESUME_SHOW_PATCH_DIFF;
/*
* Please update $__git_showcurrentpatch in git-completion.bash
* when you add new options
*/
- const char *valid_modes[] = {
- [SHOW_PATCH_DIFF] = "diff",
- [SHOW_PATCH_RAW] = "raw"
- };
- int new_value = SHOW_PATCH_RAW;
-
- BUG_ON_OPT_NEG(unset);
-
- if (arg) {
- for (new_value = 0; new_value < ARRAY_SIZE(valid_modes); new_value++) {
- if (!strcmp(arg, valid_modes[new_value]))
- break;
- }
- if (new_value >= ARRAY_SIZE(valid_modes))
- return error(_("invalid value for '%s': '%s'"),
- "--show-current-patch", arg);
- }
-
- if (resume->mode == RESUME_SHOW_PATCH && new_value != resume->sub_mode)
- return error(_("options '%s=%s' and '%s=%s' "
- "cannot be used together"),
- "--show-current-patch", arg,
- "--show-current-patch", valid_modes[resume->sub_mode]);
-
- resume->mode = RESUME_SHOW_PATCH;
- resume->sub_mode = new_value;
+ else
+ return error(_("invalid value for '%s': '%s'"),
+ "--show-current-patch", arg);
return 0;
}
@@ -2317,7 +2292,7 @@ int cmd_am(int argc, const char **argv, const char *prefix)
int binary = -1;
int keep_cr = -1;
int patch_format = PATCH_FORMAT_UNKNOWN;
- struct resume_mode resume = { .mode = RESUME_FALSE };
+ enum resume_type resume_mode = RESUME_FALSE;
int in_progress;
int ret = 0;
@@ -2388,27 +2363,27 @@ int cmd_am(int argc, const char **argv, const char *prefix)
PARSE_OPT_NOARG),
OPT_STRING(0, "resolvemsg", &state.resolvemsg, NULL,
N_("override error message when patch failure occurs")),
- OPT_CMDMODE(0, "continue", &resume.mode,
+ OPT_CMDMODE(0, "continue", &resume_mode,
N_("continue applying patches after resolving a conflict"),
RESUME_RESOLVED),
- OPT_CMDMODE('r', "resolved", &resume.mode,
+ OPT_CMDMODE('r', "resolved", &resume_mode,
N_("synonyms for --continue"),
RESUME_RESOLVED),
- OPT_CMDMODE(0, "skip", &resume.mode,
+ OPT_CMDMODE(0, "skip", &resume_mode,
N_("skip the current patch"),
RESUME_SKIP),
- OPT_CMDMODE(0, "abort", &resume.mode,
+ OPT_CMDMODE(0, "abort", &resume_mode,
N_("restore the original branch and abort the patching operation"),
RESUME_ABORT),
- OPT_CMDMODE(0, "quit", &resume.mode,
+ OPT_CMDMODE(0, "quit", &resume_mode,
N_("abort the patching operation but keep HEAD where it is"),
RESUME_QUIT),
- { OPTION_CALLBACK, 0, "show-current-patch", &resume.mode,
+ { OPTION_CALLBACK, 0, "show-current-patch", &resume_mode,
"(diff|raw)",
N_("show the patch being applied"),
PARSE_OPT_CMDMODE | PARSE_OPT_OPTARG | PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP,
- parse_opt_show_current_patch, RESUME_SHOW_PATCH },
- OPT_CMDMODE(0, "allow-empty", &resume.mode,
+ parse_opt_show_current_patch, RESUME_SHOW_PATCH_RAW },
+ OPT_CMDMODE(0, "allow-empty", &resume_mode,
N_("record the empty patch as an empty commit"),
RESUME_ALLOW_EMPTY),
OPT_BOOL(0, "committer-date-is-author-date",
@@ -2420,7 +2395,7 @@ int cmd_am(int argc, const char **argv, const char *prefix)
{ OPTION_STRING, 'S', "gpg-sign", &state.sign_commit, N_("key-id"),
N_("GPG-sign commits"),
PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
- OPT_CALLBACK_F(STOP_ON_EMPTY_COMMIT, "empty", &state.empty_type, "{stop,drop,keep}",
+ OPT_CALLBACK_F(0, "empty", &state.empty_type, "(stop|drop|keep)",
N_("how to handle empty patches"),
PARSE_OPT_NONEG, am_option_parse_empty),
OPT_HIDDEN_BOOL(0, "rebasing", &state.rebasing,
@@ -2463,12 +2438,12 @@ int cmd_am(int argc, const char **argv, const char *prefix)
* intend to feed us a patch but wanted to continue
* unattended.
*/
- if (argc || (resume.mode == RESUME_FALSE && !isatty(0)))
+ if (argc || (resume_mode == RESUME_FALSE && !isatty(0)))
die(_("previous rebase directory %s still exists but mbox given."),
state.dir);
- if (resume.mode == RESUME_FALSE)
- resume.mode = RESUME_APPLY;
+ if (resume_mode == RESUME_FALSE)
+ resume_mode = RESUME_APPLY;
if (state.signoff == SIGNOFF_EXPLICIT)
am_append_signoff(&state);
@@ -2482,7 +2457,7 @@ int cmd_am(int argc, const char **argv, const char *prefix)
* stray directories.
*/
if (file_exists(state.dir) && !state.rebasing) {
- if (resume.mode == RESUME_ABORT || resume.mode == RESUME_QUIT) {
+ if (resume_mode == RESUME_ABORT || resume_mode == RESUME_QUIT) {
am_destroy(&state);
am_state_release(&state);
return 0;
@@ -2493,7 +2468,7 @@ int cmd_am(int argc, const char **argv, const char *prefix)
state.dir);
}
- if (resume.mode)
+ if (resume_mode)
die(_("Resolve operation not in progress, we are not resuming."));
for (i = 0; i < argc; i++) {
@@ -2511,7 +2486,7 @@ int cmd_am(int argc, const char **argv, const char *prefix)
strvec_clear(&paths);
}
- switch (resume.mode) {
+ switch (resume_mode) {
case RESUME_FALSE:
am_run(&state, 0);
break;
@@ -2520,7 +2495,7 @@ int cmd_am(int argc, const char **argv, const char *prefix)
break;
case RESUME_RESOLVED:
case RESUME_ALLOW_EMPTY:
- am_resolve(&state, resume.mode == RESUME_ALLOW_EMPTY ? 1 : 0);
+ am_resolve(&state, resume_mode == RESUME_ALLOW_EMPTY ? 1 : 0);
break;
case RESUME_SKIP:
am_skip(&state);
@@ -2532,8 +2507,9 @@ int cmd_am(int argc, const char **argv, const char *prefix)
am_rerere_clear();
am_destroy(&state);
break;
- case RESUME_SHOW_PATCH:
- ret = show_patch(&state, resume.sub_mode);
+ case RESUME_SHOW_PATCH_RAW:
+ case RESUME_SHOW_PATCH_DIFF:
+ ret = show_patch(&state, resume_mode);
break;
default:
BUG("invalid resume value");
diff --git a/builtin/bisect.c b/builtin/bisect.c
index 65478ef40f..35938b05fd 100644
--- a/builtin/bisect.c
+++ b/builtin/bisect.c
@@ -26,7 +26,7 @@ static GIT_PATH_FUNC(git_path_bisect_first_parent, "BISECT_FIRST_PARENT")
static GIT_PATH_FUNC(git_path_bisect_run, "BISECT_RUN")
#define BUILTIN_GIT_BISECT_START_USAGE \
- N_("git bisect start [--term-{new,bad}=<term> --term-{old,good}=<term>]" \
+ N_("git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>]" \
" [--no-checkout] [--first-parent] [<bad> [<good>...]] [--]" \
" [<pathspec>...]")
#define BUILTIN_GIT_BISECT_STATE_USAGE \
@@ -46,7 +46,7 @@ static GIT_PATH_FUNC(git_path_bisect_run, "BISECT_RUN")
#define BUILTIN_GIT_BISECT_LOG_USAGE \
"git bisect log"
#define BUILTIN_GIT_BISECT_RUN_USAGE \
- N_("git bisect run <cmd>...")
+ N_("git bisect run <cmd> [<arg>...]")
static const char * const git_bisect_usage[] = {
BUILTIN_GIT_BISECT_START_USAGE,
diff --git a/builtin/branch.c b/builtin/branch.c
index 2ec190b14a..e7ee9bd0f1 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -173,11 +173,11 @@ static int branch_merged(int kind, const char *name,
(head_rev ? repo_in_merge_bases(the_repository, rev, head_rev) : 0) != merged) {
if (merged)
warning(_("deleting branch '%s' that has been merged to\n"
- " '%s', but not yet merged to HEAD."),
+ " '%s', but not yet merged to HEAD"),
name, reference_name);
else
warning(_("not deleting branch '%s' that is not yet merged to\n"
- " '%s', even though it is merged to HEAD."),
+ " '%s', even though it is merged to HEAD"),
name, reference_name);
}
free(reference_name_to_free);
@@ -190,13 +190,13 @@ static int check_branch_commit(const char *branchname, const char *refname,
{
struct commit *rev = lookup_commit_reference(the_repository, oid);
if (!force && !rev) {
- error(_("Couldn't look up commit object for '%s'"), refname);
+ error(_("couldn't look up commit object for '%s'"), refname);
return -1;
}
if (!force && !branch_merged(kinds, branchname, rev, head_rev)) {
- error(_("The branch '%s' is not fully merged.\n"
+ error(_("the branch '%s' is not fully merged.\n"
"If you are sure you want to delete it, "
- "run 'git branch -D %s'."), branchname, branchname);
+ "run 'git branch -D %s'"), branchname, branchname);
return -1;
}
return 0;
@@ -207,7 +207,7 @@ static void delete_branch_config(const char *branchname)
struct strbuf buf = STRBUF_INIT;
strbuf_addf(&buf, "branch.%s", branchname);
if (git_config_rename_section(buf.buf, NULL) < 0)
- warning(_("Update of config-file failed"));
+ warning(_("update of config-file failed"));
strbuf_release(&buf);
}
@@ -260,7 +260,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
if (kinds == FILTER_REFS_BRANCHES) {
const char *path;
if ((path = branch_checked_out(name))) {
- error(_("Cannot delete branch '%s' "
+ error(_("cannot delete branch '%s' "
"used by worktree at '%s'"),
bname.buf, path);
ret = 1;
@@ -275,7 +275,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
&oid, &flags);
if (!target) {
if (remote_branch) {
- error(_("remote-tracking branch '%s' not found."), bname.buf);
+ error(_("remote-tracking branch '%s' not found"), bname.buf);
} else {
char *virtual_name = mkpathdup(fmt_remotes, bname.buf);
char *virtual_target = resolve_refdup(virtual_name,
@@ -290,7 +290,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
"Did you forget --remote?"),
bname.buf);
else
- error(_("branch '%s' not found."), bname.buf);
+ error(_("branch '%s' not found"), bname.buf);
FREE_AND_NULL(virtual_target);
}
ret = 1;
@@ -518,11 +518,11 @@ static void reject_rebase_or_bisect_branch(struct worktree **worktrees,
continue;
if (is_worktree_being_rebased(wt, target))
- die(_("Branch %s is being rebased at %s"),
+ die(_("branch %s is being rebased at %s"),
target, wt->path);
if (is_worktree_being_bisected(wt, target))
- die(_("Branch %s is being bisected at %s"),
+ die(_("branch %s is being bisected at %s"),
target, wt->path);
}
}
@@ -578,7 +578,7 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int
if (ref_exists(oldref.buf))
recovery = 1;
else
- die(_("Invalid branch name: '%s'"), oldname);
+ die(_("invalid branch name: '%s'"), oldname);
}
for (int i = 0; worktrees[i]; i++) {
@@ -594,9 +594,9 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int
if ((copy || !(oldref_usage & IS_HEAD)) && !ref_exists(oldref.buf)) {
if (oldref_usage & IS_HEAD)
- die(_("No commit on branch '%s' yet."), oldname);
+ die(_("no commit on branch '%s' yet"), oldname);
else
- die(_("No branch named '%s'."), oldname);
+ die(_("no branch named '%s'"), oldname);
}
/*
@@ -624,32 +624,32 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int
if (!copy && !(oldref_usage & IS_ORPHAN) &&
rename_ref(oldref.buf, newref.buf, logmsg.buf))
- die(_("Branch rename failed"));
+ die(_("branch rename failed"));
if (copy && copy_existing_ref(oldref.buf, newref.buf, logmsg.buf))
- die(_("Branch copy failed"));
+ die(_("branch copy failed"));
if (recovery) {
if (copy)
- warning(_("Created a copy of a misnamed branch '%s'"),
+ warning(_("created a copy of a misnamed branch '%s'"),
interpreted_oldname);
else
- warning(_("Renamed a misnamed branch '%s' away"),
+ warning(_("renamed a misnamed branch '%s' away"),
interpreted_oldname);
}
if (!copy && (oldref_usage & IS_HEAD) &&
replace_each_worktree_head_symref(worktrees, oldref.buf, newref.buf,
logmsg.buf))
- die(_("Branch renamed to %s, but HEAD is not updated!"), newname);
+ die(_("branch renamed to %s, but HEAD is not updated"), newname);
strbuf_release(&logmsg);
strbuf_addf(&oldsection, "branch.%s", interpreted_oldname);
strbuf_addf(&newsection, "branch.%s", interpreted_newname);
if (!copy && git_config_rename_section(oldsection.buf, newsection.buf) < 0)
- die(_("Branch is renamed, but update of config-file failed"));
+ die(_("branch is renamed, but update of config-file failed"));
if (copy && strcmp(interpreted_oldname, interpreted_newname) && git_config_copy_section(oldsection.buf, newsection.buf) < 0)
- die(_("Branch is copied, but update of config-file failed"));
+ die(_("branch is copied, but update of config-file failed"));
strbuf_release(&oldref);
strbuf_release(&newref);
strbuf_release(&oldsection);
@@ -773,7 +773,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
head = resolve_refdup("HEAD", 0, &head_oid, NULL);
if (!head)
- die(_("Failed to resolve HEAD as a valid ref."));
+ die(_("failed to resolve HEAD as a valid ref"));
if (!strcmp(head, "HEAD"))
filter.detached = 1;
else if (!skip_prefix(head, "refs/heads/", &head))
@@ -866,7 +866,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
if (!argc) {
if (filter.detached)
- die(_("Cannot give description to detached HEAD"));
+ die(_("cannot give description to detached HEAD"));
branch_name = head;
} else if (argc == 1) {
strbuf_branchname(&buf, argv[0], INTERPRET_BRANCH_LOCAL);
@@ -878,8 +878,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
strbuf_addf(&branch_ref, "refs/heads/%s", branch_name);
if (!ref_exists(branch_ref.buf))
error((!argc || branch_checked_out(branch_ref.buf))
- ? _("No commit on branch '%s' yet.")
- : _("No branch named '%s'."),
+ ? _("no commit on branch '%s' yet")
+ : _("no branch named '%s'"),
branch_name);
else if (!edit_branch_description(branch_name))
ret = 0; /* happy */
@@ -892,8 +892,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
if (!argc)
die(_("branch name required"));
else if ((argc == 1) && filter.detached)
- die(copy? _("cannot copy the current branch while not on any.")
- : _("cannot rename the current branch while not on any."));
+ die(copy? _("cannot copy the current branch while not on any")
+ : _("cannot rename the current branch while not on any"));
else if (argc == 1)
copy_or_rename_branch(head, argv[0], copy, copy + rename > 1);
else if (argc == 2)
@@ -916,14 +916,14 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
if (!branch) {
if (!argc || !strcmp(argv[0], "HEAD"))
die(_("could not set upstream of HEAD to %s when "
- "it does not point to any branch."),
+ "it does not point to any branch"),
new_upstream);
die(_("no such branch '%s'"), argv[0]);
}
if (!ref_exists(branch->refname)) {
if (!argc || branch_checked_out(branch->refname))
- die(_("No commit on branch '%s' yet."), branch->name);
+ die(_("no commit on branch '%s' yet"), branch->name);
die(_("branch '%s' does not exist"), branch->name);
}
@@ -946,12 +946,12 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
if (!branch) {
if (!argc || !strcmp(argv[0], "HEAD"))
die(_("could not unset upstream of HEAD when "
- "it does not point to any branch."));
+ "it does not point to any branch"));
die(_("no such branch '%s'"), argv[0]);
}
if (!branch_has_merge_config(branch))
- die(_("Branch '%s' has no upstream information"), branch->name);
+ die(_("branch '%s' has no upstream information"), branch->name);
strbuf_reset(&buf);
strbuf_addf(&buf, "branch.%s.remote", branch->name);
@@ -965,11 +965,11 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
const char *start_name = argc == 2 ? argv[1] : head;
if (filter.kind != FILTER_REFS_BRANCHES)
- die(_("The -a, and -r, options to 'git branch' do not take a branch name.\n"
+ die(_("the -a, and -r, options to 'git branch' do not take a branch name.\n"
"Did you mean to use: -a|-r --list <pattern>?"));
if (track == BRANCH_TRACK_OVERRIDE)
- die(_("the '--set-upstream' option is no longer supported. Please use '--track' or '--set-upstream-to' instead."));
+ die(_("the '--set-upstream' option is no longer supported. Please use '--track' or '--set-upstream-to' instead"));
if (recurse_submodules) {
create_branches_recursively(the_repository, branch_name,
diff --git a/builtin/commit.c b/builtin/commit.c
index 7da5f92448..781af2e206 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -455,7 +455,7 @@ static const char *prepare_index(const char **argv, const char *prefix,
refresh_cache_or_die(refresh_flags);
cache_tree_update(&the_index, WRITE_TREE_SILENT);
if (write_locked_index(&the_index, &index_lock, 0))
- die(_("unable to write new_index file"));
+ die(_("unable to write new index file"));
commit_style = COMMIT_NORMAL;
ret = get_lock_file_path(&index_lock);
goto out;
@@ -479,7 +479,7 @@ static const char *prepare_index(const char **argv, const char *prefix,
cache_tree_update(&the_index, WRITE_TREE_SILENT);
if (write_locked_index(&the_index, &index_lock,
COMMIT_LOCK | SKIP_IF_UNCHANGED))
- die(_("unable to write new_index file"));
+ die(_("unable to write new index file"));
commit_style = COMMIT_AS_IS;
ret = get_index_file();
goto out;
@@ -527,7 +527,7 @@ static const char *prepare_index(const char **argv, const char *prefix,
refresh_index(&the_index, REFRESH_QUIET, NULL, NULL, NULL);
cache_tree_update(&the_index, WRITE_TREE_SILENT);
if (write_locked_index(&the_index, &index_lock, 0))
- die(_("unable to write new_index file"));
+ die(_("unable to write new index file"));
hold_lock_file_for_update(&false_lock,
git_path("next-index-%"PRIuMAX,
@@ -1862,7 +1862,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
if (commit_index_files())
die(_("repository has been updated, but unable to write\n"
- "new_index file. Check that disk is not full and quota is\n"
+ "new index file. Check that disk is not full and quota is\n"
"not exceeded, and then \"git restore --staged :/\" to recover."));
git_test_write_commit_graph_or_die();
diff --git a/builtin/grep.c b/builtin/grep.c
index b71222330a..fe78d4c98b 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -4,6 +4,7 @@
* Copyright (c) 2006 Junio C Hamano
*/
#include "builtin.h"
+#include "abspath.h"
#include "gettext.h"
#include "hex.h"
#include "repository.h"
@@ -812,14 +813,20 @@ static int file_callback(const struct option *opt, const char *arg, int unset)
{
struct grep_opt *grep_opt = opt->value;
int from_stdin;
+ const char *filename = arg;
FILE *patterns;
int lno = 0;
struct strbuf sb = STRBUF_INIT;
BUG_ON_OPT_NEG(unset);
- from_stdin = !strcmp(arg, "-");
- patterns = from_stdin ? stdin : fopen(arg, "r");
+ if (!*filename)
+ ; /* leave it as-is */
+ else
+ filename = prefix_filename_except_for_dash(grep_prefix, filename);
+
+ from_stdin = !strcmp(filename, "-");
+ patterns = from_stdin ? stdin : fopen(filename, "r");
if (!patterns)
die_errno(_("cannot open '%s'"), arg);
while (strbuf_getline(&sb, patterns) == 0) {
@@ -833,6 +840,8 @@ static int file_callback(const struct option *opt, const char *arg, int unset)
if (!from_stdin)
fclose(patterns);
strbuf_release(&sb);
+ if (filename != arg)
+ free((void *)filename);
return 0;
}
diff --git a/builtin/rebase.c b/builtin/rebase.c
index f990811614..043c65dccd 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -376,20 +376,6 @@ static int run_sequencer_rebase(struct rebase_options *opts)
return ret;
}
-static void imply_merge(struct rebase_options *opts, const char *option);
-static int parse_opt_keep_empty(const struct option *opt, const char *arg,
- int unset)
-{
- struct rebase_options *opts = opt->value;
-
- BUG_ON_OPT_ARG(arg);
-
- imply_merge(opts, unset ? "--no-keep-empty" : "--keep-empty");
- opts->keep_empty = !unset;
- opts->type = REBASE_MERGE;
- return 0;
-}
-
static int is_merge(struct rebase_options *opts)
{
return opts->type == REBASE_MERGE;
@@ -983,6 +969,18 @@ static enum empty_type parse_empty_value(const char *value)
die(_("unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and \"ask\"."), value);
}
+static int parse_opt_keep_empty(const struct option *opt, const char *arg,
+ int unset)
+{
+ struct rebase_options *opts = opt->value;
+
+ BUG_ON_OPT_ARG(arg);
+
+ imply_merge(opts, unset ? "--no-keep-empty" : "--keep-empty");
+ opts->keep_empty = !unset;
+ return 0;
+}
+
static int parse_opt_empty(const struct option *opt, const char *arg, int unset)
{
struct rebase_options *options = opt->value;
@@ -1147,7 +1145,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
"instead of ignoring them"),
1, PARSE_OPT_HIDDEN),
OPT_RERERE_AUTOUPDATE(&options.allow_rerere_autoupdate),
- OPT_CALLBACK_F(0, "empty", &options, "{drop,keep,ask}",
+ OPT_CALLBACK_F(0, "empty", &options, "(drop|keep|ask)",
N_("how to handle commits that become empty"),
PARSE_OPT_NONEG, parse_opt_empty),
OPT_CALLBACK_F('k', "keep-empty", &options, NULL,
@@ -1491,23 +1489,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
if (options.strategy) {
options.strategy = xstrdup(options.strategy);
- switch (options.type) {
- case REBASE_APPLY:
- die(_("--strategy requires --merge or --interactive"));
- case REBASE_MERGE:
- /* compatible */
- break;
- case REBASE_UNSPECIFIED:
- options.type = REBASE_MERGE;
- break;
- default:
- BUG("unhandled rebase type (%d)", options.type);
- }
+ imply_merge(&options, "--strategy");
}
- if (options.type == REBASE_MERGE)
- imply_merge(&options, "--merge");
-
if (options.root && !options.onto_name)
imply_merge(&options, "--root without --onto");
@@ -1552,7 +1536,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
if (options.type == REBASE_UNSPECIFIED) {
if (!strcmp(options.default_backend, "merge"))
- imply_merge(&options, "--merge");
+ options.type = REBASE_MERGE;
else if (!strcmp(options.default_backend, "apply"))
options.type = REBASE_APPLY;
else
diff --git a/builtin/reflog.c b/builtin/reflog.c
index df63a5892e..21337292f5 100644
--- a/builtin/reflog.c
+++ b/builtin/reflog.c
@@ -243,7 +243,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
{
struct cmd_reflog_expire_cb cmd = { 0 };
timestamp_t now = time(NULL);
- int i, status, do_all, all_worktrees = 1;
+ int i, status, do_all, single_worktree = 0;
unsigned int flags = 0;
int verbose = 0;
reflog_expiry_should_prune_fn *should_prune_fn = should_expire_reflog_ent;
@@ -268,7 +268,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
OPT_BOOL(0, "stale-fix", &cmd.stalefix,
N_("prune any reflog entries that point to broken commits")),
OPT_BOOL(0, "all", &do_all, N_("process the reflogs of all references")),
- OPT_BOOL(1, "single-worktree", &all_worktrees,
+ OPT_BOOL(0, "single-worktree", &single_worktree,
N_("limits processing to reflogs from the current worktree only")),
OPT_END()
};
@@ -318,7 +318,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
worktrees = get_worktrees();
for (p = worktrees; *p; p++) {
- if (!all_worktrees && !(*p)->is_current)
+ if (single_worktree && !(*p)->is_current)
continue;
collected.worktree = *p;
refs_for_each_reflog(get_worktree_ref_store(*p),
diff --git a/config.c b/config.c
index f9a1cca4e8..b330c7adb4 100644
--- a/config.c
+++ b/config.c
@@ -19,6 +19,7 @@
#include "repository.h"
#include "lockfile.h"
#include "mailmap.h"
+#include "attr.h"
#include "exec-cmd.h"
#include "strbuf.h"
#include "quote.h"
@@ -1760,6 +1761,18 @@ static int git_default_mailmap_config(const char *var, const char *value)
return 0;
}
+static int git_default_attr_config(const char *var, const char *value)
+{
+ if (!strcmp(var, "attr.tree"))
+ return git_config_string(&git_attr_tree, var, value);
+
+ /*
+ * Add other attribute related config variables here and to
+ * Documentation/config/attr.txt.
+ */
+ return 0;
+}
+
int git_default_config(const char *var, const char *value,
const struct config_context *ctx, void *cb)
{
@@ -1783,6 +1796,9 @@ int git_default_config(const char *var, const char *value,
if (starts_with(var, "mailmap."))
return git_default_mailmap_config(var, value);
+ if (starts_with(var, "attr."))
+ return git_default_attr_config(var, value);
+
if (starts_with(var, "advice.") || starts_with(var, "color.advice"))
return git_default_advice_config(var, value);
diff --git a/contrib/README b/contrib/README
index 05f291c1f1..21d3d0e7de 100644
--- a/contrib/README
+++ b/contrib/README
@@ -23,7 +23,7 @@ This is the same way as how I have been treating gitk, and to a
lesser degree various foreign SCM interfaces, so you know the
drill.
-I expect that things that start their life in the contrib/ area
+I expect things that start their life in the contrib/ area
to graduate out of contrib/ once they mature, either by becoming
projects on their own, or moving to the toplevel directory. On
the other hand, I expect I'll be proposing removal of disused
@@ -31,7 +31,7 @@ and inactive ones from time to time.
If you have new things to add to this area, please first propose
it on the git mailing list, and after a list discussion proves
-there are some general interests (it does not have to be a
+there is general interest (it does not have to be a
list-wide consensus for a tool targeted to a relatively narrow
audience -- for example I do not work with projects whose
upstream is svn, so I have no use for git-svn myself, but it is
diff --git a/contrib/git-jump/git-jump b/contrib/git-jump/git-jump
index 40c4b0d111..47e0c557e6 100755
--- a/contrib/git-jump/git-jump
+++ b/contrib/git-jump/git-jump
@@ -9,7 +9,7 @@ The <mode> parameter is one of:
diff: elements are diff hunks. Arguments are given to diff.
-merge: elements are merge conflicts. Arguments are ignored.
+merge: elements are merge conflicts. Arguments are given to ls-files -u.
grep: elements are grep hits. Arguments are given to git grep or, if
configured, to the command in `jump.grepCmd`.
diff --git a/fsmonitor--daemon.h b/fsmonitor--daemon.h
index 70d776c54f..673f80d2aa 100644
--- a/fsmonitor--daemon.h
+++ b/fsmonitor--daemon.h
@@ -99,7 +99,7 @@ struct fsmonitor_daemon_state {
* to only mean an external GITDIR referenced by a ".git" file.
*
* The platform FS event backends will receive watch-specific
- * relative paths (except for those OS's that always emit absolute
+ * relative paths (except for those OSes that always emit absolute
* paths). We use the following enum and routines to classify each
* path so that we know how to handle it. There is a slight asymmetry
* here because ".git/" is inside the working directory and the
diff --git a/git-p4.py b/git-p4.py
index d26a980e5a..0eb3bb4c47 100755
--- a/git-p4.py
+++ b/git-p4.py
@@ -1522,6 +1522,10 @@ class LargeFileSystem(object):
file is stored in the large file system and handles all necessary
steps.
"""
+ # symlinks aren't processed by smudge/clean filters
+ if git_mode == "120000":
+ return (git_mode, contents)
+
if self.exceedsLargeFileThreshold(relPath, contents) or self.hasLargeFileExtension(relPath):
contentTempFile = self.generateTempFile(contents)
pointer_git_mode, contents, localLargeFile = self.generatePointer(contentTempFile)
diff --git a/git-send-email.perl b/git-send-email.perl
index 288ea1ae80..cacdbd6bb2 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -799,30 +799,6 @@ $sender = sanitize_address($sender);
$time = time - scalar $#files;
-if ($validate) {
- # FIFOs can only be read once, exclude them from validation.
- my @real_files = ();
- foreach my $f (@files) {
- unless (-p $f) {
- push(@real_files, $f);
- }
- }
-
- # Run the loop once again to avoid gaps in the counter due to FIFO
- # arguments provided by the user.
- my $num = 1;
- my $num_files = scalar @real_files;
- $ENV{GIT_SENDEMAIL_FILE_TOTAL} = "$num_files";
- foreach my $r (@real_files) {
- $ENV{GIT_SENDEMAIL_FILE_COUNTER} = "$num";
- pre_process_file($r, 1);
- validate_patch($r, $target_xfer_encoding);
- $num += 1;
- }
- delete $ENV{GIT_SENDEMAIL_FILE_COUNTER};
- delete $ENV{GIT_SENDEMAIL_FILE_TOTAL};
-}
-
@files = handle_backup_files(@files);
if (@files) {
@@ -861,6 +837,9 @@ if ($compose) {
my $tpl_subject = $initial_subject || '';
my $tpl_in_reply_to = $initial_in_reply_to || '';
my $tpl_reply_to = $reply_to || '';
+ my $tpl_to = join(',', @initial_to);
+ my $tpl_cc = join(',', @initial_cc);
+ my $tpl_bcc = join(', ', @initial_bcc);
print $c <<EOT1, Git::prefix_lines("GIT: ", __(<<EOT2)), <<EOT3;
From $tpl_sender # This line is ignored.
@@ -872,6 +851,9 @@ for the patch you are writing.
Clear the body content if you don't wish to send a summary.
EOT2
From: $tpl_sender
+To: $tpl_to
+Cc: $tpl_cc
+Bcc: $tpl_bcc
Reply-To: $tpl_reply_to
Subject: $tpl_subject
In-Reply-To: $tpl_in_reply_to
@@ -888,73 +870,65 @@ EOT3
do_edit($compose_filename);
}
+ open my $c2, ">", $compose_filename . ".final"
+ or die sprintf(__("Failed to open %s.final: %s"), $compose_filename, $!);
+
open $c, "<", $compose_filename
or die sprintf(__("Failed to open %s: %s"), $compose_filename, $!);
+ my $need_8bit_cte = file_has_nonascii($compose_filename);
+ my $in_body = 0;
+ my $summary_empty = 1;
if (!defined $compose_encoding) {
$compose_encoding = "UTF-8";
}
-
- my %parsed_email;
- while (my $line = <$c>) {
- next if $line =~ m/^GIT:/;
- parse_header_line($line, \%parsed_email);
- if ($line =~ /^$/) {
- $parsed_email{'body'} = filter_body($c);
+ while(<$c>) {
+ next if m/^GIT:/;
+ if ($in_body) {
+ $summary_empty = 0 unless (/^\n$/);
+ } elsif (/^\n$/) {
+ $in_body = 1;
+ if ($need_8bit_cte) {
+ print $c2 "MIME-Version: 1.0\n",
+ "Content-Type: text/plain; ",
+ "charset=$compose_encoding\n",
+ "Content-Transfer-Encoding: 8bit\n";
+ }
+ } elsif (/^MIME-Version:/i) {
+ $need_8bit_cte = 0;
+ } elsif (/^Subject:\s*(.+)\s*$/i) {
+ $initial_subject = $1;
+ my $subject = $initial_subject;
+ $_ = "Subject: " .
+ quote_subject($subject, $compose_encoding) .
+ "\n";
+ } elsif (/^In-Reply-To:\s*(.+)\s*$/i) {
+ $initial_in_reply_to = $1;
+ next;
+ } elsif (/^Reply-To:\s*(.+)\s*$/i) {
+ $reply_to = $1;
+ } elsif (/^From:\s*(.+)\s*$/i) {
+ $sender = $1;
+ next;
+ } elsif (/^To:\s*(.+)\s*$/i) {
+ @initial_to = parse_address_line($1);
+ next;
+ } elsif (/^Cc:\s*(.+)\s*$/i) {
+ @initial_cc = parse_address_line($1);
+ next;
+ } elsif (/^Bcc:/i) {
+ @initial_bcc = parse_address_line($1);
+ next;
}
+ print $c2 $_;
}
close $c;
+ close $c2;
- open my $c2, ">", $compose_filename . ".final"
- or die sprintf(__("Failed to open %s.final: %s"), $compose_filename, $!);
-
-
- if ($parsed_email{'From'}) {
- $sender = delete($parsed_email{'From'});
- }
- if ($parsed_email{'In-Reply-To'}) {
- $initial_in_reply_to = delete($parsed_email{'In-Reply-To'});
- }
- if ($parsed_email{'Reply-To'}) {
- $reply_to = delete($parsed_email{'Reply-To'});
- }
- if ($parsed_email{'Subject'}) {
- $initial_subject = delete($parsed_email{'Subject'});
- print $c2 "Subject: " .
- quote_subject($initial_subject, $compose_encoding) .
- "\n";
- }
-
- if ($parsed_email{'MIME-Version'}) {
- print $c2 "MIME-Version: $parsed_email{'MIME-Version'}\n",
- "Content-Type: $parsed_email{'Content-Type'};\n",
- "Content-Transfer-Encoding: $parsed_email{'Content-Transfer-Encoding'}\n";
- delete($parsed_email{'MIME-Version'});
- delete($parsed_email{'Content-Type'});
- delete($parsed_email{'Content-Transfer-Encoding'});
- } elsif (file_has_nonascii($compose_filename)) {
- my $content_type = (delete($parsed_email{'Content-Type'}) or
- "text/plain; charset=$compose_encoding");
- print $c2 "MIME-Version: 1.0\n",
- "Content-Type: $content_type\n",
- "Content-Transfer-Encoding: 8bit\n";
- }
- # Preserve unknown headers
- foreach my $key (keys %parsed_email) {
- next if $key eq 'body';
- print $c2 "$key: $parsed_email{$key}";
- }
-
- if ($parsed_email{'body'}) {
- print $c2 "\n$parsed_email{'body'}\n";
- delete($parsed_email{'body'});
- } else {
+ if ($summary_empty) {
print __("Summary email is empty, skipping it\n");
$compose = -1;
}
-
- close $c2;
-
} elsif ($annotate) {
do_edit(@files);
}
@@ -1009,32 +983,6 @@ sub ask {
return;
}
-sub parse_header_line {
- my $lines = shift;
- my $parsed_line = shift;
- my $addr_pat = join "|", qw(To Cc Bcc);
-
- foreach (split(/\n/, $lines)) {
- if (/^($addr_pat):\s*(.+)$/i) {
- $parsed_line->{$1} = [ parse_address_line($2) ];
- } elsif (/^([^:]*):\s*(.+)\s*$/i) {
- $parsed_line->{$1} = $2;
- }
- }
-}
-
-sub filter_body {
- my $c = shift;
- my $body = "";
- while (my $body_line = <$c>) {
- if ($body_line !~ m/^GIT:/) {
- $body .= $body_line;
- }
- }
- return $body;
-}
-
-
my %broken_encoding;
sub file_declares_8bit_cte {
@@ -1754,10 +1702,6 @@ EOF
return 1;
}
-$in_reply_to = $initial_in_reply_to;
-$references = $initial_in_reply_to || '';
-$message_num = 0;
-
sub pre_process_file {
my ($t, $quiet) = @_;
@@ -2023,6 +1967,38 @@ sub process_file {
return 1;
}
+sub initialize_modified_loop_vars {
+ $in_reply_to = $initial_in_reply_to;
+ $references = $initial_in_reply_to || '';
+ $message_num = 0;
+}
+
+if ($validate) {
+ # FIFOs can only be read once, exclude them from validation.
+ my @real_files = ();
+ foreach my $f (@files) {
+ unless (-p $f) {
+ push(@real_files, $f);
+ }
+ }
+
+ # Run the loop once again to avoid gaps in the counter due to FIFO
+ # arguments provided by the user.
+ my $num = 1;
+ my $num_files = scalar @real_files;
+ $ENV{GIT_SENDEMAIL_FILE_TOTAL} = "$num_files";
+ initialize_modified_loop_vars();
+ foreach my $r (@real_files) {
+ $ENV{GIT_SENDEMAIL_FILE_COUNTER} = "$num";
+ pre_process_file($r, 1);
+ validate_patch($r, $target_xfer_encoding);
+ $num += 1;
+ }
+ delete $ENV{GIT_SENDEMAIL_FILE_COUNTER};
+ delete $ENV{GIT_SENDEMAIL_FILE_TOTAL};
+}
+
+initialize_modified_loop_vars();
foreach my $t (@files) {
while (!process_file($t)) {
# user edited the file
diff --git a/merge-ort.c b/merge-ort.c
index 3653725661..6491070d96 100644
--- a/merge-ort.c
+++ b/merge-ort.c
@@ -2037,7 +2037,7 @@ static int handle_content_merge(struct merge_options *opt,
* the three blobs to merge on various sides of history.
*
* extra_marker_size is the amount to extend conflict markers in
- * ll_merge; this is neeed if we have content merges of content
+ * ll_merge; this is needed if we have content merges of content
* merges, which happens for example with rename/rename(2to1) and
* rename/add conflicts.
*/
diff --git a/parse-options.c b/parse-options.c
index 093eaf2db8..e0c94b0546 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -70,42 +70,10 @@ static void fix_filename(const char *prefix, char **file)
*file = prefix_filename_except_for_dash(prefix, *file);
}
-static enum parse_opt_result opt_command_mode_error(
- const struct option *opt,
- const struct option *all_opts,
- enum opt_parsed flags)
-{
- const struct option *that;
- struct strbuf that_name = STRBUF_INIT;
-
- /*
- * Find the other option that was used to set the variable
- * already, and report that this is not compatible with it.
- */
- for (that = all_opts; that->type != OPTION_END; that++) {
- if (that == opt ||
- !(that->flags & PARSE_OPT_CMDMODE) ||
- that->value != opt->value ||
- that->defval != *(int *)opt->value)
- continue;
-
- if (that->long_name)
- strbuf_addf(&that_name, "--%s", that->long_name);
- else
- strbuf_addf(&that_name, "-%c", that->short_name);
- error(_("%s is incompatible with %s"),
- optname(opt, flags), that_name.buf);
- strbuf_release(&that_name);
- return PARSE_OPT_ERROR;
- }
- return error(_("%s : incompatible with something else"),
- optname(opt, flags));
-}
-
-static enum parse_opt_result get_value(struct parse_opt_ctx_t *p,
- const struct option *opt,
- const struct option *all_opts,
- enum opt_parsed flags)
+static enum parse_opt_result do_get_value(struct parse_opt_ctx_t *p,
+ const struct option *opt,
+ enum opt_parsed flags,
+ const char **argp)
{
const char *s, *arg;
const int unset = flags & OPT_UNSET;
@@ -118,14 +86,6 @@ static enum parse_opt_result get_value(struct parse_opt_ctx_t *p,
if (!(flags & OPT_SHORT) && p->opt && (opt->flags & PARSE_OPT_NOARG))
return error(_("%s takes no value"), optname(opt, flags));
- /*
- * Giving the same mode option twice, although unnecessary,
- * is not a grave error, so let it pass.
- */
- if ((opt->flags & PARSE_OPT_CMDMODE) &&
- *(int *)opt->value && *(int *)opt->value != opt->defval)
- return opt_command_mode_error(opt, all_opts, flags);
-
switch (opt->type) {
case OPTION_LOWLEVEL_CALLBACK:
return opt->ll_callback(p, opt, NULL, unset);
@@ -200,6 +160,8 @@ static enum parse_opt_result get_value(struct parse_opt_ctx_t *p,
p_unset = 0;
p_arg = arg;
}
+ if (opt->flags & PARSE_OPT_CMDMODE)
+ *argp = p_arg;
if (opt->callback)
return (*opt->callback)(opt, p_arg, p_unset) ? (-1) : 0;
else
@@ -247,16 +209,91 @@ static enum parse_opt_result get_value(struct parse_opt_ctx_t *p,
}
}
+struct parse_opt_cmdmode_list {
+ int value, *value_ptr;
+ const struct option *opt;
+ const char *arg;
+ enum opt_parsed flags;
+ struct parse_opt_cmdmode_list *next;
+};
+
+static void build_cmdmode_list(struct parse_opt_ctx_t *ctx,
+ const struct option *opts)
+{
+ ctx->cmdmode_list = NULL;
+
+ for (; opts->type != OPTION_END; opts++) {
+ struct parse_opt_cmdmode_list *elem = ctx->cmdmode_list;
+ int *value_ptr = opts->value;
+
+ if (!(opts->flags & PARSE_OPT_CMDMODE) || !value_ptr)
+ continue;
+
+ while (elem && elem->value_ptr != value_ptr)
+ elem = elem->next;
+ if (elem)
+ continue;
+
+ CALLOC_ARRAY(elem, 1);
+ elem->value_ptr = value_ptr;
+ elem->value = *value_ptr;
+ elem->next = ctx->cmdmode_list;
+ ctx->cmdmode_list = elem;
+ }
+}
+
+static char *optnamearg(const struct option *opt, const char *arg,
+ enum opt_parsed flags)
+{
+ if (flags & OPT_SHORT)
+ return xstrfmt("-%c%s", opt->short_name, arg ? arg : "");
+ return xstrfmt("--%s%s%s%s", flags & OPT_UNSET ? "no-" : "",
+ opt->long_name, arg ? "=" : "", arg ? arg : "");
+}
+
+static enum parse_opt_result get_value(struct parse_opt_ctx_t *p,
+ const struct option *opt,
+ enum opt_parsed flags)
+{
+ const char *arg = NULL;
+ enum parse_opt_result result = do_get_value(p, opt, flags, &arg);
+ struct parse_opt_cmdmode_list *elem = p->cmdmode_list;
+ char *opt_name, *other_opt_name;
+
+ for (; elem; elem = elem->next) {
+ if (*elem->value_ptr == elem->value)
+ continue;
+
+ if (elem->opt &&
+ (elem->opt->flags | opt->flags) & PARSE_OPT_CMDMODE)
+ break;
+
+ elem->opt = opt;
+ elem->arg = arg;
+ elem->flags = flags;
+ elem->value = *elem->value_ptr;
+ }
+
+ if (result || !elem)
+ return result;
+
+ opt_name = optnamearg(opt, arg, flags);
+ other_opt_name = optnamearg(elem->opt, elem->arg, elem->flags);
+ error(_("%s is incompatible with %s"), opt_name, other_opt_name);
+ free(opt_name);
+ free(other_opt_name);
+ return -1;
+}
+
static enum parse_opt_result parse_short_opt(struct parse_opt_ctx_t *p,
const struct option *options)
{
- const struct option *all_opts = options;
const struct option *numopt = NULL;
for (; options->type != OPTION_END; options++) {
if (options->short_name == *p->opt) {
p->opt = p->opt[1] ? p->opt + 1 : NULL;
- return get_value(p, options, all_opts, OPT_SHORT);
+ return get_value(p, options, OPT_SHORT);
}
/*
@@ -318,7 +355,6 @@ static enum parse_opt_result parse_long_opt(
struct parse_opt_ctx_t *p, const char *arg,
const struct option *options)
{
- const struct option *all_opts = options;
const char *arg_end = strchrnul(arg, '=');
const struct option *abbrev_option = NULL, *ambiguous_option = NULL;
enum opt_parsed abbrev_flags = OPT_LONG, ambiguous_flags = OPT_LONG;
@@ -387,7 +423,7 @@ is_abbreviated:
continue;
p->opt = rest + 1;
}
- return get_value(p, options, all_opts, flags ^ opt_flags);
+ return get_value(p, options, flags ^ opt_flags);
}
if (disallow_abbreviated_options && (ambiguous_option || abbrev_option))
@@ -405,7 +441,7 @@ is_abbreviated:
return PARSE_OPT_HELP;
}
if (abbrev_option)
- return get_value(p, abbrev_option, all_opts, abbrev_flags);
+ return get_value(p, abbrev_option, abbrev_flags);
return PARSE_OPT_UNKNOWN;
}
@@ -413,13 +449,11 @@ static enum parse_opt_result parse_nodash_opt(struct parse_opt_ctx_t *p,
const char *arg,
const struct option *options)
{
- const struct option *all_opts = options;
-
for (; options->type != OPTION_END; options++) {
if (!(options->flags & PARSE_OPT_NODASH))
continue;
if (options->short_name == arg[0] && arg[1] == '\0')
- return get_value(p, options, all_opts, OPT_SHORT);
+ return get_value(p, options, OPT_SHORT);
}
return PARSE_OPT_ERROR;
}
@@ -574,6 +608,7 @@ static void parse_options_start_1(struct parse_opt_ctx_t *ctx,
(flags & PARSE_OPT_KEEP_ARGV0))
BUG("Can't keep argv0 if you don't have it");
parse_options_check(options);
+ build_cmdmode_list(ctx, options);
}
void parse_options_start(struct parse_opt_ctx_t *ctx,
@@ -1006,6 +1041,11 @@ int parse_options(int argc, const char **argv,
precompose_argv_prefix(argc, argv, NULL);
free_preprocessed_options(real_options);
free(ctx.alias_groups);
+ for (struct parse_opt_cmdmode_list *elem = ctx.cmdmode_list; elem;) {
+ struct parse_opt_cmdmode_list *next = elem->next;
+ free(elem);
+ elem = next;
+ }
return parse_options_end(&ctx);
}
diff --git a/parse-options.h b/parse-options.h
index 4a66ec3bf5..bd62e20268 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -445,6 +445,8 @@ static inline void die_for_incompatible_opt3(int opt1, const char *opt1_name,
/*----- incremental advanced APIs -----*/
+struct parse_opt_cmdmode_list;
+
/*
* It's okay for the caller to consume argv/argc in the usual way.
* Other fields of that structure are private to parse-options and should not
@@ -459,6 +461,7 @@ struct parse_opt_ctx_t {
unsigned has_subcommands;
const char *prefix;
const char **alias_groups; /* must be in groups of 3 elements! */
+ struct parse_opt_cmdmode_list *cmdmode_list;
};
void parse_options_start(struct parse_opt_ctx_t *ctx,
diff --git a/pathspec.c b/pathspec.c
index 7f88f1c02b..bb1efe1f39 100644
--- a/pathspec.c
+++ b/pathspec.c
@@ -467,7 +467,12 @@ static void init_pathspec_item(struct pathspec_item *item, unsigned flags,
match = prefix_path_gently(prefix, prefixlen,
&prefixlen, copyfrom);
if (!match) {
- const char *hint_path = get_git_work_tree();
+ const char *hint_path;
+
+ if (!have_git_dir())
+ die(_("'%s' is outside the directory tree"),
+ copyfrom);
+ hint_path = get_git_work_tree();
if (!hint_path)
hint_path = get_git_dir();
die(_("%s: '%s' is outside repository at '%s'"), elt,
diff --git a/strbuf.h b/strbuf.h
index fd43c46433..e959caca87 100644
--- a/strbuf.h
+++ b/strbuf.h
@@ -12,9 +12,9 @@
struct string_list;
/**
- * strbuf's are meant to be used with all the usual C string and memory
+ * strbufs are meant to be used with all the usual C string and memory
* APIs. Given that the length of the buffer is known, it's often better to
- * use the mem* functions than a str* one (memchr vs. strchr e.g.).
+ * use the mem* functions than a str* one (e.g., memchr vs. strchr).
* Though, one has to be careful about the fact that str* functions often
* stop on NULs and that strbufs may have embedded NULs.
*
@@ -24,7 +24,7 @@ struct string_list;
* strbufs have some invariants that are very important to keep in mind:
*
* - The `buf` member is never NULL, so it can be used in any usual C
- * string operations safely. strbuf's _have_ to be initialized either by
+ * string operations safely. strbufs _have_ to be initialized either by
* `strbuf_init()` or by `= STRBUF_INIT` before the invariants, though.
*
* Do *not* assume anything on what `buf` really is (e.g. if it is
@@ -37,7 +37,7 @@ struct string_list;
*
* - The `buf` member is a byte array that has at least `len + 1` bytes
* allocated. The extra byte is used to store a `'\0'`, allowing the
- * `buf` member to be a valid C-string. Every strbuf function ensure this
+ * `buf` member to be a valid C-string. All strbuf functions ensure this
* invariant is preserved.
*
* NOTE: It is OK to "play" with the buffer directly if you work it this
diff --git a/t/README b/t/README
index 6108085989..a0ebe29484 100644
--- a/t/README
+++ b/t/README
@@ -262,8 +262,8 @@ The argument for --run, <test-selector>, is a list of description
substrings or globs or individual test numbers or ranges with an
optional negation prefix (of '!') that define what tests in a test
suite to include (or exclude, if negated) in the run. A range is two
-numbers separated with a dash and matches a range of tests with both
-ends been included. You may omit the first or the second number to
+numbers separated with a dash and specifies an inclusive range of tests
+to run. You may omit the first or the second number to
mean "from the first test" or "up to the very last test" respectively.
The argument to --run is split on commas into separate strings,
@@ -274,10 +274,10 @@ text that you want to match includes a comma, use the glob character
on all tests that match either the glob *rebase* or the glob
*merge?cherry-pick*.
-If --run starts with an unprefixed number or range the initial
-set of tests to run is empty. If the first item starts with '!'
+If --run starts with an unprefixed number or range, the initial
+set of tests to run is empty. If the first item starts with '!',
all the tests are added to the initial set. After initial set is
-determined every test number or range is added or excluded from
+determined, every test number or range is added or excluded from
the set one by one, from left to right.
For example, to run only tests up to a specific test (21), one
@@ -579,11 +579,11 @@ This test harness library does the following things:
Recommended style
-----------------
-Here are some recommented styles when writing test case.
- - Keep test title the same line with test helper function itself.
+ - Keep the test_expect_* function call and test title on
+ the same line.
- Take test_expect_success helper for example, write it like:
+ For example, with test_expect_success, write it like:
test_expect_success 'test title' '
... test body ...
@@ -595,10 +595,9 @@ Here are some recommented styles when writing test case.
'test title' \
'... test body ...'
+ - End the line with an opening single quote.
- - End the line with a single quote.
-
- - Indent the body of here-document, and use "<<-" instead of "<<"
+ - Indent here-document bodies, and use "<<-" instead of "<<"
to strip leading TABs used for indentation:
test_expect_success 'test something' '
@@ -624,7 +623,7 @@ Here are some recommented styles when writing test case.
'
- Quote or escape the EOF delimiter that begins a here-document if
- there is no parameter and other expansion in it, to signal readers
+ there is no parameter or other expansion in it, to signal readers
that they can skim it more casually:
cmd <<-\EOF
@@ -638,7 +637,7 @@ Do's & don'ts
Here are a few examples of things you probably should and shouldn't do
when writing tests.
-Here are the "do's:"
+The "do's:"
- Put all code inside test_expect_success and other assertions.
@@ -888,7 +887,7 @@ see test-lib-functions.sh for the full list and their options.
rare case where your test depends on more than one:
test_expect_success PERL,PYTHON 'yo dawg' \
- ' test $(perl -E 'print eval "1 +" . qx[python -c "print 2"]') == "4" '
+ ' test $(perl -E '\''print eval "1 +" . qx[python -c "print(2)"]'\'') = "4" '
- test_expect_failure [<prereq>] <message> <script>
@@ -1237,8 +1236,8 @@ and it knows that the object ID of an empty tree is a certain
because the things the very basic core test tries to achieve is
to serve as a basis for people who are changing the Git internals
drastically. For these people, after making certain changes,
-not seeing failures from the basic test _is_ a failure. And
-such drastic changes to the core Git that even changes these
+not seeing failures from the basic test _is_ a failure. Any
+Git core changes so drastic that they change even these
otherwise supposedly stable object IDs should be accompanied by
an update to t0000-basic.sh.
@@ -1248,7 +1247,7 @@ knowledge of the core Git internals. If all the test scripts
hardcoded the object IDs like t0000-basic.sh does, that defeats
the purpose of t0000-basic.sh, which is to isolate that level of
validation in one place. Your test also ends up needing
-updating when such a change to the internal happens, so do _not_
+an update whenever the internals change, so do _not_
do it and leave the low level of validation to t0000-basic.sh.
Test coverage
diff --git a/t/helper/test-parse-options.c b/t/helper/test-parse-options.c
index a4f6e24b0c..ded8116cc5 100644
--- a/t/helper/test-parse-options.c
+++ b/t/helper/test-parse-options.c
@@ -21,6 +21,19 @@ static struct {
int unset;
} length_cb;
+static int mode34_callback(const struct option *opt, const char *arg, int unset)
+{
+ if (unset)
+ *(int *)opt->value = 0;
+ else if (!strcmp(arg, "3"))
+ *(int *)opt->value = 3;
+ else if (!strcmp(arg, "4"))
+ *(int *)opt->value = 4;
+ else
+ return error("invalid value for '%s': '%s'", "--mode34", arg);
+ return 0;
+}
+
static int length_callback(const struct option *opt, const char *arg, int unset)
{
length_cb.called = 1;
@@ -124,6 +137,9 @@ int cmd__parse_options(int argc, const char **argv)
OPT_SET_INT(0, "set23", &integer, "set integer to 23", 23),
OPT_CMDMODE(0, "mode1", &integer, "set integer to 1 (cmdmode option)", 1),
OPT_CMDMODE(0, "mode2", &integer, "set integer to 2 (cmdmode option)", 2),
+ OPT_CALLBACK_F(0, "mode34", &integer, "(3|4)",
+ "set integer to 3 or 4 (cmdmode option)",
+ PARSE_OPT_CMDMODE, mode34_callback),
OPT_CALLBACK('L', "length", &integer, "str",
"get length of <str>", length_callback),
OPT_FILENAME('F', "file", &file, "set file to <file>"),
diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh
index 26e082f05b..ecf43ab545 100755
--- a/t/t0003-attributes.sh
+++ b/t/t0003-attributes.sh
@@ -40,6 +40,10 @@ attr_check_source () {
test_cmp expect actual &&
test_must_be_empty err
+ git $git_opts -c "attr.tree=$source" check-attr test -- "$path" >actual 2>err &&
+ test_cmp expect actual &&
+ test_must_be_empty err
+
GIT_ATTR_SOURCE="$source" git $git_opts check-attr test -- "$path" >actual 2>err &&
test_cmp expect actual &&
test_must_be_empty err
@@ -342,6 +346,74 @@ test_expect_success 'bare repository: check that .gitattribute is ignored' '
)
'
+bad_attr_source_err="fatal: bad --attr-source or GIT_ATTR_SOURCE"
+
+test_expect_success '--attr-source is bad' '
+ test_when_finished rm -rf empty &&
+ git init empty &&
+ (
+ cd empty &&
+ echo "$bad_attr_source_err" >expect_err &&
+ test_must_fail git --attr-source=HEAD check-attr test -- f/path 2>err &&
+ test_cmp expect_err err
+ )
+'
+
+test_expect_success 'attr.tree when HEAD is unborn' '
+ test_when_finished rm -rf empty &&
+ git init empty &&
+ (
+ cd empty &&
+ echo "f/path: test: unspecified" >expect &&
+ git -c attr.tree=HEAD check-attr test -- f/path >actual 2>err &&
+ test_must_be_empty err &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'bad attr source defaults to reading .gitattributes file' '
+ test_when_finished rm -rf empty &&
+ git init empty &&
+ (
+ cd empty &&
+ echo "f/path test=val" >.gitattributes &&
+ echo "f/path: test: val" >expect &&
+ git -c attr.tree=HEAD check-attr test -- f/path >actual 2>err &&
+ test_must_be_empty err &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'bare repo defaults to reading .gitattributes from HEAD' '
+ test_when_finished rm -rf test bare_with_gitattribute &&
+ git init test &&
+ test_commit -C test gitattributes .gitattributes "f/path test=val" &&
+ git clone --bare test bare_with_gitattribute &&
+ echo "f/path: test: val" >expect &&
+ git -C bare_with_gitattribute check-attr test -- f/path >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'precedence of --attr-source, GIT_ATTR_SOURCE, then attr.tree' '
+ test_when_finished rm -rf empty &&
+ git init empty &&
+ (
+ cd empty &&
+ git checkout -b attr-source &&
+ test_commit "val1" .gitattributes "f/path test=val1" &&
+ git checkout -b attr-tree &&
+ test_commit "val2" .gitattributes "f/path test=val2" &&
+ git checkout attr-source &&
+ echo "f/path: test: val1" >expect &&
+ GIT_ATTR_SOURCE=attr-source git -c attr.tree=attr-tree --attr-source=attr-source \
+ check-attr test -- f/path >actual &&
+ test_cmp expect actual &&
+ GIT_ATTR_SOURCE=attr-source git -c attr.tree=attr-tree \
+ check-attr test -- f/path >actual &&
+ test_cmp expect actual
+ )
+'
+
test_expect_success 'bare repository: with --source' '
(
cd bare.git &&
diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh
index a0ad6192d6..06fb9e6457 100755
--- a/t/t0040-parse-options.sh
+++ b/t/t0040-parse-options.sh
@@ -28,6 +28,7 @@ usage: test-tool parse-options <options>
--[no-]set23 set integer to 23
--mode1 set integer to 1 (cmdmode option)
--mode2 set integer to 2 (cmdmode option)
+ --[no-]mode34 (3|4) set integer to 3 or 4 (cmdmode option)
-L, --[no-]length <str>
get length of <str>
-F, --[no-]file <file>
@@ -366,19 +367,41 @@ test_expect_success 'OPT_NEGBIT() works' '
'
test_expect_success 'OPT_CMDMODE() works' '
- test-tool parse-options --expect="integer: 1" --mode1
+ test-tool parse-options --expect="integer: 1" --mode1 &&
+ test-tool parse-options --expect="integer: 3" --mode34=3
'
-test_expect_success 'OPT_CMDMODE() detects incompatibility' '
+test_expect_success 'OPT_CMDMODE() detects incompatibility (1)' '
test_must_fail test-tool parse-options --mode1 --mode2 >output 2>output.err &&
test_must_be_empty output &&
- test_i18ngrep "incompatible with --mode" output.err
+ test_i18ngrep "mode1" output.err &&
+ test_i18ngrep "mode2" output.err &&
+ test_i18ngrep "is incompatible with" output.err
'
-test_expect_success 'OPT_CMDMODE() detects incompatibility with something else' '
+test_expect_success 'OPT_CMDMODE() detects incompatibility (2)' '
test_must_fail test-tool parse-options --set23 --mode2 >output 2>output.err &&
test_must_be_empty output &&
- test_i18ngrep "incompatible with something else" output.err
+ test_i18ngrep "mode2" output.err &&
+ test_i18ngrep "set23" output.err &&
+ test_i18ngrep "is incompatible with" output.err
+'
+
+test_expect_success 'OPT_CMDMODE() detects incompatibility (3)' '
+ test_must_fail test-tool parse-options --mode2 --set23 >output 2>output.err &&
+ test_must_be_empty output &&
+ test_i18ngrep "mode2" output.err &&
+ test_i18ngrep "set23" output.err &&
+ test_i18ngrep "is incompatible with" output.err
+'
+
+test_expect_success 'OPT_CMDMODE() detects incompatibility (4)' '
+ test_must_fail test-tool parse-options --mode2 --mode34=3 \
+ >output 2>output.err &&
+ test_must_be_empty output &&
+ test_i18ngrep "mode2" output.err &&
+ test_i18ngrep "mode34.3" output.err &&
+ test_i18ngrep "is incompatible with" output.err
'
test_expect_success 'OPT_COUNTUP() with PARSE_OPT_NODASH works' '
diff --git a/t/t1410-reflog.sh b/t/t1410-reflog.sh
index 6c45965b1e..09e7f3cdac 100755
--- a/t/t1410-reflog.sh
+++ b/t/t1410-reflog.sh
@@ -446,6 +446,29 @@ test_expect_success 'expire with multiple worktrees' '
)
'
+test_expect_success 'expire one of multiple worktrees' '
+ git init main-wt2 &&
+ (
+ cd main-wt2 &&
+ test_tick &&
+ test_commit foo &&
+ git worktree add link-wt &&
+ test_tick &&
+ test_commit -C link-wt foobar &&
+ test_tick &&
+ test-tool ref-store worktree:link-wt for-each-reflog-ent HEAD \
+ >expect-link-wt &&
+ git reflog expire --verbose --all --expire=$test_tick \
+ --single-worktree &&
+ test-tool ref-store worktree:main for-each-reflog-ent HEAD \
+ >actual-main &&
+ test-tool ref-store worktree:link-wt for-each-reflog-ent HEAD \
+ >actual-link-wt &&
+ test_must_be_empty actual-main &&
+ test_cmp expect-link-wt actual-link-wt
+ )
+'
+
test_expect_success REFFILES 'empty reflog' '
test_when_finished "rm -rf empty" &&
git init empty &&
diff --git a/t/t2407-worktree-heads.sh b/t/t2407-worktree-heads.sh
index 469443d8ae..f6835c91dc 100755
--- a/t/t2407-worktree-heads.sh
+++ b/t/t2407-worktree-heads.sh
@@ -45,7 +45,7 @@ test_expect_success 'refuse to overwrite: checked out in worktree' '
grep "cannot force update the branch" err &&
test_must_fail git branch -D wt-$i 2>err &&
- grep "Cannot delete branch" err || return 1
+ grep "cannot delete branch" err || return 1
done
'
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index 080e4f24a6..3182abde27 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -291,10 +291,10 @@ test_expect_success 'git branch -M topic topic should work when main is checked
test_expect_success 'git branch -M and -C fail on detached HEAD' '
git checkout HEAD^{} &&
test_when_finished git checkout - &&
- echo "fatal: cannot rename the current branch while not on any." >expect &&
+ echo "fatal: cannot rename the current branch while not on any" >expect &&
test_must_fail git branch -M must-fail 2>err &&
test_cmp expect err &&
- echo "fatal: cannot copy the current branch while not on any." >expect &&
+ echo "fatal: cannot copy the current branch while not on any" >expect &&
test_must_fail git branch -C must-fail 2>err &&
test_cmp expect err
'
@@ -943,7 +943,7 @@ test_expect_success 'deleting currently checked out branch fails' '
git worktree add -b my7 my7 &&
test_must_fail git -C my7 branch -d my7 &&
test_must_fail git branch -d my7 2>actual &&
- grep "^error: Cannot delete branch .my7. used by worktree at " actual &&
+ grep "^error: cannot delete branch .my7. used by worktree at " actual &&
rm -r my7 &&
git worktree prune
'
@@ -954,7 +954,7 @@ test_expect_success 'deleting in-use branch fails' '
git -C my7 bisect start HEAD HEAD~2 &&
test_must_fail git -C my7 branch -d my7 &&
test_must_fail git branch -d my7 2>actual &&
- grep "^error: Cannot delete branch .my7. used by worktree at " actual &&
+ grep "^error: cannot delete branch .my7. used by worktree at " actual &&
rm -r my7 &&
git worktree prune
'
@@ -1024,7 +1024,7 @@ test_expect_success '--set-upstream-to fails on multiple branches' '
test_expect_success '--set-upstream-to fails on detached HEAD' '
git checkout HEAD^{} &&
test_when_finished git checkout - &&
- echo "fatal: could not set upstream of HEAD to main when it does not point to any branch." >expect &&
+ echo "fatal: could not set upstream of HEAD to main when it does not point to any branch" >expect &&
test_must_fail git branch --set-upstream-to main 2>err &&
test_cmp expect err
'
@@ -1072,7 +1072,7 @@ test_expect_success 'use --set-upstream-to modify a particular branch' '
'
test_expect_success '--unset-upstream should fail if given a non-existent branch' '
- echo "fatal: Branch '"'"'i-dont-exist'"'"' has no upstream information" >expect &&
+ echo "fatal: branch '"'"'i-dont-exist'"'"' has no upstream information" >expect &&
test_must_fail git branch --unset-upstream i-dont-exist 2>err &&
test_cmp expect err
'
@@ -1094,7 +1094,7 @@ test_expect_success 'test --unset-upstream on HEAD' '
test_must_fail git config branch.main.remote &&
test_must_fail git config branch.main.merge &&
# fail for a branch without upstream set
- echo "fatal: Branch '"'"'main'"'"' has no upstream information" >expect &&
+ echo "fatal: branch '"'"'main'"'"' has no upstream information" >expect &&
test_must_fail git branch --unset-upstream 2>err &&
test_cmp expect err
'
@@ -1108,7 +1108,7 @@ test_expect_success '--unset-upstream should fail on multiple branches' '
test_expect_success '--unset-upstream should fail on detached HEAD' '
git checkout HEAD^{} &&
test_when_finished git checkout - &&
- echo "fatal: could not unset upstream of HEAD when it does not point to any branch." >expect &&
+ echo "fatal: could not unset upstream of HEAD when it does not point to any branch" >expect &&
test_must_fail git branch --unset-upstream 2>err &&
test_cmp expect err
'
diff --git a/t/t3202-show-branch.sh b/t/t3202-show-branch.sh
index b17f388f56..2cdb834b37 100755
--- a/t/t3202-show-branch.sh
+++ b/t/t3202-show-branch.sh
@@ -10,7 +10,7 @@ GIT_TEST_DATE_NOW=1251660000; export GIT_TEST_DATE_NOW
test_expect_success 'error descriptions on empty repository' '
current=$(git branch --show-current) &&
cat >expect <<-EOF &&
- error: No commit on branch '\''$current'\'' yet.
+ error: no commit on branch '\''$current'\'' yet
EOF
test_must_fail git branch --edit-description 2>actual &&
test_cmp expect actual &&
@@ -21,7 +21,7 @@ test_expect_success 'error descriptions on empty repository' '
test_expect_success 'fatal descriptions on empty repository' '
current=$(git branch --show-current) &&
cat >expect <<-EOF &&
- fatal: No commit on branch '\''$current'\'' yet.
+ fatal: no commit on branch '\''$current'\'' yet
EOF
test_must_fail git branch --set-upstream-to=non-existent 2>actual &&
test_cmp expect actual &&
@@ -224,7 +224,7 @@ done
test_expect_success 'error descriptions on non-existent branch' '
cat >expect <<-EOF &&
- error: No branch named '\''non-existent'\'.'
+ error: no branch named '\''non-existent'\''
EOF
test_must_fail git branch --edit-description non-existent 2>actual &&
test_cmp expect actual
@@ -238,7 +238,7 @@ test_expect_success 'fatal descriptions on non-existent branch' '
test_cmp expect actual &&
cat >expect <<-EOF &&
- fatal: No branch named '\''non-existent'\''.
+ fatal: no branch named '\''non-existent'\''
EOF
test_must_fail git branch -c non-existent new-branch 2>actual &&
test_cmp expect actual &&
@@ -253,7 +253,7 @@ test_expect_success 'error descriptions on orphan branch' '
test_branch_op_in_wt() {
test_orphan_error() {
test_must_fail git $* 2>actual &&
- test_i18ngrep "No commit on branch .orphan-branch. yet.$" actual
+ test_i18ngrep "no commit on branch .orphan-branch. yet$" actual
} &&
test_orphan_error -C wt branch $1 $2 && # implicit branch
test_orphan_error -C wt branch $1 orphan-branch $2 && # explicit branch
diff --git a/t/t5001-archive-attr.sh b/t/t5001-archive-attr.sh
index 0ff47a239d..eaf959d8f6 100755
--- a/t/t5001-archive-attr.sh
+++ b/t/t5001-archive-attr.sh
@@ -138,7 +138,7 @@ test_expect_success 'git archive with worktree attributes, bare' '
'
test_expect_missing bare-worktree/ignored
-test_expect_exists bare-worktree/ignored-by-tree
+test_expect_missing bare-worktree/ignored-by-tree
test_expect_exists bare-worktree/ignored-by-worktree
test_expect_success 'export-subst' '
diff --git a/t/t7601-merge-pull-config.sh b/t/t7601-merge-pull-config.sh
index bd238d89b0..e08767df66 100755
--- a/t/t7601-merge-pull-config.sh
+++ b/t/t7601-merge-pull-config.sh
@@ -349,13 +349,13 @@ test_expect_success 'Cannot rebase with multiple heads' '
test_expect_success 'merge c1 with c2' '
git reset --hard c1 &&
- test -f c0.c &&
- test -f c1.c &&
- test ! -f c2.c &&
- test ! -f c3.c &&
+ test_path_is_file c0.c &&
+ test_path_is_file c1.c &&
+ test_path_is_missing c2.c &&
+ test_path_is_missing c3.c &&
git merge c2 &&
- test -f c1.c &&
- test -f c2.c
+ test_path_is_file c1.c &&
+ test_path_is_file c2.c
'
test_expect_success 'fast-forward pull succeeds with "true" in pull.ff' '
@@ -411,8 +411,8 @@ test_expect_success 'merge c1 with c2 (ours in pull.twohead)' '
git reset --hard c1 &&
git config pull.twohead ours &&
git merge c2 &&
- test -f c1.c &&
- ! test -f c2.c
+ test_path_is_file c1.c &&
+ test_path_is_missing c2.c
'
test_expect_success 'merge c1 with c2 and c3 (recursive in pull.octopus)' '
@@ -431,10 +431,10 @@ test_expect_success 'merge c1 with c2 and c3 (recursive and octopus in pull.octo
test "$(git rev-parse c2)" = "$(git rev-parse HEAD^2)" &&
test "$(git rev-parse c3)" = "$(git rev-parse HEAD^3)" &&
git diff --exit-code &&
- test -f c0.c &&
- test -f c1.c &&
- test -f c2.c &&
- test -f c3.c
+ test_path_is_file c0.c &&
+ test_path_is_file c1.c &&
+ test_path_is_file c2.c &&
+ test_path_is_file c3.c
'
conflict_count()
diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh
index 39d6d713ec..1caaf12430 100755
--- a/t/t7810-grep.sh
+++ b/t/t7810-grep.sh
@@ -808,6 +808,19 @@ test_expect_success 'grep -f, ignore empty lines, read patterns from stdin' '
test_cmp expected actual
'
+test_expect_success 'grep -f, use cwd relative file' '
+ test_when_finished "git rm -f sub/dir/file" &&
+ mkdir -p sub/dir &&
+ echo hit >sub/dir/file &&
+ git add sub/dir/file &&
+ echo hit >sub/dir/pattern &&
+ echo miss >pattern &&
+ (
+ cd sub/dir && git grep -f pattern file
+ ) &&
+ git -C sub/dir grep -f pattern file
+'
+
cat >expected <<EOF
y:y yy
--
@@ -1234,6 +1247,33 @@ test_expect_success 'outside of git repository with fallbackToNoIndex' '
)
'
+test_expect_success 'no repository with path outside $cwd' '
+ test_when_finished rm -fr non &&
+ rm -fr non &&
+ mkdir -p non/git/sub non/tig &&
+ (
+ GIT_CEILING_DIRECTORIES="$(pwd)/non" &&
+ export GIT_CEILING_DIRECTORIES &&
+ cd non/git &&
+ test_expect_code 128 git grep --no-index search .. 2>error &&
+ grep "is outside the directory tree" error
+ ) &&
+ (
+ GIT_CEILING_DIRECTORIES="$(pwd)/non" &&
+ export GIT_CEILING_DIRECTORIES &&
+ cd non/git &&
+ test_expect_code 128 git grep --no-index search ../tig 2>error &&
+ grep "is outside the directory tree" error
+ ) &&
+ (
+ GIT_CEILING_DIRECTORIES="$(pwd)/non" &&
+ export GIT_CEILING_DIRECTORIES &&
+ cd non/git &&
+ test_expect_code 128 git grep --no-index search ../non 2>error &&
+ grep "no such path in the working tree" error
+ )
+'
+
test_expect_success 'inside git repository but with --no-index' '
rm -fr is &&
mkdir -p is/git/sub &&
diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh
index 263db3ad17..dc7785eadb 100755
--- a/t/t9001-send-email.sh
+++ b/t/t9001-send-email.sh
@@ -633,6 +633,25 @@ test_expect_success $PREREQ "--validate respects absolute core.hooksPath path" '
test_cmp expect actual
'
+test_expect_success $PREREQ "--validate hook supports multiple addresses in arguments" '
+ hooks_path="$(pwd)/my-hooks" &&
+ test_config core.hooksPath "$hooks_path" &&
+ test_when_finished "rm my-hooks.ran" &&
+ test_must_fail git send-email \
+ --from="Example <nobody@example.com>" \
+ --to=nobody@example.com,abc@example.com \
+ --smtp-server="$(pwd)/fake.sendmail" \
+ --validate \
+ longline.patch 2>actual &&
+ test_path_is_file my-hooks.ran &&
+ cat >expect <<-EOF &&
+ fatal: longline.patch: rejected by sendemail-validate hook
+ fatal: command '"'"'git hook run --ignore-missing sendemail-validate -- <patch> <header>'"'"' died with exit code 1
+ warning: no patches were sent
+ EOF
+ test_cmp expect actual
+'
+
test_expect_success $PREREQ "--validate hook supports header argument" '
write_script my-hooks/sendemail-validate <<-\EOF &&
if test "$#" -ge 2
@@ -2505,4 +2524,45 @@ test_expect_success $PREREQ 'test forbidSendmailVariables behavior override' '
HEAD^
'
+test_expect_success $PREREQ '--compose handles lowercase headers' '
+ write_script fake-editor <<-\EOF &&
+ sed "s/^From:.*/from: edited-from@example.com/i" "$1" >"$1.tmp" &&
+ mv "$1.tmp" "$1"
+ EOF
+ clean_fake_sendmail &&
+ git send-email \
+ --compose \
+ --from="Example <from@example.com>" \
+ --to=nobody@example.com \
+ --smtp-server="$(pwd)/fake.sendmail" \
+ HEAD^ &&
+ grep "From: edited-from@example.com" msgtxt1
+'
+
+test_expect_success $PREREQ '--compose handles to headers' '
+ write_script fake-editor <<-\EOF &&
+ sed "s/^To: .*/&, edited-to@example.com/" <"$1" >"$1.tmp" &&
+ echo this is the body >>"$1.tmp" &&
+ mv "$1.tmp" "$1"
+ EOF
+ clean_fake_sendmail &&
+ GIT_SEND_EMAIL_NOTTY=1 \
+ git send-email \
+ --compose \
+ --from="Example <from@example.com>" \
+ --to=nobody@example.com \
+ --smtp-server="$(pwd)/fake.sendmail" \
+ HEAD^ &&
+ # Check both that the cover letter used our modified "to" line,
+ # but also that it was picked up for the patch.
+ q_to_tab >expect <<-\EOF &&
+ To: nobody@example.com,
+ Qedited-to@example.com
+ EOF
+ grep -A1 "^To:" msgtxt1 >msgtxt1.to &&
+ test_cmp expect msgtxt1.to &&
+ grep -A1 "^To:" msgtxt2 >msgtxt2.to &&
+ test_cmp expect msgtxt2.to
+'
+
test_done