X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=builtin-rerere.c;h=37e62481388aecc8ffb9b5943de248f496ca9d13;hb=6ba78238a824282816944550edc4297dd2808a72;hp=b8867ab4add83dee4ab99108e96949bcd65290a0;hpb=c379c4b176ce350a8d6c0773a3ad211996d809db;p=git.git diff --git a/builtin-rerere.c b/builtin-rerere.c index b8867ab4a..37e624813 100644 --- a/builtin-rerere.c +++ b/builtin-rerere.c @@ -1,3 +1,4 @@ +#include "builtin.h" #include "cache.h" #include "path-list.h" #include "xdiff/xdiff.h" @@ -12,6 +13,9 @@ static const char git_rerere_usage[] = static int cutoff_noresolve = 15; static int cutoff_resolve = 60; +/* if rerere_enabled == -1, fall back to detection of .git/rr-cache */ +static int rerere_enabled = -1; + static char *merge_rr_path; static const char *rr_path(const char *name, const char *file) @@ -57,37 +61,20 @@ static int write_rr(struct path_list *rr, int out_fd) write_in_full(out_fd, path, length) != length) die("unable to write rerere record"); } - close(out_fd); + if (close(out_fd) != 0) + die("unable to write rerere record"); return commit_lock_file(&write_lock); } -struct buffer { - char *ptr; - int nr, alloc; -}; - -static void append_line(struct buffer *buffer, const char *line) -{ - int len = strlen(line); - - if (buffer->nr + len > buffer->alloc) { - buffer->alloc = alloc_nr(buffer->nr + len); - buffer->ptr = xrealloc(buffer->ptr, buffer->alloc); - } - memcpy(buffer->ptr + buffer->nr, line, len); - buffer->nr += len; -} - static int handle_file(const char *path, unsigned char *sha1, const char *output) { SHA_CTX ctx; char buf[1024]; int hunk = 0, hunk_no = 0; - struct buffer minus = { NULL, 0, 0 }, plus = { NULL, 0, 0 }; - struct buffer *one = &minus, *two = + + struct strbuf one, two; FILE *f = fopen(path, "r"); - FILE *out; + FILE *out = NULL; if (!f) return error("Could not open %s", path); @@ -98,46 +85,50 @@ static int handle_file(const char *path, fclose(f); return error("Could not write %s", output); } - } else - out = NULL; + } if (sha1) SHA1_Init(&ctx); + strbuf_init(&one, 0); + strbuf_init(&two, 0); while (fgets(buf, sizeof(buf), f)) { if (!prefixcmp(buf, "<<<<<<< ")) hunk = 1; else if (!prefixcmp(buf, "=======")) hunk = 2; else if (!prefixcmp(buf, ">>>>>>> ")) { + int cmp = strbuf_cmp(&one, &two); + hunk_no++; hunk = 0; - if (memcmp(one->ptr, two->ptr, one->nr < two->nr ? - one->nr : two->nr) > 0) { - struct buffer *swap = one; - one = two; - two = swap; + if (cmp > 0) { + strbuf_swap(&one, &two); } if (out) { fputs("<<<<<<<\n", out); - fwrite(one->ptr, one->nr, 1, out); + fwrite(one.buf, one.len, 1, out); fputs("=======\n", out); - fwrite(two->ptr, two->nr, 1, out); + fwrite(two.buf, two.len, 1, out); fputs(">>>>>>>\n", out); } if (sha1) { - SHA1_Update(&ctx, one->ptr, one->nr); - SHA1_Update(&ctx, "\0", 1); - SHA1_Update(&ctx, two->ptr, two->nr); - SHA1_Update(&ctx, "\0", 1); + SHA1_Update(&ctx, one.buf ? one.buf : "", + one.len + 1); + SHA1_Update(&ctx, two.buf ? two.buf : "", + two.len + 1); } + strbuf_reset(&one); + strbuf_reset(&two); } else if (hunk == 1) - append_line(one, buf); + strbuf_addstr(&one, buf); else if (hunk == 2) - append_line(two, buf); + strbuf_addstr(&two, buf); else if (out) fputs(buf, out); } + strbuf_release(&one); + strbuf_release(&two); fclose(f); if (out) @@ -152,19 +143,16 @@ static int find_conflict(struct path_list *conflict) int i; if (read_cache() < 0) return error("Could not read index"); - for (i = 0; i + 2 < active_nr; i++) { - struct cache_entry *e1 = active_cache[i]; - struct cache_entry *e2 = active_cache[i+1]; - struct cache_entry *e3 = active_cache[i+2]; - if (ce_stage(e1) == 1 && - ce_stage(e2) == 2 && + for (i = 0; i+1 < active_nr; i++) { + struct cache_entry *e2 = active_cache[i]; + struct cache_entry *e3 = active_cache[i+1]; + if (ce_stage(e2) == 2 && ce_stage(e3) == 3 && - ce_same_name(e1, e2) && ce_same_name(e1, e3) && - S_ISREG(ntohl(e1->ce_mode)) && + ce_same_name(e2, e3) && S_ISREG(ntohl(e2->ce_mode)) && S_ISREG(ntohl(e3->ce_mode))) { - path_list_insert((const char *)e1->name, conflict); - i += 2; + path_list_insert((const char *)e2->name, conflict); + i++; /* skip over both #2 and #3 */ } } return 0; @@ -269,10 +257,10 @@ static int diff_two(const char *file1, const char *label1, printf("--- a/%s\n+++ b/%s\n", label1, label2); fflush(stdout); xpp.flags = XDF_NEED_MINIMAL; + memset(&xecfg, 0, sizeof(xecfg)); xecfg.ctxlen = 3; - xecfg.flags = 0; ecb.outf = outf; - xdl_diff(&minus, &plus, &xpp, &xecfg, &ecb); + xdi_diff(&minus, &plus, &xpp, &xecfg, &ecb); free(minus.ptr); free(plus.ptr); @@ -374,30 +362,72 @@ static int git_rerere_config(const char *var, const char *value) cutoff_resolve = git_config_int(var, value); else if (!strcmp(var, "gc.rerereunresolved")) cutoff_noresolve = git_config_int(var, value); + else if (!strcmp(var, "rerere.enabled")) + rerere_enabled = git_config_bool(var, value); else return git_default_config(var, value); return 0; } -int cmd_rerere(int argc, const char **argv, const char *prefix) +static int is_rerere_enabled(void) { - struct path_list merge_rr = { NULL, 0, 0, 1 }; - int i, fd = -1; struct stat st; + const char *rr_cache; + int rr_cache_exists; - if (stat(git_path("rr-cache"), &st) || !S_ISDIR(st.st_mode)) + if (!rerere_enabled) return 0; + rr_cache = git_path("rr-cache"); + rr_cache_exists = !stat(rr_cache, &st) && S_ISDIR(st.st_mode); + if (rerere_enabled < 0) + return rr_cache_exists; + + if (!rr_cache_exists && + (mkdir(rr_cache, 0777) || adjust_shared_perm(rr_cache))) + die("Could not create directory %s", rr_cache); + return 1; +} + +static int setup_rerere(struct path_list *merge_rr) +{ + int fd; + git_config(git_rerere_config); + if (!is_rerere_enabled()) + return -1; merge_rr_path = xstrdup(git_path("rr-cache/MERGE_RR")); fd = hold_lock_file_for_update(&write_lock, merge_rr_path, 1); - read_rr(&merge_rr); + read_rr(merge_rr); + return fd; +} + +int rerere(void) +{ + struct path_list merge_rr = { NULL, 0, 0, 1 }; + int fd; + + fd = setup_rerere(&merge_rr); + if (fd < 0) + return 0; + return do_plain_rerere(&merge_rr, fd); +} + +int cmd_rerere(int argc, const char **argv, const char *prefix) +{ + struct path_list merge_rr = { NULL, 0, 0, 1 }; + int i, fd; + + fd = setup_rerere(&merge_rr); + if (fd < 0) + return 0; if (argc < 2) return do_plain_rerere(&merge_rr, fd); else if (!strcmp(argv[1], "clear")) { for (i = 0; i < merge_rr.nr; i++) { + struct stat st; const char *name = (const char *)merge_rr.items[i].util; if (!stat(git_path("rr-cache/%s", name), &st) && S_ISDIR(st.st_mode) && @@ -422,4 +452,3 @@ int cmd_rerere(int argc, const char **argv, const char *prefix) path_list_clear(&merge_rr, 1); return 0; } -