bisect: libify check_good_are_ancestors_of_bad and its dependents

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 <negative-value>`. Follow POSIX conventions to return
<negative-value> to indicate error.

Code that turns BISECT_INTERNAL_SUCCESS_MERGE_BASE (-11)
 to BISECT_OK (0) from `check_good_are_ancestors_of_bad()` has been moved to
`cmd_bisect__helper()`.

Update all callers to handle the error returns.

Mentored-by: Christian Couder <chriscool@tuxfamily.org>
Mentored by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Pranit Bauva <pranit.bauva@gmail.com>
Signed-off-by: Tanushree Tumane <tanushreetumane@gmail.com>
Signed-off-by: Miriam Rubio <mirucam@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Pranit Bauva 2020-02-17 09:40:37 +01:00 committed by Junio C Hamano
parent cdd4dc2d6a
commit 45b6370812
2 changed files with 37 additions and 15 deletions

View File

@ -872,20 +872,23 @@ static int check_ancestors(struct repository *r, int rev_nr,
*
* 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(struct repository *r,
static enum bisect_error check_good_are_ancestors_of_bad(struct repository *r,
const char *prefix,
int no_checkout)
{
char *filename = git_pathdup("BISECT_ANCESTORS_OK");
char *filename;
struct stat st;
int fd, rev_nr;
enum bisect_error res = BISECT_OK;
struct commit **rev;
if (!current_bad_oid)
die(_("a %s revision is needed"), term_bad);
return error(_("a %s revision is needed"), term_bad);
filename = git_pathdup("BISECT_ANCESTORS_OK");
/* Check if file BISECT_ANCESTORS_OK exists. */
if (!stat(filename, &st) && S_ISREG(st.st_mode))
@ -901,18 +904,26 @@ static void check_good_are_ancestors_of_bad(struct repository *r,
if (check_ancestors(r, rev_nr, rev, prefix))
res = check_merge_bases(rev_nr, rev, no_checkout);
free(rev);
if (res)
exit(res == BISECT_INTERNAL_SUCCESS_MERGE_BASE ? BISECT_OK : -res);
if (!res) {
/* Create file BISECT_ANCESTORS_OK. */
fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY, 0600);
if (fd < 0)
/*
* BISECT_ANCESTORS_OK file is not absolutely necessary,
* the bisection process will continue at the next
* bisection step.
* So, just signal with a warning that something
* might be wrong.
*/
warning_errno(_("could not create file '%s'"),
filename);
else
close(fd);
}
done:
free(filename);
return res;
}
/*
@ -984,7 +995,9 @@ enum bisect_error bisect_next_all(struct repository *r, const char *prefix, int
if (read_bisect_refs())
die(_("reading bisect refs failed"));
check_good_are_ancestors_of_bad(r, prefix, no_checkout);
res = check_good_are_ancestors_of_bad(r, prefix, no_checkout);
if (res)
return res;
bisect_rev_setup(r, &revs, prefix, "%s", "^%s", 1);
revs.limited = 1;

View File

@ -666,7 +666,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
switch (cmdmode) {
case NEXT_ALL:
return bisect_next_all(the_repository, prefix, no_checkout);
res = bisect_next_all(the_repository, prefix, no_checkout);
break;
case WRITE_TERMS:
if (argc != 2)
return error(_("--write-terms requires two arguments"));
@ -713,5 +714,13 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
return error("BUG: unknown subcommand '%d'", cmdmode);
}
free_terms(&terms);
/*
* Handle early success
* From check_merge_bases > check_good_are_ancestors_of_bad > bisect_next_all
*/
if (res == BISECT_INTERNAL_SUCCESS_MERGE_BASE)
res = BISECT_OK;
return abs(res);
}