rerere: return strbuf from handle path

Currently we write the conflict to disk directly in the handle_path function. To make it re-usable for nested conflicts, instead of writing the conflict out directly, store it in a strbuf and let the caller write it out. This does mean some slight increase in memory usage, however that increase is limited to the size of the largest conflict we've currently processed. We already keep one copy of the conflict in memory, and it shouldn't be too large, so the increase in memory usage seems acceptable. As a bonus this lets us get replace the rerere_io_putconflict function with a trivial two line function. Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Thomas Gummerer committed Aug 5, 2018 at 18:20 UTC 5ebbdad3447ccaaf5af18a5f4f8f5065bd9fff3d
1 file changed +18 -40
rerere.c
+18 -40
@@ -302,38 +302,6 @@ static void rerere_io_putstr(const char *str, struct rerere_io *io)
302 ferr_puts(str, io->output, &io->wrerror);
303 }
304
305 -/*
306 - * Write a conflict marker to io->output (if defined).
307 - */
308 -static void rerere_io_putconflict(int ch, int size, struct rerere_io *io)
309 -{
310 - char buf[64];
311 -
312 - while (size) {
313 - if (size <= sizeof(buf) - 2) {
314 - memset(buf, ch, size);
315 - buf[size] = '\n';
316 - buf[size + 1] = '\0';
317 - size = 0;
318 - } else {
319 - int sz = sizeof(buf) - 1;
320 -
321 - /*
322 - * Make sure we will not write everything out
323 - * in this round by leaving at least 1 byte
324 - * for the next round, giving the next round
325 - * a chance to add the terminating LF. Yuck.
326 - */
327 - if (size <= sz)
328 - sz -= (sz - size) + 1;
329 - memset(buf, ch, sz);
330 - buf[sz] = '\0';
331 - size -= sz;
332 - }
333 - rerere_io_putstr(buf, io);
334 - }
335 -}
336 -
305 static void rerere_io_putmem(const char *mem, size_t sz, struct rerere_io *io)
306 {
307 if (io->output)
@@ -384,7 +352,14 @@ static int is_cmarker(char *buf, int marker_char, int marker_size)
352 return isspace(*buf);
353 }
354
387 -static int handle_conflict(struct rerere_io *io, int marker_size, git_SHA_CTX *ctx)
355 +static void rerere_strbuf_putconflict(struct strbuf *buf, int ch, size_t size)
356 +{
357 + strbuf_addchars(buf, ch, size);
358 + strbuf_addch(buf, '\n');
359 +}
360 +
361 +static int handle_conflict(struct strbuf *out, struct rerere_io *io,
362 + int marker_size, git_SHA_CTX *ctx)
363 {
364 enum {
365 RR_SIDE_1 = 0, RR_SIDE_2, RR_ORIGINAL
@@ -410,11 +385,11 @@ static int handle_conflict(struct rerere_io *io, int marker_size, git_SHA_CTX *c
385 if (strbuf_cmp(&one, &two) > 0)
386 strbuf_swap(&one, &two);
387 has_conflicts = 1;
413 - rerere_io_putconflict('<', marker_size, io);
414 - rerere_io_putmem(one.buf, one.len, io);
415 - rerere_io_putconflict('=', marker_size, io);
416 - rerere_io_putmem(two.buf, two.len, io);
417 - rerere_io_putconflict('>', marker_size, io);
388 + rerere_strbuf_putconflict(out, '<', marker_size);
389 + strbuf_addbuf(out, &one);
390 + rerere_strbuf_putconflict(out, '=', marker_size);
391 + strbuf_addbuf(out, &two);
392 + rerere_strbuf_putconflict(out, '>', marker_size);
393 if (ctx) {
394 git_SHA1_Update(ctx, one.buf ? one.buf : "",
395 one.len + 1);
@@ -451,21 +426,24 @@ static int handle_conflict(struct rerere_io *io, int marker_size, git_SHA_CTX *c
426 static int handle_path(unsigned char *sha1, struct rerere_io *io, int marker_size)
427 {
428 git_SHA_CTX ctx;
454 - struct strbuf buf = STRBUF_INIT;
429 + struct strbuf buf = STRBUF_INIT, out = STRBUF_INIT;
430 int has_conflicts = 0;
431 if (sha1)
432 git_SHA1_Init(&ctx);
433
434 while (!io->getline(&buf, io)) {
435 if (is_cmarker(buf.buf, '<', marker_size)) {
461 - has_conflicts = handle_conflict(io, marker_size,
436 + has_conflicts = handle_conflict(&out, io, marker_size,
437 sha1 ? &ctx : NULL);
438 if (has_conflicts < 0)
439 break;
440 + rerere_io_putmem(out.buf, out.len, io);
441 + strbuf_reset(&out);
442 } else
443 rerere_io_putstr(buf.buf, io);
444 }
445 strbuf_release(&buf);
446 + strbuf_release(&out);
447
448 if (sha1)
449 git_SHA1_Final(sha1, &ctx);