summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 612702e)
raw | patch | inline | side by side (parent: 612702e)
author | Junio C Hamano <junkio@cox.net> | |
Sat, 21 Oct 2006 07:41:38 +0000 (00:41 -0700) | ||
committer | Junio C Hamano <junkio@cox.net> | |
Sat, 21 Oct 2006 07:41:38 +0000 (00:41 -0700) |
It used to be that we can compare the address of the origin
structure to determine if they are the same because they are
always registered with scoreboard. After introduction of the
loop to try finding the best split, that is not true anymore.
The current code has rather serious leaks with origin structure,
but more importantly it gets confused when two origins that
points at the same commit and same path.
We might eventually have to refcount and gc origin, but let's
fix the correctness issue first.
Signed-off-by: Junio C Hamano <junkio@cox.net>
structure to determine if they are the same because they are
always registered with scoreboard. After introduction of the
loop to try finding the best split, that is not true anymore.
The current code has rather serious leaks with origin structure,
but more importantly it gets confused when two origins that
points at the same commit and same path.
We might eventually have to refcount and gc origin, but let's
fix the correctness issue first.
Signed-off-by: Junio C Hamano <junkio@cox.net>
builtin-pickaxe.c | patch | blob | history |
diff --git a/builtin-pickaxe.c b/builtin-pickaxe.c
index e628b5a807600c7555e10e6f40f45cf11f1a6055..3ab87efac7171e690f227ed7315fb0c22c2b7357 100644 (file)
--- a/builtin-pickaxe.c
+++ b/builtin-pickaxe.c
int *lineno;
};
+static int cmp_suspect(struct origin *a, struct origin *b)
+{
+ int cmp = hashcmp(a->commit->object.sha1, b->commit->object.sha1);
+ if (cmp)
+ return cmp;
+ return strcmp(a->path, b->path);
+}
+
static void coalesce(struct scoreboard *sb)
{
struct blame_entry *ent, *next;
for (ent = sb->ent; ent && (next = ent->next); ent = next) {
- if (ent->suspect == next->suspect &&
+ if (!cmp_suspect(ent->suspect, next->suspect) &&
ent->guilty == next->guilty &&
ent->s_lno + ent->num_lines == next->s_lno) {
ent->num_lines += next->num_lines;
if (ent->next)
ent->next->prev = ent;
free(next);
+ ent->score = 0;
next = ent; /* again */
}
}
int last_in_target = -1;
for (e = sb->ent; e; e = e->next) {
- if (e->guilty || e->suspect != target)
+ if (e->guilty || cmp_suspect(e->suspect, target))
continue;
if (last_in_target < e->s_lno + e->num_lines)
last_in_target = e->s_lno + e->num_lines;
struct blame_entry *e;
for (e = sb->ent; e; e = e->next) {
- if (e->guilty || e->suspect != target)
+ if (e->guilty || cmp_suspect(e->suspect, target))
continue;
if (same <= e->s_lno)
continue;
struct origin *parent)
{
int last_in_target;
- struct blame_entry *ent, split[3];
+ struct blame_entry *e, split[3];
mmfile_t file_p;
char type[10];
char *blob_p;
return 0;
}
- for (ent = sb->ent; ent; ent = ent->next) {
- if (ent->suspect != target || ent->guilty)
+ for (e = sb->ent; e; e = e->next) {
+ if (e->guilty || cmp_suspect(e->suspect, target))
continue;
- find_copy_in_blob(sb, ent, parent, split, &file_p);
+ find_copy_in_blob(sb, e, parent, split, &file_p);
if (split[1].suspect &&
blame_move_score < ent_score(sb, &split[1]))
- split_blame(sb, split, ent);
+ split_blame(sb, split, e);
}
free(blob_p);
return 0;
{
struct diff_options diff_opts;
const char *paths[1];
- struct blame_entry *ent;
+ struct blame_entry *e;
int i;
if (find_last_in_target(sb, target) < 0)
"", &diff_opts);
diffcore_std(&diff_opts);
- for (ent = sb->ent; ent; ent = ent->next) {
+ for (e = sb->ent; e; e = e->next) {
struct blame_entry split[3];
- if (ent->suspect != target || ent->guilty)
+ if (e->guilty || cmp_suspect(e->suspect, target))
continue;
memset(split, 0, sizeof(split));
free(blob);
continue;
}
- find_copy_in_blob(sb, ent, norigin, this, &file_p);
+ find_copy_in_blob(sb, e, norigin, this, &file_p);
copy_split_if_better(sb, split, this);
}
if (split[1].suspect &&
blame_copy_score < ent_score(sb, &split[1]))
- split_blame(sb, split, ent);
+ split_blame(sb, split, e);
}
diff_flush(&diff_opts);
for (e = sb->ent; e; e = e->next)
if (e->suspect == origin)
e->suspect = porigin;
- /* now everything blamed for origin is blamed for
- * porigin, we do not need to keep it anymore.
- * Do not free porigin (or the ones we got from
- * earlier round); they may still be used elsewhere.
- */
- free_origin(origin);
return;
}
parent_origin[i] = porigin;
@@ -834,8 +837,10 @@ static void assign_blame(struct scoreboard *sb, struct rev_info *revs, int opt)
/* Take responsibility for the remaining entries */
for (ent = sb->ent; ent; ent = ent->next)
- if (ent->suspect == suspect)
+ if (!cmp_suspect(ent->suspect, suspect))
ent->guilty = 1;
+
+ coalesce(sb);
}
}