merge-recursive: flush output buffer before printing error messages
[gitweb.git] / merge-recursive.c
index bc59815416ce2d63860f38d12cf1835921030142..b972a83b38283d8bd140478ace31db3b728154fe 100644 (file)
 #include "dir.h"
 #include "submodule.h"
 
+static void flush_output(struct merge_options *o)
+{
+       if (o->obuf.len) {
+               fputs(o->obuf.buf, stdout);
+               strbuf_reset(&o->obuf);
+       }
+}
+
+static int err(struct merge_options *o, const char *err, ...)
+{
+       va_list params;
+
+       flush_output(o);
+       va_start(params, err);
+       strbuf_vaddf(&o->obuf, err, params);
+       va_end(params);
+       error("%s", o->obuf.buf);
+       strbuf_reset(&o->obuf);
+
+       return -1;
+}
+
 static struct tree *shift_tree_object(struct tree *one, struct tree *two,
                                      const char *subtree_shift)
 {
@@ -148,14 +170,6 @@ static int show(struct merge_options *o, int v)
        return (!o->call_depth && o->verbosity >= v) || o->verbosity >= 5;
 }
 
-static void flush_output(struct merge_options *o)
-{
-       if (o->obuf.len) {
-               fputs(o->obuf.buf, stdout);
-               strbuf_reset(&o->obuf);
-       }
-}
-
 __attribute__((format (printf, 3, 4)))
 static void output(struct merge_options *o, int v, const char *fmt, ...)
 {
@@ -198,7 +212,8 @@ static void output_commit_title(struct merge_options *o, struct commit *commit)
        }
 }
 
-static int add_cacheinfo(unsigned int mode, const struct object_id *oid,
+static int add_cacheinfo(struct merge_options *o,
+               unsigned int mode, const struct object_id *oid,
                const char *path, int stage, int refresh, int options)
 {
        struct cache_entry *ce;
@@ -206,7 +221,7 @@ static int add_cacheinfo(unsigned int mode, const struct object_id *oid,
 
        ce = make_cache_entry(mode, oid ? oid->hash : null_sha1, path, stage, 0);
        if (!ce)
-               return error(_("addinfo_cache failed for path '%s'"), path);
+               return err(o, _("addinfo_cache failed for path '%s'"), path);
 
        ret = add_cache_entry(ce, options);
        if (refresh) {
@@ -276,7 +291,7 @@ struct tree *write_tree_from_memory(struct merge_options *o)
 
        if (!cache_tree_fully_valid(active_cache_tree) &&
            cache_tree_update(&the_index, 0) < 0) {
-               error(_("error building trees"));
+               err(o, _("error building trees"));
                return NULL;
        }
 
@@ -544,7 +559,8 @@ static struct string_list *get_renames(struct merge_options *o,
        return renames;
 }
 
-static int update_stages(const char *path, const struct diff_filespec *o,
+static int update_stages(struct merge_options *opt, const char *path,
+                        const struct diff_filespec *o,
                         const struct diff_filespec *a,
                         const struct diff_filespec *b)
 {
@@ -563,13 +579,13 @@ static int update_stages(const char *path, const struct diff_filespec *o,
                if (remove_file_from_cache(path))
                        return -1;
        if (o)
-               if (add_cacheinfo(o->mode, &o->oid, path, 1, 0, options))
+               if (add_cacheinfo(opt, o->mode, &o->oid, path, 1, 0, options))
                        return -1;
        if (a)
-               if (add_cacheinfo(a->mode, &a->oid, path, 2, 0, options))
+               if (add_cacheinfo(opt, a->mode, &a->oid, path, 2, 0, options))
                        return -1;
        if (b)
-               if (add_cacheinfo(b->mode, &b->oid, path, 3, 0, options))
+               if (add_cacheinfo(opt, b->mode, &b->oid, path, 3, 0, options))
                        return -1;
        return 0;
 }
@@ -720,8 +736,8 @@ static int make_room_for_path(struct merge_options *o, const char *path)
        if (status) {
                if (status == SCLD_EXISTS)
                        /* something else exists */
-                       return error(msg, path, _(": perhaps a D/F conflict?"));
-               return error(msg, path, "");
+                       return err(o, msg, path, _(": perhaps a D/F conflict?"));
+               return err(o, msg, path, "");
        }
 
        /*
@@ -729,7 +745,7 @@ static int make_room_for_path(struct merge_options *o, const char *path)
         * tracking it.
         */
        if (would_lose_untracked(path))
-               return error(_("refusing to lose untracked file at '%s'"),
+               return err(o, _("refusing to lose untracked file at '%s'"),
                             path);
 
        /* Successful unlink is good.. */
@@ -739,7 +755,7 @@ static int make_room_for_path(struct merge_options *o, const char *path)
        if (errno == ENOENT)
                return 0;
        /* .. but not some other error (who really cares what?) */
-       return error(msg, path, _(": perhaps a D/F conflict?"));
+       return err(o, msg, path, _(": perhaps a D/F conflict?"));
 }
 
 static int update_file_flags(struct merge_options *o,
@@ -771,9 +787,9 @@ static int update_file_flags(struct merge_options *o,
 
                buf = read_sha1_file(oid->hash, &type, &size);
                if (!buf)
-                       return error(_("cannot read object %s '%s'"), oid_to_hex(oid), path);
+                       return err(o, _("cannot read object %s '%s'"), oid_to_hex(oid), path);
                if (type != OBJ_BLOB) {
-                       ret = error(_("blob expected for %s '%s'"), oid_to_hex(oid), path);
+                       ret = err(o, _("blob expected for %s '%s'"), oid_to_hex(oid), path);
                        goto free_buf;
                }
                if (S_ISREG(mode)) {
@@ -797,8 +813,8 @@ static int update_file_flags(struct merge_options *o,
                                mode = 0666;
                        fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, mode);
                        if (fd < 0) {
-                               ret = error_errno(_("failed to open '%s'"),
-                                                 path);
+                               ret = err(o, _("failed to open '%s': %s"),
+                                         path, strerror(errno));
                                goto free_buf;
                        }
                        write_in_full(fd, buf, size);
@@ -808,17 +824,19 @@ static int update_file_flags(struct merge_options *o,
                        safe_create_leading_directories_const(path);
                        unlink(path);
                        if (symlink(lnk, path))
-                               ret = error_errno(_("failed to symlink '%s'"), path);
+                               ret = err(o, _("failed to symlink '%s': %s"),
+                                       path, strerror(errno));
                        free(lnk);
                } else
-                       ret = error(_("do not know what to do with %06o %s '%s'"),
-                                   mode, oid_to_hex(oid), path);
+                       ret = err(o,
+                                 _("do not know what to do with %06o %s '%s'"),
+                                 mode, oid_to_hex(oid), path);
  free_buf:
                free(buf);
        }
  update_index:
        if (!ret && update_cache)
-               add_cacheinfo(mode, oid, path, 0, update_wd, ADD_CACHE_OK_TO_ADD);
+               add_cacheinfo(o, mode, oid, path, 0, update_wd, ADD_CACHE_OK_TO_ADD);
        return ret;
 }
 
@@ -951,12 +969,12 @@ static int merge_file_1(struct merge_options *o,
                                                  branch1, branch2);
 
                        if ((merge_status < 0) || !result_buf.ptr)
-                               ret = error(_("Failed to execute internal merge"));
+                               ret = err(o, _("Failed to execute internal merge"));
 
                        if (!ret && write_sha1_file(result_buf.ptr, result_buf.size,
                                                    blob_type, result->oid.hash))
-                               ret = error(_("Unable to add %s to database"),
-                                           a->path);
+                               ret = err(o, _("Unable to add %s to database"),
+                                         a->path);
 
                        free(result_buf.ptr);
                        if (ret)
@@ -1122,7 +1140,7 @@ static int conflict_rename_delete(struct merge_options *o,
        if (o->call_depth)
                return remove_file_from_cache(dest->path);
        else
-               return update_stages(dest->path, NULL,
+               return update_stages(o, dest->path, NULL,
                                     rename_branch == o->branch1 ? dest : NULL,
                                     rename_branch == o->branch1 ? NULL : dest);
 }
@@ -1180,9 +1198,9 @@ static int handle_file(struct merge_options *o,
        if ((ret = update_file(o, 0, &rename->oid, rename->mode, dst_name)))
                ; /* fall through, do allow dst_name to be released */
        else if (stage == 2)
-               ret = update_stages(rename->path, NULL, rename, add);
+               ret = update_stages(o, rename->path, NULL, rename, add);
        else
-               ret = update_stages(rename->path, NULL, add, rename);
+               ret = update_stages(o, rename->path, NULL, add, rename);
 
        if (dst_name != rename->path)
                free(dst_name);
@@ -1575,23 +1593,25 @@ static struct object_id *stage_oid(const struct object_id *oid, unsigned mode)
        return (is_null_oid(oid) || mode == 0) ? NULL: (struct object_id *)oid;
 }
 
-static int read_oid_strbuf(const struct object_id *oid, struct strbuf *dst)
+static int read_oid_strbuf(struct merge_options *o,
+       const struct object_id *oid, struct strbuf *dst)
 {
        void *buf;
        enum object_type type;
        unsigned long size;
        buf = read_sha1_file(oid->hash, &type, &size);
        if (!buf)
-               return error(_("cannot read object %s"), oid_to_hex(oid));
+               return err(o, _("cannot read object %s"), oid_to_hex(oid));
        if (type != OBJ_BLOB) {
                free(buf);
-               return error(_("object %s is not a blob"), oid_to_hex(oid));
+               return err(o, _("object %s is not a blob"), oid_to_hex(oid));
        }
        strbuf_attach(dst, buf, size, size + 1);
        return 0;
 }
 
-static int blob_unchanged(const struct object_id *o_oid,
+static int blob_unchanged(struct merge_options *opt,
+                         const struct object_id *o_oid,
                          unsigned o_mode,
                          const struct object_id *a_oid,
                          unsigned a_mode,
@@ -1609,7 +1629,7 @@ static int blob_unchanged(const struct object_id *o_oid,
                return 0;
 
        assert(o_oid && a_oid);
-       if (read_oid_strbuf(o_oid, &o) || read_oid_strbuf(a_oid, &a))
+       if (read_oid_strbuf(opt, o_oid, &o) || read_oid_strbuf(opt, a_oid, &a))
                goto error_return;
        /*
         * Note: binary | is used so that both renormalizations are
@@ -1698,7 +1718,7 @@ static int merge_content(struct merge_options *o,
                 */
                path_renamed_outside_HEAD = !path2 || !strcmp(path, path2);
                if (!path_renamed_outside_HEAD) {
-                       add_cacheinfo(mfi.mode, &mfi.oid, path,
+                       add_cacheinfo(o, mfi.mode, &mfi.oid, path,
                                      0, (!o->call_depth), 0);
                        return mfi.clean;
                }
@@ -1711,7 +1731,7 @@ static int merge_content(struct merge_options *o,
                output(o, 1, _("CONFLICT (%s): Merge conflict in %s"),
                                reason, path);
                if (rename_conflict_info && !df_conflict_remains)
-                       if (update_stages(path, &one, &a, &b))
+                       if (update_stages(o, path, &one, &a, &b))
                                return -1;
        }
 
@@ -1721,7 +1741,7 @@ static int merge_content(struct merge_options *o,
                        remove_file_from_cache(path);
                } else {
                        if (!mfi.clean) {
-                               if (update_stages(path, &one, &a, &b))
+                               if (update_stages(o, path, &one, &a, &b))
                                        return -1;
                        } else {
                                int file_from_stage2 = was_tracked(path);
@@ -1729,7 +1749,7 @@ static int merge_content(struct merge_options *o,
                                oidcpy(&merged.oid, &mfi.oid);
                                merged.mode = mfi.mode;
 
-                               if (update_stages(path, NULL,
+                               if (update_stages(o, path, NULL,
                                                  file_from_stage2 ? &merged : NULL,
                                                  file_from_stage2 ? NULL : &merged))
                                        return -1;
@@ -1797,8 +1817,8 @@ static int process_entry(struct merge_options *o,
        } else if (o_oid && (!a_oid || !b_oid)) {
                /* Case A: Deleted in one */
                if ((!a_oid && !b_oid) ||
-                   (!b_oid && blob_unchanged(o_oid, o_mode, a_oid, a_mode, normalize, path)) ||
-                   (!a_oid && blob_unchanged(o_oid, o_mode, b_oid, b_mode, normalize, path))) {
+                   (!b_oid && blob_unchanged(o, o_oid, o_mode, a_oid, a_mode, normalize, path)) ||
+                   (!a_oid && blob_unchanged(o, o_oid, o_mode, b_oid, b_mode, normalize, path))) {
                        /* Deleted in both or deleted in one and
                         * unchanged in the other */
                        if (a_oid)
@@ -1894,7 +1914,7 @@ int merge_trees(struct merge_options *o,
 
        if (code != 0) {
                if (show(o, 4) || o->call_depth)
-                       error(_("merging of trees %s and %s failed"),
+                       err(o, _("merging of trees %s and %s failed"),
                            oid_to_hex(&head->object.oid),
                            oid_to_hex(&merge->object.oid));
                return -1;
@@ -2029,7 +2049,7 @@ int merge_recursive(struct merge_options *o,
                o->call_depth--;
 
                if (!merged_common_ancestors)
-                       return error(_("merge returned no commit"));
+                       return err(o, _("merge returned no commit"));
        }
 
        discard_cache();
@@ -2088,7 +2108,7 @@ int merge_recursive_generic(struct merge_options *o,
                for (i = 0; i < num_base_list; ++i) {
                        struct commit *base;
                        if (!(base = get_ref(base_list[i], oid_to_hex(base_list[i]))))
-                               return error(_("Could not parse object '%s'"),
+                               return err(o, _("Could not parse object '%s'"),
                                        oid_to_hex(base_list[i]));
                        commit_list_insert(base, &ca);
                }
@@ -2102,7 +2122,7 @@ int merge_recursive_generic(struct merge_options *o,
 
        if (active_cache_changed &&
            write_locked_index(&the_index, lock, COMMIT_LOCK))
-               return error(_("Unable to write index."));
+               return err(o, _("Unable to write index."));
 
        return clean ? 0 : 1;
 }