From: Junio C Hamano Date: Sat, 26 Dec 2009 22:03:17 +0000 (-0800) Subject: Merge branch 'jc/1.7.0-push-safety' X-Git-Tag: v1.7.0-rc0~143 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/7ad9cec81d86ccf7a693ad7e1218e238aee5ca9d?ds=inline;hp=-c Merge branch 'jc/1.7.0-push-safety' * jc/1.7.0-push-safety: Refuse deleting the current branch via push Refuse updating the current branch in a non-bare repository via push --- 7ad9cec81d86ccf7a693ad7e1218e238aee5ca9d diff --combined builtin-receive-pack.c index 78c0e69cdc,db12b813ac..4320c93e70 --- a/builtin-receive-pack.c +++ b/builtin-receive-pack.c @@@ -28,8 -28,6 +28,8 @@@ static int transfer_unpack_limit = -1 static int unpack_limit = 100; static int report_status; static int prefer_ofs_delta = 1; +static int auto_update_server_info; +static int auto_gc = 1; static const char *head_name; static char *capabilities_to_send; @@@ -90,16 -88,6 +90,16 @@@ static int receive_pack_config(const ch return 0; } + if (strcmp(var, "receive.updateserverinfo") == 0) { + auto_update_server_info = git_config_bool(var, value); + return 0; + } + + if (strcmp(var, "receive.autogc") == 0) { + auto_gc = git_config_bool(var, value); + return 0; + } + return git_default_config(var, value, cb); } @@@ -135,6 -123,31 +135,6 @@@ static struct command *commands static const char pre_receive_hook[] = "hooks/pre-receive"; static const char post_receive_hook[] = "hooks/post-receive"; -static int run_status(int code, const char *cmd_name) -{ - switch (code) { - case 0: - return 0; - case -ERR_RUN_COMMAND_FORK: - return error("fork of %s failed", cmd_name); - case -ERR_RUN_COMMAND_EXEC: - return error("execute of %s failed", cmd_name); - case -ERR_RUN_COMMAND_PIPE: - return error("pipe failed"); - case -ERR_RUN_COMMAND_WAITPID: - return error("waitpid failed"); - case -ERR_RUN_COMMAND_WAITPID_WRONG_PID: - return error("waitpid is confused"); - case -ERR_RUN_COMMAND_WAITPID_SIGNAL: - return error("%s died of signal", cmd_name); - case -ERR_RUN_COMMAND_WAITPID_NOEXIT: - return error("%s died strangely", cmd_name); - default: - error("%s exited with error code %d", cmd_name, -code); - return -code; - } -} - static int run_receive_hook(const char *hook_name) { static char buf[sizeof(commands->old_sha1) * 2 + PATH_MAX + 4]; @@@ -161,7 -174,7 +161,7 @@@ code = start_command(&proc); if (code) - return run_status(code, hook_name); + return code; for (cmd = commands; cmd; cmd = cmd->next) { if (!cmd->error_string) { size_t n = snprintf(buf, sizeof(buf), "%s %s %s\n", @@@ -173,7 -186,7 +173,7 @@@ } } close(proc.in); - return run_status(finish_command(&proc), hook_name); + return finish_command(&proc); } static int run_update_hook(struct command *cmd) @@@ -190,8 -203,9 +190,8 @@@ argv[3] = sha1_to_hex(cmd->new_sha1); argv[4] = NULL; - return run_status(run_command_v_opt(argv, RUN_COMMAND_NO_STDIN | - RUN_COMMAND_STDOUT_TO_STDERR), - update_hook); + return run_command_v_opt(argv, RUN_COMMAND_NO_STDIN | + RUN_COMMAND_STDOUT_TO_STDERR); } static int is_ref_checked_out(const char *ref) @@@ -204,59 -218,47 +204,47 @@@ return !strcmp(head_name, ref); } - static char *warn_unconfigured_deny_msg[] = { - "Updating the currently checked out branch may cause confusion,", - "as the index and work tree do not reflect changes that are in HEAD.", - "As a result, you may see the changes you just pushed into it", - "reverted when you run 'git diff' over there, and you may want", - "to run 'git reset --hard' before starting to work to recover.", + static char *refuse_unconfigured_deny_msg[] = { + "By default, updating the current branch in a non-bare repository", + "is denied, because it will make the index and work tree inconsistent", + "with what you pushed, and will require 'git reset --hard' to match", + "the work tree to HEAD.", "", "You can set 'receive.denyCurrentBranch' configuration variable to", - "'refuse' in the remote repository to forbid pushing into its", - "current branch." + "'ignore' or 'warn' in the remote repository to allow pushing into", + "its current branch; however, this is not recommended unless you", + "arranged to update its work tree to match what you pushed in some", + "other way.", "", - "To allow pushing into the current branch, you can set it to 'ignore';", - "but this is not recommended unless you arranged to update its work", - "tree to match what you pushed in some other way.", - "", - "To squelch this message, you can set it to 'warn'.", - "", - "Note that the default will change in a future version of git", - "to refuse updating the current branch unless you have the", - "configuration variable set to either 'ignore' or 'warn'." + "To squelch this message and still keep the default behaviour, set", + "'receive.denyCurrentBranch' configuration variable to 'refuse'." }; - static void warn_unconfigured_deny(void) + static void refuse_unconfigured_deny(void) { int i; - for (i = 0; i < ARRAY_SIZE(warn_unconfigured_deny_msg); i++) - warning("%s", warn_unconfigured_deny_msg[i]); + for (i = 0; i < ARRAY_SIZE(refuse_unconfigured_deny_msg); i++) + error("%s", refuse_unconfigured_deny_msg[i]); } - static char *warn_unconfigured_deny_delete_current_msg[] = { - "Deleting the current branch can cause confusion by making the next", - "'git clone' not check out any file.", + static char *refuse_unconfigured_deny_delete_current_msg[] = { + "By default, deleting the current branch is denied, because the next", + "'git clone' won't result in any file checked out, causing confusion.", "", "You can set 'receive.denyDeleteCurrent' configuration variable to", - "'refuse' in the remote repository to disallow deleting the current", - "branch.", - "", - "You can set it to 'ignore' to allow such a delete without a warning.", + "'warn' or 'ignore' in the remote repository to allow deleting the", + "current branch, with or without a warning message.", "", - "To make this warning message less loud, you can set it to 'warn'.", - "", - "Note that the default will change in a future version of git", - "to refuse deleting the current branch unless you have the", - "configuration variable set to either 'ignore' or 'warn'." + "To squelch this message, you can set it to 'refuse'." }; - static void warn_unconfigured_deny_delete_current(void) + static void refuse_unconfigured_deny_delete_current(void) { int i; for (i = 0; - i < ARRAY_SIZE(warn_unconfigured_deny_delete_current_msg); + i < ARRAY_SIZE(refuse_unconfigured_deny_delete_current_msg); i++) - warning("%s", warn_unconfigured_deny_delete_current_msg[i]); + error("%s", refuse_unconfigured_deny_delete_current_msg[i]); } static const char *update(struct command *cmd) @@@ -276,14 -278,14 +264,14 @@@ switch (deny_current_branch) { case DENY_IGNORE: break; - case DENY_UNCONFIGURED: case DENY_WARN: warning("updating the current branch"); - if (deny_current_branch == DENY_UNCONFIGURED) - warn_unconfigured_deny(); break; case DENY_REFUSE: + case DENY_UNCONFIGURED: error("refusing to update checked out branch: %s", name); + if (deny_current_branch == DENY_UNCONFIGURED) + refuse_unconfigured_deny(); return "branch is currently checked out"; } } @@@ -305,12 -307,12 +293,12 @@@ case DENY_IGNORE: break; case DENY_WARN: - case DENY_UNCONFIGURED: - if (deny_delete_current == DENY_UNCONFIGURED) - warn_unconfigured_deny_delete_current(); warning("deleting the current branch"); break; case DENY_REFUSE: + case DENY_UNCONFIGURED: + if (deny_delete_current == DENY_UNCONFIGURED) + refuse_unconfigured_deny_delete_current(); error("refusing to delete the current branch: %s", name); return "deletion of the current branch prohibited"; } @@@ -341,9 -343,9 +329,9 @@@ break; free_commit_list(bases); if (!ent) { - error("denying non-fast forward %s" + error("denying non-fast-forward %s" " (you should pull first)", name); - return "non-fast forward"; + return "non-fast-forward"; } } if (run_update_hook(cmd)) { @@@ -405,6 -407,7 +393,6 @@@ static void run_update_post_hook(struc argv[argc] = NULL; status = run_command_v_opt(argv, RUN_COMMAND_NO_STDIN | RUN_COMMAND_STDOUT_TO_STDERR); - run_status(status, update_post_hook); } static void execute_commands(const char *unpacker_error) @@@ -522,6 -525,7 +510,6 @@@ static const char *unpack(void code = run_command_v_opt(unpacker, RUN_GIT_CMD); if (!code) return NULL; - run_status(code, unpacker[0]); return "unpack-objects abnormal exit"; } else { const char *keeper[7]; @@@ -547,6 -551,7 +535,6 @@@ ip.git_cmd = 1; status = start_command(&ip); if (status) { - run_status(status, keeper[0]); return "index-pack fork failed"; } pack_lockfile = index_pack_lockfile(ip.out); @@@ -556,6 -561,7 +544,6 @@@ reprepare_packed_git(); return NULL; } - run_status(status, keeper[0]); return "index-pack abnormal exit"; } } @@@ -627,8 -633,6 +615,8 @@@ static void add_alternate_refs(void int cmd_receive_pack(int argc, const char **argv, const char *prefix) { + int advertise_refs = 0; + int stateless_rpc = 0; int i; char *dir = NULL; @@@ -637,15 -641,7 +625,15 @@@ const char *arg = *argv++; if (*arg == '-') { - /* Do flag handling here */ + if (!strcmp(arg, "--advertise-refs")) { + advertise_refs = 1; + continue; + } + if (!strcmp(arg, "--stateless-rpc")) { + stateless_rpc = 1; + continue; + } + usage(receive_pack_usage); } if (dir) @@@ -674,16 -670,12 +662,16 @@@ " report-status delete-refs ofs-delta " : " report-status delete-refs "; - add_alternate_refs(); - write_head_info(); - clear_extra_refs(); + if (advertise_refs || !stateless_rpc) { + add_alternate_refs(); + write_head_info(); + clear_extra_refs(); - /* EOF */ - packet_flush(1); + /* EOF */ + packet_flush(1); + } + if (advertise_refs) + return 0; read_head_info(); if (commands) { @@@ -698,14 -690,6 +686,14 @@@ report(unpack_status); run_receive_hook(post_receive_hook); run_update_post_hook(commands); + if (auto_gc) { + const char *argv_gc_auto[] = { + "gc", "--auto", "--quiet", NULL, + }; + run_command_v_opt(argv_gc_auto, RUN_GIT_CMD); + } + if (auto_update_server_info) + update_server_info(0); } return 0; } diff --combined t/t5516-fetch-push.sh index 6889a53cf9,6529d97dc0..516127b539 --- a/t/t5516-fetch-push.sh +++ b/t/t5516-fetch-push.sh @@@ -12,6 -12,7 +12,7 @@@ mk_empty () ( cd testrepo && git init && + git config receive.denyCurrentBranch warn && mv .git/hooks .git/hooks-disabled ) } @@@ -122,23 -123,6 +123,23 @@@ test_expect_success 'fetch with instead ) ' +test_expect_success 'fetch with pushInsteadOf (should not rewrite)' ' + mk_empty && + ( + TRASH=$(pwd)/ && + cd testrepo && + git config "url.trash/.pushInsteadOf" "$TRASH" && + git config remote.up.url "$TRASH." && + git config remote.up.fetch "refs/heads/*:refs/remotes/origin/*" && + git fetch up && + + r=$(git show-ref -s --verify refs/remotes/origin/master) && + test "z$r" = "z$the_commit" && + + test 1 = $(git for-each-ref refs/remotes/origin | wc -l) + ) +' + test_expect_success 'push without wildcard' ' mk_empty && @@@ -179,36 -163,6 +180,36 @@@ test_expect_success 'push with insteadO ) ' +test_expect_success 'push with pushInsteadOf' ' + mk_empty && + TRASH="$(pwd)/" && + git config "url.$TRASH.pushInsteadOf" trash/ && + git push trash/testrepo refs/heads/master:refs/remotes/origin/master && + ( + cd testrepo && + r=$(git show-ref -s --verify refs/remotes/origin/master) && + test "z$r" = "z$the_commit" && + + test 1 = $(git for-each-ref refs/remotes/origin | wc -l) + ) +' + +test_expect_success 'push with pushInsteadOf and explicit pushurl (pushInsteadOf should not rewrite)' ' + mk_empty && + TRASH="$(pwd)/" && + git config "url.trash2/.pushInsteadOf" trash/ && + git config remote.r.url trash/wrong && + git config remote.r.pushurl "$TRASH/testrepo" && + git push r refs/heads/master:refs/remotes/origin/master && + ( + cd testrepo && + r=$(git show-ref -s --verify refs/remotes/origin/master) && + test "z$r" = "z$the_commit" && + + test 1 = $(git for-each-ref refs/remotes/origin | wc -l) + ) +' + test_expect_success 'push with matching heads' ' mk_test heads/master &&