Merge branch 'ps/leakfixes-part-3'

More leakfixes.

* ps/leakfixes-part-3: (24 commits)
  commit-reach: fix trivial memory leak when computing reachability
  convert: fix leaking config strings
  entry: fix leaking pathnames during delayed checkout
  object-name: fix leaking commit list items
  t/test-repository: fix leaking repository
  builtin/credential-cache: fix trivial leaks
  builtin/worktree: fix leaking derived branch names
  builtin/shortlog: fix various trivial memory leaks
  builtin/rerere: fix various trivial memory leaks
  builtin/credential-store: fix leaking credential
  builtin/show-branch: fix several memory leaks
  builtin/rev-parse: fix memory leak with `--parseopt`
  builtin/stash: fix various trivial memory leaks
  builtin/remote: fix various trivial memory leaks
  builtin/remote: fix leaking strings in `branch_list`
  builtin/ls-remote: fix leaking `pattern` strings
  builtin/submodule--helper: fix leaking buffer in `is_tip_reachable`
  builtin/submodule--helper: fix leaking clone depth parameter
  builtin/name-rev: fix various trivial memory leaks
  builtin/describe: fix trivial memory leak when describing blob
  ...
This commit is contained in:
Junio C Hamano
2024-08-14 14:54:47 -07:00
57 changed files with 256 additions and 88 deletions

View File

@ -88,6 +88,8 @@ static void spawn_daemon(const char *socket)
die_errno("unable to read result code from cache daemon");
if (r != 3 || memcmp(buf, "ok\n", 3))
die("cache daemon did not start: %.*s", r, buf);
child_process_clear(&daemon);
close(daemon.out);
}
@ -137,7 +139,8 @@ static void announce_capabilities(void)
int cmd_credential_cache(int argc, const char **argv, const char *prefix)
{
char *socket_path = NULL;
const char *socket_path_arg = NULL;
char *socket_path;
int timeout = 900;
const char *op;
const char * const usage[] = {
@ -147,7 +150,7 @@ int cmd_credential_cache(int argc, const char **argv, const char *prefix)
struct option options[] = {
OPT_INTEGER(0, "timeout", &timeout,
"number of seconds to cache credentials"),
OPT_STRING(0, "socket", &socket_path, "path",
OPT_STRING(0, "socket", &socket_path_arg, "path",
"path of cache-daemon socket"),
OPT_END()
};
@ -160,6 +163,7 @@ int cmd_credential_cache(int argc, const char **argv, const char *prefix)
if (!have_unix_sockets())
die(_("credential-cache unavailable; no unix socket support"));
socket_path = xstrdup_or_null(socket_path_arg);
if (!socket_path)
socket_path = get_socket_path();
if (!socket_path)
@ -176,6 +180,7 @@ int cmd_credential_cache(int argc, const char **argv, const char *prefix)
else
; /* ignore unknown operation */
free(socket_path);
return 0;
}

View File

@ -218,5 +218,6 @@ int cmd_credential_store(int argc, const char **argv, const char *prefix)
; /* Ignore unknown operation. */
string_list_clear(&fns, 0);
credential_clear(&c);
return 0;
}

View File

@ -529,6 +529,7 @@ static void describe_blob(struct object_id oid, struct strbuf *dst)
traverse_commit_list(&revs, process_commit, process_object, &pcd);
reset_revision_walk();
release_revisions(&revs);
strvec_clear(&args);
}
static void describe(const char *arg, int last_one)
@ -619,6 +620,8 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
if (contains) {
struct string_list_item *item;
struct strvec args;
const char **argv_copy;
int ret;
strvec_init(&args);
strvec_pushl(&args, "name-rev",
@ -637,7 +640,21 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
strvec_pushv(&args, argv);
else
strvec_push(&args, "HEAD");
return cmd_name_rev(args.nr, args.v, prefix);
/*
* `cmd_name_rev()` modifies the array, so we'd leak its
* contained strings if we didn't do a copy here.
*/
ALLOC_ARRAY(argv_copy, args.nr + 1);
for (size_t i = 0; i < args.nr; i++)
argv_copy[i] = args.v[i];
argv_copy[args.nr] = NULL;
ret = cmd_name_rev(args.nr, argv_copy, prefix);
strvec_clear(&args);
free(argv_copy);
return ret;
}
hashmap_init(&names, commit_name_neq, NULL, 0);
@ -679,7 +696,6 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
} else if (dirty) {
struct lock_file index_lock = LOCK_INIT;
struct rev_info revs;
struct strvec args = STRVEC_INIT;
int fd;
setup_work_tree();
@ -694,8 +710,9 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
repo_update_index_if_able(the_repository, &index_lock);
repo_init_revisions(the_repository, &revs, prefix);
strvec_pushv(&args, diff_index_args);
if (setup_revisions(args.nr, args.v, &revs, NULL) != 1)
if (setup_revisions(ARRAY_SIZE(diff_index_args) - 1,
diff_index_args, &revs, NULL) != 1)
BUG("malformed internal diff-index command line");
run_diff_index(&revs, 0);

View File

@ -1434,6 +1434,7 @@ static void make_cover_letter(struct rev_info *rev, int use_separate_file,
int need_8bit_cte = 0;
struct pretty_print_context pp = {0};
struct commit *head = list[0];
char *to_free = NULL;
if (!cmit_fmt_is_mail(rev->commit_format))
die(_("cover letter needs email format"));
@ -1455,7 +1456,7 @@ static void make_cover_letter(struct rev_info *rev, int use_separate_file,
}
if (!branch_name)
branch_name = find_branch_name(rev);
branch_name = to_free = find_branch_name(rev);
pp.fmt = CMIT_FMT_EMAIL;
pp.date_mode.type = DATE_RFC2822;
@ -1466,6 +1467,7 @@ static void make_cover_letter(struct rev_info *rev, int use_separate_file,
encoding, need_8bit_cte, cfg);
fprintf(rev->diffopt.file, "%s\n", sb.buf);
free(to_free);
free(pp.after_subject);
strbuf_release(&sb);

View File

@ -19,17 +19,16 @@ static const char * const ls_remote_usage[] = {
* Is there one among the list of patterns that match the tail part
* of the path?
*/
static int tail_match(const char **pattern, const char *path)
static int tail_match(const struct strvec *pattern, const char *path)
{
const char *p;
char *pathbuf;
if (!pattern)
if (!pattern->nr)
return 1; /* no restriction */
pathbuf = xstrfmt("/%s", path);
while ((p = *(pattern++)) != NULL) {
if (!wildmatch(p, pathbuf, 0)) {
for (size_t i = 0; i < pattern->nr; i++) {
if (!wildmatch(pattern->v[i], pathbuf, 0)) {
free(pathbuf);
return 1;
}
@ -47,7 +46,7 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
int status = 0;
int show_symref_target = 0;
const char *uploadpack = NULL;
const char **pattern = NULL;
struct strvec pattern = STRVEC_INIT;
struct transport_ls_refs_options transport_options =
TRANSPORT_LS_REFS_OPTIONS_INIT;
int i;
@ -93,13 +92,8 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
packet_trace_identity("ls-remote");
if (argc > 1) {
int i;
CALLOC_ARRAY(pattern, argc);
for (i = 1; i < argc; i++) {
pattern[i - 1] = xstrfmt("*/%s", argv[i]);
}
}
for (int i = 1; i < argc; i++)
strvec_pushf(&pattern, "*/%s", argv[i]);
if (flags & REF_TAGS)
strvec_push(&transport_options.ref_prefixes, "refs/tags/");
@ -136,7 +130,7 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
struct ref_array_item *item;
if (!check_ref_type(ref, flags))
continue;
if (!tail_match(pattern, ref->name))
if (!tail_match(&pattern, ref->name))
continue;
item = ref_array_push(&ref_array, ref->name, &ref->old_oid);
item->symref = xstrdup_or_null(ref->symref);
@ -158,5 +152,7 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
if (transport_disconnect(transport))
status = 1;
transport_ls_refs_options_release(&transport_options);
strvec_clear(&pattern);
return status;
}

View File

@ -677,7 +677,9 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
always, allow_undefined, data.name_only);
}
UNLEAK(string_pool);
UNLEAK(revs);
string_list_clear(&data.ref_filters, 0);
string_list_clear(&data.exclude_filters, 0);
mem_pool_discard(&string_pool, 0);
object_array_clear(&revs);
return 0;
}

View File

@ -258,7 +258,7 @@ struct branch_info {
char *push_remote_name;
};
static struct string_list branch_list = STRING_LIST_INIT_NODUP;
static struct string_list branch_list = STRING_LIST_INIT_DUP;
static const char *abbrev_ref(const char *name, const char *prefix)
{
@ -292,8 +292,8 @@ static int config_read_branches(const char *key, const char *value,
type = PUSH_REMOTE;
else
return 0;
name = xmemdupz(key, key_len);
name = xmemdupz(key, key_len);
item = string_list_insert(&branch_list, name);
if (!item->util)
@ -337,6 +337,7 @@ static int config_read_branches(const char *key, const char *value,
BUG("unexpected type=%d", type);
}
free(name);
return 0;
}
@ -554,13 +555,16 @@ static int add_branch_for_removal(const char *refname,
refspec.dst = (char *)refname;
if (remote_find_tracking(branches->remote, &refspec))
return 0;
free(refspec.src);
/* don't delete a branch if another remote also uses it */
for (kr = branches->keep->list; kr; kr = kr->next) {
memset(&refspec, 0, sizeof(refspec));
refspec.dst = (char *)refname;
if (!remote_find_tracking(kr->remote, &refspec))
if (!remote_find_tracking(kr->remote, &refspec)) {
free(refspec.src);
return 0;
}
}
/* don't delete non-remote-tracking refs */
@ -667,7 +671,11 @@ static int config_read_push_default(const char *key, const char *value,
static void handle_push_default(const char* old_name, const char* new_name)
{
struct push_default_info push_default = {
old_name, CONFIG_SCOPE_UNKNOWN, STRBUF_INIT, -1 };
.old_name = old_name,
.scope = CONFIG_SCOPE_UNKNOWN,
.origin = STRBUF_INIT,
.linenr = -1,
};
git_config(config_read_push_default, &push_default);
if (push_default.scope >= CONFIG_SCOPE_COMMAND)
; /* pass */
@ -687,6 +695,8 @@ static void handle_push_default(const char* old_name, const char* new_name)
push_default.origin.buf, push_default.linenr,
old_name);
}
strbuf_release(&push_default.origin);
}
@ -784,7 +794,7 @@ static int mv(int argc, const char **argv, const char *prefix)
}
if (!refspec_updated)
return 0;
goto out;
/*
* First remove symrefs, then rename the rest, finally create
@ -850,10 +860,15 @@ static int mv(int argc, const char **argv, const char *prefix)
display_progress(progress, ++refs_renamed_nr);
}
stop_progress(&progress);
string_list_clear(&remote_branches, 1);
handle_push_default(rename.old_name, rename.new_name);
out:
string_list_clear(&remote_branches, 1);
strbuf_release(&old_remote_context);
strbuf_release(&buf);
strbuf_release(&buf2);
strbuf_release(&buf3);
return 0;
}
@ -944,12 +959,21 @@ static int rm(int argc, const char **argv, const char *prefix)
if (!result) {
strbuf_addf(&buf, "remote.%s", remote->name);
if (git_config_rename_section(buf.buf, NULL) < 1)
return error(_("Could not remove config section '%s'"), buf.buf);
if (git_config_rename_section(buf.buf, NULL) < 1) {
result = error(_("Could not remove config section '%s'"), buf.buf);
goto out;
}
handle_push_default(remote->name, NULL);
}
out:
for (struct known_remote *r = known_remotes.list; r;) {
struct known_remote *next = r->next;
free(r);
r = next;
}
strbuf_release(&buf);
return result;
}
@ -982,8 +1006,10 @@ static int append_ref_to_tracked_list(const char *refname,
memset(&refspec, 0, sizeof(refspec));
refspec.dst = (char *)refname;
if (!remote_find_tracking(states->remote, &refspec))
if (!remote_find_tracking(states->remote, &refspec)) {
string_list_append(&states->tracked, abbrev_branch(refspec.src));
free(refspec.src);
}
return 0;
}

View File

@ -151,7 +151,7 @@ static void get_ref_information(struct rev_cmdline_info *cmd_info,
static void determine_replay_mode(struct rev_cmdline_info *cmd_info,
const char *onto_name,
const char **advance_name,
char **advance_name,
struct commit **onto,
struct strset **update_refs)
{
@ -174,6 +174,7 @@ static void determine_replay_mode(struct rev_cmdline_info *cmd_info,
*onto = peel_committish(*advance_name);
if (repo_dwim_ref(the_repository, *advance_name, strlen(*advance_name),
&oid, &fullname, 0) == 1) {
free(*advance_name);
*advance_name = fullname;
} else {
die(_("argument to --advance must be a reference"));
@ -197,6 +198,7 @@ static void determine_replay_mode(struct rev_cmdline_info *cmd_info,
if (negative_refs_complete) {
struct hashmap_iter iter;
struct strmap_entry *entry;
const char *last_key = NULL;
if (rinfo.negative_refexprs == 0)
die(_("all positive revisions given must be references"));
@ -208,8 +210,11 @@ static void determine_replay_mode(struct rev_cmdline_info *cmd_info,
/* Only one entry, but we have to loop to get it */
strset_for_each_entry(&rinfo.negative_refs,
&iter, entry) {
*advance_name = entry->key;
last_key = entry->key;
}
free(*advance_name);
*advance_name = xstrdup_or_null(last_key);
} else { /* positive_refs_complete */
if (rinfo.negative_refexprs > 1)
die(_("cannot implicitly determine correct base for --onto"));
@ -271,7 +276,8 @@ static struct commit *pick_regular_commit(struct commit *pickme,
int cmd_replay(int argc, const char **argv, const char *prefix)
{
const char *advance_name = NULL;
const char *advance_name_opt = NULL;
char *advance_name = NULL;
struct commit *onto = NULL;
const char *onto_name = NULL;
int contained = 0;
@ -292,7 +298,7 @@ int cmd_replay(int argc, const char **argv, const char *prefix)
NULL
};
struct option replay_options[] = {
OPT_STRING(0, "advance", &advance_name,
OPT_STRING(0, "advance", &advance_name_opt,
N_("branch"),
N_("make replay advance given branch")),
OPT_STRING(0, "onto", &onto_name,
@ -306,14 +312,15 @@ int cmd_replay(int argc, const char **argv, const char *prefix)
argc = parse_options(argc, argv, prefix, replay_options, replay_usage,
PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN_OPT);
if (!onto_name && !advance_name) {
if (!onto_name && !advance_name_opt) {
error(_("option --onto or --advance is mandatory"));
usage_with_options(replay_usage, replay_options);
}
if (advance_name && contained)
if (advance_name_opt && contained)
die(_("options '%s' and '%s' cannot be used together"),
"--advance", "--contained");
advance_name = xstrdup_or_null(advance_name_opt);
repo_init_revisions(the_repository, &revs, prefix);
@ -441,6 +448,7 @@ int cmd_replay(int argc, const char **argv, const char *prefix)
cleanup:
release_revisions(&revs);
free(advance_name);
/* Return */
if (ret < 0)

View File

@ -73,11 +73,17 @@ int cmd_rerere(int argc, const char **argv, const char *prefix)
if (!strcmp(argv[0], "forget")) {
struct pathspec pathspec;
int ret;
if (argc < 2)
warning(_("'git rerere forget' without paths is deprecated"));
parse_pathspec(&pathspec, 0, PATHSPEC_PREFER_CWD,
prefix, argv + 1);
return rerere_forget(the_repository, &pathspec);
ret = rerere_forget(the_repository, &pathspec);
clear_pathspec(&pathspec);
return ret;
}
if (!strcmp(argv[0], "clear")) {

View File

@ -553,7 +553,10 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
strbuf_release(&sb);
strvec_clear(&longnames);
strvec_clear(&usage);
free((char *) opts->help);
for (size_t i = 0; i < opts_nr; i++) {
free((char *) opts[i].help);
free((char *) opts[i].argh);
}
free(opts);
return 0;
}

View File

@ -514,4 +514,5 @@ void shortlog_output(struct shortlog *log)
string_list_clear(&log->list, 1);
clear_mailmap(&log->mailmap);
string_list_clear(&log->format, 0);
string_list_clear(&log->trailers, 0);
}

View File

@ -502,14 +502,14 @@ static int rev_is_head(const char *head, const char *name)
return !strcmp(head, name);
}
static int show_merge_base(struct commit_list *seen, int num_rev)
static int show_merge_base(const struct commit_list *seen, int num_rev)
{
int all_mask = ((1u << (REV_SHIFT + num_rev)) - 1);
int all_revs = all_mask & ~((1u << REV_SHIFT) - 1);
int exit_status = 1;
while (seen) {
struct commit *commit = pop_commit(&seen);
for (const struct commit_list *s = seen; s; s = s->next) {
struct commit *commit = s->item;
int flags = commit->object.flags & all_mask;
if (!(flags & UNINTERESTING) &&
((flags & all_revs) == all_revs)) {
@ -635,7 +635,7 @@ static int parse_reflog_param(const struct option *opt, const char *arg,
int cmd_show_branch(int ac, const char **av, const char *prefix)
{
struct commit *rev[MAX_REVS], *commit;
char *reflog_msg[MAX_REVS];
char *reflog_msg[MAX_REVS] = {0};
struct commit_list *list = NULL, *seen = NULL;
unsigned int rev_mask[MAX_REVS];
int num_rev, i, extra = 0;
@ -692,6 +692,8 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
parse_reflog_param),
OPT_END()
};
const char **args_copy = NULL;
int ret;
init_commit_name_slab(&name_slab);
@ -699,8 +701,9 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
/* If nothing is specified, try the default first */
if (ac == 1 && default_args.nr) {
DUP_ARRAY(args_copy, default_args.v, default_args.nr);
ac = default_args.nr;
av = default_args.v;
av = args_copy;
}
ac = parse_options(ac, av, prefix, builtin_show_branch_options,
@ -780,7 +783,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
}
for (i = 0; i < reflog; i++) {
char *logmsg;
char *logmsg = NULL;
char *nth_desc;
const char *msg;
char *end;
@ -790,6 +793,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
if (read_ref_at(get_main_ref_store(the_repository),
ref, flags, 0, base + i, &oid, &logmsg,
&timestamp, &tz, NULL)) {
free(logmsg);
reflog = i;
break;
}
@ -842,7 +846,8 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
if (!ref_name_cnt) {
fprintf(stderr, "No revs to be shown.\n");
exit(0);
ret = 0;
goto out;
}
for (num_rev = 0; ref_name[num_rev]; num_rev++) {
@ -879,11 +884,15 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
commit_list_sort_by_date(&seen);
if (merge_base)
return show_merge_base(seen, num_rev);
if (merge_base) {
ret = show_merge_base(seen, num_rev);
goto out;
}
if (independent)
return show_independent(rev, num_rev, rev_mask);
if (independent) {
ret = show_independent(rev, num_rev, rev_mask);
goto out;
}
/* Show list; --more=-1 means list-only */
if (1 < num_rev || extra < 0) {
@ -919,8 +928,10 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
putchar('\n');
}
}
if (extra < 0)
exit(0);
if (extra < 0) {
ret = 0;
goto out;
}
/* Sort topologically */
sort_in_topological_order(&seen, sort_order);
@ -932,8 +943,8 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
all_mask = ((1u << (REV_SHIFT + num_rev)) - 1);
all_revs = all_mask & ~((1u << REV_SHIFT) - 1);
while (seen) {
struct commit *commit = pop_commit(&seen);
for (struct commit_list *l = seen; l; l = l->next) {
struct commit *commit = l->item;
int this_flag = commit->object.flags;
int is_merge_point = ((this_flag & all_revs) == all_revs);
@ -973,6 +984,15 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
if (shown_merge_point && --extra < 0)
break;
}
ret = 0;
out:
for (size_t i = 0; i < ARRAY_SIZE(reflog_msg); i++)
free(reflog_msg[i]);
free_commit_list(seen);
free_commit_list(list);
free(args_copy);
free(head);
return 0;
return ret;
}

View File

@ -1521,6 +1521,7 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
struct strbuf patch = STRBUF_INIT;
struct strbuf stash_msg_buf = STRBUF_INIT;
struct strbuf untracked_files = STRBUF_INIT;
struct strbuf out = STRBUF_INIT;
if (patch_mode && keep_index == -1)
keep_index = 1;
@ -1626,7 +1627,6 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
struct child_process cp_add = CHILD_PROCESS_INIT;
struct child_process cp_diff = CHILD_PROCESS_INIT;
struct child_process cp_apply = CHILD_PROCESS_INIT;
struct strbuf out = STRBUF_INIT;
cp_add.git_cmd = 1;
strvec_push(&cp_add.args, "add");
@ -1718,6 +1718,7 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
done:
strbuf_release(&patch);
strbuf_release(&out);
free_stash_info(&info);
strbuf_release(&stash_msg_buf);
strbuf_release(&untracked_files);
@ -1869,6 +1870,8 @@ int cmd_stash(int argc, const char **argv, const char *prefix)
OPT_SUBCOMMAND_F("save", &fn, save_stash, PARSE_OPT_NOCOMPLETE),
OPT_END()
};
const char **args_copy;
int ret;
git_config(git_stash_config, NULL);
@ -1892,5 +1895,16 @@ int cmd_stash(int argc, const char **argv, const char *prefix)
/* Assume 'stash push' */
strvec_push(&args, "push");
strvec_pushv(&args, argv);
return !!push_stash(args.nr, args.v, prefix, 1);
/*
* `push_stash()` ends up modifying the array, which causes memory
* leaks if we didn't copy the array here.
*/
DUP_ARRAY(args_copy, args.v, args.nr);
ret = !!push_stash(args.nr, args_copy, prefix, 1);
strvec_clear(&args);
free(args_copy);
return ret;
}

View File

@ -1530,7 +1530,7 @@ struct module_clone_data {
const char *path;
const char *name;
const char *url;
const char *depth;
int depth;
struct list_objects_filter_options *filter_options;
unsigned int quiet: 1;
unsigned int progress: 1;
@ -1729,8 +1729,8 @@ static int clone_submodule(const struct module_clone_data *clone_data,
strvec_push(&cp.args, "--quiet");
if (clone_data->progress)
strvec_push(&cp.args, "--progress");
if (clone_data->depth && *(clone_data->depth))
strvec_pushl(&cp.args, "--depth", clone_data->depth, NULL);
if (clone_data->depth > 0)
strvec_pushf(&cp.args, "--depth=%d", clone_data->depth);
if (reference->nr) {
struct string_list_item *item;
@ -1851,8 +1851,7 @@ static int module_clone(int argc, const char **argv, const char *prefix)
N_("reference repository")),
OPT_BOOL(0, "dissociate", &dissociate,
N_("use --reference only while cloning")),
OPT_STRING(0, "depth", &clone_data.depth,
N_("string"),
OPT_INTEGER(0, "depth", &clone_data.depth,
N_("depth for shallow clones")),
OPT__QUIET(&quiet, "suppress output for cloning a submodule"),
OPT_BOOL(0, "progress", &progress,
@ -2269,6 +2268,7 @@ static int is_tip_reachable(const char *path, const struct object_id *oid)
struct child_process cp = CHILD_PROCESS_INIT;
struct strbuf rev = STRBUF_INIT;
char *hex = oid_to_hex(oid);
int reachable;
cp.git_cmd = 1;
cp.dir = path;
@ -2278,9 +2278,12 @@ static int is_tip_reachable(const char *path, const struct object_id *oid)
prepare_submodule_repo_env(&cp.env);
if (capture_command(&cp, &rev, GIT_MAX_HEXSZ + 1) || rev.len)
return 0;
reachable = 0;
else
reachable = 1;
return 1;
strbuf_release(&rev);
return reachable;
}
static int fetch_in_submodule(const char *module_path, int depth, int quiet,
@ -3200,7 +3203,7 @@ static int add_submodule(const struct add_data *add_data)
}
clone_data.dissociate = add_data->dissociate;
if (add_data->depth >= 0)
clone_data.depth = xstrfmt("%d", add_data->depth);
clone_data.depth = add_data->depth;
if (clone_submodule(&clone_data, &reference))
goto cleanup;
@ -3223,6 +3226,7 @@ static int add_submodule(const struct add_data *add_data)
die(_("unable to checkout submodule '%s'"), add_data->sm_path);
}
ret = 0;
cleanup:
string_list_clear(&reference, 1);
return ret;

View File

@ -769,7 +769,7 @@ static int add(int ac, const char **av, const char *prefix)
char *branch_to_free = NULL;
char *new_branch_to_free = NULL;
const char *new_branch = NULL;
const char *opt_track = NULL;
char *opt_track = NULL;
const char *lock_reason = NULL;
int keep_locked = 0;
int used_new_branch_options;
@ -846,7 +846,7 @@ static int add(int ac, const char **av, const char *prefix)
if (opts.orphan && !new_branch) {
int n;
const char *s = worktree_basename(path, &n);
new_branch = xstrndup(s, n);
new_branch = new_branch_to_free = xstrndup(s, n);
} else if (opts.orphan) {
; /* no-op */
} else if (opts.detach) {
@ -875,7 +875,7 @@ static int add(int ac, const char **av, const char *prefix)
remote = unique_tracking_name(branch, &oid, NULL);
if (remote) {
new_branch = branch;
branch = remote;
branch = new_branch_to_free = remote;
}
}
@ -923,6 +923,7 @@ static int add(int ac, const char **av, const char *prefix)
ret = add_worktree(path, branch, &opts);
free(path);
free(opt_track);
free(branch_to_free);
free(new_branch_to_free);
return ret;

View File

@ -1227,4 +1227,5 @@ void tips_reachable_from_bases(struct repository *r,
done:
free(commits);
repo_clear_commit_marks(r, SEEN);
free_commit_list(stack);
}

View File

@ -963,7 +963,7 @@ int async_query_available_blobs(const char *cmd, struct string_list *available_p
while ((line = packet_read_line(process->out, NULL))) {
const char *path;
if (skip_prefix(line, "pathname=", &path))
string_list_insert(available_paths, xstrdup(path));
string_list_insert(available_paths, path);
else
; /* ignore unknown keys */
}
@ -1053,14 +1053,20 @@ static int read_convert_config(const char *var, const char *value,
* The command-line will not be interpolated in any way.
*/
if (!strcmp("smudge", key))
if (!strcmp("smudge", key)) {
FREE_AND_NULL(drv->smudge);
return git_config_string(&drv->smudge, var, value);
}
if (!strcmp("clean", key))
if (!strcmp("clean", key)) {
FREE_AND_NULL(drv->clean);
return git_config_string(&drv->clean, var, value);
}
if (!strcmp("process", key))
if (!strcmp("process", key)) {
FREE_AND_NULL(drv->process);
return git_config_string(&drv->process, var, value);
}
if (!strcmp("required", key)) {
drv->required = git_config_bool(var, value);

View File

@ -191,7 +191,7 @@ int finish_delayed_checkout(struct checkout *state, int show_progress)
progress = start_delayed_progress(_("Filtering content"), dco->paths.nr);
while (dco->filters.nr > 0) {
for_each_string_list_item(filter, &dco->filters) {
struct string_list available_paths = STRING_LIST_INIT_NODUP;
struct string_list available_paths = STRING_LIST_INIT_DUP;
if (!async_query_available_blobs(filter->string, &available_paths)) {
/* Filter reported an error */
@ -245,6 +245,8 @@ int finish_delayed_checkout(struct checkout *state, int show_progress)
} else
errs = 1;
}
string_list_clear(&available_paths, 0);
}
filter_string_list(&dco->filters, 0, string_is_not_null, NULL);

View File

@ -27,7 +27,8 @@
#include "date.h"
#include "object-file-convert.h"
static int get_oid_oneline(struct repository *r, const char *, struct object_id *, struct commit_list *);
static int get_oid_oneline(struct repository *r, const char *, struct object_id *,
const struct commit_list *);
typedef int (*disambiguate_hint_fn)(struct repository *, const struct object_id *, void *);
@ -1254,6 +1255,8 @@ static int peel_onion(struct repository *r, const char *name, int len,
prefix = xstrndup(sp + 1, name + len - 1 - (sp + 1));
commit_list_insert((struct commit *)o, &list);
ret = get_oid_oneline(r, prefix, oid, list);
free_commit_list(list);
free(prefix);
return ret;
}
@ -1388,9 +1391,10 @@ static int handle_one_ref(const char *path, const struct object_id *oid,
static int get_oid_oneline(struct repository *r,
const char *prefix, struct object_id *oid,
struct commit_list *list)
const struct commit_list *list)
{
struct commit_list *backup = NULL, *l;
struct commit_list *copy = NULL;
const struct commit_list *l;
int found = 0;
int negative = 0;
regex_t regex;
@ -1411,14 +1415,14 @@ static int get_oid_oneline(struct repository *r,
for (l = list; l; l = l->next) {
l->item->object.flags |= ONELINE_SEEN;
commit_list_insert(l->item, &backup);
commit_list_insert(l->item, &copy);
}
while (list) {
while (copy) {
const char *p, *buf;
struct commit *commit;
int matches;
commit = pop_most_recent_commit(&list, ONELINE_SEEN);
commit = pop_most_recent_commit(&copy, ONELINE_SEEN);
if (!parse_object(r, &commit->object.oid))
continue;
buf = repo_get_commit_buffer(r, commit, NULL);
@ -1433,10 +1437,9 @@ static int get_oid_oneline(struct repository *r,
}
}
regfree(&regex);
free_commit_list(list);
for (l = backup; l; l = l->next)
for (l = list; l; l = l->next)
clear_commit_marks(l->item, ONELINE_SEEN);
free_commit_list(backup);
free_commit_list(copy);
return found ? 0 : -1;
}
@ -2024,7 +2027,10 @@ static enum get_oid_result get_oid_with_context_1(struct repository *repo,
refs_for_each_ref(get_main_ref_store(repo), handle_one_ref, &cb);
refs_head_ref(get_main_ref_store(repo), handle_one_ref, &cb);
commit_list_sort_by_date(&list);
return get_oid_oneline(repo, name + 2, oid, list);
ret = get_oid_oneline(repo, name + 2, oid, list);
free_commit_list(list);
return ret;
}
if (namelen < 3 ||
name[2] != ':' ||

View File

@ -1107,7 +1107,7 @@ fail_exit:
int rerere_forget(struct repository *r, struct pathspec *pathspec)
{
int i, fd;
int i, fd, ret;
struct string_list conflict = STRING_LIST_INIT_DUP;
struct string_list merge_rr = STRING_LIST_INIT_DUP;
@ -1132,7 +1132,12 @@ int rerere_forget(struct repository *r, struct pathspec *pathspec)
continue;
rerere_forget_one_path(r->index, it->string, &merge_rr);
}
return write_rr(&merge_rr, fd);
ret = write_rr(&merge_rr, fd);
string_list_clear(&conflict, 0);
string_list_clear(&merge_rr, 1);
return ret;
}
/*

View File

@ -19,7 +19,7 @@ static void test_parse_commit_in_graph(const char *gitdir, const char *worktree,
setup_git_env(gitdir);
memset(the_repository, 0, sizeof(*the_repository));
repo_clear(the_repository);
if (repo_init(&r, gitdir, worktree))
die("Couldn't init repo");
@ -49,7 +49,7 @@ static void test_get_commit_tree_in_graph(const char *gitdir,
setup_git_env(gitdir);
memset(the_repository, 0, sizeof(*the_repository));
repo_clear(the_repository);
if (repo_init(&r, gitdir, worktree))
die("Couldn't init repo");

View File

@ -5,6 +5,7 @@ test_description='blob conversion via gitattributes'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-terminal.sh

View File

@ -1,6 +1,8 @@
#!/bin/sh
test_description='credential-cache tests'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-credential.sh

View File

@ -1,6 +1,8 @@
#!/bin/sh
test_description='credential-store tests'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-credential.sh

View File

@ -29,6 +29,7 @@ you can set GIT_TEST_CREDENTIAL_HELPER_SETUP to a sequence of shell
commands.
'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-credential.sh

View File

@ -1,6 +1,8 @@
#!/bin/sh
test_description='test git rev-parse --parseopt'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
check_invalid_long_option () {

View File

@ -5,6 +5,7 @@ test_description='tests for ref^{stuff}'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '

View File

@ -5,6 +5,7 @@ test_description='undoing resolution'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
check_resolve_undo () {

View File

@ -8,6 +8,7 @@ working tree.
'
TEST_NO_CREATE_REPO=1
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY/lib-parallel-checkout.sh"

View File

@ -10,6 +10,7 @@ properly (without access to the index or attribute stack).
'
TEST_NO_CREATE_REPO=1
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY/lib-parallel-checkout.sh"
. "$TEST_DIRECTORY/lib-encoding.sh"

View File

@ -6,6 +6,7 @@ GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_CREATE_REPO_NO_TEMPLATE=1
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-rebase.sh

View File

@ -2,6 +2,7 @@
test_description='Test handling of the current working directory becoming empty'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '

View File

@ -2,6 +2,7 @@
test_description='branch --contains <commit>, --no-contains <commit> --merged, and --no-merged'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '

View File

@ -2,6 +2,7 @@
test_description='test show-branch'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'error descriptions on empty repository' '

View File

@ -5,6 +5,7 @@ test_description='range-diff tests'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# Note that because of the range-diff's heuristics, test_commit does more

View File

@ -5,6 +5,7 @@ test_description='basic git replay tests'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
GIT_AUTHOR_NAME=author@name

View File

@ -8,6 +8,7 @@ test_description='Test git stash'
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-unique-files.sh

View File

@ -1,6 +1,8 @@
#!/bin/sh
test_description='stash -p'
TEST_PASSES_SANITIZE_LEAK=true
. ./lib-patch-mode.sh
test_expect_success 'setup' '

View File

@ -5,6 +5,7 @@
test_description='Test git stash --include-untracked'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'stash save --include-untracked some dirty working directory' '

View File

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

View File

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

View File

@ -1,6 +1,8 @@
#!/bin/sh
test_description='commit graph'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-chunk.sh

View File

@ -5,6 +5,7 @@ test_description='git ls-remote'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
generate_references () {

View File

@ -5,6 +5,7 @@ test_description='fetch --all works correctly'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
setup_repository () {

View File

@ -5,6 +5,7 @@ test_description='pulling into void'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
modify () {

View File

@ -4,6 +4,7 @@ test_description='check various push.default settings'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup bare remotes' '

View File

@ -2,6 +2,7 @@
test_description='avoiding conflicting update through symref aliasing'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '

View File

@ -5,6 +5,7 @@ test_description='pushing to a repository using the atomic push option'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
mk_repo_pair () {

View File

@ -4,6 +4,7 @@ test_description='test fetching over git protocol'
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-git-daemon.sh

View File

@ -5,6 +5,7 @@ test_description='test git rev-list --cherry-pick -- file'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# A---B---D---F

View File

@ -6,6 +6,7 @@
test_description='Merge base and parent list computation.
'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
M=1130000000

View File

@ -14,6 +14,7 @@ test_description='test describe'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
check_describe () {

View File

@ -1,6 +1,8 @@
#!/bin/sh
test_description='test dwim of revs versus pathspecs in revision parser'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '

View File

@ -4,6 +4,7 @@ test_description='git status --porcelain=v2
This test exercises porcelain V2 output for git status.'
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh

View File

@ -12,6 +12,7 @@ subcommands of git submodule.
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup - enable local submodules' '

View File

@ -16,6 +16,7 @@ test_untraceable=UnfortunatelyYes
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./lib-bash.sh
complete ()

View File

@ -8,6 +8,7 @@ test_description='test git-specific bash prompt functions'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./lib-bash.sh
. "$GIT_BUILD_DIR/contrib/completion/git-prompt.sh"