Documentation: don't assume git-sh-setup and git-parse-remote are in PATH
[gitweb.git] / builtin-blame.c
index c158d319dce78c6b1f0cfeffd91ee565a2d14eff..b451f6c64dde8ce6358bb5c8dfccc8bad181a6bb 100644 (file)
@@ -123,13 +123,19 @@ static inline struct origin *origin_incref(struct origin *o)
 static void origin_decref(struct origin *o)
 {
        if (o && --o->refcnt <= 0) {
-               if (o->file.ptr)
-                       free(o->file.ptr);
-               memset(o, 0, sizeof(*o));
+               free(o->file.ptr);
                free(o);
        }
 }
 
+static void drop_origin_blob(struct origin *o)
+{
+       if (o->file.ptr) {
+               free(o->file.ptr);
+               o->file.ptr = NULL;
+       }
+}
+
 /*
  * Each group of lines is described by a blame_entry; it can be split
  * as we pass blame to the parents.  They form a linked list in the
@@ -380,6 +386,7 @@ static struct origin *find_origin(struct scoreboard *sb,
                }
        }
        diff_flush(&diff_opts);
+       diff_tree_release_paths(&diff_opts);
        if (porigin) {
                /*
                 * Create a freestanding copy that is not part of
@@ -436,6 +443,7 @@ static struct origin *find_rename(struct scoreboard *sb,
                }
        }
        diff_flush(&diff_opts);
+       diff_tree_release_paths(&diff_opts);
        return porigin;
 }
 
@@ -532,7 +540,7 @@ static struct patch *compare_buffer(mmfile_t *file_p, mmfile_t *file_o,
        state.ret->chunks = NULL;
        state.ret->num = 0;
 
-       xdl_diff(file_p, file_o, &xpp, &xecfg, &ecb);
+       xdi_diff(file_p, file_o, &xpp, &xecfg, &ecb);
 
        if (state.ret->num) {
                struct chunk *chunk;
@@ -597,7 +605,7 @@ static void add_blame_entry(struct scoreboard *sb, struct blame_entry *e)
 
 /*
  * src typically is on-stack; we want to copy the information in it to
- * an malloced blame_entry that is already on the linked list of the
+ * a malloced blame_entry that is already on the linked list of the
  * scoreboard.  The origin of dst loses a refcnt while the origin of src
  * gains one.
  */
@@ -1157,7 +1165,7 @@ static int find_copy_in_parent(struct scoreboard *sb,
                }
        }
        diff_flush(&diff_opts);
-
+       diff_tree_release_paths(&diff_opts);
        return retval;
 }
 
@@ -1274,8 +1282,13 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
                }
 
  finish:
-       for (i = 0; i < MAXPARENT; i++)
-               origin_decref(parent_origin[i]);
+       for (i = 0; i < MAXPARENT; i++) {
+               if (parent_origin[i]) {
+                       drop_origin_blob(parent_origin[i]);
+                       origin_decref(parent_origin[i]);
+               }
+       }
+       drop_origin_blob(origin);
 }
 
 /*
@@ -1880,9 +1893,7 @@ static unsigned parse_score(const char *arg)
 
 static const char *add_prefix(const char *prefix, const char *path)
 {
-       if (!prefix || !prefix[0])
-               return path;
-       return prefix_path(prefix, strlen(prefix), path);
+       return prefix_path(prefix, prefix ? strlen(prefix) : 0, path);
 }
 
 /*
@@ -1982,7 +1993,7 @@ static void prepare_blame_range(struct scoreboard *sb,
                usage(blame_usage);
 }
 
-static int git_blame_config(const char *var, const char *value)
+static int git_blame_config(const char *var, const char *value, void *cb)
 {
        if (!strcmp(var, "blame.showroot")) {
                show_root = git_config_bool(var, value);
@@ -1992,7 +2003,7 @@ static int git_blame_config(const char *var, const char *value)
                blank_boundary = git_config_bool(var, value);
                return 0;
        }
-       return git_default_config(var, value);
+       return git_default_config(var, value, cb);
 }
 
 static struct commit *fake_working_tree_commit(const char *path, const char *contents_from)
@@ -2059,7 +2070,7 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con
                if (strbuf_read(&buf, 0, 0) < 0)
                        die("read error %s from stdin", strerror(errno));
        }
-       convert_to_git(path, buf.buf, buf.len, &buf);
+       convert_to_git(path, buf.buf, buf.len, &buf, 0);
        origin->file.ptr = buf.buf;
        origin->file.size = buf.len;
        pretend_sha1_file(buf.buf, buf.len, OBJ_BLOB, origin->blob_sha1);
@@ -2078,7 +2089,7 @@ static struct commit *fake_working_tree_commit(const char *path, const char *con
        if (!mode) {
                int pos = cache_name_pos(path, len);
                if (0 <= pos)
-                       mode = ntohl(active_cache[pos]->ce_mode);
+                       mode = active_cache[pos]->ce_mode;
                else
                        /* Let's not bother reading from HEAD tree */
                        mode = S_IFREG | 0644;
@@ -2130,7 +2141,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
 
        cmd_is_annotate = !strcmp(argv[0], "annotate");
 
-       git_config(git_blame_config);
+       git_config(git_blame_config, NULL);
        save_commit_buffer = 0;
 
        opt = 0;
@@ -2355,7 +2366,8 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
         * bottom commits we would reach while traversing as
         * uninteresting.
         */
-       prepare_revision_walk(&revs);
+       if (prepare_revision_walk(&revs))
+               die("revision walk setup failed");
 
        if (is_null_sha1(sb.final->object.sha1)) {
                char *buf;