]> git.ipfire.org Git - thirdparty/git.git/blobdiff - diff.c
Merge branch 'en/ort-perf-batch-9'
[thirdparty/git.git] / diff.c
diff --git a/diff.c b/diff.c
index 69e3bc00ed8f72ad8d012175541166a6cec4ffcd..4acccd9d7edbb9e097a1d5b8b3bc2ff0ebf3acdb 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -2233,14 +2233,12 @@ static void init_diff_words_data(struct emit_callback *ecbdata,
        struct diff_options *o = xmalloc(sizeof(struct diff_options));
        memcpy(o, orig_opts, sizeof(struct diff_options));
 
-       ecbdata->diff_words =
-               xcalloc(1, sizeof(struct diff_words_data));
+       CALLOC_ARRAY(ecbdata->diff_words, 1);
        ecbdata->diff_words->type = o->word_diff;
        ecbdata->diff_words->opt = o;
 
        if (orig_opts->emitted_symbols)
-               o->emitted_symbols =
-                       xcalloc(1, sizeof(struct emitted_diff_symbols));
+               CALLOC_ARRAY(o->emitted_symbols, 1);
 
        if (!o->word_regex)
                o->word_regex = userdiff_word_regex(one, o->repo->index);
@@ -2509,7 +2507,7 @@ static struct diffstat_file *diffstat_add(struct diffstat_t *diffstat,
                                          const char *name_b)
 {
        struct diffstat_file *x;
-       x = xcalloc(1, sizeof(*x));
+       CALLOC_ARRAY(x, 1);
        ALLOC_GROW(diffstat->files, diffstat->nr + 1, diffstat->alloc);
        diffstat->files[diffstat->nr++] = x;
        if (name_b) {
@@ -4918,7 +4916,7 @@ static int diff_opt_find_object(const struct option *option,
                return error(_("unable to resolve '%s'"), arg);
 
        if (!opt->objfind)
-               opt->objfind = xcalloc(1, sizeof(*opt->objfind));
+               CALLOC_ARRAY(opt->objfind, 1);
 
        opt->pickaxe_opts |= DIFF_PICKAXE_KIND_OBJFIND;
        opt->flags.recursive = 1;
@@ -5348,6 +5346,19 @@ static int diff_opt_word_diff_regex(const struct option *opt,
        return 0;
 }
 
+static int diff_opt_rotate_to(const struct option *opt, const char *arg, int unset)
+{
+       struct diff_options *options = opt->value;
+
+       BUG_ON_OPT_NEG(unset);
+       if (!strcmp(opt->long_name, "skip-to"))
+               options->skip_instead_of_rotate = 1;
+       else
+               options->skip_instead_of_rotate = 0;
+       options->rotate_to = arg;
+       return 0;
+}
+
 static void prep_parse_options(struct diff_options *options)
 {
        struct option parseopts[] = {
@@ -5599,6 +5610,12 @@ static void prep_parse_options(struct diff_options *options)
                          DIFF_PICKAXE_REGEX, PARSE_OPT_NONEG),
                OPT_FILENAME('O', NULL, &options->orderfile,
                             N_("control the order in which files appear in the output")),
+               OPT_CALLBACK_F(0, "rotate-to", options, N_("<path>"),
+                              N_("show the change in the specified path first"),
+                              PARSE_OPT_NONEG, diff_opt_rotate_to),
+               OPT_CALLBACK_F(0, "skip-to", options, N_("<path>"),
+                              N_("skip the output to the specified path"),
+                              PARSE_OPT_NONEG, diff_opt_rotate_to),
                OPT_CALLBACK_F(0, "find-object", options, N_("<object-id>"),
                               N_("look for differences that change the number of occurrences of the specified object"),
                               PARSE_OPT_NONEG, diff_opt_find_object),
@@ -6336,6 +6353,32 @@ static void diff_flush_patch_all_file_pairs(struct diff_options *o)
        }
 }
 
+static void diff_free_file(struct diff_options *options)
+{
+       if (options->close_file)
+               fclose(options->file);
+}
+
+static void diff_free_ignore_regex(struct diff_options *options)
+{
+       int i;
+
+       for (i = 0; i < options->ignore_regex_nr; i++) {
+               regfree(options->ignore_regex[i]);
+               free(options->ignore_regex[i]);
+       }
+       free(options->ignore_regex);
+}
+
+void diff_free(struct diff_options *options)
+{
+       if (options->no_free)
+               return;
+
+       diff_free_file(options);
+       diff_free_ignore_regex(options);
+}
+
 void diff_flush(struct diff_options *options)
 {
        struct diff_queue_struct *q = &diff_queued_diff;
@@ -6399,8 +6442,7 @@ void diff_flush(struct diff_options *options)
                 * options->file to /dev/null should be safe, because we
                 * aren't supposed to produce any output anyway.
                 */
-               if (options->close_file)
-                       fclose(options->file);
+               diff_free_file(options);
                options->file = xfopen("/dev/null", "w");
                options->close_file = 1;
                options->color_moved = 0;
@@ -6433,8 +6475,7 @@ void diff_flush(struct diff_options *options)
 free_queue:
        free(q->queue);
        DIFF_QUEUE_CLEAR(q);
-       if (options->close_file)
-               fclose(options->file);
+       diff_free(options);
 
        /*
         * Report the content-level differences with HAS_CHANGES;
@@ -6669,6 +6710,8 @@ void diffcore_std(struct diff_options *options)
                diffcore_pickaxe(options);
        if (options->orderfile)
                diffcore_order(options->orderfile);
+       if (options->rotate_to)
+               diffcore_rotate(options);
        if (!options->found_follow)
                /* See try_to_follow_renames() in tree-diff.c */
                diff_resolve_rename_copy();