Merge branch 'ak/protect-any-current-branch'
"git fetch" without the "--update-head-ok" option ought to protect a checked out branch from getting updated, to prevent the working tree that checks it out to go out of sync. The code was written before the use of "git worktree" got widespread, and only checked the branch that was checked out in the current worktree, which has been updated. (originally called ak/fetch-not-overwrite-any-current-branch) * ak/protect-any-current-branch: branch: protect branches checked out in all worktrees receive-pack: protect current branch for bare repository worktree receive-pack: clean dead code from update_worktree() fetch: protect branches checked out in all worktrees worktree: simplify find_shared_symref() memory ownership model branch: lowercase error messages receive-pack: lowercase error messages fetch: lowercase error messages
This commit is contained in:
@@ -175,7 +175,7 @@ static int receive_pack_config(const char *var, const char *value, void *cb)
|
||||
strbuf_addf(&fsck_msg_types, "%c%s=%s",
|
||||
fsck_msg_types.len ? ',' : '=', var, value);
|
||||
else
|
||||
warning("Skipping unknown msg id '%s'", var);
|
||||
warning("skipping unknown msg id '%s'", var);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1434,29 +1434,22 @@ static const char *push_to_checkout(unsigned char *hash,
|
||||
|
||||
static const char *update_worktree(unsigned char *sha1, const struct worktree *worktree)
|
||||
{
|
||||
const char *retval, *work_tree, *git_dir = NULL;
|
||||
const char *retval, *git_dir;
|
||||
struct strvec env = STRVEC_INIT;
|
||||
|
||||
if (worktree && worktree->path)
|
||||
work_tree = worktree->path;
|
||||
else if (git_work_tree_cfg)
|
||||
work_tree = git_work_tree_cfg;
|
||||
else
|
||||
work_tree = "..";
|
||||
if (!worktree || !worktree->path)
|
||||
BUG("worktree->path must be non-NULL");
|
||||
|
||||
if (is_bare_repository())
|
||||
if (worktree->is_bare)
|
||||
return "denyCurrentBranch = updateInstead needs a worktree";
|
||||
if (worktree)
|
||||
git_dir = get_worktree_git_dir(worktree);
|
||||
if (!git_dir)
|
||||
git_dir = get_git_dir();
|
||||
git_dir = get_worktree_git_dir(worktree);
|
||||
|
||||
strvec_pushf(&env, "GIT_DIR=%s", absolute_path(git_dir));
|
||||
|
||||
if (!hook_exists(push_to_checkout_hook))
|
||||
retval = push_to_deploy(sha1, &env, work_tree);
|
||||
retval = push_to_deploy(sha1, &env, worktree->path);
|
||||
else
|
||||
retval = push_to_checkout(sha1, &env, work_tree);
|
||||
retval = push_to_checkout(sha1, &env, worktree->path);
|
||||
|
||||
strvec_clear(&env);
|
||||
return retval;
|
||||
@@ -1471,19 +1464,22 @@ static const char *update(struct command *cmd, struct shallow_info *si)
|
||||
struct object_id *old_oid = &cmd->old_oid;
|
||||
struct object_id *new_oid = &cmd->new_oid;
|
||||
int do_update_worktree = 0;
|
||||
const struct worktree *worktree = is_bare_repository() ? NULL : find_shared_symref("HEAD", name);
|
||||
struct worktree **worktrees = get_worktrees();
|
||||
const struct worktree *worktree =
|
||||
find_shared_symref(worktrees, "HEAD", name);
|
||||
|
||||
/* only refs/... are allowed */
|
||||
if (!starts_with(name, "refs/") || check_refname_format(name + 5, 0)) {
|
||||
rp_error("refusing to create funny ref '%s' remotely", name);
|
||||
return "funny refname";
|
||||
ret = "funny refname";
|
||||
goto out;
|
||||
}
|
||||
|
||||
strbuf_addf(&namespaced_name_buf, "%s%s", get_git_namespace(), name);
|
||||
free(namespaced_name);
|
||||
namespaced_name = strbuf_detach(&namespaced_name_buf, NULL);
|
||||
|
||||
if (worktree) {
|
||||
if (worktree && !worktree->is_bare) {
|
||||
switch (deny_current_branch) {
|
||||
case DENY_IGNORE:
|
||||
break;
|
||||
@@ -1495,7 +1491,8 @@ static const char *update(struct command *cmd, struct shallow_info *si)
|
||||
rp_error("refusing to update checked out branch: %s", name);
|
||||
if (deny_current_branch == DENY_UNCONFIGURED)
|
||||
refuse_unconfigured_deny();
|
||||
return "branch is currently checked out";
|
||||
ret = "branch is currently checked out";
|
||||
goto out;
|
||||
case DENY_UPDATE_INSTEAD:
|
||||
/* pass -- let other checks intervene first */
|
||||
do_update_worktree = 1;
|
||||
@@ -1506,13 +1503,15 @@ static const char *update(struct command *cmd, struct shallow_info *si)
|
||||
if (!is_null_oid(new_oid) && !has_object_file(new_oid)) {
|
||||
error("unpack should have generated %s, "
|
||||
"but I can't find it!", oid_to_hex(new_oid));
|
||||
return "bad pack";
|
||||
ret = "bad pack";
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!is_null_oid(old_oid) && is_null_oid(new_oid)) {
|
||||
if (deny_deletes && starts_with(name, "refs/heads/")) {
|
||||
rp_error("denying ref deletion for %s", name);
|
||||
return "deletion prohibited";
|
||||
ret = "deletion prohibited";
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (worktree || (head_name && !strcmp(namespaced_name, head_name))) {
|
||||
@@ -1528,9 +1527,11 @@ static const char *update(struct command *cmd, struct shallow_info *si)
|
||||
if (deny_delete_current == DENY_UNCONFIGURED)
|
||||
refuse_unconfigured_deny_delete_current();
|
||||
rp_error("refusing to delete the current branch: %s", name);
|
||||
return "deletion of the current branch prohibited";
|
||||
ret = "deletion of the current branch prohibited";
|
||||
goto out;
|
||||
default:
|
||||
return "Invalid denyDeleteCurrent setting";
|
||||
ret = "Invalid denyDeleteCurrent setting";
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1548,25 +1549,28 @@ static const char *update(struct command *cmd, struct shallow_info *si)
|
||||
old_object->type != OBJ_COMMIT ||
|
||||
new_object->type != OBJ_COMMIT) {
|
||||
error("bad sha1 objects for %s", name);
|
||||
return "bad ref";
|
||||
ret = "bad ref";
|
||||
goto out;
|
||||
}
|
||||
old_commit = (struct commit *)old_object;
|
||||
new_commit = (struct commit *)new_object;
|
||||
if (!in_merge_bases(old_commit, new_commit)) {
|
||||
rp_error("denying non-fast-forward %s"
|
||||
" (you should pull first)", name);
|
||||
return "non-fast-forward";
|
||||
ret = "non-fast-forward";
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
if (run_update_hook(cmd)) {
|
||||
rp_error("hook declined to update %s", name);
|
||||
return "hook declined";
|
||||
ret = "hook declined";
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (do_update_worktree) {
|
||||
ret = update_worktree(new_oid->hash, find_shared_symref("HEAD", name));
|
||||
ret = update_worktree(new_oid->hash, worktree);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (is_null_oid(new_oid)) {
|
||||
@@ -1574,9 +1578,9 @@ static const char *update(struct command *cmd, struct shallow_info *si)
|
||||
if (!parse_object(the_repository, old_oid)) {
|
||||
old_oid = NULL;
|
||||
if (ref_exists(name)) {
|
||||
rp_warning("Allowing deletion of corrupt ref.");
|
||||
rp_warning("allowing deletion of corrupt ref");
|
||||
} else {
|
||||
rp_warning("Deleting a non-existent ref.");
|
||||
rp_warning("deleting a non-existent ref");
|
||||
cmd->did_not_exist = 1;
|
||||
}
|
||||
}
|
||||
@@ -1585,17 +1589,19 @@ static const char *update(struct command *cmd, struct shallow_info *si)
|
||||
old_oid,
|
||||
0, "push", &err)) {
|
||||
rp_error("%s", err.buf);
|
||||
strbuf_release(&err);
|
||||
return "failed to delete";
|
||||
ret = "failed to delete";
|
||||
} else {
|
||||
ret = NULL; /* good */
|
||||
}
|
||||
strbuf_release(&err);
|
||||
return NULL; /* good */
|
||||
}
|
||||
else {
|
||||
struct strbuf err = STRBUF_INIT;
|
||||
if (shallow_update && si->shallow_ref[cmd->index] &&
|
||||
update_shallow_ref(cmd, si))
|
||||
return "shallow error";
|
||||
update_shallow_ref(cmd, si)) {
|
||||
ret = "shallow error";
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ref_transaction_update(transaction,
|
||||
namespaced_name,
|
||||
@@ -1603,14 +1609,16 @@ static const char *update(struct command *cmd, struct shallow_info *si)
|
||||
0, "push",
|
||||
&err)) {
|
||||
rp_error("%s", err.buf);
|
||||
strbuf_release(&err);
|
||||
|
||||
return "failed to update ref";
|
||||
ret = "failed to update ref";
|
||||
} else {
|
||||
ret = NULL; /* good */
|
||||
}
|
||||
strbuf_release(&err);
|
||||
|
||||
return NULL; /* good */
|
||||
}
|
||||
|
||||
out:
|
||||
free_worktrees(worktrees);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void run_update_post_hook(struct command *commands)
|
||||
@@ -2476,9 +2484,9 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
|
||||
argc = parse_options(argc, argv, prefix, options, receive_pack_usage, 0);
|
||||
|
||||
if (argc > 1)
|
||||
usage_msg_opt(_("Too many arguments."), receive_pack_usage, options);
|
||||
usage_msg_opt(_("too many arguments"), receive_pack_usage, options);
|
||||
if (argc == 0)
|
||||
usage_msg_opt(_("You must specify a directory."), receive_pack_usage, options);
|
||||
usage_msg_opt(_("you must specify a directory"), receive_pack_usage, options);
|
||||
|
||||
service_dir = argv[0];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user