<feed xmlns='http://www.w3.org/2005/Atom'>
<title>git/ref-filter.c, branch v2.42.2</title>
<subtitle>Mirror of https://git.kernel.org/pub/scm/git/git.git/
</subtitle>
<id>https://git.shady.money/git/atom?h=v2.42.2</id>
<link rel='self' href='https://git.shady.money/git/atom?h=v2.42.2'/>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/'/>
<updated>2023-09-05T21:49:40Z</updated>
<entry>
<title>ref-filter: sort numerically when ":size" is used</title>
<updated>2023-09-05T21:49:40Z</updated>
<author>
<name>Kousik Sanagavarapu</name>
<email>five231003@gmail.com</email>
</author>
<published>2023-09-02T09:00:39Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=6d79cd8474b7bb4979f2a7544fd736bed190261a'/>
<id>urn:sha1:6d79cd8474b7bb4979f2a7544fd736bed190261a</id>
<content type='text'>
Atoms like "raw" and "contents" have a ":size" option which can be used
to know the size of the data. Since these atoms have the cmp_type
FIELD_STR, they are sorted alphabetically from 'a' to 'z' and '0' to
'9'. Meaning, even when the ":size" option is used and what we
ultimatlely have is numbers, we still sort alphabetically.

For example, consider the the following case in a repo

refname			contents:size		raw:size
=======			=============		========
refs/heads/branch1	1130			1210
refs/heads/master	300			410
refs/tags/v1.0		140			260

Sorting with "--format="%(refname) %(contents:size) --sort=contents:size"
would give

refs/heads/branch1 1130
refs/tags/v1.0.0 140
refs/heads/master 300

which is an alphabetic sort, while what one might really expect is

refs/tags/v1.0.0 140
refs/heads/master 300
refs/heads/branch1 1130

which is a numeric sort (that is, a "$ sort -n file" as opposed to a
"$ sort file", where "file" contains only the "contents:size" or
"raw:size" info, each of which is on a newline).

Same is the case with "--sort=raw:size".

So, sort numerically whenever the sort is done with "contents:size" or
"raw:size" and do it the normal alphabetic way when "contents" or "raw"
are used with some other option (they are FIELD_STR anyways).

Helped-by: Jeff King &lt;peff@peff.net&gt;
Signed-off-by: Kousik Sanagavarapu &lt;five231003@gmail.com&gt;
Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
<entry>
<title>Merge branch 'ks/ref-filter-describe'</title>
<updated>2023-08-02T16:37:24Z</updated>
<author>
<name>Junio C Hamano</name>
<email>gitster@pobox.com</email>
</author>
<published>2023-08-02T16:37:24Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=70e5c5ddddadc7f15f64f812ae511eab83ca0040'/>
<id>urn:sha1:70e5c5ddddadc7f15f64f812ae511eab83ca0040</id>
<content type='text'>
"git branch --list --format=&lt;format&gt;" and friends are taught
a new "%(describe)" placeholder.

* ks/ref-filter-describe:
  ref-filter: add new "describe" atom
  ref-filter: add multiple-option parsing functions
</content>
</entry>
<entry>
<title>Merge branch 'jk/nested-points-at'</title>
<updated>2023-07-25T19:05:24Z</updated>
<author>
<name>Junio C Hamano</name>
<email>gitster@pobox.com</email>
</author>
<published>2023-07-25T19:05:24Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=5929e66755acc797b2612d8d6d6b6fd6e7759169'/>
<id>urn:sha1:5929e66755acc797b2612d8d6d6b6fd6e7759169</id>
<content type='text'>
"git tag --list --points-at X" showed tags that directly refers to
object X, but did not list a tag that points at such a tag, which
has been corrected.

* jk/nested-points-at:
  ref-filter: simplify return type of match_points_at
  ref-filter: avoid parsing non-tags in match_points_at()
  ref-filter: avoid parsing tagged objects in match_points_at()
  ref-filter: handle nested tags in --points-at option
</content>
</entry>
<entry>
<title>ref-filter: add new "describe" atom</title>
<updated>2023-07-24T17:42:29Z</updated>
<author>
<name>Kousik Sanagavarapu</name>
<email>five231003@gmail.com</email>
</author>
<published>2023-07-23T16:19:59Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=f5d18f8c0ef9cc3e62420268c2e72d1fd46b940c'/>
<id>urn:sha1:f5d18f8c0ef9cc3e62420268c2e72d1fd46b940c</id>
<content type='text'>
Duplicate the logic of %(describe) and friends from pretty to
ref-filter. In the future, this change helps in unifying both the
formats as ref-filter will be able to do everything that pretty is doing
and we can have a single interface.

The new atom "describe" and its friends are equivalent to the existing
pretty formats with the same name.

Helped-by: Junio C Hamano &lt;gitster@pobox.com&gt;
Mentored-by: Christian Couder &lt;christian.couder@gmail.com&gt;
Mentored-by: Hariom Verma &lt;hariom18599@gmail.com&gt;
Signed-off-by: Kousik Sanagavarapu &lt;five231003@gmail.com&gt;
Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
<entry>
<title>ref-filter: add multiple-option parsing functions</title>
<updated>2023-07-24T16:55:00Z</updated>
<author>
<name>Kousik Sanagavarapu</name>
<email>five231003@gmail.com</email>
</author>
<published>2023-07-23T16:19:58Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=f46094a5e6b80098786b4e1448be032dfbdf3f43'/>
<id>urn:sha1:f46094a5e6b80098786b4e1448be032dfbdf3f43</id>
<content type='text'>
The functions

	match_placeholder_arg_value()
	match_placeholder_bool_arg()

were added in pretty 4f732e0fd7 (pretty: allow %(trailers) options
with explicit value, 2019-01-29) to parse multiple options in an
argument to --pretty. For example,

	git log --pretty="%(trailers:key=Signed-Off-By,separator=%x2C )"

will output all the trailers matching the key and seperates them by
a comma followed by a space per commit.

Add similar functions,

	match_atom_arg_value()
	match_atom_bool_arg()

in ref-filter.

There is no atom yet that can use these functions in ref-filter, but we
are going to add a new %(describe) atom in a subsequent commit where we
parse options like tags=&lt;bool-value&gt; or match=&lt;pattern&gt; given to it.

Helped-by: Junio C Hamano &lt;gitster@pobox.com&gt;
Mentored-by: Christian Couder &lt;christian.couder@gmail.com&gt;
Mentored-by: Hariom Verma &lt;hariom18599@gmail.com&gt;
Signed-off-by: Kousik Sanagavarapu &lt;five231003@gmail.com&gt;
Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
<entry>
<title>Merge branch 'tb/refs-exclusion-and-packed-refs'</title>
<updated>2023-07-21T20:47:26Z</updated>
<author>
<name>Junio C Hamano</name>
<email>gitster@pobox.com</email>
</author>
<published>2023-07-21T20:47:26Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=39fe402d6727efb6c98ddca19fae1f094ffaa6b3'/>
<id>urn:sha1:39fe402d6727efb6c98ddca19fae1f094ffaa6b3</id>
<content type='text'>
Enumerating refs in the packed-refs file, while excluding refs that
match certain patterns, has been optimized.

* tb/refs-exclusion-and-packed-refs:
  ls-refs.c: avoid enumerating hidden refs where possible
  upload-pack.c: avoid enumerating hidden refs where possible
  builtin/receive-pack.c: avoid enumerating hidden references
  refs.h: implement `hidden_refs_to_excludes()`
  refs.h: let `for_each_namespaced_ref()` take excluded patterns
  revision.h: store hidden refs in a `strvec`
  refs/packed-backend.c: add trace2 counters for jump list
  refs/packed-backend.c: implement jump lists to avoid excluded pattern(s)
  refs/packed-backend.c: refactor `find_reference_location()`
  refs: plumb `exclude_patterns` argument throughout
  builtin/for-each-ref.c: add `--exclude` option
  ref-filter.c: parameterize match functions over patterns
  ref-filter: add `ref_filter_clear()`
  ref-filter: clear reachable list pointers after freeing
  ref-filter.h: provide `REF_FILTER_INIT`
  refs.c: rename `ref_filter`
</content>
</entry>
<entry>
<title>ref-filter: simplify return type of match_points_at</title>
<updated>2023-07-17T21:16:05Z</updated>
<author>
<name>Jeff King</name>
<email>peff@peff.net</email>
</author>
<published>2023-07-02T22:38:29Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=d9e00621591549cd2d9989d290a7e0c63eadd03b'/>
<id>urn:sha1:d9e00621591549cd2d9989d290a7e0c63eadd03b</id>
<content type='text'>
We return the oid that matched, but the sole caller only cares whether
we matched anything at all. This is mostly academic, since there's only
one caller, but the lifetime of the returned pointer is not immediately
clear. Sometimes it points to an oid in a tag struct, which should live
forever. And sometimes to the oid passed in, which only lives as long as
the each_ref_fn callback we're called from.

Simplify this to a boolean return which is more direct and obvious. As a
bonus, this lets us avoid the weird pattern of overwriting our "oid"
parameter in the loop (since we now only refer to the tagged oid one
time, and can just inline the call to get it).

Signed-off-by: Jeff King &lt;peff@peff.net&gt;
Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
<entry>
<title>ref-filter: avoid parsing non-tags in match_points_at()</title>
<updated>2023-07-17T21:16:05Z</updated>
<author>
<name>Jeff King</name>
<email>peff@peff.net</email>
</author>
<published>2023-07-02T22:37:47Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=870eb53ab20e9ff453e3b89b4927c154c2b7211a'/>
<id>urn:sha1:870eb53ab20e9ff453e3b89b4927c154c2b7211a</id>
<content type='text'>
When handling --points-at, we have to try to peel each ref to see if
it's a tag that points at a requested oid. We start this process by
calling parse_object() on the oid pointed to by each ref.

The cost of parsing each object adds up, especially in an output that
doesn't otherwise need to open the objects at all. Ideally we'd use
peel_iterated_oid() here, which uses the cached information in the
packed-refs file. But we can't, because our --points-at must match not
only the fully peeled value, but any interim values (so if tag A points
to tag B which points to commit C, we should match --points-at=B, but
peel_iterated_oid() will only tell us about C).

So the best we can do (absent changes to the packed-refs peel traits) is
to avoid parsing non-tags. The obvious way to do that is to call
oid_object_info() to check the type before parsing. But there are a few
gotchas there, like checking if the object has already been parsed.

Instead we can just tell parse_object() that we are OK skipping the hash
check, which lets it turn on several optimizations. Commits can be
loaded via the commit graph (so it's both fast and we have the benefit
of the parsed data if we need it later at the output stage). Blobs are
not loaded at all. Trees are still loaded, but it's rather rare to have
a ref point directly to a tree (and since this is just an optimization,
kicking in 99% of the time is OK).

Even though we're paying for an extra lookup, the cost to avoid parsing
the non-tags is a net benefit. In my git.git repository with 941 tags
and 1440 other refs pointing to commits, this significantly cuts the
runtime:

  Benchmark 1: ./git.old for-each-ref --points-at=HEAD
    Time (mean ± σ):      26.8 ms ±   0.5 ms    [User: 24.5 ms, System: 2.2 ms]
    Range (min … max):    25.9 ms …  29.2 ms    107 runs

  Benchmark 2: ./git.new for-each-ref --points-at=HEAD
    Time (mean ± σ):       9.1 ms ±   0.3 ms    [User: 6.8 ms, System: 2.2 ms]
    Range (min … max):     8.6 ms …  10.2 ms    308 runs

  Summary
    './git.new for-each-ref --points-at=HEAD' ran
      2.96 ± 0.10 times faster than './git.old for-each-ref --points-at=HEAD'

In a repository that is mostly annotated tags, we'd expect less
improvement (we might still skip a few object loads, but that's balanced
by the extra lookups). In my clone of linux.git, which has 782 tags and
3 branches, the run-time is about the same (it's actually ~1% faster on
average after this patch, but that's within the run-to-run noise).

Signed-off-by: Jeff King &lt;peff@peff.net&gt;
Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
<entry>
<title>ref-filter: avoid parsing tagged objects in match_points_at()</title>
<updated>2023-07-17T21:16:05Z</updated>
<author>
<name>Jeff King</name>
<email>peff@peff.net</email>
</author>
<published>2023-07-02T22:35:40Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=b9584c5858799d5603851af5f0dbad5e7af29b22'/>
<id>urn:sha1:b9584c5858799d5603851af5f0dbad5e7af29b22</id>
<content type='text'>
When we peel tags to check if they match a --points-at oid, we
recursively parse the tagged object to see if it is also a tag. But
since the tag itself tells us the type of the object it points to (and
even gives us the appropriate object struct via its "tagged" member), we
can use that directly.

We do still have to make sure to call parse_tag() before looking at each
tag. This is redundant for the outermost tag (since we did call
parse_object() to find its type), but that's OK; parse_tag() is smart
enough to make this a noop when the tag has already been parsed.

In my clone of linux.git, with 782 tags (and only 3 non-tags), this
yields a significant speedup (bringing us back where we were before the
commit before this one started recursively dereferencing tags):

  Benchmark 1: ./git.old for-each-ref --points-at=HEAD --format="%(refname)"
    Time (mean ± σ):      20.3 ms ±   0.5 ms    [User: 11.1 ms, System: 9.1 ms]
    Range (min … max):    19.6 ms …  21.5 ms    141 runs

  Benchmark 2: ./git.new for-each-ref --points-at=HEAD --format="%(refname)"
    Time (mean ± σ):      11.4 ms ±   0.2 ms    [User: 6.3 ms, System: 5.0 ms]
    Range (min … max):    11.0 ms …  12.2 ms    250 runs

  Summary
    './git.new for-each-ref --points-at=HEAD --format="%(refname)"' ran
      1.79 ± 0.05 times faster than './git.old for-each-ref --points-at=HEAD --format="%(refname)"'

Signed-off-by: Jeff King &lt;peff@peff.net&gt;
Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
<entry>
<title>ref-filter: handle nested tags in --points-at option</title>
<updated>2023-07-17T21:16:05Z</updated>
<author>
<name>Jan Klötzke</name>
<email>jan@kloetzke.net</email>
</author>
<published>2023-07-01T20:57:02Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/git/commit/?id=468887f0f8a0a9e465737c3ad23cb40c8d690f2f'/>
<id>urn:sha1:468887f0f8a0a9e465737c3ad23cb40c8d690f2f</id>
<content type='text'>
Tags are dereferenced until reaching a different object type to handle
nested tags, e.g. on checkout. In contrast, "git tag --points-at=..."
fails to list such nested tags because only one level of indirection is
obtained in filter_refs(). Implement the recursive dereferencing for the
"--points-at" option when filtering refs to unify the behaviour.

Signed-off-by: Jan Klötzke &lt;jan@kloetzke.net&gt;
Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
</content>
</entry>
</feed>
