fast-import: don't fail on omitted committer name
[gitweb.git] / merge-recursive.c
index 59482ffc87f7ae0b2004e3f1bbb467d199a3bcde..db9ba19ddf94fec3a5cfff450b35f5bb7b46c35e 100644 (file)
@@ -83,10 +83,8 @@ struct rename_df_conflict_info {
  * Since we want to write the index eventually, we cannot reuse the index
  * for these (temporary) data.
  */
-struct stage_data
-{
-       struct
-       {
+struct stage_data {
+       struct {
                unsigned mode;
                unsigned char sha[20];
        } stages[4];
@@ -137,7 +135,6 @@ static void flush_output(struct merge_options *o)
 __attribute__((format (printf, 3, 4)))
 static void output(struct merge_options *o, int v, const char *fmt, ...)
 {
-       int len;
        va_list ap;
 
        if (!show(o, v))
@@ -148,21 +145,9 @@ static void output(struct merge_options *o, int v, const char *fmt, ...)
        strbuf_setlen(&o->obuf, o->obuf.len + o->call_depth * 2);
 
        va_start(ap, fmt);
-       len = vsnprintf(o->obuf.buf + o->obuf.len, strbuf_avail(&o->obuf), fmt, ap);
+       strbuf_vaddf(&o->obuf, fmt, ap);
        va_end(ap);
 
-       if (len < 0)
-               len = 0;
-       if (len >= strbuf_avail(&o->obuf)) {
-               strbuf_grow(&o->obuf, len + 2);
-               va_start(ap, fmt);
-               len = vsnprintf(o->obuf.buf + o->obuf.len, strbuf_avail(&o->obuf), fmt, ap);
-               va_end(ap);
-               if (len >= strbuf_avail(&o->obuf)) {
-                       die("this should not happen, your snprintf is broken");
-               }
-       }
-       strbuf_setlen(&o->obuf, o->obuf.len + len);
        strbuf_add(&o->obuf, "\n", 1);
        if (!o->buffer_output)
                flush_output(o);
@@ -288,7 +273,9 @@ static int save_files_dirs(const unsigned char *sha1,
 static int get_files_dirs(struct merge_options *o, struct tree *tree)
 {
        int n;
-       if (read_tree_recursive(tree, "", 0, 0, NULL, save_files_dirs, o))
+       struct pathspec match_all;
+       init_pathspec(&match_all, NULL);
+       if (read_tree_recursive(tree, "", 0, 0, &match_all, save_files_dirs, o))
                return 0;
        n = o->current_file_set.nr + o->current_directory_set.nr;
        return n;
@@ -354,11 +341,10 @@ static void make_room_for_directories_of_df_conflicts(struct merge_options *o,
         * make room for the corresponding directory.  Such paths will
         * later be processed in process_df_entry() at the end.  If
         * the corresponding directory ends up being removed by the
-        * merge, then the file will be reinstated at that time
-        * (albeit with a different timestamp!); otherwise, if the
-        * file is not supposed to be removed by the merge, the
-        * contents of the file will be placed in another unique
-        * filename.
+        * merge, then the file will be reinstated at that time;
+        * otherwise, if the file is not supposed to be removed by the
+        * merge, the contents of the file will be placed in another
+        * unique filename.
         *
         * NOTE: This function relies on the fact that entries for a
         * D/F conflict will appear adjacent in the index, with the
@@ -367,16 +353,8 @@ static void make_room_for_directories_of_df_conflicts(struct merge_options *o,
         */
        const char *last_file = NULL;
        int last_len = 0;
-       struct stage_data *last_e;
        int i;
 
-       /*
-        * Do not do any of this crazyness during the recursive; we don't
-        * even write anything to the working tree!
-        */
-       if (o->call_depth)
-               return;
-
        for (i = 0; i < entries->nr; i++) {
                const char *path = entries->items[i].string;
                int len = strlen(path);
@@ -404,15 +382,13 @@ static void make_room_for_directories_of_df_conflicts(struct merge_options *o,
                if (S_ISREG(e->stages[2].mode) || S_ISLNK(e->stages[2].mode)) {
                        last_file = path;
                        last_len = len;
-                       last_e = e;
                } else {
                        last_file = NULL;
                }
        }
 }
 
-struct rename
-{
+struct rename {
        struct diff_filepair *pair;
        struct stage_data *src_entry;
        struct stage_data *dst_entry;
@@ -442,13 +418,16 @@ static struct string_list *get_renames(struct merge_options *o,
        opts.detect_rename = DIFF_DETECT_RENAME;
        opts.rename_limit = o->merge_rename_limit >= 0 ? o->merge_rename_limit :
                            o->diff_rename_limit >= 0 ? o->diff_rename_limit :
-                           500;
-       opts.warn_on_too_large_rename = 1;
+                           1000;
+       opts.rename_score = o->rename_score;
+       opts.show_rename_progress = o->show_rename_progress;
        opts.output_format = DIFF_FORMAT_NO_OUTPUT;
        if (diff_setup_done(&opts) < 0)
                die("diff setup failed");
        diff_tree_sha1(o_tree->object.sha1, tree->object.sha1, "", &opts);
        diffcore_std(&opts);
+       if (opts.needed_rename_limit > o->needed_rename_limit)
+               o->needed_rename_limit = opts.needed_rename_limit;
        for (i = 0; i < diff_queued_diff.nr; ++i) {
                struct string_list_item *item;
                struct rename *re;
@@ -724,8 +703,7 @@ static void update_file(struct merge_options *o,
 
 /* Low level file merging, update and removal */
 
-struct merge_file_info
-{
+struct merge_file_info {
        unsigned char sha[20];
        unsigned mode;
        unsigned clean:1,
@@ -741,22 +719,26 @@ static int merge_3way(struct merge_options *o,
                      const char *branch2)
 {
        mmfile_t orig, src1, src2;
+       struct ll_merge_options ll_opts = {0};
        char *base_name, *name1, *name2;
        int merge_status;
-       int favor;
 
-       if (o->call_depth)
-               favor = 0;
-       else {
+       ll_opts.renormalize = o->renormalize;
+       ll_opts.xdl_opts = o->xdl_opts;
+
+       if (o->call_depth) {
+               ll_opts.virtual_ancestor = 1;
+               ll_opts.variant = 0;
+       } else {
                switch (o->recursive_variant) {
                case MERGE_RECURSIVE_OURS:
-                       favor = XDL_MERGE_FAVOR_OURS;
+                       ll_opts.variant = XDL_MERGE_FAVOR_OURS;
                        break;
                case MERGE_RECURSIVE_THEIRS:
-                       favor = XDL_MERGE_FAVOR_THEIRS;
+                       ll_opts.variant = XDL_MERGE_FAVOR_THEIRS;
                        break;
                default:
-                       favor = 0;
+                       ll_opts.variant = 0;
                        break;
                }
        }
@@ -779,10 +761,7 @@ static int merge_3way(struct merge_options *o,
        read_mmblob(&src2, b->sha1);
 
        merge_status = ll_merge(result_buf, a->path, &orig, base_name,
-                               &src1, name1, &src2, name2,
-                               ((o->call_depth ? LL_OPT_VIRTUAL_ANCESTOR : 0) |
-                                (o->renormalize ? LL_OPT_RENORMALIZE : 0) |
-                                create_ll_flag(favor)));
+                               &src1, name1, &src2, name2, &ll_opts);
 
        free(name1);
        free(name2);
@@ -977,7 +956,6 @@ static int process_renames(struct merge_options *o,
        }
 
        for (i = 0, j = 0; i < a_renames->nr || j < b_renames->nr;) {
-               char *src;
                struct string_list *renames1, *renames2Dst;
                struct rename *ren1 = NULL, *ren2 = NULL;
                const char *branch1, *branch2;
@@ -1012,7 +990,6 @@ static int process_renames(struct merge_options *o,
                        ren2 = ren1;
                        ren1 = tmp;
                }
-               src = ren1->pair->one->path;
 
                ren1->dst_entry->processed = 1;
                ren1->src_entry->processed = 1;
@@ -1280,13 +1257,9 @@ static int merge_content(struct merge_options *o,
        }
 
        if (mfi.clean && !df_conflict_remains &&
-           sha_eq(mfi.sha, a_sha) && mfi.mode == a.mode &&
-           !o->call_depth && !lstat(path, &st)) {
+           sha_eq(mfi.sha, a_sha) && mfi.mode == a.mode)
                output(o, 3, "Skipped %s (merged same as existing)", path);
-               add_cacheinfo(mfi.mode, mfi.sha, path,
-                             0 /*stage*/, 1 /*refresh*/, 0 /*options*/);
-               return mfi.clean;
-       } else
+       else
                output(o, 2, "Auto-merging %s", path);
 
        if (!mfi.clean) {
@@ -1676,6 +1649,9 @@ int merge_recursive(struct merge_options *o,
                commit_list_insert(h2, &(*result)->parents->next);
        }
        flush_output(o);
+       if (show(o, 2))
+               diff_warn_rename_limit("merge.renamelimit",
+                                      o->needed_rename_limit, 0);
        return clean;
 }
 
@@ -1733,15 +1709,15 @@ int merge_recursive_generic(struct merge_options *o,
 static int merge_recursive_config(const char *var, const char *value, void *cb)
 {
        struct merge_options *o = cb;
-       if (!strcasecmp(var, "merge.verbosity")) {
+       if (!strcmp(var, "merge.verbosity")) {
                o->verbosity = git_config_int(var, value);
                return 0;
        }
-       if (!strcasecmp(var, "diff.renamelimit")) {
+       if (!strcmp(var, "diff.renamelimit")) {
                o->diff_rename_limit = git_config_int(var, value);
                return 0;
        }
-       if (!strcasecmp(var, "merge.renamelimit")) {
+       if (!strcmp(var, "merge.renamelimit")) {
                o->merge_rename_limit = git_config_int(var, value);
                return 0;
        }
@@ -1768,3 +1744,37 @@ void init_merge_options(struct merge_options *o)
        memset(&o->current_directory_set, 0, sizeof(struct string_list));
        o->current_directory_set.strdup_strings = 1;
 }
+
+int parse_merge_opt(struct merge_options *o, const char *s)
+{
+       if (!s || !*s)
+               return -1;
+       if (!strcmp(s, "ours"))
+               o->recursive_variant = MERGE_RECURSIVE_OURS;
+       else if (!strcmp(s, "theirs"))
+               o->recursive_variant = MERGE_RECURSIVE_THEIRS;
+       else if (!strcmp(s, "subtree"))
+               o->subtree_shift = "";
+       else if (!prefixcmp(s, "subtree="))
+               o->subtree_shift = s + strlen("subtree=");
+       else if (!strcmp(s, "patience"))
+               o->xdl_opts |= XDF_PATIENCE_DIFF;
+       else if (!strcmp(s, "ignore-space-change"))
+               o->xdl_opts |= XDF_IGNORE_WHITESPACE_CHANGE;
+       else if (!strcmp(s, "ignore-all-space"))
+               o->xdl_opts |= XDF_IGNORE_WHITESPACE;
+       else if (!strcmp(s, "ignore-space-at-eol"))
+               o->xdl_opts |= XDF_IGNORE_WHITESPACE_AT_EOL;
+       else if (!strcmp(s, "renormalize"))
+               o->renormalize = 1;
+       else if (!strcmp(s, "no-renormalize"))
+               o->renormalize = 0;
+       else if (!prefixcmp(s, "rename-threshold=")) {
+               const char *score = s + strlen("rename-threshold=");
+               if ((o->rename_score = parse_rename_score(&score)) == -1 || *score != 0)
+                       return -1;
+       }
+       else
+               return -1;
+       return 0;
+}