Skip to content

Commit 1ee2c33

Browse files
committed
blame: provide line accessor
blame: introduce git_blame_line Provide a structure that can provide the line-level information.
1 parent 1474c89 commit 1ee2c33

File tree

3 files changed

+72
-4
lines changed

3 files changed

+72
-4
lines changed

include/git2/blame.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,10 +216,25 @@ typedef struct git_blame_hunk {
216216
char boundary;
217217
} git_blame_hunk;
218218

219+
/**
220+
* Structure that represents a line in a blamed file.
221+
*/
222+
typedef struct git_blame_line {
223+
const char *ptr;
224+
size_t len;
225+
} git_blame_line;
219226

220227
/** Opaque structure to hold blame results */
221228
typedef struct git_blame git_blame;
222229

230+
/**
231+
* Gets the number of lines that exist in the blame structure.
232+
*
233+
* @param blame The blame structure to query.
234+
* @return The number of line.
235+
*/
236+
GIT_EXTERN(size_t) git_blame_linecount(git_blame *blame);
237+
223238
/**
224239
* Gets the number of hunks that exist in the blame structure.
225240
*
@@ -251,6 +266,17 @@ GIT_EXTERN(const git_blame_hunk *) git_blame_hunk_byline(
251266
git_blame *blame,
252267
size_t lineno);
253268

269+
/**
270+
* Gets the information about the line in the blame.
271+
*
272+
* @param blame the blame structure to query
273+
* @param idx the (1-based) line number
274+
* @return the blamed line, or NULL on error
275+
*/
276+
GIT_EXTERN(const git_blame_line *) git_blame_line_byindex(
277+
git_blame *blame,
278+
size_t idx);
279+
254280
#ifndef GIT_DEPRECATE_HARD
255281
/**
256282
* Gets the number of hunks that exist in the blame structure.

src/libgit2/blame.c

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,10 +144,9 @@ git_blame *git_blame__alloc(
144144
gbr->options = opts;
145145

146146
if (git_vector_init(&gbr->hunks, 8, hunk_cmp) < 0 ||
147-
git_vector_init(&gbr->paths, 8, paths_cmp) < 0 ||
148-
(gbr->path = git__strdup(path)) == NULL ||
149-
git_vector_insert(&gbr->paths, git__strdup(path)) < 0)
150-
{
147+
git_vector_init(&gbr->paths, 8, paths_cmp) < 0 ||
148+
(gbr->path = git__strdup(path)) == NULL ||
149+
git_vector_insert(&gbr->paths, git__strdup(path)) < 0) {
151150
git_blame_free(gbr);
152151
return NULL;
153152
}
@@ -170,7 +169,9 @@ void git_blame_free(git_blame *blame)
170169

171170
git_vector_foreach(&blame->hunks, i, hunk)
172171
free_hunk(hunk);
172+
173173
git_vector_dispose(&blame->hunks);
174+
git_array_clear(blame->lines);
174175

175176
git_vector_dispose_deep(&blame->paths);
176177

@@ -190,6 +191,23 @@ size_t git_blame_hunkcount(git_blame *blame)
190191
return blame->hunks.length;
191192
}
192193

194+
size_t git_blame_linecount(git_blame *blame)
195+
{
196+
GIT_ASSERT_ARG(blame);
197+
198+
return git_array_size(blame->line_index);
199+
}
200+
201+
const git_blame_line *git_blame_line_byindex(
202+
git_blame *blame,
203+
size_t idx)
204+
{
205+
GIT_ASSERT_ARG_WITH_RETVAL(blame, NULL);
206+
GIT_ASSERT_WITH_RETVAL(idx > 0 && idx <= git_array_size(blame->line_index), NULL);
207+
208+
return git_array_get(blame->lines, idx - 1);
209+
}
210+
193211
const git_blame_hunk *git_blame_hunk_byindex(
194212
git_blame *blame,
195213
size_t index)
@@ -315,25 +333,48 @@ static int index_blob_lines(git_blame *blame)
315333
const char *buf = blame->final_buf;
316334
size_t len = blame->final_buf_size;
317335
int num = 0, incomplete = 0, bol = 1;
336+
git_blame_line *line = NULL;
318337
size_t *i;
319338

320339
if (len && buf[len-1] != '\n')
321340
incomplete++; /* incomplete line at the end */
341+
322342
while (len--) {
323343
if (bol) {
324344
i = git_array_alloc(blame->line_index);
325345
GIT_ERROR_CHECK_ALLOC(i);
326346
*i = buf - blame->final_buf;
347+
348+
GIT_ASSERT(line == NULL);
349+
line = git_array_alloc(blame->lines);
350+
GIT_ERROR_CHECK_ALLOC(line);
351+
352+
line->ptr = buf;
327353
bol = 0;
328354
}
355+
329356
if (*buf++ == '\n') {
357+
GIT_ASSERT(line);
358+
line->len = (buf - line->ptr) - 1;
359+
line = NULL;
360+
330361
num++;
331362
bol = 1;
332363
}
333364
}
365+
334366
i = git_array_alloc(blame->line_index);
335367
GIT_ERROR_CHECK_ALLOC(i);
336368
*i = buf - blame->final_buf;
369+
370+
if (!bol) {
371+
GIT_ASSERT(line);
372+
line->len = buf - line->ptr;
373+
line = NULL;
374+
}
375+
376+
GIT_ASSERT(!line);
377+
337378
blame->num_lines = num + incomplete;
338379
return blame->num_lines;
339380
}

src/libgit2/blame.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ struct git_blame {
7171
git_blame_options options;
7272

7373
git_vector hunks;
74+
git_array_t(git_blame_line) lines;
7475
git_vector paths;
7576

7677
git_blob *final_blob;

0 commit comments

Comments
 (0)