blame: provide line accessor

blame: introduce git_blame_line

Provide a structure that can provide the line-level information.
This commit is contained in:
Edward Thomson
2024-07-09 20:14:26 +01:00
parent 1474c892f9
commit 1ee2c33993
3 changed files with 72 additions and 4 deletions

View File

@@ -216,10 +216,25 @@ typedef struct git_blame_hunk {
char boundary;
} git_blame_hunk;
/**
* Structure that represents a line in a blamed file.
*/
typedef struct git_blame_line {
const char *ptr;
size_t len;
} git_blame_line;
/** Opaque structure to hold blame results */
typedef struct git_blame git_blame;
/**
* Gets the number of lines that exist in the blame structure.
*
* @param blame The blame structure to query.
* @return The number of line.
*/
GIT_EXTERN(size_t) git_blame_linecount(git_blame *blame);
/**
* Gets the number of hunks that exist in the blame structure.
*
@@ -251,6 +266,17 @@ GIT_EXTERN(const git_blame_hunk *) git_blame_hunk_byline(
git_blame *blame,
size_t lineno);
/**
* Gets the information about the line in the blame.
*
* @param blame the blame structure to query
* @param idx the (1-based) line number
* @return the blamed line, or NULL on error
*/
GIT_EXTERN(const git_blame_line *) git_blame_line_byindex(
git_blame *blame,
size_t idx);
#ifndef GIT_DEPRECATE_HARD
/**
* Gets the number of hunks that exist in the blame structure.

View File

@@ -144,10 +144,9 @@ git_blame *git_blame__alloc(
gbr->options = opts;
if (git_vector_init(&gbr->hunks, 8, hunk_cmp) < 0 ||
git_vector_init(&gbr->paths, 8, paths_cmp) < 0 ||
(gbr->path = git__strdup(path)) == NULL ||
git_vector_insert(&gbr->paths, git__strdup(path)) < 0)
{
git_vector_init(&gbr->paths, 8, paths_cmp) < 0 ||
(gbr->path = git__strdup(path)) == NULL ||
git_vector_insert(&gbr->paths, git__strdup(path)) < 0) {
git_blame_free(gbr);
return NULL;
}
@@ -170,7 +169,9 @@ void git_blame_free(git_blame *blame)
git_vector_foreach(&blame->hunks, i, hunk)
free_hunk(hunk);
git_vector_dispose(&blame->hunks);
git_array_clear(blame->lines);
git_vector_dispose_deep(&blame->paths);
@@ -190,6 +191,23 @@ size_t git_blame_hunkcount(git_blame *blame)
return blame->hunks.length;
}
size_t git_blame_linecount(git_blame *blame)
{
GIT_ASSERT_ARG(blame);
return git_array_size(blame->line_index);
}
const git_blame_line *git_blame_line_byindex(
git_blame *blame,
size_t idx)
{
GIT_ASSERT_ARG_WITH_RETVAL(blame, NULL);
GIT_ASSERT_WITH_RETVAL(idx > 0 && idx <= git_array_size(blame->line_index), NULL);
return git_array_get(blame->lines, idx - 1);
}
const git_blame_hunk *git_blame_hunk_byindex(
git_blame *blame,
size_t index)
@@ -315,25 +333,48 @@ static int index_blob_lines(git_blame *blame)
const char *buf = blame->final_buf;
size_t len = blame->final_buf_size;
int num = 0, incomplete = 0, bol = 1;
git_blame_line *line = NULL;
size_t *i;
if (len && buf[len-1] != '\n')
incomplete++; /* incomplete line at the end */
while (len--) {
if (bol) {
i = git_array_alloc(blame->line_index);
GIT_ERROR_CHECK_ALLOC(i);
*i = buf - blame->final_buf;
GIT_ASSERT(line == NULL);
line = git_array_alloc(blame->lines);
GIT_ERROR_CHECK_ALLOC(line);
line->ptr = buf;
bol = 0;
}
if (*buf++ == '\n') {
GIT_ASSERT(line);
line->len = (buf - line->ptr) - 1;
line = NULL;
num++;
bol = 1;
}
}
i = git_array_alloc(blame->line_index);
GIT_ERROR_CHECK_ALLOC(i);
*i = buf - blame->final_buf;
if (!bol) {
GIT_ASSERT(line);
line->len = buf - line->ptr;
line = NULL;
}
GIT_ASSERT(!line);
blame->num_lines = num + incomplete;
return blame->num_lines;
}

View File

@@ -71,6 +71,7 @@ struct git_blame {
git_blame_options options;
git_vector hunks;
git_array_t(git_blame_line) lines;
git_vector paths;
git_blob *final_blob;