diff options
Diffstat (limited to 'diff.c')
-rw-r--r-- | diff.c | 100 |
1 files changed, 53 insertions, 47 deletions
@@ -2,6 +2,7 @@ * Copyright (C) 2005 Junio C Hamano */ #include "cache.h" +#include "tempfile.h" #include "quote.h" #include "diff.h" #include "diffcore.h" @@ -12,7 +13,7 @@ #include "run-command.h" #include "utf8.h" #include "userdiff.h" -#include "sigchain.h" +#include "submodule-config.h" #include "submodule.h" #include "ll-merge.h" #include "string-list.h" @@ -308,11 +309,26 @@ static const char *external_diff(void) return external_diff_cmd; } +/* + * Keep track of files used for diffing. Sometimes such an entry + * refers to a temporary file, sometimes to an existing file, and + * sometimes to "/dev/null". + */ static struct diff_tempfile { - const char *name; /* filename external diff should read from */ - char hex[41]; + /* + * filename external diff should read from, or NULL if this + * entry is currently not in use: + */ + const char *name; + + char hex[GIT_SHA1_HEXSZ + 1]; char mode[10]; - char tmp_path[PATH_MAX]; + + /* + * If this diff_tempfile instance refers to a temporary file, + * this tempfile object is used to manage its lifetime. + */ + struct tempfile tempfile; } diff_temp[2]; typedef unsigned long (*sane_truncate_fn)(char *line, unsigned long len); @@ -597,25 +613,16 @@ static struct diff_tempfile *claim_diff_tempfile(void) { die("BUG: diff is failing to clean up its tempfiles"); } -static int remove_tempfile_installed; - static void remove_tempfile(void) { int i; for (i = 0; i < ARRAY_SIZE(diff_temp); i++) { - if (diff_temp[i].name == diff_temp[i].tmp_path) - unlink_or_warn(diff_temp[i].name); + if (is_tempfile_active(&diff_temp[i].tempfile)) + delete_tempfile(&diff_temp[i].tempfile); diff_temp[i].name = NULL; } } -static void remove_tempfile_on_signal(int signo) -{ - remove_tempfile(); - sigchain_pop(signo); - raise(signo); -} - static void print_line_count(FILE *file, int count) { switch (count) { @@ -1033,8 +1040,9 @@ static void diff_words_show(struct diff_words_data *diff_words) xpp.flags = 0; /* as only the hunk header will be parsed, we need a 0-context */ xecfg.ctxlen = 0; - xdi_diff_outf(&minus, &plus, fn_out_diff_words_aux, diff_words, - &xpp, &xecfg); + if (xdi_diff_outf(&minus, &plus, fn_out_diff_words_aux, diff_words, + &xpp, &xecfg)) + die("unable to generate word diff"); free(minus.ptr); free(plus.ptr); if (diff_words->current_plus != diff_words->plus.text.ptr + @@ -2441,8 +2449,9 @@ static void builtin_diff(const char *name_a, xecfg.ctxlen = strtoul(v, NULL, 10); if (o->word_diff) init_diff_words_data(&ecbdata, o, one, two); - xdi_diff_outf(&mf1, &mf2, fn_out_consume, &ecbdata, - &xpp, &xecfg); + if (xdi_diff_outf(&mf1, &mf2, fn_out_consume, &ecbdata, + &xpp, &xecfg)) + die("unable to generate diff for %s", one->path); if (o->word_diff) free_diff_words_data(&ecbdata); if (textconv_one) @@ -2519,8 +2528,9 @@ static void builtin_diffstat(const char *name_a, const char *name_b, xpp.flags = o->xdl_opts; xecfg.ctxlen = o->context; xecfg.interhunkctxlen = o->interhunkcontext; - xdi_diff_outf(&mf1, &mf2, diffstat_consume, diffstat, - &xpp, &xecfg); + if (xdi_diff_outf(&mf1, &mf2, diffstat_consume, diffstat, + &xpp, &xecfg)) + die("unable to generate diffstat for %s", one->path); } diff_free_filespec_data(one); @@ -2566,8 +2576,9 @@ static void builtin_checkdiff(const char *name_a, const char *name_b, memset(&xecfg, 0, sizeof(xecfg)); xecfg.ctxlen = 1; /* at least one context line */ xpp.flags = 0; - xdi_diff_outf(&mf1, &mf2, checkdiff_consume, &data, - &xpp, &xecfg); + if (xdi_diff_outf(&mf1, &mf2, checkdiff_consume, &data, + &xpp, &xecfg)) + die("unable to generate checkdiff for %s", one->path); if (data.ws_rule & WS_BLANK_AT_EOF) { struct emit_callback ecbdata; @@ -2858,8 +2869,7 @@ static void prep_temp_blob(const char *path, struct diff_tempfile *temp, strbuf_addstr(&template, "XXXXXX_"); strbuf_addstr(&template, base); - fd = git_mkstemps(temp->tmp_path, PATH_MAX, template.buf, - strlen(base) + 1); + fd = mks_tempfile_ts(&temp->tempfile, template.buf, strlen(base) + 1); if (fd < 0) die_errno("unable to create temp-file"); if (convert_to_working_tree(path, @@ -2869,11 +2879,10 @@ static void prep_temp_blob(const char *path, struct diff_tempfile *temp, } if (write_in_full(fd, blob, size) != size) die_errno("unable to write temp-file"); - close(fd); - temp->name = temp->tmp_path; - strcpy(temp->hex, sha1_to_hex(sha1)); - temp->hex[40] = 0; - sprintf(temp->mode, "%06o", mode); + close_tempfile(&temp->tempfile); + temp->name = get_tempfile_path(&temp->tempfile); + sha1_to_hex_r(temp->hex, sha1); + xsnprintf(temp->mode, sizeof(temp->mode), "%06o", mode); strbuf_release(&buf); strbuf_release(&template); free(path_dup); @@ -2890,17 +2899,11 @@ static struct diff_tempfile *prepare_temp_file(const char *name, * a '+' entry produces this for file-1. */ temp->name = "/dev/null"; - strcpy(temp->hex, "."); - strcpy(temp->mode, "."); + xsnprintf(temp->hex, sizeof(temp->hex), "."); + xsnprintf(temp->mode, sizeof(temp->mode), "."); return temp; } - if (!remove_tempfile_installed) { - atexit(remove_tempfile); - sigchain_push_common(remove_tempfile_on_signal); - remove_tempfile_installed = 1; - } - if (!S_ISGITLINK(one->mode) && (!one->sha1_valid || reuse_worktree_file(name, one->sha1, 1))) { @@ -2925,16 +2928,16 @@ static struct diff_tempfile *prepare_temp_file(const char *name, /* we can borrow from the file in the work tree */ temp->name = name; if (!one->sha1_valid) - strcpy(temp->hex, sha1_to_hex(null_sha1)); + sha1_to_hex_r(temp->hex, null_sha1); else - strcpy(temp->hex, sha1_to_hex(one->sha1)); + sha1_to_hex_r(temp->hex, one->sha1); /* Even though we may sometimes borrow the * contents from the work tree, we always want * one->mode. mode is trustworthy even when * !(one->sha1_valid), as long as * DIFF_FILE_VALID(one). */ - sprintf(temp->mode, "%06o", one->mode); + xsnprintf(temp->mode, sizeof(temp->mode), "%06o", one->mode); } return temp; } @@ -3820,9 +3823,10 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) DIFF_OPT_SET(options, FIND_COPIES_HARDER); else if (!strcmp(arg, "--follow")) DIFF_OPT_SET(options, FOLLOW_RENAMES); - else if (!strcmp(arg, "--no-follow")) + else if (!strcmp(arg, "--no-follow")) { DIFF_OPT_CLR(options, FOLLOW_RENAMES); - else if (!strcmp(arg, "--color")) + DIFF_OPT_CLR(options, DEFAULT_FOLLOW_RENAMES); + } else if (!strcmp(arg, "--color")) options->use_color = 1; else if (skip_prefix(arg, "--color=", &arg)) { int value = git_config_colorbool(NULL, arg); @@ -4079,9 +4083,9 @@ const char *diff_unique_abbrev(const unsigned char *sha1, int len) if (abblen < 37) { static char hex[41]; if (len < abblen && abblen <= len + 2) - sprintf(hex, "%s%.*s", abbrev, len+3-abblen, ".."); + xsnprintf(hex, sizeof(hex), "%s%.*s", abbrev, len+3-abblen, ".."); else - sprintf(hex, "%s...", abbrev); + xsnprintf(hex, sizeof(hex), "%s...", abbrev); return hex; } return sha1_to_hex(sha1); @@ -4508,8 +4512,10 @@ static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1) xpp.flags = 0; xecfg.ctxlen = 3; xecfg.flags = 0; - xdi_diff_outf(&mf1, &mf2, patch_id_consume, &data, - &xpp, &xecfg); + if (xdi_diff_outf(&mf1, &mf2, patch_id_consume, &data, + &xpp, &xecfg)) + return error("unable to generate patch-id diff for %s", + p->one->path); } git_SHA1_Final(sha1, &ctx); |