rerere: only return whether a path has conflicts or not
[gitweb.git] / rerere.c
index e0862e27786244b1a98723d09475223cc001dd62..bf803043e28676ccde5a0d75f955872b2c3a2022 100644 (file)
--- a/rerere.c
+++ b/rerere.c
@@ -212,7 +212,7 @@ static void read_rr(struct string_list *rr)
 
                /* There has to be the hash, tab, path and then NUL */
                if (buf.len < 42 || get_sha1_hex(buf.buf, sha1))
-                       die("corrupt MERGE_RR");
+                       die(_("corrupt MERGE_RR"));
 
                if (buf.buf[40] != '.') {
                        variant = 0;
@@ -221,10 +221,10 @@ static void read_rr(struct string_list *rr)
                        errno = 0;
                        variant = strtol(buf.buf + 41, &path, 10);
                        if (errno)
-                               die("corrupt MERGE_RR");
+                               die(_("corrupt MERGE_RR"));
                }
                if (*(path++) != '\t')
-                       die("corrupt MERGE_RR");
+                       die(_("corrupt MERGE_RR"));
                buf.buf[40] = '\0';
                id = new_rerere_id_hex(buf.buf);
                id->variant = variant;
@@ -259,12 +259,12 @@ static int write_rr(struct string_list *rr, int out_fd)
                                    rr->items[i].string, 0);
 
                if (write_in_full(out_fd, buf.buf, buf.len) < 0)
-                       die("unable to write rerere record");
+                       die(_("unable to write rerere record"));
 
                strbuf_release(&buf);
        }
        if (commit_lock_file(&write_lock) != 0)
-               die("unable to write rerere record");
+               die(_("unable to write rerere record"));
        return 0;
 }
 
@@ -393,16 +393,13 @@ static int is_cmarker(char *buf, int marker_char, int marker_size)
  * one side of the conflict, NUL, the other side of the conflict,
  * and NUL concatenated together.
  *
- * Return the number of conflict hunks found.
- *
- * NEEDSWORK: the logic and theory of operation behind this conflict
- * normalization may deserve to be documented somewhere, perhaps in
- * Documentation/technical/rerere.txt.
+ * Return 1 if conflict hunks are found, 0 if there are no conflict
+ * hunks and -1 if an error occured.
  */
 static int handle_path(unsigned char *sha1, struct rerere_io *io, int marker_size)
 {
        git_SHA_CTX ctx;
-       int hunk_no = 0;
+       int has_conflicts = 0;
        enum {
                RR_CONTEXT = 0, RR_SIDE_1, RR_SIDE_2, RR_ORIGINAL
        } hunk = RR_CONTEXT;
@@ -430,7 +427,7 @@ static int handle_path(unsigned char *sha1, struct rerere_io *io, int marker_siz
                                goto bad;
                        if (strbuf_cmp(&one, &two) > 0)
                                strbuf_swap(&one, &two);
-                       hunk_no++;
+                       has_conflicts = 1;
                        hunk = RR_CONTEXT;
                        rerere_io_putconflict('<', marker_size, io);
                        rerere_io_putmem(one.buf, one.len, io);
@@ -466,7 +463,7 @@ static int handle_path(unsigned char *sha1, struct rerere_io *io, int marker_siz
                git_SHA1_Final(sha1, &ctx);
        if (hunk != RR_CONTEXT)
                return -1;
-       return hunk_no;
+       return has_conflicts;
 }
 
 /*
@@ -475,7 +472,7 @@ static int handle_path(unsigned char *sha1, struct rerere_io *io, int marker_siz
  */
 static int handle_file(const char *path, unsigned char *sha1, const char *output)
 {
-       int hunk_no = 0;
+       int has_conflicts = 0;
        struct rerere_io_file io;
        int marker_size = ll_merge_marker_size(path);
 
@@ -484,34 +481,34 @@ static int handle_file(const char *path, unsigned char *sha1, const char *output
        io.input = fopen(path, "r");
        io.io.wrerror = 0;
        if (!io.input)
-               return error_errno("Could not open %s", path);
+               return error_errno(_("could not open '%s'"), path);
 
        if (output) {
                io.io.output = fopen(output, "w");
                if (!io.io.output) {
-                       error_errno("Could not write %s", output);
+                       error_errno(_("could not write '%s'"), output);
                        fclose(io.input);
                        return -1;
                }
        }
 
-       hunk_no = handle_path(sha1, (struct rerere_io *)&io, marker_size);
+       has_conflicts = handle_path(sha1, (struct rerere_io *)&io, marker_size);
 
        fclose(io.input);
        if (io.io.wrerror)
-               error("There were errors while writing %s (%s)",
+               error(_("there were errors while writing '%s' (%s)"),
                      path, strerror(io.io.wrerror));
        if (io.io.output && fclose(io.io.output))
-               io.io.wrerror = error_errno("Failed to flush %s", path);
+               io.io.wrerror = error_errno(_("failed to flush '%s'"), path);
 
-       if (hunk_no < 0) {
+       if (has_conflicts < 0) {
                if (output)
                        unlink_or_warn(output);
-               return error("Could not parse conflict hunks in %s", path);
+               return error(_("could not parse conflict hunks in '%s'"), path);
        }
        if (io.io.wrerror)
                return -1;
-       return hunk_no;
+       return has_conflicts;
 }
 
 /*
@@ -568,7 +565,7 @@ static int find_conflict(struct string_list *conflict)
 {
        int i;
        if (read_cache() < 0)
-               return error("Could not read index");
+               return error(_("index file corrupt"));
 
        for (i = 0; i < active_nr;) {
                int conflict_type;
@@ -601,7 +598,7 @@ int rerere_remaining(struct string_list *merge_rr)
        if (setup_rerere(merge_rr, RERERE_READONLY))
                return 0;
        if (read_cache() < 0)
-               return error("Could not read index");
+               return error(_("index file corrupt"));
 
        for (i = 0; i < active_nr;) {
                int conflict_type;
@@ -684,17 +681,17 @@ static int merge(const struct rerere_id *id, const char *path)
         * Mark that "postimage" was used to help gc.
         */
        if (utime(rerere_path(id, "postimage"), NULL) < 0)
-               warning_errno("failed utime() on %s",
+               warning_errno(_("failed utime() on '%s'"),
                              rerere_path(id, "postimage"));
 
        /* Update "path" with the resolution */
        f = fopen(path, "w");
        if (!f)
-               return error_errno("Could not open %s", path);
+               return error_errno(_("could not open '%s'"), path);
        if (fwrite(result.ptr, result.size, 1, f) != 1)
-               error_errno("Could not write %s", path);
+               error_errno(_("could not write '%s'"), path);
        if (fclose(f))
-               return error_errno("Writing %s failed", path);
+               return error_errno(_("writing '%s' failed"), path);
 
 out:
        free(cur.ptr);
@@ -714,13 +711,13 @@ static void update_paths(struct string_list *update)
                struct string_list_item *item = &update->items[i];
                if (add_file_to_cache(item->string, 0))
                        exit(128);
-               fprintf(stderr, "Staged '%s' using previous resolution.\n",
+               fprintf_ln(stderr, _("Staged '%s' using previous resolution."),
                        item->string);
        }
 
        if (write_locked_index(&the_index, &index_lock,
                               COMMIT_LOCK | SKIP_IF_UNCHANGED))
-               die("Unable to write new index file");
+               die(_("unable to write new index file"));
 }
 
 static void remove_variant(struct rerere_id *id)
@@ -752,7 +749,7 @@ static void do_rerere_one_path(struct string_list_item *rr_item,
                if (!handle_file(path, NULL, NULL)) {
                        copy_file(rerere_path(id, "postimage"), path, 0666);
                        id->collection->status[variant] |= RR_HAS_POSTIMAGE;
-                       fprintf(stderr, "Recorded resolution for '%s'.\n", path);
+                       fprintf_ln(stderr, _("Recorded resolution for '%s'."), path);
                        free_rerere_id(rr_item);
                        rr_item->util = NULL;
                        return;
@@ -786,9 +783,9 @@ static void do_rerere_one_path(struct string_list_item *rr_item,
                if (rerere_autoupdate)
                        string_list_insert(update, path);
                else
-                       fprintf(stderr,
-                               "Resolved '%s' using previous resolution.\n",
-                               path);
+                       fprintf_ln(stderr,
+                                  _("Resolved '%s' using previous resolution."),
+                                  path);
                free_rerere_id(rr_item);
                rr_item->util = NULL;
                return;
@@ -802,11 +799,11 @@ static void do_rerere_one_path(struct string_list_item *rr_item,
        if (id->collection->status[variant] & RR_HAS_POSTIMAGE) {
                const char *path = rerere_path(id, "postimage");
                if (unlink(path))
-                       die_errno("cannot unlink stray '%s'", path);
+                       die_errno(_("cannot unlink stray '%s'"), path);
                id->collection->status[variant] &= ~RR_HAS_POSTIMAGE;
        }
        id->collection->status[variant] |= RR_HAS_PREIMAGE;
-       fprintf(stderr, "Recorded preimage for '%s'\n", path);
+       fprintf_ln(stderr, _("Recorded preimage for '%s'"), path);
 }
 
 static int do_plain_rerere(struct string_list *rr, int fd)
@@ -827,10 +824,7 @@ static int do_plain_rerere(struct string_list *rr, int fd)
                struct rerere_id *id;
                unsigned char sha1[20];
                const char *path = conflict.items[i].string;
-               int ret;
-
-               if (string_list_has_string(rr, path))
-                       continue;
+               int ret, has_string;
 
                /*
                 * Ask handle_file() to scan and assign a
@@ -838,7 +832,12 @@ static int do_plain_rerere(struct string_list *rr, int fd)
                 * yet.
                 */
                ret = handle_file(path, sha1, NULL);
-               if (ret < 1)
+               has_string = string_list_has_string(rr, path);
+               if (ret < 0 && has_string) {
+                       remove_variant(string_list_lookup(rr, path)->util);
+                       string_list_remove(rr, path, 1);
+               }
+               if (ret < 1 || has_string)
                        continue;
 
                id = new_rerere_id(sha1);
@@ -878,7 +877,7 @@ static int is_rerere_enabled(void)
                return rr_cache_exists;
 
        if (!rr_cache_exists && mkdir_in_gitdir(git_path_rr_cache()))
-               die("Could not create directory %s", git_path_rr_cache());
+               die(_("could not create directory '%s'"), git_path_rr_cache());
        return 1;
 }
 
@@ -956,7 +955,7 @@ static int handle_cache(const char *path, unsigned char *sha1, const char *outpu
        mmfile_t mmfile[3] = {{NULL}};
        mmbuffer_t result = {NULL, 0};
        const struct cache_entry *ce;
-       int pos, len, i, hunk_no;
+       int pos, len, i, has_conflicts;
        struct rerere_io_mem io;
        int marker_size = ll_merge_marker_size(path);
 
@@ -1010,11 +1009,11 @@ static int handle_cache(const char *path, unsigned char *sha1, const char *outpu
         * Grab the conflict ID and optionally write the original
         * contents with conflict markers out.
         */
-       hunk_no = handle_path(sha1, (struct rerere_io *)&io, marker_size);
+       has_conflicts = handle_path(sha1, (struct rerere_io *)&io, marker_size);
        strbuf_release(&io.input);
        if (io.io.output)
                fclose(io.io.output);
-       return hunk_no;
+       return has_conflicts;
 }
 
 static int rerere_forget_one_path(const char *path, struct string_list *rr)
@@ -1031,7 +1030,7 @@ static int rerere_forget_one_path(const char *path, struct string_list *rr)
         */
        ret = handle_cache(path, sha1, NULL);
        if (ret < 1)
-               return error("Could not parse conflict hunks in '%s'", path);
+               return error(_("could not parse conflict hunks in '%s'"), path);
 
        /* Nuke the recorded resolution for the conflict */
        id = new_rerere_id(sha1);
@@ -1049,7 +1048,7 @@ static int rerere_forget_one_path(const char *path, struct string_list *rr)
                handle_cache(path, sha1, rerere_path(id, "thisimage"));
                if (read_mmfile(&cur, rerere_path(id, "thisimage"))) {
                        free(cur.ptr);
-                       error("Failed to update conflicted state in '%s'", path);
+                       error(_("failed to update conflicted state in '%s'"), path);
                        goto fail_exit;
                }
                cleanly_resolved = !try_merge(id, path, &cur, &result);
@@ -1060,16 +1059,16 @@ static int rerere_forget_one_path(const char *path, struct string_list *rr)
        }
 
        if (id->collection->status_nr <= id->variant) {
-               error("no remembered resolution for '%s'", path);
+               error(_("no remembered resolution for '%s'"), path);
                goto fail_exit;
        }
 
        filename = rerere_path(id, "postimage");
        if (unlink(filename)) {
                if (errno == ENOENT)
-                       error("no remembered resolution for %s", path);
+                       error(_("no remembered resolution for '%s'"), path);
                else
-                       error_errno("cannot unlink %s", filename);
+                       error_errno(_("cannot unlink '%s'"), filename);
                goto fail_exit;
        }
 
@@ -1079,7 +1078,7 @@ static int rerere_forget_one_path(const char *path, struct string_list *rr)
         * the postimage.
         */
        handle_cache(path, sha1, rerere_path(id, "preimage"));
-       fprintf(stderr, "Updated preimage for '%s'\n", path);
+       fprintf_ln(stderr, _("Updated preimage for '%s'"), path);
 
        /*
         * And remember that we can record resolution for this
@@ -1088,7 +1087,7 @@ static int rerere_forget_one_path(const char *path, struct string_list *rr)
        item = string_list_insert(rr, path);
        free_rerere_id(item);
        item->util = id;
-       fprintf(stderr, "Forgot resolution for %s\n", path);
+       fprintf(stderr, _("Forgot resolution for '%s'\n"), path);
        return 0;
 
 fail_exit:
@@ -1103,7 +1102,7 @@ int rerere_forget(struct pathspec *pathspec)
        struct string_list merge_rr = STRING_LIST_INIT_DUP;
 
        if (read_cache() < 0)
-               return error("Could not read index");
+               return error(_("index file corrupt"));
 
        fd = setup_rerere(&merge_rr, RERERE_NOAUTOUPDATE);
        if (fd < 0)
@@ -1191,7 +1190,7 @@ void rerere_gc(struct string_list *rr)
        git_config(git_default_config, NULL);
        dir = opendir(git_path("rr-cache"));
        if (!dir)
-               die_errno("unable to open rr-cache directory");
+               die_errno(_("unable to open rr-cache directory"));
        /* Collect stale conflict IDs ... */
        while ((e = readdir(dir))) {
                struct rerere_dir *rr_dir;