Skip to content

Commit

Permalink
unpack-trees.[ch]: embed "dir" in "struct unpack_trees_options"
Browse files Browse the repository at this point in the history
Change the "struct dir" in "struct unpack_trees_options" away from a
pointer to being embedded in the struct itself, this mean that we can
initialize it with our new UNPACK_TREES_OPTIONS_INIT macro.

As it turned out nothing actually needed to provide its own "struct
dir" to this API, there's another patch to "hide" the struct instead,
see the discussion at [1], but I think just allocating it on the stack
along with the rest makes more sense.

This fixes a memory leak in "builtin/checkout.c" that's been there
since the clear_unpack_trees_porcelain() function was added in
1c41d28 (unpack_trees_options: free messages when done,
2018-05-21), i.e. we still had a memory leak from allocating the "dir"
member here. That "dir" member had in turn been with us ever since
782c2d6 (Build in checkout, 2008-02-07).

This fixes that memory leak, and allows us to remove the boilerplate
dir_clear() elsewhere in favor of just using
clear_unpack_trees_porcelain().

1. https://lore.kernel.org/git/87ilyjviiy.fsf@evledraar.gmail.com/

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
  • Loading branch information
avar committed Oct 1, 2021
1 parent 22652c0 commit 6461d6a
Show file tree
Hide file tree
Showing 6 changed files with 20 additions and 30 deletions.
5 changes: 2 additions & 3 deletions builtin/checkout.c
Original file line number Diff line number Diff line change
Expand Up @@ -745,9 +745,8 @@ static int merge_working_tree(const struct checkout_opts *opts,
&new_branch_info->commit->object.oid :
&new_branch_info->oid, NULL);
if (opts->overwrite_ignore) {
topts.dir = xcalloc(1, sizeof(*topts.dir));
topts.dir->flags |= DIR_SHOW_IGNORED;
setup_standard_excludes(topts.dir);
topts.dir.flags |= DIR_SHOW_IGNORED;
setup_standard_excludes(&topts.dir);
}
tree = parse_tree_indirect(old_branch_info->commit ?
&old_branch_info->commit->object.oid :
Expand Down
11 changes: 4 additions & 7 deletions builtin/read-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,20 +53,17 @@ static int index_output_cb(const struct option *opt, const char *arg,
static int exclude_per_directory_cb(const struct option *opt, const char *arg,
int unset)
{
struct dir_struct *dir;
struct unpack_trees_options *opts;

BUG_ON_OPT_NEG(unset);

opts = (struct unpack_trees_options *)opt->value;

if (opts->dir)
if (opts->dir.exclude_per_dir)
die("more than one --exclude-per-directory given.");

dir = xcalloc(1, sizeof(*opts->dir));
dir->flags |= DIR_SHOW_IGNORED;
dir->exclude_per_dir = arg;
opts->dir = dir;
opts->dir.flags |= DIR_SHOW_IGNORED;
opts->dir.exclude_per_dir = arg;
/* We do not need to nor want to do read-directory
* here; we are merely interested in reusing the
* per directory ignore stack mechanism.
Expand Down Expand Up @@ -208,7 +205,7 @@ int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix)
if ((opts.update || opts.index_only) && !opts.merge)
die("%s is meaningless without -m, --reset, or --prefix",
opts.update ? "-u" : "-i");
if ((opts.dir && !opts.update))
if ((opts.dir.exclude_per_dir && !opts.update))
die("--exclude-per-directory is meaningless unless -u");
if (opts.merge && !opts.index_only)
setup_work_tree();
Expand Down
7 changes: 2 additions & 5 deletions merge-ort.c
Original file line number Diff line number Diff line change
Expand Up @@ -4045,9 +4045,8 @@ static int checkout(struct merge_options *opt,
unpack_opts.verbose_update = (opt->verbosity > 2);
unpack_opts.fn = twoway_merge;
if (1/* FIXME: opts->overwrite_ignore*/) {
CALLOC_ARRAY(unpack_opts.dir, 1);
unpack_opts.dir->flags |= DIR_SHOW_IGNORED;
setup_standard_excludes(unpack_opts.dir);
unpack_opts.dir.flags |= DIR_SHOW_IGNORED;
setup_standard_excludes(&unpack_opts.dir);
}
parse_tree(prev);
init_tree_desc(&trees[0], prev->buffer, prev->size);
Expand All @@ -4056,8 +4055,6 @@ static int checkout(struct merge_options *opt,

ret = unpack_trees(2, trees, &unpack_opts);
clear_unpack_trees_porcelain(&unpack_opts);
dir_clear(unpack_opts.dir);
FREE_AND_NULL(unpack_opts.dir);
return ret;
}

Expand Down
10 changes: 3 additions & 7 deletions merge.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,9 @@ int checkout_fast_forward(struct repository *r,
int overwrite_ignore)
{
struct tree *trees[MAX_UNPACK_TREES];
struct unpack_trees_options opts;
struct unpack_trees_options opts = UNPACK_TREES_OPTIONS_INIT;
struct tree_desc t[MAX_UNPACK_TREES];
int i, nr_trees = 0;
struct dir_struct dir = DIR_INIT;
struct lock_file lock_file = LOCK_INIT;

refresh_index(r->index, REFRESH_QUIET, NULL, NULL, NULL);
Expand All @@ -79,11 +78,9 @@ int checkout_fast_forward(struct repository *r,
init_tree_desc(t+i, trees[i]->buffer, trees[i]->size);
}

memset(&opts, 0, sizeof(opts));
if (overwrite_ignore) {
dir.flags |= DIR_SHOW_IGNORED;
setup_standard_excludes(&dir);
opts.dir = &dir;
opts.dir.flags |= DIR_SHOW_IGNORED;
setup_standard_excludes(&opts.dir);
}

opts.head_idx = 1;
Expand All @@ -101,7 +98,6 @@ int checkout_fast_forward(struct repository *r,
clear_unpack_trees_porcelain(&opts);
return -1;
}
dir_clear(&dir);
clear_unpack_trees_porcelain(&opts);

if (write_locked_index(r->index, &lock_file, COMMIT_LOCK))
Expand Down
10 changes: 4 additions & 6 deletions unpack-trees.c
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ void setup_unpack_trees_porcelain(struct unpack_trees_options *opts,
void clear_unpack_trees_porcelain(struct unpack_trees_options *opts)
{
strvec_clear(&opts->msgs_to_free);
dir_clear(&opts->dir);
memset(opts->msgs, 0, sizeof(opts->msgs));
}

Expand Down Expand Up @@ -2081,7 +2082,7 @@ static int verify_clean_subdirectory(const struct cache_entry *ce,
*/
int namelen;
int i;
struct dir_struct d;
struct dir_struct d = DIR_INIT;
char *pathbuf;
int cnt = 0;

Expand Down Expand Up @@ -2132,9 +2133,7 @@ static int verify_clean_subdirectory(const struct cache_entry *ce,
*/
pathbuf = xstrfmt("%.*s/", namelen, ce->name);

memset(&d, 0, sizeof(d));
if (o->dir)
d.exclude_per_dir = o->dir->exclude_per_dir;
d.exclude_per_dir = o->dir.exclude_per_dir;
i = read_directory(&d, o->src_index, pathbuf, namelen+1, NULL);
if (i)
return add_rejected_path(o, ERROR_NOT_UPTODATE_DIR, ce->name);
Expand Down Expand Up @@ -2175,8 +2174,7 @@ static int check_ok_to_remove(const char *name, int len, int dtype,
if (ignore_case && icase_exists(o, name, len, st))
return 0;

if (o->dir &&
is_excluded(o->dir, o->src_index, name, &dtype))
if (is_excluded(&o->dir, o->src_index, name, &dtype))
/*
* ce->name is explicitly excluded, so it is Ok to
* overwrite it.
Expand Down
7 changes: 5 additions & 2 deletions unpack-trees.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "strvec.h"
#include "string-list.h"
#include "tree-walk.h"
#include "dir.h"

#define MAX_UNPACK_TREES MAX_TRAVERSE_TREES

Expand Down Expand Up @@ -66,7 +67,7 @@ struct unpack_trees_options {
dry_run;
const char *prefix;
int cache_bottom;
struct dir_struct *dir;
struct dir_struct dir;
struct pathspec *pathspec;
merge_fn_t fn;
const char *msgs[NB_UNPACK_TREES_WARNING_TYPES];
Expand All @@ -90,7 +91,9 @@ struct unpack_trees_options {
struct pattern_list *pl; /* for internal use */
struct checkout_metadata meta;
};
#define UNPACK_TREES_OPTIONS_INIT { 0 }
#define UNPACK_TREES_OPTIONS_INIT { \
.dir = DIR_INIT, \
}

int unpack_trees(unsigned n, struct tree_desc *t,
struct unpack_trees_options *options);
Expand Down

0 comments on commit 6461d6a

Please sign in to comment.