unsigned processed:1;
};
-struct output_buffer
-{
- struct output_buffer *next;
- char *str;
-};
-
static struct path_list current_file_set = {NULL, 0, 0, 1};
static struct path_list current_directory_set = {NULL, 0, 0, 1};
static int call_depth = 0;
static int verbosity = 2;
+static int rename_limit = -1;
static int buffer_output = 1;
-static struct output_buffer *output_list, *output_end;
+static struct strbuf obuf = STRBUF_INIT;
-static int show (int v)
+static int show(int v)
{
return (!call_depth && verbosity >= v) || verbosity >= 5;
}
-static void output(int v, const char *fmt, ...)
+static void flush_output(void)
{
- va_list args;
- va_start(args, fmt);
- if (buffer_output && show(v)) {
- struct output_buffer *b = xmalloc(sizeof(*b));
- nfvasprintf(&b->str, fmt, args);
- b->next = NULL;
- if (output_end)
- output_end->next = b;
- else
- output_list = b;
- output_end = b;
- } else if (show(v)) {
- int i;
- for (i = call_depth; i--;)
- fputs(" ", stdout);
- vfprintf(stdout, fmt, args);
- fputc('\n', stdout);
+ if (obuf.len) {
+ fputs(obuf.buf, stdout);
+ strbuf_reset(&obuf);
}
- va_end(args);
}
-static void flush_output()
+static void output(int v, const char *fmt, ...)
{
- struct output_buffer *b, *n;
- for (b = output_list; b; b = n) {
- int i;
- for (i = call_depth; i--;)
- fputs(" ", stdout);
- fputs(b->str, stdout);
- fputc('\n', stdout);
- n = b->next;
- free(b->str);
- free(b);
+ int len;
+ va_list ap;
+
+ if (!show(v))
+ return;
+
+ strbuf_grow(&obuf, call_depth * 2 + 2);
+ memset(obuf.buf + obuf.len, ' ', call_depth * 2);
+ strbuf_setlen(&obuf, obuf.len + call_depth * 2);
+
+ va_start(ap, fmt);
+ len = vsnprintf(obuf.buf + obuf.len, strbuf_avail(&obuf), fmt, ap);
+ va_end(ap);
+
+ if (len < 0)
+ len = 0;
+ if (len >= strbuf_avail(&obuf)) {
+ strbuf_grow(&obuf, len + 2);
+ va_start(ap, fmt);
+ len = vsnprintf(obuf.buf + obuf.len, strbuf_avail(&obuf), fmt, ap);
+ va_end(ap);
+ if (len >= strbuf_avail(&obuf)) {
+ die("this should not happen, your snprintf is broken");
+ }
}
- output_list = NULL;
- output_end = NULL;
+ strbuf_setlen(&obuf, obuf.len + len);
+ strbuf_add(&obuf, "\n", 1);
+ if (!buffer_output)
+ flush_output();
}
static void output_commit_title(struct commit *commit)
}
}
-static struct cache_entry *make_cache_entry(unsigned int mode,
- const unsigned char *sha1, const char *path, int stage, int refresh)
-{
- int size, len;
- struct cache_entry *ce;
-
- if (!verify_path(path))
- return NULL;
-
- len = strlen(path);
- size = cache_entry_size(len);
- ce = xcalloc(1, size);
-
- hashcpy(ce->sha1, sha1);
- memcpy(ce->name, path, len);
- ce->ce_flags = create_ce_flags(len, stage);
- ce->ce_mode = create_ce_mode(mode);
-
- if (refresh)
- return refresh_cache_entry(ce, 0);
-
- return ce;
-}
-
static int add_cacheinfo(unsigned int mode, const unsigned char *sha1,
const char *path, int stage, int refresh, int options)
{
*/
static int index_only = 0;
+static void init_tree_desc_from_tree(struct tree_desc *desc, struct tree *tree)
+{
+ parse_tree(tree);
+ init_tree_desc(desc, tree->buffer, tree->size);
+}
+
static int git_merge_trees(int index_only,
struct tree *common,
struct tree *head,
struct tree *merge)
{
int rc;
- struct object_list *trees = NULL;
+ struct tree_desc t[3];
struct unpack_trees_options opts;
memset(&opts, 0, sizeof(opts));
opts.head_idx = 2;
opts.fn = threeway_merge;
- object_list_append(&common->object, &trees);
- object_list_append(&head->object, &trees);
- object_list_append(&merge->object, &trees);
+ init_tree_desc_from_tree(t+0, common);
+ init_tree_desc_from_tree(t+1, head);
+ init_tree_desc_from_tree(t+2, merge);
- rc = unpack_trees(trees, &opts);
+ rc = unpack_trees(3, t, &opts);
cache_tree_free(&active_cache_tree);
return rc;
}
renames = xcalloc(1, sizeof(struct path_list));
diff_setup(&opts);
- opts.recursive = 1;
+ DIFF_OPT_SET(&opts, RECURSIVE);
opts.detect_rename = DIFF_DETECT_RENAME;
+ opts.rename_limit = rename_limit;
opts.output_format = DIFF_FORMAT_NO_OUTPUT;
if (diff_setup_done(&opts) < 0)
die("diff setup failed");
static int remove_path(const char *name)
{
- int ret, len;
+ int ret;
char *slash, *dirs;
ret = unlink(name);
if (ret)
return ret;
- len = strlen(name);
- dirs = xmalloc(len+1);
- memcpy(dirs, name, len);
- dirs[len] = '\0';
+ dirs = xstrdup(name);
while ((slash = strrchr(name, '/'))) {
*slash = '\0';
- len = slash - name;
if (rmdir(name) != 0)
break;
}
flush_buffer(fd, buf, size);
close(fd);
} else if (S_ISLNK(mode)) {
- char *lnk = xmalloc(size + 1);
- memcpy(lnk, buf, size);
- lnk[size] = '\0';
+ char *lnk = xmemdupz(buf, size);
mkdir_p(path, 0777);
unlink(path);
symlink(lnk, path);
/*
* Built-in low-levels
*/
+static int ll_binary_merge(const struct ll_merge_driver *drv_unused,
+ const char *path_unused,
+ mmfile_t *orig,
+ mmfile_t *src1, const char *name1,
+ mmfile_t *src2, const char *name2,
+ mmbuffer_t *result)
+{
+ /*
+ * The tentative merge result is "ours" for the final round,
+ * or common ancestor for an internal merge. Still return
+ * "conflicted merge" status.
+ */
+ mmfile_t *stolen = index_only ? orig : src1;
+
+ result->ptr = stolen->ptr;
+ result->size = stolen->size;
+ stolen->ptr = NULL;
+ return 1;
+}
+
static int ll_xdl_merge(const struct ll_merge_driver *drv_unused,
const char *path_unused,
mmfile_t *orig,
{
xpparam_t xpp;
+ if (buffer_is_binary(orig->ptr, orig->size) ||
+ buffer_is_binary(src1->ptr, src1->size) ||
+ buffer_is_binary(src2->ptr, src2->size)) {
+ warning("Cannot merge binary files: %s vs. %s\n",
+ name1, name2);
+ return ll_binary_merge(drv_unused, path_unused,
+ orig, src1, name1,
+ src2, name2,
+ result);
+ }
+
memset(&xpp, 0, sizeof(xpp));
return xdl_merge(orig,
src1, name1,
return 0;
}
-static int ll_binary_merge(const struct ll_merge_driver *drv_unused,
- const char *path_unused,
- mmfile_t *orig,
- mmfile_t *src1, const char *name1,
- mmfile_t *src2, const char *name2,
- mmbuffer_t *result)
-{
- /*
- * The tentative merge result is "ours" for the final round,
- * or common ancestor for an internal merge. Still return
- * "conflicted merge" status.
- */
- mmfile_t *stolen = index_only ? orig : src1;
-
- result->ptr = stolen->ptr;
- result->size = stolen->size;
- stolen->ptr = NULL;
- return 1;
-}
-
#define LL_BINARY_MERGE 0
#define LL_TEXT_MERGE 1
#define LL_UNION_MERGE 2
int fd;
strcpy(path, ".merge_file_XXXXXX");
- fd = mkstemp(path);
- if (fd < 0)
- die("unable to create temp-file");
+ fd = xmkstemp(path);
if (write_in_full(fd, src->ptr, src->size) != src->size)
die("unable to write temp-file");
close(fd);
if (!strncmp(fn->name, name, namelen) && !fn->name[namelen])
break;
if (!fn) {
- char *namebuf;
fn = xcalloc(1, sizeof(struct ll_merge_driver));
- namebuf = xmalloc(namelen + 1);
- memcpy(namebuf, name, namelen);
- namebuf[namelen] = 0;
- fn->name = namebuf;
+ fn->name = xmemdupz(name, namelen);
fn->fn = ll_ext_merge;
- fn->next = NULL;
*ll_user_merge_tail = fn;
ll_user_merge_tail = &(fn->next);
}
mfi = merge_file(o, a, b,
a_branch, b_branch);
- if (mfi.merge || !mfi.clean)
- output(1, "Renamed %s => %s", ren1_src, ren1_dst);
- if (mfi.merge)
- output(2, "Auto-merged %s", ren1_dst);
- if (!mfi.clean) {
- output(1, "CONFLICT (rename/modify): Merge conflict in %s",
- ren1_dst);
- clean_merge = 0;
-
- if (!index_only)
- update_stages(ren1_dst,
- o, a, b, 1);
+ if (mfi.clean &&
+ sha_eq(mfi.sha, ren1->pair->two->sha1) &&
+ mfi.mode == ren1->pair->two->mode)
+ /*
+ * This messaged is part of
+ * t6022 test. If you change
+ * it update the test too.
+ */
+ output(3, "Skipped %s (merged same as existing)", ren1_dst);
+ else {
+ if (mfi.merge || !mfi.clean)
+ output(1, "Renamed %s => %s", ren1_src, ren1_dst);
+ if (mfi.merge)
+ output(2, "Auto-merged %s", ren1_dst);
+ if (!mfi.clean) {
+ output(1, "CONFLICT (rename/modify): Merge conflict in %s",
+ ren1_dst);
+ clean_merge = 0;
+
+ if (!index_only)
+ update_stages(ren1_dst,
+ o, a, b, 1);
+ }
+ update_file(mfi.clean, mfi.sha, mfi.mode, ren1_dst);
}
- update_file(mfi.clean, mfi.sha, mfi.mode, ren1_dst);
}
}
}
{
struct commit_list *iter;
struct commit *merged_common_ancestors;
- struct tree *mrtree;
+ struct tree *mrtree = mrtree;
int clean;
if (show(4)) {
verbosity = git_config_int(var, value);
return 0;
}
+ if (!strcasecmp(var, "diff.renamelimit")) {
+ rename_limit = git_config_int(var, value);
+ return 0;
+ }
return git_default_config(var, value);
}