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

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

From
Ramsay Jones <ramsay@ramsayjones.plus.com>
Date
May 30, 2016, 16:57 UTC
Message-ID
<574C70EF.5070705@ramsayjones.plus.com>
In-Reply-To
<574C5AB0.4090005@ramsayjones.plus.com>
On 30/05/16 16:22, Ramsay Jones wrote:
Show 106 quoted lines
> 
> 
> On 30/05/16 08:55, Michael Haggerty wrote:
> [snip]
> 
>>  /* Reference is a symbolic reference. */
>> diff --git a/refs/files-backend.c b/refs/files-backend.c
>> index 8ab4d5f..dbf1587 100644
>> --- a/refs/files-backend.c
>> +++ b/refs/files-backend.c
>> @@ -1,6 +1,7 @@
>>  #include "../cache.h"
>>  #include "../refs.h"
>>  #include "refs-internal.h"
>> +#include "../iterator.h"
>>  #include "../lockfile.h"
>>  #include "../object.h"
>>  #include "../dir.h"
>> @@ -704,6 +705,154 @@ static void prime_ref_dir(struct ref_dir *dir)
>>  	}
>>  }
>>  
>> +/*
>> + * A level in the reference hierarchy that is currently being iterated
>> + * through.
>> + */
>> +struct cache_ref_iterator_level {
>> +	/*
>> +	 * The ref_dir being iterated over at this level. The ref_dir
>> +         * is sorted before being stored here.
>> +	 */
>> +	struct ref_dir *dir;
>> +
>> +	/*
>> +	 * The index of the current entry within dir (which might
>> +	 * itself be a directory). If index == -1, then the iteration
>> +	 * hasn't yet begun. If index == dir->nr, then the iteration
>> +	 * through this level is over.
>> +	 */
>> +	int index;
>> +};
>> +
>> +/*
>> + * Represent an iteration through a ref_dir in the memory cache. The
>> + * iteration recurses through subdirectories.
>> + */
>> +struct cache_ref_iterator {
>> +	struct ref_iterator base;
>> +
>> +	/*
>> +	 * The number of levels currently on the stack. This is always
>> +	 * at least 1, because when it becomes zero the iteration is
>> +	 * ended and this struct is freed.
>> +	 */
>> +	size_t levels_nr;
>> +
>> +	/* The number of levels that have been allocated on the stack */
>> +	size_t levels_alloc;
>> +
>> +	/*
>> +	 * A stack of levels. levels[0] is the uppermost level that is
>> +	 * being iterated over in this iteration. (This is not
>> +	 * necessary the top level in the references hierarchy. If we
>> +	 * are iterating through a subtree, then levels[0] will hold
>> +	 * the ref_dir for that subtree, and subsequent levels will go
>> +	 * on from there.)
>> +	 */
>> +	struct cache_ref_iterator_level *levels;
>> +};
>> +
>> +static int cache_ref_iterator_advance(struct ref_iterator *ref_iterator)
>> +{
>> +	struct cache_ref_iterator *iter =
>> +		(struct cache_ref_iterator *)ref_iterator;
>> +
>> +	while (1) {
>> +		struct cache_ref_iterator_level *level =
>> +			&iter->levels[iter->levels_nr - 1];
>> +		struct ref_dir *dir = level->dir;
>> +		struct ref_entry *entry;
>> +
>> +		if (level->index == -1)
>> +			sort_ref_dir(dir);
> 
> do you need to sort here ...
>> +
>> +		if (++level->index == level->dir->nr) {
>> +			/* This level is exhausted; pop up a level */
>> +			if (--iter->levels_nr == 0)
>> +				return ref_iterator_abort(ref_iterator);
>> +
>> +			continue;
>> +		}
>> +
>> +		entry = dir->entries[level->index];
>> +
>> +		if (entry->flag & REF_DIR) {
>> +			/* push down a level */
>> +			ALLOC_GROW(iter->levels, iter->levels_nr + 1,
>> +				   iter->levels_alloc);
>> +
>> +			level = &iter->levels[iter->levels_nr++];
>> +			level->dir = get_ref_dir(entry);
>> +			sort_ref_dir(level->dir);
> 
> ... given that you sort here?

I had intended to say 'or vice versa' here. When I wrote this, I had not finished reading this patch (let alone the series). Now, I suspect that you can simply drop this 'sort_ref_dir()' call site. Unless I've misread the code, of course! ;-)

ATB, Ramsay Jones

Previous: Ramsay JonesNext: Michael Haggerty
Message 12 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.