push options: {pre,post}-receive hook learns about push options
[git/git.git] / builtin / receive-pack.c
index 15c323a..6cdd2c6 100644 (file)
@@ -550,8 +550,16 @@ static void prepare_push_cert_sha1(struct child_process *proc)
        }
 }
 
+struct receive_hook_feed_state {
+       struct command *cmd;
+       int skip_broken;
+       struct strbuf buf;
+       const struct string_list *push_options;
+};
+
 typedef int (*feed_fn)(void *, const char **, size_t *);
-static int run_and_feed_hook(const char *hook_name, feed_fn feed, void *feed_state)
+static int run_and_feed_hook(const char *hook_name, feed_fn feed,
+                            struct receive_hook_feed_state *feed_state)
 {
        struct child_process proc = CHILD_PROCESS_INIT;
        struct async muxer;
@@ -567,6 +575,16 @@ static int run_and_feed_hook(const char *hook_name, feed_fn feed, void *feed_sta
        proc.argv = argv;
        proc.in = -1;
        proc.stdout_to_stderr = 1;
+       if (feed_state->push_options) {
+               int i;
+               for (i = 0; i < feed_state->push_options->nr; i++)
+                       argv_array_pushf(&proc.env_array,
+                               "GIT_PUSH_OPTION_%d=%s", i,
+                               feed_state->push_options->items[i].string);
+               argv_array_pushf(&proc.env_array, "GIT_PUSH_OPTION_COUNT=%d",
+                                feed_state->push_options->nr);
+       } else
+               argv_array_pushf(&proc.env_array, "GIT_PUSH_OPTION_COUNT");
 
        if (use_sideband) {
                memset(&muxer, 0, sizeof(muxer));
@@ -606,12 +624,6 @@ static int run_and_feed_hook(const char *hook_name, feed_fn feed, void *feed_sta
        return finish_command(&proc);
 }
 
-struct receive_hook_feed_state {
-       struct command *cmd;
-       int skip_broken;
-       struct strbuf buf;
-};
-
 static int feed_receive_hook(void *state_, const char **bufp, size_t *sizep)
 {
        struct receive_hook_feed_state *state = state_;
@@ -634,8 +646,10 @@ static int feed_receive_hook(void *state_, const char **bufp, size_t *sizep)
        return 0;
 }
 
-static int run_receive_hook(struct command *commands, const char *hook_name,
-                           int skip_broken)
+static int run_receive_hook(struct command *commands,
+                           const char *hook_name,
+                           int skip_broken,
+                           const struct string_list *push_options)
 {
        struct receive_hook_feed_state state;
        int status;
@@ -646,6 +660,7 @@ static int run_receive_hook(struct command *commands, const char *hook_name,
        if (feed_receive_hook(&state, NULL, NULL))
                return 0;
        state.cmd = commands;
+       state.push_options = push_options;
        status = run_and_feed_hook(hook_name, feed_receive_hook, &state);
        strbuf_release(&state.buf);
        return status;
@@ -1316,7 +1331,8 @@ cleanup:
 
 static void execute_commands(struct command *commands,
                             const char *unpacker_error,
-                            struct shallow_info *si)
+                            struct shallow_info *si,
+                            const struct string_list *push_options)
 {
        struct command *cmd;
        unsigned char sha1[20];
@@ -1335,7 +1351,7 @@ static void execute_commands(struct command *commands,
 
        reject_updates_to_hidden(commands);
 
-       if (run_receive_hook(commands, "pre-receive", 0)) {
+       if (run_receive_hook(commands, "pre-receive", 0, push_options)) {
                for (cmd = commands; cmd; cmd = cmd->next) {
                        if (!cmd->error_string)
                                cmd->error_string = "pre-receive hook declined";
@@ -1756,6 +1772,7 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
 
        if ((commands = read_head_info(&shallow)) != NULL) {
                const char *unpack_status = NULL;
+               struct string_list push_options = STRING_LIST_INIT_DUP;
 
                prepare_shallow_info(&si, &shallow);
                if (!si.nr_ours && !si.nr_theirs)
@@ -1764,13 +1781,17 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
                        unpack_status = unpack_with_sideband(&si);
                        update_shallow_info(commands, &si, &ref);
                }
-               execute_commands(commands, unpack_status, &si);
+               execute_commands(commands, unpack_status, &si,
+                                &push_options);
                if (pack_lockfile)
                        unlink_or_warn(pack_lockfile);
                if (report_status)
                        report(commands, unpack_status);
-               run_receive_hook(commands, "post-receive", 1);
+               run_receive_hook(commands, "post-receive", 1,
+                                &push_options);
                run_update_post_hook(commands);
+               if (push_options.nr)
+                       string_list_clear(&push_options, 0);
                if (auto_gc) {
                        const char *argv_gc_auto[] = {
                                "gc", "--auto", "--quiet", NULL,