Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[RFC] basic note iterator implementation #1396

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 6, 2013
Merged

[RFC] basic note iterator implementation #1396

merged 4 commits into from
Mar 6, 2013

Conversation

cholin
Copy link

@cholin cholin commented Mar 6, 2013

This is a basic note iterator implementation (regarding #1384). I would be happy about comments, as this is my first contribution to libgit2.

This pull requests adds the following functions:

  • git_note_iterator_new()- create a new note iterator
  • git_note_iterator_free()
  • git_note_next() - retrieves the next item of the iterator

Nico von Geyso added 2 commits March 6, 2013 17:01
* git_note_iterator_new() - create a new note iterator
* git_note_next() - retrieves the next item of the iterator
error = retrieve_note_tree_and_commit(&tree, &commit, repo, &notes_ref);
if (!error) {
*it = (git_note_iterator *)git__malloc(sizeof(git_iterator));
GITERR_CHECK_ALLOC(*it);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

git_iterator_for_tree() will do this allocation for you. You don't need to preallocate the object.

@arrbee
Copy link
Member

arrbee commented Mar 6, 2013

@cholin ❤️ Thanks for this!

Looking pretty good! ⭐ ⭐ All my comments are small things.

In addition to the other comments, I'd love to see you rewrite git_note_foreach() to use the iterator APIs in order to remove the code duplication between that and git_note_iterator_new(). I think it's just a matter of adding something like:

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_iterator_next(&note_id, &annotated_id, iter))) {
        if (note_cb(&note_id, &annotated_id, payload)) {
            error = GIT_EUSER;
            break;
        }
    }

    if (error == GIT_ITEROVER)
        error = 0;

    git_note_iterator_free(iter);
    return error;
}

(Sorry, I didn't really test that code, but it should be something like that.) It's not that that is so much less code, but just that it means there will be only one version of the logic to setup and advance through the list. In some cases (e.g. diff), the foreach API doesn't use the iterator API because there is a significant performance or memory cost for doing so, but in this case, the two versions are identical.

@vmg
Copy link
Member

vmg commented Mar 6, 2013

These are great news. Thanks @cholin for heading this project of adding more iterator objects to libgit2. I know you're specially interested on this for Python bindings, but other languages will certainly benefit from this. :)

cl_git_pass(git_note_iterator_new(&iter, _repo, "refs/notes/beer"));

for (i = 0; git_note_next(&note_id, &annotated_id, iter) != GIT_ITEROVER; ++i)
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Likewise for this.

@vmg
Copy link
Member

vmg commented Mar 6, 2013

@arrbee: How would you feel if all iterators in the external API were generic git_iterator * pointers? I feel like this could greatly reduce the amount of new (superfluous) types while not making the API harder to understand, since you'd still have e.g. git_notes_next to let you know that the iterator you're working on yields notes.

* fixed style issues
* use new iterator functions for git_note_foreach()
@arrbee
Copy link
Member

arrbee commented Mar 6, 2013

@vmg That's an interesting thought, but I'm not sure. This notes case is pretty special because it can directly use a tree iterator. I suspect that few of the other public iterators will map cleanly to the internal iterator objects. And right now, those internal iterator objects have a very specific semantics. For example, if we have a git_status_iterator, on the inside it is not going to have an existing git_iterator object in it.

If you want to repurpose the git_iterator type to create a public opaque type with very little fixed implementation and internally build a "class hierarchy" with something like a git_path_iterator intermediate class that provides "iterator over trees and blobs" semantics (renaming the current git_iterator internal type), for which the tree, index, and workdir iterators are more specific sub-classes, we could probably make it work, but I'm not certain there is much to gain from that.

Additionally, because of how I'm using them, it is more convenient for the internal iterator classes to support independent "look up the current value" and "advance to the next value" actions. This public notes API opts for a simpler "get current and advance to next" design, which I think is good for a public API since it keeps the number of functions small.

@carlosmn
Copy link
Member

carlosmn commented Mar 6, 2013

I'd been thinking of doing that when writing the ref iterator. As no iterators are going to hold any common data, you'd have to typedef struct git_iterator {} git_iterator, cast, and then hope the user doesn't pass the wrong iterator.

@arrbee
Copy link
Member

arrbee commented Mar 6, 2013

I think if we were going to do it, we'd do something like: typedef struct git_iterator { int type; } git_iterator; and for all iterators to begin with a common type constant so that you could immediately verify that you were using them with the correct functions.

But again, I don't see a huge win from doing this. I'd rather agree on common naming and behaviors that we'll use consistently (e.g. git_xxx_iterator, new(), free(), next() vs advance(), returning GIT_ITEROVER) and just worry about that.

@arrbee
Copy link
Member

arrbee commented Mar 6, 2013

Larger discussion aside, this looks good to go. Thanks @cholin !

arrbee added a commit that referenced this pull request Mar 6, 2013
[RFC] basic note iterator implementation
@arrbee arrbee merged commit 1b405a2 into libgit2:development Mar 6, 2013
@cholin cholin deleted the features/note-iterator branch March 6, 2013 22:03
@scunz
Copy link
Contributor

scunz commented Mar 6, 2013

@vmg isn't the file (tests-clar/clar_main.c, added by this PR) generated and thus is probably missing in .gitignore?

@cholin
Copy link
Author

cholin commented Mar 6, 2013

yea accidently added it. my fault - sry. perhaps someone can remove it and add it to `.gitignore?.

@arrbee
Copy link
Member

arrbee commented Mar 6, 2013

Damn, GitHub diff didn't show the content of that file and I overlooked it when I merged. :-(

@arrbee
Copy link
Member

arrbee commented Mar 7, 2013

It's no longer used with clar2 so I just removed it.

@scunz
Copy link
Contributor

scunz commented Mar 7, 2013

That at least explains why it's not any longer in the .gitignore file.

I strongly suggest that you fellows at github rethink that feature for not-showing too large diffs. Heck, this was a real source file - with the CMake-globs actually anything could have gone into the codebase without further notice... 🎱

phatblat pushed a commit to phatblat/libgit2 that referenced this pull request Sep 13, 2014
[RFC] basic note iterator implementation
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants