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()`
This commit is contained in:
commit
e47dbece39
@ -21,12 +21,13 @@ static void argv_array_push_nodup(struct argv_array *array, const char *value)
|
||||
array->argv[array->argc] = NULL;
|
||||
}
|
||||
|
||||
void argv_array_push(struct argv_array *array, const char *value)
|
||||
const char *argv_array_push(struct argv_array *array, const char *value)
|
||||
{
|
||||
argv_array_push_nodup(array, xstrdup(value));
|
||||
return array->argv[array->argc - 1];
|
||||
}
|
||||
|
||||
void argv_array_pushf(struct argv_array *array, const char *fmt, ...)
|
||||
const char *argv_array_pushf(struct argv_array *array, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
struct strbuf v = STRBUF_INIT;
|
||||
@ -36,6 +37,7 @@ void argv_array_pushf(struct argv_array *array, const char *fmt, ...)
|
||||
va_end(ap);
|
||||
|
||||
argv_array_push_nodup(array, strbuf_detach(&v, NULL));
|
||||
return array->argv[array->argc - 1];
|
||||
}
|
||||
|
||||
void argv_array_pushl(struct argv_array *array, ...)
|
||||
|
@ -12,9 +12,9 @@ struct argv_array {
|
||||
#define ARGV_ARRAY_INIT { empty_argv, 0, 0 }
|
||||
|
||||
void argv_array_init(struct argv_array *);
|
||||
void argv_array_push(struct argv_array *, const char *);
|
||||
const char *argv_array_push(struct argv_array *, const char *);
|
||||
__attribute__((format (printf,2,3)))
|
||||
void argv_array_pushf(struct argv_array *, const char *fmt, ...);
|
||||
const char *argv_array_pushf(struct argv_array *, const char *fmt, ...);
|
||||
LAST_ARG_MUST_BE_NULL
|
||||
void argv_array_pushl(struct argv_array *, ...);
|
||||
void argv_array_pushv(struct argv_array *, const char **);
|
||||
|
@ -527,6 +527,7 @@ static int merge_working_tree(const struct checkout_opts *opts,
|
||||
init_tree_desc(&trees[1], tree->buffer, tree->size);
|
||||
|
||||
ret = unpack_trees(2, trees, &topts);
|
||||
clear_unpack_trees_porcelain(&topts);
|
||||
if (ret == -1) {
|
||||
/*
|
||||
* Unpack couldn't do a trivial merge; either
|
||||
|
@ -338,10 +338,10 @@ static void init_tree_desc_from_tree(struct tree_desc *desc, struct tree *tree)
|
||||
init_tree_desc(desc, tree->buffer, tree->size);
|
||||
}
|
||||
|
||||
static int git_merge_trees(struct merge_options *o,
|
||||
struct tree *common,
|
||||
struct tree *head,
|
||||
struct tree *merge)
|
||||
static int unpack_trees_start(struct merge_options *o,
|
||||
struct tree *common,
|
||||
struct tree *head,
|
||||
struct tree *merge)
|
||||
{
|
||||
int rc;
|
||||
struct tree_desc t[3];
|
||||
@ -380,6 +380,12 @@ static int git_merge_trees(struct merge_options *o,
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void unpack_trees_finish(struct merge_options *o)
|
||||
{
|
||||
discard_index(&o->orig_index);
|
||||
clear_unpack_trees_porcelain(&o->unpack_opts);
|
||||
}
|
||||
|
||||
struct tree *write_tree_from_memory(struct merge_options *o)
|
||||
{
|
||||
struct tree *result = NULL;
|
||||
@ -3267,13 +3273,14 @@ int merge_trees(struct merge_options *o,
|
||||
return 1;
|
||||
}
|
||||
|
||||
code = git_merge_trees(o, common, head, merge);
|
||||
code = unpack_trees_start(o, common, head, merge);
|
||||
|
||||
if (code != 0) {
|
||||
if (show(o, 4) || o->call_depth)
|
||||
err(o, _("merging of trees %s and %s failed"),
|
||||
oid_to_hex(&head->object.oid),
|
||||
oid_to_hex(&merge->object.oid));
|
||||
unpack_trees_finish(o);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -3326,20 +3333,15 @@ cleanup:
|
||||
|
||||
hashmap_free(&o->current_file_dir_set, 1);
|
||||
|
||||
if (clean < 0)
|
||||
if (clean < 0) {
|
||||
unpack_trees_finish(o);
|
||||
return clean;
|
||||
}
|
||||
}
|
||||
else
|
||||
clean = 1;
|
||||
|
||||
/* Free the extra index left from git_merge_trees() */
|
||||
/*
|
||||
* FIXME: Need to also free data allocated by
|
||||
* setup_unpack_trees_porcelain() tucked away in o->unpack_opts.msgs,
|
||||
* but the problem is that only half of it refers to dynamically
|
||||
* allocated data, while the other half points at static strings.
|
||||
*/
|
||||
discard_index(&o->orig_index);
|
||||
unpack_trees_finish(o);
|
||||
|
||||
if (o->call_depth && !(*result = write_tree_from_memory(o)))
|
||||
return -1;
|
||||
|
35
merge.c
35
merge.c
@ -91,8 +91,24 @@ int checkout_fast_forward(const struct object_id *head,
|
||||
return -1;
|
||||
|
||||
memset(&trees, 0, sizeof(trees));
|
||||
memset(&opts, 0, sizeof(opts));
|
||||
memset(&t, 0, sizeof(t));
|
||||
|
||||
trees[nr_trees] = parse_tree_indirect(head);
|
||||
if (!trees[nr_trees++]) {
|
||||
rollback_lock_file(&lock_file);
|
||||
return -1;
|
||||
}
|
||||
trees[nr_trees] = parse_tree_indirect(remote);
|
||||
if (!trees[nr_trees++]) {
|
||||
rollback_lock_file(&lock_file);
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < nr_trees; i++) {
|
||||
parse_tree(trees[i]);
|
||||
init_tree_desc(t+i, trees[i]->buffer, trees[i]->size);
|
||||
}
|
||||
|
||||
memset(&opts, 0, sizeof(opts));
|
||||
if (overwrite_ignore) {
|
||||
memset(&dir, 0, sizeof(dir));
|
||||
dir.flags |= DIR_SHOW_IGNORED;
|
||||
@ -109,24 +125,13 @@ int checkout_fast_forward(const struct object_id *head,
|
||||
opts.fn = twoway_merge;
|
||||
setup_unpack_trees_porcelain(&opts, "merge");
|
||||
|
||||
trees[nr_trees] = parse_tree_indirect(head);
|
||||
if (!trees[nr_trees++]) {
|
||||
rollback_lock_file(&lock_file);
|
||||
return -1;
|
||||
}
|
||||
trees[nr_trees] = parse_tree_indirect(remote);
|
||||
if (!trees[nr_trees++]) {
|
||||
rollback_lock_file(&lock_file);
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < nr_trees; i++) {
|
||||
parse_tree(trees[i]);
|
||||
init_tree_desc(t+i, trees[i]->buffer, trees[i]->size);
|
||||
}
|
||||
if (unpack_trees(nr_trees, t, &opts)) {
|
||||
rollback_lock_file(&lock_file);
|
||||
clear_unpack_trees_porcelain(&opts);
|
||||
return -1;
|
||||
}
|
||||
clear_unpack_trees_porcelain(&opts);
|
||||
|
||||
if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
|
||||
return error(_("unable to write new index file"));
|
||||
return 0;
|
||||
|
@ -1,5 +1,6 @@
|
||||
#define NO_THE_INDEX_COMPATIBILITY_MACROS
|
||||
#include "cache.h"
|
||||
#include "argv-array.h"
|
||||
#include "repository.h"
|
||||
#include "config.h"
|
||||
#include "dir.h"
|
||||
@ -103,6 +104,8 @@ void setup_unpack_trees_porcelain(struct unpack_trees_options *opts,
|
||||
const char **msgs = opts->msgs;
|
||||
const char *msg;
|
||||
|
||||
argv_array_init(&opts->msgs_to_free);
|
||||
|
||||
if (!strcmp(cmd, "checkout"))
|
||||
msg = advice_commit_before_merge
|
||||
? _("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,
|
||||
"Please commit your changes or stash them before you %s.")
|
||||
: _("Your local changes to the following files would be overwritten by %s:\n%%s");
|
||||
msgs[ERROR_WOULD_OVERWRITE] = msgs[ERROR_NOT_UPTODATE_FILE] =
|
||||
xstrfmt(msg, cmd, cmd);
|
||||
argv_array_pushf(&opts->msgs_to_free, msg, cmd, cmd);
|
||||
|
||||
msgs[ERROR_NOT_UPTODATE_DIR] =
|
||||
_("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,
|
||||
? _("The following untracked working tree files would be removed by %s:\n%%s"
|
||||
"Please move or remove them before you %s.")
|
||||
: _("The following untracked working tree files would be removed by %s:\n%%s");
|
||||
msgs[ERROR_WOULD_LOSE_UNTRACKED_REMOVED] = xstrfmt(msg, cmd, cmd);
|
||||
msgs[ERROR_WOULD_LOSE_UNTRACKED_REMOVED] =
|
||||
argv_array_pushf(&opts->msgs_to_free, msg, cmd, cmd);
|
||||
|
||||
if (!strcmp(cmd, "checkout"))
|
||||
msg = advice_commit_before_merge
|
||||
@ -156,7 +160,8 @@ void setup_unpack_trees_porcelain(struct unpack_trees_options *opts,
|
||||
? _("The following untracked working tree files would be overwritten by %s:\n%%s"
|
||||
"Please move or remove them before you %s.")
|
||||
: _("The following untracked working tree files would be overwritten by %s:\n%%s");
|
||||
msgs[ERROR_WOULD_LOSE_UNTRACKED_OVERWRITTEN] = xstrfmt(msg, cmd, cmd);
|
||||
msgs[ERROR_WOULD_LOSE_UNTRACKED_OVERWRITTEN] =
|
||||
argv_array_pushf(&opts->msgs_to_free, msg, cmd, cmd);
|
||||
|
||||
/*
|
||||
* 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,
|
||||
opts->unpack_rejects[i].strdup_strings = 1;
|
||||
}
|
||||
|
||||
void clear_unpack_trees_porcelain(struct unpack_trees_options *opts)
|
||||
{
|
||||
argv_array_clear(&opts->msgs_to_free);
|
||||
memset(opts->msgs, 0, sizeof(opts->msgs));
|
||||
}
|
||||
|
||||
static int do_add_entry(struct unpack_trees_options *o, struct cache_entry *ce,
|
||||
unsigned int set, unsigned int clear)
|
||||
{
|
||||
|
@ -2,7 +2,7 @@
|
||||
#define UNPACK_TREES_H
|
||||
|
||||
#include "tree-walk.h"
|
||||
#include "string-list.h"
|
||||
#include "argv-array.h"
|
||||
|
||||
#define MAX_UNPACK_TREES 8
|
||||
|
||||
@ -33,6 +33,11 @@ enum unpack_trees_error_types {
|
||||
void setup_unpack_trees_porcelain(struct unpack_trees_options *opts,
|
||||
const char *cmd);
|
||||
|
||||
/*
|
||||
* Frees resources allocated by setup_unpack_trees_porcelain().
|
||||
*/
|
||||
void clear_unpack_trees_porcelain(struct unpack_trees_options *opts);
|
||||
|
||||
struct unpack_trees_options {
|
||||
unsigned int reset,
|
||||
merge,
|
||||
@ -57,6 +62,7 @@ struct unpack_trees_options {
|
||||
struct pathspec *pathspec;
|
||||
merge_fn_t fn;
|
||||
const char *msgs[NB_UNPACK_TREES_ERROR_TYPES];
|
||||
struct argv_array msgs_to_free;
|
||||
/*
|
||||
* Store error messages in an array, each case
|
||||
* corresponding to a error message type
|
||||
|
Loading…
Reference in New Issue
Block a user