merge-recursive: Remember to free generated unique path names
[gitweb.git] / diff.c
diff --git a/diff.c b/diff.c
index 5376d01e1b26f0297e20f14bd8adcfefd374ab08..559bf574a88f97402f32e1bd4ab51f6f0c9d5026 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -1050,8 +1050,16 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)
                        emit_line(ecbdata->opt, plain, reset, line, len);
                        fputs("~\n", ecbdata->opt->file);
                } else {
-                       /* don't print the prefix character */
-                       emit_line(ecbdata->opt, plain, reset, line+1, len-1);
+                       /*
+                        * Skip the prefix character, if any.  With
+                        * diff_suppress_blank_empty, there may be
+                        * none.
+                        */
+                       if (line[0] != '\n') {
+                             line++;
+                             len--;
+                       }
+                       emit_line(ecbdata->opt, plain, reset, line, len);
                }
                return;
        }
@@ -3987,6 +3995,28 @@ static int is_summary_empty(const struct diff_queue_struct *q)
        return 1;
 }
 
+static const char rename_limit_warning[] =
+"inexact rename detection was skipped due to too many files.";
+
+static const char degrade_cc_to_c_warning[] =
+"only found copies from modified paths due to too many files.";
+
+static const char rename_limit_advice[] =
+"you may want to set your %s variable to at least "
+"%d and retry the command.";
+
+void diff_warn_rename_limit(const char *varname, int needed, int degraded_cc)
+{
+       if (degraded_cc)
+               warning(degrade_cc_to_c_warning);
+       else if (needed)
+               warning(rename_limit_warning);
+       else
+               return;
+       if (0 < needed && needed < 32767)
+               warning(rename_limit_advice, varname, needed);
+}
+
 void diff_flush(struct diff_options *options)
 {
        struct diff_queue_struct *q = &diff_queued_diff;
@@ -4268,6 +4298,10 @@ void diffcore_std(struct diff_options *options)
 int diff_result_code(struct diff_options *opt, int status)
 {
        int result = 0;
+
+       diff_warn_rename_limit("diff.renamelimit",
+                              opt->needed_rename_limit,
+                              opt->degraded_cc_to_c);
        if (!DIFF_OPT_TST(opt, EXIT_WITH_STATUS) &&
            !(opt->output_format & DIFF_FORMAT_CHECKDIFF))
                return status;
@@ -4381,20 +4415,20 @@ void diff_change(struct diff_options *options,
                DIFF_OPT_SET(options, HAS_CHANGES);
 }
 
-void diff_unmerge(struct diff_options *options,
-                 const char *path,
-                 unsigned mode, const unsigned char *sha1)
+struct diff_filepair *diff_unmerge(struct diff_options *options, const char *path)
 {
+       struct diff_filepair *pair;
        struct diff_filespec *one, *two;
 
        if (options->prefix &&
            strncmp(path, options->prefix, options->prefix_length))
-               return;
+               return NULL;
 
        one = alloc_filespec(path);
        two = alloc_filespec(path);
-       fill_filespec(one, sha1, mode);
-       diff_queue(&diff_queued_diff, one, two)->is_unmerged = 1;
+       pair = diff_queue(&diff_queued_diff, one, two);
+       pair->is_unmerged = 1;
+       return pair;
 }
 
 static char *run_textconv(const char *pgm, struct diff_filespec *spec,