This splits the handle_file() function into in-core part and I/O parts of the logic to create the preimage, so that we can compute the conflict identifier without having to use temporary files. Signed-off-by: Junio C Hamano <gitster@xxxxxxxxx> --- rerere.c | 117 +++++++++++++++++++++++++++++++++++++++++++------------------ 1 files changed, 82 insertions(+), 35 deletions(-) diff --git a/rerere.c b/rerere.c index 88bb4f1..f013ae7 100644 --- a/rerere.c +++ b/rerere.c @@ -83,8 +83,41 @@ static inline void ferr_puts(const char *s, FILE *fp, int *err) ferr_write(s, strlen(s), fp, err); } -static int handle_file(const char *path, - unsigned char *sha1, const char *output) +struct rerere_io { + int (*getline)(struct strbuf *, struct rerere_io *); + void (*putstr)(const char *, struct rerere_io *); + void (*putmem)(const char *, size_t, struct rerere_io *); + /* some more stuff */ +}; + +struct rerere_io_file { + struct rerere_io io; + FILE *input; + FILE *output; + int wrerror; +}; + +static int rerere_file_getline(struct strbuf *sb, struct rerere_io *io_) +{ + struct rerere_io_file *io = (struct rerere_io_file *)io_; + return strbuf_getwholeline(sb, io->input, '\n'); +} + +static void rerere_file_putstr(const char *str, struct rerere_io *io_) +{ + struct rerere_io_file *io = (struct rerere_io_file *)io_; + if (io->output) + ferr_puts(str, io->output, &io->wrerror); +} + +static void rerere_file_putmem(const char *mem, size_t sz, struct rerere_io *io_) +{ + struct rerere_io_file *io = (struct rerere_io_file *)io_; + if (io->output) + ferr_write(mem, sz, io->output, &io->wrerror); +} + +static int handle_path(unsigned char *sha1, struct rerere_io *io) { git_SHA_CTX ctx; int hunk_no = 0; @@ -93,25 +126,11 @@ static int handle_file(const char *path, } hunk = RR_CONTEXT; struct strbuf one = STRBUF_INIT, two = STRBUF_INIT; struct strbuf buf = STRBUF_INIT; - FILE *f = fopen(path, "r"); - FILE *out = NULL; - int wrerror = 0; - - if (!f) - return error("Could not open %s", path); - - if (output) { - out = fopen(output, "w"); - if (!out) { - fclose(f); - return error("Could not write %s", output); - } - } if (sha1) git_SHA1_Init(&ctx); - while (!strbuf_getwholeline(&buf, f, '\n')) { + while (!io->getline(&buf, io)) { if (!prefixcmp(buf.buf, "<<<<<<< ")) { if (hunk != RR_CONTEXT) goto bad; @@ -131,13 +150,11 @@ static int handle_file(const char *path, strbuf_swap(&one, &two); hunk_no++; hunk = RR_CONTEXT; - if (out) { - ferr_puts("<<<<<<<\n", out, &wrerror); - ferr_write(one.buf, one.len, out, &wrerror); - ferr_puts("=======\n", out, &wrerror); - ferr_write(two.buf, two.len, out, &wrerror); - ferr_puts(">>>>>>>\n", out, &wrerror); - } + io->putstr("<<<<<<<\n", io); + io->putmem(one.buf, one.len, io); + io->putstr("=======\n", io); + io->putmem(two.buf, two.len, io); + io->putstr(">>>>>>>\n", io); if (sha1) { git_SHA1_Update(&ctx, one.buf ? one.buf : "", one.len + 1); @@ -152,8 +169,8 @@ static int handle_file(const char *path, ; /* discard */ else if (hunk == RR_SIDE_2) strbuf_addstr(&two, buf.buf); - else if (out) - ferr_puts(buf.buf, out, &wrerror); + else + io->putstr(buf.buf, io); continue; bad: hunk = 99; /* force error exit */ @@ -163,21 +180,51 @@ static int handle_file(const char *path, strbuf_release(&two); strbuf_release(&buf); - fclose(f); - if (wrerror) - error("There were errors while writing %s (%s)", - path, strerror(wrerror)); - if (out && fclose(out)) - wrerror = error("Failed to flush %s: %s", - path, strerror(errno)); if (sha1) git_SHA1_Final(sha1, &ctx); - if (hunk != RR_CONTEXT) { + if (hunk != RR_CONTEXT) + return -1; + return hunk_no; +} + +static int handle_file(const char *path, unsigned char *sha1, const char *output) +{ + int hunk_no = 0; + struct rerere_io_file io; + + memset(&io, 0, sizeof(io)); + io.io.getline = rerere_file_getline; + io.io.putstr = rerere_file_putstr; + io.io.putmem = rerere_file_putmem; + io.input = fopen(path, "r"); + io.wrerror = 0; + if (!io.input) + return error("Could not open %s", path); + + if (output) { + io.output = fopen(output, "w"); + if (!io.output) { + fclose(io.input); + return error("Could not write %s", output); + } + } + + hunk_no = handle_path(sha1, (struct rerere_io *)&io); + + fclose(io.input); + if (io.wrerror) + error("There were errors while writing %s (%s)", + path, strerror(io.wrerror)); + if (io.output && fclose(io.output)) + io.wrerror = error("Failed to flush %s: %s", + path, strerror(errno)); + + if (hunk_no < 0) { if (output) unlink_or_warn(output); return error("Could not parse conflict hunks in %s", path); } - if (wrerror) + if (io.wrerror) return -1; return hunk_no; } -- 1.6.6 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html