git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH 09/13] refs: introduce an iterator interface

From
Eric Sunshine <sunshine@sunshineco.com>
Date
May 31, 2016, 05:29 UTC
Message-ID
<CAPig+cSjzZGUjdgkz1y7brGNb1M2gHfW0UG-wgBc00beNDQmnA@mail.gmail.com>
In-Reply-To
<89634d216544d1102dafd5d18247bff2581d48a8.1464537050.git.mhagger@alum.mit.edu>
On Mon, May 30, 2016 at 3:55 AM, Michael Haggerty <mhagger@alum.mit.edu> wrote:
Show 21 quoted lines
> [...]
> This commit introduces a new iteration primitive for references: a
> ref_iterator. A ref_iterator is a polymorphic object that a reference
> storage backend can be asked to instantiate. There are three functions
> that can be applied to a ref_iterator:
>
> * ref_iterator_advance(): move to the next reference in the iteration
> * ref_iterator_abort(): end the iteration before it is exhausted
> * ref_iterator_peel(): peel the reference currently being looked at
> [...]
> Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
> ---
> diff --git a/refs/refs-internal.h b/refs/refs-internal.h
> @@ -249,6 +249,199 @@ int rename_ref_available(const char *oldname, const char *newname);
> +/*
> + * Advance the iterator to the first or next item and return ITER_OK.
> + * If the iteration is exhausted, free the resources associated with
> + * the ref_iterator and return ITER_DONE. On errors, free the iterator
> + * resources and return ITER_ERROR. It is a bug to use ref_iterator or
> + * call this function again after it has returned false.
> + */
Either:
    s/false/something other than ITER_OK/
or:
    s/false/ITER_DONE or ITER_ERROR/
Show 6 quoted lines
> +int ref_iterator_advance(struct ref_iterator *ref_iterator);
> +
> +/*
> + * An iterator over nothing (its first ref_iterator_advance() call
> + * returns 0).
> + */
s/0/ITER_DONE/
Show 6 quoted lines
> +struct ref_iterator *empty_ref_iterator_begin(void);
> +
> +/*
> + * Return true iff ref_iterator is an empty_ref_iterator.
> + */
> +int is_empty_ref_iterator(struct ref_iterator *ref_iterator);

I can see that you used this function as an optimization or convenience in overlay_ref_iterator_begin(), but do you expect it to be generally useful otherwise? Is it worth publishing? Do you have other use-cases in mind?

Also, can you explain why the merge iterator doesn't also perform the optimization/convenience of checking if one iterator is an empty iterator?

> +/*
> + * Iterate over the intries from iter0 and iter1, with the values
s/intries/entries/
Show 21 quoted lines
> + * interleaved as directed by the select function. The iterator takes
> + * ownership of iter0 and iter1 and frees them when the iteration is
> + * over.
> + */
> +struct ref_iterator *merge_ref_iterator_begin(
> +               struct ref_iterator *iter0, struct ref_iterator *iter1,
> +               ref_iterator_select_fn *select, void *cb_data);
> +
> +/*
> + * An iterator consisting of the union of the entries from iter0 and
> + * iter1. If there are entries common to the two sub-iterators, use
> + * the one from iter1. Each iterator must iterate over its entries in
> + * strcmp() order by refname for this to work.
> + *
> + * The new iterator takes ownership of its arguments and frees them
> + * when the iteration is over. As a convenience to callers, if iter0
> + * or iter1 is_empty_ref_iterator(), then abort that one immediately
> + * and return the other iterator directly, without wrapping it.
> + */
> +struct ref_iterator *overlay_ref_iterator_begin(struct ref_iterator *iter0,
> +                                               struct ref_iterator *iter1);

When reading about the overlay iterator (both code and documentation), my expectation was that iter0 would shadow iter1, not the other way around as implemented here. Of course, that's entirely subjective, but the generic names don't provide any useful clues as to which shadows which. Perhaps giving them more meaningful names would help.

Show 15 quoted lines
> +/*
> + * Wrap iter0, only letting through the references whose names start
> + * with prefix. If trim is set, set iter->refname to the name of the
> + * reference with that many characters trimmed off the front;
> + * otherwise set it to the full refname. The new iterator takes over
> + * ownership of iter0 and frees it when iteration is over. It makes
> + * its own copy of prefix.
> + *
> + * As an convenience to callers, if prefix is the empty string and
> + * trim is zero, this function returns iter0 directly, without
> + * wrapping it.
> + */
> +struct ref_iterator *prefix_ref_iterator_begin(struct ref_iterator *iter0,
> +                                              const char *prefix,
> +                                              int trim);
Minor: Similarly, when reading the code and documentation, I wondered
why this was named 'iter0' when no 'iter1' was in sight. Perhaps name
it simply 'iter'.
Previous: Michael HaggertyNext: Michael Haggerty
Message 14 of 27 in “Reference iterators”
  1. 00/13 Reference iteratorsMichael Haggerty, May 30, 2016
  2. 01/13 refs: remove unnecessary "extern" keywordsMichael Haggerty, May 30, 2016
  3. 02/13 do_for_each_ref(): move docstring to the header fileMichael Haggerty, May 30, 2016
  4. 03/13 refs: use name "prefix" consistentlyMichael Haggerty, May 30, 2016
  5. 04/13 delete_refs(): add a flags argumentMichael Haggerty, May 30, 2016
  6. 05/13 remote rm: handle symbolic refs correctlyMichael Haggerty, May 30, 2016
  7. 06/13 get_ref_cache(): only create an instance if there is a submoduleMichael Haggerty, May 30, 2016
  8. 07/13 entry_resolves_to_object(): rename function from ref_resolves_to_object()Michael Haggerty, May 30, 2016
  9. 08/13 ref_resolves_to_object(): new functionMichael Haggerty, May 30, 2016
  10. 09/13 refs: introduce an iterator interfaceMichael Haggerty, May 30, 2016
  11. Ramsay JonesMay 30, 2016
  12. Ramsay JonesMay 30, 2016
  13. Michael HaggertyMay 31, 2016
  14. Eric SunshineMay 31, 2016
  15. Michael HaggertyMay 31, 2016
  16. Eric SunshineMay 31, 2016
  17. Michael HaggertyJun 3, 2016
  18. Junio C HamanoMay 31, 2016
  19. Michael HaggertyMay 31, 2016
  20. Duy NguyenJun 2, 2016
  21. Michael HaggertyJun 2, 2016
  22. 10/13 do_for_each_ref(): reimplement using reference iterationMichael Haggerty, May 30, 2016
  23. 11/13 for_each_reflog(): don't abort for bad referencesMichael Haggerty, May 30, 2016
  24. 12/13 dir_iterator: new API for iterating over a directory treeMichael Haggerty, May 30, 2016
  25. David TurnerJun 1, 2016
  26. Michael HaggertyJun 3, 2016
  27. 13/13 for_each_reflog(): reimplement using iteratorsMichael Haggerty, May 30, 2016

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.