Fix a refname trimming problem in `log --bisect`
v2 cover Fix a refname trimming problem in `log --bisect`
This is v2 of these patches. Thanks to Peff and Junio for their feedback about v1 [1].
Changes since v1:
* Added a test and tweaked the commit message of the first patch.
As before, the second patch is optional. If it is omitted, it might flush out any other bugs like this one in client code. If it is included, regressions are less likely, but we won't learn about other misuses of the API. I have no strong opinion either way.
Michael
[1] http://public-inbox.org/git/[email protected]/
Michael Haggerty (2):
for_each_bisect_ref(): don't trim refnames prefix_ref_iterator_advance(): relax the check of trim length
refs.c | 12 ++++++++++++ refs.h | 5 ++++- refs/iterator.c | 8 ++++---- revision.c | 2 +- t/t6002-rev-list-bisect.sh | 14 ++++++++++++++ 5 files changed, 35 insertions(+), 6 deletions(-)
Signature · 1 line
2.11.0
PATCH v2 1/2 for_each_bisect_ref(): don't trim refnames
for_each_bisect_ref() is called by for_each_bad_bisect_ref() with a term "bad". This used to make it call for_each_ref_in_submodule() with a prefix "refs/bisect/bad". But the latter is the name of the reference that is being sought, so the empty string was being passed to the callback as the trimmed refname. Moreover, this questionable practice was turned into an error by
b9c8e7f2fb prefix_ref_iterator: don't trim too much, 2017-05-22
It makes more sense (and agrees better with the documentation of --bisect) for the callers to receive the full reference names. So
* Add a new function, for_each_fullref_in_submodule(), to the refs API. This plugs a gap in the existing functionality, analogous to for_each_fullref_in() but accepting a submodule argument.
* Change for_each_bad_bisect_ref() to call the new function rather than for_each_ref_in_submodule().
* Add a test.
--- refs.c | 12 ++++++++++++ refs.h | 5 ++++- revision.c | 2 +- t/t6002-rev-list-bisect.sh | 14 ++++++++++++++ 4 files changed, 31 insertions(+), 2 deletions(-)
refs.c +12 -0
@@ -1341,6 +1341,18 @@ int for_each_ref_in_submodule(const char *submodule, const char *prefix, prefix, fn, cb_data); } +int for_each_fullref_in_submodule (const char *submodule,const char *prefix, +each_ref_fn fn,void *cb_data, +unsigned int broken) +{ +unsigned int flag =0 ; + +if (broken) + flag =DO_FOR_EACH_INCLUDE_BROKEN ; +return do_for_each_ref (get_submodule_ref_store (submodule), + prefix, fn,0 , flag, cb_data); +} +int for_each_replace_ref (each_ref_fn fn,void *cb_data) { return do_for_each_ref(get_main_ref_store(),
refs.h +4 -1
@@ -303,7 +303,10 @@ int head_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data);int for_each_ref_submodule (const char *submodule,each_ref_fn fn,void *cb_data);int for_each_ref_in_submodule (const char *submodule,const char *prefix, -each_ref_fn fn,void *cb_data); +each_ref_fn fn,void *cb_data); +int for_each_fullref_in_submodule (const char *submodule,const char *prefix, +each_ref_fn fn,void *cb_data, +unsigned int broken);int for_each_tag_ref_submodule (const char *submodule,each_ref_fn fn,void *cb_data); int for_each_branch_ref_submodule(const char *submodule,
revision.c +1 -1
@@ -2044,7 +2044,7 @@ static int for_each_bisect_ref(const char *submodule, each_ref_fn fn, void *cb_dstruct strbuf bisect_refs =STRBUF_INIT ;int status;strbuf_addf (&bisect_refs,"refs/bisect/%s" , term); - status =for_each_ref_in_submodule (submodule, bisect_refs.buf, fn, cb_data); + status =for_each_fullref_in_submodule (submodule, bisect_refs.buf, fn, cb_data,0 );strbuf_release (&bisect_refs);return status; }
t/t6002-rev-list-bisect.sh +14 -0
@@ -235,4 +235,18 @@ test_sequence "--bisect" # # + +test_expect_success '--bisect can default to good/bad refs' ' + git update-ref refs/bisect/bad c3 && + good=$(git rev-parse b1) && + git update-ref refs/bisect/good-$good $good && + good=$(git rev-parse c1) && + git update-ref refs/bisect/good-$good $good && + + # the only thing between c3 and c1 is c2 + git rev-parse c2 >expect && + git rev-list --bisect >actual && + test_cmp expect actual +' + test_done
Signature · 1 line
2.11.0
PATCH v2 2/2 prefix_ref_iterator_advance(): relax the check of trim length
In reply to Michael HaggertyBefore the previous commit, for_each_bad_bisect_ref() called for_each_fullref_in_submodule() in such a way as to trim the whole refname away. This is a questionable use of the API, but is not ipso facto dangerous, so tolerate it in case there are other callers relying on this behavior. But continue to refuse to trim *more* characters than the refname contains, as that really makes no sense.
--- refs/iterator.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
refs/iterator.c +4 -4
@@ -298,11 +298,11 @@ static int prefix_ref_iterator_advance(struct ref_iterator *ref_iterator)* you haven't already checked for via a * prefix check, whether via this * `prefix_ref_iterator` or upstream in -* `iter0`). So if there wouldn't be at least -* one character left in the refname after -* trimming, report it as a bug: +* `iter0`. So consider it a bug if we are +* asked to trim off more characters than the +* refname contains: */ -if (strlen (iter->iter0->refname) <= iter->trim) +if (strlen (iter->iter0->refname) < iter->trim)die ("BUG: attempt to trim too many characters" ); iter->base.refname = iter->iter0->refname + iter->trim; }else {
Signature · 1 line
2.11.0
Quoted 6 lines · Michael Haggerty
This is v2 of these patches. Thanks to Peff and Junio for their feedback about v1 [1].
Changes since v1:
* Added a test and tweaked the commit message of the first patch.
Thanks, both changes look good to me.
Quoted 4 lines
As before, the second patch is optional. If it is omitted, it might flush out any other bugs like this one in client code. If it is included, regressions are less likely, but we won't learn about other misuses of the API. I have no strong opinion either way.
My feeling is still slightly towards "don't include", but I also don't have a strong opinion.
-Peff
Quoted 9 lines · Jeff King
Quoted 4 lines · Michael Haggerty
As before, the second patch is optional. If it is omitted, it might flush out any other bugs like this one in client code. If it is included, regressions are less likely, but we won't learn about other misuses of the API. I have no strong opinion either way.
My feeling is still slightly towards "don't include", but I also don't have a strong opinion.
I am inclined to the "don't include 2/2 and cook 1/2 alone but a bit longer" approach.
Thanks, both.
Quoted 9 lines · Junio C Hamano
Quoted 7 lines · Jeff King
Quoted 4 lines · Michael Haggerty
As before, the second patch is optional. If it is omitted, it might flush out any other bugs like this one in client code. If it is included, regressions are less likely, but we won't learn about other misuses of the API. I have no strong opinion either way.
Quoted 5 lines
Quoted 2 lines
My feeling is still slightly towards "don't include", but I also don't have a strong opinion.
I am inclined to the "don't include 2/2 and cook 1/2 alone but a bit longer" approach.
I don't think it helps to cook 1/2 longer. The assertion that triggered is already in master. Patch 1 fixes one case in an obviously-correct way. Patch 2 is just about guessing whether _other_ cases may trigger.
So if we wanted to cook longer we'd have to revert b9c8e7f2f (prefix_ref_iterator: don't trim too much, 2017-05-22), but I don't think that's worth doing.
-Peff