Skip to content

Commit e47dbec

Browse files
committed
Merge branch 'ma/unpack-trees-free-msgs'
Leak plugging. * ma/unpack-trees-free-msgs: unpack_trees_options: free messages when done argv-array: return the pushed string from argv_push*() merge-recursive: provide pair of `unpack_trees_{start,finish}()` merge: setup `opts` later in `checkout_fast_forward()`
2 parents 9472b13 + 1c41d28 commit e47dbec

File tree

7 files changed

+64
-37
lines changed

7 files changed

+64
-37
lines changed

argv-array.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,13 @@ static void argv_array_push_nodup(struct argv_array *array, const char *value)
2121
array->argv[array->argc] = NULL;
2222
}
2323

24-
void argv_array_push(struct argv_array *array, const char *value)
24+
const char *argv_array_push(struct argv_array *array, const char *value)
2525
{
2626
argv_array_push_nodup(array, xstrdup(value));
27+
return array->argv[array->argc - 1];
2728
}
2829

29-
void argv_array_pushf(struct argv_array *array, const char *fmt, ...)
30+
const char *argv_array_pushf(struct argv_array *array, const char *fmt, ...)
3031
{
3132
va_list ap;
3233
struct strbuf v = STRBUF_INIT;
@@ -36,6 +37,7 @@ void argv_array_pushf(struct argv_array *array, const char *fmt, ...)
3637
va_end(ap);
3738

3839
argv_array_push_nodup(array, strbuf_detach(&v, NULL));
40+
return array->argv[array->argc - 1];
3941
}
4042

4143
void argv_array_pushl(struct argv_array *array, ...)

argv-array.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ struct argv_array {
1212
#define ARGV_ARRAY_INIT { empty_argv, 0, 0 }
1313

1414
void argv_array_init(struct argv_array *);
15-
void argv_array_push(struct argv_array *, const char *);
15+
const char *argv_array_push(struct argv_array *, const char *);
1616
__attribute__((format (printf,2,3)))
17-
void argv_array_pushf(struct argv_array *, const char *fmt, ...);
17+
const char *argv_array_pushf(struct argv_array *, const char *fmt, ...);
1818
LAST_ARG_MUST_BE_NULL
1919
void argv_array_pushl(struct argv_array *, ...);
2020
void argv_array_pushv(struct argv_array *, const char **);

builtin/checkout.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,7 @@ static int merge_working_tree(const struct checkout_opts *opts,
527527
init_tree_desc(&trees[1], tree->buffer, tree->size);
528528

529529
ret = unpack_trees(2, trees, &topts);
530+
clear_unpack_trees_porcelain(&topts);
530531
if (ret == -1) {
531532
/*
532533
* Unpack couldn't do a trivial merge; either

merge-recursive.c

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -338,10 +338,10 @@ static void init_tree_desc_from_tree(struct tree_desc *desc, struct tree *tree)
338338
init_tree_desc(desc, tree->buffer, tree->size);
339339
}
340340

341-
static int git_merge_trees(struct merge_options *o,
342-
struct tree *common,
343-
struct tree *head,
344-
struct tree *merge)
341+
static int unpack_trees_start(struct merge_options *o,
342+
struct tree *common,
343+
struct tree *head,
344+
struct tree *merge)
345345
{
346346
int rc;
347347
struct tree_desc t[3];
@@ -380,6 +380,12 @@ static int git_merge_trees(struct merge_options *o,
380380
return rc;
381381
}
382382

383+
static void unpack_trees_finish(struct merge_options *o)
384+
{
385+
discard_index(&o->orig_index);
386+
clear_unpack_trees_porcelain(&o->unpack_opts);
387+
}
388+
383389
struct tree *write_tree_from_memory(struct merge_options *o)
384390
{
385391
struct tree *result = NULL;
@@ -3267,13 +3273,14 @@ int merge_trees(struct merge_options *o,
32673273
return 1;
32683274
}
32693275

3270-
code = git_merge_trees(o, common, head, merge);
3276+
code = unpack_trees_start(o, common, head, merge);
32713277

32723278
if (code != 0) {
32733279
if (show(o, 4) || o->call_depth)
32743280
err(o, _("merging of trees %s and %s failed"),
32753281
oid_to_hex(&head->object.oid),
32763282
oid_to_hex(&merge->object.oid));
3283+
unpack_trees_finish(o);
32773284
return -1;
32783285
}
32793286

@@ -3326,20 +3333,15 @@ int merge_trees(struct merge_options *o,
33263333

33273334
hashmap_free(&o->current_file_dir_set, 1);
33283335

3329-
if (clean < 0)
3336+
if (clean < 0) {
3337+
unpack_trees_finish(o);
33303338
return clean;
3339+
}
33313340
}
33323341
else
33333342
clean = 1;
33343343

3335-
/* Free the extra index left from git_merge_trees() */
3336-
/*
3337-
* FIXME: Need to also free data allocated by
3338-
* setup_unpack_trees_porcelain() tucked away in o->unpack_opts.msgs,
3339-
* but the problem is that only half of it refers to dynamically
3340-
* allocated data, while the other half points at static strings.
3341-
*/
3342-
discard_index(&o->orig_index);
3344+
unpack_trees_finish(o);
33433345

33443346
if (o->call_depth && !(*result = write_tree_from_memory(o)))
33453347
return -1;

merge.c

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,24 @@ int checkout_fast_forward(const struct object_id *head,
9191
return -1;
9292

9393
memset(&trees, 0, sizeof(trees));
94-
memset(&opts, 0, sizeof(opts));
9594
memset(&t, 0, sizeof(t));
95+
96+
trees[nr_trees] = parse_tree_indirect(head);
97+
if (!trees[nr_trees++]) {
98+
rollback_lock_file(&lock_file);
99+
return -1;
100+
}
101+
trees[nr_trees] = parse_tree_indirect(remote);
102+
if (!trees[nr_trees++]) {
103+
rollback_lock_file(&lock_file);
104+
return -1;
105+
}
106+
for (i = 0; i < nr_trees; i++) {
107+
parse_tree(trees[i]);
108+
init_tree_desc(t+i, trees[i]->buffer, trees[i]->size);
109+
}
110+
111+
memset(&opts, 0, sizeof(opts));
96112
if (overwrite_ignore) {
97113
memset(&dir, 0, sizeof(dir));
98114
dir.flags |= DIR_SHOW_IGNORED;
@@ -109,24 +125,13 @@ int checkout_fast_forward(const struct object_id *head,
109125
opts.fn = twoway_merge;
110126
setup_unpack_trees_porcelain(&opts, "merge");
111127

112-
trees[nr_trees] = parse_tree_indirect(head);
113-
if (!trees[nr_trees++]) {
114-
rollback_lock_file(&lock_file);
115-
return -1;
116-
}
117-
trees[nr_trees] = parse_tree_indirect(remote);
118-
if (!trees[nr_trees++]) {
119-
rollback_lock_file(&lock_file);
120-
return -1;
121-
}
122-
for (i = 0; i < nr_trees; i++) {
123-
parse_tree(trees[i]);
124-
init_tree_desc(t+i, trees[i]->buffer, trees[i]->size);
125-
}
126128
if (unpack_trees(nr_trees, t, &opts)) {
127129
rollback_lock_file(&lock_file);
130+
clear_unpack_trees_porcelain(&opts);
128131
return -1;
129132
}
133+
clear_unpack_trees_porcelain(&opts);
134+
130135
if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
131136
return error(_("unable to write new index file"));
132137
return 0;

unpack-trees.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#define NO_THE_INDEX_COMPATIBILITY_MACROS
22
#include "cache.h"
3+
#include "argv-array.h"
34
#include "repository.h"
45
#include "config.h"
56
#include "dir.h"
@@ -103,6 +104,8 @@ void setup_unpack_trees_porcelain(struct unpack_trees_options *opts,
103104
const char **msgs = opts->msgs;
104105
const char *msg;
105106

107+
argv_array_init(&opts->msgs_to_free);
108+
106109
if (!strcmp(cmd, "checkout"))
107110
msg = advice_commit_before_merge
108111
? _("Your local changes to the following files would be overwritten by checkout:\n%%s"
@@ -119,7 +122,7 @@ void setup_unpack_trees_porcelain(struct unpack_trees_options *opts,
119122
"Please commit your changes or stash them before you %s.")
120123
: _("Your local changes to the following files would be overwritten by %s:\n%%s");
121124
msgs[ERROR_WOULD_OVERWRITE] = msgs[ERROR_NOT_UPTODATE_FILE] =
122-
xstrfmt(msg, cmd, cmd);
125+
argv_array_pushf(&opts->msgs_to_free, msg, cmd, cmd);
123126

124127
msgs[ERROR_NOT_UPTODATE_DIR] =
125128
_("Updating the following directories would lose untracked files in them:\n%s");
@@ -139,7 +142,8 @@ void setup_unpack_trees_porcelain(struct unpack_trees_options *opts,
139142
? _("The following untracked working tree files would be removed by %s:\n%%s"
140143
"Please move or remove them before you %s.")
141144
: _("The following untracked working tree files would be removed by %s:\n%%s");
142-
msgs[ERROR_WOULD_LOSE_UNTRACKED_REMOVED] = xstrfmt(msg, cmd, cmd);
145+
msgs[ERROR_WOULD_LOSE_UNTRACKED_REMOVED] =
146+
argv_array_pushf(&opts->msgs_to_free, msg, cmd, cmd);
143147

144148
if (!strcmp(cmd, "checkout"))
145149
msg = advice_commit_before_merge
@@ -156,7 +160,8 @@ void setup_unpack_trees_porcelain(struct unpack_trees_options *opts,
156160
? _("The following untracked working tree files would be overwritten by %s:\n%%s"
157161
"Please move or remove them before you %s.")
158162
: _("The following untracked working tree files would be overwritten by %s:\n%%s");
159-
msgs[ERROR_WOULD_LOSE_UNTRACKED_OVERWRITTEN] = xstrfmt(msg, cmd, cmd);
163+
msgs[ERROR_WOULD_LOSE_UNTRACKED_OVERWRITTEN] =
164+
argv_array_pushf(&opts->msgs_to_free, msg, cmd, cmd);
160165

161166
/*
162167
* Special case: ERROR_BIND_OVERLAP refers to a pair of paths, we
@@ -179,6 +184,12 @@ void setup_unpack_trees_porcelain(struct unpack_trees_options *opts,
179184
opts->unpack_rejects[i].strdup_strings = 1;
180185
}
181186

187+
void clear_unpack_trees_porcelain(struct unpack_trees_options *opts)
188+
{
189+
argv_array_clear(&opts->msgs_to_free);
190+
memset(opts->msgs, 0, sizeof(opts->msgs));
191+
}
192+
182193
static int do_add_entry(struct unpack_trees_options *o, struct cache_entry *ce,
183194
unsigned int set, unsigned int clear)
184195
{

unpack-trees.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#define UNPACK_TREES_H
33

44
#include "tree-walk.h"
5-
#include "string-list.h"
5+
#include "argv-array.h"
66

77
#define MAX_UNPACK_TREES 8
88

@@ -33,6 +33,11 @@ enum unpack_trees_error_types {
3333
void setup_unpack_trees_porcelain(struct unpack_trees_options *opts,
3434
const char *cmd);
3535

36+
/*
37+
* Frees resources allocated by setup_unpack_trees_porcelain().
38+
*/
39+
void clear_unpack_trees_porcelain(struct unpack_trees_options *opts);
40+
3641
struct unpack_trees_options {
3742
unsigned int reset,
3843
merge,
@@ -57,6 +62,7 @@ struct unpack_trees_options {
5762
struct pathspec *pathspec;
5863
merge_fn_t fn;
5964
const char *msgs[NB_UNPACK_TREES_ERROR_TYPES];
65+
struct argv_array msgs_to_free;
6066
/*
6167
* Store error messages in an array, each case
6268
* corresponding to a error message type

0 commit comments

Comments
 (0)