Merge branch 'jc/perl-cat-blob'
[gitweb.git] / builtin / receive-pack.c
index ff781febcad92dfccd8a3d97d0414526ded36943..62ba6e7a3d014be01fe01ed497c083f7e44e9d34 100644 (file)
@@ -59,6 +59,11 @@ static enum deny_action parse_deny_action(const char *var, const char *value)
 
 static int receive_pack_config(const char *var, const char *value, void *cb)
 {
+       int status = parse_hide_refs_config(var, value, "receive");
+
+       if (status)
+               return status;
+
        if (strcmp(var, "receive.denydeletes") == 0) {
                deny_deletes = git_config_bool(var, value);
                return 0;
@@ -119,6 +124,9 @@ static int receive_pack_config(const char *var, const char *value, void *cb)
 
 static void show_ref(const char *path, const unsigned char *sha1)
 {
+       if (ref_is_hidden(path))
+               return;
+
        if (sent_capabilities)
                packet_write(1, "%s %s\n", sha1_to_hex(sha1), path);
        else
@@ -182,9 +190,6 @@ struct command {
        char ref_name[FLEX_ARRAY]; /* more */
 };
 
-static const char pre_receive_hook[] = "hooks/pre-receive";
-static const char post_receive_hook[] = "hooks/post-receive";
-
 static void rp_error(const char *err, ...) __attribute__((format (printf, 1, 2)));
 static void rp_warning(const char *err, ...) __attribute__((format (printf, 1, 2)));
 
@@ -242,10 +247,10 @@ static int run_and_feed_hook(const char *hook_name, feed_fn feed, void *feed_sta
        const char *argv[2];
        int code;
 
-       if (access(hook_name, X_OK) < 0)
+       argv[0] = find_hook(hook_name);
+       if (!argv[0])
                return 0;
 
-       argv[0] = hook_name;
        argv[1] = NULL;
 
        memset(&proc, 0, sizeof(proc));
@@ -331,15 +336,14 @@ static int run_receive_hook(struct command *commands, const char *hook_name,
 
 static int run_update_hook(struct command *cmd)
 {
-       static const char update_hook[] = "hooks/update";
        const char *argv[5];
        struct child_process proc;
        int code;
 
-       if (access(update_hook, X_OK) < 0)
+       argv[0] = find_hook("update");
+       if (!argv[0])
                return 0;
 
-       argv[0] = update_hook;
        argv[1] = cmd->ref_name;
        argv[2] = sha1_to_hex(cmd->old_sha1);
        argv[3] = sha1_to_hex(cmd->new_sha1);
@@ -532,24 +536,25 @@ static const char *update(struct command *cmd)
        }
 }
 
-static char update_post_hook[] = "hooks/post-update";
-
 static void run_update_post_hook(struct command *commands)
 {
        struct command *cmd;
        int argc;
        const char **argv;
        struct child_process proc;
+       char *hook;
 
+       hook = find_hook("post-update");
        for (argc = 0, cmd = commands; cmd; cmd = cmd->next) {
                if (cmd->error_string || cmd->did_not_exist)
                        continue;
                argc++;
        }
-       if (!argc || access(update_post_hook, X_OK) < 0)
+       if (!argc || !hook)
                return;
+
        argv = xmalloc(sizeof(*argv) * (2 + argc));
-       argv[0] = update_post_hook;
+       argv[0] = hook;
 
        for (argc = 1, cmd = commands; cmd; cmd = cmd->next) {
                char *p;
@@ -688,6 +693,20 @@ static int iterate_receive_command_list(void *cb_data, unsigned char sha1[20])
        return -1; /* end of list */
 }
 
+static void reject_updates_to_hidden(struct command *commands)
+{
+       struct command *cmd;
+
+       for (cmd = commands; cmd; cmd = cmd->next) {
+               if (cmd->error_string || !ref_is_hidden(cmd->ref_name))
+                       continue;
+               if (is_null_sha1(cmd->new_sha1))
+                       cmd->error_string = "deny deleting a hidden ref";
+               else
+                       cmd->error_string = "deny updating a hidden ref";
+       }
+}
+
 static void execute_commands(struct command *commands, const char *unpacker_error)
 {
        struct command *cmd;
@@ -704,7 +723,9 @@ static void execute_commands(struct command *commands, const char *unpacker_erro
                                       0, &cmd))
                set_connectivity_errors(commands);
 
-       if (run_receive_hook(commands, pre_receive_hook, 0)) {
+       reject_updates_to_hidden(commands);
+
+       if (run_receive_hook(commands, "pre-receive", 0)) {
                for (cmd = commands; cmd; cmd = cmd->next) {
                        if (!cmd->error_string)
                                cmd->error_string = "pre-receive hook declined";
@@ -994,7 +1015,7 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
                        unlink_or_warn(pack_lockfile);
                if (report_status)
                        report(commands, unpack_status);
-               run_receive_hook(commands, post_receive_hook, 1);
+               run_receive_hook(commands, "post-receive", 1);
                run_update_post_hook(commands);
                if (auto_gc) {
                        const char *argv_gc_auto[] = {