git-apply(1): Clarify that one can select where to apply the patch
[gitweb.git] / diff.c
diff --git a/diff.c b/diff.c
index 11798af0c190f369e8ac9cb0463f794bc3bb5d10..dcfbcb0215766efefa786b18d793c4bf96740b8c 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -30,14 +30,14 @@ int diff_auto_refresh_index = 1;
 static int diff_mnemonic_prefix;
 
 static char diff_colors[][COLOR_MAXLEN] = {
-       "\033[m",       /* reset */
-       "",             /* PLAIN (normal) */
-       "\033[1m",      /* METAINFO (bold) */
-       "\033[36m",     /* FRAGINFO (cyan) */
-       "\033[31m",     /* OLD (red) */
-       "\033[32m",     /* NEW (green) */
-       "\033[33m",     /* COMMIT (yellow) */
-       "\033[41m",     /* WHITESPACE (red background) */
+       GIT_COLOR_RESET,
+       GIT_COLOR_NORMAL,       /* PLAIN */
+       GIT_COLOR_BOLD,         /* METAINFO */
+       GIT_COLOR_CYAN,         /* FRAGINFO */
+       GIT_COLOR_RED,          /* OLD */
+       GIT_COLOR_GREEN,        /* NEW */
+       GIT_COLOR_YELLOW,       /* COMMIT */
+       GIT_COLOR_BG_RED,       /* WHITESPACE */
 };
 
 static void diff_filespec_load_driver(struct diff_filespec *one);
@@ -62,6 +62,15 @@ static int parse_diff_color_slot(const char *var, int ofs)
        die("bad config variable '%s'", var);
 }
 
+static int git_config_rename(const char *var, const char *value)
+{
+       if (!value)
+               return DIFF_DETECT_RENAME;
+       if (!strcasecmp(value, "copies") || !strcasecmp(value, "copy"))
+               return  DIFF_DETECT_COPY;
+       return git_config_bool(var,value) ? DIFF_DETECT_RENAME : 0;
+}
+
 /*
  * These are to give UI layer defaults.
  * The core-level commands such as git-diff-files should
@@ -75,13 +84,7 @@ int git_diff_ui_config(const char *var, const char *value, void *cb)
                return 0;
        }
        if (!strcmp(var, "diff.renames")) {
-               if (!value)
-                       diff_detect_rename_default = DIFF_DETECT_RENAME;
-               else if (!strcasecmp(value, "copies") ||
-                        !strcasecmp(value, "copy"))
-                       diff_detect_rename_default = DIFF_DETECT_COPY;
-               else if (git_config_bool(var,value))
-                       diff_detect_rename_default = DIFF_DETECT_RENAME;
+               diff_detect_rename_default = git_config_rename(var, value);
                return 0;
        }
        if (!strcmp(var, "diff.autorefreshindex")) {
@@ -186,7 +189,7 @@ 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(diff_temp[i].name);
+                       unlink_or_warn(diff_temp[i].name);
                diff_temp[i].name = NULL;
        }
 }
@@ -836,10 +839,9 @@ static int scale_linear(int it, int width, int max_change)
 }
 
 static void show_name(FILE *file,
-                     const char *prefix, const char *name, int len,
-                     const char *reset, const char *set)
+                     const char *prefix, const char *name, int len)
 {
-       fprintf(file, " %s%s%-*s%s |", set, prefix, len, name, reset);
+       fprintf(file, " %s%-*s |", prefix, len, name);
 }
 
 static void show_graph(FILE *file, char ch, int cnt, const char *set, const char *reset)
@@ -873,9 +875,9 @@ static void fill_print_name(struct diffstat_file *file)
        file->print_name = pname;
 }
 
-static void show_stats(struct diffstat_tdata, struct diff_options *options)
+static void show_stats(struct diffstat_t *data, struct diff_options *options)
 {
-       int i, len, add, del, total, adds = 0, dels = 0;
+       int i, len, add, del, adds = 0, dels = 0;
        int max_change = 0, max_len = 0;
        int total_files = data->nr;
        int width, name_width;
@@ -953,7 +955,7 @@ static void show_stats(struct diffstat_t* data, struct diff_options *options)
                }
 
                if (data->files[i]->is_binary) {
-                       show_name(options->file, prefix, name, len, reset, set);
+                       show_name(options->file, prefix, name, len);
                        fprintf(options->file, "  Bin ");
                        fprintf(options->file, "%s%d%s", del_c, deleted, reset);
                        fprintf(options->file, " -> ");
@@ -963,7 +965,7 @@ static void show_stats(struct diffstat_t* data, struct diff_options *options)
                        continue;
                }
                else if (data->files[i]->is_unmerged) {
-                       show_name(options->file, prefix, name, len, reset, set);
+                       show_name(options->file, prefix, name, len);
                        fprintf(options->file, "  Unmerged\n");
                        continue;
                }
@@ -978,16 +980,14 @@ static void show_stats(struct diffstat_t* data, struct diff_options *options)
                 */
                add = added;
                del = deleted;
-               total = add + del;
                adds += add;
                dels += del;
 
                if (width <= max_change) {
                        add = scale_linear(add, width, max_change);
                        del = scale_linear(del, width, max_change);
-                       total = add + del;
                }
-               show_name(options->file, prefix, name, len, reset, set);
+               show_name(options->file, prefix, name, len);
                fprintf(options->file, "%5d%s", added + deleted,
                                added + deleted ? " " : "");
                show_graph(options->file, '+', add, add_c, reset);
@@ -995,8 +995,8 @@ static void show_stats(struct diffstat_t* data, struct diff_options *options)
                fprintf(options->file, "\n");
        }
        fprintf(options->file,
-              "%s %d files changed, %d insertions(+), %d deletions(-)%s\n",
-              set, total_files, adds, dels, reset);
+              " %d files changed, %d insertions(+), %d deletions(-)\n",
+              total_files, adds, dels);
 }
 
 static void show_shortstats(struct diffstat_t* data, struct diff_options *options)
@@ -1024,7 +1024,7 @@ static void show_shortstats(struct diffstat_t* data, struct diff_options *option
               total_files, adds, dels);
 }
 
-static void show_numstat(struct diffstat_tdata, struct diff_options *options)
+static void show_numstat(struct diffstat_t *data, struct diff_options *options)
 {
        int i;
 
@@ -1759,7 +1759,8 @@ static int reuse_worktree_file(const char *name, const unsigned char *sha1, int
        struct stat st;
        int pos, len;
 
-       /* We do not read the cache ourselves here, because the
+       /*
+        * We do not read the cache ourselves here, because the
         * benchmark with my previous version that always reads cache
         * shows that it makes things worse for diff-tree comparing
         * two linux-2.6 kernel trees in an already checked out work
@@ -1783,7 +1784,7 @@ static int reuse_worktree_file(const char *name, const unsigned char *sha1, int
         * objects however would tend to be slower as they need
         * to be individually opened and inflated.
         */
-       if (!FAST_WORKING_DIRECTORY && !want_file && has_sha1_pack(sha1, NULL))
+       if (!FAST_WORKING_DIRECTORY && !want_file && has_sha1_pack(sha1))
                return 0;
 
        len = strlen(name);
@@ -1799,6 +1800,13 @@ static int reuse_worktree_file(const char *name, const unsigned char *sha1, int
        if (hashcmp(sha1, ce->sha1) || !S_ISREG(ce->ce_mode))
                return 0;
 
+       /*
+        * If ce is marked as "assume unchanged", there is no
+        * guarantee that work tree matches what we are looking for.
+        */
+       if (ce->ce_flags & CE_VALID)
+               return 0;
+
        /*
         * If ce matches the file in the work tree, we can reuse it.
         */
@@ -2006,18 +2014,15 @@ static struct diff_tempfile *prepare_temp_file(const char *name,
                        die("stat(%s): %s", name, strerror(errno));
                }
                if (S_ISLNK(st.st_mode)) {
-                       int ret;
-                       char buf[PATH_MAX + 1]; /* ought to be SYMLINK_MAX */
-                       ret = readlink(name, buf, sizeof(buf));
-                       if (ret < 0)
+                       struct strbuf sb = STRBUF_INIT;
+                       if (strbuf_readlink(&sb, name, st.st_size) < 0)
                                die("readlink(%s)", name);
-                       if (ret == sizeof(buf))
-                               die("symlink too long: %s", name);
-                       prep_temp_blob(name, temp, buf, ret,
+                       prep_temp_blob(name, temp, sb.buf, sb.len,
                                       (one->sha1_valid ?
                                        one->sha1 : null_sha1),
                                       (one->sha1_valid ?
                                        one->mode : S_IFLNK));
+                       strbuf_release(&sb);
                }
                else {
                        /* we can borrow from the file in the work tree */
@@ -2574,13 +2579,13 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
 
        /* xdiff options */
        else if (!strcmp(arg, "-w") || !strcmp(arg, "--ignore-all-space"))
-               options->xdl_opts |= XDF_IGNORE_WHITESPACE;
+               DIFF_XDL_SET(options, IGNORE_WHITESPACE);
        else if (!strcmp(arg, "-b") || !strcmp(arg, "--ignore-space-change"))
-               options->xdl_opts |= XDF_IGNORE_WHITESPACE_CHANGE;
+               DIFF_XDL_SET(options, IGNORE_WHITESPACE_CHANGE);
        else if (!strcmp(arg, "--ignore-space-at-eol"))
-               options->xdl_opts |= XDF_IGNORE_WHITESPACE_AT_EOL;
+               DIFF_XDL_SET(options, IGNORE_WHITESPACE_AT_EOL);
        else if (!strcmp(arg, "--patience"))
-               options->xdl_opts |= XDF_PATIENCE_DIFF;
+               DIFF_XDL_SET(options, PATIENCE_DIFF);
 
        /* flags options */
        else if (!strcmp(arg, "--binary")) {
@@ -2601,10 +2606,13 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
                DIFF_OPT_SET(options, COLOR_DIFF);
        else if (!strcmp(arg, "--no-color"))
                DIFF_OPT_CLR(options, COLOR_DIFF);
-       else if (!strcmp(arg, "--color-words"))
-               options->flags |= DIFF_OPT_COLOR_DIFF | DIFF_OPT_COLOR_DIFF_WORDS;
+       else if (!strcmp(arg, "--color-words")) {
+               DIFF_OPT_SET(options, COLOR_DIFF);
+               DIFF_OPT_SET(options, COLOR_DIFF_WORDS);
+       }
        else if (!prefixcmp(arg, "--color-words=")) {
-               options->flags |= DIFF_OPT_COLOR_DIFF | DIFF_OPT_COLOR_DIFF_WORDS;
+               DIFF_OPT_SET(options, COLOR_DIFF);
+               DIFF_OPT_SET(options, COLOR_DIFF_WORDS);
                options->word_regex = arg + 14;
        }
        else if (!strcmp(arg, "--exit-code"))