aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/RelNotes/2.40.0.txt29
-rw-r--r--Documentation/config/format.txt3
-rw-r--r--Documentation/git-archive.txt5
-rw-r--r--Documentation/git-credential.txt6
-rw-r--r--Documentation/git-hook.txt7
-rw-r--r--Documentation/git-ls-remote.txt19
-rw-r--r--Documentation/gitattributes.txt31
-rw-r--r--Documentation/gitcredentials.txt2
-rw-r--r--Documentation/rev-list-options.txt10
-rwxr-xr-xGIT-VERSION-GEN2
-rw-r--r--archive.c8
-rw-r--r--archive.h1
-rw-r--r--builtin/am.c26
-rw-r--r--builtin/clean.c1
-rw-r--r--builtin/clone.c5
-rw-r--r--builtin/commit-graph.c10
-rw-r--r--builtin/commit.c18
-rw-r--r--builtin/credential-cache--daemon.c3
-rw-r--r--builtin/fetch.c3
-rw-r--r--builtin/hook.c4
-rw-r--r--builtin/log.c2
-rw-r--r--builtin/ls-remote.c2
-rw-r--r--builtin/merge.c22
-rw-r--r--builtin/mv.c8
-rw-r--r--builtin/name-rev.c37
-rw-r--r--builtin/push.c30
-rw-r--r--builtin/receive-pack.c11
-rw-r--r--builtin/repack.c13
-rw-r--r--builtin/reset.c11
-rw-r--r--builtin/rm.c2
-rw-r--r--builtin/show-branch.c1
-rw-r--r--builtin/stash.c18
-rw-r--r--builtin/update-index.c4
-rw-r--r--builtin/worktree.c6
-rw-r--r--builtin/write-tree.c5
-rw-r--r--bundle.c6
-rw-r--r--cache-tree.c3
-rw-r--r--cache-tree.h15
-rw-r--r--cache.h12
-rw-r--r--contrib/coccinelle/index-compatibility.cocci36
-rw-r--r--contrib/coccinelle/index-compatibility.pending.cocci24
-rw-r--r--credential.c20
-rw-r--r--credential.h2
-rw-r--r--delta-islands.c12
-rw-r--r--diff.c90
-rw-r--r--diff.h1
-rw-r--r--dir-iterator.c12
-rw-r--r--dir-iterator.h20
-rw-r--r--gpg-interface.c8
-rw-r--r--grep.c15
-rw-r--r--hook.c5
-rw-r--r--hook.h5
-rw-r--r--http-backend.c9
-rw-r--r--range-diff.c11
-rw-r--r--refs.c93
-rw-r--r--run-command.c13
-rw-r--r--sequencer.c57
-rw-r--r--t/helper/test-ctype.c30
-rw-r--r--t/helper/test-dir-iterator.c6
-rw-r--r--t/helper/test-genzeros.c11
-rw-r--r--t/lib-diff-alternative.sh38
-rw-r--r--t/lib-httpd.sh7
-rw-r--r--t/lib-httpd/apache.conf16
-rw-r--r--t/lib-httpd/proxy-passwd1
-rwxr-xr-xt/t0023-crlf-am.sh1
-rwxr-xr-xt/t0066-dir-iterator.sh44
-rwxr-xr-xt/t0300-credentials.sh94
-rwxr-xr-xt/t1301-shared-repo.sh1
-rwxr-xr-xt/t1302-repo-version.sh1
-rwxr-xr-xt/t1304-default-acl.sh1
-rwxr-xr-xt/t1401-symbolic-ref.sh34
-rwxr-xr-xt/t1408-packed-refs.sh1
-rwxr-xr-xt/t1410-reflog.sh1
-rwxr-xr-xt/t1416-ref-transaction-hooks.sh1
-rwxr-xr-xt/t1451-fsck-buffer.sh2
-rwxr-xr-xt/t1800-hook.sh18
-rwxr-xr-xt/t2015-checkout-unborn.sh11
-rwxr-xr-xt/t2401-worktree-prune.sh1
-rwxr-xr-xt/t2402-worktree-list.sh1
-rwxr-xr-xt/t2406-worktree-repair.sh1
-rwxr-xr-xt/t3206-range-diff.sh32
-rwxr-xr-xt/t3210-pack-refs.sh1
-rwxr-xr-xt/t3404-rebase-interactive.sh23
-rwxr-xr-xt/t3800-mktag.sh1
-rwxr-xr-xt/t4014-format-patch.sh18
-rwxr-xr-xt/t4152-am-subjects.sh2
-rwxr-xr-xt/t4254-am-corrupt.sh2
-rwxr-xr-xt/t4256-am-format-flowed.sh1
-rwxr-xr-xt/t4257-am-interactive.sh2
-rwxr-xr-xt/t5000-tar-tree.sh19
-rwxr-xr-xt/t5001-archive-attr.sh1
-rwxr-xr-xt/t5004-archive-corner-cases.sh2
-rwxr-xr-xt/t5302-pack-index.sh2
-rwxr-xr-xt/t5306-pack-nobase.sh2
-rwxr-xr-xt/t5312-prune-corruption.sh1
-rwxr-xr-xt/t5317-pack-objects-filter-objects.sh1
-rwxr-xr-xt/t5319-multi-pack-index.sh16
-rwxr-xr-xt/t5330-no-lazy-fetch-with-commit-graph.sh1
-rwxr-xr-xt/t5403-post-checkout-hook.sh1
-rwxr-xr-xt/t5405-send-pack-rewind.sh1
-rwxr-xr-xt/t5406-remote-rejects.sh1
-rwxr-xr-xt/t5502-quickfetch.sh1
-rwxr-xr-xt/t5504-fetch-receive-strict.sh1
-rwxr-xr-xt/t5507-remote-environment.sh2
-rwxr-xr-xt/t5514-fetch-multiple.sh5
-rwxr-xr-xt/t5522-pull-symlink.sh1
-rwxr-xr-xt/t5523-push-upstream.sh1
-rwxr-xr-xt/t5527-fetch-odd-refs.sh1
-rwxr-xr-xt/t5529-push-errors.sh2
-rwxr-xr-xt/t5546-receive-limits.sh2
-rwxr-xr-xt/t5547-push-quarantine.sh2
-rwxr-xr-xt/t5560-http-backend-noserver.sh1
-rwxr-xr-xt/t5561-http-backend.sh1
-rwxr-xr-xt/t5562-http-backend-content-length.sh2
-rwxr-xr-xt/t5564-http-proxy.sh41
-rwxr-xr-xt/t5573-pull-verify-signatures.sh2
-rwxr-xr-xt/t5604-clone-reference.sh1
-rwxr-xr-xt/t5606-clone-options.sh1
-rwxr-xr-xt/t5613-info-alternate.sh2
-rwxr-xr-xt/t5705-session-id-in-capabilities.sh1
-rwxr-xr-xt/t5810-proto-disable-local.sh2
-rwxr-xr-xt/t5813-proto-disable-ssh.sh2
-rwxr-xr-xt/t6011-rev-list-with-bad-commit.sh1
-rwxr-xr-xt/t6014-rev-list-all.sh1
-rwxr-xr-xt/t6021-rev-list-exclude-hidden.sh1
-rwxr-xr-xt/t6120-describe.sh6
-rwxr-xr-xt/t6439-merge-co-error-msgs.sh1
-rwxr-xr-xt/t6501-freshen-objects.sh1
-rwxr-xr-xt/t7105-reset-patch.sh2
-rwxr-xr-xt/t7106-reset-unborn-branch.sh2
-rwxr-xr-xt/t7107-reset-pathspec-file.sh1
-rwxr-xr-xt/t7301-clean-interactive.sh1
-rwxr-xr-xt/t7403-submodule-sync.sh1
-rwxr-xr-xt/t7409-submodule-detached-work-tree.sh1
-rwxr-xr-xt/t7416-submodule-dash-url.sh2
-rwxr-xr-xt/t7450-bad-git-dotfiles.sh2
-rwxr-xr-xt/t7510-signed-commit.sh44
-rwxr-xr-xt/t7612-merge-verify-signatures.sh1
-rwxr-xr-xt/t7701-repack-unpack-unreachable.sh1
-rw-r--r--userdiff.c4
-rw-r--r--userdiff.h1
141 files changed, 1052 insertions, 382 deletions
diff --git a/Documentation/RelNotes/2.40.0.txt b/Documentation/RelNotes/2.40.0.txt
index d1428f5fb8..922cf22af3 100644
--- a/Documentation/RelNotes/2.40.0.txt
+++ b/Documentation/RelNotes/2.40.0.txt
@@ -54,6 +54,9 @@ UI, Workflows & Features
* Userdiff regexp update for Java language.
+ * "git fetch --jobs=0" used to hit a BUG(), which has been corrected
+ to use the available CPUs.
+
Performance, Internal Implementation, Development Support etc.
@@ -223,6 +226,31 @@ Fixes since v2.39
back to interpreted execution in such a case.
(merge 50b6ad55b0 cb/grep-fallback-failing-jit later to maint).
+ * "git name-rev" heuristics update.
+ (merge b2182a8730 en/name-rev-make-taggerdate-much-less-important later to maint).
+
+ * Remove more remaining uses of macros that relies on the_index
+ singleton instance without explicitly spelling it out.
+
+ * Remove unnecessary explicit sizing of strbuf.
+ (merge 93ea118bed rs/cache-tree-strbuf-growth-fix later to maint).
+
+ * Doc update.
+ (merge d9ec3b0dc0 jk/doc-ls-remote-matching later to maint).
+
+ * Error messages given upon a signature verification failure used to
+ discard the errors from underlying gpg program, which has been
+ corrected.
+ (merge ad6b320756 js/gpg-errors later to maint).
+
+ * Update --date=default documentation.
+ (merge 9deef088ae rd/doc-default-date-format later to maint).
+
+ * A test helper had a single write(2) of 256kB, which was too big for
+ some platforms (e.g. NonStop), which has been corrected by using
+ xwrite() wrapper appropriately.
+ (merge 58eab6ff13 jc/genzeros-avoid-raw-write later to maint).
+
* Other code cleanup, docfix, build fix, etc.
(merge 4eb1ccecd4 dh/mingw-ownership-check-typofix later to maint).
(merge f95526419b ar/typofix-gitattributes-doc later to maint).
@@ -249,3 +277,4 @@ Fixes since v2.39
(merge e65b868d07 rs/size-t-fixes later to maint).
(merge 3eb1e1ca9a ab/config-h-remove-unused later to maint).
(merge d390e08076 cw/doc-pushurl-vs-url later to maint).
+ (merge 567342fc77 rs/ctype-test later to maint).
diff --git a/Documentation/config/format.txt b/Documentation/config/format.txt
index 3bd78269e2..73678d88a1 100644
--- a/Documentation/config/format.txt
+++ b/Documentation/config/format.txt
@@ -3,7 +3,8 @@ format.attach::
'format-patch'. The value can also be a double quoted string
which will enable attachments as the default and set the
value as the boundary. See the --attach option in
- linkgit:git-format-patch[1].
+ linkgit:git-format-patch[1]. To countermand an earlier
+ value, set it to an empty string.
format.from::
Provides the default value for the `--from` option to format-patch.
diff --git a/Documentation/git-archive.txt b/Documentation/git-archive.txt
index 60c040988b..6bab201d37 100644
--- a/Documentation/git-archive.txt
+++ b/Documentation/git-archive.txt
@@ -86,6 +86,11 @@ cases, write an untracked file and use `--add-file` instead.
Look for attributes in .gitattributes files in the working tree
as well (see <<ATTRIBUTES>>).
+--mtime=<time>::
+ Set modification time of archive entries. Without this option
+ the committer time is used if `<tree-ish>` is a commit or tag,
+ and the current time if it is a tree.
+
<extra>::
This can be any options that the archiver backend understands.
See next section.
diff --git a/Documentation/git-credential.txt b/Documentation/git-credential.txt
index ac2818b9f6..29d184ab82 100644
--- a/Documentation/git-credential.txt
+++ b/Documentation/git-credential.txt
@@ -144,6 +144,12 @@ Git understands the following attributes:
The credential's password, if we are asking it to be stored.
+`password_expiry_utc`::
+
+ Generated passwords such as an OAuth access token may have an expiry date.
+ When reading credentials from helpers, `git credential fill` ignores expired
+ passwords. Represented as Unix time UTC, seconds since 1970.
+
`url`::
When this special attribute is read by `git credential`, the
diff --git a/Documentation/git-hook.txt b/Documentation/git-hook.txt
index 77c3a8ad90..3407f3c2c0 100644
--- a/Documentation/git-hook.txt
+++ b/Documentation/git-hook.txt
@@ -8,7 +8,7 @@ git-hook - Run git hooks
SYNOPSIS
--------
[verse]
-'git hook' run [--ignore-missing] <hook-name> [-- <hook-args>]
+'git hook' run [--ignore-missing] [--to-stdin=<path>] <hook-name> [-- <hook-args>]
DESCRIPTION
-----------
@@ -31,6 +31,11 @@ linkgit:githooks[5] for arguments hooks might expect (if any).
OPTIONS
-------
+--to-stdin::
+ For "run"; Specify a file which will be streamed into the
+ hook's stdin. The hook will receive the entire file from
+ beginning to EOF.
+
--ignore-missing::
Ignore any missing hook by quietly returning zero. Used for
tools that want to do a blind one-shot run of a hook that may
diff --git a/Documentation/git-ls-remote.txt b/Documentation/git-ls-remote.txt
index 492e573856..ff3da547dd 100644
--- a/Documentation/git-ls-remote.txt
+++ b/Documentation/git-ls-remote.txt
@@ -11,7 +11,7 @@ SYNOPSIS
[verse]
'git ls-remote' [--heads] [--tags] [--refs] [--upload-pack=<exec>]
[-q | --quiet] [--exit-code] [--get-url] [--sort=<key>]
- [--symref] [<repository> [<refs>...]]
+ [--symref] [<repository> [<patterns>...]]
DESCRIPTION
-----------
@@ -85,25 +85,32 @@ OPTIONS
either a URL or the name of a remote (see the GIT URLS and
REMOTES sections of linkgit:git-fetch[1]).
-<refs>...::
+<patterns>...::
When unspecified, all references, after filtering done
- with --heads and --tags, are shown. When <refs>... are
- specified, only references matching the given patterns
- are displayed.
+ with --heads and --tags, are shown. When <patterns>... are
+ specified, only references matching one or more of the given
+ patterns are displayed. Each pattern is interpreted as a glob
+ (see `glob` in linkgit:gitglossary[7]) which is matched against
+ the "tail" of a ref, starting either from the start of the ref
+ (so a full name like `refs/heads/foo` matches) or from a slash
+ separator (so `bar` matches `refs/heads/bar` but not
+ `refs/heads/foobar`).
EXAMPLES
--------
----
-$ git ls-remote --tags ./.
+$ git ls-remote --tags .
d6602ec5194c87b0fc87103ca4d67251c76f233a refs/tags/v0.99
f25a265a342aed6041ab0cc484224d9ca54b6f41 refs/tags/v0.99.1
7ceca275d047c90c0c7d5afb13ab97efdf51bd6e refs/tags/v0.99.3
c5db5456ae3b0873fc659c19fafdde22313cc441 refs/tags/v0.99.2
0918385dbd9656cab0d1d81ba7453d49bbc16250 refs/tags/junio-gpg-pub
+
$ git ls-remote http://www.kernel.org/pub/scm/git/git.git master seen rc
5fe978a5381f1fbad26a80e682ddd2a401966740 refs/heads/master
c781a84b5204fb294c9ccc79f8b3baceeb32c061 refs/heads/seen
+
$ git remote add korg http://www.kernel.org/pub/scm/git/git.git
$ git ls-remote --tags korg v\*
d6602ec5194c87b0fc87103ca4d67251c76f233a refs/tags/v0.99
diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt
index c19e64ea0e..39bfbca1ff 100644
--- a/Documentation/gitattributes.txt
+++ b/Documentation/gitattributes.txt
@@ -758,6 +758,37 @@ with the above configuration, i.e. `j-c-diff`, with 7
parameters, just like `GIT_EXTERNAL_DIFF` program is called.
See linkgit:git[1] for details.
+Setting the internal diff algorithm
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The diff algorithm can be set through the `diff.algorithm` config key, but
+sometimes it may be helpful to set the diff algorithm per path. For example,
+one may want to use the `minimal` diff algorithm for .json files, and the
+`histogram` for .c files, and so on without having to pass in the algorithm
+through the command line each time.
+
+First, in `.gitattributes`, assign the `diff` attribute for paths.
+
+------------------------
+*.json diff=<name>
+------------------------
+
+Then, define a "diff.<name>.algorithm" configuration to specify the diff
+algorithm, choosing from `myers`, `patience`, `minimal`, or `histogram`.
+
+----------------------------------------------------------------
+[diff "<name>"]
+ algorithm = histogram
+----------------------------------------------------------------
+
+This diff algorithm applies to user facing diff output like git-diff(1),
+git-show(1) and is used for the `--stat` output as well. The merge machinery
+will not use the diff algorithm set through this method.
+
+NOTE: If `diff.<name>.command` is defined for path with the
+`diff=<name>` attribute, it is executed as an external diff driver
+(see above), and adding `diff.<name>.algorithm` has no effect, as the
+algorithm is not passed to the external diff driver.
Defining a custom hunk-header
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/Documentation/gitcredentials.txt b/Documentation/gitcredentials.txt
index 4522471c33..100f045bb1 100644
--- a/Documentation/gitcredentials.txt
+++ b/Documentation/gitcredentials.txt
@@ -167,7 +167,7 @@ helper::
If there are multiple instances of the `credential.helper` configuration
variable, each helper will be tried in turn, and may provide a username,
password, or nothing. Once Git has acquired both a username and a
-password, no more helpers will be tried.
+non-expired password, no more helpers will be tried.
+
If `credential.helper` is configured to the empty string, this resets
the helper list to empty (so you may override a helper set by a
diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt
index ff68e48406..0d90d5b154 100644
--- a/Documentation/rev-list-options.txt
+++ b/Documentation/rev-list-options.txt
@@ -1100,12 +1100,12 @@ preferred format. See the `strftime` manual for a complete list of
format placeholders. When using `-local`, the correct syntax is
`--date=format-local:...`.
-`--date=default` is the default format, and is similar to
-`--date=rfc2822`, with a few exceptions:
+`--date=default` is the default format, and is based on ctime(3)
+output. It shows a single line with three-letter day of the week,
+three-letter month, day-of-month, hour-minute-seconds in "HH:MM:SS"
+format, followed by 4-digit year, plus timezone information, unless
+the local time zone is used, e.g. `Thu Jan 1 00:00:00 1970 +0000`.
--
- - there is no comma after the day-of-week
-
- - the time zone is omitted when the local time zone is used
ifdef::git-rev-list[]
--header::
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index c4c2d3e022..dd62a3ea59 100755
--- a/GIT-VERSION-GEN
+++ b/GIT-VERSION-GEN
@@ -1,7 +1,7 @@
#!/bin/sh
GVF=GIT-VERSION-FILE
-DEF_VER=v2.39.GIT
+DEF_VER=v2.40.0-rc0
LF='
'
diff --git a/archive.c b/archive.c
index 81ff76fce9..9aeaf2bd87 100644
--- a/archive.c
+++ b/archive.c
@@ -472,6 +472,8 @@ static void parse_treeish_arg(const char **argv,
commit_oid = NULL;
archive_time = time(NULL);
}
+ if (ar_args->mtime_option)
+ archive_time = approxidate(ar_args->mtime_option);
tree = parse_tree_indirect(&oid);
if (!tree)
@@ -586,6 +588,7 @@ static int parse_archive_args(int argc, const char **argv,
const char *remote = NULL;
const char *exec = NULL;
const char *output = NULL;
+ const char *mtime_option = NULL;
int compression_level = -1;
int verbose = 0;
int i;
@@ -607,6 +610,9 @@ static int parse_archive_args(int argc, const char **argv,
OPT_BOOL(0, "worktree-attributes", &worktree_attributes,
N_("read .gitattributes in working directory")),
OPT__VERBOSE(&verbose, N_("report archived files on stderr")),
+ { OPTION_STRING, 0, "mtime", &mtime_option, N_("time"),
+ N_("set modification time of archive entries"),
+ PARSE_OPT_NONEG },
OPT_NUMBER_CALLBACK(&compression_level,
N_("set compression level"), number_callback),
OPT_GROUP(""),
@@ -668,6 +674,7 @@ static int parse_archive_args(int argc, const char **argv,
args->base = base;
args->baselen = strlen(base);
args->worktree_attributes = worktree_attributes;
+ args->mtime_option = mtime_option;
return argc;
}
@@ -710,6 +717,7 @@ int write_archive(int argc, const char **argv, const char *prefix,
string_list_clear_func(&args.extra_files, extra_file_info_clear);
free(args.refname);
+ clear_pathspec(&args.pathspec);
return rc;
}
diff --git a/archive.h b/archive.h
index 08bed3ed3a..7178e2a9a2 100644
--- a/archive.h
+++ b/archive.h
@@ -16,6 +16,7 @@ struct archiver_args {
struct tree *tree;
const struct object_id *commit_oid;
const struct commit *commit;
+ const char *mtime_option;
timestamp_t time;
struct pathspec pathspec;
unsigned int verbose : 1;
diff --git a/builtin/am.c b/builtin/am.c
index 82a41cbfc4..e0848ddadf 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -3,7 +3,7 @@
*
* Based on git-am.sh by Junio C Hamano.
*/
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
+#define USE_THE_INDEX_VARIABLE
#include "cache.h"
#include "config.h"
#include "builtin.h"
@@ -495,24 +495,12 @@ static int run_applypatch_msg_hook(struct am_state *state)
*/
static int run_post_rewrite_hook(const struct am_state *state)
{
- struct child_process cp = CHILD_PROCESS_INIT;
- const char *hook = find_hook("post-rewrite");
- int ret;
-
- if (!hook)
- return 0;
+ struct run_hooks_opt opt = RUN_HOOKS_OPT_INIT;
- strvec_push(&cp.args, hook);
- strvec_push(&cp.args, "rebase");
+ strvec_push(&opt.args, "rebase");
+ opt.path_to_stdin = am_path(state, "rewritten");
- cp.in = xopen(am_path(state, "rewritten"), O_RDONLY);
- cp.stdout_to_stderr = 1;
- cp.trace2_hook_name = "post-rewrite";
-
- ret = run_command(&cp);
-
- close(cp.in);
- return ret;
+ return run_hooks_opt("post-rewrite", &opt);
}
/**
@@ -1655,7 +1643,7 @@ static void do_commit(const struct am_state *state)
if (!state->no_verify && run_hooks("pre-applypatch"))
exit(1);
- if (write_cache_as_tree(&tree, 0, NULL))
+ if (write_index_as_tree(&tree, &the_index, get_index_file(), 0, NULL))
die(_("git write-tree failed to write a tree"));
if (!get_oid_commit("HEAD", &parent)) {
@@ -2063,7 +2051,7 @@ static int clean_index(const struct object_id *head, const struct object_id *rem
if (fast_forward_to(head_tree, head_tree, 1))
return -1;
- if (write_cache_as_tree(&index, 0, NULL))
+ if (write_index_as_tree(&index, &the_index, get_index_file(), 0, NULL))
return -1;
index_tree = parse_tree_indirect(&index);
diff --git a/builtin/clean.c b/builtin/clean.c
index 1e6d491d3b..10aaa8c603 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -1092,5 +1092,6 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
strbuf_release(&buf);
string_list_clear(&del_list, 0);
string_list_clear(&exclude_list, 0);
+ clear_pathspec(&pathspec);
return (errors != 0);
}
diff --git a/builtin/clone.c b/builtin/clone.c
index 5691364ea1..65b5b7db6d 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -892,6 +892,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
int is_bundle = 0, is_local;
int reject_shallow = 0;
const char *repo_name, *repo, *work_tree, *git_dir;
+ char *repo_to_free = NULL;
char *path = NULL, *dir, *display_repo = NULL;
int dest_exists, real_dest_exists = 0;
const struct ref *refs, *remote_head;
@@ -949,7 +950,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
path = get_repo_path(repo_name, &is_bundle);
if (path) {
FREE_AND_NULL(path);
- repo = absolute_pathdup(repo_name);
+ repo = repo_to_free = absolute_pathdup(repo_name);
} else if (strchr(repo_name, ':')) {
repo = repo_name;
display_repo = transport_anonymize_url(repo);
@@ -1417,7 +1418,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
free(unborn_head);
free(dir);
free(path);
- UNLEAK(repo);
+ free(repo_to_free);
junk_mode = JUNK_LEAVE_ALL;
transport_ls_refs_options_release(&transport_ls_refs_options);
diff --git a/builtin/commit-graph.c b/builtin/commit-graph.c
index e8f77f535f..93704f95a9 100644
--- a/builtin/commit-graph.c
+++ b/builtin/commit-graph.c
@@ -67,6 +67,7 @@ static int graph_verify(int argc, const char **argv, const char *prefix)
int fd;
struct stat st;
int flags = 0;
+ int ret;
static struct option builtin_commit_graph_verify_options[] = {
OPT_BOOL(0, "shallow", &opts.shallow,
@@ -111,8 +112,9 @@ static int graph_verify(int argc, const char **argv, const char *prefix)
if (!graph)
return !!open_ok;
- UNLEAK(graph);
- return verify_commit_graph(the_repository, graph, flags);
+ ret = verify_commit_graph(the_repository, graph, flags);
+ free_commit_graph(graph);
+ return ret;
}
extern int read_replace_refs;
@@ -267,8 +269,8 @@ static int graph_write(int argc, const char **argv, const char *prefix)
if (opts.reachable) {
if (write_commit_graph_reachable(odb, flags, &write_opts))
- return 1;
- return 0;
+ result = 1;
+ goto cleanup;
}
if (opts.stdin_packs) {
diff --git a/builtin/commit.c b/builtin/commit.c
index 44b763d7cd..985a0445b7 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -5,7 +5,7 @@
* Based on git-commit.sh by Junio C Hamano and Linus Torvalds
*/
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
+#define USE_THE_INDEX_VARIABLE
#include "cache.h"
#include "config.h"
#include "lockfile.h"
@@ -414,7 +414,7 @@ static const char *prepare_index(const char **argv, const char *prefix,
discard_index(&the_index);
read_index_from(&the_index, get_lock_file_path(&index_lock),
get_git_dir());
- if (update_main_cache_tree(WRITE_TREE_SILENT) == 0) {
+ if (cache_tree_update(&the_index, WRITE_TREE_SILENT) == 0) {
if (reopen_lock_file(&index_lock) < 0)
die(_("unable to write index file"));
if (write_locked_index(&the_index, &index_lock, 0))
@@ -444,7 +444,7 @@ static const char *prepare_index(const char **argv, const char *prefix,
LOCK_DIE_ON_ERROR);
add_files_to_cache(also ? prefix : NULL, &pathspec, 0);
refresh_cache_or_die(refresh_flags);
- update_main_cache_tree(WRITE_TREE_SILENT);
+ cache_tree_update(&the_index, WRITE_TREE_SILENT);
if (write_locked_index(&the_index, &index_lock, 0))
die(_("unable to write new_index file"));
commit_style = COMMIT_NORMAL;
@@ -467,7 +467,7 @@ static const char *prepare_index(const char **argv, const char *prefix,
refresh_cache_or_die(refresh_flags);
if (the_index.cache_changed
|| !cache_tree_fully_valid(the_index.cache_tree))
- update_main_cache_tree(WRITE_TREE_SILENT);
+ 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"));
@@ -516,7 +516,7 @@ static const char *prepare_index(const char **argv, const char *prefix,
repo_hold_locked_index(the_repository, &index_lock, LOCK_DIE_ON_ERROR);
add_remove_files(&partial);
refresh_index(&the_index, REFRESH_QUIET, NULL, NULL, NULL);
- update_main_cache_tree(WRITE_TREE_SILENT);
+ cache_tree_update(&the_index, WRITE_TREE_SILENT);
if (write_locked_index(&the_index, &index_lock, 0))
die(_("unable to write new_index file"));
@@ -991,9 +991,9 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
struct object_id oid;
const char *parent = "HEAD";
- if (!active_nr) {
- discard_cache();
- if (read_cache() < 0)
+ if (!the_index.cache_nr) {
+ discard_index(&the_index);
+ if (repo_read_index(the_repository) < 0)
die(_("Cannot read index"));
}
@@ -1079,7 +1079,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
}
read_index_from(&the_index, index_file, get_git_dir());
- if (update_main_cache_tree(0)) {
+ if (cache_tree_update(&the_index, 0)) {
error(_("Error building trees"));
return 0;
}
diff --git a/builtin/credential-cache--daemon.c b/builtin/credential-cache--daemon.c
index f3c89831d4..338058be7f 100644
--- a/builtin/credential-cache--daemon.c
+++ b/builtin/credential-cache--daemon.c
@@ -127,6 +127,9 @@ static void serve_one_client(FILE *in, FILE *out)
if (e) {
fprintf(out, "username=%s\n", e->item.username);
fprintf(out, "password=%s\n", e->item.password);
+ if (e->item.password_expiry_utc != TIME_MAX)
+ fprintf(out, "password_expiry_utc=%"PRItime"\n",
+ e->item.password_expiry_utc);
}
}
else if (!strcmp(action.buf, "exit")) {
diff --git a/builtin/fetch.c b/builtin/fetch.c
index a21ce89312..a09606b472 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -2196,6 +2196,9 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
if (dry_run)
write_fetch_head = 0;
+ if (!max_jobs)
+ max_jobs = online_cpus();
+
if (!git_config_get_string_tmp("fetch.bundleuri", &bundle_uri) &&
fetch_bundle_uri(the_repository, bundle_uri, NULL))
warning(_("failed to fetch bundles from '%s'"), bundle_uri);
diff --git a/builtin/hook.c b/builtin/hook.c
index b6530d189a..f95b7965c5 100644
--- a/builtin/hook.c
+++ b/builtin/hook.c
@@ -7,7 +7,7 @@
#include "strvec.h"
#define BUILTIN_HOOK_RUN_USAGE \
- N_("git hook run [--ignore-missing] <hook-name> [-- <hook-args>]")
+ N_("git hook run [--ignore-missing] [--to-stdin=<path>] <hook-name> [-- <hook-args>]")
static const char * const builtin_hook_usage[] = {
BUILTIN_HOOK_RUN_USAGE,
@@ -28,6 +28,8 @@ static int run(int argc, const char **argv, const char *prefix)
struct option run_options[] = {
OPT_BOOL(0, "ignore-missing", &ignore_missing,
N_("silently ignore missing requested <hook-name>")),
+ OPT_STRING(0, "to-stdin", &opt.path_to_stdin, N_("path"),
+ N_("file to read into hooks' stdin")),
OPT_END(),
};
int ret;
diff --git a/builtin/log.c b/builtin/log.c
index 04412dd9c9..a70fba198f 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -1007,6 +1007,8 @@ static int git_format_config(const char *var, const char *value, void *cb)
if (!strcmp(var, "format.attach")) {
if (value && *value)
default_attach = xstrdup(value);
+ else if (value && !*value)
+ FREE_AND_NULL(default_attach);
else
default_attach = xstrdup(git_version_string);
return 0;
diff --git a/builtin/ls-remote.c b/builtin/ls-remote.c
index 5d5ac03871..6516177348 100644
--- a/builtin/ls-remote.c
+++ b/builtin/ls-remote.c
@@ -8,7 +8,7 @@
static const char * const ls_remote_usage[] = {
N_("git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<exec>]\n"
" [-q | --quiet] [--exit-code] [--get-url] [--sort=<key>]\n"
- " [--symref] [<repository> [<refs>...]]"),
+ " [--symref] [<repository> [<patterns>...]]"),
NULL
};
diff --git a/builtin/merge.c b/builtin/merge.c
index 74de2ebd2b..0a3c10a096 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -6,7 +6,7 @@
* Based on git-merge.sh by Junio C Hamano.
*/
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
+#define USE_THE_INDEX_VARIABLE
#include "cache.h"
#include "config.h"
#include "parse-options.h"
@@ -390,8 +390,8 @@ static void restore_state(const struct object_id *head,
run_command(&cmd);
refresh_cache:
- discard_cache();
- if (read_cache() < 0)
+ discard_index(&the_index);
+ if (repo_read_index(the_repository) < 0)
die(_("could not read index"));
}
@@ -706,7 +706,7 @@ static int read_tree_trivial(struct object_id *common, struct object_id *head,
static void write_tree_trivial(struct object_id *oid)
{
- if (write_cache_as_tree(oid, 0, NULL))
+ if (write_index_as_tree(oid, &the_index, get_index_file(), 0, NULL))
die(_("git write-tree failed to write a tree"));
}
@@ -1560,7 +1560,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
!common->next &&
oideq(&common->item->object.oid, &head_commit->object.oid)) {
/* Again the most common case of merging one remote. */
- struct strbuf msg = STRBUF_INIT;
+ const char *msg = have_message ?
+ "Fast-forward (no commit created; -m option ignored)" :
+ "Fast-forward";
struct commit *commit;
if (verbosity >= 0) {
@@ -1570,10 +1572,6 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
find_unique_abbrev(&remoteheads->item->object.oid,
DEFAULT_ABBREV));
}
- strbuf_addstr(&msg, "Fast-forward");
- if (have_message)
- strbuf_addstr(&msg,
- " (no commit created; -m option ignored)");
commit = remoteheads->item;
if (!commit) {
ret = 1;
@@ -1592,9 +1590,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
goto done;
}
- finish(head_commit, remoteheads, &commit->object.oid, msg.buf);
+ finish(head_commit, remoteheads, &commit->object.oid, msg);
remove_merge_branch_state(the_repository);
- strbuf_release(&msg);
goto done;
} else if (!remoteheads->next && common->next)
;
@@ -1621,7 +1618,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
error(_("Your local changes to the following files would be overwritten by merge:\n %s"),
sb.buf);
strbuf_release(&sb);
- return 2;
+ ret = 2;
+ goto done;
}
/* See if it is really trivial. */
diff --git a/builtin/mv.c b/builtin/mv.c
index 19790ce38f..edd7b931fd 100644
--- a/builtin/mv.c
+++ b/builtin/mv.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2006 Johannes Schindelin
*/
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
+#define USE_THE_INDEX_VARIABLE
#include "builtin.h"
#include "config.h"
#include "pathspec.h"
@@ -489,7 +489,8 @@ remove_entry:
if ((mode & SPARSE) &&
path_in_sparse_checkout(dst, &the_index)) {
/* from out-of-cone to in-cone */
- int dst_pos = cache_name_pos(dst, strlen(dst));
+ int dst_pos = index_name_pos(&the_index, dst,
+ strlen(dst));
struct cache_entry *dst_ce = the_index.cache[dst_pos];
dst_ce->ce_flags &= ~CE_SKIP_WORKTREE;
@@ -500,7 +501,8 @@ remove_entry:
!(mode & SPARSE) &&
!path_in_sparse_checkout(dst, &the_index)) {
/* from in-cone to out-of-cone */
- int dst_pos = cache_name_pos(dst, strlen(dst));
+ int dst_pos = index_name_pos(&the_index, dst,
+ strlen(dst));
struct cache_entry *dst_ce = the_index.cache[dst_pos];
/*
diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index 15535e914a..97959bfaf9 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -108,19 +108,11 @@ static int is_better_name(struct rev_name *name,
int name_distance = effective_distance(name->distance, name->generation);
int new_distance = effective_distance(distance, generation);
- /*
- * When comparing names based on tags, prefer names
- * based on the older tag, even if it is farther away.
- */
+ /* If both are tags, we prefer the nearer one. */
if (from_tag && name->from_tag)
- return (name->taggerdate > taggerdate ||
- (name->taggerdate == taggerdate &&
- name_distance > new_distance));
+ return name_distance > new_distance;
- /*
- * We know that at least one of them is a non-tag at this point.
- * favor a tag over a non-tag.
- */
+ /* Favor a tag over a non-tag. */
if (name->from_tag != from_tag)
return from_tag;
@@ -273,17 +265,6 @@ static int subpath_matches(const char *path, const char *filter)
return -1;
}
-static const char *name_ref_abbrev(const char *refname, int shorten_unambiguous)
-{
- if (shorten_unambiguous)
- refname = shorten_unambiguous_ref(refname, 0);
- else if (skip_prefix(refname, "refs/heads/", &refname))
- ; /* refname already advanced */
- else
- skip_prefix(refname, "refs/", &refname);
- return refname;
-}
-
struct name_ref_data {
int tags_only;
int name_only;
@@ -309,11 +290,19 @@ static void add_to_tip_table(const struct object_id *oid, const char *refname,
int shorten_unambiguous, struct commit *commit,
timestamp_t taggerdate, int from_tag, int deref)
{
- refname = name_ref_abbrev(refname, shorten_unambiguous);
+ char *short_refname = NULL;
+
+ if (shorten_unambiguous)
+ short_refname = shorten_unambiguous_ref(refname, 0);
+ else if (skip_prefix(refname, "refs/heads/", &refname))
+ ; /* refname already advanced */
+ else
+ skip_prefix(refname, "refs/", &refname);
ALLOC_GROW(tip_table.table, tip_table.nr + 1, tip_table.alloc);
oidcpy(&tip_table.table[tip_table.nr].oid, oid);
- tip_table.table[tip_table.nr].refname = xstrdup(refname);
+ tip_table.table[tip_table.nr].refname = short_refname ?
+ short_refname : xstrdup(refname);
tip_table.table[tip_table.nr].commit = commit;
tip_table.table[tip_table.nr].taggerdate = taggerdate;
tip_table.table[tip_table.nr].from_tag = from_tag;
diff --git a/builtin/push.c b/builtin/push.c
index 60ac8017e5..8f7d326ab3 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -63,16 +63,9 @@ static struct refspec rs = REFSPEC_INIT_PUSH;
static struct string_list push_options_config = STRING_LIST_INIT_DUP;
static void refspec_append_mapped(struct refspec *refspec, const char *ref,
- struct remote *remote, struct ref *local_refs)
+ struct remote *remote, struct ref *matched)
{
const char *branch_name;
- struct ref *matched = NULL;
-
- /* Does "ref" uniquely name our ref? */
- if (count_refspec_match(ref, local_refs, &matched) != 1) {
- refspec_append(refspec, ref);
- return;
- }
if (remote->push.nr) {
struct refspec_item query;
@@ -120,15 +113,28 @@ static void set_refspecs(const char **refs, int nr, const char *repo)
die(_("--delete only accepts plain target ref names"));
refspec_appendf(&rs, ":%s", ref);
} else if (!strchr(ref, ':')) {
- if (!remote) {
- /* lazily grab remote and local_refs */
- remote = remote_get(repo);
+ struct ref *matched = NULL;
+
+ /* lazily grab local_refs */
+ if (!local_refs)
local_refs = get_local_heads();
+
+ /* Does "ref" uniquely name our ref? */
+ if (count_refspec_match(ref, local_refs, &matched) != 1) {
+ refspec_append(&rs, ref);
+ } else {
+ /* lazily grab remote */
+ if (!remote)
+ remote = remote_get(repo);
+ if (!remote)
+ BUG("must get a remote for repo '%s'", repo);
+
+ refspec_append_mapped(&rs, ref, remote, matched);
}
- refspec_append_mapped(&rs, ref, remote, local_refs);
} else
refspec_append(&rs, ref);
}
+ free_refs(local_refs);
}
static int push_url_of_remote(struct remote *remote, const char ***url_p)
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index a90af30363..cd5c7a28ef 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -2032,6 +2032,16 @@ static struct command **queue_command(struct command **tail,
return &cmd->next;
}
+static void free_commands(struct command *commands)
+{
+ while (commands) {
+ struct command *next = commands->next;
+
+ free(commands);
+ commands = next;
+ }
+}
+
static void queue_commands_from_cert(struct command **tail,
struct strbuf *push_cert)
{
@@ -2569,6 +2579,7 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
run_receive_hook(commands, "post-receive", 1,
&push_options);
run_update_post_hook(commands);
+ free_commands(commands);
string_list_clear(&push_options, 0);
if (auto_gc) {
struct child_process proc = CHILD_PROCESS_INIT;
diff --git a/builtin/repack.c b/builtin/repack.c
index c1402ad038..f649379531 100644
--- a/builtin/repack.c
+++ b/builtin/repack.c
@@ -948,7 +948,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
ret = start_command(&cmd);
if (ret)
- return ret;
+ goto cleanup;
if (geometry) {
FILE *in = xfdopen(cmd.in, "w");
@@ -977,7 +977,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
fclose(out);
ret = finish_command(&cmd);
if (ret)
- return ret;
+ goto cleanup;
if (!names.nr && !po_args.quiet)
printf_ln(_("Nothing new to pack."));
@@ -1007,7 +1007,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
&existing_nonkept_packs,
&existing_kept_packs);
if (ret)
- return ret;
+ goto cleanup;
if (delete_redundant && expire_to) {
/*
@@ -1039,7 +1039,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
&existing_nonkept_packs,
&existing_kept_packs);
if (ret)
- return ret;
+ goto cleanup;
}
}
@@ -1115,7 +1115,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
string_list_clear(&include, 0);
if (ret)
- return ret;
+ goto cleanup;
}
reprepare_packed_git(the_repository);
@@ -1172,10 +1172,11 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
write_midx_file(get_object_directory(), NULL, NULL, flags);
}
+cleanup:
string_list_clear(&names, 1);
string_list_clear(&existing_nonkept_packs, 0);
string_list_clear(&existing_kept_packs, 0);
clear_pack_geometry(geometry);
- return 0;
+ return ret;
}
diff --git a/builtin/reset.c b/builtin/reset.c
index 4b59aa9aea..0697fa89de 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -391,8 +391,9 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
if (reset_type != NONE)
die(_("options '%s' and '%s' cannot be used together"), "--patch", "--{hard,mixed,soft}");
trace2_cmd_mode("patch-interactive");
- return !!run_add_p(the_repository, ADD_P_RESET, rev,
+ update_ref_status = !!run_add_p(the_repository, ADD_P_RESET, rev,
&pathspec);
+ goto cleanup;
}
/* git reset tree [--] paths... can be used to
@@ -441,8 +442,10 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
LOCK_DIE_ON_ERROR);
if (reset_type == MIXED) {
int flags = quiet ? REFRESH_QUIET : REFRESH_IN_PORCELAIN;
- if (read_from_tree(&pathspec, &oid, intent_to_add))
- return 1;
+ if (read_from_tree(&pathspec, &oid, intent_to_add)) {
+ update_ref_status = 1;
+ goto cleanup;
+ }
the_index.updated_skipworktree = 1;
if (!no_refresh && get_git_work_tree()) {
uint64_t t_begin, t_delta_in_ms;
@@ -490,5 +493,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
discard_index(&the_index);
+cleanup:
+ clear_pathspec(&pathspec);
return update_ref_status;
}
diff --git a/builtin/rm.c b/builtin/rm.c
index 4a4aec0d00..8844f90655 100644
--- a/builtin/rm.c
+++ b/builtin/rm.c
@@ -3,7 +3,7 @@
*
* Copyright (C) Linus Torvalds 2006
*/
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
+#define USE_THE_INDEX_VARIABLE
#include "builtin.h"
#include "advice.h"
#include "config.h"
diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index c013abaf94..358ac3e519 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -956,5 +956,6 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
if (shown_merge_point && --extra < 0)
break;
}
+ free(head);
return 0;
}
diff --git a/builtin/stash.c b/builtin/stash.c
index 9fcd2e5d99..3a4f9fd566 100644
--- a/builtin/stash.c
+++ b/builtin/stash.c
@@ -1,4 +1,4 @@
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
+#define USE_THE_INDEX_VARIABLE
#include "builtin.h"
#include "config.h"
#include "parse-options.h"
@@ -529,7 +529,8 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,
NULL, NULL, NULL))
return -1;
- if (write_cache_as_tree(&c_tree, 0, NULL))
+ if (write_index_as_tree(&c_tree, &the_index, get_index_file(), 0,
+ NULL))
return error(_("cannot apply a stash in the middle of a merge"));
if (index) {
@@ -553,7 +554,8 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,
discard_index(&the_index);
repo_read_index(the_repository);
- if (write_cache_as_tree(&index_tree, 0, NULL))
+ if (write_index_as_tree(&index_tree, &the_index,
+ get_index_file(), 0, NULL))
return error(_("could not save index tree"));
reset_head();
@@ -1378,7 +1380,8 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b
strbuf_addf(&commit_tree_label, "index on %s\n", msg.buf);
commit_list_insert(head_commit, &parents);
- if (write_cache_as_tree(&info->i_tree, 0, NULL) ||
+ if (write_index_as_tree(&info->i_tree, &the_index, get_index_file(), 0,
+ NULL) ||
commit_tree(commit_tree_label.buf, commit_tree_label.len,
&info->i_tree, parents, &info->i_commit, NULL, NULL)) {
if (!quiet)
@@ -1728,6 +1731,7 @@ static int push_stash(int argc, const char **argv, const char *prefix,
OPT_PATHSPEC_FILE_NUL(&pathspec_file_nul),
OPT_END()
};
+ int ret;
if (argc) {
force_assume = !strcmp(argv[0], "-p");
@@ -1767,8 +1771,10 @@ static int push_stash(int argc, const char **argv, const char *prefix,
die(_("the option '%s' requires '%s'"), "--pathspec-file-nul", "--pathspec-from-file");
}
- return do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
- include_untracked, only_staged);
+ ret = do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
+ include_untracked, only_staged);
+ clear_pathspec(&ps);
+ return ret;
}
static int push_stash_unassumed(int argc, const char **argv, const char *prefix)
diff --git a/builtin/update-index.c b/builtin/update-index.c
index 82d5902cc8..bf38885d54 100644
--- a/builtin/update-index.c
+++ b/builtin/update-index.c
@@ -3,7 +3,7 @@
*
* Copyright (C) Linus Torvalds, 2005
*/
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
+#define USE_THE_INDEX_VARIABLE
#include "cache.h"
#include "bulk-checkin.h"
#include "config.h"
@@ -381,7 +381,7 @@ static int process_path(const char *path, struct stat *st, int stat_errno)
if (has_symlink_leading_path(path, len))
return error("'%s' is beyond a symbolic link", path);
- pos = cache_name_pos(path, len);
+ pos = index_name_pos(&the_index, path, len);
ce = pos < 0 ? NULL : the_index.cache[pos];
if (ce && ce_skip_worktree(ce)) {
/*
diff --git a/builtin/worktree.c b/builtin/worktree.c
index f51c40f1e1..254283aa6f 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -173,7 +173,7 @@ static void prune_worktrees(void)
{
struct strbuf reason = STRBUF_INIT;
struct strbuf main_path = STRBUF_INIT;
- struct string_list kept = STRING_LIST_INIT_NODUP;
+ struct string_list kept = STRING_LIST_INIT_DUP;
DIR *dir = opendir(git_path("worktrees"));
struct dirent *d;
if (!dir)
@@ -184,14 +184,14 @@ static void prune_worktrees(void)
if (should_prune_worktree(d->d_name, &reason, &path, expire))
prune_worktree(d->d_name, reason.buf);
else if (path)
- string_list_append(&kept, path)->util = xstrdup(d->d_name);
+ string_list_append_nodup(&kept, path)->util = xstrdup(d->d_name);
}
closedir(dir);
strbuf_add_absolute_path(&main_path, get_git_common_dir());
/* massage main worktree absolute path to match 'gitdir' content */
strbuf_strip_suffix(&main_path, "/.");
- string_list_append(&kept, strbuf_detach(&main_path, NULL));
+ string_list_append_nodup(&kept, strbuf_detach(&main_path, NULL));
prune_dups(&kept);
string_list_clear(&kept, 1);
diff --git a/builtin/write-tree.c b/builtin/write-tree.c
index 45d61707e7..078010315f 100644
--- a/builtin/write-tree.c
+++ b/builtin/write-tree.c
@@ -3,7 +3,7 @@
*
* Copyright (C) Linus Torvalds, 2005
*/
-#define USE_THE_INDEX_COMPATIBILITY_MACROS
+#define USE_THE_INDEX_VARIABLE
#include "builtin.h"
#include "cache.h"
#include "config.h"
@@ -38,7 +38,8 @@ int cmd_write_tree(int argc, const char **argv, const char *cmd_prefix)
argc = parse_options(argc, argv, cmd_prefix, write_tree_options,
write_tree_usage, 0);
- ret = write_cache_as_tree(&oid, flags, tree_prefix);
+ ret = write_index_as_tree(&oid, &the_index, get_index_file(), flags,
+ tree_prefix);
switch (ret) {
case 0:
printf("%s\n", oid_to_hex(&oid));
diff --git a/bundle.c b/bundle.c
index 76c3a90489..6ab6cd7378 100644
--- a/bundle.c
+++ b/bundle.c
@@ -610,6 +610,10 @@ int unbundle(struct repository *r, struct bundle_header *header,
enum verify_bundle_flags flags)
{
struct child_process ip = CHILD_PROCESS_INIT;
+
+ if (verify_bundle(r, header, flags))
+ return -1;
+
strvec_pushl(&ip.args, "index-pack", "--fix-thin", "--stdin", NULL);
/* If there is a filter, then we need to create the promisor pack. */
@@ -621,8 +625,6 @@ int unbundle(struct repository *r, struct bundle_header *header,
strvec_clear(extra_index_pack_args);
}
- if (verify_bundle(r, header, flags))
- return -1;
ip.in = bundle_fd;
ip.no_stdout = 1;
ip.git_cmd = 1;
diff --git a/cache-tree.c b/cache-tree.c
index 9af457f47c..88c2c04f87 100644
--- a/cache-tree.c
+++ b/cache-tree.c
@@ -760,7 +760,7 @@ static void prime_cache_tree_rec(struct repository *r,
struct tree_desc desc;
struct name_entry entry;
int cnt;
- int base_path_len = tree_path->len;
+ size_t base_path_len = tree_path->len;
oidcpy(&it->oid, &tree->object.oid);
@@ -785,7 +785,6 @@ static void prime_cache_tree_rec(struct repository *r,
*/
if (r->index->sparse_index) {
strbuf_setlen(tree_path, base_path_len);
- strbuf_grow(tree_path, base_path_len + entry.pathlen + 1);
strbuf_add(tree_path, entry.path, entry.pathlen);
strbuf_addch(tree_path, '/');
}
diff --git a/cache-tree.h b/cache-tree.h
index 8efeccebfc..bd97caa07b 100644
--- a/cache-tree.h
+++ b/cache-tree.h
@@ -53,19 +53,4 @@ int write_index_as_tree(struct object_id *oid, struct index_state *index_state,
void prime_cache_tree(struct repository *, struct index_state *, struct tree *);
int cache_tree_matches_traversal(struct cache_tree *, struct name_entry *ent, struct traverse_info *info);
-
-#ifdef USE_THE_INDEX_COMPATIBILITY_MACROS
-static inline int write_cache_as_tree(struct object_id *oid, int flags, const char *prefix)
-{
- return write_index_as_tree(oid, &the_index, get_index_file(), flags, prefix);
-}
-
-static inline int update_main_cache_tree(int flags)
-{
- if (!the_index.cache_tree)
- the_index.cache_tree = cache_tree();
- return cache_tree_update(&the_index, flags);
-}
-#endif
-
#endif
diff --git a/cache.h b/cache.h
index 52d017335e..12789903e8 100644
--- a/cache.h
+++ b/cache.h
@@ -449,18 +449,8 @@ typedef int (*must_prefetch_predicate)(const struct cache_entry *);
void prefetch_cache_entries(const struct index_state *istate,
must_prefetch_predicate must_prefetch);
-#if defined(USE_THE_INDEX_COMPATIBILITY_MACROS) || defined(USE_THE_INDEX_VARIABLE)
+#ifdef USE_THE_INDEX_VARIABLE
extern struct index_state the_index;
-
-#ifndef USE_THE_INDEX_VARIABLE
-#ifdef USE_THE_INDEX_COMPATIBILITY_MACROS
-#define active_nr (the_index.cache_nr)
-
-#define read_cache() repo_read_index(the_repository)
-#define discard_cache() discard_index(&the_index)
-#define cache_name_pos(name, namelen) index_name_pos(&the_index,(name),(namelen))
-#endif
-#endif
#endif
#define TYPE_BITS 3
diff --git a/contrib/coccinelle/index-compatibility.cocci b/contrib/coccinelle/index-compatibility.cocci
index 8520f03128..31e36cf3c4 100644
--- a/contrib/coccinelle/index-compatibility.cocci
+++ b/contrib/coccinelle/index-compatibility.cocci
@@ -1,6 +1,7 @@
// the_index.* variables
@@
identifier AC = active_cache;
+identifier AN = active_nr;
identifier ACC = active_cache_changed;
identifier ACT = active_cache_tree;
@@
@@ -8,6 +9,9 @@ identifier ACT = active_cache_tree;
- AC
+ the_index.cache
|
+- AN
++ the_index.cache_nr
+|
- ACC
+ the_index.cache_changed
|
@@ -15,19 +19,13 @@ identifier ACT = active_cache_tree;
+ the_index.cache_tree
)
-@@
-identifier AN = active_nr;
-identifier f != prepare_to_commit;
-@@
- f(...) {<...
-- AN
-+ the_index.cache_nr
- ...>}
-
// "the_repository" simple cases
@@
@@
(
+- read_cache
++ repo_read_index
+|
- read_cache_unmerged
+ repo_read_index_unmerged
|
@@ -96,6 +94,15 @@ identifier f != prepare_to_commit;
|
- resolve_undo_clear
+ resolve_undo_clear_index
+|
+- cache_name_pos
++ index_name_pos
+|
+- update_main_cache_tree
++ cache_tree_update
+|
+- discard_cache
++ discard_index
)
(
+ &the_index,
@@ -137,3 +144,14 @@ identifier f != prepare_to_commit;
...
+ , NULL, NULL, NULL
)
+
+@@
+expression O;
+@@
+- write_cache_as_tree
++ write_index_as_tree
+ (
+- O,
++ O, &the_index, get_index_file(),
+ ...
+ )
diff --git a/contrib/coccinelle/index-compatibility.pending.cocci b/contrib/coccinelle/index-compatibility.pending.cocci
deleted file mode 100644
index 01f875d006..0000000000
--- a/contrib/coccinelle/index-compatibility.pending.cocci
+++ /dev/null
@@ -1,24 +0,0 @@
-// "the_repository" simple cases
-@@
-@@
-(
-- read_cache
-+ repo_read_index
-)
- (
-+ the_repository,
- ...)
-
-// "the_index" simple cases
-@@
-@@
-(
-- discard_cache
-+ discard_index
-|
-- cache_name_pos
-+ index_name_pos
-)
- (
-+ &the_index,
- ...)
diff --git a/credential.c b/credential.c
index f6389a5068..f32011343f 100644
--- a/credential.c
+++ b/credential.c
@@ -7,6 +7,7 @@
#include "prompt.h"
#include "sigchain.h"
#include "urlmatch.h"
+#include "git-compat-util.h"
void credential_init(struct credential *c)
{
@@ -234,6 +235,11 @@ int credential_read(struct credential *c, FILE *fp)
} else if (!strcmp(key, "path")) {
free(c->path);
c->path = xstrdup(value);
+ } else if (!strcmp(key, "password_expiry_utc")) {
+ errno = 0;
+ c->password_expiry_utc = parse_timestamp(value, NULL, 10);
+ if (c->password_expiry_utc == 0 || errno == ERANGE)
+ c->password_expiry_utc = TIME_MAX;
} else if (!strcmp(key, "url")) {
credential_from_url(c, value);
} else if (!strcmp(key, "quit")) {
@@ -269,6 +275,11 @@ void credential_write(const struct credential *c, FILE *fp)
credential_write_item(fp, "path", c->path, 0);
credential_write_item(fp, "username", c->username, 0);
credential_write_item(fp, "password", c->password, 0);
+ if (c->password_expiry_utc != TIME_MAX) {
+ char *s = xstrfmt("%"PRItime, c->password_expiry_utc);
+ credential_write_item(fp, "password_expiry_utc", s, 0);
+ free(s);
+ }
}
static int run_credential_helper(struct credential *c,
@@ -342,6 +353,12 @@ void credential_fill(struct credential *c)
for (i = 0; i < c->helpers.nr; i++) {
credential_do(c, c->helpers.items[i].string, "get");
+ if (c->password_expiry_utc < time(NULL)) {
+ /* Discard expired password */
+ FREE_AND_NULL(c->password);
+ /* Reset expiry to maintain consistency */
+ c->password_expiry_utc = TIME_MAX;
+ }
if (c->username && c->password)
return;
if (c->quit)
@@ -360,7 +377,7 @@ void credential_approve(struct credential *c)
if (c->approved)
return;
- if (!c->username || !c->password)
+ if (!c->username || !c->password || c->password_expiry_utc < time(NULL))
return;
credential_apply_config(c);
@@ -381,6 +398,7 @@ void credential_reject(struct credential *c)
FREE_AND_NULL(c->username);
FREE_AND_NULL(c->password);
+ c->password_expiry_utc = TIME_MAX;
c->approved = 0;
}
diff --git a/credential.h b/credential.h
index f430e77fea..935b28a70f 100644
--- a/credential.h
+++ b/credential.h
@@ -126,10 +126,12 @@ struct credential {
char *protocol;
char *host;
char *path;
+ timestamp_t password_expiry_utc;
};
#define CREDENTIAL_INIT { \
.helpers = STRING_LIST_INIT_DUP, \
+ .password_expiry_utc = TIME_MAX, \
}
/* Initialize a credential structure, setting all fields to empty. */
diff --git a/delta-islands.c b/delta-islands.c
index 8b234cb85b..afdec0a878 100644
--- a/delta-islands.c
+++ b/delta-islands.c
@@ -517,11 +517,13 @@ void free_island_marks(void)
{
struct island_bitmap *bitmap;
- kh_foreach_value(island_marks, bitmap, {
- if (!--bitmap->refcount)
- free(bitmap);
- });
- kh_destroy_oid_map(island_marks);
+ if (island_marks) {
+ kh_foreach_value(island_marks, bitmap, {
+ if (!--bitmap->refcount)
+ free(bitmap);
+ });
+ kh_destroy_oid_map(island_marks);
+ }
/* detect use-after-free with a an address which is never valid: */
island_marks = (void *)-1;
diff --git a/diff.c b/diff.c
index 329eebf16a..469e18aed2 100644
--- a/diff.c
+++ b/diff.c
@@ -3437,6 +3437,22 @@ static int diff_filepair_is_phoney(struct diff_filespec *one,
return !DIFF_FILE_VALID(one) && !DIFF_FILE_VALID(two);
}
+static int set_diff_algorithm(struct diff_options *opts,
+ const char *alg)
+{
+ long value = parse_algorithm_value(alg);
+
+ if (value < 0)
+ return -1;
+
+ /* clear out previous settings */
+ DIFF_XDL_CLR(opts, NEED_MINIMAL);
+ opts->xdl_opts &= ~XDF_DIFF_ALGORITHM_MASK;
+ opts->xdl_opts |= value;
+
+ return 0;
+}
+
static void builtin_diff(const char *name_a,
const char *name_b,
struct diff_filespec *one,
@@ -4440,15 +4456,13 @@ static void run_diff_cmd(const char *pgm,
const char *xfrm_msg = NULL;
int complete_rewrite = (p->status == DIFF_STATUS_MODIFIED) && p->score;
int must_show_header = 0;
+ struct userdiff_driver *drv = NULL;
-
- if (o->flags.allow_external) {
- struct userdiff_driver *drv;
-
+ if (o->flags.allow_external || !o->ignore_driver_algorithm)
drv = userdiff_find_by_path(o->repo->index, attr_path);
- if (drv && drv->external)
- pgm = drv->external;
- }
+
+ if (o->flags.allow_external && drv && drv->external)
+ pgm = drv->external;
if (msg) {
/*
@@ -4465,12 +4479,16 @@ static void run_diff_cmd(const char *pgm,
run_external_diff(pgm, name, other, one, two, xfrm_msg, o);
return;
}
- if (one && two)
+ if (one && two) {
+ if (!o->ignore_driver_algorithm && drv && drv->algorithm)
+ set_diff_algorithm(o, drv->algorithm);
+
builtin_diff(name, other ? other : name,
one, two, xfrm_msg, must_show_header,
o, complete_rewrite);
- else
+ } else {
fprintf(o->file, "* Unmerged path %s\n", name);
+ }
}
static void diff_fill_oid_info(struct diff_filespec *one, struct index_state *istate)
@@ -4567,6 +4585,14 @@ static void run_diffstat(struct diff_filepair *p, struct diff_options *o,
const char *name;
const char *other;
+ if (!o->ignore_driver_algorithm) {
+ struct userdiff_driver *drv = userdiff_find_by_path(o->repo->index,
+ p->one->path);
+
+ if (drv && drv->algorithm)
+ set_diff_algorithm(o, drv->algorithm);
+ }
+
if (DIFF_PAIR_UNMERGED(p)) {
/* unmerged */
builtin_diffstat(p->one->path, NULL, NULL, NULL,
@@ -5107,17 +5133,32 @@ static int diff_opt_diff_algorithm(const struct option *opt,
const char *arg, int unset)
{
struct diff_options *options = opt->value;
- long value = parse_algorithm_value(arg);
BUG_ON_OPT_NEG(unset);
- if (value < 0)
+
+ if (set_diff_algorithm(options, arg))
return error(_("option diff-algorithm accepts \"myers\", "
"\"minimal\", \"patience\" and \"histogram\""));
- /* clear out previous settings */
- DIFF_XDL_CLR(options, NEED_MINIMAL);
- options->xdl_opts &= ~XDF_DIFF_ALGORITHM_MASK;
- options->xdl_opts |= value;
+ options->ignore_driver_algorithm = 1;
+
+ return 0;
+}
+
+static int diff_opt_diff_algorithm_no_arg(const struct option *opt,
+ const char *arg, int unset)
+{
+ struct diff_options *options = opt->value;
+
+ BUG_ON_OPT_NEG(unset);
+ BUG_ON_OPT_ARG(arg);
+
+ if (set_diff_algorithm(options, opt->long_name))
+ BUG("available diff algorithms include \"myers\", "
+ "\"minimal\", \"patience\" and \"histogram\"");
+
+ options->ignore_driver_algorithm = 1;
+
return 0;
}
@@ -5250,7 +5291,6 @@ static int diff_opt_patience(const struct option *opt,
BUG_ON_OPT_NEG(unset);
BUG_ON_OPT_ARG(arg);
- options->xdl_opts = DIFF_WITH_ALG(options, PATIENCE_DIFF);
/*
* Both --patience and --anchored use PATIENCE_DIFF
* internally, so remove any anchors previously
@@ -5259,7 +5299,9 @@ static int diff_opt_patience(const struct option *opt,
for (i = 0; i < options->anchors_nr; i++)
free(options->anchors[i]);
options->anchors_nr = 0;
- return 0;
+ options->ignore_driver_algorithm = 1;
+
+ return set_diff_algorithm(options, "patience");
}
static int diff_opt_ignore_regex(const struct option *opt,
@@ -5562,9 +5604,10 @@ struct option *add_diff_options(const struct option *opts,
N_("prevent rename/copy detection if the number of rename/copy targets exceeds given limit")),
OPT_GROUP(N_("Diff algorithm options")),
- OPT_BIT(0, "minimal", &options->xdl_opts,
- N_("produce the smallest possible diff"),
- XDF_NEED_MINIMAL),
+ OPT_CALLBACK_F(0, "minimal", options, NULL,
+ N_("produce the smallest possible diff"),
+ PARSE_OPT_NONEG | PARSE_OPT_NOARG,
+ diff_opt_diff_algorithm_no_arg),
OPT_BIT_F('w', "ignore-all-space", &options->xdl_opts,
N_("ignore whitespace when comparing lines"),
XDF_IGNORE_WHITESPACE, PARSE_OPT_NONEG),
@@ -5590,9 +5633,10 @@ struct option *add_diff_options(const struct option *opts,
N_("generate diff using the \"patience diff\" algorithm"),
PARSE_OPT_NONEG | PARSE_OPT_NOARG,
diff_opt_patience),
- OPT_BITOP(0, "histogram", &options->xdl_opts,
- N_("generate diff using the \"histogram diff\" algorithm"),
- XDF_HISTOGRAM_DIFF, XDF_DIFF_ALGORITHM_MASK),
+ OPT_CALLBACK_F(0, "histogram", options, NULL,
+ N_("generate diff using the \"histogram diff\" algorithm"),
+ PARSE_OPT_NONEG | PARSE_OPT_NOARG,
+ diff_opt_diff_algorithm_no_arg),
OPT_CALLBACK_F(0, "diff-algorithm", options, N_("<algorithm>"),
N_("choose a diff algorithm"),
PARSE_OPT_NONEG, diff_opt_diff_algorithm),
diff --git a/diff.h b/diff.h
index 41eb2c3d42..8d770b1d57 100644
--- a/diff.h
+++ b/diff.h
@@ -333,6 +333,7 @@ struct diff_options {
int prefix_length;
const char *stat_sep;
int xdl_opts;
+ int ignore_driver_algorithm;
/* see Documentation/diff-options.txt */
char **anchors;
diff --git a/dir-iterator.c b/dir-iterator.c
index 3764dd81a1..cedd304759 100644
--- a/dir-iterator.c
+++ b/dir-iterator.c
@@ -112,10 +112,7 @@ static int prepare_next_entry_data(struct dir_iterator_int *iter,
iter->base.basename = iter->base.path.buf +
iter->levels[iter->levels_nr - 1].prefix_len;
- if (iter->flags & DIR_ITERATOR_FOLLOW_SYMLINKS)
- err = stat(iter->base.path.buf, &iter->base.st);
- else
- err = lstat(iter->base.path.buf, &iter->base.st);
+ err = lstat(iter->base.path.buf, &iter->base.st);
saved_errno = errno;
if (err && errno != ENOENT)
@@ -213,13 +210,10 @@ struct dir_iterator *dir_iterator_begin(const char *path, unsigned int flags)
iter->flags = flags;
/*
- * Note: stat/lstat already checks for NULL or empty strings and
+ * Note: lstat already checks for NULL or empty strings and
* nonexistent paths.
*/
- if (iter->flags & DIR_ITERATOR_FOLLOW_SYMLINKS)
- err = stat(iter->base.path.buf, &iter->base.st);
- else
- err = lstat(iter->base.path.buf, &iter->base.st);
+ err = lstat(iter->base.path.buf, &iter->base.st);
if (err < 0) {
saved_errno = errno;
diff --git a/dir-iterator.h b/dir-iterator.h
index e3b6ff2800..479e1ec784 100644
--- a/dir-iterator.h
+++ b/dir-iterator.h
@@ -54,24 +54,8 @@
* and ITER_ERROR is returned immediately. In both cases, a meaningful
* warning is emitted. Note: ENOENT errors are always ignored so that
* the API users may remove files during iteration.
- *
- * - DIR_ITERATOR_FOLLOW_SYMLINKS: make dir-iterator follow symlinks.
- * i.e., linked directories' contents will be iterated over and
- * iter->base.st will contain information on the referred files,
- * not the symlinks themselves, which is the default behavior. Broken
- * symlinks are ignored.
- *
- * Note: setting DIR_ITERATOR_FOLLOW_SYMLINKS affects resolving the
- * starting path as well (e.g., attempting to iterate starting at a
- * symbolic link pointing to a directory without FOLLOW_SYMLINKS will
- * result in an error).
- *
- * Warning: circular symlinks are also followed when
- * DIR_ITERATOR_FOLLOW_SYMLINKS is set. The iteration may end up with
- * an ELOOP if they happen and DIR_ITERATOR_PEDANTIC is set.
*/
#define DIR_ITERATOR_PEDANTIC (1 << 0)
-#define DIR_ITERATOR_FOLLOW_SYMLINKS (1 << 1)
struct dir_iterator {
/* The current path: */
@@ -88,9 +72,7 @@ struct dir_iterator {
const char *basename;
/*
- * The result of calling lstat() on path; or stat(), if the
- * DIR_ITERATOR_FOLLOW_SYMLINKS flag was set at
- * dir_iterator's initialization.
+ * The result of calling lstat() on path.
*/
struct stat st;
};
diff --git a/gpg-interface.c b/gpg-interface.c
index 687236430b..5cd66d3a78 100644
--- a/gpg-interface.c
+++ b/gpg-interface.c
@@ -977,9 +977,13 @@ static int sign_buffer_gpg(struct strbuf *buffer, struct strbuf *signature,
break; /* found */
}
ret |= !cp;
+ if (ret) {
+ error(_("gpg failed to sign the data:\n%s"),
+ gpg_status.len ? gpg_status.buf : "(no gpg output)");
+ strbuf_release(&gpg_status);
+ return -1;
+ }
strbuf_release(&gpg_status);
- if (ret)
- return error(_("gpg failed to sign the data"));
/* Strip CR from the line endings, in case we are on Windows. */
remove_cr_after(signature, bottom);
diff --git a/grep.c b/grep.c
index 0690ed9b89..cee44a78d0 100644
--- a/grep.c
+++ b/grep.c
@@ -815,11 +815,11 @@ static void free_pattern_expr(struct grep_expr *x)
free(x);
}
-void free_grep_patterns(struct grep_opt *opt)
+static void free_grep_pat(struct grep_pat *pattern)
{
struct grep_pat *p, *n;
- for (p = opt->pattern_list; p; p = n) {
+ for (p = pattern; p; p = n) {
n = p->next;
switch (p->token) {
case GREP_PATTERN: /* atom */
@@ -836,10 +836,15 @@ void free_grep_patterns(struct grep_opt *opt)
}
free(p);
}
+}
- if (!opt->pattern_expression)
- return;
- free_pattern_expr(opt->pattern_expression);
+void free_grep_patterns(struct grep_opt *opt)
+{
+ free_grep_pat(opt->pattern_list);
+ free_grep_pat(opt->header_list);
+
+ if (opt->pattern_expression)
+ free_pattern_expr(opt->pattern_expression);
}
static const char *end_of_line(const char *cp, unsigned long *left)
diff --git a/hook.c b/hook.c
index a4fa1031f2..1a84831863 100644
--- a/hook.c
+++ b/hook.c
@@ -55,6 +55,11 @@ static int pick_next_hook(struct child_process *cp,
cp->no_stdin = 1;
strvec_pushv(&cp->env, hook_cb->options->env.v);
+ /* reopen the file for stdin; run_command closes it. */
+ if (hook_cb->options->path_to_stdin) {
+ cp->no_stdin = 0;
+ cp->in = xopen(hook_cb->options->path_to_stdin, O_RDONLY);
+ }
cp->stdout_to_stderr = 1;
cp->trace2_hook_name = hook_cb->hook_name;
cp->dir = hook_cb->options->dir;
diff --git a/hook.h b/hook.h
index 4258b13da0..19ab9a5806 100644
--- a/hook.h
+++ b/hook.h
@@ -30,6 +30,11 @@ struct run_hooks_opt
* was invoked.
*/
int *invoked_hook;
+
+ /**
+ * Path to file which should be piped to stdin for each hook.
+ */
+ const char *path_to_stdin;
};
#define RUN_HOOKS_OPT_INIT { \
diff --git a/http-backend.c b/http-backend.c
index 6eb3b2fe51..8ab58e55f8 100644
--- a/http-backend.c
+++ b/http-backend.c
@@ -759,10 +759,14 @@ int cmd_main(int argc, const char **argv)
struct service_cmd *c = &services[i];
regex_t re;
regmatch_t out[1];
+ int ret;
if (regcomp(&re, c->pattern, REG_EXTENDED))
die("Bogus regex in service table: %s", c->pattern);
- if (!regexec(&re, dir, 1, out, 0)) {
+ ret = regexec(&re, dir, 1, out, 0);
+ regfree(&re);
+
+ if (!ret) {
size_t n;
if (strcmp(method, c->method))
@@ -774,7 +778,6 @@ int cmd_main(int argc, const char **argv)
dir[out[0].rm_so] = 0;
break;
}
- regfree(&re);
}
if (!cmd)
@@ -786,6 +789,7 @@ int cmd_main(int argc, const char **argv)
if (!getenv("GIT_HTTP_EXPORT_ALL") &&
access("git-daemon-export-ok", F_OK) )
not_found(&hdr, "Repository not exported: '%s'", dir);
+ free(dir);
http_config();
max_request_buffer = git_env_ulong("GIT_HTTP_MAX_REQUEST_BUFFER",
@@ -795,5 +799,6 @@ int cmd_main(int argc, const char **argv)
setenv(GIT_PROTOCOL_ENVIRONMENT, proto_header, 0);
cmd->imp(&hdr, cmd_arg);
+ free(cmd_arg);
return 0;
}
diff --git a/range-diff.c b/range-diff.c
index 8255ab4349..086365dffb 100644
--- a/range-diff.c
+++ b/range-diff.c
@@ -383,11 +383,14 @@ static void output_pair_header(struct diff_options *diffopt,
const char *color_new = diff_get_color_opt(diffopt, DIFF_FILE_NEW);
const char *color_commit = diff_get_color_opt(diffopt, DIFF_COMMIT);
const char *color;
+ char abbrev = diffopt->abbrev;
+
+ if (abbrev < 0)
+ abbrev = DEFAULT_ABBREV;
if (!dashes->len)
strbuf_addchars(dashes, '-',
- strlen(find_unique_abbrev(oid,
- DEFAULT_ABBREV)));
+ strlen(find_unique_abbrev(oid, abbrev)));
if (!b_util) {
color = color_old;
@@ -409,7 +412,7 @@ static void output_pair_header(struct diff_options *diffopt,
strbuf_addf(buf, "%*s: %s ", patch_no_width, "-", dashes->buf);
else
strbuf_addf(buf, "%*d: %s ", patch_no_width, a_util->i + 1,
- find_unique_abbrev(&a_util->oid, DEFAULT_ABBREV));
+ find_unique_abbrev(&a_util->oid, abbrev));
if (status == '!')
strbuf_addf(buf, "%s%s", color_reset, color);
@@ -421,7 +424,7 @@ static void output_pair_header(struct diff_options *diffopt,
strbuf_addf(buf, " %*s: %s", patch_no_width, "-", dashes->buf);
else
strbuf_addf(buf, " %*d: %s", patch_no_width, b_util->i + 1,
- find_unique_abbrev(&b_util->oid, DEFAULT_ABBREV));
+ find_unique_abbrev(&b_util->oid, abbrev));
commit = lookup_commit_reference(the_repository, oid);
if (commit) {
diff --git a/refs.c b/refs.c
index e31dbcda59..aeae31c972 100644
--- a/refs.c
+++ b/refs.c
@@ -1310,65 +1310,68 @@ int update_ref(const char *msg, const char *refname,
old_oid, flags, onerr);
}
+/*
+ * Check that the string refname matches a rule of the form
+ * "{prefix}%.*s{suffix}". So "foo/bar/baz" would match the rule
+ * "foo/%.*s/baz", and return the string "bar".
+ */
+static const char *match_parse_rule(const char *refname, const char *rule,
+ size_t *len)
+{
+ /*
+ * Check that rule matches refname up to the first percent in the rule.
+ * We can bail immediately if not, but otherwise we leave "rule" at the
+ * %-placeholder, and "refname" at the start of the potential matched
+ * name.
+ */
+ while (*rule != '%') {
+ if (!*rule)
+ BUG("rev-parse rule did not have percent");
+ if (*refname++ != *rule++)
+ return NULL;
+ }
+
+ /*
+ * Check that our "%" is the expected placeholder. This assumes there
+ * are no other percents (placeholder or quoted) in the string, but
+ * that is sufficient for our rev-parse rules.
+ */
+ if (!skip_prefix(rule, "%.*s", &rule))
+ return NULL;
+
+ /*
+ * And now check that our suffix (if any) matches.
+ */
+ if (!strip_suffix(refname, rule, len))
+ return NULL;
+
+ return refname; /* len set by strip_suffix() */
+}
+
char *refs_shorten_unambiguous_ref(struct ref_store *refs,
const char *refname, int strict)
{
int i;
- static char **scanf_fmts;
- static int nr_rules;
- char *short_name;
struct strbuf resolved_buf = STRBUF_INIT;
- if (!nr_rules) {
- /*
- * Pre-generate scanf formats from ref_rev_parse_rules[].
- * Generate a format suitable for scanf from a
- * ref_rev_parse_rules rule by interpolating "%s" at the
- * location of the "%.*s".
- */
- size_t total_len = 0;
- size_t offset = 0;
-
- /* the rule list is NULL terminated, count them first */
- for (nr_rules = 0; ref_rev_parse_rules[nr_rules]; nr_rules++)
- /* -2 for strlen("%.*s") - strlen("%s"); +1 for NUL */
- total_len += strlen(ref_rev_parse_rules[nr_rules]) - 2 + 1;
-
- scanf_fmts = xmalloc(st_add(st_mult(sizeof(char *), nr_rules), total_len));
-
- offset = 0;
- for (i = 0; i < nr_rules; i++) {
- assert(offset < total_len);
- scanf_fmts[i] = (char *)&scanf_fmts[nr_rules] + offset;
- offset += xsnprintf(scanf_fmts[i], total_len - offset,
- ref_rev_parse_rules[i], 2, "%s") + 1;
- }
- }
-
- /* bail out if there are no rules */
- if (!nr_rules)
- return xstrdup(refname);
-
- /* buffer for scanf result, at most refname must fit */
- short_name = xstrdup(refname);
-
/* skip first rule, it will always match */
- for (i = nr_rules - 1; i > 0 ; --i) {
+ for (i = NUM_REV_PARSE_RULES - 1; i > 0 ; --i) {
int j;
int rules_to_fail = i;
- int short_name_len;
+ const char *short_name;
+ size_t short_name_len;
- if (1 != sscanf(refname, scanf_fmts[i], short_name))
+ short_name = match_parse_rule(refname, ref_rev_parse_rules[i],
+ &short_name_len);
+ if (!short_name)
continue;
- short_name_len = strlen(short_name);
-
/*
* in strict mode, all (except the matched one) rules
* must fail to resolve to a valid non-ambiguous ref
*/
if (strict)
- rules_to_fail = nr_rules;
+ rules_to_fail = NUM_REV_PARSE_RULES;
/*
* check if the short name resolves to a valid ref,
@@ -1388,7 +1391,8 @@ char *refs_shorten_unambiguous_ref(struct ref_store *refs,
*/
strbuf_reset(&resolved_buf);
strbuf_addf(&resolved_buf, rule,
- short_name_len, short_name);
+ cast_size_t_to_int(short_name_len),
+ short_name);
if (refs_ref_exists(refs, resolved_buf.buf))
break;
}
@@ -1399,12 +1403,11 @@ char *refs_shorten_unambiguous_ref(struct ref_store *refs,
*/
if (j == rules_to_fail) {
strbuf_release(&resolved_buf);
- return short_name;
+ return xmemdupz(short_name, short_name_len);
}
}
strbuf_release(&resolved_buf);
- free(short_name);
return xstrdup(refname);
}
diff --git a/run-command.c b/run-command.c
index 50cc011654..6bd16acb06 100644
--- a/run-command.c
+++ b/run-command.c
@@ -1586,6 +1586,14 @@ static int pp_start_one(struct parallel_processes *pp,
if (i == opts->processes)
BUG("bookkeeping is hard");
+ /*
+ * By default, do not inherit stdin from the parent process - otherwise,
+ * all children would share stdin! Users may overwrite this to provide
+ * something to the child's stdin by having their 'get_next_task'
+ * callback assign 0 to .no_stdin and an appropriate integer to .in.
+ */
+ pp->children[i].process.no_stdin = 1;
+
code = opts->get_next_task(&pp->children[i].process,
opts->ungroup ? NULL : &pp->children[i].err,
opts->data,
@@ -1601,7 +1609,6 @@ static int pp_start_one(struct parallel_processes *pp,
pp->children[i].process.err = -1;
pp->children[i].process.stdout_to_stderr = 1;
}
- pp->children[i].process.no_stdin = 1;
if (start_command(&pp->children[i].process)) {
if (opts->start_failure)
@@ -1632,9 +1639,7 @@ static void pp_buffer_stderr(struct parallel_processes *pp,
const struct run_process_parallel_opts *opts,
int output_timeout)
{
- int i;
-
- while ((i = poll(pp->pfd, opts->processes, output_timeout) < 0)) {
+ while (poll(pp->pfd, opts->processes, output_timeout) < 0) {
if (errno == EINTR)
continue;
pp_cleanup(pp, opts);
diff --git a/sequencer.c b/sequencer.c
index fb23f734ad..a7e6db4f78 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -2487,6 +2487,34 @@ static int is_command(enum todo_command command, const char **bol)
(*bol = p));
}
+static int check_label_or_ref_arg(enum todo_command command, const char *arg)
+{
+ switch (command) {
+ case TODO_LABEL:
+ /*
+ * '#' is not a valid label as the merge command uses it to
+ * separate merge parents from the commit subject.
+ */
+ if (!strcmp(arg, "#") ||
+ check_refname_format(arg, REFNAME_ALLOW_ONELEVEL))
+ return error(_("'%s' is not a valid label"), arg);
+ break;
+
+ case TODO_UPDATE_REF:
+ if (check_refname_format(arg, REFNAME_ALLOW_ONELEVEL))
+ return error(_("'%s' is not a valid refname"), arg);
+ if (check_refname_format(arg, 0))
+ return error(_("update-ref requires a fully qualified "
+ "refname e.g. refs/heads/%s"), arg);
+ break;
+
+ default:
+ BUG("unexpected todo_command");
+ }
+
+ return 0;
+}
+
static int parse_insn_line(struct repository *r, struct todo_item *item,
const char *buf, const char *bol, char *eol)
{
@@ -2535,10 +2563,19 @@ static int parse_insn_line(struct repository *r, struct todo_item *item,
if (item->command == TODO_EXEC || item->command == TODO_LABEL ||
item->command == TODO_RESET || item->command == TODO_UPDATE_REF) {
+ int ret = 0;
+
item->commit = NULL;
item->arg_offset = bol - buf;
item->arg_len = (int)(eol - bol);
- return 0;
+ if (item->command == TODO_LABEL ||
+ item->command == TODO_UPDATE_REF) {
+ saved = *eol;
+ *eol = '\0';
+ ret = check_label_or_ref_arg(item->command, bol);
+ *eol = saved;
+ }
+ return ret;
}
if (item->command == TODO_FIXUP) {
@@ -4844,8 +4881,7 @@ cleanup_head_ref:
if (!stat(rebase_path_rewritten_list(), &st) &&
st.st_size > 0) {
struct child_process child = CHILD_PROCESS_INIT;
- const char *post_rewrite_hook =
- find_hook("post-rewrite");
+ struct run_hooks_opt hook_opt = RUN_HOOKS_OPT_INIT;
child.in = open(rebase_path_rewritten_list(), O_RDONLY);
child.git_cmd = 1;
@@ -4855,18 +4891,9 @@ cleanup_head_ref:
/* we don't care if this copying failed */
run_command(&child);
- if (post_rewrite_hook) {
- struct child_process hook = CHILD_PROCESS_INIT;
-
- hook.in = open(rebase_path_rewritten_list(),
- O_RDONLY);
- hook.stdout_to_stderr = 1;
- hook.trace2_hook_name = "post-rewrite";
- strvec_push(&hook.args, post_rewrite_hook);
- strvec_push(&hook.args, "rebase");
- /* we don't care if this hook failed */
- run_command(&hook);
- }
+ hook_opt.path_to_stdin = rebase_path_rewritten_list();
+ strvec_push(&hook_opt.args, "rebase");
+ run_hooks_opt("post-rewrite", &hook_opt);
}
apply_autostash(rebase_path_autostash());
diff --git a/t/helper/test-ctype.c b/t/helper/test-ctype.c
index 92c4c2313e..b21bd672d9 100644
--- a/t/helper/test-ctype.c
+++ b/t/helper/test-ctype.c
@@ -11,9 +11,14 @@ static void report_error(const char *class, int ch)
static int is_in(const char *s, int ch)
{
- /* We can't find NUL using strchr. It's classless anyway. */
+ /*
+ * We can't find NUL using strchr. Accept it as the first
+ * character in the spec -- there are no empty classes.
+ */
if (ch == '\0')
- return 0;
+ return ch == *s;
+ if (*s == '\0')
+ s++;
return !!strchr(s, ch);
}
@@ -28,6 +33,20 @@ static int is_in(const char *s, int ch)
#define DIGIT "0123456789"
#define LOWER "abcdefghijklmnopqrstuvwxyz"
#define UPPER "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+#define PUNCT "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"
+#define ASCII \
+ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" \
+ "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" \
+ "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" \
+ "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f" \
+ "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f" \
+ "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f" \
+ "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f" \
+ "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
+#define CNTRL \
+ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" \
+ "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" \
+ "\x7f"
int cmd__ctype(int argc, const char **argv)
{
@@ -38,6 +57,13 @@ int cmd__ctype(int argc, const char **argv)
TEST_CLASS(is_glob_special, "*?[\\");
TEST_CLASS(is_regex_special, "$()*+.?[\\^{|");
TEST_CLASS(is_pathspec_magic, "!\"#%&',-/:;<=>@_`~");
+ TEST_CLASS(isascii, ASCII);
+ TEST_CLASS(islower, LOWER);
+ TEST_CLASS(isupper, UPPER);
+ TEST_CLASS(iscntrl, CNTRL);
+ TEST_CLASS(ispunct, PUNCT);
+ TEST_CLASS(isxdigit, DIGIT "abcdefABCDEF");
+ TEST_CLASS(isprint, LOWER UPPER DIGIT PUNCT " ");
return rc;
}
diff --git a/t/helper/test-dir-iterator.c b/t/helper/test-dir-iterator.c
index 659b6bfa81..6b297bd753 100644
--- a/t/helper/test-dir-iterator.c
+++ b/t/helper/test-dir-iterator.c
@@ -15,7 +15,7 @@ static const char *error_name(int error_number)
/*
* usage:
- * tool-test dir-iterator [--follow-symlinks] [--pedantic] directory_path
+ * tool-test dir-iterator [--pedantic] directory_path
*/
int cmd__dir_iterator(int argc, const char **argv)
{
@@ -24,9 +24,7 @@ int cmd__dir_iterator(int argc, const char **argv)
int iter_status;
for (++argv, --argc; *argv && starts_with(*argv, "--"); ++argv, --argc) {
- if (strcmp(*argv, "--follow-symlinks") == 0)
- flags |= DIR_ITERATOR_FOLLOW_SYMLINKS;
- else if (strcmp(*argv, "--pedantic") == 0)
+ if (strcmp(*argv, "--pedantic") == 0)
flags |= DIR_ITERATOR_PEDANTIC;
else
die("invalid option '%s'", *argv);
diff --git a/t/helper/test-genzeros.c b/t/helper/test-genzeros.c
index 8ca988d621..47af843b68 100644
--- a/t/helper/test-genzeros.c
+++ b/t/helper/test-genzeros.c
@@ -17,15 +17,16 @@ int cmd__genzeros(int argc, const char **argv)
/* Writing out individual NUL bytes is slow... */
while (count < 0)
- if (write(1, zeros, ARRAY_SIZE(zeros)) < 0)
- return -1;
+ if (xwrite(1, zeros, ARRAY_SIZE(zeros)) < 0)
+ die_errno("write error");
while (count > 0) {
- n = write(1, zeros, count < ARRAY_SIZE(zeros) ?
- count : ARRAY_SIZE(zeros));
+ n = xwrite(1, zeros,
+ count < ARRAY_SIZE(zeros)
+ ? count : ARRAY_SIZE(zeros));
if (n < 0)
- return -1;
+ die_errno("write error");
count -= n;
}
diff --git a/t/lib-diff-alternative.sh b/t/lib-diff-alternative.sh
index 8d1e408bb5..a8f5d3274a 100644
--- a/t/lib-diff-alternative.sh
+++ b/t/lib-diff-alternative.sh
@@ -105,10 +105,46 @@ index $file1..$file2 100644
}
EOF
+ cat >expect_diffstat <<EOF
+ file1 => file2 | 21 ++++++++++-----------
+ 1 file changed, 10 insertions(+), 11 deletions(-)
+EOF
+
STRATEGY=$1
+ test_expect_success "$STRATEGY diff from attributes" '
+ echo "file* diff=driver" >.gitattributes &&
+ git config diff.driver.algorithm "$STRATEGY" &&
+ test_must_fail git diff --no-index file1 file2 > output &&
+ cat expect &&
+ cat output &&
+ test_cmp expect output
+ '
+
+ test_expect_success "$STRATEGY diff from attributes has valid diffstat" '
+ echo "file* diff=driver" >.gitattributes &&
+ git config diff.driver.algorithm "$STRATEGY" &&
+ test_must_fail git diff --stat --no-index file1 file2 > output &&
+ test_cmp expect_diffstat output
+ '
+
test_expect_success "$STRATEGY diff" '
- test_must_fail git diff --no-index "--$STRATEGY" file1 file2 > output &&
+ test_must_fail git diff --no-index "--diff-algorithm=$STRATEGY" file1 file2 > output &&
+ test_cmp expect output
+ '
+
+ test_expect_success "$STRATEGY diff command line precedence before attributes" '
+ echo "file* diff=driver" >.gitattributes &&
+ git config diff.driver.algorithm myers &&
+ test_must_fail git diff --no-index "--diff-algorithm=$STRATEGY" file1 file2 > output &&
+ test_cmp expect output
+ '
+
+ test_expect_success "$STRATEGY diff attributes precedence before config" '
+ git config diff.algorithm default &&
+ echo "file* diff=driver" >.gitattributes &&
+ git config diff.driver.algorithm "$STRATEGY" &&
+ test_must_fail git diff --no-index file1 file2 > output &&
test_cmp expect output
'
diff --git a/t/lib-httpd.sh b/t/lib-httpd.sh
index 5d2d56c445..059fd74adb 100644
--- a/t/lib-httpd.sh
+++ b/t/lib-httpd.sh
@@ -25,6 +25,7 @@
# LIB_HTTPD_DAV enable DAV
# LIB_HTTPD_SVN enable SVN at given location (e.g. "svn")
# LIB_HTTPD_SSL enable SSL
+# LIB_HTTPD_PROXY enable proxy
#
# Copyright (c) 2008 Clemens Buchacher <drizzd@aon.at>
#
@@ -133,6 +134,7 @@ install_script () {
prepare_httpd() {
mkdir -p "$HTTPD_DOCUMENT_ROOT_PATH"
cp "$TEST_PATH"/passwd "$HTTPD_ROOT_PATH"
+ cp "$TEST_PATH"/proxy-passwd "$HTTPD_ROOT_PATH"
install_script incomplete-length-upload-pack-v2-http.sh
install_script incomplete-body-upload-pack-v2-http.sh
install_script error-no-report.sh
@@ -176,6 +178,11 @@ prepare_httpd() {
export LIB_HTTPD_SVN LIB_HTTPD_SVNPATH
fi
fi
+
+ if test -n "$LIB_HTTPD_PROXY"
+ then
+ HTTPD_PARA="$HTTPD_PARA -DPROXY"
+ fi
}
enable_http2 () {
diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf
index 51a4fbcf62..e31293a45f 100644
--- a/t/lib-httpd/apache.conf
+++ b/t/lib-httpd/apache.conf
@@ -47,6 +47,22 @@ Protocols h2c
LoadModule authz_host_module modules/mod_authz_host.so
</IfModule>
+<IfDefine PROXY>
+<IfModule !mod_proxy.c>
+ LoadModule proxy_module modules/mod_proxy.so
+</IfModule>
+<IfModule !mod_proxy_http.c>
+ LoadModule proxy_http_module modules/mod_proxy_http.so
+</IfModule>
+ProxyRequests On
+<Proxy "*">
+ AuthType Basic
+ AuthName "proxy-auth"
+ AuthUserFile proxy-passwd
+ Require valid-user
+</Proxy>
+</IfDefine>
+
<IfModule !mod_authn_core.c>
LoadModule authn_core_module modules/mod_authn_core.so
</IfModule>
diff --git a/t/lib-httpd/proxy-passwd b/t/lib-httpd/proxy-passwd
new file mode 100644
index 0000000000..77c25138e0
--- /dev/null
+++ b/t/lib-httpd/proxy-passwd
@@ -0,0 +1 @@
+proxuser:2x7tAukjAED5M
diff --git a/t/t0023-crlf-am.sh b/t/t0023-crlf-am.sh
index f9bbb91f64..575805513a 100755
--- a/t/t0023-crlf-am.sh
+++ b/t/t0023-crlf-am.sh
@@ -2,6 +2,7 @@
test_description='Test am with auto.crlf'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
cat >patchfile <<\EOF
diff --git a/t/t0066-dir-iterator.sh b/t/t0066-dir-iterator.sh
index 04b811622b..7d0a0da8c0 100755
--- a/t/t0066-dir-iterator.sh
+++ b/t/t0066-dir-iterator.sh
@@ -106,13 +106,7 @@ test_expect_success SYMLINKS 'setup dirs with symlinks' '
ln -s d dir4/a/e &&
ln -s ../b dir4/a/f &&
- mkdir -p dir5/a/b &&
- mkdir -p dir5/a/c &&
- ln -s ../c dir5/a/b/d &&
- ln -s ../ dir5/a/b/e &&
- ln -s ../../ dir5/a/b/f &&
-
- ln -s dir4 dir6
+ ln -s dir4 dir5
'
test_expect_success SYMLINKS 'dir-iterator should not follow symlinks by default' '
@@ -131,44 +125,10 @@ test_expect_success SYMLINKS 'dir-iterator should not follow symlinks by default
test_cmp expected-no-follow-sorted-output actual-no-follow-sorted-output
'
-test_expect_success SYMLINKS 'dir-iterator should follow symlinks w/ follow flag' '
- cat >expected-follow-sorted-output <<-EOF &&
- [d] (a) [a] ./dir4/a
- [d] (a/f) [f] ./dir4/a/f
- [d] (a/f/c) [c] ./dir4/a/f/c
- [d] (b) [b] ./dir4/b
- [d] (b/c) [c] ./dir4/b/c
- [f] (a/d) [d] ./dir4/a/d
- [f] (a/e) [e] ./dir4/a/e
- EOF
-
- test-tool dir-iterator --follow-symlinks ./dir4 >out &&
- sort out >actual-follow-sorted-output &&
-
- test_cmp expected-follow-sorted-output actual-follow-sorted-output
-'
-
test_expect_success SYMLINKS 'dir-iterator does not resolve top-level symlinks' '
- test_must_fail test-tool dir-iterator ./dir6 >out &&
+ test_must_fail test-tool dir-iterator ./dir5 >out &&
grep "ENOTDIR" out
'
-test_expect_success SYMLINKS 'dir-iterator resolves top-level symlinks w/ follow flag' '
- cat >expected-follow-sorted-output <<-EOF &&
- [d] (a) [a] ./dir6/a
- [d] (a/f) [f] ./dir6/a/f
- [d] (a/f/c) [c] ./dir6/a/f/c
- [d] (b) [b] ./dir6/b
- [d] (b/c) [c] ./dir6/b/c
- [f] (a/d) [d] ./dir6/a/d
- [f] (a/e) [e] ./dir6/a/e
- EOF
-
- test-tool dir-iterator --follow-symlinks ./dir6 >out &&
- sort out >actual-follow-sorted-output &&
-
- test_cmp expected-follow-sorted-output actual-follow-sorted-output
-'
-
test_done
diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh
index 3485c0534e..c66d91e82d 100755
--- a/t/t0300-credentials.sh
+++ b/t/t0300-credentials.sh
@@ -35,6 +35,16 @@ test_expect_success 'setup helper scripts' '
test -z "$pass" || echo password=$pass
EOF
+ write_script git-credential-verbatim-with-expiry <<-\EOF &&
+ user=$1; shift
+ pass=$1; shift
+ pexpiry=$1; shift
+ . ./dump
+ test -z "$user" || echo username=$user
+ test -z "$pass" || echo password=$pass
+ test -z "$pexpiry" || echo password_expiry_utc=$pexpiry
+ EOF
+
PATH="$PWD:$PATH"
'
@@ -109,6 +119,43 @@ test_expect_success 'credential_fill continues through partial response' '
EOF
'
+test_expect_success 'credential_fill populates password_expiry_utc' '
+ check fill "verbatim-with-expiry one two 9999999999" <<-\EOF
+ protocol=http
+ host=example.com
+ --
+ protocol=http
+ host=example.com
+ username=one
+ password=two
+ password_expiry_utc=9999999999
+ --
+ verbatim-with-expiry: get
+ verbatim-with-expiry: protocol=http
+ verbatim-with-expiry: host=example.com
+ EOF
+'
+
+test_expect_success 'credential_fill ignores expired password' '
+ check fill "verbatim-with-expiry one two 5" "verbatim three four" <<-\EOF
+ protocol=http
+ host=example.com
+ --
+ protocol=http
+ host=example.com
+ username=three
+ password=four
+ --
+ verbatim-with-expiry: get
+ verbatim-with-expiry: protocol=http
+ verbatim-with-expiry: host=example.com
+ verbatim: get
+ verbatim: protocol=http
+ verbatim: host=example.com
+ verbatim: username=one
+ EOF
+'
+
test_expect_success 'credential_fill passes along metadata' '
check fill "verbatim one two" <<-\EOF
protocol=ftp
@@ -149,6 +196,24 @@ test_expect_success 'credential_approve calls all helpers' '
EOF
'
+test_expect_success 'credential_approve stores password expiry' '
+ check approve useless <<-\EOF
+ protocol=http
+ host=example.com
+ username=foo
+ password=bar
+ password_expiry_utc=9999999999
+ --
+ --
+ useless: store
+ useless: protocol=http
+ useless: host=example.com
+ useless: username=foo
+ useless: password=bar
+ useless: password_expiry_utc=9999999999
+ EOF
+'
+
test_expect_success 'do not bother storing password-less credential' '
check approve useless <<-\EOF
protocol=http
@@ -159,6 +224,17 @@ test_expect_success 'do not bother storing password-less credential' '
EOF
'
+test_expect_success 'credential_approve does not store expired password' '
+ check approve useless <<-\EOF
+ protocol=http
+ host=example.com
+ username=foo
+ password=bar
+ password_expiry_utc=5
+ --
+ --
+ EOF
+'
test_expect_success 'credential_reject calls all helpers' '
check reject useless "verbatim one two" <<-\EOF
@@ -181,6 +257,24 @@ test_expect_success 'credential_reject calls all helpers' '
EOF
'
+test_expect_success 'credential_reject erases credential regardless of expiry' '
+ check reject useless <<-\EOF
+ protocol=http
+ host=example.com
+ username=foo
+ password=bar
+ password_expiry_utc=5
+ --
+ --
+ useless: erase
+ useless: protocol=http
+ useless: host=example.com
+ useless: username=foo
+ useless: password=bar
+ useless: password_expiry_utc=5
+ EOF
+'
+
test_expect_success 'usernames can be preserved' '
check fill "verbatim \"\" three" <<-\EOF
protocol=http
diff --git a/t/t1301-shared-repo.sh b/t/t1301-shared-repo.sh
index 58d6da7feb..1b6437ec07 100755
--- a/t/t1301-shared-repo.sh
+++ b/t/t1301-shared-repo.sh
@@ -9,6 +9,7 @@ GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_CREATE_REPO_NO_TEMPLATE=1
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Remove a default ACL from the test dir if possible.
diff --git a/t/t1302-repo-version.sh b/t/t1302-repo-version.sh
index 7cf80bf66a..70389fa2eb 100755
--- a/t/t1302-repo-version.sh
+++ b/t/t1302-repo-version.sh
@@ -5,6 +5,7 @@
test_description='Test repository version check'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t1304-default-acl.sh b/t/t1304-default-acl.sh
index c69ae41306..31b89dd969 100755
--- a/t/t1304-default-acl.sh
+++ b/t/t1304-default-acl.sh
@@ -9,6 +9,7 @@ test_description='Test repository with default ACL'
# => this must come before . ./test-lib.sh
umask 077
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# We need an arbitrary other user give permission to using ACLs. root
diff --git a/t/t1401-symbolic-ref.sh b/t/t1401-symbolic-ref.sh
index d708acdb81..be23be30c7 100755
--- a/t/t1401-symbolic-ref.sh
+++ b/t/t1401-symbolic-ref.sh
@@ -189,4 +189,38 @@ test_expect_success 'symbolic-ref pointing at another' '
test_cmp expect actual
'
+test_expect_success 'symbolic-ref --short handles complex utf8 case' '
+ name="测试-加-增加-加-增加" &&
+ git symbolic-ref TEST_SYMREF "refs/heads/$name" &&
+ # In the real world, we saw problems with this case only
+ # when the locale includes UTF-8. Set it here to try to make things as
+ # hard as possible for us to pass, but in practice we should do the
+ # right thing regardless (and of course some platforms may not even
+ # have this locale).
+ LC_ALL=en_US.UTF-8 git symbolic-ref --short TEST_SYMREF >actual &&
+ echo "$name" >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'symbolic-ref --short handles name with suffix' '
+ git symbolic-ref TEST_SYMREF "refs/remotes/origin/HEAD" &&
+ git symbolic-ref --short TEST_SYMREF >actual &&
+ echo "origin" >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'symbolic-ref --short handles almost-matching name' '
+ git symbolic-ref TEST_SYMREF "refs/headsXfoo" &&
+ git symbolic-ref --short TEST_SYMREF >actual &&
+ echo "headsXfoo" >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'symbolic-ref --short handles name with percent' '
+ git symbolic-ref TEST_SYMREF "refs/heads/%foo" &&
+ git symbolic-ref --short TEST_SYMREF >actual &&
+ echo "%foo" >expect &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t1408-packed-refs.sh b/t/t1408-packed-refs.sh
index 41ba1f1d7f..9469c79a58 100755
--- a/t/t1408-packed-refs.sh
+++ b/t/t1408-packed-refs.sh
@@ -5,6 +5,7 @@ test_description='packed-refs entries are covered by loose refs'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t1410-reflog.sh b/t/t1410-reflog.sh
index aa59954f6c..6c45965b1e 100755
--- a/t/t1410-reflog.sh
+++ b/t/t1410-reflog.sh
@@ -7,6 +7,7 @@ test_description='Test prune and reflog expiration'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
check_have () {
diff --git a/t/t1416-ref-transaction-hooks.sh b/t/t1416-ref-transaction-hooks.sh
index 27731722a5..b32ca798f9 100755
--- a/t/t1416-ref-transaction-hooks.sh
+++ b/t/t1416-ref-transaction-hooks.sh
@@ -5,6 +5,7 @@ test_description='reference transaction hooks'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t1451-fsck-buffer.sh b/t/t1451-fsck-buffer.sh
index 9ac270abab..3413da40e4 100755
--- a/t/t1451-fsck-buffer.sh
+++ b/t/t1451-fsck-buffer.sh
@@ -14,6 +14,8 @@ so.
These tests _might_ catch such overruns in normal use, but should be run with
ASan or valgrind for more confidence.
'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# the general idea for tags and commits is to build up the "base" file
diff --git a/t/t1800-hook.sh b/t/t1800-hook.sh
index 2ef3579fa7..3506f627b6 100755
--- a/t/t1800-hook.sh
+++ b/t/t1800-hook.sh
@@ -177,4 +177,22 @@ test_expect_success 'git hook run a hook with a bad shebang' '
test_cmp expect actual
'
+test_expect_success 'stdin to hooks' '
+ write_script .git/hooks/test-hook <<-\EOF &&
+ echo BEGIN stdin
+ cat
+ echo END stdin
+ EOF
+
+ cat >expect <<-EOF &&
+ BEGIN stdin
+ hello
+ END stdin
+ EOF
+
+ echo hello >input &&
+ git hook run --to-stdin=input test-hook 2>actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t2015-checkout-unborn.sh b/t/t2015-checkout-unborn.sh
index 9425aae639..fb0e13881c 100755
--- a/t/t2015-checkout-unborn.sh
+++ b/t/t2015-checkout-unborn.sh
@@ -9,11 +9,12 @@ TEST_PASSES_SANITIZE_LEAK=true
test_expect_success 'setup' '
mkdir parent &&
- (cd parent &&
- git init &&
- echo content >file &&
- git add file &&
- git commit -m base
+ (
+ cd parent &&
+ git init &&
+ echo content >file &&
+ git add file &&
+ git commit -m base
) &&
git fetch parent main:origin
'
diff --git a/t/t2401-worktree-prune.sh b/t/t2401-worktree-prune.sh
index 3d28c7f06b..568a47ec42 100755
--- a/t/t2401-worktree-prune.sh
+++ b/t/t2401-worktree-prune.sh
@@ -5,6 +5,7 @@ test_description='prune $GIT_DIR/worktrees'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success initialize '
diff --git a/t/t2402-worktree-list.sh b/t/t2402-worktree-list.sh
index 79e0fce2d9..9ad9be0c20 100755
--- a/t/t2402-worktree-list.sh
+++ b/t/t2402-worktree-list.sh
@@ -5,6 +5,7 @@ test_description='test git worktree list'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t2406-worktree-repair.sh b/t/t2406-worktree-repair.sh
index 5c44453e1c..8970780efc 100755
--- a/t/t2406-worktree-repair.sh
+++ b/t/t2406-worktree-repair.sh
@@ -2,6 +2,7 @@
test_description='test git worktree repair'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t3206-range-diff.sh b/t/t3206-range-diff.sh
index 84dd0cd26d..b5f4d6a653 100755
--- a/t/t3206-range-diff.sh
+++ b/t/t3206-range-diff.sh
@@ -33,6 +33,26 @@ test_expect_success 'setup' '
u3 sha256:736c4bc
u4 sha256:673e77d
+ # topic (abbrev=10)
+ t1_abbrev sha1:4de457d2c0
+ t2_abbrev sha1:fccce22f8c
+ t3_abbrev sha1:147e64ef53
+ t4_abbrev sha1:a63e992599
+ t1_abbrev sha256:b89f8b9092
+ t2_abbrev sha256:5f12aadf34
+ t3_abbrev sha256:ea8b273a6c
+ t4_abbrev sha256:14b73361fc
+
+ # unmodified (abbrev=10)
+ u1_abbrev sha1:35b9b25f76
+ u2_abbrev sha1:de345ab3de
+ u3_abbrev sha1:9af6654000
+ u4_abbrev sha1:2901f773f3
+ u1_abbrev sha256:e3731be242
+ u2_abbrev sha256:14fadf8cee
+ u3_abbrev sha256:736c4bcb44
+ u4_abbrev sha256:673e77d589
+
# reordered
r1 sha1:aca177a
r2 sha1:14ad629
@@ -153,6 +173,18 @@ test_expect_success 'simple A B C (unmodified)' '
test_cmp expect actual
'
+test_expect_success 'simple A..B A..C (unmodified) with --abbrev' '
+ git range-diff --no-color --abbrev=10 main..topic main..unmodified \
+ >actual &&
+ cat >expect <<-EOF &&
+ 1: $(test_oid t1_abbrev) = 1: $(test_oid u1_abbrev) s/5/A/
+ 2: $(test_oid t2_abbrev) = 2: $(test_oid u2_abbrev) s/4/A/
+ 3: $(test_oid t3_abbrev) = 3: $(test_oid u3_abbrev) s/11/B/
+ 4: $(test_oid t4_abbrev) = 4: $(test_oid u4_abbrev) s/12/B/
+ EOF
+ test_cmp expect actual
+'
+
test_expect_success 'A^! and A^-<n> (unmodified)' '
git range-diff --no-color topic^! unmodified^-1 >actual &&
cat >expect <<-EOF &&
diff --git a/t/t3210-pack-refs.sh b/t/t3210-pack-refs.sh
index 577f32dc71..07a0ff93de 100755
--- a/t/t3210-pack-refs.sh
+++ b/t/t3210-pack-refs.sh
@@ -12,6 +12,7 @@ semantic is still the same.
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'enable reflogs' '
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index 462cefd25d..efeb74ad50 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -2072,6 +2072,7 @@ test_expect_success '--update-refs: --edit-todo with no update-ref lines' '
'
test_expect_success '--update-refs: check failed ref update' '
+ test_when_finished "test_might_fail git rebase --abort" &&
git checkout -B update-refs-error no-conflict-branch &&
git branch -f base HEAD~4 &&
git branch -f first HEAD~3 &&
@@ -2123,6 +2124,28 @@ test_expect_success '--update-refs: check failed ref update' '
test_cmp expect err.trimmed
'
+test_expect_success 'bad labels and refs rejected when parsing todo list' '
+ test_when_finished "test_might_fail git rebase --abort" &&
+ cat >todo <<-\EOF &&
+ exec >execed
+ label #
+ label :invalid
+ update-ref :bad
+ update-ref topic
+ EOF
+ rm -f execed &&
+ (
+ set_replace_editor todo &&
+ test_must_fail git rebase -i HEAD 2>err
+ ) &&
+ grep "'\''#'\'' is not a valid label" err &&
+ grep "'\'':invalid'\'' is not a valid label" err &&
+ grep "'\'':bad'\'' is not a valid refname" err &&
+ grep "update-ref requires a fully qualified refname e.g. refs/heads/topic" \
+ err &&
+ test_path_is_missing execed
+'
+
# This must be the last test in this file
test_expect_success '$EDITOR and friends are unchanged' '
test_editor_unchanged
diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index e3cf0ffbe5..d3e428ff46 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -4,6 +4,7 @@
test_description='git mktag: tag object verify test'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
###########################################################
diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh
index 012f155e10..f3313b8c58 100755
--- a/t/t4014-format-patch.sh
+++ b/t/t4014-format-patch.sh
@@ -2281,6 +2281,24 @@ test_expect_success 'format-patch --attach cover-letter only is non-multipart' '
test_line_count = 1 output
'
+test_expect_success 'format-patch with format.attach' '
+ test_when_finished "rm -fr patches" &&
+ separator=attachment-separator &&
+ test_config format.attach "$separator" &&
+ filename=$(git format-patch -o patches -1) &&
+ grep "^Content-Type: multipart/.*$separator" "$filename"
+'
+
+test_expect_success 'format-patch with format.attach=disabled' '
+ test_when_finished "rm -fr patches" &&
+ separator=attachment-separator &&
+ test_config_global format.attach "$separator" &&
+ test_config format.attach "" &&
+ filename=$(git format-patch -o patches -1) &&
+ # The output should not even declare content type for text/plain.
+ ! grep "^Content-Type: multipart/" "$filename"
+'
+
test_expect_success '-c format.mboxrd format-patch' '
sp=" " &&
cat >msg <<-INPUT_END &&
diff --git a/t/t4152-am-subjects.sh b/t/t4152-am-subjects.sh
index 4c68245aca..9f2edba1f8 100755
--- a/t/t4152-am-subjects.sh
+++ b/t/t4152-am-subjects.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test subject preservation with format-patch | am'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
make_patches() {
diff --git a/t/t4254-am-corrupt.sh b/t/t4254-am-corrupt.sh
index 54be7da161..45f1d4f95e 100755
--- a/t/t4254-am-corrupt.sh
+++ b/t/t4254-am-corrupt.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='git am with corrupt input'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
make_mbox_with_nul () {
diff --git a/t/t4256-am-format-flowed.sh b/t/t4256-am-format-flowed.sh
index 2369c4e17a..1015273bc8 100755
--- a/t/t4256-am-format-flowed.sh
+++ b/t/t4256-am-format-flowed.sh
@@ -2,6 +2,7 @@
test_description='test format=flowed support of git am'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t4257-am-interactive.sh b/t/t4257-am-interactive.sh
index aed8f4de3d..f26d7fd2db 100755
--- a/t/t4257-am-interactive.sh
+++ b/t/t4257-am-interactive.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='am --interactive tests'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'set up patches to apply' '
diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh
index eb3214bc17..918a2fc7c6 100755
--- a/t/t5000-tar-tree.sh
+++ b/t/t5000-tar-tree.sh
@@ -105,6 +105,18 @@ check_added() {
'
}
+check_mtime() {
+ dir=$1
+ path_in_archive=$2
+ mtime=$3
+
+ test_expect_success " validate mtime of $path_in_archive" '
+ test-tool chmtime --get $dir/$path_in_archive >actual.mtime &&
+ echo $mtime >expect.mtime &&
+ test_cmp expect.mtime actual.mtime
+ '
+}
+
test_expect_success 'setup' '
test_oid_cache <<-EOF
obj sha1:19f9c8273ec45a8938e6999cb59b3ff66739902a
@@ -174,6 +186,13 @@ test_expect_success 'git archive' '
check_tar b
+test_expect_success 'git archive --mtime' '
+ git archive --mtime=2002-02-02T02:02:02-0200 HEAD >with_mtime.tar
+'
+
+check_tar with_mtime
+check_mtime with_mtime a/a 1012622522
+
test_expect_success 'git archive --prefix=prefix/' '
git archive --prefix=prefix/ HEAD >with_prefix.tar
'
diff --git a/t/t5001-archive-attr.sh b/t/t5001-archive-attr.sh
index 2f6eef5e37..04d300eeda 100755
--- a/t/t5001-archive-attr.sh
+++ b/t/t5001-archive-attr.sh
@@ -3,6 +3,7 @@
test_description='git archive attribute tests'
TEST_CREATE_REPO_NO_TEMPLATE=1
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
SUBSTFORMAT='%H (%h)%n'
diff --git a/t/t5004-archive-corner-cases.sh b/t/t5004-archive-corner-cases.sh
index ae508e2162..9f2c6da80e 100755
--- a/t/t5004-archive-corner-cases.sh
+++ b/t/t5004-archive-corner-cases.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test corner cases of git-archive'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# the 10knuls.tar file is used to test for an empty git generated tar
diff --git a/t/t5302-pack-index.sh b/t/t5302-pack-index.sh
index 59e9e77223..f89809be53 100755
--- a/t/t5302-pack-index.sh
+++ b/t/t5302-pack-index.sh
@@ -4,6 +4,8 @@
#
test_description='pack index with 64-bit offsets and object CRC'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t5306-pack-nobase.sh b/t/t5306-pack-nobase.sh
index 51973f4a51..846c5ca7d3 100755
--- a/t/t5306-pack-nobase.sh
+++ b/t/t5306-pack-nobase.sh
@@ -6,6 +6,8 @@
test_description='git-pack-object with missing base
'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Create A-B chain
diff --git a/t/t5312-prune-corruption.sh b/t/t5312-prune-corruption.sh
index 9d8e249ae8..230cb38712 100755
--- a/t/t5312-prune-corruption.sh
+++ b/t/t5312-prune-corruption.sh
@@ -14,6 +14,7 @@ what currently happens. If that changes, these tests should be revisited.
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'disable reflogs' '
diff --git a/t/t5317-pack-objects-filter-objects.sh b/t/t5317-pack-objects-filter-objects.sh
index 5b707d911b..b26d476c64 100755
--- a/t/t5317-pack-objects-filter-objects.sh
+++ b/t/t5317-pack-objects-filter-objects.sh
@@ -5,6 +5,7 @@ test_description='git pack-objects using object filtering'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Test blob:none filter.
diff --git a/t/t5319-multi-pack-index.sh b/t/t5319-multi-pack-index.sh
index b5f9b10922..499d5d4c78 100755
--- a/t/t5319-multi-pack-index.sh
+++ b/t/t5319-multi-pack-index.sh
@@ -1015,4 +1015,20 @@ test_expect_success 'complains when run outside of a repository' '
grep "not a git repository" err
'
+test_expect_success 'repack with delta islands' '
+ git init repo &&
+ test_when_finished "rm -fr repo" &&
+ (
+ cd repo &&
+
+ test_commit first &&
+ git repack &&
+ test_commit second &&
+ git repack &&
+
+ git multi-pack-index write &&
+ git -c repack.useDeltaIslands=true multi-pack-index repack
+ )
+'
+
test_done
diff --git a/t/t5330-no-lazy-fetch-with-commit-graph.sh b/t/t5330-no-lazy-fetch-with-commit-graph.sh
index 2cc7fd7a47..5eb28f0512 100755
--- a/t/t5330-no-lazy-fetch-with-commit-graph.sh
+++ b/t/t5330-no-lazy-fetch-with-commit-graph.sh
@@ -2,6 +2,7 @@
test_description='test for no lazy fetch with the commit-graph'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup: prepare a repository with a commit' '
diff --git a/t/t5403-post-checkout-hook.sh b/t/t5403-post-checkout-hook.sh
index 978f240cda..cfaae54739 100755
--- a/t/t5403-post-checkout-hook.sh
+++ b/t/t5403-post-checkout-hook.sh
@@ -7,6 +7,7 @@ test_description='Test the post-checkout hook.'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t5405-send-pack-rewind.sh b/t/t5405-send-pack-rewind.sh
index 11f03239a0..1686ac13aa 100755
--- a/t/t5405-send-pack-rewind.sh
+++ b/t/t5405-send-pack-rewind.sh
@@ -5,6 +5,7 @@ test_description='forced push to replace commit we do not have'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t5406-remote-rejects.sh b/t/t5406-remote-rejects.sh
index dcbeb42082..d6a9946633 100755
--- a/t/t5406-remote-rejects.sh
+++ b/t/t5406-remote-rejects.sh
@@ -2,6 +2,7 @@
test_description='remote push rejects are reported by client'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t5502-quickfetch.sh b/t/t5502-quickfetch.sh
index b160f8b7fb..7b3ff21b98 100755
--- a/t/t5502-quickfetch.sh
+++ b/t/t5502-quickfetch.sh
@@ -5,6 +5,7 @@ test_description='test quickfetch from local'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t5504-fetch-receive-strict.sh b/t/t5504-fetch-receive-strict.sh
index 88d3c56750..0b8ab4afdb 100755
--- a/t/t5504-fetch-receive-strict.sh
+++ b/t/t5504-fetch-receive-strict.sh
@@ -4,6 +4,7 @@ test_description='fetch/receive strict mode'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup and inject "corrupt or missing" object' '
diff --git a/t/t5507-remote-environment.sh b/t/t5507-remote-environment.sh
index e6149295b1..c6a6957c50 100755
--- a/t/t5507-remote-environment.sh
+++ b/t/t5507-remote-environment.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='check environment showed to remote side of transports'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'set up "remote" push situation' '
diff --git a/t/t5514-fetch-multiple.sh b/t/t5514-fetch-multiple.sh
index 511ba3bd45..54f422ced3 100755
--- a/t/t5514-fetch-multiple.sh
+++ b/t/t5514-fetch-multiple.sh
@@ -197,4 +197,9 @@ test_expect_success 'parallel' '
test_i18ngrep "could not fetch .two.*128" err
'
+test_expect_success 'git fetch --multiple --jobs=0 picks a default' '
+ (cd test &&
+ git fetch --multiple --jobs=0)
+'
+
test_done
diff --git a/t/t5522-pull-symlink.sh b/t/t5522-pull-symlink.sh
index bcff460d0a..394bc60cb8 100755
--- a/t/t5522-pull-symlink.sh
+++ b/t/t5522-pull-symlink.sh
@@ -2,6 +2,7 @@
test_description='pulling from symlinked subdir'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# The scenario we are building:
diff --git a/t/t5523-push-upstream.sh b/t/t5523-push-upstream.sh
index fdb4292056..c9acc07635 100755
--- a/t/t5523-push-upstream.sh
+++ b/t/t5523-push-upstream.sh
@@ -4,6 +4,7 @@ test_description='push with --set-upstream'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-terminal.sh
diff --git a/t/t5527-fetch-odd-refs.sh b/t/t5527-fetch-odd-refs.sh
index e2770e4541..98ece27c6a 100755
--- a/t/t5527-fetch-odd-refs.sh
+++ b/t/t5527-fetch-odd-refs.sh
@@ -4,6 +4,7 @@ test_description='test fetching of oddly-named refs'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# afterwards we will have:
diff --git a/t/t5529-push-errors.sh b/t/t5529-push-errors.sh
index ce85fd30ad..0247137cb3 100755
--- a/t/t5529-push-errors.sh
+++ b/t/t5529-push-errors.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='detect some push errors early (before contacting remote)'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup commits' '
diff --git a/t/t5546-receive-limits.sh b/t/t5546-receive-limits.sh
index 0b0e987fdb..eed3c9d81a 100755
--- a/t/t5546-receive-limits.sh
+++ b/t/t5546-receive-limits.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='check receive input limits'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Let's run tests with different unpack limits: 1 and 10000
diff --git a/t/t5547-push-quarantine.sh b/t/t5547-push-quarantine.sh
index 1876fb34e5..9f899b8c7d 100755
--- a/t/t5547-push-quarantine.sh
+++ b/t/t5547-push-quarantine.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='check quarantine of objects during push'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'create picky dest repo' '
diff --git a/t/t5560-http-backend-noserver.sh b/t/t5560-http-backend-noserver.sh
index d30cf4f5b8..f75068de64 100755
--- a/t/t5560-http-backend-noserver.sh
+++ b/t/t5560-http-backend-noserver.sh
@@ -4,6 +4,7 @@ test_description='test git-http-backend-noserver'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
HTTPD_DOCUMENT_ROOT_PATH="$TRASH_DIRECTORY"
diff --git a/t/t5561-http-backend.sh b/t/t5561-http-backend.sh
index 9c57d84315..e1d3b8caed 100755
--- a/t/t5561-http-backend.sh
+++ b/t/t5561-http-backend.sh
@@ -4,6 +4,7 @@ test_description='test git-http-backend'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-httpd.sh
diff --git a/t/t5562-http-backend-content-length.sh b/t/t5562-http-backend-content-length.sh
index b68ec22d3f..7ee9858a78 100755
--- a/t/t5562-http-backend-content-length.sh
+++ b/t/t5562-http-backend-content-length.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test git-http-backend respects CONTENT_LENGTH'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_lazy_prereq GZIP 'gzip --version'
diff --git a/t/t5564-http-proxy.sh b/t/t5564-http-proxy.sh
new file mode 100755
index 0000000000..9da5134614
--- /dev/null
+++ b/t/t5564-http-proxy.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+test_description="test fetching through http proxy"
+
+. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-httpd.sh
+
+LIB_HTTPD_PROXY=1
+start_httpd
+
+test_expect_success 'setup repository' '
+ test_commit foo &&
+ git init --bare "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
+ git push --mirror "$HTTPD_DOCUMENT_ROOT_PATH/repo.git"
+'
+
+setup_askpass_helper
+
+# sanity check that our test setup is correctly using proxy
+test_expect_success 'proxy requires password' '
+ test_config_global http.proxy $HTTPD_DEST &&
+ test_must_fail git clone $HTTPD_URL/smart/repo.git 2>err &&
+ grep "error.*407" err
+'
+
+test_expect_success 'clone through proxy with auth' '
+ test_when_finished "rm -rf clone" &&
+ test_config_global http.proxy http://proxuser:proxpass@$HTTPD_DEST &&
+ GIT_TRACE_CURL=$PWD/trace git clone $HTTPD_URL/smart/repo.git clone &&
+ grep -i "Proxy-Authorization: Basic <redacted>" trace
+'
+
+test_expect_success 'clone can prompt for proxy password' '
+ test_when_finished "rm -rf clone" &&
+ test_config_global http.proxy http://proxuser@$HTTPD_DEST &&
+ set_askpass nobody proxpass &&
+ GIT_TRACE_CURL=$PWD/trace git clone $HTTPD_URL/smart/repo.git clone &&
+ expect_askpass pass proxuser
+'
+
+test_done
diff --git a/t/t5573-pull-verify-signatures.sh b/t/t5573-pull-verify-signatures.sh
index a53dd8550d..1221ac0597 100755
--- a/t/t5573-pull-verify-signatures.sh
+++ b/t/t5573-pull-verify-signatures.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='pull signature verification tests'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY/lib-gpg.sh"
diff --git a/t/t5604-clone-reference.sh b/t/t5604-clone-reference.sh
index 7ccebb40c3..83e3c97861 100755
--- a/t/t5604-clone-reference.sh
+++ b/t/t5604-clone-reference.sh
@@ -7,6 +7,7 @@ test_description='test clone --reference'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
base_dir=$(pwd)
diff --git a/t/t5606-clone-options.sh b/t/t5606-clone-options.sh
index cf221e92c4..27f9f77638 100755
--- a/t/t5606-clone-options.sh
+++ b/t/t5606-clone-options.sh
@@ -4,6 +4,7 @@ test_description='basic clone options'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t5613-info-alternate.sh b/t/t5613-info-alternate.sh
index 895f46bb91..7708cbafa9 100755
--- a/t/t5613-info-alternate.sh
+++ b/t/t5613-info-alternate.sh
@@ -4,6 +4,8 @@
#
test_description='test transitive info/alternate entries'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'preparing first repository' '
diff --git a/t/t5705-session-id-in-capabilities.sh b/t/t5705-session-id-in-capabilities.sh
index ed38c76c29..b8a722ec27 100755
--- a/t/t5705-session-id-in-capabilities.sh
+++ b/t/t5705-session-id-in-capabilities.sh
@@ -2,6 +2,7 @@
test_description='session ID in capabilities'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
REPO="$(pwd)/repo"
diff --git a/t/t5810-proto-disable-local.sh b/t/t5810-proto-disable-local.sh
index c1ef99b85c..862610256f 100755
--- a/t/t5810-proto-disable-local.sh
+++ b/t/t5810-proto-disable-local.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test disabling of local paths in clone/fetch'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY/lib-proto-disable.sh"
diff --git a/t/t5813-proto-disable-ssh.sh b/t/t5813-proto-disable-ssh.sh
index 3f084ee306..2e975dc70e 100755
--- a/t/t5813-proto-disable-ssh.sh
+++ b/t/t5813-proto-disable-ssh.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='test disabling of git-over-ssh in clone/fetch'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY/lib-proto-disable.sh"
diff --git a/t/t6011-rev-list-with-bad-commit.sh b/t/t6011-rev-list-with-bad-commit.sh
index bad02cf5b8..b2e422cf0f 100755
--- a/t/t6011-rev-list-with-bad-commit.sh
+++ b/t/t6011-rev-list-with-bad-commit.sh
@@ -2,6 +2,7 @@
test_description='git rev-list should notice bad commits'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Note:
diff --git a/t/t6014-rev-list-all.sh b/t/t6014-rev-list-all.sh
index c9bedd29cb..16b8bd1d09 100755
--- a/t/t6014-rev-list-all.sh
+++ b/t/t6014-rev-list-all.sh
@@ -2,6 +2,7 @@
test_description='--all includes detached HEADs'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
diff --git a/t/t6021-rev-list-exclude-hidden.sh b/t/t6021-rev-list-exclude-hidden.sh
index 32b2b09413..11c50b7c0d 100755
--- a/t/t6021-rev-list-exclude-hidden.sh
+++ b/t/t6021-rev-list-exclude-hidden.sh
@@ -2,6 +2,7 @@
test_description='git rev-list --exclude-hidden test'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t6120-describe.sh b/t/t6120-describe.sh
index 9a35e783a7..c9afcef201 100755
--- a/t/t6120-describe.sh
+++ b/t/t6120-describe.sh
@@ -657,4 +657,10 @@ test_expect_success 'setup: describe commits with disjoint bases 2' '
check_describe -C disjoint2 "B-3-gHASH" HEAD
+test_expect_success 'setup misleading taggerdates' '
+ GIT_COMMITTER_DATE="2006-12-12 12:31" git tag -a -m "another tag" newer-tag-older-commit unique-file~1
+'
+
+check_describe newer-tag-older-commit~1 --contains unique-file~2
+
test_done
diff --git a/t/t6439-merge-co-error-msgs.sh b/t/t6439-merge-co-error-msgs.sh
index 52cf0c8769..0cbec57cda 100755
--- a/t/t6439-merge-co-error-msgs.sh
+++ b/t/t6439-merge-co-error-msgs.sh
@@ -5,6 +5,7 @@ test_description='unpack-trees error messages'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
diff --git a/t/t6501-freshen-objects.sh b/t/t6501-freshen-objects.sh
index 10662456ae..3968b47ed5 100755
--- a/t/t6501-freshen-objects.sh
+++ b/t/t6501-freshen-objects.sh
@@ -28,6 +28,7 @@ test_description='check pruning of dependent objects'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# We care about reachability, so we do not want to use
diff --git a/t/t7105-reset-patch.sh b/t/t7105-reset-patch.sh
index fc2a6cf5c7..9b46da7aaa 100755
--- a/t/t7105-reset-patch.sh
+++ b/t/t7105-reset-patch.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='git reset --patch'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-patch-mode.sh
test_expect_success PERL 'setup' '
diff --git a/t/t7106-reset-unborn-branch.sh b/t/t7106-reset-unborn-branch.sh
index ecb85c3b82..a0b67a0b84 100755
--- a/t/t7106-reset-unborn-branch.sh
+++ b/t/t7106-reset-unborn-branch.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='git reset should work on unborn branch'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t7107-reset-pathspec-file.sh b/t/t7107-reset-pathspec-file.sh
index 523efbecde..af5ea406db 100755
--- a/t/t7107-reset-pathspec-file.sh
+++ b/t/t7107-reset-pathspec-file.sh
@@ -2,6 +2,7 @@
test_description='reset --pathspec-from-file'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_tick
diff --git a/t/t7301-clean-interactive.sh b/t/t7301-clean-interactive.sh
index a07e8b86de..d82a3210a1 100755
--- a/t/t7301-clean-interactive.sh
+++ b/t/t7301-clean-interactive.sh
@@ -2,6 +2,7 @@
test_description='git clean -i basic tests'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-terminal.sh
diff --git a/t/t7403-submodule-sync.sh b/t/t7403-submodule-sync.sh
index ea92ef52a5..ff09443a0a 100755
--- a/t/t7403-submodule-sync.sh
+++ b/t/t7403-submodule-sync.sh
@@ -11,6 +11,7 @@ These tests exercise the "git submodule sync" subcommand.
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t7409-submodule-detached-work-tree.sh b/t/t7409-submodule-detached-work-tree.sh
index 374ed481e9..574a6fc526 100755
--- a/t/t7409-submodule-detached-work-tree.sh
+++ b/t/t7409-submodule-detached-work-tree.sh
@@ -13,6 +13,7 @@ TEST_NO_CREATE_REPO=1
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t7416-submodule-dash-url.sh b/t/t7416-submodule-dash-url.sh
index 3ebd985981..7cf72b9a07 100755
--- a/t/t7416-submodule-dash-url.sh
+++ b/t/t7416-submodule-dash-url.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='check handling of disallowed .gitmodule urls'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t7450-bad-git-dotfiles.sh b/t/t7450-bad-git-dotfiles.sh
index ba1f569bcb..0d0c3f2c68 100755
--- a/t/t7450-bad-git-dotfiles.sh
+++ b/t/t7450-bad-git-dotfiles.sh
@@ -12,6 +12,8 @@ Such as:
- symlinked .gitmodules, etc
'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-pack.sh
diff --git a/t/t7510-signed-commit.sh b/t/t7510-signed-commit.sh
index bc7a31ba3e..48f86cb367 100755
--- a/t/t7510-signed-commit.sh
+++ b/t/t7510-signed-commit.sh
@@ -387,4 +387,48 @@ test_expect_success GPG 'verify-commit verifies multiply signed commits' '
! grep "BAD signature from" actual
'
+test_expect_success 'custom `gpg.program`' '
+ write_script fake-gpg <<-\EOF &&
+ args="$*"
+
+ # skip uninteresting options
+ while case "$1" in
+ --status-fd=*|--keyid-format=*) ;; # skip
+ *) break;;
+ esac; do shift; done
+
+ case "$1" in
+ -bsau)
+ test -z "$LET_GPG_PROGRAM_FAIL" || {
+ echo "zOMG signing failed!" >&2
+ exit 1
+ }
+ cat >sign.file
+ echo "[GNUPG:] SIG_CREATED $args" >&2
+ echo "-----BEGIN PGP MESSAGE-----"
+ echo "$args"
+ echo "-----END PGP MESSAGE-----"
+ ;;
+ --verify)
+ cat "$2" >verify.file
+ exit 0
+ ;;
+ *)
+ echo "Unhandled args: $*" >&2
+ exit 1
+ ;;
+ esac
+ EOF
+
+ test_config gpg.program "$(pwd)/fake-gpg" &&
+ git commit -S --allow-empty -m signed-commit &&
+ test_path_exists sign.file &&
+ git show --show-signature &&
+ test_path_exists verify.file &&
+
+ test_must_fail env LET_GPG_PROGRAM_FAIL=1 \
+ git commit -S --allow-empty -m must-fail 2>err &&
+ grep zOMG err
+'
+
test_done
diff --git a/t/t7612-merge-verify-signatures.sh b/t/t7612-merge-verify-signatures.sh
index 61330f71b1..f5c90cc22a 100755
--- a/t/t7612-merge-verify-signatures.sh
+++ b/t/t7612-merge-verify-signatures.sh
@@ -4,6 +4,7 @@ test_description='merge signature verification tests'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY/lib-gpg.sh"
diff --git a/t/t7701-repack-unpack-unreachable.sh b/t/t7701-repack-unpack-unreachable.sh
index b7ac4f598a..ebb267855f 100755
--- a/t/t7701-repack-unpack-unreachable.sh
+++ b/t/t7701-repack-unpack-unreachable.sh
@@ -5,6 +5,7 @@ test_description='git repack works correctly'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
fsha1=
diff --git a/userdiff.c b/userdiff.c
index 94cca1a2a8..58a3d59ef8 100644
--- a/userdiff.c
+++ b/userdiff.c
@@ -293,7 +293,7 @@ PATTERNS("scheme",
"|([^][)(}{[ \t])+"),
PATTERNS("tex", "^(\\\\((sub)*section|chapter|part)\\*{0,1}\\{.*)$",
"\\\\[a-zA-Z@]+|\\\\.|[a-zA-Z0-9\x80-\xff]+"),
-{ "default", NULL, -1, { NULL, 0 } },
+{ "default", NULL, NULL, -1, { NULL, 0 } },
};
#undef PATTERNS
#undef IPATTERN
@@ -394,6 +394,8 @@ int userdiff_config(const char *k, const char *v)
return parse_bool(&drv->textconv_want_cache, k, v);
if (!strcmp(type, "wordregex"))
return git_config_string(&drv->word_regex, k, v);
+ if (!strcmp(type, "algorithm"))
+ return git_config_string(&drv->algorithm, k, v);
return 0;
}
diff --git a/userdiff.h b/userdiff.h
index aee91bc77e..24419db697 100644
--- a/userdiff.h
+++ b/userdiff.h
@@ -14,6 +14,7 @@ struct userdiff_funcname {
struct userdiff_driver {
const char *name;
const char *external;
+ const char *algorithm;
int binary;
struct userdiff_funcname funcname;
const char *word_regex;