Pergunta

I want to get the same the number of commits since the last tag. The same result can be found with regular git using:

git rev-list --count HEAD ^$(git describe --tags --abbrev=0)

using libgit2 from the C api.

My attempt is inspired from http://ben.straub.cc/2013/10/02/revwalk/. I removed error checking to make the code shorter.

git_revwalk *walk;
git_revwalk_new(&walk, repo);
git_revwalk_sorting(walk,
    GIT_SORT_TOPOLOGICAL |
    GIT_SORT_TIME);
git_revwalk_push_head(walk);
git_revwalk_hide_glob(walk, "tags/*");

int i = 0;
git_oid oid;
while (git_revwalk_next(&oid, walk) == 0) {
    git_commit *c;

    git_commit_lookup(&c, repo, &oid);
    if(git_commit_parentcount(c) == 1)
        i++;
    git_commit_free(c);
}
return i;

The problem is that the count i is too large. I believe that the critical part is git_revwalk_hide_glob(walk, "tags/*");.

Foi útil?

Solução

The most likely case in that you have annotated tags, which the revision walker doesn't like, as they're not commit objects, making the call fail and for an arbitrary amount of tags not to be excluded. Testing locally,

if (git_revwalk_hide_glob(walk, "tags/*") < 0)
    printf("error: %s\n", giterr_last()->message);

showed the exact error message for that. I've openend an issue to remind me to look at it.

A way to work around it would be to use a reference iterator or foreach to loop over the tags (which is what the revwalk code does for you) and peel the targets, e.g.by using git_reference_peel.

git_reference_iterator_glob_new(&iter, repo, "refs/tags/*");
while (git_reference_next(&ref, iter) == 0) {
    git_object *obj;

    /* go down to a commit object */
    git_reference_peel(&obj, ref, GIT_OBJ_COMMIT);
    /* and hide that */
    git_revwalk_hide(walk, git_object_id(obj));

    git_object_free(obj);
    git_reference_free(ref);
}

As an aside, your code would miscount the number of commits in case there is a root commit in the commits that are shown. You should be checking for < 2 parents to exclude merges, instead of == 1, or you're leaving out root commits, which have 0 parents (this is going to be a rare situation, but you find all sorts of weird things in the wild).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top