Commit 25c47aae by Ben Straub

Detect boundaries, support limiting commit range

parent 9d42fcbe
...@@ -93,6 +93,8 @@ typedef struct git_blame_options { ...@@ -93,6 +93,8 @@ typedef struct git_blame_options {
* - `orig_start_line_number` is the 1-based line number where this hunk begins * - `orig_start_line_number` is the 1-based line number where this hunk begins
* in the file named by `orig_path` in the commit specified by * in the file named by `orig_path` in the commit specified by
* `orig_commit_id`. * `orig_commit_id`.
* - `boundary` is 1 iff the hunk has been tracked to a boundary commit (the
* root, or the commit specified in git_blame_options.oldest_commit)
*/ */
typedef struct git_blame_hunk { typedef struct git_blame_hunk {
uint16_t lines_in_hunk; uint16_t lines_in_hunk;
...@@ -103,6 +105,8 @@ typedef struct git_blame_hunk { ...@@ -103,6 +105,8 @@ typedef struct git_blame_hunk {
git_oid orig_commit_id; git_oid orig_commit_id;
const char *orig_path; const char *orig_path;
uint16_t orig_start_line_number; uint16_t orig_start_line_number;
char boundary;
} git_blame_hunk; } git_blame_hunk;
......
...@@ -247,6 +247,7 @@ static git_blame_hunk* hunk_from_entry(struct blame_entry *e) ...@@ -247,6 +247,7 @@ static git_blame_hunk* hunk_from_entry(struct blame_entry *e)
git_blame_hunk *h = new_hunk( git_blame_hunk *h = new_hunk(
e->lno+1, e->num_lines, e->s_lno+1, e->suspect->path); e->lno+1, e->num_lines, e->s_lno+1, e->suspect->path);
git_oid_cpy(&h->final_commit_id, git_commit_id(e->suspect->commit)); git_oid_cpy(&h->final_commit_id, git_commit_id(e->suspect->commit));
h->boundary = e->is_boundary ? 1 : 0;
return h; return h;
} }
......
...@@ -456,8 +456,12 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, uint32_t op ...@@ -456,8 +456,12 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, uint32_t op
GIT_UNUSED(opt); GIT_UNUSED(opt);
num_sg = git_commit_parentcount(commit); num_sg = git_commit_parentcount(commit);
if (!num_sg) if (!git_oid_cmp(git_commit_id(commit), &sb->blame->options.oldest_commit))
num_sg = 0;
if (!num_sg) {
git_oid_cpy(&sb->blame->options.oldest_commit, git_commit_id(commit));
goto finish; goto finish;
}
else if (num_sg < (int)ARRAY_SIZE(sg_buf)) else if (num_sg < (int)ARRAY_SIZE(sg_buf))
memset(sg_buf, 0, sizeof(sg_buf)); memset(sg_buf, 0, sizeof(sg_buf));
else else
...@@ -558,9 +562,14 @@ void assign_blame(struct scoreboard *sb, uint32_t opt) ...@@ -558,9 +562,14 @@ void assign_blame(struct scoreboard *sb, uint32_t opt)
pass_blame(sb, suspect, opt); pass_blame(sb, suspect, opt);
/* Take responsibility for the remaining entries */ /* Take responsibility for the remaining entries */
for (ent = sb->ent; ent; ent = ent->next) for (ent = sb->ent; ent; ent = ent->next) {
if (same_suspect(ent->suspect, suspect)) if (same_suspect(ent->suspect, suspect)) {
ent->guilty = 1; ent->guilty = 1;
ent->is_boundary = !git_oid_cmp(
git_commit_id(suspect->commit),
&sb->blame->options.oldest_commit);
}
}
origin_decref(suspect); origin_decref(suspect);
} }
} }
......
...@@ -55,6 +55,10 @@ struct blame_entry { ...@@ -55,6 +55,10 @@ struct blame_entry {
* scanning the lines over and over. * scanning the lines over and over.
*/ */
unsigned score; unsigned score;
/* Whether this entry has been tracked to a boundary commit.
*/
bool is_boundary;
}; };
/* /*
......
...@@ -15,7 +15,7 @@ void hunk_message(size_t idx, const git_blame_hunk *hunk, const char *fmt, ...) ...@@ -15,7 +15,7 @@ void hunk_message(size_t idx, const git_blame_hunk *hunk, const char *fmt, ...)
} }
void check_blame_hunk_index(git_repository *repo, git_blame *blame, int idx, void check_blame_hunk_index(git_repository *repo, git_blame *blame, int idx,
int start_line, int len, const char *commit_id, const char *orig_path) int start_line, int len, char boundary, const char *commit_id, const char *orig_path)
{ {
char expected[41] = {0}, actual[41] = {0}; char expected[41] = {0}, actual[41] = {0};
const git_blame_hunk *hunk = git_blame_get_hunk_byindex(blame, idx); const git_blame_hunk *hunk = git_blame_get_hunk_byindex(blame, idx);
...@@ -53,6 +53,12 @@ void check_blame_hunk_index(git_repository *repo, git_blame *blame, int idx, ...@@ -53,6 +53,12 @@ void check_blame_hunk_index(git_repository *repo, git_blame *blame, int idx,
hunk->orig_path, orig_path); hunk->orig_path, orig_path);
} }
cl_assert_equal_s(hunk->orig_path, orig_path); cl_assert_equal_s(hunk->orig_path, orig_path);
if (hunk->boundary != boundary) {
hunk_message(idx, hunk, "doesn't match boundary flag (got %d, expected %d)\n",
hunk->boundary, boundary);
}
cl_assert_equal_i(boundary, hunk->boundary);
} }
...@@ -9,6 +9,7 @@ void check_blame_hunk_index( ...@@ -9,6 +9,7 @@ void check_blame_hunk_index(
int idx, int idx,
int start_line, int start_line,
int len, int len,
char boundary,
const char *commit_id, const char *commit_id,
const char *orig_path); const char *orig_path);
......
...@@ -38,7 +38,7 @@ CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC ...@@ -38,7 +38,7 @@ CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer))); cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer)));
cl_assert_equal_i(5, git_blame_get_hunk_count(g_bufferblame)); cl_assert_equal_i(5, git_blame_get_hunk_count(g_bufferblame));
check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 1, "000000", "b.txt"); check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 1, 0, "000000", "b.txt");
} }
void test_blame_buffer__deleted_line(void) void test_blame_buffer__deleted_line(void)
...@@ -59,9 +59,9 @@ CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC ...@@ -59,9 +59,9 @@ CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\n"; CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\n";
cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer))); cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer)));
check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 3, "63d671eb", "b.txt"); check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 3, 0, "63d671eb", "b.txt");
check_blame_hunk_index(g_repo, g_bufferblame, 3, 9, 1, "63d671eb", "b.txt"); check_blame_hunk_index(g_repo, g_bufferblame, 3, 9, 1, 0, "63d671eb", "b.txt");
check_blame_hunk_index(g_repo, g_bufferblame, 4, 10, 5, "aa06ecca", "b.txt"); check_blame_hunk_index(g_repo, g_bufferblame, 4, 10, 5, 0, "aa06ecca", "b.txt");
} }
void test_blame_buffer__add_splits_hunk(void) void test_blame_buffer__add_splits_hunk(void)
...@@ -84,9 +84,9 @@ CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC ...@@ -84,9 +84,9 @@ CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\n"; CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\n";
cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer))); cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer)));
check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 2, "63d671eb", "b.txt"); check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 2, 0, "63d671eb", "b.txt");
check_blame_hunk_index(g_repo, g_bufferblame, 3, 8, 1, "00000000", "b.txt"); check_blame_hunk_index(g_repo, g_bufferblame, 3, 8, 1, 0, "00000000", "b.txt");
check_blame_hunk_index(g_repo, g_bufferblame, 4, 9, 3, "63d671eb", "b.txt"); check_blame_hunk_index(g_repo, g_bufferblame, 4, 9, 3, 0, "63d671eb", "b.txt");
} }
void test_blame_buffer__delete_crosses_hunk_boundary(void) void test_blame_buffer__delete_crosses_hunk_boundary(void)
...@@ -101,8 +101,8 @@ BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB ...@@ -101,8 +101,8 @@ BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\n"; CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\n";
cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer))); cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer)));
check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 1, "63d671eb", "b.txt"); check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 1, 0, "63d671eb", "b.txt");
check_blame_hunk_index(g_repo, g_bufferblame, 3, 7, 2, "aa06ecca", "b.txt"); check_blame_hunk_index(g_repo, g_bufferblame, 3, 7, 2, 0, "aa06ecca", "b.txt");
} }
void test_blame_buffer__replace_line(void) void test_blame_buffer__replace_line(void)
...@@ -124,7 +124,7 @@ CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC ...@@ -124,7 +124,7 @@ CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\n"; CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\n";
cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer))); cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer)));
check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 1, "63d671eb", "b.txt"); check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 1, 0, "63d671eb", "b.txt");
check_blame_hunk_index(g_repo, g_bufferblame, 3, 7, 1, "00000000", "b.txt"); check_blame_hunk_index(g_repo, g_bufferblame, 3, 7, 1, 0, "00000000", "b.txt");
check_blame_hunk_index(g_repo, g_bufferblame, 4, 8, 3, "63d671eb", "b.txt"); check_blame_hunk_index(g_repo, g_bufferblame, 4, 8, 3, 0, "63d671eb", "b.txt");
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment