Merge branch 'sg/test-lib-simplify-expr-away' into HEAD
[gitweb.git] / diff.c
diff --git a/diff.c b/diff.c
index 46260ed7a1d521cf95342caff83a825b34959bdc..059123c5dcef4129763895b0f2ad5a54728b0c07 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -13,7 +13,6 @@
 #include "run-command.h"
 #include "utf8.h"
 #include "userdiff.h"
-#include "sigchain.h"
 #include "submodule-config.h"
 #include "submodule.h"
 #include "ll-merge.h"
@@ -322,7 +321,7 @@ static struct diff_tempfile {
         */
        const char *name;
 
-       char hex[41];
+       char hex[GIT_SHA1_HEXSZ + 1];
        char mode[10];
 
        /*
@@ -2608,12 +2607,9 @@ static void builtin_checkdiff(const char *name_a, const char *name_b,
 
 struct diff_filespec *alloc_filespec(const char *path)
 {
-       int namelen = strlen(path);
-       struct diff_filespec *spec = xmalloc(sizeof(*spec) + namelen + 1);
+       struct diff_filespec *spec;
 
-       memset(spec, 0, sizeof(*spec));
-       spec->path = (char *)(spec + 1);
-       memcpy(spec->path, path, namelen+1);
+       FLEXPTR_ALLOC_STR(spec, path, path);
        spec->count = 1;
        spec->is_binary = -1;
        return spec;
@@ -2708,21 +2704,21 @@ static int reuse_worktree_file(const char *name, const unsigned char *sha1, int
 
 static int diff_populate_gitlink(struct diff_filespec *s, int size_only)
 {
-       int len;
-       char *data = xmalloc(100), *dirty = "";
+       struct strbuf buf = STRBUF_INIT;
+       char *dirty = "";
 
        /* Are we looking at the work tree? */
        if (s->dirty_submodule)
                dirty = "-dirty";
 
-       len = snprintf(data, 100,
-                      "Subproject commit %s%s\n", sha1_to_hex(s->sha1), dirty);
-       s->data = data;
-       s->size = len;
-       s->should_free = 1;
+       strbuf_addf(&buf, "Subproject commit %s%s\n", sha1_to_hex(s->sha1), dirty);
+       s->size = buf.len;
        if (size_only) {
                s->data = NULL;
-               free(data);
+               strbuf_release(&buf);
+       } else {
+               s->data = strbuf_detach(&buf, NULL);
+               s->should_free = 1;
        }
        return 0;
 }
@@ -2882,9 +2878,8 @@ static void prep_temp_blob(const char *path, struct diff_tempfile *temp,
                die_errno("unable to write temp-file");
        close_tempfile(&temp->tempfile);
        temp->name = get_tempfile_path(&temp->tempfile);
-       strcpy(temp->hex, sha1_to_hex(sha1));
-       temp->hex[40] = 0;
-       sprintf(temp->mode, "%06o", mode);
+       sha1_to_hex_r(temp->hex, sha1);
+       xsnprintf(temp->mode, sizeof(temp->mode), "%06o", mode);
        strbuf_release(&buf);
        strbuf_release(&template);
        free(path_dup);
@@ -2901,8 +2896,8 @@ 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;
        }
 
@@ -2930,16 +2925,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;
        }
@@ -3695,12 +3690,16 @@ static int parse_ws_error_highlight(struct diff_options *opt, const char *arg)
        return 1;
 }
 
-int diff_opt_parse(struct diff_options *options, const char **av, int ac)
+int diff_opt_parse(struct diff_options *options,
+                  const char **av, int ac, const char *prefix)
 {
        const char *arg = av[0];
        const char *optarg;
        int argcount;
 
+       if (!prefix)
+               prefix = "";
+
        /* Output format options */
        if (!strcmp(arg, "-p") || !strcmp(arg, "-u") || !strcmp(arg, "--patch")
            || opt_arg(arg, 'U', "unified", &options->context))
@@ -3917,7 +3916,8 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
        else if (!strcmp(arg, "--pickaxe-regex"))
                options->pickaxe_opts |= DIFF_PICKAXE_REGEX;
        else if ((argcount = short_opt('O', av, &optarg))) {
-               options->orderfile = optarg;
+               const char *path = prefix_filename(prefix, strlen(prefix), optarg);
+               options->orderfile = xstrdup(path);
                return argcount;
        }
        else if ((argcount = parse_long_opt("diff-filter", av, &optarg))) {
@@ -3956,9 +3956,10 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
        else if (!strcmp(arg, "--no-function-context"))
                DIFF_OPT_CLR(options, FUNCCONTEXT);
        else if ((argcount = parse_long_opt("output", av, &optarg))) {
-               options->file = fopen(optarg, "w");
+               const char *path = prefix_filename(prefix, strlen(prefix), optarg);
+               options->file = fopen(path, "w");
                if (!options->file)
-                       die_errno("Could not open '%s'", optarg);
+                       die_errno("Could not open '%s'", path);
                options->close_file = 1;
                return argcount;
        } else
@@ -4085,9 +4086,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);
@@ -5081,7 +5082,7 @@ size_t fill_textconv(struct userdiff_driver *driver,
 {
        size_t size;
 
-       if (!driver || !driver->textconv) {
+       if (!driver) {
                if (!DIFF_FILE_VALID(df)) {
                        *outbuf = "";
                        return 0;
@@ -5092,6 +5093,9 @@ size_t fill_textconv(struct userdiff_driver *driver,
                return df->size;
        }
 
+       if (!driver->textconv)
+               die("BUG: fill_textconv called with non-textconv driver");
+
        if (driver->textconv_cache && df->sha1_valid) {
                *outbuf = notes_cache_get(driver->textconv_cache, df->sha1,
                                          &size);