Merge branch 'jt/partial-clone-fsck-connectivity'
[gitweb.git] / blame.c
diff --git a/blame.c b/blame.c
index 14d0e0b5751c2abaad16dac81a71436ca29ddde4..0c4490a35bbda9d5c85c9f223f1ae64777ad6391 100644 (file)
--- a/blame.c
+++ b/blame.c
@@ -1,11 +1,31 @@
 #include "cache.h"
 #include "refs.h"
+#include "object-store.h"
 #include "cache-tree.h"
 #include "mergesort.h"
 #include "diff.h"
 #include "diffcore.h"
 #include "tag.h"
 #include "blame.h"
+#include "alloc.h"
+#include "commit-slab.h"
+
+define_commit_slab(blame_suspects, struct blame_origin *);
+static struct blame_suspects blame_suspects;
+
+struct blame_origin *get_blame_suspects(struct commit *commit)
+{
+       struct blame_origin **result;
+
+       result = blame_suspects_peek(&blame_suspects, commit);
+
+       return result ? *result : NULL;
+}
+
+static void set_blame_suspects(struct commit *commit, struct blame_origin *origin)
+{
+       *blame_suspects_at(&blame_suspects, commit) = origin;
+}
 
 void blame_origin_decref(struct blame_origin *o)
 {
@@ -15,12 +35,12 @@ void blame_origin_decref(struct blame_origin *o)
                        blame_origin_decref(o->previous);
                free(o->file.ptr);
                /* Should be present exactly once in commit chain */
-               for (p = o->commit->util; p; l = p, p = p->next) {
+               for (p = get_blame_suspects(o->commit); p; l = p, p = p->next) {
                        if (p == o) {
                                if (l)
                                        l->next = p->next;
                                else
-                                       o->commit->util = p->next;
+                                       set_blame_suspects(o->commit, p->next);
                                free(o);
                                return;
                        }
@@ -41,8 +61,8 @@ static struct blame_origin *make_origin(struct commit *commit, const char *path)
        FLEX_ALLOC_STR(o, path, path);
        o->commit = commit;
        o->refcnt = 1;
-       o->next = commit->util;
-       commit->util = o;
+       o->next = get_blame_suspects(commit);
+       set_blame_suspects(commit, o);
        return o;
 }
 
@@ -54,13 +74,13 @@ static struct blame_origin *get_origin(struct commit *commit, const char *path)
 {
        struct blame_origin *o, *l;
 
-       for (o = commit->util, l = NULL; o; l = o, o = o->next) {
+       for (o = get_blame_suspects(commit), l = NULL; o; l = o, o = o->next) {
                if (!strcmp(o->path, path)) {
                        /* bump to front */
                        if (l) {
                                l->next = o->next;
-                               o->next = commit->util;
-                               commit->util = o;
+                               o->next = get_blame_suspects(commit);
+                               set_blame_suspects(commit, o);
                        }
                        return blame_origin_incref(o);
                }
@@ -110,17 +130,19 @@ static void append_merge_parents(struct commit_list **tail)
        int merge_head;
        struct strbuf line = STRBUF_INIT;
 
-       merge_head = open(git_path_merge_head(), O_RDONLY);
+       merge_head = open(git_path_merge_head(the_repository), O_RDONLY);
        if (merge_head < 0) {
                if (errno == ENOENT)
                        return;
-               die("cannot open '%s' for reading", git_path_merge_head());
+               die("cannot open '%s' for reading",
+                   git_path_merge_head(the_repository));
        }
 
        while (!strbuf_getwholeline_fd(&line, merge_head, '\n')) {
                struct object_id oid;
                if (line.len < GIT_SHA1_HEXSZ || get_oid_hex(line.buf, &oid))
-                       die("unknown line in '%s': %s", git_path_merge_head(), line.buf);
+                       die("unknown line in '%s': %s",
+                           git_path_merge_head(the_repository), line.buf);
                tail = append_parent(tail, &oid);
        }
        close(merge_head);
@@ -161,7 +183,7 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,
 
        read_cache();
        time(&now);
-       commit = alloc_commit_node();
+       commit = alloc_commit_node(the_repository);
        commit->object.parsed = 1;
        commit->date = now;
        parent_tail = &commit->parents;
@@ -478,7 +500,7 @@ static void queue_blames(struct blame_scoreboard *sb, struct blame_origin *porig
                porigin->suspects = blame_merge(porigin->suspects, sorted);
        else {
                struct blame_origin *o;
-               for (o = porigin->commit->util; o; o = o->next) {
+               for (o = get_blame_suspects(porigin->commit); o; o = o->next) {
                        if (o->suspects) {
                                porigin->suspects = sorted;
                                return;
@@ -525,7 +547,7 @@ static struct blame_origin *find_origin(struct commit *parent,
        const char *paths[2];
 
        /* First check any existing origins */
-       for (porigin = parent->util; porigin; porigin = porigin->next)
+       for (porigin = get_blame_suspects(parent); porigin; porigin = porigin->next)
                if (!strcmp(porigin->path, origin->path)) {
                        /*
                         * The same path between origin and its parent
@@ -1550,7 +1572,7 @@ void assign_blame(struct blame_scoreboard *sb, int opt)
 
        while (commit) {
                struct blame_entry *ent;
-               struct blame_origin *suspect = commit->util;
+               struct blame_origin *suspect = get_blame_suspects(commit);
 
                /* find one suspect to break down */
                while (suspect && !suspect->suspects)
@@ -1752,6 +1774,8 @@ void setup_scoreboard(struct blame_scoreboard *sb, const char *path, struct blam
        struct commit *final_commit = NULL;
        enum object_type type;
 
+       init_blame_suspects(&blame_suspects);
+
        if (sb->reverse && sb->contents_from)
                die(_("--contents and --reverse do not blend well."));
 
@@ -1815,7 +1839,7 @@ void setup_scoreboard(struct blame_scoreboard *sb, const char *path, struct blam
        }
 
        if (is_null_oid(&sb->final->object.oid)) {
-               o = sb->final->util;
+               o = get_blame_suspects(sb->final);
                sb->final_buf = xmemdupz(o->file.ptr, o->file.size);
                sb->final_buf_size = o->file.size;
        }