[PATCH] Make the git-fsck-objects diagnostics more useful
[git.git] / diff.c
diff --git a/diff.c b/diff.c
index bb2a43b..d8d20c2 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -19,6 +19,7 @@ static const char *external_diff(void)
 {
        static const char *external_diff_cmd = NULL;
        static int done_preparing = 0;
+       const char *env_diff_opts;
 
        if (done_preparing)
                return external_diff_cmd;
@@ -31,11 +32,11 @@ static const char *external_diff(void)
         *
         * GIT_DIFF_OPTS="-c";
         */
-       if (gitenv("GIT_EXTERNAL_DIFF"))
-               external_diff_cmd = gitenv("GIT_EXTERNAL_DIFF");
+       external_diff_cmd = getenv("GIT_EXTERNAL_DIFF");
 
        /* In case external diff fails... */
-       diff_opts = gitenv("GIT_DIFF_OPTS") ? : diff_opts;
+       env_diff_opts = getenv("GIT_DIFF_OPTS");
+       if (env_diff_opts) diff_opts = env_diff_opts;
 
        done_preparing = 1;
        return external_diff_cmd;
@@ -213,14 +214,10 @@ struct diff_filespec *alloc_filespec(const char *path)
 {
        int namelen = strlen(path);
        struct diff_filespec *spec = xmalloc(sizeof(*spec) + namelen + 1);
+
+       memset(spec, 0, sizeof(*spec));
        spec->path = (char *)(spec + 1);
-       strcpy(spec->path, path);
-       spec->should_free = spec->should_munmap = 0;
-       spec->xfrm_flags = 0;
-       spec->size = 0;
-       spec->data = NULL;
-       spec->mode = 0;
-       memset(spec->sha1, 0, 20);
+       memcpy(spec->path, path, namelen+1);
        return spec;
 }
 
@@ -405,13 +402,14 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only)
        return 0;
 }
 
-void diff_free_filespec(struct diff_filespec *s)
+void diff_free_filespec_data(struct diff_filespec *s)
 {
        if (s->should_free)
                free(s->data);
        else if (s->should_munmap)
                munmap(s->data, s->size);
-       free(s);
+       s->should_free = s->should_munmap = 0;
+       s->data = NULL;
 }
 
 static void prep_temp_blob(struct diff_tempfile *temp,
@@ -530,10 +528,12 @@ static void run_external_diff(const char *pgm,
        pid_t pid;
        int status;
        static int atexit_asked = 0;
+       const char *othername;
 
+       othername = (other? other : name);
        if (one && two) {
                prepare_temp_file(name, &temp[0], one);
-               prepare_temp_file(other ? : name, &temp[1], two);
+               prepare_temp_file(othername, &temp[1], two);
                if (! atexit_asked &&
                    (temp[0].name == temp[0].tmp_path ||
                     temp[1].name == temp[1].tmp_path)) {
@@ -574,7 +574,7 @@ static void run_external_diff(const char *pgm,
                 * otherwise we use the built-in one.
                 */
                if (one && two)
-                       builtin_diff(name, other ? : name, temp, xfrm_msg,
+                       builtin_diff(name, othername, temp, xfrm_msg,
                                     complete_rewrite);
                else
                        printf("* Unmerged path %s\n", name);
@@ -701,7 +701,7 @@ static int parse_num(const char **cp_p)
                        scale *= 10;
                        num = num * 10 + ch - '0';
                }
-               *cp++;
+               cp++;
        }
        *cp_p = cp;
 
@@ -762,14 +762,17 @@ struct diff_filepair *diff_queue(struct diff_queue_struct *queue,
        dp->status = 0;
        dp->source_stays = 0;
        dp->broken_pair = 0;
-       diff_q(queue, dp);
+       if (queue)
+               diff_q(queue, dp);
        return dp;
 }
 
 void diff_free_filepair(struct diff_filepair *p)
 {
-       diff_free_filespec(p->one);
-       diff_free_filespec(p->two);
+       diff_free_filespec_data(p->one);
+       diff_free_filespec_data(p->two);
+       free(p->one);
+       free(p->two);
        free(p);
 }
 
@@ -889,13 +892,13 @@ int diff_queue_is_empty(void)
 void diff_debug_filespec(struct diff_filespec *s, int x, const char *one)
 {
        fprintf(stderr, "queue[%d] %s (%s) %s %06o %s\n",
-               x, one ? : "",
+               x, one ? one : "",
                s->path,
                DIFF_FILE_VALID(s) ? "valid" : "invalid",
                s->mode,
                s->sha1_valid ? sha1_to_hex(s->sha1) : "");
        fprintf(stderr, "queue[%d] %s size %lu flags %d\n",
-               x, one ? : "",
+               x, one ? one : "",
                s->size, s->xfrm_flags);
 }
 
@@ -904,7 +907,7 @@ void diff_debug_filepair(const struct diff_filepair *p, int i)
        diff_debug_filespec(p->one, i, "one");
        diff_debug_filespec(p->two, i, "two");
        fprintf(stderr, "score %d, status %c stays %d broken %d\n",
-               p->score, p->status ? : '?',
+               p->score, p->status ? p->status : '?',
                p->source_stays, p->broken_pair);
 }
 
@@ -952,7 +955,9 @@ static void diff_resolve_rename_copy(void)
                        }
                        /* See if there is some other filepair that
                         * copies from the same source as us.  If so
-                        * we are a copy.  Otherwise we are a rename.
+                        * we are a copy.  Otherwise we are either a
+                        * copy if the path stays, or a rename if it
+                        * does not, but we already handled "stays" case.
                         */
                        for (j = i + 1; j < q->nr; j++) {
                                pp = q->queue[j];
@@ -1010,9 +1015,8 @@ void diff_flush(int diff_output_style, int line_termination)
                        diff_flush_name(p, line_termination);
                        break;
                }
-       }
-       for (i = 0; i < q->nr; i++)
                diff_free_filepair(q->queue[i]);
+       }
        free(q->queue);
        q->queue = NULL;
        q->nr = q->alloc = 0;