Git bisect part3
cover Git bisect part3
Changes since pranit’s v15 patch series
=======================================
bisect--helper: refer branch.buf before strbuf_release(...)
===========================================================
bisect--helper: change retval to res
====================================
bisect--helper: decide_next() helper function.
==============================================
bisect--helper: bisect_next and bisect_auto_next shell function in C
====================================================================
Divided this commit into nine commits
=====================================
1. bisect.c: libify exit_if_skipped_commits to error_if_skipped... 2. bisect.c: libify bisect_checkout and its dependants 3. bisect.c: libify check_merge_bases and its dependents. 4. bisect.c: libify check_good_are_ancestors_of_bad and its dependents 5. bisect.c: libify handle_bad_merge_base and its dependants 6. bisect.c: libify bisect_next_all and its dependants 7. bisect--helper: bisect_next and bisect_auto_next shell function in C 8. bisect--helper: Finish bisect_start() conversion 9. bisect--helper: dequote arguments in bisect-start
10. changed error to return error
11. Removed goto done; as it was present just before done: call
12. Use xstrdup(argv[i]) instead of argv[i] to prevent memory leak
13. Adjusted the indentation Style: removed a space left of the comma.
14. Changed the find the next bisection state statement to ‘checkout the next bisection commit’
15. Changed ‘sha1_to_hex’ to ‘oid_to_hex’ as modern code does not use this unsigned function
16. Changed the return type from ‘void’ to ‘int’ as the function was returning a value
17. Changed ‘const unsigned sha1’ to ‘struct object_id oid’
18. Changed (res == 10) branch and the (res == 2) branch into separate functions bisect_successful(struct bisect_terms *terms) and bisect_skipped_commits(struct bisect_terms *terms)respectively and just call them.
19. Removed unnecessary comments
20. Changed exit code to return type like exit(2) to return 2; and
exit(res) to return res;
21. Changed handle_bad_merge_base(); to declare res =
handle_skipped_merge_base(mb); 22. Changed bisect_start to git bisect--helper --bisect-start
bisect--helper: retire --bisect-clean-state subcommand
======================================================
bisect--helper: retire --next-all subcommand
============================================
bisect--helper: retire --check-expected-revs subcommand
=======================================================
bisect--helper: retire --write-terms subcommand
===============================================
bisect--helper: retire --bisect-write subcommand
================================================
bisect--helper: retire --bisect-autostart subcommand
====================================================
bisect--helper: retire --bisect-auto-next subcommand
====================================================
bisect--helper: retire --check-and-set-terms subcommand
=======================================================
bisect--helper: bisect_autostart shell function in C
====================================================
* Use STDIN_FINENO instead of 0.
* Fix typo THe to The
* Use return 1 instead of exit(0). Sayingno` is same outcome as not having a tty to ask for yes or no.
* Add missing is in N_("start the bisection if BISECT_START empty or missing"), BISECT_AUTOSTART),
* use set_terms()
* die(“...”) to return error(“...”)
bisect--helper: bisect_state & bisect_head shell function in C
==============================================================
* move get_terms() to cmd_bisect__helper()
* die(“...”) to return error(“...”)
* use oid instead of sha1. convert dependant functions also.
* check_expected_revs() returns void, remove if around it.
* use set_terms()
bisect--helper: bisect_log shell function in C
==============================================
* use STDOUT_FILENO instead of 1.
* die(“...”) to return error(“...”)
bisect--helper: bisect_replay shell function in C
=================================================
* use “cannot read file '%s' for replaying” error message instead of “no such file with name '%s' exists”, as it would be misleading if the file exists but is empty.
* starts_with(word.buf, "#") would be more accurate and can also handle cases where user edited the file and accidently removed <space> between # bad….
* bisect_terms() now accepts terms and option.
* use more informative error message : “Replay file contains rubbish ("%s")”
* remove unnecessary goto finish
* die(“...”) to return error(“...”)
* use set_terms()
bisect--helper: remove the dequote in bisect_start()
====================================================
bisect--helper: bisect_skip shell function in C
===============================================
Pranit Bauva (23):
bisect.c: libify exit_if_skipped_commits to error_if_skipped... bisect.c: libify bisect_checkout and its dependants bisect.c: libify check_merge_bases and its dependents. bisect.c: libify check_good_are_ancestors_of_bad and its dependents bisect.c: libify handle_bad_merge_base and its dependants bisect.c: libify bisect_next_all and its dependants
bisect--helper: bisect_next and bisect_auto_next shell function in
C
bisect--helper: Finish bisect_start() conversion
bisect--helper: dequote arguments in bisect-start
bisect--helper: retire --bisect-clean-state subcommand
bisect--helper: retire --next-all subcommand
bisect--helper: bisect_autostart shell function in C
bisect--helper: bisect_state & bisect_head shell function in C
bisect--helper: retire --check-expected-revs subcommand
bisect--helper: retire --write-terms subcommand
bisect--helper: bisect_log shell function in C
bisect--helper: bisect_replay shell function in C
bisect--helper: retire --bisect-write subcommand
bisect--helper: retire --bisect-autostart subcommand
bisect--helper: retire --bisect-auto-next subcommand
bisect--helper: remove the dequote in bisect_start()
bisect--helper: bisect_skip shell function in C
bisect--helper: retire --check-and-set-terms subcommand
Tanushree Tumane (3):
bisect--helper: refer branch.buf before strbuf_release(...)
bisect--helper: change retval to res
bisect--helper: decide_next() helper function.
bisect.c | 140 ++++++--- builtin/bisect--helper.c | 654 ++++++++++++++++++++++++++++++++------- git-bisect.sh | 196 +----------- 3 files changed, 649 insertions(+), 341 deletions(-)
base-commit: 06f5608c14e6972748b84649d5b8ffd335bbd209
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-117%2Ftanushree27%2Fgit-bisect-part3-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-117/tanushree27/git-bisect-part3-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/117
Signature · 1 line
gitgitgadget
PATCH 1/26 bisect--helper: refer branch.buf before strbuf_release(...)
From: Tanushree Tumane <[email protected]>
move error("...%s...", branch.buf); before strbuf_release(&branch);.
add ' ' before "reset.." in error message.
--- builtin/bisect--helper.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
builtin/bisect--helper.c +4 -3
@@ -169,11 +169,12 @@ static int bisect_reset(const char *commit)argv_array_pushl (&argv,"checkout" , branch.buf,"--" ,NULL );if (run_command_v_opt (argv.argv,RUN_GIT_CMD )) { +error (_ ("could not check out original" +" HEAD '%s'. Try 'git bisect" +" reset <commit>'." ), branch.buf);strbuf_release (&branch);argv_array_clear (&argv); -return error (_ ("could not check out original" -" HEAD '%s'. Try 'git bisect" -"reset <commit>'." ), branch.buf); +return -1 ; }argv_array_clear (&argv); }
Signature · 1 line
gitgitgadget
PATCH 2/26 bisect--helper: change `retval` to `res`
In reply to Tanushree Tumane via GitGitGadgetFrom: Tanushree Tumane <[email protected]>
Conversion of variable retval to res to have a uniformity of a single variable all over the patch series, which makes the patch series unvaried.
--- builtin/bisect--helper.c | 50 ++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 25 deletions(-)
builtin/bisect--helper.c +25 -25
@@ -206,31 +206,31 @@ static int bisect_write(const char *state, const char *rev,struct object_id oid;struct commit *commit;FILE *fp =NULL ; -int retval =0 ; +int res =0 ;if (!strcmp (state, terms->term_bad)) {strbuf_addf (&tag,"refs/bisect/%s" , state); }else if (one_of (state, terms->term_good,"skip" ,NULL )) {strbuf_addf (&tag,"refs/bisect/%s-%s" , state, rev); }else { - retval =error (_ ("Bad bisect_write argument: %s" ), state); + res =error (_ ("Bad bisect_write argument: %s" ), state); goto finish; }if (get_oid (rev, &oid)) { - retval =error (_ ("couldn't get the oid of the rev '%s'" ), rev); + res =error (_ ("couldn't get the oid of the rev '%s'" ), rev); goto finish; }if (update_ref (NULL , tag.buf, &oid,NULL ,0 ,UPDATE_REFS_MSG_ON_ERR )) { - retval =-1 ; + res =-1 ; goto finish; } fp =fopen (git_path_bisect_log (),"a" );if (!fp) { - retval =error_errno (_ ("couldn't open the file '%s'" ),git_path_bisect_log ()); + res =error_errno (_ ("couldn't open the file '%s'" ),git_path_bisect_log ()); goto finish; }
@@ -244,7 +244,7 @@ static int bisect_write(const char *state, const char *rev,if (fp)fclose (fp);strbuf_release (&tag); -return retval; +return res; }static int check_and_set_terms (struct bisect_terms *terms,const char *cmd)
@@ -294,7 +294,7 @@ static const char *need_bisect_start_warning =static int bisect_next_check (const struct bisect_terms *terms,const char *current_term) { -int missing_good =1 , missing_bad =1 , retval =0 ; +int missing_good =1 , missing_bad =1 , res =0 ;const char *bad_ref =xstrfmt ("refs/bisect/%s" , terms->term_bad);const char *good_glob =xstrfmt ("%s-*" , terms->term_good);
@@ -308,7 +308,7 @@ static int bisect_next_check(const struct bisect_terms *terms, goto finish;if (!current_term) { - retval =-1 ; + res =-1 ; goto finish; }
@@ -329,21 +329,21 @@ static int bisect_next_check(const struct bisect_terms *terms,*/ yesno =git_prompt (_ ("Are you sure [Y/n]? " ),PROMPT_ECHO );if (starts_with (yesno,"N" ) ||starts_with (yesno,"n" )) - retval =-1 ; + res =-1 ; goto finish; }if (!is_empty_or_missing_file (git_path_bisect_start ())) { - retval =error (_ (need_bad_and_good_revision_warning), + res =error (_ (need_bad_and_good_revision_warning), vocab_bad, vocab_good, vocab_bad, vocab_good); }else { - retval =error (_ (need_bisect_start_warning), + res =error (_ (need_bisect_start_warning), vocab_good, vocab_bad, vocab_good, vocab_bad); } finish:free ((void *) good_glob);free ((void *) bad_ref); -return retval; +return res; }static int get_terms (struct bisect_terms *terms)
@@ -397,7 +397,7 @@ static int bisect_terms(struct bisect_terms *terms, const char *option)static int bisect_append_log_quoted (const char **argv) { -int retval =0 ; +int res =0 ;FILE *fp =fopen (git_path_bisect_log (),"a" );struct strbuf orig_args =STRBUF_INIT ;
@@ -405,25 +405,25 @@ static int bisect_append_log_quoted(const char **argv)return -1 ;if (fprintf (fp,"git bisect start" ) <1 ) { - retval =-1 ; + res =-1 ; goto finish; }sq_quote_argv (&orig_args, argv);if (fprintf (fp,"%s\n" , orig_args.buf) <1 ) - retval =-1 ; + res =-1 ; finish:fclose (fp);strbuf_release (&orig_args); -return retval; +return res; }static int bisect_start (struct bisect_terms *terms,int no_checkout,const char **argv,int argc) {int i, has_double_dash =0 , must_write_terms =0 , bad_seen =0 ; -int flags, pathspec_pos, retval =0 ; +int flags, pathspec_pos, res =0 ;struct string_list revs =STRING_LIST_INIT_DUP ;struct string_list states =STRING_LIST_INIT_DUP ;struct strbuf start_head =STRBUF_INIT ;
@@ -524,7 +524,7 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout,argv_array_pushl (&argv,"checkout" , start_head.buf,"--" ,NULL );if (run_command_v_opt (argv.argv,RUN_GIT_CMD )) { - retval =error (_ ("checking out '%s' failed." + res =error (_ ("checking out '%s' failed." " Try 'git bisect start " "<valid-branch>'." ), start_head.buf);
@@ -574,7 +574,7 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout,get_oid (start_head.buf, &oid);if (update_ref (NULL ,"BISECT_HEAD" , &oid,NULL ,0 ,UPDATE_REFS_MSG_ON_ERR )) { - retval =-1 ; + res =-1 ; goto finish; } }
@@ -586,26 +586,26 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout,for (i =0 ; i < states.nr; i++)if (bisect_write (states.items[i].string, revs.items[i].string, terms,1 )) { - retval =-1 ; + res =-1 ; goto finish; }if (must_write_terms &&write_terms (terms->term_bad, terms->term_good)) { - retval =-1 ; + res =-1 ; goto finish; } - retval =bisect_append_log_quoted (argv); -if (retval) - retval =-1 ; + res =bisect_append_log_quoted (argv); +if (res) + res =-1 ; finish:string_list_clear (&revs,0 );string_list_clear (&states,0 );strbuf_release (&start_head);strbuf_release (&bisect_names); -return retval; +return res; }int cmd_bisect__helper (int argc,const char **argv,const char *prefix)
Signature · 1 line
gitgitgadget
PATCH 3/26 bisect--helper: `decide_next()` helper function.
In reply to Tanushree Tumane via GitGitGadgetFrom: Tanushree Tumane <[email protected]>
introduce decide_next() helper function from bisect_next_check() for better and clear understanding.
convert *...warning char pointers to ...warning[]char arrays, as char [] only creates char array while char * creates both char array and a pointer to that char array.
--- builtin/bisect--helper.c | 66 +++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 32 deletions(-)
builtin/bisect--helper.c +34 -32
@@ -282,35 +282,23 @@ static int mark_good(const char *refname, const struct object_id *oid,return 1 ; } -static const char *need_bad_and_good_revision_warning = +static const char need_bad_and_good_revision_warning[] =N_ ("You need to give me at least one %s and %s revision.\n" "You can use \"git bisect %s\" and \"git bisect %s\" for that." ); -static const char *need_bisect_start_warning = +static const char need_bisect_start_warning[] =N_ ("You need to start by \"git bisect start\".\n" "You then need to give me at least one %s and %s revision.\n" "You can use \"git bisect %s\" and \"git bisect %s\" for that." ); -static int bisect_next_check (const struct bisect_terms *terms, -const char *current_term) +static int decide_next (const struct bisect_terms *terms, +const char *current_term,int missing_good, +int missing_bad) { -int missing_good =1 , missing_bad =1 , res =0 ; -const char *bad_ref =xstrfmt ("refs/bisect/%s" , terms->term_bad); -const char *good_glob =xstrfmt ("%s-*" , terms->term_good); - -if (ref_exists (bad_ref)) - missing_bad =0 ; - -for_each_glob_ref_in (mark_good, good_glob,"refs/bisect/" , - (void *) &missing_good); -if (!missing_good && !missing_bad) - goto finish; - -if (!current_term) { - res =-1 ; - goto finish; - } +return 0 ; +if (!current_term) +return -1 ;if (missing_good && !missing_bad && !strcmp (current_term, terms->term_good)) {
@@ -321,7 +309,7 @@ static int bisect_next_check(const struct bisect_terms *terms,*/ warning (_ ("bisecting only with a %s commit" ), terms->term_bad);if (!isatty (0 )) - goto finish; +return 0 ;/* * TRANSLATORS: Make sure to include [Y] and [n] in your * translation. The program will only accept English input
@@ -329,21 +317,35 @@ static int bisect_next_check(const struct bisect_terms *terms,*/ yesno =git_prompt (_ ("Are you sure [Y/n]? " ),PROMPT_ECHO );if (starts_with (yesno,"N" ) ||starts_with (yesno,"n" )) - res =-1 ; - goto finish; - } -if (!is_empty_or_missing_file (git_path_bisect_start ())) { - res =error (_ (need_bad_and_good_revision_warning), - vocab_bad, vocab_good, vocab_bad, vocab_good); - }else { - res =error (_ (need_bisect_start_warning), - vocab_good, vocab_bad, vocab_good, vocab_bad); +return -1 ; +return 0 ; } -finish: +if (!is_empty_or_missing_file (git_path_bisect_start ())) +return error (_ (need_bad_and_good_revision_warning), + vocab_bad, vocab_good, vocab_bad, vocab_good); +else +return error (_ (need_bisect_start_warning), + vocab_good, vocab_bad, vocab_good, vocab_bad); +} + +static int bisect_next_check (const struct bisect_terms *terms, +const char *current_term) +{ +int missing_good =1 , missing_bad =1 ; +const char *bad_ref =xstrfmt ("refs/bisect/%s" , terms->term_bad); +const char *good_glob =xstrfmt ("%s-*" , terms->term_good); + +if (ref_exists (bad_ref)) + missing_bad =0 ; + +for_each_glob_ref_in (mark_good, good_glob,"refs/bisect/" , + (void *) &missing_good); +free ((void *) good_glob);free ((void *) bad_ref); -return res; + +return decide_next (terms, current_term, missing_good, missing_bad); }static int get_terms (struct bisect_terms *terms)
Signature · 1 line
gitgitgadget
PATCH 4/26 bisect.c: libify `exit_if_skipped_commits` to `error_if_skipped...`
In reply to Tanushree Tumane via GitGitGadgetFrom: Pranit Bauva <[email protected]>
Since we want to get rid of git-bisect.sh it would be necessary to convert those exit() calls to return statements so that errors can be reported.
Emulate try catch in C by converting exit(<positive-value>) to return <negetive-value>. Follow POSIX conventions to return <negative-value> to indicate error.
Modify cmd_bisect_helper() to handle these negative returns.
Turn exit() to return calls in exit_if_skipped_commits() and rename the method to error_if_skipped_commits().
Handle this return in dependant method bisect_next_all().
--- bisect.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-)
bisect.c +16 -7
@@ -659,11 +659,11 @@ static void bisect_common(struct rev_info *revs)mark_edges_uninteresting (revs,NULL ); } -static void exit_if_skipped_commits (struct commit_list *tried, +static int error_if_skipped_commits (struct commit_list *tried,const struct object_id *bad) {if (!tried) -return ; +return 0 ;printf ("There are only 'skip'ped commits left to test.\n" "The first %s commit could be any of:\n" , term_bad);
@@ -674,7 +674,13 @@ static void exit_if_skipped_commits(struct commit_list *tried,if (bad)printf ("%s\n" ,oid_to_hex (bad));printf (_ ("We cannot bisect more!\n" )); -exit (2 ); + +/* +* We don't want to clean the bisection state +* as we need to get back to where we started +* by using `git bisect reset`. +*/ +return -2 ; }static int is_expected_rev (const struct object_id *oid)
@@ -949,7 +955,7 @@ int bisect_next_all(const char *prefix, int no_checkout) {struct rev_info revs;struct commit_list *tried; -int reaches =0 , all =0 , nr, steps; +int reaches =0 , all =0 , nr, steps, res;struct object_id *bisect_rev;char *steps_msg;
@@ -972,8 +978,9 @@ int bisect_next_all(const char *prefix, int no_checkout)* We should exit here only if the "bad" * commit is also a "skip" commit. */ -exit_if_skipped_commits (tried,NULL ); - + res =error_if_skipped_commits (tried,NULL ); +if (res) +exit (-res); printf(_("%s was both %s and %s\n"), oid_to_hex(current_bad_oid), term_good,
@@ -990,7 +997,9 @@ int bisect_next_all(const char *prefix, int no_checkout) bisect_rev = &revs.commits->item->object.oid;if (oideq (bisect_rev, current_bad_oid)) { -exit_if_skipped_commits (tried, current_bad_oid); + res =error_if_skipped_commits (tried, current_bad_oid); +if (res) +exit (-res);printf ("%s is the first %s commit\n" ,oid_to_hex (bisect_rev), term_bad);show_diff_tree (prefix, revs.commits->item);
Signature · 1 line
gitgitgadget
PATCH 5/26 bisect.c: libify `bisect_checkout` and its dependants
In reply to Tanushree Tumane via GitGitGadgetFrom: Pranit Bauva <[email protected]>
Since we want to get rid of git-bisect.sh it would be necessary to convert those exit() calls to return statements so that errors can be reported.
Emulate try catch in C by converting exit(<positive-value>) to return <negetive-value>. Follow POSIX conventions to return <negative-value> to indicate error.
Turn exit() to return calls in bisect_checkout().
Handle this return in dependant methods - check_merge_bases().
--- bisect.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
bisect.c +5 -5
@@ -710,7 +710,7 @@ static int is_expected_rev(const struct object_id *oid)static int bisect_checkout (const struct object_id *bisect_rev,int no_checkout) {char bisect_rev_hex[GIT_MAX_HEXSZ +1 ]; - +int res =0 ;memcpy (bisect_rev_hex,oid_to_hex (bisect_rev),GIT_SHA1_HEXSZ +1 );update_ref (NULL ,"BISECT_EXPECTED_REV" , bisect_rev,NULL ,0 ,UPDATE_REFS_DIE_ON_ERR );
@@ -719,14 +719,14 @@ static int bisect_checkout(const struct object_id *bisect_rev, int no_checkout)update_ref (NULL ,"BISECT_HEAD" , bisect_rev,NULL ,0 ,UPDATE_REFS_DIE_ON_ERR ); }else { -int res; res =run_command_v_opt (argv_checkout,RUN_GIT_CMD );if (res) -exit (res); +return res >0 ? -res : res; } argv_show_branch[1 ] = bisect_rev_hex; -return run_command_v_opt (argv_show_branch,RUN_GIT_CMD ); + res =run_command_v_opt (argv_show_branch,RUN_GIT_CMD ); +return res >0 ? -res : res; }static struct commit *get_commit_reference (const struct object_id *oid)
@@ -822,7 +822,7 @@ static void check_merge_bases(int rev_nr, struct commit **rev, int no_checkout)handle_skipped_merge_base (mb); }else {printf (_ ("Bisecting: a merge base must be tested\n" )); -exit (bisect_checkout (mb, no_checkout)); +exit (-bisect_checkout (mb, no_checkout)); } }
Signature · 1 line
gitgitgadget
PATCH 6/26 bisect.c: libify `check_merge_bases` and its dependents.
In reply to Tanushree Tumane via GitGitGadgetFrom: Pranit Bauva <[email protected]>
Since we want to get rid of git-bisect.sh it would be necessary to convert those exit() calls to return statements so that errors can be reported.
Emulate try catch in C by converting exit(<positive-value>) to return <negetive-value>. Follow POSIX conventions to return <negative-value> to indicate error.
Turn exit() to return calls in check_merge_bases().
In check_merge_bases() there is an early success special case,
so we have introduced special error code -11 which indicates early success. This -11 is converted back to 0 in check_good_are_ancestors_of_bad().
Mentored by: Johannes Schindelin <[email protected]>
--- bisect.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-)
bisect.c +15 -5
@@ -801,13 +801,16 @@ static void handle_skipped_merge_base(const struct object_id *mb)* "check_merge_bases" checks that merge bases are not "bad" (or "new"). * * - If one is "bad" (or "new"), it means the user assumed something wrong -* and we must exit with a non 0 error code. +* and we must return error with a non 0 error code. * - If one is "good" (or "old"), that's good, we have nothing to do. * - If one is "skipped", we can't know but we should warn. * - If we don't know, we should check it out and ask the user to test. +* - If a merge base must be tested, on success return -11 a special condition +* for early success, this will be converted back to 0 in cmd_bisect__helper. */ -static void check_merge_bases (int rev_nr,struct commit **rev,int no_checkout) +static int check_merge_bases (int rev_nr,struct commit **rev,int no_checkout) { +int res =0 ;struct commit_list *result; result =get_merge_bases_many (rev[0 ], rev_nr -1 , rev +1 );
@@ -822,11 +825,16 @@ static void check_merge_bases(int rev_nr, struct commit **rev, int no_checkout)handle_skipped_merge_base (mb); }else {printf (_ ("Bisecting: a merge base must be tested\n" )); -exit (-bisect_checkout (mb, no_checkout)); + res =bisect_checkout (mb, no_checkout); +if (!res) +/* indicate early success */ + res =-11 ; +break ; } }free_commit_list (result); +return res; }static int check_ancestors (int rev_nr,struct commit **rev,const char *prefix)
@@ -857,7 +865,7 @@ static void check_good_are_ancestors_of_bad(const char *prefix, int no_checkout) {char *filename =git_pathdup ("BISECT_ANCESTORS_OK" );struct stat st; -int fd, rev_nr; +int fd, rev_nr, res =0 ;struct commit **rev;if (!current_bad_oid)
@@ -874,8 +882,10 @@ static void check_good_are_ancestors_of_bad(const char *prefix, int no_checkout)/* Check if all good revs are ancestor of the bad rev. */ rev =get_bad_and_good_commits (&rev_nr);if (check_ancestors (rev_nr, rev, prefix)) -check_merge_bases (rev_nr, rev, no_checkout); + res =check_merge_bases (rev_nr, rev, no_checkout);free (rev); +if (res) +exit (res ==-11 ?0 : -res);/* Create file BISECT_ANCESTORS_OK. */ fd =open (filename,O_CREAT |O_TRUNC |O_WRONLY ,0600 );
Signature · 1 line
gitgitgadget
PATCH 7/26 bisect.c: libify `check_good_are_ancestors_of_bad` and its dependents
In reply to Tanushree Tumane via GitGitGadgetFrom: Pranit Bauva <[email protected]>
Since we want to get rid of git-bisect.sh it would be necessary to convert those exit() calls to return statements so that errors can be reported.
Emulate try catch in C by converting exit(<positive-value>) to return <negetive-value>. Follow POSIX conventions to return <negative-value> to indicate error.
Turn exit() to return calls in check_good_are_ancestors_of_bad().
In check_merge_bases() there is an early success special case, so we have introduced special error code -11 which indicates early success. This -11 is converted back to 0 in cmd_bisect_helper().
Mentored by: Johannes Schindelin <[email protected]>
--- bisect.c | 41 +++++++++++++++++++++++++--------------- builtin/bisect--helper.c | 12 ++++++++++-- 2 files changed, 36 insertions(+), 17 deletions(-)
bisect.c +26 -15
@@ -859,17 +859,24 @@ static int check_ancestors(int rev_nr, struct commit **rev, const char *prefix)* * If that's not the case, we need to check the merge bases. * If a merge base must be tested by the user, its source code will be -* checked out to be tested by the user and we will exit. +* checked out to be tested by the user and we will return. */ -static void check_good_are_ancestors_of_bad (const char *prefix,int no_checkout) +static int check_good_are_ancestors_of_bad (const char *prefix,int no_checkout) {char *filename =git_pathdup ("BISECT_ANCESTORS_OK" );struct stat st;int fd, rev_nr, res =0 ;struct commit **rev; -if (!current_bad_oid) -die (_ ("a %s revision is needed" ), term_bad); +/* +* We don't want to clean the bisection state +* as we need to get back to where we started +* by using `git bisect reset`. +*/ +if (!current_bad_oid) { + res =error (_ ("a %s revision is needed" ), term_bad); + goto done; + }/* Check if file BISECT_ANCESTORS_OK exists. */ if (!stat (filename, &st) &&S_ISREG (st.st_mode))
@@ -884,18 +891,20 @@ static void check_good_are_ancestors_of_bad(const char *prefix, int no_checkout)if (check_ancestors (rev_nr, rev, prefix)) res =check_merge_bases (rev_nr, rev, no_checkout);free (rev); -if (res) -exit (res ==-11 ?0 : -res); - -/* Create file BISECT_ANCESTORS_OK. */ - fd =open (filename,O_CREAT |O_TRUNC |O_WRONLY ,0600 ); -if (fd <0 ) -warning_errno (_ ("could not create file '%s'" ), - filename); -else -close (fd); + +if (!res) + { +/* Create file BISECT_ANCESTORS_OK. */ + fd =open (filename,O_CREAT |O_TRUNC |O_WRONLY ,0600 ); +if (fd <0 ) +warning_errno (_ ("could not create file '%s'" ), + filename); +else +close (fd); + } done:free (filename); +return res; }/*
@@ -973,7 +982,9 @@ int bisect_next_all(const char *prefix, int no_checkout)if (read_bisect_refs ())die (_ ("reading bisect refs failed" )); -check_good_are_ancestors_of_bad (prefix, no_checkout); + res =check_good_are_ancestors_of_bad (prefix, no_checkout); +if (res) +return res;bisect_rev_setup (&revs, prefix,"%s" ,"^%s" ,1 ); revs.limited =1 ;
builtin/bisect--helper.c +10 -2
@@ -663,7 +663,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)switch (cmdmode) {case NEXT_ALL : -return bisect_next_all (prefix, no_checkout); + res =bisect_next_all (prefix, no_checkout); +break ;case WRITE_TERMS :if (argc !=2 )return error (_ ("--write-terms requires two arguments" ));
@@ -710,5 +711,12 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)return error ("BUG: unknown subcommand '%d'" , cmdmode); }free_terms (&terms); -return !!res; +/* +* Handle early success +* From check_merge_bases > check_good_are_ancestors_of_bad > bisect_next_all +*/ +if (res ==-11 ) + res =0 ; + +return res <0 ? -res : res; }
Signature · 1 line
gitgitgadget
PATCH 8/26 bisect.c: libify `handle_bad_merge_base` and its dependants
In reply to Tanushree Tumane via GitGitGadgetFrom: Pranit Bauva <[email protected]>
Since we want to get rid of git-bisect.sh it would be necessary to convert those exit() calls to return statements so that errors can be reported.
Emulate try catch in C by converting exit(<positive-value>) to return <negetive-value>. Follow POSIX conventions to return <negative-value> to indicate error.
Turn exit() to return calls in handle_bad_merge_base().
Handle/libify this return in dependant methods - check_merge_bases().
--- bisect.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
bisect.c +5 -4
@@ -751,7 +751,7 @@ static struct commit **get_bad_and_good_commits(int *rev_nr)return rev; } -static void handle_bad_merge_base (void ) +static int handle_bad_merge_base (void ) {if (is_expected_rev (current_bad_oid)) {char *bad_hex =oid_to_hex (current_bad_oid);
@@ -772,14 +772,14 @@ static void handle_bad_merge_base(void) "between %s and [%s].\n"), bad_hex, term_bad, term_good, bad_hex, good_hex); } -exit (3 ); +return -3 ; }fprintf (stderr,_ ("Some %s revs are not ancestors of the %s rev.\n" "git bisect cannot work properly in this case.\n" "Maybe you mistook %s and %s revs?\n" ), term_good, term_bad, term_good, term_bad); -exit (1 ); +return -1 ; }static void handle_skipped_merge_base (const struct object_id *mb)
@@ -818,7 +818,8 @@ static int check_merge_bases(int rev_nr, struct commit **rev, int no_checkout)for (; result; result = result->next) {const struct object_id *mb = &result->item->object.oid;if (oideq (mb, current_bad_oid)) { -handle_bad_merge_base (); + res =handle_bad_merge_base (); +break ; }else if (0 <=oid_array_lookup (&good_revs, mb)) {continue ; }else if (0 <=oid_array_lookup (&skipped_revs, mb)) {
Signature · 1 line
gitgitgadget
PATCH 9/26 bisect.c: libify `bisect_next_all` and its dependants
In reply to Tanushree Tumane via GitGitGadgetFrom: Pranit Bauva <[email protected]>
Since we want to get rid of git-bisect.sh it would be necessary to convert those exit() calls to return statements so that errors can be reported.
Emulate try catch in C by converting exit(<positive-value>) to return <negetive-value>. Follow POSIX conventions to return <negative-value> to indicate error.
Turn exit() to return calls in bisect_next_all().
--- bisect.c | 41 ++++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-)
bisect.c +30 -11
@@ -964,10 +964,12 @@ void read_bisect_terms(const char **read_bad, const char **read_good) }/* -* We use the convention that exiting with an exit code 10 means that -* the bisection process finished successfully. -* In this case the calling shell script should exit 0. -* +* We use the convention that return -10 means the bisection process +* finished successfully. +* In this case the calling function or command should not turn a -10 +* return code into an error or a non zero exit code. +* This returned -10 is converted to 10 at the end of cmd_bisect__helper(). +* * If no_checkout is non-zero, the bisection process does not * checkout the trial commit but instead simply updates BISECT_HEAD. */
@@ -997,23 +999,35 @@ int bisect_next_all(const char *prefix, int no_checkout)if (!revs.commits) {/* -* We should exit here only if the "bad" +* We should return error here only if the "bad" * commit is also a "skip" commit. */ res =error_if_skipped_commits (tried,NULL );if (res) -exit (-res); +return res;printf (_ ("%s was both %s and %s\n" ),oid_to_hex (current_bad_oid), term_good, term_bad); -exit (1 ); + +/* +* We don't want to clean the bisection state +* as we need to get back to where we started +* by using `git bisect reset`. +*/ +return -1 ; }if (!all) {fprintf (stderr,_ ("No testable commit found.\n" "Maybe you started with bad path parameters?\n" )); -exit (4 ); + +/* +* We don't want to clean the bisection state +* as we need to get back to where we started +* by using `git bisect reset`. +*/ +return -4 ; } bisect_rev = &revs.commits->item->object.oid;
@@ -1021,12 +1035,17 @@ int bisect_next_all(const char *prefix, int no_checkout)if (oideq (bisect_rev, current_bad_oid)) { res =error_if_skipped_commits (tried, current_bad_oid);if (res) -exit (-res); +return res;printf ("%s is the first %s commit\n" ,oid_to_hex (bisect_rev), term_bad);show_diff_tree (prefix, revs.commits->item); -/* This means the bisection process succeeded. */ -exit (10 ); +/* +* This means the bisection process succeeded. +* Using -10 so that the call chain can simply check +* for negative return values for early returns up +* until the cmd_bisect__helper() caller. +*/ +return -10 ; } nr = all - reaches -1 ;
Signature · 1 line
gitgitgadget
PATCH 10/26 bisect--helper: `bisect_next` and `bisect_auto_next` shell function in C
In reply to Tanushree Tumane via GitGitGadgetFrom: Pranit Bauva <[email protected]>
Reimplement the bisect_next() and the bisect_auto_next() shell function in C and add the subcommands to git bisect--helper to call it from git-bisect.sh .
Using --bisect-next and --bisect-auto-start subcommands is a temporary measure to port shell function to C so as to use the existing test suite. As more functions are ported, this subcommand will be retired and will be called by some other methods.
--- bisect.c | 6 ++ builtin/bisect--helper.c | 156 ++++++++++++++++++++++++++++++++++++++- git-bisect.sh | 47 ++---------- 3 files changed, 166 insertions(+), 43 deletions(-)
bisect.c +6 -0
@@ -633,6 +633,12 @@ static void bisect_rev_setup(struct rev_info *revs, const char *prefix,struct argv_array rev_argv =ARGV_ARRAY_INIT ;int i; +/* +* Since the code is slowly being converted to C, there might be +* instances where the revisions were initialized before. Thus +* we first need to reset it. +*/ +reset_revision_walk ();repo_init_revisions (the_repository, revs, prefix); revs->abbrev =0 ; revs->commit_format =CMIT_FMT_UNSPECIFIED ;
builtin/bisect--helper.c +155 -1
192 lines not on this page · raw message
git-bisect.sh +5 -42
71 lines not on this page · raw message
Signature · 1 line
gitgitgadget
PATCH 11/26 bisect--helper: Finish `bisect_start()` conversion
In reply to Tanushree Tumane via GitGitGadgetFrom: Pranit Bauva <[email protected]>
With the conversion of bisect_auto_next() in previous commit, bisect_start() has been successfully ported to C.
Add the subcommands to git bisect--helper and call it from git-bisect.sh.
Remove bisect_start() shell method and call git bisect--helper --bisect-start subcommand from git-bisect.sh.
Removing the part about signals as we are not doing anything anymore to trap signals. While at it, "trap" is changed to "handle". As "trap" is a reference to the shell "trap" builtin, which isn't used anymore.
--- builtin/bisect--helper.c | 29 +++++++++++++++++++++++++++-- git-bisect.sh | 29 +++-------------------------- 2 files changed, 30 insertions(+), 28 deletions(-)
builtin/bisect--helper.c +27 -2
@@ -697,9 +697,9 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout,return -1 ;/* -* In case of mistaken revs or checkout error, or signals received, +* In case of mistaken revs or checkout error, * "bisect_auto_next" below may exit or misbehave. -* We have to trap this to be able to clean up using +* We have to handle this to be able to clean up using * "bisect_clean_state". */
@@ -743,6 +743,31 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout,string_list_clear (&states,0 );strbuf_release (&start_head);strbuf_release (&bisect_names); +if (res) +return res; + + res =bisect_auto_next (terms,NULL ); +/* +* In case of mistaken revs or checkout error, or signals received, +* "bisect_auto_next" below may exit or misbehave. +* We have to trap this to be able to clean up using +* "bisect_clean_state". +* return code -11 is special code that indicates special success. +* -> bisect_start() +* . res = bisect_auto_next() +* -> bisect_auto_next() +* . return bisect_next() +* -> bisect_next() +* . res = bisect_next_all() +* -> bisect_next_all() +* . res = check_good_are_ancestors_of_bad() +* -> check_good_are_ancestors_of_bad() +* . res = check_merge_bases() +* -> check_merge_bases() +* . res = -11 +*/ +if (res && res !=-11 ) +bisect_clean_state ();return res; }
git-bisect.sh +3 -26
@@ -63,35 +63,13 @@ bisect_autostart() { [Nn]*) exit ;; esac - bisect_start + git bisect--helper --bisect-start else exit 1 fi } } -bisect_start() { - git bisect--helper --bisect-start $@ || exit - - # - # Change state. - # In case of mistaken revs or checkout error, or signals received, - # "bisect_auto_next" below may exit or misbehave. - # We have to trap this to be able to clean up using - # "bisect_clean_state". - # - trap 'git bisect--helper --bisect-clean-state' 0 - trap 'exit 255' 1 2 3 15 - - # - # Check if we can proceed to the next bisect state. - # - get_terms - git bisect--helper --bisect-auto-next || exit - - trap '-' 0 -} - bisect_skip() { all='' for arg in "$@"
@@ -184,8 +162,7 @@ bisect_replay () { get_terms case "$command" in start) - cmd="bisect_start $rev" - eval "$cmd" ;; + eval "git bisect--helper --bisect-start $rev" ;; "$TERM_GOOD"|"$TERM_BAD"|skip) git bisect--helper --bisect-write "$command" "$rev" "$TERM_GOOD" "$TERM_BAD" || exit;; terms)
@@ -284,7 +261,7 @@ case "$#" in help) git bisect -h ;; start) - bisect_start "$@" ;; + git bisect--helper --bisect-start "$@" ;; bad|good|new|old|"$TERM_BAD"|"$TERM_GOOD") bisect_state "$cmd" "$@" ;; skip)
Signature · 1 line
gitgitgadget
PATCH 12/26 bisect--helper: dequote arguments in `bisect-start`
In reply to Tanushree Tumane via GitGitGadgetFrom: Pranit Bauva <[email protected]>
As more and more calls are happening to the subcommands in git bisect--helper, more specifically when bisect_start $rev is converted to git bisect--helper --bisect-start $rev it is necessary to dequote the arguments because of shell to C conversion.
--- builtin/bisect--helper.c | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-)
builtin/bisect--helper.c +29 -10
@@ -557,6 +557,11 @@ static int bisect_auto_next(struct bisect_terms *terms, const char *prefix)return 0 ; } +static inline char *dequote_arg (const char *arg) +{ +return arg[0 ] !='\'' ?xstrdup (arg) :sq_dequote (xstrdup (arg)); +} +static int bisect_start (struct bisect_terms *terms,int no_checkout,const char **argv,int argc) {
@@ -577,15 +582,22 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout,* Check for one bad and then some good revisions */ for (i =0 ; i < argc; i++) { -if (!strcmp (argv[i],"--" )) { +char *arg =dequote_arg (argv[i]); + +if (!strcmp (arg,"--" )) { has_double_dash =1 ; +free (arg);break ; } +free (arg); }for (i =0 ; i < argc; i++) { -const char *arg = argv[i]; -if (!strcmp (argv[i],"--" )) { +char *dequoted =dequote_arg (argv[i]); +const char *arg = dequoted; + +if (!strcmp (arg,"--" )) { +free (dequoted);break ; }else if (!strcmp (arg,"--no-checkout" )) { no_checkout =1 ;
@@ -593,7 +605,7 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout, !strcmp(arg, "--term-old")) { must_write_terms =1 ;free ((void *) terms->term_good); - terms->term_good =xstrdup (argv[++i]); + terms->term_good =dequote_arg (argv[++i]); } else if (skip_prefix(arg, "--term-good=", &arg) || skip_prefix(arg, "--term-old=", &arg)) { must_write_terms =1 ;
@@ -603,24 +615,31 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout, !strcmp(arg, "--term-new")) { must_write_terms =1 ;free ((void *) terms->term_bad); - terms->term_bad =xstrdup (argv[++i]); + terms->term_bad =dequote_arg (argv[++i]); } else if (skip_prefix(arg, "--term-bad=", &arg) || skip_prefix(arg, "--term-new=", &arg)) { must_write_terms =1 ;free ((void *) terms->term_bad); terms->term_bad =xstrdup (arg); } else if (starts_with(arg, "--") && - !one_of(arg, "--term-good", "--term-bad", NULL)) { -return error (_ ("unrecognized option: '%s'" ), arg); + !one_of(arg, "--term-good", "--term-bad", NULL)) { +error (_ ("unrecognized option: '%s'" ), arg); +free (dequoted); +return -1 ; } else {char *commit_id =xstrfmt ("%s^{commit}" , arg); -if (get_oid (commit_id, &oid) && has_double_dash) -die (_ ("'%s' does not appear to be a valid " -"revision" ), arg); +if (get_oid (commit_id, &oid) && has_double_dash) { +error (_ ("'%s' does not appear to be a valid " +"revision" ), arg); +free (commit_id); +free (dequoted); +return -1 ; + }string_list_append (&revs,oid_to_hex (&oid));free (commit_id); } +free (dequoted); } pathspec_pos = i;
Signature · 1 line
gitgitgadget
PATCH 13/26 bisect--helper: retire `--bisect-clean-state` subcommand
In reply to Tanushree Tumane via GitGitGadgetFrom: Pranit Bauva <[email protected]>
The bisect-clean-state subcommand is no longer used in the shell script while the C code uses bisect_clean_state() thus remove the subcommand.
--- builtin/bisect--helper.c | 8 -------- 1 file changed, 8 deletions(-)
builtin/bisect--helper.c +0 -8
@@ -22,7 +22,6 @@ static GIT_PATH_FUNC(git_path_bisect_names, "BISECT_NAMES")static const char *const git_bisect_helper_usage[] = {N_ ("git bisect--helper --next-all [--no-checkout]" ),N_ ("git bisect--helper --write-terms <bad_term> <good_term>" ), -N_ ("git bisect--helper --bisect-clean-state" ),N_ ("git bisect--helper --bisect-reset [<commit>]" ),N_ ("git bisect--helper --bisect-write [--no-log] <state> <revision> <good_term> <bad_term>" ),N_ ("git bisect--helper --bisect-check-and-set-terms <command> <good_term> <bad_term>" ),
@@ -795,7 +794,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)enum {NEXT_ALL =1 ,WRITE_TERMS , -BISECT_CLEAN_STATE ,CHECK_EXPECTED_REVS ,BISECT_RESET ,BISECT_WRITE ,
@@ -812,8 +810,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) N_("perform 'git bisect next'"), NEXT_ALL),OPT_CMDMODE (0 ,"write-terms" , &cmdmode,N_ ("write the terms to .git/BISECT_TERMS" ),WRITE_TERMS ), -OPT_CMDMODE (0 ,"bisect-clean-state" , &cmdmode, -N_ ("cleanup the bisection state" ),BISECT_CLEAN_STATE ),OPT_CMDMODE (0 ,"check-expected-revs" , &cmdmode,N_ ("check for expected revs" ),CHECK_EXPECTED_REVS ), OPT_CMDMODE(0, "bisect-reset", &cmdmode,
@@ -855,10 +851,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)if (argc !=2 )return error (_ ("--write-terms requires two arguments" ));return write_terms (argv[0 ], argv[1 ]); -case BISECT_CLEAN_STATE : -if (argc !=0 ) -return error (_ ("--bisect-clean-state requires no arguments" )); -return bisect_clean_state ();case CHECK_EXPECTED_REVS :check_expected_revs (argv, argc);return 0 ;
Signature · 1 line
gitgitgadget
PATCH 14/26 bisect--helper: retire `--next-all` subcommand
In reply to Tanushree Tumane via GitGitGadgetFrom: Pranit Bauva <[email protected]>
The --next-all subcommand is no longer used in the shell script and the function bisect_next_all() is called from the C implementation of bisect_next().
--- builtin/bisect--helper.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-)
builtin/bisect--helper.c +1 -8
@@ -20,7 +20,6 @@ static GIT_PATH_FUNC(git_path_head_name, "head-name") static GIT_PATH_FUNC(git_path_bisect_names, "BISECT_NAMES") static const char * const git_bisect_helper_usage[] = { -N_ ("git bisect--helper --next-all [--no-checkout]" ),N_ ("git bisect--helper --write-terms <bad_term> <good_term>" ),N_ ("git bisect--helper --bisect-reset [<commit>]" ),N_ ("git bisect--helper --bisect-write [--no-log] <state> <revision> <good_term> <bad_term>" ),
@@ -792,8 +791,7 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout,int cmd_bisect__helper (int argc,const char **argv,const char *prefix) {enum { -NEXT_ALL =1 , -WRITE_TERMS , +WRITE_TERMS =1 ,CHECK_EXPECTED_REVS ,BISECT_RESET ,BISECT_WRITE ,
@@ -806,8 +804,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) } cmdmode =0 ;int no_checkout =0 , res =0 , nolog =0 ;struct option options[] = { -OPT_CMDMODE (0 ,"next-all" , &cmdmode, -N_ ("perform 'git bisect next'" ),NEXT_ALL ),OPT_CMDMODE (0 ,"write-terms" , &cmdmode,N_ ("write the terms to .git/BISECT_TERMS" ),WRITE_TERMS ), OPT_CMDMODE(0, "check-expected-revs", &cmdmode,
@@ -844,9 +840,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)usage_with_options (git_bisect_helper_usage, options);switch (cmdmode) { -case NEXT_ALL : - res =bisect_next_all (prefix, no_checkout); -break ;case WRITE_TERMS :if (argc !=2 )return error (_ ("--write-terms requires two arguments" ));
Signature · 1 line
gitgitgadget
PATCH 15/26 bisect--helper: `bisect_autostart` shell function in C
In reply to Tanushree Tumane via GitGitGadgetFrom: Pranit Bauva <[email protected]>
Reimplement the bisect_autostart() shell function in C and add the C implementation from bisect_next() which was previously left uncovered. Also add a subcommand --bisect-autostart to git bisect--helper be called from bisect_state() from git-bisect.sh .
Using --bisect-autostart subcommand is a temporary measure to port shell function to C so as to use the existing test suite. As more functions are ported, this subcommand will be retired and will be called by bisect_state().
--- builtin/bisect--helper.c | 39 +++++++++++++++++++++++++++++++++++++++ git-bisect.sh | 23 +---------------------- 2 files changed, 40 insertions(+), 22 deletions(-)
builtin/bisect--helper.c +39 -0
@@ -30,6 +30,7 @@ static const char * const git_bisect_helper_usage[] = { "[--no-checkout] [<bad> [<good>...]] [--] [<paths>...]"),N_ ("git bisect--helper --bisect-next" ),N_ ("git bisect--helper --bisect-auto-next" ), +N_ ("git bisect--helper --bisect-autostart" ), NULL };
@@ -56,6 +57,8 @@ static void set_terms(struct bisect_terms *terms, const char *bad,static const char *vocab_bad ="bad|new" ;static const char *vocab_good ="good|old" ; +static int bisect_autostart (struct bisect_terms *terms); +/* * Check whether the string `term` belongs to the set of strings * included in the variable arguments.
@@ -530,6 +533,7 @@ static int bisect_next(struct bisect_terms *terms, const char *prefix) {int res, no_checkout; +bisect_autostart (terms);if (bisect_next_check (terms, terms->term_good))return -1 ;
@@ -788,6 +792,32 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout,return res; } +static int bisect_autostart (struct bisect_terms *terms) +{ +if (is_empty_or_missing_file (git_path_bisect_start ())) { +const char *yesno; +const char *argv[] = {NULL }; +fprintf (stderr,_ ("You need to start by \"git bisect " +"start\"\n" )); + +if (!isatty (STDIN_FILENO )) +return 1 ; + +/* +* TRANSLATORS: Make sure to include [Y] and [n] in your +* translation. The program will only accept English input +* at this point. +*/ + yesno =git_prompt (_ ("Do you want me to do it for you " +"[Y/n]? " ),PROMPT_ECHO ); +if (starts_with (yesno,_ ("n" )) ||starts_with (yesno,_ ("N" ))) +return 1 ; + +return bisect_start (terms,0 , argv,0 ); + } +return 0 ; +} +int cmd_bisect__helper (int argc,const char **argv,const char *prefix) {enum {
@@ -801,6 +831,7 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)BISECT_START ,BISECT_NEXT ,BISECT_AUTO_NEXT , +BISECT_AUTOSTART , } cmdmode = 0;int no_checkout =0 , res =0 , nolog =0 ; struct option options[] = {
@@ -824,6 +855,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) N_("find the next bisection commit"), BISECT_NEXT),OPT_CMDMODE (0 ,"bisect-auto-next" , &cmdmode,N_ ("verify the next bisection state then checkout the next bisection commit" ),BISECT_AUTO_NEXT ), +OPT_CMDMODE (0 ,"bisect-autostart" , &cmdmode, +N_ ("start the bisection if BISECT_START is empty or missing" ),BISECT_AUTOSTART ),OPT_BOOL (0 ,"no-checkout" , &no_checkout,N_ ("update BISECT_HEAD instead of checking out the current commit" )), OPT_BOOL(0, "no-log", &nolog,
@@ -890,6 +923,12 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)get_terms (&terms); res =bisect_auto_next (&terms, prefix);break ; +case BISECT_AUTOSTART : +if (argc) +return error (_ ("--bisect-autostart requires 0 arguments" )); +set_terms (&terms,"bad" ,"good" ); + res =bisect_autostart (&terms); +break ;default :return error ("BUG: unknown subcommand '%d'" , cmdmode); }
git-bisect.sh +1 -22
@@ -49,27 +49,6 @@ bisect_head() fi } -bisect_autostart() { - test -s "$GIT_DIR/BISECT_START" || { - gettextln "You need to start by \"git bisect start\"" >&2 - if test -t 0 - then - # TRANSLATORS: Make sure to include [Y] and [n] in your - # translation. The program will only accept English input - # at this point. - gettext "Do you want me to do it for you [Y/n]? " >&2 - read yesno - case "$yesno" in - [Nn]*) - exit ;; - esac - git bisect--helper --bisect-start - else - exit 1 - fi - } -} - bisect_skip() { all='' for arg in "$@"
@@ -86,7 +65,7 @@ bisect_skip() { } bisect_state() { - bisect_autostart + git bisect--helper --bisect-autostart state=$1 git bisect--helper --check-and-set-terms $state $TERM_GOOD $TERM_BAD || exit get_terms
Signature · 1 line
gitgitgadget
PATCH 16/26 bisect--helper: `bisect_state` & `bisect_head` shell function in C
In reply to Tanushree Tumane via GitGitGadgetFrom: Pranit Bauva <[email protected]>
Reimplement the bisect_state() shell function in C and also add a subcommand --bisect-state to git-bisect--helper to call it from git-bisect.sh .
Using --bisect-state subcommand is a temporary measure to port shell function to C so as to use the existing test suite. As more functions are ported, this subcommand will be retired and will be called by some other methods.
bisect_head() is called from bisect_state(), thus it is not required to introduce another subcommand.
--- builtin/bisect--helper.c | 80 ++++++++++++++++++++++++++++++++++++++++ git-bisect.sh | 55 ++------------------------- 2 files changed, 84 insertions(+), 51 deletions(-)
builtin/bisect--helper.c +80 -0
@@ -31,6 +31,8 @@ static const char * const git_bisect_helper_usage[] = {N_ ("git bisect--helper --bisect-next" ),N_ ("git bisect--helper --bisect-auto-next" ),N_ ("git bisect--helper --bisect-autostart" ), +N_ ("git bisect--helper --bisect-state (bad|new) [<rev>]" ), +N_ ("git bisect--helper --bisect-state (good|old) [<rev>...]" ), NULL };
@@ -818,6 +820,74 @@ static int bisect_autostart(struct bisect_terms *terms)return 0 ; } +static char *bisect_head (void ) +{ +if (is_empty_or_missing_file (git_path_bisect_head ())) +return "HEAD" ; +else +return "BISECT_HEAD" ; +} + +static int bisect_state (struct bisect_terms *terms,const char **argv, +int argc) +{ +const char *state = argv[0 ]; + +if (check_and_set_terms (terms, state)) +return -1 ; + +if (!argc) +return error (_ ("Please call `--bisect-state` with at least one argument" )); + +if (argc ==1 &&one_of (state, terms->term_good, + terms->term_bad,"skip" ,NULL )) { +const char *bisected_head =xstrdup (bisect_head ()); +const char *hex[1 ]; +struct object_id oid; + +if (get_oid (bisected_head, &oid)) +return error (_ ("Bad rev input: %s" ), bisected_head); +if (bisect_write (state,oid_to_hex (&oid), terms,0 )) +return -1 ; + + *hex =xstrdup (oid_to_hex (&oid)); +check_expected_revs (hex,1 ); +return bisect_auto_next (terms,NULL ); + } + +if ((argc ==2 && !strcmp (state, terms->term_bad)) || +one_of (state, terms->term_good,"skip" ,NULL )) { +int i; +struct string_list hex =STRING_LIST_INIT_DUP ; + +for (i =1 ; i < argc; i++) { +struct object_id oid; + +if (get_oid (argv[i], &oid)) { +string_list_clear (&hex,0 ); +return error (_ ("Bad rev input: %s" ), argv[i]); + } +string_list_append (&hex,oid_to_hex (&oid)); + } +for (i =0 ; i < hex.nr; i++) { +const char **hex_string = (const char **) &hex.items[i].string; +if (bisect_write (state, *hex_string, terms,0 )) { +string_list_clear (&hex,0 ); +return -1 ; + } +check_expected_revs (hex_string,1 ); + } +string_list_clear (&hex,0 ); +return bisect_auto_next (terms,NULL ); + } + +if (!strcmp (state, terms->term_bad)) +return error (_ ("'git bisect %s' can take only one argument." ), + terms->term_bad); + +return -1 ; +} +int cmd_bisect__helper (int argc,const char **argv,const char *prefix) {enum {
@@ -832,6 +902,7 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)BISECT_NEXT ,BISECT_AUTO_NEXT ,BISECT_AUTOSTART , + BISECT_STATE } cmdmode =0 ;int no_checkout =0 , res =0 , nolog =0 ;struct option options[] = {
@@ -857,6 +928,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) N_("verify the next bisection state then checkout the next bisection commit"), BISECT_AUTO_NEXT),OPT_CMDMODE (0 ,"bisect-autostart" , &cmdmode,N_ ("start the bisection if BISECT_START is empty or missing" ),BISECT_AUTOSTART ), +OPT_CMDMODE (0 ,"bisect-state" , &cmdmode, +N_ ("mark the state of ref (or refs)" ),BISECT_STATE ),OPT_BOOL (0 ,"no-checkout" , &no_checkout,N_ ("update BISECT_HEAD instead of checking out the current commit" )), OPT_BOOL(0, "no-log", &nolog,
@@ -929,6 +1002,13 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)set_terms (&terms,"bad" ,"good" ); res =bisect_autostart (&terms);break ; +case BISECT_STATE : +if (argc ==0 ) +return error (_ ("--bisect-state requires at least one revision" )); +set_terms (&terms,"bad" ,"good" ); +get_terms (&terms); + res =bisect_state (&terms, argv, argc); +break ;default :return error ("BUG: unknown subcommand '%d'" , cmdmode); }
git-bisect.sh +4 -51
85 lines not on this page · raw message
Signature · 1 line
gitgitgadget
PATCH 17/26 bisect--helper: retire `--check-expected-revs` subcommand
In reply to Tanushree Tumane via GitGitGadgetFrom: Pranit Bauva <[email protected]>
The --check-expected-revs subcommand is no longer used in the shell script and the function check_expected_revs() is called from the C implementation of bisect_next().
--- builtin/bisect--helper.c | 6 ------ 1 file changed, 6 deletions(-)
builtin/bisect--helper.c +0 -6
@@ -892,7 +892,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) {enum {WRITE_TERMS =1 , -CHECK_EXPECTED_REVS ,BISECT_RESET ,BISECT_WRITE ,CHECK_AND_SET_TERMS ,
@@ -908,8 +907,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)struct option options[] = {OPT_CMDMODE (0 ,"write-terms" , &cmdmode,N_ ("write the terms to .git/BISECT_TERMS" ),WRITE_TERMS ), -OPT_CMDMODE (0 ,"check-expected-revs" , &cmdmode, -N_ ("check for expected revs" ),CHECK_EXPECTED_REVS ),OPT_CMDMODE (0 ,"bisect-reset" , &cmdmode,N_ ("reset the bisection state" ),BISECT_RESET ), OPT_CMDMODE(0, "bisect-write", &cmdmode,
@@ -950,9 +947,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)if (argc !=2 )return error (_ ("--write-terms requires two arguments" ));return write_terms (argv[0 ], argv[1 ]); -case CHECK_EXPECTED_REVS : -check_expected_revs (argv, argc); -return 0 ;case BISECT_RESET :if (argc >1 )return error (_ ("--bisect-reset requires either no argument or a commit" ));
Signature · 1 line
gitgitgadget
PATCH 18/26 bisect--helper: retire `--write-terms` subcommand
In reply to Tanushree Tumane via GitGitGadgetFrom: Pranit Bauva <[email protected]>
The --write-terms subcommand is no longer used in the shell script and the function write_terms() is called from the C implementation of set_terms() and bisect_start().
--- builtin/bisect--helper.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-)
builtin/bisect--helper.c +1 -9
@@ -20,7 +20,6 @@ static GIT_PATH_FUNC(git_path_head_name, "head-name") static GIT_PATH_FUNC(git_path_bisect_names, "BISECT_NAMES") static const char * const git_bisect_helper_usage[] = { -N_ ("git bisect--helper --write-terms <bad_term> <good_term>" ),N_ ("git bisect--helper --bisect-reset [<commit>]" ),N_ ("git bisect--helper --bisect-write [--no-log] <state> <revision> <good_term> <bad_term>" ),N_ ("git bisect--helper --bisect-check-and-set-terms <command> <good_term> <bad_term>" ),
@@ -891,8 +890,7 @@ static int bisect_state(struct bisect_terms *terms, const char **argv,int cmd_bisect__helper (int argc,const char **argv,const char *prefix) {enum { -WRITE_TERMS =1 , -BISECT_RESET , +BISECT_RESET =1 ,BISECT_WRITE ,CHECK_AND_SET_TERMS ,BISECT_NEXT_CHECK ,
@@ -905,8 +903,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) } cmdmode =0 ;int no_checkout =0 , res =0 , nolog =0 ;struct option options[] = { -OPT_CMDMODE (0 ,"write-terms" , &cmdmode, -N_ ("write the terms to .git/BISECT_TERMS" ),WRITE_TERMS ),OPT_CMDMODE (0 ,"bisect-reset" , &cmdmode,N_ ("reset the bisection state" ),BISECT_RESET ), OPT_CMDMODE(0, "bisect-write", &cmdmode,
@@ -943,10 +939,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)usage_with_options (git_bisect_helper_usage, options);switch (cmdmode) { -case WRITE_TERMS : -if (argc !=2 ) -return error (_ ("--write-terms requires two arguments" )); -return write_terms (argv[0 ], argv[1 ]);case BISECT_RESET :if (argc >1 )return error (_ ("--bisect-reset requires either no argument or a commit" ));
Signature · 1 line
gitgitgadget
PATCH 19/26 bisect--helper: `bisect_log` shell function in C
In reply to Tanushree Tumane via GitGitGadgetFrom: Pranit Bauva <[email protected]>
Reimplement the bisect_log() shell function in C and also add --bisect-log subcommand to git bisect--helper to call it from git-bisect.sh .
Using --bisect-log subcommand is a temporary measure to port shell function to C so as to use the existing test suite. As more functions are ported, this subcommand will be retired and will be called by some other method.
--- builtin/bisect--helper.c | 22 +++++++++++++++++++++- git-bisect.sh | 7 +------ 2 files changed, 22 insertions(+), 7 deletions(-)
builtin/bisect--helper.c +21 -1
@@ -887,6 +887,18 @@ static int bisect_state(struct bisect_terms *terms, const char **argv,return -1 ; } +static int bisect_log (void ) +{ +int fd, status; + fd =open (git_path_bisect_log (),O_RDONLY ); +if (fd <0 ) +return -1 ; + + status =copy_fd (fd,STDOUT_FILENO ); +close (fd); +return status ?-1 :0 ; +} +int cmd_bisect__helper (int argc,const char **argv,const char *prefix) {enum {
@@ -899,7 +911,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)BISECT_NEXT ,BISECT_AUTO_NEXT ,BISECT_AUTOSTART , - BISECT_STATE +BISECT_STATE , + BISECT_LOG } cmdmode =0 ;int no_checkout =0 , res =0 , nolog =0 ;struct option options[] = {
@@ -923,6 +936,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) N_("start the bisection if BISECT_START is empty or missing"), BISECT_AUTOSTART),OPT_CMDMODE (0 ,"bisect-state" , &cmdmode,N_ ("mark the state of ref (or refs)" ),BISECT_STATE ), +OPT_CMDMODE (0 ,"bisect-log" , &cmdmode, +N_ ("output the contents of BISECT_LOG" ),BISECT_LOG ),OPT_BOOL (0 ,"no-checkout" , &no_checkout,N_ ("update BISECT_HEAD instead of checking out the current commit" )), OPT_BOOL(0, "no-log", &nolog,
@@ -995,6 +1010,11 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)get_terms (&terms); res =bisect_state (&terms, argv, argc);break ; +case BISECT_LOG : +if (argc >1 ) +return error (_ ("--bisect-log requires 0 arguments" )); + res =bisect_log (); +break ;default :return error ("BUG: unknown subcommand '%d'" , cmdmode); }
git-bisect.sh +1 -6
@@ -167,11 +167,6 @@ exit code \$res from '\$command' is < 0 or >= 128" >&2 done } -bisect_log () { - test -s "$GIT_DIR/BISECT_LOG" || die "$(gettext "We are not bisecting.")" - cat "$GIT_DIR/BISECT_LOG" -} - get_terms () { if test -s "$GIT_DIR/BISECT_TERMS" then
@@ -209,7 +204,7 @@ case "$#" in replay) bisect_replay "$@" ;; log) - bisect_log ;; + git bisect--helper --bisect-log ;; run) bisect_run "$@" ;; terms)
Signature · 1 line
gitgitgadget
PATCH 20/26 bisect--helper: `bisect_replay` shell function in C
In reply to Tanushree Tumane via GitGitGadgetFrom: Pranit Bauva <[email protected]>
Reimplement the bisect_replay shell function in C and also add --bisect-replay subcommand to git bisect--helper to call it from git-bisect.sh
Using --bisect-replay subcommand is a temporary measure to port shell function to C so as to use the existing test suite. As more functions are ported, this subcommand will be retired and will be called by some other method.
--- builtin/bisect--helper.c | 123 ++++++++++++++++++++++++++++++++++++++- git-bisect.sh | 32 +--------- 2 files changed, 123 insertions(+), 32 deletions(-)
builtin/bisect--helper.c +122 -1
@@ -32,6 +32,7 @@ static const char * const git_bisect_helper_usage[] = {N_ ("git bisect--helper --bisect-autostart" ),N_ ("git bisect--helper --bisect-state (bad|new) [<rev>]" ),N_ ("git bisect--helper --bisect-state (good|old) [<rev>...]" ), +N_ ("git bisect--helper --bisect-replay <filename>" ), NULL };
@@ -899,6 +900,117 @@ static int bisect_log(void)return status ?-1 :0 ; } +static int get_next_word (const char *line,int pos,struct strbuf *word) +{ +int i, len =strlen (line), begin =0 ; +strbuf_reset (word); +for (i = pos; i < len; i++) { +if (line[i] ==' ' && begin) +return i +1 ; + +if (!begin) + begin =1 ; +strbuf_addch (word, line[i]); + } + +return i; +} + +static int bisect_replay (struct bisect_terms *terms,const char *filename) +{ +struct strbuf line =STRBUF_INIT ; +struct strbuf word =STRBUF_INIT ; +FILE *fp =NULL ; +int res =0 ; + +if (is_empty_or_missing_file (filename)) { +error (_ ("cannot read file '%s' for replaying" ), filename); + res =-1 ; + goto finish; + } + +if (bisect_reset (NULL )) { + res =-1 ; + goto finish; + } + + fp =fopen (filename,"r" ); +if (!fp) { + res =-1 ; + goto finish; + } + +while (strbuf_getline (&line, fp) !=EOF ) { +int pos =0 ; +while (pos < line.len) { + pos =get_next_word (line.buf, pos, &word); + +if (!strcmp (word.buf,"git" )) { +continue ; + }else if (!strcmp (word.buf,"git-bisect" )) { +continue ; + }else if (!strcmp (word.buf,"bisect" )) { +continue ; + }else if (starts_with (word.buf,"#" )) { +break ; + } + +get_terms (terms); +if (check_and_set_terms (terms, word.buf)) { + res =-1 ; + goto finish; + } + +if (!strcmp (word.buf,"start" )) { +struct argv_array argv =ARGV_ARRAY_INIT ; +sq_dequote_to_argv_array (line.buf+pos, &argv); +if (bisect_start (terms,0 , argv.argv, argv.argc)) { +argv_array_clear (&argv); + res =-1 ; + goto finish; + } +argv_array_clear (&argv); +break ; + } + +if (one_of (word.buf, terms->term_good, + terms->term_bad,"skip" ,NULL )) { +if (bisect_write (word.buf, line.buf+pos, terms,0 )) { + res =-1 ; + goto finish; + } +break ; + } + +if (!strcmp (word.buf,"terms" )) { +struct argv_array argv =ARGV_ARRAY_INIT ; +sq_dequote_to_argv_array (line.buf+pos, &argv); +if (bisect_terms (terms, argv.argc ==1 ? argv.argv[0 ] :NULL )) { +argv_array_clear (&argv); + res =-1 ; + goto finish; + } +argv_array_clear (&argv); +break ; + } + +error (_ ("Replay file contains rubbish (\"%s\")" ), + word.buf); + res =-1 ; + goto finish; + } + } +finish: +if (fp) +fclose (fp); +strbuf_release (&line); +strbuf_release (&word); +if (res) +return -1 ; + +return bisect_auto_next (terms,NULL ); +} +int cmd_bisect__helper (int argc,const char **argv,const char *prefix) {enum {
@@ -912,7 +1024,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)BISECT_AUTO_NEXT ,BISECT_AUTOSTART ,BISECT_STATE , - BISECT_LOG +BISECT_LOG , + BISECT_REPLAY } cmdmode =0 ;int no_checkout =0 , res =0 , nolog =0 ;struct option options[] = {
@@ -938,6 +1051,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) N_("mark the state of ref (or refs)"), BISECT_STATE),OPT_CMDMODE (0 ,"bisect-log" , &cmdmode,N_ ("output the contents of BISECT_LOG" ),BISECT_LOG ), +OPT_CMDMODE (0 ,"bisect-replay" , &cmdmode, +N_ ("replay the bisection process from the given file" ),BISECT_REPLAY ),OPT_BOOL (0 ,"no-checkout" , &no_checkout,N_ ("update BISECT_HEAD instead of checking out the current commit" )), OPT_BOOL(0, "no-log", &nolog,
@@ -1015,6 +1130,12 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)return error (_ ("--bisect-log requires 0 arguments" )); res =bisect_log ();break ; +case BISECT_REPLAY : +if (argc !=1 ) +return error (_ ("no logfile given" )); +set_terms (&terms,"bad" ,"good" ); + res =bisect_replay (&terms, argv[0 ]); +break ;default :return error ("BUG: unknown subcommand '%d'" , cmdmode); }
git-bisect.sh +1 -31
@@ -77,36 +77,6 @@ bisect_visualize() { eval '"$@"' --bisect -- $(cat "$GIT_DIR/BISECT_NAMES") } -bisect_replay () { - file="$1" - test "$#" -eq 1 || die "$(gettext "No logfile given")" - test -r "$file" || die "$(eval_gettext "cannot read \$file for replaying")" - git bisect--helper --bisect-reset || exit - while read git bisect command rev - do - test "$git $bisect" = "git bisect" || test "$git" = "git-bisect" || continue - if test "$git" = "git-bisect" - then - rev="$command" - command="$bisect" - fi - get_terms - git bisect--helper --check-and-set-terms "$command" "$TERM_GOOD" "$TERM_BAD" || exit - get_terms - case "$command" in - start) - eval "git bisect--helper --bisect-start $rev" ;; - "$TERM_GOOD"|"$TERM_BAD"|skip) - git bisect--helper --bisect-write "$command" "$rev" "$TERM_GOOD" "$TERM_BAD" || exit;; - terms) - git bisect--helper --bisect-terms $rev || exit;; - *) - die "$(gettext "?? what are you talking about?")" ;; - esac - done <"$file" - git bisect--helper --bisect-auto-next -} - bisect_run () { git bisect--helper --bisect-next-check $TERM_GOOD $TERM_BAD fail || exit
@@ -202,7 +172,7 @@ case "$#" in reset) git bisect--helper --bisect-reset "$@" ;; replay) - bisect_replay "$@" ;; + git bisect--helper --bisect-replay "$@" ;; log) git bisect--helper --bisect-log ;; run)
Signature · 1 line
gitgitgadget
PATCH 21/26 bisect--helper: retire `--bisect-write` subcommand
In reply to Tanushree Tumane via GitGitGadgetFrom: Pranit Bauva <[email protected]>
The --bisect-write subcommand is no longer used in the shell script and the function bisect_write() is called from the C implementation.
--- builtin/bisect--helper.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-)
builtin/bisect--helper.c +1 -10
@@ -21,7 +21,6 @@ static GIT_PATH_FUNC(git_path_bisect_names, "BISECT_NAMES")static const char *const git_bisect_helper_usage[] = {N_ ("git bisect--helper --bisect-reset [<commit>]" ), -N_ ("git bisect--helper --bisect-write [--no-log] <state> <revision> <good_term> <bad_term>" ),N_ ("git bisect--helper --bisect-check-and-set-terms <command> <good_term> <bad_term>" ),N_ ("git bisect--helper --bisect-next-check <good_term> <bad_term> [<term>]" ),N_ ("git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad | --term-new]" ),
@@ -1015,7 +1014,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) {enum {BISECT_RESET =1 , -BISECT_WRITE ,CHECK_AND_SET_TERMS ,BISECT_NEXT_CHECK ,BISECT_TERMS ,
@@ -1031,8 +1029,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)struct option options[] = {OPT_CMDMODE (0 ,"bisect-reset" , &cmdmode,N_ ("reset the bisection state" ),BISECT_RESET ), -OPT_CMDMODE (0 ,"bisect-write" , &cmdmode, -N_ ("write out the bisection state in BISECT_LOG" ),BISECT_WRITE ),OPT_CMDMODE (0 ,"check-and-set-terms" , &cmdmode,N_ ("check and set terms in a bisection state" ),CHECK_AND_SET_TERMS ), OPT_CMDMODE(0, "bisect-next-check", &cmdmode,
@@ -1072,12 +1068,7 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)case BISECT_RESET :if (argc >1 )return error (_ ("--bisect-reset requires either no argument or a commit" )); -return !!bisect_reset (argc ? argv[0 ] :NULL ); -case BISECT_WRITE : -if (argc !=4 && argc !=5 ) -return error (_ ("--bisect-write requires either 4 or 5 arguments" )); -set_terms (&terms, argv[3 ], argv[2 ]); - res =bisect_write (argv[0 ], argv[1 ], &terms, nolog); + res =bisect_reset (argc ? argv[0 ] :NULL );break ;case CHECK_AND_SET_TERMS :if (argc !=3 )
Signature · 1 line
gitgitgadget
PATCH 22/26 bisect--helper: retire `--bisect-autostart` subcommand
In reply to Tanushree Tumane via GitGitGadgetFrom: Pranit Bauva <[email protected]>
The --bisect-autostart subcommand is no longer used in the shell script and the function bisect_autostart() is called from the C implementation.
--- builtin/bisect--helper.c | 10 ---------- 1 file changed, 10 deletions(-)
builtin/bisect--helper.c +0 -10
@@ -28,7 +28,6 @@ static const char * const git_bisect_helper_usage[] = { "[--no-checkout] [<bad> [<good>...]] [--] [<paths>...]"),N_ ("git bisect--helper --bisect-next" ),N_ ("git bisect--helper --bisect-auto-next" ), -N_ ("git bisect--helper --bisect-autostart" ),N_ ("git bisect--helper --bisect-state (bad|new) [<rev>]" ),N_ ("git bisect--helper --bisect-state (good|old) [<rev>...]" ), N_("git bisect--helper --bisect-replay <filename>"),
@@ -1020,7 +1019,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)BISECT_START ,BISECT_NEXT ,BISECT_AUTO_NEXT , -BISECT_AUTOSTART ,BISECT_STATE ,BISECT_LOG ,BISECT_REPLAY
@@ -1041,8 +1039,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) N_("find the next bisection commit"), BISECT_NEXT),OPT_CMDMODE (0 ,"bisect-auto-next" , &cmdmode,N_ ("verify the next bisection state then checkout the next bisection commit" ),BISECT_AUTO_NEXT ), -OPT_CMDMODE (0 ,"bisect-autostart" , &cmdmode, -N_ ("start the bisection if BISECT_START is empty or missing" ),BISECT_AUTOSTART ),OPT_CMDMODE (0 ,"bisect-state" , &cmdmode,N_ ("mark the state of ref (or refs)" ),BISECT_STATE ), OPT_CMDMODE(0, "bisect-log", &cmdmode,
@@ -1103,12 +1099,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)get_terms (&terms); res =bisect_auto_next (&terms, prefix);break ; -case BISECT_AUTOSTART : -if (argc) -return error (_ ("--bisect-autostart requires 0 arguments" )); -set_terms (&terms,"bad" ,"good" ); - res =bisect_autostart (&terms); -break ;case BISECT_STATE :if (argc ==0 )return error (_ ("--bisect-state requires at least one revision" ));
Signature · 1 line
gitgitgadget
PATCH 23/26 bisect--helper: retire `--bisect-auto-next` subcommand
In reply to Tanushree Tumane via GitGitGadgetFrom: Pranit Bauva <[email protected]>
The --bisect-auto-next subcommand is no longer used in the shell script and the function bisect_auto_next() is called from the C implementation.
--- builtin/bisect--helper.c | 10 ---------- 1 file changed, 10 deletions(-)
builtin/bisect--helper.c +0 -10
@@ -27,7 +27,6 @@ static const char * const git_bisect_helper_usage[] = {N_ ("git bisect--helper --bisect-start [--term-{old,good}=<term> --term-{new,bad}=<term>]" "[--no-checkout] [<bad> [<good>...]] [--] [<paths>...]" ),N_ ("git bisect--helper --bisect-next" ), -N_ ("git bisect--helper --bisect-auto-next" ),N_ ("git bisect--helper --bisect-state (bad|new) [<rev>]" ),N_ ("git bisect--helper --bisect-state (good|old) [<rev>...]" ), N_("git bisect--helper --bisect-replay <filename>"),
@@ -1018,7 +1017,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)BISECT_TERMS ,BISECT_START ,BISECT_NEXT , -BISECT_AUTO_NEXT ,BISECT_STATE ,BISECT_LOG ,BISECT_REPLAY
@@ -1037,8 +1035,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) N_("start the bisect session"), BISECT_START),OPT_CMDMODE (0 ,"bisect-next" , &cmdmode,N_ ("find the next bisection commit" ),BISECT_NEXT ), -OPT_CMDMODE (0 ,"bisect-auto-next" , &cmdmode, -N_ ("verify the next bisection state then checkout the next bisection commit" ),BISECT_AUTO_NEXT ),OPT_CMDMODE (0 ,"bisect-state" , &cmdmode,N_ ("mark the state of ref (or refs)" ),BISECT_STATE ), OPT_CMDMODE(0, "bisect-log", &cmdmode,
@@ -1093,12 +1089,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)get_terms (&terms); res =bisect_next (&terms, prefix);break ; -case BISECT_AUTO_NEXT : -if (argc) -return error (_ ("--bisect-auto-next requires 0 arguments" )); -get_terms (&terms); - res =bisect_auto_next (&terms, prefix); -break ;case BISECT_STATE :if (argc ==0 )return error (_ ("--bisect-state requires at least one revision" ));
Signature · 1 line
gitgitgadget
PATCH 24/26 bisect--helper: remove the dequote in bisect_start()
In reply to Tanushree Tumane via GitGitGadgetFrom: Pranit Bauva <[email protected]>
Dequoting the arguments was introduced in 25b48b5c to port the function bisect_next() but after the bisect_replay() porting, the dequoting is carried out itself when it passes the arguments to bisect_start() in a simpler way thus dequoting again isn't required. So remove the extra "dequoting" code introduced by the commit 25b48b5c.
--- builtin/bisect--helper.c | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-)
builtin/bisect--helper.c +5 -19
@@ -558,11 +558,6 @@ static int bisect_auto_next(struct bisect_terms *terms, const char *prefix)return 0 ; } -static inline char *dequote_arg (const char *arg) -{ -return arg[0 ] !='\'' ?xstrdup (arg) :sq_dequote (xstrdup (arg)); -} -static int bisect_start (struct bisect_terms *terms,int no_checkout,const char **argv,int argc) {
@@ -583,22 +578,16 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout,* Check for one bad and then some good revisions */ for (i =0 ; i < argc; i++) { -char *arg =dequote_arg (argv[i]); -if (!strcmp (arg,"--" )) { +if (!strcmp (argv[i],"--" )) { has_double_dash =1 ; -free (arg);break ; } -free (arg); }for (i =0 ; i < argc; i++) { -char *dequoted =dequote_arg (argv[i]); -const char *arg = dequoted; - -if (!strcmp (arg,"--" )) { -free (dequoted); +const char *arg = argv[i]; +if (!strcmp (argv[i],"--" )) {break ; }else if (!strcmp (arg,"--no-checkout" )) { no_checkout =1 ;
@@ -606,7 +595,7 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout, !strcmp(arg, "--term-old")) { must_write_terms =1 ;free ((void *) terms->term_good); - terms->term_good =dequote_arg (argv[++i]); + terms->term_good =xstrdup (argv[++i]); } else if (skip_prefix(arg, "--term-good=", &arg) || skip_prefix(arg, "--term-old=", &arg)) { must_write_terms =1 ;
@@ -616,7 +605,7 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout, !strcmp(arg, "--term-new")) { must_write_terms =1 ;free ((void *) terms->term_bad); - terms->term_bad =dequote_arg (argv[++i]); + terms->term_bad =xstrdup (argv[++i]); } else if (skip_prefix(arg, "--term-bad=", &arg) || skip_prefix(arg, "--term-new=", &arg)) { must_write_terms =1 ;
@@ -625,7 +614,6 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout, }else if (starts_with (arg,"--" ) && !one_of (arg,"--term-good" ,"--term-bad" ,NULL )) {error (_ ("unrecognized option: '%s'" ), arg); -free (dequoted);return -1 ; }else {char *commit_id =xstrfmt ("%s^{commit}" , arg);
@@ -633,14 +621,12 @@ static int bisect_start(struct bisect_terms *terms, int no_checkout,error (_ ("'%s' does not appear to be a valid " "revision" ), arg);free (commit_id); -free (dequoted);return -1 ; }string_list_append (&revs,oid_to_hex (&oid));free (commit_id); } -free (dequoted); } pathspec_pos = i;
Signature · 1 line
gitgitgadget
PATCH 25/26 bisect--helper: `bisect_skip` shell function in C
In reply to Tanushree Tumane via GitGitGadgetFrom: Pranit Bauva <[email protected]>
Reimplement the bisect_skip() shell function in C and also add bisect-skip subcommand to git bisect--helper to call it from git-bisect.sh
Using --bisect-skip subcommand is a temporary measure to port shell function to C so as to use the existing test suite. As more functions are ported, this subcommand will be retired and will be called by some other method.
--- builtin/bisect--helper.c | 45 +++++++++++++++++++++++++++++++++++++++- git-bisect.sh | 17 +-------------- 2 files changed, 45 insertions(+), 17 deletions(-)
builtin/bisect--helper.c +44 -1
@@ -30,6 +30,7 @@ static const char * const git_bisect_helper_usage[] = {N_ ("git bisect--helper --bisect-state (bad|new) [<rev>]" ),N_ ("git bisect--helper --bisect-state (good|old) [<rev>...]" ),N_ ("git bisect--helper --bisect-replay <filename>" ), +N_ ("git bisect--helper --bisect-skip [(<rev>|<range>)...]" ), NULL };
@@ -994,6 +995,41 @@ static int bisect_replay(struct bisect_terms *terms, const char *filename)return bisect_auto_next (terms,NULL ); } +static int bisect_skip (struct bisect_terms *terms,const char **argv,int argc) +{ +int i, res; +const char *pattern ="*..*" ; +struct argv_array argv_state =ARGV_ARRAY_INIT ; + +argv_array_push (&argv_state,"skip" ); + +for (i =0 ; i < argc; i++) { +if (!wildmatch (pattern, argv[i],0 )) { +struct rev_info revs; +struct commit *commit; +struct argv_array rev_argv =ARGV_ARRAY_INIT ; + +argv_array_pushl (&rev_argv,"skipped_commits" , argv[i],NULL ); +init_revisions (&revs,NULL ); +setup_revisions (rev_argv.argc, rev_argv.argv, &revs,NULL ); +argv_array_clear (&rev_argv); + +if (prepare_revision_walk (&revs)) +die (_ ("revision walk setup failed\n" )); +while ((commit =get_revision (&revs)) !=NULL ) +argv_array_push (&argv_state, +oid_to_hex (&commit->object.oid)); + +reset_revision_walk (); + }else { +argv_array_push (&argv_state, argv[i]); + } + } + res =bisect_state (terms, argv_state.argv, argv_state.argc); +argv_array_clear (&argv_state); +return res; +} +int cmd_bisect__helper (int argc,const char **argv,const char *prefix) {enum {
@@ -1005,7 +1041,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)BISECT_NEXT ,BISECT_STATE ,BISECT_LOG , - BISECT_REPLAY +BISECT_REPLAY , + BISECT_SKIP } cmdmode =0 ;int no_checkout =0 , res =0 , nolog =0 ;struct option options[] = {
@@ -1027,6 +1064,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) N_("output the contents of BISECT_LOG"), BISECT_LOG),OPT_CMDMODE (0 ,"bisect-replay" , &cmdmode,N_ ("replay the bisection process from the given file" ),BISECT_REPLAY ), +OPT_CMDMODE (0 ,"bisect-skip" , &cmdmode, +N_ ("skip some commits for checkout" ),BISECT_SKIP ),OPT_BOOL (0 ,"no-checkout" , &no_checkout,N_ ("update BISECT_HEAD instead of checking out the current commit" )), OPT_BOOL(0, "no-log", &nolog,
@@ -1093,6 +1132,10 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)set_terms (&terms,"bad" ,"good" ); res =bisect_replay (&terms, argv[0 ]);break ; +case BISECT_SKIP : +set_terms (&terms,"bad" ,"good" ); + res =bisect_skip (&terms, argv, argc); +break ;default :return error ("BUG: unknown subcommand '%d'" , cmdmode); }
git-bisect.sh +1 -16
@@ -39,21 +39,6 @@ _x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40" TERM_BAD=bad TERM_GOOD=good -bisect_skip() { - all='' - for arg in "$@" - do - case "$arg" in - *..*) - revs=$(git rev-list "$arg") || die "$(eval_gettext "Bad rev input: \$arg")" ;; - *) - revs=$(git rev-parse --sq-quote "$arg") ;; - esac - all="$all $revs" - done - eval git bisect--helper --bisect-state 'skip' $all -} - bisect_visualize() { git bisect--helper --bisect-next-check $TERM_GOOD $TERM_BAD fail || exit
@@ -162,7 +147,7 @@ case "$#" in bad|good|new|old|"$TERM_BAD"|"$TERM_GOOD") git bisect--helper --bisect-state "$cmd" "$@" ;; skip) - bisect_skip "$@" ;; + git bisect--helper --bisect-skip "$@" ;; next) # Not sure we want "next" at the UI level anymore. get_terms
Signature · 1 line
gitgitgadget
PATCH 26/26 bisect--helper: retire `--check-and-set-terms` subcommand
In reply to Tanushree Tumane via GitGitGadgetFrom: Pranit Bauva <[email protected]>
The --check-and-set-terms subcommand is no longer used in the shell script and the function check_and_set_terms() is called from the C implementation.
--- builtin/bisect--helper.c | 10 ---------- 1 file changed, 10 deletions(-)
builtin/bisect--helper.c +0 -10
@@ -21,7 +21,6 @@ static GIT_PATH_FUNC(git_path_bisect_names, "BISECT_NAMES")static const char *const git_bisect_helper_usage[] = {N_ ("git bisect--helper --bisect-reset [<commit>]" ), -N_ ("git bisect--helper --bisect-check-and-set-terms <command> <good_term> <bad_term>" ),N_ ("git bisect--helper --bisect-next-check <good_term> <bad_term> [<term>]" ),N_ ("git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad | --term-new]" ), N_("git bisect--helper --bisect-start [--term-{old,good}=<term> --term-{new,bad}=<term>]"
@@ -1034,7 +1033,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix) {enum {BISECT_RESET =1 , -CHECK_AND_SET_TERMS ,BISECT_NEXT_CHECK ,BISECT_TERMS ,BISECT_START ,
@@ -1048,8 +1046,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)struct option options[] = {OPT_CMDMODE (0 ,"bisect-reset" , &cmdmode,N_ ("reset the bisection state" ),BISECT_RESET ), -OPT_CMDMODE (0 ,"check-and-set-terms" , &cmdmode, -N_ ("check and set terms in a bisection state" ),CHECK_AND_SET_TERMS ),OPT_CMDMODE (0 ,"bisect-next-check" , &cmdmode,N_ ("check whether bad or good terms exist" ),BISECT_NEXT_CHECK ), OPT_CMDMODE(0, "bisect-terms", &cmdmode,
@@ -1087,12 +1083,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)return error (_ ("--bisect-reset requires either no argument or a commit" )); res =bisect_reset (argc ? argv[0 ] :NULL );break ; -case CHECK_AND_SET_TERMS : -if (argc !=3 ) -return error (_ ("--check-and-set-terms requires 3 arguments" )); -set_terms (&terms, argv[2 ], argv[1 ]); - res =check_and_set_terms (&terms, argv[0 ]); -break ;case BISECT_NEXT_CHECK :if (argc !=2 && argc !=3 )return error (_ ("--bisect-next-check requires 2 or 3 arguments" ));
Signature · 1 line
gitgitgadget