Commit 0a0f0558 by Ben Straub

git_blame is a scoreboard

parent ef03d040
......@@ -210,10 +210,10 @@ static git_blame_hunk *split_hunk_in_vector(
* To allow quick access to the contents of nth line in the
* final image, prepare an index in the scoreboard.
*/
static int prepare_lines(git_blame__scoreboard *sb)
static int prepare_lines(git_blame *blame)
{
const char *buf = sb->final_buf;
git_off_t len = sb->final_buf_size;
const char *buf = blame->final_buf;
git_off_t len = blame->final_buf_size;
int num = 0, incomplete = 0, bol = 1;
if (len && buf[len-1] != '\n')
......@@ -227,8 +227,8 @@ static int prepare_lines(git_blame__scoreboard *sb)
bol = 1;
}
}
sb->num_lines = num + incomplete;
return sb->num_lines;
blame->num_lines = num + incomplete;
return blame->num_lines;
}
static git_blame_hunk* hunk_from_entry(git_blame__entry *e)
......@@ -244,21 +244,20 @@ static int walk_and_mark(git_blame *blame)
{
int error;
git_blame__scoreboard sb = {0};
git_blame__entry *ent = NULL;
git_blob *blob = NULL;
git_blame__origin *o;
if ((error = git_commit_lookup(&sb.final, blame->repository, &blame->options.newest_commit)) < 0 ||
(error = git_object_lookup_bypath((git_object**)&blob, (git_object*)sb.final, blame->path, GIT_OBJ_BLOB)) < 0)
if ((error = git_commit_lookup(&blame->final, blame->repository, &blame->options.newest_commit)) < 0 ||
(error = git_object_lookup_bypath((git_object**)&blob, (git_object*)blame->final, blame->path, GIT_OBJ_BLOB)) < 0)
goto cleanup;
sb.final_buf = git_blob_rawcontent(blob);
sb.final_buf_size = git_blob_rawsize(blob);
if ((error = get_origin(&o, &sb, sb.final, blame->path)) < 0)
blame->final_buf = git_blob_rawcontent(blob);
blame->final_buf_size = git_blob_rawsize(blob);
if ((error = get_origin(&o, blame, blame->final, blame->path)) < 0)
goto cleanup;
ent = git__calloc(1, sizeof(*ent));
ent->num_lines = prepare_lines(&sb);
ent->num_lines = prepare_lines(blame);
ent->lno = blame->options.min_line - 1;
ent->num_lines = ent->num_lines - blame->options.min_line + 1;
if (blame->options.max_line > 0) {
......@@ -267,15 +266,14 @@ static int walk_and_mark(git_blame *blame)
ent->s_lno = ent->lno;
ent->suspect = o;
sb.ent = ent;
sb.path = blame->path;
sb.blame = blame;
blame->ent = ent;
blame->path = blame->path;
assign_blame(&sb, blame->options.flags);
coalesce(&sb);
assign_blame(blame, blame->options.flags);
coalesce(blame);
cleanup:
for (ent = sb.ent; ent; ) {
for (ent = blame->ent; ent; ) {
git_blame__entry *e = ent->next;
git_blame__origin *o = ent->suspect;
......
......@@ -8,6 +8,61 @@
#include "array.h"
#include "git2/oid.h"
/*
* One blob in a commit that is being suspected
*/
typedef struct git_blame__origin {
int refcnt;
struct git_blame__origin *previous;
git_commit *commit;
git_blob *blob;
char path[];
} git_blame__origin;
/*
* Each group of lines is described by a git_blame__entry; it can be split
* as we pass blame to the parents. They form a linked list in the
* scoreboard structure, sorted by the target line number.
*/
typedef struct git_blame__entry {
struct git_blame__entry *prev;
struct git_blame__entry *next;
/* the first line of this group in the final image;
* internally all line numbers are 0 based.
*/
int lno;
/* how many lines this group has */
int num_lines;
/* the commit that introduced this group into the final image */
git_blame__origin *suspect;
/* true if the suspect is truly guilty; false while we have not
* checked if the group came from one of its parents.
*/
char guilty;
/* true if the entry has been scanned for copies in the current parent
*/
char scanned;
/* the line number of the first line of this group in the
* suspect's file; internally all line numbers are 0 based.
*/
int s_lno;
/* how significant this entry is -- cached to avoid
* scanning the lines over and over.
*/
unsigned score;
/* Whether this entry has been tracked to a boundary commit.
*/
bool is_boundary;
} git_blame__entry;
struct git_blame {
const char *path;
git_repository *repository;
......@@ -20,6 +75,13 @@ struct git_blame {
size_t current_diff_line;
git_blame_hunk *current_hunk;
/* Scoreboard fields */
git_commit *final;
git_blame__entry *ent;
int num_lines;
const char *final_buf;
git_off_t final_buf_size;
};
git_blame *git_blame__alloc(
......
......@@ -3,95 +3,14 @@
#define INCLUDE_blame_git__
#include "git2.h"
#include "xdiff/xinclude.h"
#include "blame.h"
#include "xdiff/xinclude.h"
/*
* One blob in a commit that is being suspected
*/
typedef struct git_blame__origin {
int refcnt;
struct git_blame__origin *previous;
git_commit *commit;
git_blob *blob;
char path[];
} git_blame__origin;
/*
* Each group of lines is described by a git_blame__entry; it can be split
* as we pass blame to the parents. They form a linked list in the
* scoreboard structure, sorted by the target line number.
*/
typedef struct git_blame__entry {
struct git_blame__entry *prev;
struct git_blame__entry *next;
/* the first line of this group in the final image;
* internally all line numbers are 0 based.
*/
int lno;
/* how many lines this group has */
int num_lines;
/* the commit that introduced this group into the final image */
git_blame__origin *suspect;
/* true if the suspect is truly guilty; false while we have not
* checked if the group came from one of its parents.
*/
char guilty;
/* true if the entry has been scanned for copies in the current parent
*/
char scanned;
/* the line number of the first line of this group in the
* suspect's file; internally all line numbers are 0 based.
*/
int s_lno;
/* how significant this entry is -- cached to avoid
* scanning the lines over and over.
*/
unsigned score;
/* Whether this entry has been tracked to a boundary commit.
*/
bool is_boundary;
} git_blame__entry;
/*
* The current state of the blame assignment.
*/
typedef struct git_blame__scoreboard {
/* the final commit (i.e. where we started digging from) */
git_commit *final;
const char *path;
/*
* The contents in the final image.
* Used by many functions to obtain contents of the nth line,
* indexed with scoreboard.lineno[blame_entry.lno].
*/
const char *final_buf;
git_off_t final_buf_size;
/* linked list of blames */
git_blame__entry *ent;
/* look-up a line in the final buffer */
int num_lines;
git_blame *blame;
} git_blame__scoreboard;
int get_origin(git_blame__origin **out, git_blame__scoreboard *sb, git_commit *commit, const char *path);
int get_origin(git_blame__origin **out, git_blame *sb, git_commit *commit, const char *path);
int make_origin(git_blame__origin **out, git_commit *commit, const char *path);
git_blame__origin *origin_incref(git_blame__origin *o);
void origin_decref(git_blame__origin *o);
void assign_blame(git_blame__scoreboard *sb, uint32_t flags);
void coalesce(git_blame__scoreboard *sb);
void assign_blame(git_blame *sb, uint32_t flags);
void coalesce(git_blame *sb);
#endif
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