Merge branch 'ps/leakfixes-part-8'

More leakfixes.

* ps/leakfixes-part-8: (23 commits)
  builtin/send-pack: fix leaking list of push options
  remote: fix leaking push reports
  t/helper: fix leaks in proc-receive helper
  pack-write: fix return parameter of `write_rev_file_order()`
  revision: fix leaking saved parents
  revision: fix memory leaks when rewriting parents
  midx-write: fix leaking buffer
  pack-bitmap-write: fix leaking OID array
  pseudo-merge: fix leaking strmap keys
  pseudo-merge: fix various memory leaks
  line-log: fix several memory leaks
  diff: improve lifecycle management of diff queues
  builtin/revert: fix leaking `gpg_sign` and `strategy` config
  t/helper: fix leaking repository in partial-clone helper
  builtin/clone: fix leaking repo state when cloning with bundle URIs
  builtin/pack-redundant: fix various memory leaks
  builtin/stash: fix leaking `pathspec_from_file`
  submodule: fix leaking submodule entry list
  wt-status: fix leaking buffer with sparse directories
  shell: fix leaking strings
  ...
This commit is contained in:
Junio C Hamano 2024-10-10 14:22:27 -07:00
commit 31bc4454de
62 changed files with 329 additions and 123 deletions

View File

@ -476,8 +476,6 @@ struct bloom_filter *get_or_compute_bloom_filter(struct repository *r,
*last_slash = '\0'; *last_slash = '\0';
} while (*path); } while (*path);
diff_free_filepair(diff_queued_diff.queue[i]);
} }
if (hashmap_get_size(&pathmap) > settings->max_changed_paths) { if (hashmap_get_size(&pathmap) > settings->max_changed_paths) {
@ -508,8 +506,6 @@ struct bloom_filter *get_or_compute_bloom_filter(struct repository *r,
cleanup: cleanup:
hashmap_clear_and_free(&pathmap, struct pathmap_hash_entry, entry); hashmap_clear_and_free(&pathmap, struct pathmap_hash_entry, entry);
} else { } else {
for (i = 0; i < diff_queued_diff.nr; i++)
diff_free_filepair(diff_queued_diff.queue[i]);
init_truncated_large_filter(filter, settings->hash_version); init_truncated_large_filter(filter, settings->hash_version);
if (computed) if (computed)
@ -519,9 +515,7 @@ struct bloom_filter *get_or_compute_bloom_filter(struct repository *r,
if (computed) if (computed)
*computed |= BLOOM_COMPUTED; *computed |= BLOOM_COMPUTED;
free(diff_queued_diff.queue); diff_queue_clear(&diff_queued_diff);
DIFF_QUEUE_CLEAR(&diff_queued_diff);
return filter; return filter;
} }

View File

@ -738,6 +738,7 @@ static int submodule_create_branch(struct repository *r,
strbuf_release(&child_err); strbuf_release(&child_err);
strbuf_release(&out_buf); strbuf_release(&out_buf);
free(out_prefix);
return ret; return ret;
} }
@ -794,7 +795,7 @@ void create_branches_recursively(struct repository *r, const char *name,
create_branch(r, name, start_committish, force, 0, reflog, quiet, create_branch(r, name, start_committish, force, 0, reflog, quiet,
BRANCH_TRACK_NEVER, dry_run); BRANCH_TRACK_NEVER, dry_run);
if (dry_run) if (dry_run)
return; goto out;
/* /*
* NEEDSWORK If tracking was set up in the superproject but not the * NEEDSWORK If tracking was set up in the superproject but not the
* submodule, users might expect "git branch --recurse-submodules" to * submodule, users might expect "git branch --recurse-submodules" to
@ -815,8 +816,11 @@ void create_branches_recursively(struct repository *r, const char *name,
die(_("submodule '%s': cannot create branch '%s'"), die(_("submodule '%s': cannot create branch '%s'"),
submodule_entry_list.entries[i].submodule->name, submodule_entry_list.entries[i].submodule->name,
name); name);
repo_clear(submodule_entry_list.entries[i].repo);
} }
out:
submodule_entry_list_release(&submodule_entry_list);
free(branch_point);
} }
void remove_merge_branch_state(struct repository *r) void remove_merge_branch_state(struct repository *r)

View File

@ -15,13 +15,23 @@ int cmd_annotate(int argc,
struct repository *repo UNUSED) struct repository *repo UNUSED)
{ {
struct strvec args = STRVEC_INIT; struct strvec args = STRVEC_INIT;
int i; const char **args_copy;
int ret;
strvec_pushl(&args, "annotate", "-c", NULL); strvec_pushl(&args, "annotate", "-c", NULL);
for (int i = 1; i < argc; i++)
for (i = 1; i < argc; i++) {
strvec_push(&args, argv[i]); strvec_push(&args, argv[i]);
}
return cmd_blame(args.nr, args.v, prefix, the_repository); /*
* `cmd_blame()` ends up modifying the array, which causes memory leaks
* if we didn't copy the array here.
*/
CALLOC_ARRAY(args_copy, args.nr + 1);
COPY_ARRAY(args_copy, args.v, args.nr);
ret = cmd_blame(args.nr, args_copy, prefix, the_repository);
strvec_clear(&args);
free(args_copy);
return ret;
} }

View File

@ -1403,8 +1403,17 @@ int cmd_clone(int argc,
* data from the --bundle-uri option. * data from the --bundle-uri option.
*/ */
if (bundle_uri) { if (bundle_uri) {
struct remote_state *state;
int has_heuristic = 0; int has_heuristic = 0;
/*
* We need to save the remote state as our remote's lifetime is
* tied to it.
*/
state = the_repository->remote_state;
the_repository->remote_state = NULL;
repo_clear(the_repository);
/* At this point, we need the_repository to match the cloned repo. */ /* At this point, we need the_repository to match the cloned repo. */
if (repo_init(the_repository, git_dir, work_tree)) if (repo_init(the_repository, git_dir, work_tree))
warning(_("failed to initialize the repo, skipping bundle URI")); warning(_("failed to initialize the repo, skipping bundle URI"));
@ -1413,6 +1422,10 @@ int cmd_clone(int argc,
bundle_uri); bundle_uri);
else if (has_heuristic) else if (has_heuristic)
git_config_set_gently("fetch.bundleuri", bundle_uri); git_config_set_gently("fetch.bundleuri", bundle_uri);
remote_state_clear(the_repository->remote_state);
free(the_repository->remote_state);
the_repository->remote_state = state;
} else { } else {
/* /*
* Populate transport->got_remote_bundle_uri and * Populate transport->got_remote_bundle_uri and
@ -1422,12 +1435,26 @@ int cmd_clone(int argc,
if (transport->bundles && if (transport->bundles &&
hashmap_get_size(&transport->bundles->bundles)) { hashmap_get_size(&transport->bundles->bundles)) {
struct remote_state *state;
/*
* We need to save the remote state as our remote's
* lifetime is tied to it.
*/
state = the_repository->remote_state;
the_repository->remote_state = NULL;
repo_clear(the_repository);
/* At this point, we need the_repository to match the cloned repo. */ /* At this point, we need the_repository to match the cloned repo. */
if (repo_init(the_repository, git_dir, work_tree)) if (repo_init(the_repository, git_dir, work_tree))
warning(_("failed to initialize the repo, skipping bundle URI")); warning(_("failed to initialize the repo, skipping bundle URI"));
else if (fetch_bundle_list(the_repository, else if (fetch_bundle_list(the_repository,
transport->bundles)) transport->bundles))
warning(_("failed to fetch advertised bundles")); warning(_("failed to fetch advertised bundles"));
remote_state_clear(the_repository->remote_state);
free(the_repository->remote_state);
the_repository->remote_state = state;
} else { } else {
clear_bundle_list(transport->bundles); clear_bundle_list(transport->bundles);
FREE_AND_NULL(transport->bundles); FREE_AND_NULL(transport->bundles);

View File

@ -1505,7 +1505,7 @@ static void rename_tmp_packfile(const char **final_name,
struct strbuf *name, unsigned char *hash, struct strbuf *name, unsigned char *hash,
const char *ext, int make_read_only_if_same) const char *ext, int make_read_only_if_same)
{ {
if (*final_name != curr_name) { if (!*final_name || strcmp(*final_name, curr_name)) {
if (!*final_name) if (!*final_name)
*final_name = odb_pack_name(name, hash, ext); *final_name = odb_pack_name(name, hash, ext);
if (finalize_object_file(curr_name, *final_name)) if (finalize_object_file(curr_name, *final_name))
@ -1726,7 +1726,7 @@ int cmd_index_pack(int argc,
{ {
int i, fix_thin_pack = 0, verify = 0, stat_only = 0, rev_index; int i, fix_thin_pack = 0, verify = 0, stat_only = 0, rev_index;
const char *curr_index; const char *curr_index;
const char *curr_rev_index = NULL; char *curr_rev_index = NULL;
const char *index_name = NULL, *pack_name = NULL, *rev_index_name = NULL; const char *index_name = NULL, *pack_name = NULL, *rev_index_name = NULL;
const char *keep_msg = NULL; const char *keep_msg = NULL;
const char *promisor_msg = NULL; const char *promisor_msg = NULL;
@ -1968,8 +1968,7 @@ int cmd_index_pack(int argc,
free((void *) curr_pack); free((void *) curr_pack);
if (!index_name) if (!index_name)
free((void *) curr_index); free((void *) curr_index);
if (!rev_index_name) free(curr_rev_index);
free((void *) curr_rev_index);
/* /*
* Let the caller know this pack is not self contained * Let the caller know this pack is not self contained

View File

@ -69,6 +69,15 @@ static inline void llist_init(struct llist **list)
(*list)->size = 0; (*list)->size = 0;
} }
static void llist_free(struct llist *list)
{
for (struct llist_item *i = list->front, *next; i; i = next) {
next = i->next;
llist_item_put(i);
}
free(list);
}
static struct llist * llist_copy(struct llist *list) static struct llist * llist_copy(struct llist *list)
{ {
struct llist *ret; struct llist *ret;
@ -206,6 +215,14 @@ static inline struct pack_list * pack_list_insert(struct pack_list **pl,
return p; return p;
} }
static void pack_list_free(struct pack_list *pl)
{
for (struct pack_list *next; pl; pl = next) {
next = pl->next;
free(pl);
}
}
static inline size_t pack_list_size(struct pack_list *pl) static inline size_t pack_list_size(struct pack_list *pl)
{ {
size_t ret = 0; size_t ret = 0;
@ -419,7 +436,8 @@ static void minimize(struct pack_list **min)
/* return if there are no objects missing from the unique set */ /* return if there are no objects missing from the unique set */
if (missing->size == 0) { if (missing->size == 0) {
free(missing); llist_free(missing);
pack_list_free(non_unique);
return; return;
} }
@ -434,6 +452,8 @@ static void minimize(struct pack_list **min)
} }
while (non_unique) { while (non_unique) {
struct pack_list *next;
/* sort the non_unique packs, greater size of remaining_objects first */ /* sort the non_unique packs, greater size of remaining_objects first */
sort_pack_list(&non_unique); sort_pack_list(&non_unique);
if (non_unique->remaining_objects->size == 0) if (non_unique->remaining_objects->size == 0)
@ -444,8 +464,14 @@ static void minimize(struct pack_list **min)
for (pl = non_unique->next; pl && pl->remaining_objects->size > 0; pl = pl->next) for (pl = non_unique->next; pl && pl->remaining_objects->size > 0; pl = pl->next)
llist_sorted_difference_inplace(pl->remaining_objects, non_unique->remaining_objects); llist_sorted_difference_inplace(pl->remaining_objects, non_unique->remaining_objects);
non_unique = non_unique->next; next = non_unique->next;
free(non_unique);
non_unique = next;
} }
pack_list_free(non_unique);
llist_free(unique_pack_objects);
llist_free(missing);
} }
static void load_all_objects(void) static void load_all_objects(void)
@ -565,7 +591,6 @@ static void load_all(void)
int cmd_pack_redundant(int argc, const char **argv, const char *prefix UNUSED, struct repository *repo UNUSED) { int cmd_pack_redundant(int argc, const char **argv, const char *prefix UNUSED, struct repository *repo UNUSED) {
int i; int i_still_use_this = 0; struct pack_list *min = NULL, *red, *pl; int i; int i_still_use_this = 0; struct pack_list *min = NULL, *red, *pl;
struct llist *ignore; struct llist *ignore;
struct object_id *oid;
char buf[GIT_MAX_HEXSZ + 2]; /* hex hash + \n + \0 */ char buf[GIT_MAX_HEXSZ + 2]; /* hex hash + \n + \0 */
if (argc == 2 && !strcmp(argv[1], "-h")) if (argc == 2 && !strcmp(argv[1], "-h"))
@ -625,11 +650,11 @@ int cmd_pack_redundant(int argc, const char **argv, const char *prefix UNUSED, s
/* ignore objects given on stdin */ /* ignore objects given on stdin */
llist_init(&ignore); llist_init(&ignore);
if (!isatty(0)) { if (!isatty(0)) {
struct object_id oid;
while (fgets(buf, sizeof(buf), stdin)) { while (fgets(buf, sizeof(buf), stdin)) {
oid = xmalloc(sizeof(*oid)); if (get_oid_hex(buf, &oid))
if (get_oid_hex(buf, oid))
die("Bad object ID on stdin: %s", buf); die("Bad object ID on stdin: %s", buf);
llist_insert_sorted_unique(ignore, oid, NULL); llist_insert_sorted_unique(ignore, &oid, NULL);
} }
} }
llist_sorted_difference_inplace(all_objects, ignore); llist_sorted_difference_inplace(all_objects, ignore);
@ -671,5 +696,8 @@ int cmd_pack_redundant(int argc, const char **argv, const char *prefix UNUSED, s
fprintf(stderr, "%luMB of redundant packs in total.\n", fprintf(stderr, "%luMB of redundant packs in total.\n",
(unsigned long)pack_set_bytecount(red)/(1024*1024)); (unsigned long)pack_set_bytecount(red)/(1024*1024));
pack_list_free(red);
pack_list_free(min);
llist_free(ignore);
return 0; return 0;
} }

View File

@ -374,6 +374,7 @@ static void write_head_info(void)
struct command { struct command {
struct command *next; struct command *next;
const char *error_string; const char *error_string;
char *error_string_owned;
struct ref_push_report *report; struct ref_push_report *report;
unsigned int skip_update:1, unsigned int skip_update:1,
did_not_exist:1, did_not_exist:1,
@ -1083,7 +1084,7 @@ static int read_proc_receive_report(struct packet_reader *reader,
hint->run_proc_receive |= RUN_PROC_RECEIVE_RETURNED; hint->run_proc_receive |= RUN_PROC_RECEIVE_RETURNED;
if (!strcmp(head, "ng")) { if (!strcmp(head, "ng")) {
if (p) if (p)
hint->error_string = xstrdup(p); hint->error_string = hint->error_string_owned = xstrdup(p);
else else
hint->error_string = "failed"; hint->error_string = "failed";
code = -1; code = -1;
@ -2054,6 +2055,8 @@ static void free_commands(struct command *commands)
while (commands) { while (commands) {
struct command *next = commands->next; struct command *next = commands->next;
ref_push_report_free(commands->report);
free(commands->error_string_owned);
free(commands); free(commands);
commands = next; commands = next;
} }

View File

@ -110,6 +110,9 @@ static int run_sequencer(int argc, const char **argv, const char *prefix,
const char * const * usage_str = revert_or_cherry_pick_usage(opts); const char * const * usage_str = revert_or_cherry_pick_usage(opts);
const char *me = action_name(opts); const char *me = action_name(opts);
const char *cleanup_arg = NULL; const char *cleanup_arg = NULL;
const char sentinel_value;
const char *strategy = &sentinel_value;
const char *gpg_sign = &sentinel_value;
enum empty_action empty_opt = EMPTY_COMMIT_UNSPECIFIED; enum empty_action empty_opt = EMPTY_COMMIT_UNSPECIFIED;
int cmd = 0; int cmd = 0;
struct option base_options[] = { struct option base_options[] = {
@ -125,10 +128,10 @@ static int run_sequencer(int argc, const char **argv, const char *prefix,
OPT_CALLBACK('m', "mainline", opts, N_("parent-number"), OPT_CALLBACK('m', "mainline", opts, N_("parent-number"),
N_("select mainline parent"), option_parse_m), N_("select mainline parent"), option_parse_m),
OPT_RERERE_AUTOUPDATE(&opts->allow_rerere_auto), OPT_RERERE_AUTOUPDATE(&opts->allow_rerere_auto),
OPT_STRING(0, "strategy", &opts->strategy, N_("strategy"), N_("merge strategy")), OPT_STRING(0, "strategy", &strategy, N_("strategy"), N_("merge strategy")),
OPT_STRVEC('X', "strategy-option", &opts->xopts, N_("option"), OPT_STRVEC('X', "strategy-option", &opts->xopts, N_("option"),
N_("option for merge strategy")), N_("option for merge strategy")),
{ OPTION_STRING, 'S', "gpg-sign", &opts->gpg_sign, N_("key-id"), { OPTION_STRING, 'S', "gpg-sign", &gpg_sign, N_("key-id"),
N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" }, N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
OPT_END() OPT_END()
}; };
@ -240,8 +243,14 @@ static int run_sequencer(int argc, const char **argv, const char *prefix,
usage_with_options(usage_str, options); usage_with_options(usage_str, options);
/* These option values will be free()d */ /* These option values will be free()d */
opts->gpg_sign = xstrdup_or_null(opts->gpg_sign); if (gpg_sign != &sentinel_value) {
opts->strategy = xstrdup_or_null(opts->strategy); free(opts->gpg_sign);
opts->gpg_sign = xstrdup_or_null(gpg_sign);
}
if (strategy != &sentinel_value) {
free(opts->strategy);
opts->strategy = xstrdup_or_null(strategy);
}
if (!opts->strategy && getenv("GIT_TEST_MERGE_ALGORITHM")) if (!opts->strategy && getenv("GIT_TEST_MERGE_ALGORITHM"))
opts->strategy = xstrdup(getenv("GIT_TEST_MERGE_ALGORITHM")); opts->strategy = xstrdup(getenv("GIT_TEST_MERGE_ALGORITHM"));
free(options); free(options);

View File

@ -340,6 +340,7 @@ int cmd_send_pack(int argc,
/* stable plumbing output; do not modify or localize */ /* stable plumbing output; do not modify or localize */
fprintf(stderr, "Everything up-to-date\n"); fprintf(stderr, "Everything up-to-date\n");
string_list_clear(&push_options, 0);
free_refs(remote_refs); free_refs(remote_refs);
free_refs(local_refs); free_refs(local_refs);
refspec_clear(&rs); refspec_clear(&rs);

View File

@ -1759,7 +1759,7 @@ static int push_stash(int argc, const char **argv, const char *prefix,
int quiet = 0; int quiet = 0;
int pathspec_file_nul = 0; int pathspec_file_nul = 0;
const char *stash_msg = NULL; const char *stash_msg = NULL;
const char *pathspec_from_file = NULL; char *pathspec_from_file = NULL;
struct pathspec ps; struct pathspec ps;
struct option options[] = { struct option options[] = {
OPT_BOOL('k', "keep-index", &keep_index, OPT_BOOL('k', "keep-index", &keep_index,
@ -1821,7 +1821,9 @@ static int push_stash(int argc, const char **argv, const char *prefix,
ret = do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode, ret = do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
include_untracked, only_staged); include_untracked, only_staged);
clear_pathspec(&ps); clear_pathspec(&ps);
free(pathspec_from_file);
return ret; return ret;
} }

22
diff.c
View File

@ -5983,11 +5983,18 @@ void diff_free_filepair(struct diff_filepair *p)
free(p); free(p);
} }
void diff_free_queue(struct diff_queue_struct *q) void diff_queue_init(struct diff_queue_struct *q)
{
struct diff_queue_struct blank = DIFF_QUEUE_INIT;
memcpy(q, &blank, sizeof(*q));
}
void diff_queue_clear(struct diff_queue_struct *q)
{ {
for (int i = 0; i < q->nr; i++) for (int i = 0; i < q->nr; i++)
diff_free_filepair(q->queue[i]); diff_free_filepair(q->queue[i]);
free(q->queue); free(q->queue);
diff_queue_init(q);
} }
const char *diff_aligned_abbrev(const struct object_id *oid, int len) const char *diff_aligned_abbrev(const struct object_id *oid, int len)
@ -6551,8 +6558,7 @@ int diff_flush_patch_id(struct diff_options *options, struct object_id *oid, int
struct diff_queue_struct *q = &diff_queued_diff; struct diff_queue_struct *q = &diff_queued_diff;
int result = diff_get_patch_id(options, oid, diff_header_only); int result = diff_get_patch_id(options, oid, diff_header_only);
diff_free_queue(q); diff_queue_clear(q);
DIFF_QUEUE_CLEAR(q);
return result; return result;
} }
@ -6835,8 +6841,7 @@ void diff_flush(struct diff_options *options)
} }
free_queue: free_queue:
diff_free_queue(q); diff_queue_clear(q);
DIFF_QUEUE_CLEAR(q);
diff_free(options); diff_free(options);
/* /*
@ -6867,9 +6872,7 @@ static void diffcore_apply_filter(struct diff_options *options)
{ {
int i; int i;
struct diff_queue_struct *q = &diff_queued_diff; struct diff_queue_struct *q = &diff_queued_diff;
struct diff_queue_struct outq; struct diff_queue_struct outq = DIFF_QUEUE_INIT;
DIFF_QUEUE_CLEAR(&outq);
if (!options->filter) if (!options->filter)
return; return;
@ -6962,8 +6965,7 @@ static void diffcore_skip_stat_unmatch(struct diff_options *diffopt)
{ {
int i; int i;
struct diff_queue_struct *q = &diff_queued_diff; struct diff_queue_struct *q = &diff_queued_diff;
struct diff_queue_struct outq; struct diff_queue_struct outq = DIFF_QUEUE_INIT;
DIFF_QUEUE_CLEAR(&outq);
for (i = 0; i < q->nr; i++) { for (i = 0; i < q->nr; i++) {
struct diff_filepair *p = q->queue[i]; struct diff_filepair *p = q->queue[i];

View File

@ -131,7 +131,7 @@ static int should_break(struct repository *r,
void diffcore_break(struct repository *r, int break_score) void diffcore_break(struct repository *r, int break_score)
{ {
struct diff_queue_struct *q = &diff_queued_diff; struct diff_queue_struct *q = &diff_queued_diff;
struct diff_queue_struct outq; struct diff_queue_struct outq = DIFF_QUEUE_INIT;
/* When the filepair has this much edit (insert and delete), /* When the filepair has this much edit (insert and delete),
* it is first considered to be a rewrite and broken into a * it is first considered to be a rewrite and broken into a
@ -178,8 +178,6 @@ void diffcore_break(struct repository *r, int break_score)
if (!merge_score) if (!merge_score)
merge_score = DEFAULT_MERGE_SCORE; merge_score = DEFAULT_MERGE_SCORE;
DIFF_QUEUE_CLEAR(&outq);
for (i = 0; i < q->nr; i++) { for (i = 0; i < q->nr; i++) {
struct diff_filepair *p = q->queue[i]; struct diff_filepair *p = q->queue[i];
int score; int score;
@ -275,11 +273,9 @@ static void merge_broken(struct diff_filepair *p,
void diffcore_merge_broken(void) void diffcore_merge_broken(void)
{ {
struct diff_queue_struct *q = &diff_queued_diff; struct diff_queue_struct *q = &diff_queued_diff;
struct diff_queue_struct outq; struct diff_queue_struct outq = DIFF_QUEUE_INIT;
int i, j; int i, j;
DIFF_QUEUE_CLEAR(&outq);
for (i = 0; i < q->nr; i++) { for (i = 0; i < q->nr; i++) {
struct diff_filepair *p = q->queue[i]; struct diff_filepair *p = q->queue[i];
if (!p) if (!p)

View File

@ -182,9 +182,7 @@ static void pickaxe(struct diff_queue_struct *q, struct diff_options *o,
regex_t *regexp, kwset_t kws, pickaxe_fn fn) regex_t *regexp, kwset_t kws, pickaxe_fn fn)
{ {
int i; int i;
struct diff_queue_struct outq; struct diff_queue_struct outq = DIFF_QUEUE_INIT;
DIFF_QUEUE_CLEAR(&outq);
if (o->pickaxe_opts & DIFF_PICKAXE_ALL) { if (o->pickaxe_opts & DIFF_PICKAXE_ALL) {
/* Showing the whole changeset if needle exists */ /* Showing the whole changeset if needle exists */

View File

@ -1388,7 +1388,7 @@ void diffcore_rename_extended(struct diff_options *options,
int detect_rename = options->detect_rename; int detect_rename = options->detect_rename;
int minimum_score = options->rename_score; int minimum_score = options->rename_score;
struct diff_queue_struct *q = &diff_queued_diff; struct diff_queue_struct *q = &diff_queued_diff;
struct diff_queue_struct outq; struct diff_queue_struct outq = DIFF_QUEUE_INIT;
struct diff_score *mx; struct diff_score *mx;
int i, j, rename_count, skip_unmodified = 0; int i, j, rename_count, skip_unmodified = 0;
int num_destinations, dst_cnt; int num_destinations, dst_cnt;
@ -1638,7 +1638,6 @@ void diffcore_rename_extended(struct diff_options *options,
* are recorded in rename_dst. The original list is still in *q. * are recorded in rename_dst. The original list is still in *q.
*/ */
trace2_region_enter("diff", "write back to queue", options->repo); trace2_region_enter("diff", "write back to queue", options->repo);
DIFF_QUEUE_CLEAR(&outq);
for (i = 0; i < q->nr; i++) { for (i = 0; i < q->nr; i++) {
struct diff_filepair *p = q->queue[i]; struct diff_filepair *p = q->queue[i];
struct diff_filepair *pair_to_free = NULL; struct diff_filepair *pair_to_free = NULL;

View File

@ -10,7 +10,7 @@
void diffcore_rotate(struct diff_options *opt) void diffcore_rotate(struct diff_options *opt)
{ {
struct diff_queue_struct *q = &diff_queued_diff; struct diff_queue_struct *q = &diff_queued_diff;
struct diff_queue_struct outq; struct diff_queue_struct outq = DIFF_QUEUE_INIT;
int rotate_to, i; int rotate_to, i;
if (!q->nr) if (!q->nr)
@ -31,7 +31,6 @@ void diffcore_rotate(struct diff_options *opt)
return; return;
} }
DIFF_QUEUE_CLEAR(&outq);
rotate_to = i; rotate_to = i;
for (i = rotate_to; i < q->nr; i++) for (i = rotate_to; i < q->nr; i++)

View File

@ -153,18 +153,16 @@ struct diff_queue_struct {
int nr; int nr;
}; };
#define DIFF_QUEUE_CLEAR(q) \ #define DIFF_QUEUE_INIT { 0 }
do { \
(q)->queue = NULL; \ void diff_queue_init(struct diff_queue_struct *q);
(q)->nr = (q)->alloc = 0; \ void diff_queue_clear(struct diff_queue_struct *q);
} while (0)
extern struct diff_queue_struct diff_queued_diff; extern struct diff_queue_struct diff_queued_diff;
struct diff_filepair *diff_queue(struct diff_queue_struct *, struct diff_filepair *diff_queue(struct diff_queue_struct *,
struct diff_filespec *, struct diff_filespec *,
struct diff_filespec *); struct diff_filespec *);
void diff_q(struct diff_queue_struct *, struct diff_filepair *); void diff_q(struct diff_queue_struct *, struct diff_filepair *);
void diff_free_queue(struct diff_queue_struct *q);
/* dir_rename_relevance: the reason we want rename information for a dir */ /* dir_rename_relevance: the reason we want rename information for a dir */
enum dir_rename_relevance { enum dir_rename_relevance {

View File

@ -248,8 +248,10 @@ static void line_log_data_init(struct line_log_data *r)
static void line_log_data_clear(struct line_log_data *r) static void line_log_data_clear(struct line_log_data *r)
{ {
range_set_release(&r->ranges); range_set_release(&r->ranges);
free(r->path);
if (r->pair) if (r->pair)
diff_free_filepair(r->pair); diff_free_filepair(r->pair);
diff_ranges_release(&r->diff);
} }
static void free_line_log_data(struct line_log_data *r) static void free_line_log_data(struct line_log_data *r)
@ -571,7 +573,8 @@ parse_lines(struct repository *r, struct commit *commit,
struct line_log_data *p; struct line_log_data *p;
for_each_string_list_item(item, args) { for_each_string_list_item(item, args) {
const char *name_part, *range_part; const char *name_part;
char *range_part;
char *full_name; char *full_name;
struct diff_filespec *spec; struct diff_filespec *spec;
long begin = 0, end = 0; long begin = 0, end = 0;
@ -615,6 +618,7 @@ parse_lines(struct repository *r, struct commit *commit,
free_filespec(spec); free_filespec(spec);
FREE_AND_NULL(ends); FREE_AND_NULL(ends);
free(range_part);
} }
for (p = ranges; p; p = p->next) for (p = ranges; p; p = p->next)
@ -760,15 +764,13 @@ static void parse_pathspec_from_ranges(struct pathspec *pathspec,
{ {
struct line_log_data *r; struct line_log_data *r;
struct strvec array = STRVEC_INIT; struct strvec array = STRVEC_INIT;
const char **paths;
for (r = range; r; r = r->next) for (r = range; r; r = r->next)
strvec_push(&array, r->path); strvec_push(&array, r->path);
paths = strvec_detach(&array);
parse_pathspec(pathspec, 0, PATHSPEC_PREFER_FULL, "", paths); parse_pathspec(pathspec, 0, PATHSPEC_PREFER_FULL, "", array.v);
/* strings are now owned by pathspec */
free(paths); strvec_clear(&array);
} }
void line_log_init(struct rev_info *rev, const char *prefix, struct string_list *args) void line_log_init(struct rev_info *rev, const char *prefix, struct string_list *args)
@ -781,21 +783,22 @@ void line_log_init(struct rev_info *rev, const char *prefix, struct string_list
add_line_range(rev, commit, range); add_line_range(rev, commit, range);
parse_pathspec_from_ranges(&rev->diffopt.pathspec, range); parse_pathspec_from_ranges(&rev->diffopt.pathspec, range);
free_line_log_data(range);
} }
static void move_diff_queue(struct diff_queue_struct *dst, static void move_diff_queue(struct diff_queue_struct *dst,
struct diff_queue_struct *src) struct diff_queue_struct *src)
{ {
assert(src != dst); assert(src != dst);
memcpy(dst, src, sizeof(struct diff_queue_struct)); memcpy(dst, src, sizeof(*dst));
DIFF_QUEUE_CLEAR(src); diff_queue_init(src);
} }
static void filter_diffs_for_paths(struct line_log_data *range, int keep_deletions) static void filter_diffs_for_paths(struct line_log_data *range, int keep_deletions)
{ {
int i; int i;
struct diff_queue_struct outq; struct diff_queue_struct outq = DIFF_QUEUE_INIT;
DIFF_QUEUE_CLEAR(&outq);
for (i = 0; i < diff_queued_diff.nr; i++) { for (i = 0; i < diff_queued_diff.nr; i++) {
struct diff_filepair *p = diff_queued_diff.queue[i]; struct diff_filepair *p = diff_queued_diff.queue[i];
@ -850,12 +853,12 @@ static void queue_diffs(struct line_log_data *range,
clear_pathspec(&opt->pathspec); clear_pathspec(&opt->pathspec);
parse_pathspec_from_ranges(&opt->pathspec, range); parse_pathspec_from_ranges(&opt->pathspec, range);
} }
DIFF_QUEUE_CLEAR(&diff_queued_diff); diff_queue_clear(&diff_queued_diff);
diff_tree_oid(parent_tree_oid, tree_oid, "", opt); diff_tree_oid(parent_tree_oid, tree_oid, "", opt);
if (opt->detect_rename && diff_might_be_rename()) { if (opt->detect_rename && diff_might_be_rename()) {
/* must look at the full tree diff to detect renames */ /* must look at the full tree diff to detect renames */
clear_pathspec(&opt->pathspec); clear_pathspec(&opt->pathspec);
DIFF_QUEUE_CLEAR(&diff_queued_diff); diff_queue_clear(&diff_queued_diff);
diff_tree_oid(parent_tree_oid, tree_oid, "", opt); diff_tree_oid(parent_tree_oid, tree_oid, "", opt);
@ -1095,7 +1098,7 @@ static struct diff_filepair *diff_filepair_dup(struct diff_filepair *pair)
static void free_diffqueues(int n, struct diff_queue_struct *dq) static void free_diffqueues(int n, struct diff_queue_struct *dq)
{ {
for (int i = 0; i < n; i++) for (int i = 0; i < n; i++)
diff_free_queue(&dq[i]); diff_queue_clear(&dq[i]);
free(dq); free(dq);
} }
@ -1130,11 +1133,19 @@ static int process_all_files(struct line_log_data **range_out,
while (rg && strcmp(rg->path, pair->two->path)) while (rg && strcmp(rg->path, pair->two->path))
rg = rg->next; rg = rg->next;
assert(rg); assert(rg);
if (rg->pair)
diff_free_filepair(rg->pair);
rg->pair = diff_filepair_dup(queue->queue[i]); rg->pair = diff_filepair_dup(queue->queue[i]);
diff_ranges_release(&rg->diff);
memcpy(&rg->diff, pairdiff, sizeof(struct diff_ranges)); memcpy(&rg->diff, pairdiff, sizeof(struct diff_ranges));
FREE_AND_NULL(pairdiff);
} }
if (pairdiff) {
diff_ranges_release(pairdiff);
free(pairdiff); free(pairdiff);
} }
}
return changed; return changed;
} }
@ -1198,7 +1209,7 @@ static int process_ranges_ordinary_commit(struct rev_info *rev, struct commit *c
if (parent) if (parent)
add_line_range(rev, parent, parent_range); add_line_range(rev, parent, parent_range);
free_line_log_data(parent_range); free_line_log_data(parent_range);
diff_free_queue(&queue); diff_queue_clear(&queue);
return changed; return changed;
} }
@ -1211,12 +1222,13 @@ static int process_ranges_merge_commit(struct rev_info *rev, struct commit *comm
struct commit_list *p; struct commit_list *p;
int i; int i;
int nparents = commit_list_count(commit->parents); int nparents = commit_list_count(commit->parents);
int ret;
if (nparents > 1 && rev->first_parent_only) if (nparents > 1 && rev->first_parent_only)
nparents = 1; nparents = 1;
ALLOC_ARRAY(diffqueues, nparents); ALLOC_ARRAY(diffqueues, nparents);
ALLOC_ARRAY(cand, nparents); CALLOC_ARRAY(cand, nparents);
ALLOC_ARRAY(parents, nparents); ALLOC_ARRAY(parents, nparents);
p = commit->parents; p = commit->parents;
@ -1228,7 +1240,6 @@ static int process_ranges_merge_commit(struct rev_info *rev, struct commit *comm
for (i = 0; i < nparents; i++) { for (i = 0; i < nparents; i++) {
int changed; int changed;
cand[i] = NULL;
changed = process_all_files(&cand[i], rev, &diffqueues[i], range); changed = process_all_files(&cand[i], rev, &diffqueues[i], range);
if (!changed) { if (!changed) {
/* /*
@ -1236,13 +1247,10 @@ static int process_ranges_merge_commit(struct rev_info *rev, struct commit *comm
* don't follow any other path in history * don't follow any other path in history
*/ */
add_line_range(rev, parents[i], cand[i]); add_line_range(rev, parents[i], cand[i]);
clear_commit_line_range(rev, commit);
commit_list_append(parents[i], &commit->parents); commit_list_append(parents[i], &commit->parents);
free(parents);
free(cand); ret = 0;
free_diffqueues(nparents, diffqueues); goto out;
/* NEEDSWORK leaking like a sieve */
return 0;
} }
} }
@ -1250,18 +1258,25 @@ static int process_ranges_merge_commit(struct rev_info *rev, struct commit *comm
* No single parent took the blame. We add the candidates * No single parent took the blame. We add the candidates
* from the above loop to the parents. * from the above loop to the parents.
*/ */
for (i = 0; i < nparents; i++) { for (i = 0; i < nparents; i++)
add_line_range(rev, parents[i], cand[i]); add_line_range(rev, parents[i], cand[i]);
}
ret = 1;
out:
clear_commit_line_range(rev, commit); clear_commit_line_range(rev, commit);
free(parents); free(parents);
for (i = 0; i < nparents; i++) {
if (!cand[i])
continue;
line_log_data_clear(cand[i]);
free(cand[i]);
}
free(cand); free(cand);
free_diffqueues(nparents, diffqueues); free_diffqueues(nparents, diffqueues);
return 1; return ret;
/* NEEDSWORK evil merge detection stuff */ /* NEEDSWORK evil merge detection stuff */
/* NEEDSWORK leaking like a sieve */
} }
int line_log_process_ranges_arbitrary_commit(struct rev_info *rev, struct commit *commit) int line_log_process_ranges_arbitrary_commit(struct rev_info *rev, struct commit *commit)

View File

@ -675,7 +675,7 @@ static void show_diff_of_diff(struct rev_info *opt)
struct diff_queue_struct dq; struct diff_queue_struct dq;
memcpy(&dq, &diff_queued_diff, sizeof(diff_queued_diff)); memcpy(&dq, &diff_queued_diff, sizeof(diff_queued_diff));
DIFF_QUEUE_CLEAR(&diff_queued_diff); diff_queue_init(&diff_queued_diff);
fprintf_ln(opt->diffopt.file, "\n%s", opt->idiff_title); fprintf_ln(opt->diffopt.file, "\n%s", opt->idiff_title);
show_interdiff(opt->idiff_oid1, opt->idiff_oid2, 2, show_interdiff(opt->idiff_oid1, opt->idiff_oid2, 2,
@ -694,7 +694,7 @@ static void show_diff_of_diff(struct rev_info *opt)
}; };
memcpy(&dq, &diff_queued_diff, sizeof(diff_queued_diff)); memcpy(&dq, &diff_queued_diff, sizeof(diff_queued_diff));
DIFF_QUEUE_CLEAR(&diff_queued_diff); diff_queue_init(&diff_queued_diff);
fprintf_ln(opt->diffopt.file, "\n%s", opt->rdiff_title); fprintf_ln(opt->diffopt.file, "\n%s", opt->rdiff_title);
/* /*

View File

@ -3536,7 +3536,7 @@ simple_cleanup:
/* Free memory for renames->pairs[] and combined */ /* Free memory for renames->pairs[] and combined */
for (s = MERGE_SIDE1; s <= MERGE_SIDE2; s++) { for (s = MERGE_SIDE1; s <= MERGE_SIDE2; s++) {
free(renames->pairs[s].queue); free(renames->pairs[s].queue);
DIFF_QUEUE_CLEAR(&renames->pairs[s]); diff_queue_init(&renames->pairs[s]);
} }
for (i = 0; i < combined.nr; i++) for (i = 0; i < combined.nr; i++)
pool_diff_free_filepair(&opt->priv->pool, combined.queue[i]); pool_diff_free_filepair(&opt->priv->pool, combined.queue[i]);

View File

@ -649,7 +649,7 @@ static void write_midx_reverse_index(char *midx_name, unsigned char *midx_hash,
struct write_midx_context *ctx) struct write_midx_context *ctx)
{ {
struct strbuf buf = STRBUF_INIT; struct strbuf buf = STRBUF_INIT;
const char *tmp_file; char *tmp_file;
trace2_region_enter("midx", "write_midx_reverse_index", the_repository); trace2_region_enter("midx", "write_midx_reverse_index", the_repository);
@ -662,6 +662,7 @@ static void write_midx_reverse_index(char *midx_name, unsigned char *midx_hash,
die(_("cannot store reverse index file")); die(_("cannot store reverse index file"));
strbuf_release(&buf); strbuf_release(&buf);
free(tmp_file);
trace2_region_leave("midx", "write_midx_reverse_index", the_repository); trace2_region_leave("midx", "write_midx_reverse_index", the_repository);
} }
@ -1445,6 +1446,8 @@ static int write_midx_internal(const char *object_dir,
return -1; return -1;
} }
strbuf_release(&final_midx_name);
keep_hashes[ctx.num_multi_pack_indexes_before] = keep_hashes[ctx.num_multi_pack_indexes_before] =
xstrdup(hash_to_hex(midx_hash)); xstrdup(hash_to_hex(midx_hash));

View File

@ -64,6 +64,12 @@ static void free_pseudo_merge_commit_idx(struct pseudo_merge_commit_idx *idx)
free(idx); free(idx);
} }
static void pseudo_merge_group_release_cb(void *payload, const char *name UNUSED)
{
pseudo_merge_group_release(payload);
free(payload);
}
void bitmap_writer_free(struct bitmap_writer *writer) void bitmap_writer_free(struct bitmap_writer *writer)
{ {
uint32_t i; uint32_t i;
@ -82,6 +88,8 @@ void bitmap_writer_free(struct bitmap_writer *writer)
kh_foreach_value(writer->pseudo_merge_commits, idx, kh_foreach_value(writer->pseudo_merge_commits, idx,
free_pseudo_merge_commit_idx(idx)); free_pseudo_merge_commit_idx(idx));
kh_destroy_oid_map(writer->pseudo_merge_commits); kh_destroy_oid_map(writer->pseudo_merge_commits);
string_list_clear_func(&writer->pseudo_merge_groups,
pseudo_merge_group_release_cb);
for (i = 0; i < writer->selected_nr; i++) { for (i = 0; i < writer->selected_nr; i++) {
struct bitmapped_commit *bc = &writer->selected[i]; struct bitmapped_commit *bc = &writer->selected[i];
@ -905,6 +913,7 @@ static void write_pseudo_merges(struct bitmap_writer *writer,
for (i = 0; i < writer->pseudo_merges_nr; i++) for (i = 0; i < writer->pseudo_merges_nr; i++)
bitmap_free(commits_bitmap[i]); bitmap_free(commits_bitmap[i]);
oid_array_clear(&commits);
free(pseudo_merge_ofs); free(pseudo_merge_ofs);
free(commits_bitmap); free(commits_bitmap);
} }

View File

@ -1390,7 +1390,7 @@ static struct bitmap *find_objects(struct bitmap_index *bitmap_git,
} }
base = bitmap_new(); base = bitmap_new();
if (!cascade_pseudo_merges_1(bitmap_git, base, roots_bitmap)) cascade_pseudo_merges_1(bitmap_git, base, roots_bitmap);
bitmap_free(roots_bitmap); bitmap_free(roots_bitmap);
} }

View File

@ -213,7 +213,7 @@ static void write_rev_trailer(struct hashfile *f, const unsigned char *hash)
hashwrite(f, hash, the_hash_algo->rawsz); hashwrite(f, hash, the_hash_algo->rawsz);
} }
const char *write_rev_file(const char *rev_name, char *write_rev_file(const char *rev_name,
struct pack_idx_entry **objects, struct pack_idx_entry **objects,
uint32_t nr_objects, uint32_t nr_objects,
const unsigned char *hash, const unsigned char *hash,
@ -221,7 +221,7 @@ const char *write_rev_file(const char *rev_name,
{ {
uint32_t *pack_order; uint32_t *pack_order;
uint32_t i; uint32_t i;
const char *ret; char *ret;
if (!(flags & WRITE_REV) && !(flags & WRITE_REV_VERIFY)) if (!(flags & WRITE_REV) && !(flags & WRITE_REV_VERIFY))
return NULL; return NULL;
@ -239,13 +239,14 @@ const char *write_rev_file(const char *rev_name,
return ret; return ret;
} }
const char *write_rev_file_order(const char *rev_name, char *write_rev_file_order(const char *rev_name,
uint32_t *pack_order, uint32_t *pack_order,
uint32_t nr_objects, uint32_t nr_objects,
const unsigned char *hash, const unsigned char *hash,
unsigned flags) unsigned flags)
{ {
struct hashfile *f; struct hashfile *f;
char *path;
int fd; int fd;
if ((flags & WRITE_REV) && (flags & WRITE_REV_VERIFY)) if ((flags & WRITE_REV) && (flags & WRITE_REV_VERIFY))
@ -255,12 +256,13 @@ const char *write_rev_file_order(const char *rev_name,
if (!rev_name) { if (!rev_name) {
struct strbuf tmp_file = STRBUF_INIT; struct strbuf tmp_file = STRBUF_INIT;
fd = odb_mkstemp(&tmp_file, "pack/tmp_rev_XXXXXX"); fd = odb_mkstemp(&tmp_file, "pack/tmp_rev_XXXXXX");
rev_name = strbuf_detach(&tmp_file, NULL); path = strbuf_detach(&tmp_file, NULL);
} else { } else {
unlink(rev_name); unlink(rev_name);
fd = xopen(rev_name, O_CREAT|O_EXCL|O_WRONLY, 0600); fd = xopen(rev_name, O_CREAT|O_EXCL|O_WRONLY, 0600);
path = xstrdup(rev_name);
} }
f = hashfd(fd, rev_name); f = hashfd(fd, path);
} else if (flags & WRITE_REV_VERIFY) { } else if (flags & WRITE_REV_VERIFY) {
struct stat statbuf; struct stat statbuf;
if (stat(rev_name, &statbuf)) { if (stat(rev_name, &statbuf)) {
@ -271,22 +273,24 @@ const char *write_rev_file_order(const char *rev_name,
die_errno(_("could not stat: %s"), rev_name); die_errno(_("could not stat: %s"), rev_name);
} }
f = hashfd_check(rev_name); f = hashfd_check(rev_name);
} else path = xstrdup(rev_name);
} else {
return NULL; return NULL;
}
write_rev_header(f); write_rev_header(f);
write_rev_index_positions(f, pack_order, nr_objects); write_rev_index_positions(f, pack_order, nr_objects);
write_rev_trailer(f, hash); write_rev_trailer(f, hash);
if (rev_name && adjust_shared_perm(rev_name) < 0) if (adjust_shared_perm(path) < 0)
die(_("failed to make %s readable"), rev_name); die(_("failed to make %s readable"), path);
finalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA, finalize_hashfile(f, NULL, FSYNC_COMPONENT_PACK_METADATA,
CSUM_HASH_IN_STREAM | CSUM_CLOSE | CSUM_HASH_IN_STREAM | CSUM_CLOSE |
((flags & WRITE_IDX_VERIFY) ? 0 : CSUM_FSYNC)); ((flags & WRITE_IDX_VERIFY) ? 0 : CSUM_FSYNC));
return rev_name; return path;
} }
static void write_mtimes_header(struct hashfile *f) static void write_mtimes_header(struct hashfile *f)
@ -550,7 +554,7 @@ void stage_tmp_packfiles(struct strbuf *name_buffer,
unsigned char hash[], unsigned char hash[],
char **idx_tmp_name) char **idx_tmp_name)
{ {
const char *rev_tmp_name = NULL; char *rev_tmp_name = NULL;
char *mtimes_tmp_name = NULL; char *mtimes_tmp_name = NULL;
if (adjust_shared_perm(pack_tmp_name)) if (adjust_shared_perm(pack_tmp_name))
@ -576,7 +580,7 @@ void stage_tmp_packfiles(struct strbuf *name_buffer,
if (mtimes_tmp_name) if (mtimes_tmp_name)
rename_tmp_packfile(name_buffer, mtimes_tmp_name, "mtimes"); rename_tmp_packfile(name_buffer, mtimes_tmp_name, "mtimes");
free((char *)rev_tmp_name); free(rev_tmp_name);
free(mtimes_tmp_name); free(mtimes_tmp_name);
} }

4
pack.h
View File

@ -96,8 +96,8 @@ struct ref;
void write_promisor_file(const char *promisor_name, struct ref **sought, int nr_sought); void write_promisor_file(const char *promisor_name, struct ref **sought, int nr_sought);
const char *write_rev_file(const char *rev_name, struct pack_idx_entry **objects, uint32_t nr_objects, const unsigned char *hash, unsigned flags); char *write_rev_file(const char *rev_name, struct pack_idx_entry **objects, uint32_t nr_objects, const unsigned char *hash, unsigned flags);
const char *write_rev_file_order(const char *rev_name, uint32_t *pack_order, uint32_t nr_objects, const unsigned char *hash, unsigned flags); char *write_rev_file_order(const char *rev_name, uint32_t *pack_order, uint32_t nr_objects, const unsigned char *hash, unsigned flags);
/* /*
* The "hdr" output buffer should be at least this big, which will handle sizes * The "hdr" output buffer should be at least this big, which will handle sizes

View File

@ -87,7 +87,7 @@ static void pseudo_merge_group_init(struct pseudo_merge_group *group)
{ {
memset(group, 0, sizeof(struct pseudo_merge_group)); memset(group, 0, sizeof(struct pseudo_merge_group));
strmap_init_with_options(&group->matches, NULL, 0); strmap_init_with_options(&group->matches, NULL, 1);
group->decay = DEFAULT_PSEUDO_MERGE_DECAY; group->decay = DEFAULT_PSEUDO_MERGE_DECAY;
group->max_merges = DEFAULT_PSEUDO_MERGE_MAX_MERGES; group->max_merges = DEFAULT_PSEUDO_MERGE_MAX_MERGES;
@ -97,6 +97,25 @@ static void pseudo_merge_group_init(struct pseudo_merge_group *group)
group->stable_size = DEFAULT_PSEUDO_MERGE_STABLE_SIZE; group->stable_size = DEFAULT_PSEUDO_MERGE_STABLE_SIZE;
} }
void pseudo_merge_group_release(struct pseudo_merge_group *group)
{
struct hashmap_iter iter;
struct strmap_entry *e;
regfree(group->pattern);
free(group->pattern);
strmap_for_each_entry(&group->matches, &iter, e) {
struct pseudo_merge_matches *matches = e->value;
free(matches->stable);
free(matches->unstable);
free(matches);
}
strmap_clear(&group->matches, 0);
free(group->merges);
}
static int pseudo_merge_config(const char *var, const char *value, static int pseudo_merge_config(const char *var, const char *value,
const struct config_context *ctx, const struct config_context *ctx,
void *cb_data) void *cb_data)
@ -256,7 +275,7 @@ static int find_pseudo_merge_group_for_ref(const char *refname,
matches = strmap_get(&group->matches, group_name.buf); matches = strmap_get(&group->matches, group_name.buf);
if (!matches) { if (!matches) {
matches = xcalloc(1, sizeof(*matches)); matches = xcalloc(1, sizeof(*matches));
strmap_put(&group->matches, strbuf_detach(&group_name, NULL), strmap_put(&group->matches, group_name.buf,
matches); matches);
} }

View File

@ -51,6 +51,8 @@ struct pseudo_merge_group {
timestamp_t stable_threshold; timestamp_t stable_threshold;
}; };
void pseudo_merge_group_release(struct pseudo_merge_group *group);
struct pseudo_merge_matches { struct pseudo_merge_matches {
struct commit **stable; struct commit **stable;
struct commit **unstable; struct commit **unstable;

View File

@ -3125,6 +3125,7 @@ out:
if (f) if (f)
free_hashfile(f); free_hashfile(f);
strbuf_release(&sb); strbuf_release(&sb);
free(eoie_c);
free(ieot); free(ieot);
return ret; return ret;
} }

View File

@ -868,6 +868,20 @@ struct strvec *push_url_of_remote(struct remote *remote)
return remote->pushurl.nr ? &remote->pushurl : &remote->url; return remote->pushurl.nr ? &remote->pushurl : &remote->url;
} }
void ref_push_report_free(struct ref_push_report *report)
{
while (report) {
struct ref_push_report *next = report->next;
free(report->ref_name);
free(report->old_oid);
free(report->new_oid);
free(report);
report = next;
}
}
static int match_name_with_pattern(const char *key, const char *name, static int match_name_with_pattern(const char *key, const char *name,
const char *value, char **result) const char *value, char **result)
{ {
@ -1122,6 +1136,7 @@ void free_one_ref(struct ref *ref)
if (!ref) if (!ref)
return; return;
free_one_ref(ref->peer_ref); free_one_ref(ref->peer_ref);
ref_push_report_free(ref->report);
free(ref->remote_status); free(ref->remote_status);
free(ref->tracking_ref); free(ref->tracking_ref);
free(ref->symref); free(ref->symref);

View File

@ -126,13 +126,15 @@ int remote_has_url(struct remote *remote, const char *url);
struct strvec *push_url_of_remote(struct remote *remote); struct strvec *push_url_of_remote(struct remote *remote);
struct ref_push_report { struct ref_push_report {
const char *ref_name; char *ref_name;
struct object_id *old_oid; struct object_id *old_oid;
struct object_id *new_oid; struct object_id *new_oid;
unsigned int forced_update:1; unsigned int forced_update:1;
struct ref_push_report *next; struct ref_push_report *next;
}; };
void ref_push_report_free(struct ref_push_report *);
struct ref { struct ref {
struct ref *next; struct ref *next;
struct object_id old_oid; struct object_id old_oid;

View File

@ -3250,6 +3250,7 @@ static int remove_duplicate_parents(struct rev_info *revs, struct commit *commit
struct commit *parent = p->item; struct commit *parent = p->item;
if (parent->object.flags & TMP_MARK) { if (parent->object.flags & TMP_MARK) {
*pp = p->next; *pp = p->next;
free(p);
if (ts) if (ts)
compact_treesame(revs, commit, surviving_parents); compact_treesame(revs, commit, surviving_parents);
continue; continue;
@ -4005,6 +4006,7 @@ int rewrite_parents(struct rev_info *revs, struct commit *commit,
break; break;
case rewrite_one_noparents: case rewrite_one_noparents:
*pp = parent->next; *pp = parent->next;
free(parent);
continue; continue;
case rewrite_one_error: case rewrite_one_error:
return -1; return -1;
@ -4205,10 +4207,18 @@ static void save_parents(struct rev_info *revs, struct commit *commit)
*pp = EMPTY_PARENT_LIST; *pp = EMPTY_PARENT_LIST;
} }
static void free_saved_parent(struct commit_list **parents)
{
if (*parents != EMPTY_PARENT_LIST)
free_commit_list(*parents);
}
static void free_saved_parents(struct rev_info *revs) static void free_saved_parents(struct rev_info *revs)
{ {
if (revs->saved_parents_slab) if (!revs->saved_parents_slab)
clear_saved_parents(revs->saved_parents_slab); return;
deep_clear_saved_parents(revs->saved_parents_slab, free_saved_parent);
FREE_AND_NULL(revs->saved_parents_slab);
} }
struct commit_list *get_saved_parents(struct rev_info *revs, const struct commit *commit) struct commit_list *get_saved_parents(struct rev_info *revs, const struct commit *commit)

View File

@ -732,6 +732,7 @@ static int cmd_reconfigure(int argc, const char **argv)
succeeded = 1; succeeded = 1;
the_repository = old_repo; the_repository = old_repo;
repo_clear(&r);
if (toggle_maintenance(1) >= 0) if (toggle_maintenance(1) >= 0)
succeeded = 1; succeeded = 1;

View File

@ -143,6 +143,7 @@ static void run_shell(void)
} }
free(argv); free(argv);
free(split_args);
free(rawargs); free(rawargs);
} while (!done); } while (!done);
} }
@ -216,9 +217,8 @@ int cmd_main(int argc, const char **argv)
count = split_cmdline(prog, &user_argv); count = split_cmdline(prog, &user_argv);
if (count >= 0) { if (count >= 0) {
if (is_valid_cmd_name(user_argv[0])) { if (is_valid_cmd_name(user_argv[0])) {
prog = make_cmd(user_argv[0]); char *cmd = make_cmd(user_argv[0]);
user_argv[0] = prog; execv(cmd, (char *const *) user_argv);
execv(user_argv[0], (char *const *) user_argv);
} }
free(prog); free(prog);
free(user_argv); free(user_argv);

View File

@ -901,8 +901,9 @@ static void traverse_tree_submodules(struct repository *r,
struct submodule_tree_entry *st_entry; struct submodule_tree_entry *st_entry;
struct name_entry name_entry; struct name_entry name_entry;
char *tree_path = NULL; char *tree_path = NULL;
char *tree_buf;
fill_tree_descriptor(r, &tree, treeish_name); tree_buf = fill_tree_descriptor(r, &tree, treeish_name);
while (tree_entry(&tree, &name_entry)) { while (tree_entry(&tree, &name_entry)) {
if (prefix) if (prefix)
tree_path = tree_path =
@ -930,6 +931,8 @@ static void traverse_tree_submodules(struct repository *r,
&name_entry.oid, out); &name_entry.oid, out);
free(tree_path); free(tree_path);
} }
free(tree_buf);
} }
void submodules_of_tree(struct repository *r, void submodules_of_tree(struct repository *r,
@ -943,6 +946,16 @@ void submodules_of_tree(struct repository *r,
traverse_tree_submodules(r, treeish_name, NULL, treeish_name, out); traverse_tree_submodules(r, treeish_name, NULL, treeish_name, out);
} }
void submodule_entry_list_release(struct submodule_entry_list *list)
{
for (size_t i = 0; i < list->entry_nr; i++) {
free(list->entries[i].name_entry);
repo_clear(list->entries[i].repo);
free(list->entries[i].repo);
}
free(list->entries);
}
void submodule_free(struct repository *r) void submodule_free(struct repository *r)
{ {
if (r->submodule_cache) if (r->submodule_cache)

View File

@ -136,4 +136,7 @@ struct submodule_entry_list {
void submodules_of_tree(struct repository *r, void submodules_of_tree(struct repository *r,
const struct object_id *treeish_name, const struct object_id *treeish_name,
struct submodule_entry_list *ret); struct submodule_entry_list *ret);
void submodule_entry_list_release(struct submodule_entry_list *list);
#endif /* SUBMODULE_CONFIG_H */ #endif /* SUBMODULE_CONFIG_H */

View File

@ -26,6 +26,8 @@ static void object_info(const char *gitdir, const char *oid_hex)
if (oid_object_info_extended(&r, &oid, &oi, 0)) if (oid_object_info_extended(&r, &oid, &oi, 0))
die("could not obtain object info"); die("could not obtain object info");
printf("%d\n", (int) size); printf("%d\n", (int) size);
repo_clear(&r);
} }
int cmd__partial_clone(int argc, const char **argv) int cmd__partial_clone(int argc, const char **argv)

View File

@ -196,5 +196,12 @@ int cmd__proc_receive(int argc, const char **argv)
packet_flush(1); packet_flush(1);
sigchain_pop(SIGPIPE); sigchain_pop(SIGPIPE);
while (commands) {
struct command *next = commands->next;
free(commands);
commands = next;
}
string_list_clear(&push_options, 0);
return 0; return 0;
} }

View File

@ -2,6 +2,7 @@
test_description='partial clone' test_description='partial clone'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
. "$TEST_DIRECTORY"/lib-terminal.sh . "$TEST_DIRECTORY"/lib-terminal.sh

View File

@ -5,6 +5,7 @@ test_description='compare full workdir to sparse workdir'
GIT_TEST_SPLIT_INDEX=0 GIT_TEST_SPLIT_INDEX=0
GIT_TEST_SPARSE_INDEX= GIT_TEST_SPARSE_INDEX=
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
test_expect_success 'setup' ' test_expect_success 'setup' '

View File

@ -5,6 +5,7 @@ test_description='git branch submodule tests'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
. "$TEST_DIRECTORY"/lib-rebase.sh . "$TEST_DIRECTORY"/lib-rebase.sh

View File

@ -7,6 +7,7 @@ This test runs git rebase and tests the subtree strategy.
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
. "$TEST_DIRECTORY"/lib-rebase.sh . "$TEST_DIRECTORY"/lib-rebase.sh

View File

@ -5,6 +5,7 @@
test_description='test {cherry-pick,revert} --[no-]gpg-sign' test_description='test {cherry-pick,revert} --[no-]gpg-sign'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
. "$TEST_DIRECTORY/lib-gpg.sh" . "$TEST_DIRECTORY/lib-gpg.sh"

View File

@ -2,6 +2,7 @@
test_description='stash --pathspec-from-file' test_description='stash --pathspec-from-file'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
test_tick test_tick

View File

@ -34,6 +34,7 @@ relationship between packs and objects is as follows:
Px2 | s s s x x x Px2 | s s s x x x
' '
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
main_repo=main.git main_repo=main.git

View File

@ -2,6 +2,7 @@
test_description='exercise basic multi-pack bitmap functionality (.rev files)' test_description='exercise basic multi-pack bitmap functionality (.rev files)'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
. "${TEST_DIRECTORY}/lib-bitmap.sh" . "${TEST_DIRECTORY}/lib-bitmap.sh"

View File

@ -4,6 +4,7 @@ test_description='pseudo-merge bitmaps'
GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0 GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
test_pseudo_merges () { test_pseudo_merges () {

View File

@ -1,6 +1,8 @@
#!/bin/sh #!/bin/sh
test_description='incremental multi-pack-index' test_description='incremental multi-pack-index'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
. "$TEST_DIRECTORY"/lib-midx.sh . "$TEST_DIRECTORY"/lib-midx.sh

View File

@ -8,6 +8,7 @@ test_description='Test proc-receive hook'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
. "$TEST_DIRECTORY"/t5411/common-functions.sh . "$TEST_DIRECTORY"/t5411/common-functions.sh

View File

@ -8,6 +8,7 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB=1 GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB=1
export GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB export GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
mk_repo_pair () { mk_repo_pair () {

View File

@ -7,6 +7,7 @@ TEST_NO_CREATE_REPO=1
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
# Test protocol v2 with 'file://' transport # Test protocol v2 with 'file://' transport

View File

@ -7,6 +7,7 @@ TEST_NO_CREATE_REPO=1
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
# Test protocol v2 with 'git://' transport # Test protocol v2 with 'git://' transport

View File

@ -7,6 +7,7 @@ TEST_NO_CREATE_REPO=1
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
# Test protocol v2 with 'http://' transport # Test protocol v2 with 'http://' transport

View File

@ -5,6 +5,7 @@ test_description='merge simplification'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
note () { note () {

View File

@ -10,6 +10,7 @@ test_description='--graph and simplified history'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
. "$TEST_DIRECTORY"/lib-log-graph.sh . "$TEST_DIRECTORY"/lib-log-graph.sh

View File

@ -4,6 +4,7 @@ test_description='git filter-branch'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
. "$TEST_DIRECTORY/lib-gpg.sh" . "$TEST_DIRECTORY/lib-gpg.sh"

View File

@ -5,6 +5,7 @@ GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_CREATE_REPO_NO_TEMPLATE=1 TEST_CREATE_REPO_NO_TEMPLATE=1
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
PROG='git annotate' PROG='git annotate'

View File

@ -2,6 +2,7 @@
test_description='test the `scalar` command' test_description='test the `scalar` command'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
GIT_TEST_MAINT_SCHEDULER="crontab:test-tool crontab cron.txt,launchctl:true,schtasks:true" GIT_TEST_MAINT_SCHEDULER="crontab:test-tool crontab cron.txt,launchctl:true,schtasks:true"

View File

@ -2,6 +2,7 @@
test_description='test the `scalar clone` subcommand' test_description='test the `scalar clone` subcommand'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
. "${TEST_DIRECTORY}/lib-terminal.sh" . "${TEST_DIRECTORY}/lib-terminal.sh"

View File

@ -7,6 +7,7 @@ test_description='git fast-export'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
test_expect_success 'setup' ' test_expect_success 'setup' '

View File

@ -11,6 +11,7 @@ cvs CLI client via git-cvsserver server'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
if ! test_have_prereq PERL; then if ! test_have_prereq PERL; then

View File

@ -8,6 +8,7 @@ tags, branches and other git refspecs'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
######### #########

View File

@ -1,6 +1,8 @@
#!/bin/sh #!/bin/sh
test_description='git shell tests' test_description='git shell tests'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh . ./test-lib.sh
test_expect_success 'shell allows upload-pack' ' test_expect_success 'shell allows upload-pack' '

View File

@ -717,6 +717,7 @@ static int add_file_to_list(const struct object_id *oid,
static void wt_status_collect_changes_initial(struct wt_status *s) static void wt_status_collect_changes_initial(struct wt_status *s)
{ {
struct index_state *istate = s->repo->index; struct index_state *istate = s->repo->index;
struct strbuf base = STRBUF_INIT;
int i; int i;
for (i = 0; i < istate->cache_nr; i++) { for (i = 0; i < istate->cache_nr; i++) {
@ -735,7 +736,6 @@ static void wt_status_collect_changes_initial(struct wt_status *s)
* expanding the trees to find the elements that are new in this * expanding the trees to find the elements that are new in this
* tree and marking them with DIFF_STATUS_ADDED. * tree and marking them with DIFF_STATUS_ADDED.
*/ */
struct strbuf base = STRBUF_INIT;
struct pathspec ps = { 0 }; struct pathspec ps = { 0 };
struct tree *tree = lookup_tree(istate->repo, &ce->oid); struct tree *tree = lookup_tree(istate->repo, &ce->oid);
@ -743,9 +743,11 @@ static void wt_status_collect_changes_initial(struct wt_status *s)
ps.has_wildcard = 1; ps.has_wildcard = 1;
ps.max_depth = -1; ps.max_depth = -1;
strbuf_reset(&base);
strbuf_add(&base, ce->name, ce->ce_namelen); strbuf_add(&base, ce->name, ce->ce_namelen);
read_tree_at(istate->repo, tree, &base, 0, &ps, read_tree_at(istate->repo, tree, &base, 0, &ps,
add_file_to_list, s); add_file_to_list, s);
continue; continue;
} }
@ -772,6 +774,8 @@ static void wt_status_collect_changes_initial(struct wt_status *s)
s->committable = 1; s->committable = 1;
} }
} }
strbuf_release(&base);
} }
static void wt_status_collect_untracked(struct wt_status *s) static void wt_status_collect_untracked(struct wt_status *s)