To libify `git apply` functionality we have to signal errors
to the caller instead of die()ing.

As a first step in this direction, let's make apply_patch() return
-1 or -128 in case of errors instead of dying. For now its only
caller apply_all_patches() will exit(128) when apply_patch()
return -128 and it will exit(1) when it returns -1.

We exit() with code 128 because that was what die() was doing
and we want to keep the distinction between exiting with code 1
and exiting with code 128.

Helped-by: Eric Sunshine <sunsh...@sunshineco.com>
Signed-off-by: Christian Couder <chrisc...@tuxfamily.org>
---
 builtin/apply.c | 60 ++++++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 45 insertions(+), 15 deletions(-)

diff --git a/builtin/apply.c b/builtin/apply.c
index ed923ca..435030a 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -4404,6 +4404,15 @@ static struct lock_file lock_file;
 #define INACCURATE_EOF (1<<0)
 #define RECOUNT                (1<<1)
 
+/*
+ * Try to apply a patch.
+ *
+ * Returns:
+ *  -128 if a bad error happened (like patch unreadable)
+ *  -1 if patch did not apply and user cannot deal with it
+ *   0 if the patch applied
+ *   1 if the patch did not apply but user might fix it
+ */
 static int apply_patch(struct apply_state *state,
                       int fd,
                       const char *filename,
@@ -4413,6 +4422,7 @@ static int apply_patch(struct apply_state *state,
        struct strbuf buf = STRBUF_INIT; /* owns the patch text */
        struct patch *list = NULL, **listp = &list;
        int skipped_patch = 0;
+       int res = 0;
 
        state->patch_input_file = filename;
        read_patch_file(&buf, fd);
@@ -4445,8 +4455,11 @@ static int apply_patch(struct apply_state *state,
                offset += nr;
        }
 
-       if (!list && !skipped_patch)
-               die(_("unrecognized input"));
+       if (!list && !skipped_patch) {
+               error(_("unrecognized input"));
+               res = -128;
+               goto end;
+       }
 
        if (state->whitespace_error && (state->ws_error_action == 
die_on_ws_error))
                state->apply = 0;
@@ -4455,21 +4468,23 @@ static int apply_patch(struct apply_state *state,
        if (state->update_index && state->newfd < 0)
                state->newfd = hold_locked_index(state->lock_file, 1);
 
-       if (state->check_index) {
-               if (read_cache() < 0)
-                       die(_("unable to read index file"));
+       if (state->check_index && read_cache() < 0) {
+               error(_("unable to read index file"));
+               res = -128;
+               goto end;
        }
 
        if ((state->check || state->apply) &&
            check_patch_list(state, list) < 0 &&
-           !state->apply_with_reject)
-               exit(1);
+           !state->apply_with_reject) {
+               res = -1;
+               goto end;
+       }
 
        if (state->apply && write_out_results(state, list)) {
-               if (state->apply_with_reject)
-                       exit(1);
                /* with --3way, we still need to write the index out */
-               return 1;
+               res = state->apply_with_reject ? -1 : 1;
+               goto end;
        }
 
        if (state->fake_ancestor)
@@ -4484,10 +4499,11 @@ static int apply_patch(struct apply_state *state,
        if (state->summary)
                summary_patch_list(list);
 
+end:
        free_patch_list(list);
        strbuf_release(&buf);
        string_list_clear(&state->fn_table, 0);
-       return 0;
+       return res;
 }
 
 static void git_apply_config(void)
@@ -4628,6 +4644,7 @@ static int apply_all_patches(struct apply_state *state,
                             int options)
 {
        int i;
+       int res;
        int errs = 0;
        int read_stdin = 1;
 
@@ -4636,7 +4653,10 @@ static int apply_all_patches(struct apply_state *state,
                int fd;
 
                if (!strcmp(arg, "-")) {
-                       errs |= apply_patch(state, 0, "<stdin>", options);
+                       res = apply_patch(state, 0, "<stdin>", options);
+                       if (res < 0)
+                               goto end;
+                       errs |= res;
                        read_stdin = 0;
                        continue;
                } else if (0 < state->prefix_length)
@@ -4649,12 +4669,19 @@ static int apply_all_patches(struct apply_state *state,
                        die_errno(_("can't open patch '%s'"), arg);
                read_stdin = 0;
                set_default_whitespace_mode(state);
-               errs |= apply_patch(state, fd, arg, options);
+               res = apply_patch(state, fd, arg, options);
+               if (res < 0)
+                       goto end;
+               errs |= res;
                close(fd);
        }
        set_default_whitespace_mode(state);
-       if (read_stdin)
-               errs |= apply_patch(state, 0, "<stdin>", options);
+       if (read_stdin) {
+               res = apply_patch(state, 0, "<stdin>", options);
+               if (res < 0)
+                       goto end;
+               errs |= res;
+       }
 
        if (state->whitespace_error) {
                if (state->squelch_whitespace_errors &&
@@ -4690,6 +4717,9 @@ static int apply_all_patches(struct apply_state *state,
        }
 
        return !!errs;
+
+end:
+       exit(res == -1 ? 1 : 128);
 }
 
 int cmd_apply(int argc, const char **argv, const char *prefix)
-- 
2.9.2.614.g4980f51

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to