aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/RelNotes/2.48.0.txt30
-rw-r--r--Documentation/fetch-options.txt2
-rw-r--r--Documentation/git-clone.txt2
-rw-r--r--Documentation/git-fetch-pack.txt2
-rw-r--r--Documentation/git-index-pack.txt5
-rw-r--r--builtin/clone.c4
-rw-r--r--builtin/commit.c26
-rw-r--r--builtin/fetch.c4
-rw-r--r--builtin/grep.c13
-rw-r--r--builtin/index-pack.c111
-rw-r--r--builtin/ls-remote.c1
-rw-r--r--builtin/merge.c1
-rw-r--r--builtin/pack-objects.c28
-rw-r--r--builtin/pull.c4
-rw-r--r--builtin/tag.c2
-rw-r--r--combine-diff.c5
-rw-r--r--compat/mingw.c157
-rw-r--r--diff-lib.c1
-rw-r--r--dir.c12
-rw-r--r--fetch-pack.c42
-rw-r--r--grep.c1
-rw-r--r--list-objects-filter-options.c17
-rw-r--r--pretty.c1
-rw-r--r--revision.c5
-rw-r--r--sparse-index.c7
-rw-r--r--t/helper/test-dump-untracked-cache.c2
-rw-r--r--t/helper/test-reach.c10
-rw-r--r--t/helper/test-read-cache.c2
-rwxr-xr-xt/t0410-partial-clone.sh6
-rwxr-xr-xt/t0610-reftable-basics.sh8
-rwxr-xr-xt/t1016-compatObjectFormat.sh262
-rwxr-xr-xt/t4038-diff-combined.sh1
-rwxr-xr-xt/t4202-log.sh1
-rwxr-xr-xt/t4216-log-bloom.sh1
-rwxr-xr-xt/t5300-pack-object.sh10
-rwxr-xr-xt/t5330-no-lazy-fetch-with-commit-graph.sh4
-rwxr-xr-xt/t5500-fetch-pack.sh7
-rwxr-xr-xt/t5616-partial-clone.sh30
-rwxr-xr-xt/t5702-protocol-v2.sh1
-rwxr-xr-xt/t5801-remote-helpers.sh1
-rwxr-xr-xt/t6112-rev-list-filters-objects.sh1
-rwxr-xr-xt/t6424-merge-unrelated-index-changes.sh1
-rwxr-xr-xt/t6600-test-reach.sh1
-rwxr-xr-xt/t7004-tag.sh1
-rwxr-xr-xt/t7031-verify-tag-signed-ssh.sh1
-rwxr-xr-xt/t7063-status-untracked-cache.sh1
-rwxr-xr-xt/t7500-commit-template-squash-signoff.sh1
-rwxr-xr-xt/t7502-commit-porcelain.sh1
-rwxr-xr-xt/t7510-signed-commit.sh1
-rwxr-xr-xt/t7513-interpret-trailers.sh1
-rwxr-xr-xt/t7519-status-fsmonitor.sh1
-rwxr-xr-xt/t7528-signed-commit-ssh.sh1
-rwxr-xr-xt/t7610-mergetool.sh1
-rwxr-xr-xt/t7810-grep.sh1
-rw-r--r--trailer.c22
-rw-r--r--transport-helper.c2
-rw-r--r--upload-pack.c7
57 files changed, 641 insertions, 233 deletions
diff --git a/Documentation/RelNotes/2.48.0.txt b/Documentation/RelNotes/2.48.0.txt
index 9e882c8352..8eb6f81d3c 100644
--- a/Documentation/RelNotes/2.48.0.txt
+++ b/Documentation/RelNotes/2.48.0.txt
@@ -109,28 +109,38 @@ Fixes since v2.47
(merge 0c1a9987da db/submodule-fetch-with-remote-name-fix later to maint).
* Fixes compile time warnings with 64-bit MSVC.
- (merge 386d372031 sk/msvc-warnings later to maint).
* Teaches 'shortlog' to explicitly use SHA-1 when operating outside
of a repository.
- (merge b33001645e wm/shortlog-hash later to maint).
* Fix 'git grep' regression on macOS by disabling lookahead when
encountering invalid UTF-8 byte sequences.
- (merge ce025ae4f6 rs/grep-lookahead later to maint).
* The dumb-http code regressed when the result of re-indexing a pack
yielded an *.idx file that differs in content from the *.idx file
it downloaded from the remote. This has been corrected by no longer
relying on: the *.idx file we got from the remote.
- (merge 863f2459a2 jk/dumb-http-finalize later to maint).
* When called with '--left-right' and '--use-bitmap-index', 'rev-list'
will produce output without any left/right markers, which has been
corrected.
+ * More leakfixes.
+
+ * Test modernization.
+
+ * The "--shallow-exclude=<ref>" option to various history transfer
+ commands takes a ref, not an arbitrary revision.
+
+ * A regression where commit objects missing from a commit-graph can
+ cause an infinite loop when doing a fetch in a partial clone has
+ been fixed.
+
+ * The MinGW compatibility layer has been taught to support POSIX
+ semantics for atomic renames when other process(es) have a file
+ opened at the destination path.
+
* Other code cleanup, docfix, build fix, etc.
- (merge 66893a14d0 ps/leakfixes-part-8 later to maint).
(merge 1164e270b5 jk/output-prefix-cleanup later to maint).
(merge f36b8cbaef jh/config-unset-doc-fix later to maint).
(merge 4154ed4108 js/doc-platform-support-link-fix later to maint).
@@ -142,14 +152,4 @@ Fixes since v2.47
(merge 6dab49b9fb tc/bundle-uri-leakfix later to maint).
(merge f1ed39987b xx/protocol-v2-doc-markup-fix later to maint).
(merge 41869f7447 ak/typofixes later to maint).
- (merge f1eea0b620 ak/typofix later to maint).
(merge dcd590a39d bf/t-readme-mention-reftable later to maint).
- (merge 52acf6771b kh/submitting-patches later to maint).
- (merge a73070fbd4 ks/t4205-fixup later to maint).
- (merge 9e362dd060 co/t6050-pipefix later to maint).
- (merge 91687cd13f sk/t7011-cleanup later to maint).
- (merge 19c291e5b2 ua/t3404-cleanup later to maint).
- (merge c32d4a8cfe ss/duplicate-typos later to maint).
- (merge 09bf122507 sk/t9101-cleanup later to maint).
- (merge c348191afe ak/t1016-cleanup later to maint).
- (merge f56f9d6c0b ak/more-typofixes later to maint).
diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt
index 9dc7ac8dbd..b01372e4b3 100644
--- a/Documentation/fetch-options.txt
+++ b/Documentation/fetch-options.txt
@@ -29,7 +29,7 @@
Deepen or shorten the history of a shallow repository to
include all reachable commits after <date>.
---shallow-exclude=<revision>::
+--shallow-exclude=<ref>::
Deepen or shorten the history of a shallow repository to
exclude commits reachable from a specified remote branch or tag.
This option can be specified multiple times.
diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt
index 116ad64820..7acb4cb176 100644
--- a/Documentation/git-clone.txt
+++ b/Documentation/git-clone.txt
@@ -255,7 +255,7 @@ corresponding `--mirror` and `--no-tags` options instead.
`--shallow-since=<date>`::
Create a shallow clone with a history after the specified time.
-`--shallow-exclude=<revision>`::
+`--shallow-exclude=<ref>`::
Create a shallow clone with a history, excluding commits
reachable from a specified remote branch or tag. This option
can be specified multiple times.
diff --git a/Documentation/git-fetch-pack.txt b/Documentation/git-fetch-pack.txt
index b3467664d3..b5223576a7 100644
--- a/Documentation/git-fetch-pack.txt
+++ b/Documentation/git-fetch-pack.txt
@@ -91,7 +91,7 @@ be in a separate packet, and the list must end with a flush packet.
Deepen or shorten the history of a shallow repository to
include all reachable commits after <date>.
---shallow-exclude=<revision>::
+--shallow-exclude=<ref>::
Deepen or shorten the history of a shallow repository to
exclude commits reachable from a specified remote branch or tag.
This option can be specified multiple times.
diff --git a/Documentation/git-index-pack.txt b/Documentation/git-index-pack.txt
index 5a20deefd5..4be09e58e7 100644
--- a/Documentation/git-index-pack.txt
+++ b/Documentation/git-index-pack.txt
@@ -139,6 +139,11 @@ include::object-format-disclaimer.txt[]
written. If a `<message>` is provided, then that content will be
written to the .promisor file for future reference. See
link:technical/partial-clone.html[partial clone] for more information.
++
+Also, if there are objects in the given pack that references non-promisor
+objects (in the repo), repacks those non-promisor objects into a promisor
+pack. This avoids a situation in which a repo has non-promisor objects that are
+accessible through promisor objects.
NOTES
-----
diff --git a/builtin/clone.c b/builtin/clone.c
index 59fcb317a6..c0013c75cd 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -147,8 +147,8 @@ static struct option builtin_clone_options[] = {
N_("create a shallow clone of that depth")),
OPT_STRING(0, "shallow-since", &option_since, N_("time"),
N_("create a shallow clone since a specific time")),
- OPT_STRING_LIST(0, "shallow-exclude", &option_not, N_("revision"),
- N_("deepen history of shallow clone, excluding rev")),
+ OPT_STRING_LIST(0, "shallow-exclude", &option_not, N_("ref"),
+ N_("deepen history of shallow clone, excluding ref")),
OPT_BOOL(0, "single-branch", &option_single_branch,
N_("clone only one branch, HEAD or --branch")),
OPT_BOOL(0, "no-tags", &option_no_tags,
diff --git a/builtin/commit.c b/builtin/commit.c
index 8db4e9df0c..71d674138c 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -135,7 +135,7 @@ static struct strvec trailer_args = STRVEC_INIT;
* is specified explicitly.
*/
static enum commit_msg_cleanup_mode cleanup_mode;
-static char *cleanup_arg;
+static char *cleanup_config;
static enum commit_whence whence;
static int use_editor = 1, include_status = 1;
@@ -728,6 +728,13 @@ static void prepare_amend_commit(struct commit *commit, struct strbuf *sb,
repo_unuse_commit_buffer(the_repository, commit, buffer);
}
+static void change_data_free(void *util, const char *str UNUSED)
+{
+ struct wt_status_change_data *d = util;
+ free(d->rename_source);
+ free(d);
+}
+
static int prepare_to_commit(const char *index_file, const char *prefix,
struct commit *current_head,
struct wt_status *s,
@@ -991,7 +998,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
s->use_color = 0;
committable = run_status(s->fp, index_file, prefix, 1, s);
s->use_color = saved_color_setting;
- string_list_clear(&s->change, 1);
+ string_list_clear_func(&s->change, change_data_free);
} else {
struct object_id oid;
const char *parent = "HEAD";
@@ -1380,8 +1387,6 @@ static int parse_and_validate_options(int argc, const char *argv[],
if (0 <= edit_flag)
use_editor = edit_flag;
- cleanup_mode = get_cleanup_mode(cleanup_arg, use_editor);
-
handle_untracked_files_arg(s);
if (all && argc > 0)
@@ -1629,8 +1634,10 @@ static int git_commit_config(const char *k, const char *v,
include_status = git_config_bool(k, v);
return 0;
}
- if (!strcmp(k, "commit.cleanup"))
- return git_config_string(&cleanup_arg, k, v);
+ if (!strcmp(k, "commit.cleanup")) {
+ FREE_AND_NULL(cleanup_config);
+ return git_config_string(&cleanup_config, k, v);
+ }
if (!strcmp(k, "commit.gpgsign")) {
sign_commit = git_config_bool(k, v) ? "" : NULL;
return 0;
@@ -1651,6 +1658,7 @@ int cmd_commit(int argc,
struct repository *repo UNUSED)
{
static struct wt_status s;
+ static const char *cleanup_arg = NULL;
static struct option builtin_commit_options[] = {
OPT__QUIET(&quiet, N_("suppress summary after successful commit")),
OPT__VERBOSE(&verbose, N_("show diff in commit message template")),
@@ -1750,6 +1758,12 @@ int cmd_commit(int argc,
if (verbose == -1)
verbose = (config_commit_verbose < 0) ? 0 : config_commit_verbose;
+ if (cleanup_arg) {
+ free(cleanup_config);
+ cleanup_config = xstrdup(cleanup_arg);
+ }
+ cleanup_mode = get_cleanup_mode(cleanup_config, use_editor);
+
if (dry_run)
return dry_run_commit(argv, prefix, current_head, &s);
index_file = prepare_index(argv, prefix, current_head, 0);
diff --git a/builtin/fetch.c b/builtin/fetch.c
index d9027e4dc9..18eff4e5fa 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -2216,8 +2216,8 @@ int cmd_fetch(int argc,
N_("deepen history of shallow clone")),
OPT_STRING(0, "shallow-since", &deepen_since, N_("time"),
N_("deepen history of shallow repository based on time")),
- OPT_STRING_LIST(0, "shallow-exclude", &deepen_not, N_("revision"),
- N_("deepen history of shallow clone, excluding rev")),
+ OPT_STRING_LIST(0, "shallow-exclude", &deepen_not, N_("ref"),
+ N_("deepen history of shallow clone, excluding ref")),
OPT_INTEGER(0, "deepen", &deepen_relative,
N_("deepen history of shallow clone")),
OPT_SET_INT_F(0, "unshallow", &unshallow,
diff --git a/builtin/grep.c b/builtin/grep.c
index f17d46a06e..98b85c7fca 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -906,6 +906,7 @@ int cmd_grep(int argc,
int dummy;
int use_index = 1;
int allow_revs;
+ int ret;
struct option options[] = {
OPT_BOOL(0, "cached", &cached,
@@ -1172,8 +1173,10 @@ int cmd_grep(int argc,
* Optimize out the case where the amount of matches is limited to zero.
* We do this to keep results consistent with GNU grep(1).
*/
- if (opt.max_count == 0)
- return 1;
+ if (opt.max_count == 0) {
+ ret = 1;
+ goto out;
+ }
if (show_in_pager) {
if (num_threads > 1)
@@ -1267,10 +1270,14 @@ int cmd_grep(int argc,
hit |= wait_all();
if (hit && show_in_pager)
run_pager(&opt, prefix);
+
+ ret = !hit;
+
+out:
clear_pathspec(&pathspec);
string_list_clear(&path_list, 0);
free_grep_patterns(&opt);
object_array_clear(&list);
free_repos();
- return !hit;
+ return ret;
}
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index 9d23b41b3a..08b340552f 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -9,6 +9,7 @@
#include "csum-file.h"
#include "blob.h"
#include "commit.h"
+#include "tag.h"
#include "tree.h"
#include "progress.h"
#include "fsck.h"
@@ -20,9 +21,14 @@
#include "object-file.h"
#include "object-store-ll.h"
#include "oid-array.h"
+#include "oidset.h"
+#include "path.h"
#include "replace-object.h"
+#include "tree-walk.h"
#include "promisor-remote.h"
+#include "run-command.h"
#include "setup.h"
+#include "strvec.h"
static const char index_pack_usage[] =
"git index-pack [-v] [-o <index-file>] [--keep | --keep=<msg>] [--[no-]rev-index] [--verify] [--strict[=<msg-id>=<severity>...]] [--fsck-objects[=<msg-id>=<severity>...]] (<pack-file> | --stdin [--fix-thin] [<pack-file>])";
@@ -148,6 +154,13 @@ static uint32_t input_crc32;
static int input_fd, output_fd;
static const char *curr_pack;
+/*
+ * local_links is guarded by read_mutex, and record_local_links is read-only in
+ * a thread.
+ */
+static struct oidset local_links = OIDSET_INIT;
+static int record_local_links;
+
static struct thread_local *thread_data;
static int nr_dispatched;
static int threads_active;
@@ -799,6 +812,44 @@ static int check_collison(struct object_entry *entry)
return 0;
}
+static void record_if_local_object(const struct object_id *oid)
+{
+ struct object_info info = OBJECT_INFO_INIT;
+ if (oid_object_info_extended(the_repository, oid, &info, 0))
+ /* Missing; assume it is a promisor object */
+ return;
+ if (info.whence == OI_PACKED && info.u.packed.pack->pack_promisor)
+ return;
+ oidset_insert(&local_links, oid);
+}
+
+static void do_record_local_links(struct object *obj)
+{
+ if (obj->type == OBJ_TREE) {
+ struct tree *tree = (struct tree *)obj;
+ struct tree_desc desc;
+ struct name_entry entry;
+ if (init_tree_desc_gently(&desc, &tree->object.oid,
+ tree->buffer, tree->size, 0))
+ /*
+ * Error messages are given when packs are
+ * verified, so do not print any here.
+ */
+ return;
+ while (tree_entry_gently(&desc, &entry))
+ record_if_local_object(&entry.oid);
+ } else if (obj->type == OBJ_COMMIT) {
+ struct commit *commit = (struct commit *) obj;
+ struct commit_list *parents = commit->parents;
+
+ for (; parents; parents = parents->next)
+ record_if_local_object(&parents->item->object.oid);
+ } else if (obj->type == OBJ_TAG) {
+ struct tag *tag = (struct tag *) obj;
+ record_if_local_object(get_tagged_oid(tag));
+ }
+}
+
static void sha1_object(const void *data, struct object_entry *obj_entry,
unsigned long size, enum object_type type,
const struct object_id *oid)
@@ -845,7 +896,7 @@ static void sha1_object(const void *data, struct object_entry *obj_entry,
free(has_data);
}
- if (strict || do_fsck_object) {
+ if (strict || do_fsck_object || record_local_links) {
read_lock();
if (type == OBJ_BLOB) {
struct blob *blob = lookup_blob(the_repository, oid);
@@ -877,6 +928,8 @@ static void sha1_object(const void *data, struct object_entry *obj_entry,
die(_("fsck error in packed object"));
if (strict && fsck_walk(obj, NULL, &fsck_options))
die(_("Not all child objects of %s are reachable"), oid_to_hex(&obj->oid));
+ if (record_local_links)
+ do_record_local_links(obj);
if (obj->type == OBJ_TREE) {
struct tree *item = (struct tree *) obj;
@@ -1719,6 +1772,58 @@ static void show_pack_info(int stat_only)
free(chain_histogram);
}
+static void repack_local_links(void)
+{
+ struct child_process cmd = CHILD_PROCESS_INIT;
+ FILE *out;
+ struct strbuf line = STRBUF_INIT;
+ struct oidset_iter iter;
+ struct object_id *oid;
+ char *base_name;
+
+ if (!oidset_size(&local_links))
+ return;
+
+ base_name = mkpathdup("%s/pack/pack", repo_get_object_directory(the_repository));
+
+ strvec_push(&cmd.args, "pack-objects");
+ strvec_push(&cmd.args, "--exclude-promisor-objects-best-effort");
+ strvec_push(&cmd.args, base_name);
+ cmd.git_cmd = 1;
+ cmd.in = -1;
+ cmd.out = -1;
+ if (start_command(&cmd))
+ die(_("could not start pack-objects to repack local links"));
+
+ oidset_iter_init(&local_links, &iter);
+ while ((oid = oidset_iter_next(&iter))) {
+ if (write_in_full(cmd.in, oid_to_hex(oid), the_hash_algo->hexsz) < 0 ||
+ write_in_full(cmd.in, "\n", 1) < 0)
+ die(_("failed to feed local object to pack-objects"));
+ }
+ close(cmd.in);
+
+ out = xfdopen(cmd.out, "r");
+ while (strbuf_getline_lf(&line, out) != EOF) {
+ unsigned char binary[GIT_MAX_RAWSZ];
+ if (line.len != the_hash_algo->hexsz ||
+ !hex_to_bytes(binary, line.buf, line.len))
+ die(_("index-pack: Expecting full hex object ID lines only from pack-objects."));
+
+ /*
+ * pack-objects creates the .pack and .idx files, but not the
+ * .promisor file. Create the .promisor file, which is empty.
+ */
+ write_special_file("promisor", "", NULL, binary, NULL);
+ }
+
+ fclose(out);
+ if (finish_command(&cmd))
+ die(_("could not finish pack-objects to repack local links"));
+ strbuf_release(&line);
+ free(base_name);
+}
+
int cmd_index_pack(int argc,
const char **argv,
const char *prefix,
@@ -1794,7 +1899,7 @@ int cmd_index_pack(int argc,
} else if (skip_to_optional_arg(arg, "--keep", &keep_msg)) {
; /* nothing to do */
} else if (skip_to_optional_arg(arg, "--promisor", &promisor_msg)) {
- ; /* already parsed */
+ record_local_links = 1;
} else if (starts_with(arg, "--threads=")) {
char *end;
nr_threads = strtoul(arg+10, &end, 0);
@@ -1970,6 +2075,8 @@ int cmd_index_pack(int argc,
free((void *) curr_index);
free(curr_rev_index);
+ repack_local_links();
+
/*
* Let the caller know this pack is not self contained
*/
diff --git a/builtin/ls-remote.c b/builtin/ls-remote.c
index 423318f87e..42f34e1236 100644
--- a/builtin/ls-remote.c
+++ b/builtin/ls-remote.c
@@ -166,6 +166,7 @@ int cmd_ls_remote(int argc,
status = 0; /* we found something */
}
+ string_list_clear(&server_options, 0);
ref_sorting_release(sorting);
ref_array_clear(&ref_array);
if (transport_disconnect(transport))
diff --git a/builtin/merge.c b/builtin/merge.c
index 84d0f3604b..51038eaca8 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -754,6 +754,7 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,
clean = merge_recursive(&o, head, remoteheads->item,
reversed, &result);
free_commit_list(reversed);
+ strbuf_release(&o.obuf);
if (clean < 0) {
rollback_lock_file(&lock);
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 0800714267..762949e4c8 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -239,6 +239,7 @@ static enum {
static uint16_t write_bitmap_options = BITMAP_OPT_HASH_CACHE;
static int exclude_promisor_objects;
+static int exclude_promisor_objects_best_effort;
static int use_delta_islands;
@@ -4312,6 +4313,18 @@ static int option_parse_cruft_expiration(const struct option *opt UNUSED,
return 0;
}
+static int is_not_in_promisor_pack_obj(struct object *obj, void *data UNUSED)
+{
+ struct object_info info = OBJECT_INFO_INIT;
+ if (oid_object_info_extended(the_repository, &obj->oid, &info, 0))
+ BUG("should_include_obj should only be called on existing objects");
+ return info.whence != OI_PACKED || !info.u.packed.pack->pack_promisor;
+}
+
+static int is_not_in_promisor_pack(struct commit *commit, void *data) {
+ return is_not_in_promisor_pack_obj((struct object *) commit, data);
+}
+
int cmd_pack_objects(int argc,
const char **argv,
const char *prefix,
@@ -4424,6 +4437,9 @@ int cmd_pack_objects(int argc,
option_parse_missing_action),
OPT_BOOL(0, "exclude-promisor-objects", &exclude_promisor_objects,
N_("do not pack objects in promisor packfiles")),
+ OPT_BOOL(0, "exclude-promisor-objects-best-effort",
+ &exclude_promisor_objects_best_effort,
+ N_("implies --missing=allow-any")),
OPT_BOOL(0, "delta-islands", &use_delta_islands,
N_("respect islands during delta compression")),
OPT_STRING_LIST(0, "uri-protocol", &uri_protocols,
@@ -4504,10 +4520,18 @@ int cmd_pack_objects(int argc,
strvec_push(&rp, "--unpacked");
}
+ if (exclude_promisor_objects && exclude_promisor_objects_best_effort)
+ die(_("options '%s' and '%s' cannot be used together"),
+ "--exclude-promisor-objects", "--exclude-promisor-objects-best-effort");
if (exclude_promisor_objects) {
use_internal_rev_list = 1;
fetch_if_missing = 0;
strvec_push(&rp, "--exclude-promisor-objects");
+ } else if (exclude_promisor_objects_best_effort) {
+ use_internal_rev_list = 1;
+ fetch_if_missing = 0;
+ option_parse_missing_action(NULL, "allow-any", 0);
+ /* revs configured below */
}
if (unpack_unreachable || keep_unreachable || pack_loose_unreachable)
use_internal_rev_list = 1;
@@ -4627,6 +4651,10 @@ int cmd_pack_objects(int argc,
repo_init_revisions(the_repository, &revs, NULL);
list_objects_filter_copy(&revs.filter, &filter_options);
+ if (exclude_promisor_objects_best_effort) {
+ revs.include_check = is_not_in_promisor_pack;
+ revs.include_check_obj = is_not_in_promisor_pack_obj;
+ }
get_object_list(&revs, rp.nr, rp.v);
release_revisions(&revs);
}
diff --git a/builtin/pull.c b/builtin/pull.c
index 388ef3d130..edc56907aa 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -218,8 +218,8 @@ static struct option pull_options[] = {
OPT_PASSTHRU_ARGV(0, "shallow-since", &opt_fetch, N_("time"),
N_("deepen history of shallow repository based on time"),
0),
- OPT_PASSTHRU_ARGV(0, "shallow-exclude", &opt_fetch, N_("revision"),
- N_("deepen history of shallow clone, excluding rev"),
+ OPT_PASSTHRU_ARGV(0, "shallow-exclude", &opt_fetch, N_("ref"),
+ N_("deepen history of shallow clone, excluding ref"),
0),
OPT_PASSTHRU_ARGV(0, "deepen", &opt_fetch, N_("n"),
N_("deepen history of shallow clone"),
diff --git a/builtin/tag.c b/builtin/tag.c
index 93d10d5915..c37c0a68fd 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -164,7 +164,7 @@ static int do_sign(struct strbuf *buffer, struct object_id **compat_oid,
int ret = -1;
if (sign_buffer(buffer, &sig, keyid))
- return -1;
+ goto out;
if (compat) {
const struct git_hash_algo *algo = the_repository->hash_algo;
diff --git a/combine-diff.c b/combine-diff.c
index f6b624dc28..33d0ed7097 100644
--- a/combine-diff.c
+++ b/combine-diff.c
@@ -1185,7 +1185,8 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
result_file.ptr = result;
result_file.size = result_size;
- /* Even p_lno[cnt+1] is valid -- that is for the end line number
+ /*
+ * Even p_lno[cnt+1] is valid -- that is for the end line number
* for deletion hunk at the end.
*/
CALLOC_ARRAY(sline[0].p_lno, st_mult(st_add(cnt, 2), num_parent));
@@ -1220,7 +1221,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
}
free(result);
- for (lno = 0; lno < cnt; lno++) {
+ for (lno = 0; lno < cnt + 2; lno++) {
if (sline[lno].lost) {
struct lline *ll = sline[lno].lost;
while (ll) {
diff --git a/compat/mingw.c b/compat/mingw.c
index 0ff550cef3..63f36c893b 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -502,7 +502,7 @@ static int mingw_open_append(wchar_t const *wfilename, int oflags, ...)
* to append to the file.
*/
handle = CreateFileW(wfilename, FILE_APPEND_DATA,
- FILE_SHARE_WRITE | FILE_SHARE_READ,
+ FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
NULL, create, FILE_ATTRIBUTE_NORMAL, NULL);
if (handle == INVALID_HANDLE_VALUE) {
DWORD err = GetLastError();
@@ -533,6 +533,70 @@ static int mingw_open_append(wchar_t const *wfilename, int oflags, ...)
}
/*
+ * Ideally, we'd use `_wopen()` to implement this functionality so that we
+ * don't have to reimplement it, but unfortunately we do not have tight control
+ * over the share mode there. And while `_wsopen()` and friends exist that give
+ * us _some_ control over the share mode, this family of functions doesn't give
+ * us the ability to enable FILE_SHARE_DELETE, either. But this is a strict
+ * requirement for us though so that we can unlink or rename over files that
+ * are held open by another process.
+ *
+ * We are thus forced to implement our own emulation of `open()`. To make our
+ * life simpler we only implement basic support for this, namely opening
+ * existing files for reading and/or writing. This means that newly created
+ * files won't have their sharing mode set up correctly, but for now I couldn't
+ * find any case where this matters. We may have to revisit that in the future
+ * though based on our needs.
+ */
+static int mingw_open_existing(const wchar_t *filename, int oflags, ...)
+{
+ SECURITY_ATTRIBUTES security_attributes = {
+ .nLength = sizeof(security_attributes),
+ .bInheritHandle = !(oflags & O_NOINHERIT),
+ };
+ HANDLE handle;
+ DWORD access;
+ int fd;
+
+ /* We only support basic flags. */
+ if (oflags & ~(O_ACCMODE | O_NOINHERIT)) {
+ errno = ENOSYS;
+ return -1;
+ }
+
+ switch (oflags & O_ACCMODE) {
+ case O_RDWR:
+ access = GENERIC_READ | GENERIC_WRITE;
+ break;
+ case O_WRONLY:
+ access = GENERIC_WRITE;
+ break;
+ default:
+ access = GENERIC_READ;
+ break;
+ }
+
+ handle = CreateFileW(filename, access,
+ FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
+ &security_attributes, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (handle == INVALID_HANDLE_VALUE) {
+ DWORD err = GetLastError();
+
+ /* See `mingw_open_append()` for why we have this conversion. */
+ if (err == ERROR_INVALID_PARAMETER)
+ err = ERROR_PATH_NOT_FOUND;
+
+ errno = err_win_to_posix(err);
+ return -1;
+ }
+
+ fd = _open_osfhandle((intptr_t)handle, oflags | O_BINARY);
+ if (fd < 0)
+ CloseHandle(handle);
+ return fd;
+}
+
+/*
* Does the pathname map to the local named pipe filesystem?
* That is, does it have a "//./pipe/" prefix?
*/
@@ -567,6 +631,8 @@ int mingw_open (const char *filename, int oflags, ...)
if ((oflags & O_APPEND) && !is_local_named_pipe_path(filename))
open_fn = mingw_open_append;
+ else if (!(oflags & ~(O_ACCMODE | O_NOINHERIT)))
+ open_fn = mingw_open_existing;
else
open_fn = _wopen;
@@ -1006,7 +1072,7 @@ int mingw_utime (const char *file_name, const struct utimbuf *times)
osfilehandle = CreateFileW(wfilename,
FILE_WRITE_ATTRIBUTES,
- 0 /*FileShare.None*/,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
(attrs != INVALID_FILE_ATTRIBUTES &&
@@ -2155,10 +2221,16 @@ int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)
#undef rename
int mingw_rename(const char *pold, const char *pnew)
{
+ static int supports_file_rename_info_ex = 1;
DWORD attrs, gle;
int tries = 0;
wchar_t wpold[MAX_PATH], wpnew[MAX_PATH];
- if (xutftowcs_path(wpold, pold) < 0 || xutftowcs_path(wpnew, pnew) < 0)
+ int wpnew_len;
+
+ if (xutftowcs_path(wpold, pold) < 0)
+ return -1;
+ wpnew_len = xutftowcs_path(wpnew, pnew);
+ if (wpnew_len < 0)
return -1;
/*
@@ -2169,11 +2241,84 @@ int mingw_rename(const char *pold, const char *pnew)
return 0;
if (errno != EEXIST)
return -1;
+
repeat:
- if (MoveFileExW(wpold, wpnew, MOVEFILE_REPLACE_EXISTING))
- return 0;
+ if (supports_file_rename_info_ex) {
+ /*
+ * Our minimum required Windows version is still set to Windows
+ * Vista. We thus have to declare required infrastructure for
+ * FileRenameInfoEx ourselves until we bump _WIN32_WINNT to
+ * 0x0A00. Furthermore, we have to handle cases where the
+ * FileRenameInfoEx call isn't supported yet.
+ */
+#define FILE_RENAME_FLAG_REPLACE_IF_EXISTS 0x00000001
+#define FILE_RENAME_FLAG_POSIX_SEMANTICS 0x00000002
+ FILE_INFO_BY_HANDLE_CLASS FileRenameInfoEx = 22;
+ struct {
+ /*
+ * This is usually an unnamed union, but that is not
+ * part of ISO C99. We thus inline the field, as we
+ * really only care for the Flags field anyway.
+ */
+ DWORD Flags;
+ HANDLE RootDirectory;
+ DWORD FileNameLength;
+ /*
+ * The actual structure is defined with a single-character
+ * flex array so that the structure has to be allocated on
+ * the heap. As we declare this structure ourselves though
+ * we can avoid the allocation and define FileName to have
+ * MAX_PATH bytes.
+ */
+ WCHAR FileName[MAX_PATH];
+ } rename_info = { 0 };
+ HANDLE old_handle = INVALID_HANDLE_VALUE;
+ BOOL success;
+
+ old_handle = CreateFileW(wpold, DELETE,
+ FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
+ NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (old_handle == INVALID_HANDLE_VALUE) {
+ errno = err_win_to_posix(GetLastError());
+ return -1;
+ }
+
+ rename_info.Flags = FILE_RENAME_FLAG_REPLACE_IF_EXISTS |
+ FILE_RENAME_FLAG_POSIX_SEMANTICS;
+ rename_info.FileNameLength = wpnew_len * sizeof(WCHAR);
+ memcpy(rename_info.FileName, wpnew, wpnew_len * sizeof(WCHAR));
+
+ success = SetFileInformationByHandle(old_handle, FileRenameInfoEx,
+ &rename_info, sizeof(rename_info));
+ gle = GetLastError();
+ CloseHandle(old_handle);
+ if (success)
+ return 0;
+
+ /*
+ * When we see ERROR_INVALID_PARAMETER we can assume that the
+ * current system doesn't support FileRenameInfoEx. Keep us
+ * from using it in future calls and retry.
+ */
+ if (gle == ERROR_INVALID_PARAMETER) {
+ supports_file_rename_info_ex = 0;
+ goto repeat;
+ }
+
+ /*
+ * In theory, we shouldn't get ERROR_ACCESS_DENIED because we
+ * always open files with FILE_SHARE_DELETE But in practice we
+ * cannot assume that Git is the only one accessing files, and
+ * other applications may not set FILE_SHARE_DELETE. So we have
+ * to retry.
+ */
+ } else {
+ if (MoveFileExW(wpold, wpnew, MOVEFILE_REPLACE_EXISTING))
+ return 0;
+ gle = GetLastError();
+ }
+
/* TODO: translate more errors */
- gle = GetLastError();
if (gle == ERROR_ACCESS_DENIED &&
(attrs = GetFileAttributesW(wpnew)) != INVALID_FILE_ATTRIBUTES) {
if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
diff --git a/diff-lib.c b/diff-lib.c
index 6b14b95962..3cf353946f 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -661,6 +661,7 @@ int do_diff_cache(const struct object_id *tree_oid, struct diff_options *opt)
repo_init_revisions(opt->repo, &revs, NULL);
copy_pathspec(&revs.prune_data, &opt->pathspec);
+ diff_free(&revs.diffopt);
revs.diffopt = *opt;
revs.diffopt.no_free = 1;
diff --git a/dir.c b/dir.c
index e3ddd5b529..7f35a3e317 100644
--- a/dir.c
+++ b/dir.c
@@ -1056,6 +1056,8 @@ static void do_invalidate_gitignore(struct untracked_cache_dir *dir)
{
int i;
dir->valid = 0;
+ for (size_t i = 0; i < dir->untracked_nr; i++)
+ free(dir->untracked[i]);
dir->untracked_nr = 0;
for (i = 0; i < dir->dirs_nr; i++)
do_invalidate_gitignore(dir->dirs[i]);
@@ -1083,6 +1085,8 @@ static void invalidate_directory(struct untracked_cache *uc,
uc->dir_invalidated++;
dir->valid = 0;
+ for (size_t i = 0; i < dir->untracked_nr; i++)
+ free(dir->untracked[i]);
dir->untracked_nr = 0;
for (i = 0; i < dir->dirs_nr; i++)
dir->dirs[i]->recurse = 0;
@@ -2868,14 +2872,14 @@ static void set_untracked_ident(struct untracked_cache *uc)
static unsigned new_untracked_cache_flags(struct index_state *istate)
{
struct repository *repo = istate->repo;
- char *val;
+ const char *val;
/*
* This logic is coordinated with the setting of these flags in
* wt-status.c#wt_status_collect_untracked(), and the evaluation
* of the config setting in commit.c#git_status_config()
*/
- if (!repo_config_get_string(repo, "status.showuntrackedfiles", &val) &&
+ if (!repo_config_get_string_tmp(repo, "status.showuntrackedfiles", &val) &&
!strcmp(val, "all"))
return 0;
@@ -3573,6 +3577,8 @@ static void write_one_dir(struct untracked_cache_dir *untracked,
* for safety..
*/
if (!untracked->valid) {
+ for (size_t i = 0; i < untracked->untracked_nr; i++)
+ free(untracked->untracked[i]);
untracked->untracked_nr = 0;
untracked->check_only = 0;
}
@@ -3905,6 +3911,8 @@ static void invalidate_one_directory(struct untracked_cache *uc,
{
uc->dir_invalidated++;
ucd->valid = 0;
+ for (size_t i = 0; i < ucd->untracked_nr; i++)
+ free(ucd->untracked[i]);
ucd->untracked_nr = 0;
}
diff --git a/fetch-pack.c b/fetch-pack.c
index f752da93a8..fe1fb3c1b7 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -122,29 +122,41 @@ static void for_each_cached_alternate(struct fetch_negotiator *negotiator,
cb(negotiator, cache.items[i]);
}
-static struct commit *deref_without_lazy_fetch_extended(const struct object_id *oid,
- int mark_tags_complete,
- enum object_type *type,
- unsigned int oi_flags)
+static void die_in_commit_graph_only(const struct object_id *oid)
{
- struct object_info info = { .typep = type };
+ die(_("You are attempting to fetch %s, which is in the commit graph file but not in the object database.\n"
+ "This is probably due to repo corruption.\n"
+ "If you are attempting to repair this repo corruption by refetching the missing object, use 'git fetch --refetch' with the missing object."),
+ oid_to_hex(oid));
+}
+
+static struct commit *deref_without_lazy_fetch(const struct object_id *oid,
+ int mark_tags_complete_and_check_obj_db)
+{
+ enum object_type type;
+ struct object_info info = { .typep = &type };
struct commit *commit;
commit = lookup_commit_in_graph(the_repository, oid);
- if (commit)
+ if (commit) {
+ if (mark_tags_complete_and_check_obj_db) {
+ if (!has_object(the_repository, oid, 0))
+ die_in_commit_graph_only(oid);
+ }
return commit;
+ }
while (1) {
if (oid_object_info_extended(the_repository, oid, &info,
- oi_flags))
+ OBJECT_INFO_SKIP_FETCH_OBJECT | OBJECT_INFO_QUICK))
return NULL;
- if (*type == OBJ_TAG) {
+ if (type == OBJ_TAG) {
struct tag *tag = (struct tag *)
parse_object(the_repository, oid);
if (!tag->tagged)
return NULL;
- if (mark_tags_complete)
+ if (mark_tags_complete_and_check_obj_db)
tag->object.flags |= COMPLETE;
oid = &tag->tagged->oid;
} else {
@@ -152,7 +164,7 @@ static struct commit *deref_without_lazy_fetch_extended(const struct object_id *
}
}
- if (*type == OBJ_COMMIT) {
+ if (type == OBJ_COMMIT) {
struct commit *commit = lookup_commit(the_repository, oid);
if (!commit || repo_parse_commit(the_repository, commit))
return NULL;
@@ -162,16 +174,6 @@ static struct commit *deref_without_lazy_fetch_extended(const struct object_id *
return NULL;
}
-
-static struct commit *deref_without_lazy_fetch(const struct object_id *oid,
- int mark_tags_complete)
-{
- enum object_type type;
- unsigned flags = OBJECT_INFO_SKIP_FETCH_OBJECT | OBJECT_INFO_QUICK;
- return deref_without_lazy_fetch_extended(oid, mark_tags_complete,
- &type, flags);
-}
-
static int rev_list_insert_ref(struct fetch_negotiator *negotiator,
const struct object_id *oid)
{
diff --git a/grep.c b/grep.c
index 506f0423c8..e95cded414 100644
--- a/grep.c
+++ b/grep.c
@@ -756,6 +756,7 @@ static struct grep_expr *grep_splice_or(struct grep_expr *x, struct grep_expr *y
assert(x->node == GREP_NODE_OR);
if (x->u.binary.right &&
x->u.binary.right->node == GREP_NODE_TRUE) {
+ free(x->u.binary.right);
x->u.binary.right = y;
break;
}
diff --git a/list-objects-filter-options.c b/list-objects-filter-options.c
index 00611107d2..fa72e81e4a 100644
--- a/list-objects-filter-options.c
+++ b/list-objects-filter-options.c
@@ -252,16 +252,14 @@ void parse_list_objects_filter(
const char *arg)
{
struct strbuf errbuf = STRBUF_INIT;
- int parse_error;
if (!filter_options->filter_spec.buf)
BUG("filter_options not properly initialized");
if (!filter_options->choice) {
+ if (gently_parse_list_objects_filter(filter_options, arg, &errbuf))
+ die("%s", errbuf.buf);
strbuf_addstr(&filter_options->filter_spec, arg);
-
- parse_error = gently_parse_list_objects_filter(
- filter_options, arg, &errbuf);
} else {
struct list_objects_filter_options *sub;
@@ -271,18 +269,17 @@ void parse_list_objects_filter(
*/
transform_to_combine_type(filter_options);
- strbuf_addch(&filter_options->filter_spec, '+');
- filter_spec_append_urlencode(filter_options, arg);
ALLOC_GROW_BY(filter_options->sub, filter_options->sub_nr, 1,
filter_options->sub_alloc);
sub = &filter_options->sub[filter_options->sub_nr - 1];
list_objects_filter_init(sub);
- parse_error = gently_parse_list_objects_filter(sub, arg,
- &errbuf);
+ if (gently_parse_list_objects_filter(sub, arg, &errbuf))
+ die("%s", errbuf.buf);
+
+ strbuf_addch(&filter_options->filter_spec, '+');
+ filter_spec_append_urlencode(filter_options, arg);
}
- if (parse_error)
- die("%s", errbuf.buf);
}
int opt_parse_list_objects_filter(const struct option *opt,
diff --git a/pretty.c b/pretty.c
index 6403e26890..098378720a 100644
--- a/pretty.c
+++ b/pretty.c
@@ -2032,6 +2032,7 @@ void repo_format_commit_message(struct repository *r,
free(context.commit_encoding);
repo_unuse_commit_buffer(r, commit, context.message);
+ signature_check_clear(&context.signature_check);
}
static void pp_header(struct pretty_print_context *pp,
diff --git a/revision.c b/revision.c
index f5f5b84f2b..8df75b8224 100644
--- a/revision.c
+++ b/revision.c
@@ -3227,6 +3227,11 @@ void release_revisions(struct rev_info *revs)
clear_decoration(&revs->treesame, free);
line_log_free(revs);
oidset_clear(&revs->missing_commits);
+
+ for (int i = 0; i < revs->bloom_keys_nr; i++)
+ clear_bloom_key(&revs->bloom_keys[i]);
+ FREE_AND_NULL(revs->bloom_keys);
+ revs->bloom_keys_nr = 0;
}
static void add_child(struct rev_info *revs, struct commit *parent, struct commit *child)
diff --git a/sparse-index.c b/sparse-index.c
index 3d7f2164e2..2107840bfc 100644
--- a/sparse-index.c
+++ b/sparse-index.c
@@ -2,6 +2,7 @@
#include "git-compat-util.h"
#include "environment.h"
+#include "ewah/ewok.h"
#include "gettext.h"
#include "name-hash.h"
#include "read-cache-ll.h"
@@ -242,7 +243,8 @@ int convert_to_sparse(struct index_state *istate, int flags)
cache_tree_update(istate, 0);
istate->fsmonitor_has_run_once = 0;
- FREE_AND_NULL(istate->fsmonitor_dirty);
+ ewah_free(istate->fsmonitor_dirty);
+ istate->fsmonitor_dirty = NULL;
FREE_AND_NULL(istate->fsmonitor_last_update);
istate->sparse_index = INDEX_COLLAPSED;
@@ -438,7 +440,8 @@ void expand_index(struct index_state *istate, struct pattern_list *pl)
istate->cache_nr = full->cache_nr;
istate->cache_alloc = full->cache_alloc;
istate->fsmonitor_has_run_once = 0;
- FREE_AND_NULL(istate->fsmonitor_dirty);
+ ewah_free(istate->fsmonitor_dirty);
+ istate->fsmonitor_dirty = NULL;
FREE_AND_NULL(istate->fsmonitor_last_update);
strbuf_release(&base);
diff --git a/t/helper/test-dump-untracked-cache.c b/t/helper/test-dump-untracked-cache.c
index 4f010d5324..b2e70837a9 100644
--- a/t/helper/test-dump-untracked-cache.c
+++ b/t/helper/test-dump-untracked-cache.c
@@ -68,5 +68,7 @@ int cmd__dump_untracked_cache(int ac UNUSED, const char **av UNUSED)
printf("flags %08x\n", uc->dir_flags);
if (uc->root)
dump(uc->root, &base);
+
+ strbuf_release(&base);
return 0;
}
diff --git a/t/helper/test-reach.c b/t/helper/test-reach.c
index 995e382863..84deee604a 100644
--- a/t/helper/test-reach.c
+++ b/t/helper/test-reach.c
@@ -127,10 +127,12 @@ int cmd__reach(int ac, const char **av)
exit(128);
printf("%s(A,X):\n", av[1]);
print_sorted_commit_ids(list);
+ free_commit_list(list);
} else if (!strcmp(av[1], "reduce_heads")) {
struct commit_list *list = reduce_heads(X);
printf("%s(X):\n", av[1]);
print_sorted_commit_ids(list);
+ free_commit_list(list);
} else if (!strcmp(av[1], "can_all_from_reach")) {
printf("%s(X,Y):%d\n", av[1], can_all_from_reach(X, Y, 1));
} else if (!strcmp(av[1], "can_all_from_reach_with_flag")) {
@@ -153,6 +155,7 @@ int cmd__reach(int ac, const char **av)
filter.with_commit_tag_algo = 0;
printf("%s(_,A,X,_):%d\n", av[1], commit_contains(&filter, A, X, &cache));
+ clear_contains_cache(&cache);
} else if (!strcmp(av[1], "get_reachable_subset")) {
const int reachable_flag = 1;
int i, count = 0;
@@ -176,7 +179,14 @@ int cmd__reach(int ac, const char **av)
die(_("too many commits marked reachable"));
print_sorted_commit_ids(list);
+ free_commit_list(list);
}
+ object_array_clear(&X_obj);
+ strbuf_release(&buf);
+ free_commit_list(X);
+ free_commit_list(Y);
+ free(X_array);
+ free(Y_array);
return 0;
}
diff --git a/t/helper/test-read-cache.c b/t/helper/test-read-cache.c
index d285c656bd..e277dde8e7 100644
--- a/t/helper/test-read-cache.c
+++ b/t/helper/test-read-cache.c
@@ -11,8 +11,6 @@ int cmd__read_cache(int argc, const char **argv)
int i, cnt = 1;
const char *name = NULL;
- initialize_repository(the_repository);
-
if (argc > 1 && skip_prefix(argv[1], "--print-and-refresh=", &name)) {
argc--;
argv++;
diff --git a/t/t0410-partial-clone.sh b/t/t0410-partial-clone.sh
index 818700fbec..e2b317db65 100755
--- a/t/t0410-partial-clone.sh
+++ b/t/t0410-partial-clone.sh
@@ -241,7 +241,7 @@ test_expect_success 'fetching of missing objects works with ref-in-want enabled'
grep "fetch< fetch=.*ref-in-want" trace
'
-test_expect_success 'fetching of missing objects from another promisor remote' '
+test_expect_success 'fetching from another promisor remote' '
git clone "file://$(pwd)/server" server2 &&
test_commit -C server2 bar &&
git -C server2 repack -a -d --write-bitmap-index &&
@@ -264,8 +264,8 @@ test_expect_success 'fetching of missing objects from another promisor remote' '
grep "$HASH2" out
'
-test_expect_success 'fetching of missing objects configures a promisor remote' '
- git clone "file://$(pwd)/server" server3 &&
+test_expect_success 'fetching with --filter configures a promisor remote' '
+ test_create_repo server3 &&
test_commit -C server3 baz &&
git -C server3 repack -a -d --write-bitmap-index &&
HASH3=$(git -C server3 rev-parse baz) &&
diff --git a/t/t0610-reftable-basics.sh b/t/t0610-reftable-basics.sh
index babec7993e..eaf6fab6d2 100755
--- a/t/t0610-reftable-basics.sh
+++ b/t/t0610-reftable-basics.sh
@@ -450,10 +450,12 @@ test_expect_success 'ref transaction: retry acquiring tables.list lock' '
)
'
-# This test fails most of the time on Windows systems. The root cause is
+# This test fails most of the time on Cygwin systems. The root cause is
# that Windows does not allow us to rename the "tables.list.lock" file into
-# place when "tables.list" is open for reading by a concurrent process.
-test_expect_success !WINDOWS 'ref transaction: many concurrent writers' '
+# place when "tables.list" is open for reading by a concurrent process. We have
+# worked around that in our MinGW-based rename emulation, but the Cygwin
+# emulation seems to be insufficient.
+test_expect_success !CYGWIN 'ref transaction: many concurrent writers' '
test_when_finished "rm -rf repo" &&
git init repo &&
(
diff --git a/t/t1016-compatObjectFormat.sh b/t/t1016-compatObjectFormat.sh
index 8341a2fe83..32e0af392e 100755
--- a/t/t1016-compatObjectFormat.sh
+++ b/t/t1016-compatObjectFormat.sh
@@ -24,84 +24,83 @@ TEST_PASSES_SANITIZE_LEAK=true
# the commit is identical to the commit in the other repository.
compat_hash () {
- case "$1" in
- "sha1")
- echo "sha256"
- ;;
- "sha256")
- echo "sha1"
- ;;
- esac
+ case "$1" in
+ "sha1")
+ echo "sha256"
+ ;;
+ "sha256")
+ echo "sha1"
+ ;;
+ esac
}
hello_oid () {
- case "$1" in
- "sha1")
- echo "$hello_sha1_oid"
- ;;
- "sha256")
- echo "$hello_sha256_oid"
- ;;
- esac
+ case "$1" in
+ "sha1")
+ echo "$hello_sha1_oid"
+ ;;
+ "sha256")
+ echo "$hello_sha256_oid"
+ ;;
+ esac
}
tree_oid () {
- case "$1" in
- "sha1")
- echo "$tree_sha1_oid"
- ;;
- "sha256")
- echo "$tree_sha256_oid"
- ;;
- esac
+ case "$1" in
+ "sha1")
+ echo "$tree_sha1_oid"
+ ;;
+ "sha256")
+ echo "$tree_sha256_oid"
+ ;;
+ esac
}
commit_oid () {
- case "$1" in
- "sha1")
- echo "$commit_sha1_oid"
- ;;
- "sha256")
- echo "$commit_sha256_oid"
- ;;
- esac
+ case "$1" in
+ "sha1")
+ echo "$commit_sha1_oid"
+ ;;
+ "sha256")
+ echo "$commit_sha256_oid"
+ ;;
+ esac
}
commit2_oid () {
- case "$1" in
- "sha1")
- echo "$commit2_sha1_oid"
- ;;
- "sha256")
- echo "$commit2_sha256_oid"
- ;;
- esac
+ case "$1" in
+ "sha1")
+ echo "$commit2_sha1_oid"
+ ;;
+ "sha256")
+ echo "$commit2_sha256_oid"
+ ;;
+ esac
}
del_sigcommit () {
- local delete="$1"
-
- if test "$delete" = "sha256" ; then
- local pattern="gpgsig-sha256"
- else
- local pattern="gpgsig"
- fi
- test-tool delete-gpgsig "$pattern"
+ local delete="$1"
+
+ if test "$delete" = "sha256" ; then
+ local pattern="gpgsig-sha256"
+ else
+ local pattern="gpgsig"
+ fi
+ test-tool delete-gpgsig "$pattern"
}
-
del_sigtag () {
- local storage="$1"
- local delete="$2"
-
- if test "$storage" = "$delete" ; then
- local pattern="trailer"
- elif test "$storage" = "sha256" ; then
- local pattern="gpgsig"
- else
- local pattern="gpgsig-sha256"
- fi
- test-tool delete-gpgsig "$pattern"
+ local storage="$1"
+ local delete="$2"
+
+ if test "$storage" = "$delete" ; then
+ local pattern="trailer"
+ elif test "$storage" = "sha256" ; then
+ local pattern="gpgsig"
+ else
+ local pattern="gpgsig-sha256"
+ fi
+ test-tool delete-gpgsig "$pattern"
}
base=$(pwd)
@@ -146,9 +145,9 @@ do
'
test_expect_success "create a $hash branch" '
git checkout -b branch $(commit_oid $hash) &&
- echo "More more more give me more!" > more &&
+ echo "More more more give me more!" >more &&
eval more_${hash}_oid=$(git hash-object more) &&
- echo "Another and another and another" > another &&
+ echo "Another and another and another" >another &&
eval another_${hash}_oid=$(git hash-object another) &&
git update-index --add more another &&
git commit -m "Add more files!" &&
@@ -165,15 +164,15 @@ do
'
test_expect_success GPG2 "create additional $hash signed commits" '
git commit --gpg-sign --allow-empty -m "This is an additional signed commit" &&
- git cat-file commit HEAD | del_sigcommit sha256 > "../${hash}_signedcommit3" &&
- git cat-file commit HEAD | del_sigcommit sha1 > "../${hash}_signedcommit4" &&
+ git cat-file commit HEAD | del_sigcommit sha256 >"../${hash}_signedcommit3" &&
+ git cat-file commit HEAD | del_sigcommit sha1 >"../${hash}_signedcommit4" &&
eval signedcommit3_${hash}_oid=$(git hash-object -t commit -w ../${hash}_signedcommit3) &&
eval signedcommit4_${hash}_oid=$(git hash-object -t commit -w ../${hash}_signedcommit4)
'
test_expect_success GPG2 "create additional $hash signed tags" '
git tag -s -m "This is an additional signed tag" signedtag34 HEAD &&
- git cat-file tag signedtag34 | del_sigtag "${hash}" sha256 > ../${hash}_signedtag3 &&
- git cat-file tag signedtag34 | del_sigtag "${hash}" sha1 > ../${hash}_signedtag4 &&
+ git cat-file tag signedtag34 | del_sigtag "${hash}" sha256 >../${hash}_signedtag3 &&
+ git cat-file tag signedtag34 | del_sigtag "${hash}" sha1 >../${hash}_signedtag4 &&
eval signedtag3_${hash}_oid=$(git hash-object -t tag -w ../${hash}_signedtag3) &&
eval signedtag4_${hash}_oid=$(git hash-object -t tag -w ../${hash}_signedtag4)
'
@@ -181,81 +180,80 @@ done
cd "$base"
compare_oids () {
- test "$#" = 5 && { local PREREQ="$1"; shift; } || PREREQ=
- local type="$1"
- local name="$2"
- local sha1_oid="$3"
- local sha256_oid="$4"
-
- echo ${sha1_oid} > ${name}_sha1_expected
- echo ${sha256_oid} > ${name}_sha256_expected
- echo ${type} > ${name}_type_expected
-
- git --git-dir=repo-sha1/.git rev-parse --output-object-format=sha256 ${sha1_oid} > ${name}_sha1_sha256_found
- git --git-dir=repo-sha256/.git rev-parse --output-object-format=sha1 ${sha256_oid} > ${name}_sha256_sha1_found
- local sha1_sha256_oid="$(cat ${name}_sha1_sha256_found)"
- local sha256_sha1_oid="$(cat ${name}_sha256_sha1_found)"
-
- test_expect_success $PREREQ "Verify ${type} ${name}'s sha1 oid" '
- git --git-dir=repo-sha256/.git rev-parse --output-object-format=sha1 ${sha256_oid} > ${name}_sha1 &&
- test_cmp ${name}_sha1 ${name}_sha1_expected
-'
-
- test_expect_success $PREREQ "Verify ${type} ${name}'s sha256 oid" '
- git --git-dir=repo-sha1/.git rev-parse --output-object-format=sha256 ${sha1_oid} > ${name}_sha256 &&
- test_cmp ${name}_sha256 ${name}_sha256_expected
-'
+ test "$#" = 5 && { local PREREQ="$1"; shift; } || PREREQ=
+ local type="$1"
+ local name="$2"
+ local sha1_oid="$3"
+ local sha256_oid="$4"
+
+ echo ${sha1_oid} >${name}_sha1_expected
+ echo ${sha256_oid} >${name}_sha256_expected
+ echo ${type} >${name}_type_expected
+
+ git --git-dir=repo-sha1/.git rev-parse --output-object-format=sha256 ${sha1_oid} >${name}_sha1_sha256_found
+ git --git-dir=repo-sha256/.git rev-parse --output-object-format=sha1 ${sha256_oid} >${name}_sha256_sha1_found
+ local sha1_sha256_oid="$(cat ${name}_sha1_sha256_found)"
+ local sha256_sha1_oid="$(cat ${name}_sha256_sha1_found)"
+
+ test_expect_success $PREREQ "Verify ${type} ${name}'s sha1 oid" '
+ git --git-dir=repo-sha256/.git rev-parse --output-object-format=sha1 ${sha256_oid} >${name}_sha1 &&
+ test_cmp ${name}_sha1 ${name}_sha1_expected
+ '
- test_expect_success $PREREQ "Verify ${name}'s sha1 type" '
- git --git-dir=repo-sha1/.git cat-file -t ${sha1_oid} > ${name}_type1 &&
- git --git-dir=repo-sha256/.git cat-file -t ${sha256_sha1_oid} > ${name}_type2 &&
- test_cmp ${name}_type1 ${name}_type2 &&
- test_cmp ${name}_type1 ${name}_type_expected
-'
+ test_expect_success $PREREQ "Verify ${type} ${name}'s sha256 oid" '
+ git --git-dir=repo-sha1/.git rev-parse --output-object-format=sha256 ${sha1_oid} >${name}_sha256 &&
+ test_cmp ${name}_sha256 ${name}_sha256_expected
+ '
- test_expect_success $PREREQ "Verify ${name}'s sha256 type" '
- git --git-dir=repo-sha256/.git cat-file -t ${sha256_oid} > ${name}_type3 &&
- git --git-dir=repo-sha1/.git cat-file -t ${sha1_sha256_oid} > ${name}_type4 &&
- test_cmp ${name}_type3 ${name}_type4 &&
- test_cmp ${name}_type3 ${name}_type_expected
-'
+ test_expect_success $PREREQ "Verify ${name}'s sha1 type" '
+ git --git-dir=repo-sha1/.git cat-file -t ${sha1_oid} >${name}_type1 &&
+ git --git-dir=repo-sha256/.git cat-file -t ${sha256_sha1_oid} >${name}_type2 &&
+ test_cmp ${name}_type1 ${name}_type2 &&
+ test_cmp ${name}_type1 ${name}_type_expected
+ '
- test_expect_success $PREREQ "Verify ${name}'s sha1 size" '
- git --git-dir=repo-sha1/.git cat-file -s ${sha1_oid} > ${name}_size1 &&
- git --git-dir=repo-sha256/.git cat-file -s ${sha256_sha1_oid} > ${name}_size2 &&
- test_cmp ${name}_size1 ${name}_size2
-'
+ test_expect_success $PREREQ "Verify ${name}'s sha256 type" '
+ git --git-dir=repo-sha256/.git cat-file -t ${sha256_oid} >${name}_type3 &&
+ git --git-dir=repo-sha1/.git cat-file -t ${sha1_sha256_oid} >${name}_type4 &&
+ test_cmp ${name}_type3 ${name}_type4 &&
+ test_cmp ${name}_type3 ${name}_type_expected
+ '
- test_expect_success $PREREQ "Verify ${name}'s sha256 size" '
- git --git-dir=repo-sha256/.git cat-file -s ${sha256_oid} > ${name}_size3 &&
- git --git-dir=repo-sha1/.git cat-file -s ${sha1_sha256_oid} > ${name}_size4 &&
- test_cmp ${name}_size3 ${name}_size4
-'
+ test_expect_success $PREREQ "Verify ${name}'s sha1 size" '
+ git --git-dir=repo-sha1/.git cat-file -s ${sha1_oid} >${name}_size1 &&
+ git --git-dir=repo-sha256/.git cat-file -s ${sha256_sha1_oid} >${name}_size2 &&
+ test_cmp ${name}_size1 ${name}_size2
+ '
- test_expect_success $PREREQ "Verify ${name}'s sha1 pretty content" '
- git --git-dir=repo-sha1/.git cat-file -p ${sha1_oid} > ${name}_content1 &&
- git --git-dir=repo-sha256/.git cat-file -p ${sha256_sha1_oid} > ${name}_content2 &&
- test_cmp ${name}_content1 ${name}_content2
-'
+ test_expect_success $PREREQ "Verify ${name}'s sha256 size" '
+ git --git-dir=repo-sha256/.git cat-file -s ${sha256_oid} >${name}_size3 &&
+ git --git-dir=repo-sha1/.git cat-file -s ${sha1_sha256_oid} >${name}_size4 &&
+ test_cmp ${name}_size3 ${name}_size4
+ '
- test_expect_success $PREREQ "Verify ${name}'s sha256 pretty content" '
- git --git-dir=repo-sha256/.git cat-file -p ${sha256_oid} > ${name}_content3 &&
- git --git-dir=repo-sha1/.git cat-file -p ${sha1_sha256_oid} > ${name}_content4 &&
- test_cmp ${name}_content3 ${name}_content4
-'
+ test_expect_success $PREREQ "Verify ${name}'s sha1 pretty content" '
+ git --git-dir=repo-sha1/.git cat-file -p ${sha1_oid} >${name}_content1 &&
+ git --git-dir=repo-sha256/.git cat-file -p ${sha256_sha1_oid} >${name}_content2 &&
+ test_cmp ${name}_content1 ${name}_content2
+ '
- test_expect_success $PREREQ "Verify ${name}'s sha1 content" '
- git --git-dir=repo-sha1/.git cat-file ${type} ${sha1_oid} > ${name}_content5 &&
- git --git-dir=repo-sha256/.git cat-file ${type} ${sha256_sha1_oid} > ${name}_content6 &&
- test_cmp ${name}_content5 ${name}_content6
-'
+ test_expect_success $PREREQ "Verify ${name}'s sha256 pretty content" '
+ git --git-dir=repo-sha256/.git cat-file -p ${sha256_oid} >${name}_content3 &&
+ git --git-dir=repo-sha1/.git cat-file -p ${sha1_sha256_oid} >${name}_content4 &&
+ test_cmp ${name}_content3 ${name}_content4
+ '
- test_expect_success $PREREQ "Verify ${name}'s sha256 content" '
- git --git-dir=repo-sha256/.git cat-file ${type} ${sha256_oid} > ${name}_content7 &&
- git --git-dir=repo-sha1/.git cat-file ${type} ${sha1_sha256_oid} > ${name}_content8 &&
- test_cmp ${name}_content7 ${name}_content8
-'
+ test_expect_success $PREREQ "Verify ${name}'s sha1 content" '
+ git --git-dir=repo-sha1/.git cat-file ${type} ${sha1_oid} >${name}_content5 &&
+ git --git-dir=repo-sha256/.git cat-file ${type} ${sha256_sha1_oid} >${name}_content6 &&
+ test_cmp ${name}_content5 ${name}_content6
+ '
+ test_expect_success $PREREQ "Verify ${name}'s sha256 content" '
+ git --git-dir=repo-sha256/.git cat-file ${type} ${sha256_oid} >${name}_content7 &&
+ git --git-dir=repo-sha1/.git cat-file ${type} ${sha1_sha256_oid} >${name}_content8 &&
+ test_cmp ${name}_content7 ${name}_content8
+ '
}
compare_oids 'blob' hello "$hello_sha1_oid" "$hello_sha256_oid"
diff --git a/t/t4038-diff-combined.sh b/t/t4038-diff-combined.sh
index 2ce26e585c..00190802d8 100755
--- a/t/t4038-diff-combined.sh
+++ b/t/t4038-diff-combined.sh
@@ -5,6 +5,7 @@ test_description='combined diff'
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-diff.sh
diff --git a/t/t4202-log.sh b/t/t4202-log.sh
index 51f7beb59f..35bec4089a 100755
--- a/t/t4202-log.sh
+++ b/t/t4202-log.sh
@@ -5,6 +5,7 @@ test_description='git log'
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"
. "$TEST_DIRECTORY/lib-terminal.sh"
diff --git a/t/t4216-log-bloom.sh b/t/t4216-log-bloom.sh
index 3f163dc396..8d22338f6a 100755
--- a/t/t4216-log-bloom.sh
+++ b/t/t4216-log-bloom.sh
@@ -4,6 +4,7 @@ test_description='git log for a path with Bloom filters'
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-chunk.sh
diff --git a/t/t5300-pack-object.sh b/t/t5300-pack-object.sh
index 3b9dae331a..aff164ddf8 100755
--- a/t/t5300-pack-object.sh
+++ b/t/t5300-pack-object.sh
@@ -156,6 +156,11 @@ test_expect_success 'pack without delta' '
check_deltas stderr = 0
'
+test_expect_success 'negative window clamps to 0' '
+ git pack-objects --progress --window=-1 neg-window <obj-list 2>stderr &&
+ check_deltas stderr = 0
+'
+
test_expect_success 'pack-objects with bogus arguments' '
test_must_fail git pack-objects --window=0 test-1 blah blah <obj-list
'
@@ -630,11 +635,6 @@ test_expect_success 'prefetch objects' '
test_line_count = 1 donelines
'
-test_expect_success 'negative window clamps to 0' '
- git pack-objects --progress --window=-1 neg-window <obj-list 2>stderr &&
- check_deltas stderr = 0
-'
-
for hash in sha1 sha256
do
test_expect_success "verify-pack with $hash packfile" '
diff --git a/t/t5330-no-lazy-fetch-with-commit-graph.sh b/t/t5330-no-lazy-fetch-with-commit-graph.sh
index 5eb28f0512..21f36eb8c3 100755
--- a/t/t5330-no-lazy-fetch-with-commit-graph.sh
+++ b/t/t5330-no-lazy-fetch-with-commit-graph.sh
@@ -38,9 +38,9 @@ test_expect_success 'fetch any commit from promisor with the usage of the commit
git -C with-commit-graph config remote.origin.partialclonefilter blob:none &&
test_commit -C with-commit any-commit &&
anycommit=$(git -C with-commit rev-parse HEAD) &&
- GIT_TRACE="$(pwd)/trace.txt" \
+ test_must_fail env GIT_TRACE="$(pwd)/trace.txt" \
git -C with-commit-graph fetch origin $anycommit 2>err &&
- ! grep "fatal: promisor-remote: unable to fork off fetch subprocess" err &&
+ test_grep ! "fatal: promisor-remote: unable to fork off fetch subprocess" err &&
grep "git fetch origin" trace.txt >actual &&
test_line_count = 1 actual
'
diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh
index 8da8e7fe42..6552da78d1 100755
--- a/t/t5500-fetch-pack.sh
+++ b/t/t5500-fetch-pack.sh
@@ -926,6 +926,13 @@ test_expect_success 'fetch exclude tag one' '
test_cmp expected actual
'
+test_expect_success 'fetch exclude tag one as revision' '
+ test_when_finished rm -f rev err &&
+ git -C shallow-exclude rev-parse one >rev &&
+ test_must_fail git -C shallow12 fetch --shallow-exclude $(cat rev) origin 2>err &&
+ grep "deepen-not is not a ref:" err
+'
+
test_expect_success 'fetching deepen' '
test_create_repo shallow-deepen &&
(
diff --git a/t/t5616-partial-clone.sh b/t/t5616-partial-clone.sh
index c53e93be2f..91d1808883 100755
--- a/t/t5616-partial-clone.sh
+++ b/t/t5616-partial-clone.sh
@@ -694,6 +694,36 @@ test_expect_success 'lazy-fetch in submodule succeeds' '
git -C client restore --recurse-submodules --source=HEAD^ :/
'
+test_expect_success 'after fetching descendants of non-promisor commits, gc works' '
+ # Setup
+ git init full &&
+ git -C full config uploadpack.allowfilter 1 &&
+ git -C full config uploadpack.allowanysha1inwant 1 &&
+ touch full/foo &&
+ git -C full add foo &&
+ git -C full commit -m "commit 1" &&
+ git -C full checkout --detach &&
+
+ # Partial clone and push commit to remote
+ git clone "file://$(pwd)/full" --filter=blob:none partial &&
+ echo "hello" > partial/foo &&
+ git -C partial commit -a -m "commit 2" &&
+ git -C partial push &&
+
+ # gc in partial repo
+ git -C partial gc --prune=now &&
+
+ # Create another commit in normal repo
+ git -C full checkout main &&
+ echo " world" >> full/foo &&
+ git -C full commit -a -m "commit 3" &&
+
+ # Pull from remote in partial repo, and run gc again
+ git -C partial pull &&
+ git -C partial gc --prune=now
+'
+
+
. "$TEST_DIRECTORY"/lib-httpd.sh
start_httpd
diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh
index d3df81e785..e4ce059236 100755
--- a/t/t5702-protocol-v2.sh
+++ b/t/t5702-protocol-v2.sh
@@ -7,6 +7,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 protocol v2 with 'git://' transport
diff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh
index d21877150e..d4882288a3 100755
--- a/t/t5801-remote-helpers.sh
+++ b/t/t5801-remote-helpers.sh
@@ -8,6 +8,7 @@ test_description='Test remote-helper import and export commands'
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/t6112-rev-list-filters-objects.sh b/t/t6112-rev-list-filters-objects.sh
index 0387f35a32..71e38491fa 100755
--- a/t/t6112-rev-list-filters-objects.sh
+++ b/t/t6112-rev-list-filters-objects.sh
@@ -5,6 +5,7 @@ test_description='git rev-list 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 the blob:none filter.
diff --git a/t/t6424-merge-unrelated-index-changes.sh b/t/t6424-merge-unrelated-index-changes.sh
index 7677c5f08d..a7ea8acb84 100755
--- a/t/t6424-merge-unrelated-index-changes.sh
+++ b/t/t6424-merge-unrelated-index-changes.sh
@@ -2,6 +2,7 @@
test_description="merges with unrelated index changes"
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Testcase for some simple merges
diff --git a/t/t6600-test-reach.sh b/t/t6600-test-reach.sh
index 2591f8b8b3..307deefed2 100755
--- a/t/t6600-test-reach.sh
+++ b/t/t6600-test-reach.sh
@@ -2,6 +2,7 @@
test_description='basic commit reachability tests'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Construct a grid-like commit graph with points (x,y)
diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh
index b1316e62f4..42b3327e69 100755
--- a/t/t7004-tag.sh
+++ b/t/t7004-tag.sh
@@ -10,6 +10,7 @@ Tests for operations with tags.'
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
. "$TEST_DIRECTORY"/lib-terminal.sh
diff --git a/t/t7031-verify-tag-signed-ssh.sh b/t/t7031-verify-tag-signed-ssh.sh
index 80359d48f7..0efd17b363 100755
--- a/t/t7031-verify-tag-signed-ssh.sh
+++ b/t/t7031-verify-tag-signed-ssh.sh
@@ -4,6 +4,7 @@ test_description='signed tag 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/t7063-status-untracked-cache.sh b/t/t7063-status-untracked-cache.sh
index 8929ef481f..13fea7931c 100755
--- a/t/t7063-status-untracked-cache.sh
+++ b/t/t7063-status-untracked-cache.sh
@@ -5,6 +5,7 @@ test_description='test untracked cache'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# On some filesystems (e.g. FreeBSD's ext2 and ufs) directory mtime
diff --git a/t/t7500-commit-template-squash-signoff.sh b/t/t7500-commit-template-squash-signoff.sh
index 4dca8d97a7..379d3ed341 100755
--- a/t/t7500-commit-template-squash-signoff.sh
+++ b/t/t7500-commit-template-squash-signoff.sh
@@ -7,6 +7,7 @@ test_description='git commit
Tests for template, signoff, squash and -F functions.'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-rebase.sh
diff --git a/t/t7502-commit-porcelain.sh b/t/t7502-commit-porcelain.sh
index b37e2018a7..84f1ff52b6 100755
--- a/t/t7502-commit-porcelain.sh
+++ b/t/t7502-commit-porcelain.sh
@@ -5,6 +5,7 @@ test_description='git commit porcelain-ish'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
commit_msg_is () {
diff --git a/t/t7510-signed-commit.sh b/t/t7510-signed-commit.sh
index 0d2dd29fe6..eb229082e4 100755
--- a/t/t7510-signed-commit.sh
+++ b/t/t7510-signed-commit.sh
@@ -4,6 +4,7 @@ test_description='signed commit tests'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
GNUPGHOME_NOT_USED=$GNUPGHOME
. "$TEST_DIRECTORY/lib-gpg.sh"
diff --git a/t/t7513-interpret-trailers.sh b/t/t7513-interpret-trailers.sh
index 818a8dafbd..502752c0f3 100755
--- a/t/t7513-interpret-trailers.sh
+++ b/t/t7513-interpret-trailers.sh
@@ -5,6 +5,7 @@
test_description='git interpret-trailers'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# When we want one trailing space at the end of each line, let's use sed
diff --git a/t/t7519-status-fsmonitor.sh b/t/t7519-status-fsmonitor.sh
index 7ee69ecdd4..0f88a58a81 100755
--- a/t/t7519-status-fsmonitor.sh
+++ b/t/t7519-status-fsmonitor.sh
@@ -2,6 +2,7 @@
test_description='git status with file system watcher'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Note, after "git reset --hard HEAD" no extensions exist other than 'TREE'
diff --git a/t/t7528-signed-commit-ssh.sh b/t/t7528-signed-commit-ssh.sh
index 065f780636..68e18856b6 100755
--- a/t/t7528-signed-commit-ssh.sh
+++ b/t/t7528-signed-commit-ssh.sh
@@ -4,6 +4,7 @@ test_description='ssh signed commit tests'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
GNUPGHOME_NOT_USED=$GNUPGHOME
. "$TEST_DIRECTORY/lib-gpg.sh"
diff --git a/t/t7610-mergetool.sh b/t/t7610-mergetool.sh
index 22b3a85b3e..5c5e79e990 100755
--- a/t/t7610-mergetool.sh
+++ b/t/t7610-mergetool.sh
@@ -10,6 +10,7 @@ Testing basic merge tool invocation'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# All the mergetool test work by checking out a temporary branch based
diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh
index 64ac4f04ee..1bdb8e5a99 100755
--- a/t/t7810-grep.sh
+++ b/t/t7810-grep.sh
@@ -9,6 +9,7 @@ test_description='git grep various.
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_invalid_grep_expression() {
diff --git a/trailer.c b/trailer.c
index 682d74505b..8ba350404d 100644
--- a/trailer.c
+++ b/trailer.c
@@ -249,7 +249,9 @@ static char *apply_command(struct conf_info *conf, const char *arg)
static void apply_item_command(struct trailer_item *in_tok, struct arg_item *arg_tok)
{
if (arg_tok->conf.command || arg_tok->conf.cmd) {
- const char *arg;
+ char *value_to_free = NULL;
+ char *arg;
+
if (arg_tok->value && arg_tok->value[0]) {
arg = arg_tok->value;
} else {
@@ -257,9 +259,13 @@ static void apply_item_command(struct trailer_item *in_tok, struct arg_item *arg
arg = xstrdup(in_tok->value);
else
arg = xstrdup("");
+ value_to_free = arg_tok->value;
}
+
arg_tok->value = apply_command(&arg_tok->conf, arg);
- free((char *)arg);
+
+ free(value_to_free);
+ free(arg);
}
}
@@ -1105,6 +1111,8 @@ void format_trailers(const struct process_trailer_options *opts,
struct list_head *trailers,
struct strbuf *out)
{
+ struct strbuf tok = STRBUF_INIT;
+ struct strbuf val = STRBUF_INIT;
size_t origlen = out->len;
struct list_head *pos;
struct trailer_item *item;
@@ -1112,9 +1120,9 @@ void format_trailers(const struct process_trailer_options *opts,
list_for_each(pos, trailers) {
item = list_entry(pos, struct trailer_item, list);
if (item->token) {
- struct strbuf tok = STRBUF_INIT;
- struct strbuf val = STRBUF_INIT;
+ strbuf_reset(&tok);
strbuf_addstr(&tok, item->token);
+ strbuf_reset(&val);
strbuf_addstr(&val, item->value);
/*
@@ -1145,9 +1153,6 @@ void format_trailers(const struct process_trailer_options *opts,
if (!opts->separator)
strbuf_addch(out, '\n');
}
- strbuf_release(&tok);
- strbuf_release(&val);
-
} else if (!opts->only_trailers) {
if (opts->separator && out->len != origlen) {
strbuf_addbuf(out, opts->separator);
@@ -1159,6 +1164,9 @@ void format_trailers(const struct process_trailer_options *opts,
strbuf_addch(out, '\n');
}
}
+
+ strbuf_release(&tok);
+ strbuf_release(&val);
}
void format_trailers_from_commit(const struct process_trailer_options *opts,
diff --git a/transport-helper.c b/transport-helper.c
index 013ec79dc9..bc27653cde 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -399,6 +399,8 @@ static int release_helper(struct transport *transport)
int res = 0;
struct helper_data *data = transport->data;
refspec_clear(&data->rs);
+ free(data->import_marks);
+ free(data->export_marks);
res = disconnect_helper(transport);
free(transport->data);
return res;
diff --git a/upload-pack.c b/upload-pack.c
index 6d6e0f9f98..43006c0614 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -166,6 +166,7 @@ static void upload_pack_data_clear(struct upload_pack_data *data)
object_array_clear(&data->extra_edge_obj);
list_objects_filter_release(&data->filter_options);
string_list_clear(&data->allowed_filters, 0);
+ string_list_clear(&data->uri_protocols, 0);
free((char *)data->pack_objects_hook);
}
@@ -1025,10 +1026,14 @@ static int process_deepen_not(const char *line, struct oidset *deepen_not, int *
{
const char *arg;
if (skip_prefix(line, "deepen-not ", &arg)) {
+ int cnt;
char *ref = NULL;
struct object_id oid;
- if (expand_ref(the_repository, arg, strlen(arg), &oid, &ref) != 1)
+ cnt = expand_ref(the_repository, arg, strlen(arg), &oid, &ref);
+ if (cnt > 1)
die("git upload-pack: ambiguous deepen-not: %s", line);
+ if (cnt < 1)
+ die("git upload-pack: deepen-not is not a ref: %s", line);
oidset_insert(deepen_not, &oid);
free(ref);
*deepen_rev_list = 1;