mirror of
https://git.proxmox.com/git/libgit2
synced 2025-08-13 19:30:37 +00:00
Merge pull request #1396 from cholin/features/note-iterator
[RFC] basic note iterator implementation
This commit is contained in:
commit
1b405a232f
@ -29,6 +29,54 @@ GIT_BEGIN_DECL
|
||||
typedef int (*git_note_foreach_cb)(
|
||||
const git_oid *blob_id, const git_oid *annotated_object_id, void *payload);
|
||||
|
||||
/**
|
||||
* note iterator
|
||||
*/
|
||||
typedef struct git_iterator git_note_iterator;
|
||||
|
||||
/**
|
||||
* Creates a new iterator for notes
|
||||
*
|
||||
* The iterator must be freed manually by the user.
|
||||
*
|
||||
* @param out pointer to the iterator
|
||||
* @param repo repository where to look up the note
|
||||
* @param notes_ref canonical name of the reference to use (optional); defaults to
|
||||
* "refs/notes/commits"
|
||||
*
|
||||
* @return 0 or an error code
|
||||
*/
|
||||
GIT_EXTERN(int) git_note_iterator_new(
|
||||
git_note_iterator **out,
|
||||
git_repository *repo,
|
||||
const char *notes_ref);
|
||||
|
||||
/**
|
||||
* Frees an git_note_iterator
|
||||
*
|
||||
* @param it pointer to the iterator
|
||||
*/
|
||||
GIT_EXTERN(void) git_note_iterator_free(git_note_iterator *it);
|
||||
|
||||
/**
|
||||
* Returns the current item (note_id and annotated_id) and advance the iterator
|
||||
* internally to the next value
|
||||
*
|
||||
* The notes must not be freed manually by the user.
|
||||
*
|
||||
* @param it pointer to the iterator
|
||||
* @param note_id id of blob containing the message
|
||||
* @param annotated_id id of the git object being annotated
|
||||
*
|
||||
* @return 0 (no error), GIT_ITEROVER (iteration is done) or an error code
|
||||
* (negative value)
|
||||
*/
|
||||
GIT_EXTERN(int) git_note_next(
|
||||
git_oid* note_id,
|
||||
git_oid* annotated_id,
|
||||
git_note_iterator *it);
|
||||
|
||||
|
||||
/**
|
||||
* Read the note for an object
|
||||
*
|
||||
|
99
src/notes.c
99
src/notes.c
@ -531,14 +531,11 @@ void git_note_free(git_note *note)
|
||||
|
||||
static int process_entry_path(
|
||||
const char* entry_path,
|
||||
const git_oid *note_oid,
|
||||
git_note_foreach_cb note_cb,
|
||||
void *payload)
|
||||
git_oid *annotated_object_id)
|
||||
{
|
||||
int error = -1;
|
||||
size_t i = 0, j = 0, len;
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
git_oid annotated_object_id;
|
||||
|
||||
if ((error = git_buf_puts(&buf, entry_path)) < 0)
|
||||
goto cleanup;
|
||||
@ -571,11 +568,7 @@ static int process_entry_path(
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if ((error = git_oid_fromstr(&annotated_object_id, buf.ptr)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (note_cb(note_oid, &annotated_object_id, payload))
|
||||
error = GIT_EUSER;
|
||||
error = git_oid_fromstr(annotated_object_id, buf.ptr);
|
||||
|
||||
cleanup:
|
||||
git_buf_free(&buf);
|
||||
@ -583,32 +576,86 @@ cleanup:
|
||||
}
|
||||
|
||||
int git_note_foreach(
|
||||
git_repository *repo,
|
||||
const char *notes_ref,
|
||||
git_note_foreach_cb note_cb,
|
||||
void *payload)
|
||||
{
|
||||
int error;
|
||||
git_note_iterator *iter = NULL;
|
||||
git_oid note_id, annotated_id;
|
||||
|
||||
if ((error = git_note_iterator_new(&iter, repo, notes_ref)) < 0)
|
||||
return error;
|
||||
|
||||
while (!(error = git_note_next(¬e_id, &annotated_id, iter))) {
|
||||
if (note_cb(¬e_id, &annotated_id, payload)) {
|
||||
error = GIT_EUSER;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (error == GIT_ITEROVER)
|
||||
error = 0;
|
||||
|
||||
git_note_iterator_free(iter);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
void git_note_iterator_free(git_note_iterator *it)
|
||||
{
|
||||
if (it == NULL)
|
||||
return;
|
||||
|
||||
git_iterator_free(it);
|
||||
}
|
||||
|
||||
|
||||
int git_note_iterator_new(
|
||||
git_note_iterator **it,
|
||||
git_repository *repo,
|
||||
const char *notes_ref,
|
||||
git_note_foreach_cb note_cb,
|
||||
void *payload)
|
||||
const char *notes_ref)
|
||||
{
|
||||
int error;
|
||||
git_iterator *iter = NULL;
|
||||
git_tree *tree = NULL;
|
||||
git_commit *commit = NULL;
|
||||
const git_index_entry *item;
|
||||
git_tree *tree = NULL;
|
||||
|
||||
if (!(error = retrieve_note_tree_and_commit(
|
||||
&tree, &commit, repo, ¬es_ref)) &&
|
||||
!(error = git_iterator_for_tree(&iter, tree)))
|
||||
error = git_iterator_current(iter, &item);
|
||||
error = retrieve_note_tree_and_commit(&tree, &commit, repo, ¬es_ref);
|
||||
if (error < 0)
|
||||
goto cleanup;
|
||||
|
||||
while (!error && item) {
|
||||
error = process_entry_path(item->path, &item->oid, note_cb, payload);
|
||||
if ((error = git_iterator_for_tree(it, tree)) < 0)
|
||||
git_iterator_free(*it);
|
||||
|
||||
if (!error)
|
||||
error = git_iterator_advance(iter, &item);
|
||||
}
|
||||
|
||||
git_iterator_free(iter);
|
||||
cleanup:
|
||||
git_tree_free(tree);
|
||||
git_commit_free(commit);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int git_note_next(
|
||||
git_oid* note_id,
|
||||
git_oid* annotated_id,
|
||||
git_note_iterator *it)
|
||||
{
|
||||
int error;
|
||||
const git_index_entry *item;
|
||||
|
||||
if ((error = git_iterator_current(it, &item)) < 0)
|
||||
goto exit;
|
||||
|
||||
if (item != NULL) {
|
||||
git_oid_cpy(note_id, &item->oid);
|
||||
error = process_entry_path(item->path, annotated_id);
|
||||
|
||||
if (error >= 0)
|
||||
error = git_iterator_advance(it, NULL);
|
||||
} else {
|
||||
error = GIT_ITEROVER;
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "common.h"
|
||||
|
||||
#include "git2/oid.h"
|
||||
#include "git2/types.h"
|
||||
|
||||
#define GIT_NOTES_DEFAULT_REF "refs/notes/commits"
|
||||
|
||||
|
3453
tests-clar/clar_main.c
Normal file
3453
tests-clar/clar_main.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -40,7 +40,8 @@ static void create_note(git_oid *note_oid, const char *canonical_namespace, cons
|
||||
static struct {
|
||||
const char *note_sha;
|
||||
const char *annotated_object_sha;
|
||||
} list_expectations[] = {
|
||||
}
|
||||
list_expectations[] = {
|
||||
{ "1c73b1f51762155d357bcd1fd4f2c409ef80065b", "4a202b346bb0fb0db7eff3cffeb3c70babbd2045" },
|
||||
{ "1c73b1f51762155d357bcd1fd4f2c409ef80065b", "9fd738e8f7967c078dceed8190330fc8648ee56a" },
|
||||
{ "257b43746b6b46caa4aa788376c647cce0a33e2b", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750" },
|
||||
@ -317,3 +318,70 @@ void test_notes_notes__removing_a_note_which_doesnt_exists_returns_ENOTFOUND(voi
|
||||
cl_git_fail(error);
|
||||
cl_assert_equal_i(GIT_ENOTFOUND, error);
|
||||
}
|
||||
|
||||
void test_notes_notes__can_iterate_default_namespace(void)
|
||||
{
|
||||
git_note_iterator *iter;
|
||||
git_note *note;
|
||||
git_oid note_id, annotated_id;
|
||||
git_oid note_created[2];
|
||||
const char* note_message[] = {
|
||||
"I decorate a65f\n",
|
||||
"I decorate c478\n"
|
||||
};
|
||||
int i, err;
|
||||
|
||||
create_note(¬e_created[0], "refs/notes/commits",
|
||||
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750", note_message[0]);
|
||||
create_note(¬e_created[1], "refs/notes/commits",
|
||||
"c47800c7266a2be04c571c04d5a6614691ea99bd", note_message[1]);
|
||||
|
||||
cl_git_pass(git_note_iterator_new(&iter, _repo, NULL));
|
||||
|
||||
for (i = 0; (err = git_note_next(¬e_id, &annotated_id, iter)) >= 0; ++i) {
|
||||
cl_git_pass(git_note_read(¬e, _repo, NULL, &annotated_id));
|
||||
cl_assert_equal_s(git_note_message(note), note_message[i]);
|
||||
git_note_free(note);
|
||||
}
|
||||
|
||||
cl_assert_equal_i(GIT_ITEROVER, err);
|
||||
cl_assert_equal_i(2, i);
|
||||
git_note_iterator_free(iter);
|
||||
}
|
||||
|
||||
void test_notes_notes__can_iterate_custom_namespace(void)
|
||||
{
|
||||
git_note_iterator *iter;
|
||||
git_note *note;
|
||||
git_oid note_id, annotated_id;
|
||||
git_oid note_created[2];
|
||||
const char* note_message[] = {
|
||||
"I decorate a65f\n",
|
||||
"I decorate c478\n"
|
||||
};
|
||||
int i, err;
|
||||
|
||||
create_note(¬e_created[0], "refs/notes/beer",
|
||||
"a65fedf39aefe402d3bb6e24df4d4f5fe4547750", note_message[0]);
|
||||
create_note(¬e_created[1], "refs/notes/beer",
|
||||
"c47800c7266a2be04c571c04d5a6614691ea99bd", note_message[1]);
|
||||
|
||||
cl_git_pass(git_note_iterator_new(&iter, _repo, "refs/notes/beer"));
|
||||
|
||||
for (i = 0; (err = git_note_next(¬e_id, &annotated_id, iter)) >= 0; ++i) {
|
||||
cl_git_pass(git_note_read(¬e, _repo, "refs/notes/beer", &annotated_id));
|
||||
cl_assert_equal_s(git_note_message(note), note_message[i]);
|
||||
git_note_free(note);
|
||||
}
|
||||
|
||||
cl_assert_equal_i(GIT_ITEROVER, err);
|
||||
cl_assert_equal_i(2, i);
|
||||
git_note_iterator_free(iter);
|
||||
}
|
||||
|
||||
void test_notes_notes__empty_iterate(void)
|
||||
{
|
||||
git_note_iterator *iter;
|
||||
|
||||
cl_git_fail(git_note_iterator_new(&iter, _repo, "refs/notes/commits"));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user