commit 916f288c7e2f6e7bcc2643b8287a4b32f518899f from: Stefan Sperling date: Tue Jul 30 09:30:20 2019 UTC prevent 'got commit' on branches outside "refs/heads/" (the only exception is the work tree's temporary histedit branch) commit - fe307c9bac71d85284c7cee8abb80b52a253710b commit + 916f288c7e2f6e7bcc2643b8287a4b32f518899f blob - 3412f52f18e3f4bef7e8088a1711149e0abef66f blob + fb33529afb444edbcd9f9cd91ad331cf2f45bb1b --- got/got.1 +++ got/got.1 @@ -522,6 +522,9 @@ opens a temporary file in an editor where a log messag .Pp .Cm got commit will refuse to run if certain preconditions are not met. +If the work tree's current branch is not in the +.Dq refs/heads/ +reference namespace, new commits may not be created on this branch. Local changes may only be committed if they are based on file content found in the most recent commit on the work tree's branch. If a path is found to be out of date, blob - dc2cda4ba6b716c5e52b8ec10832a3d71942076e blob + 7c2acecdb74e15acbad569de791032d408e06416 --- got/got.c +++ got/got.c @@ -3228,7 +3228,7 @@ cmd_commit(int argc, char *argv[]) const char *got_author = getenv("GOT_AUTHOR"); struct collect_commit_logmsg_arg cl_arg; char *editor = NULL; - int ch, rebase_in_progress; + int ch, rebase_in_progress, histedit_in_progress; struct got_pathlist_head paths; TAILQ_INIT(&paths); @@ -3275,6 +3275,11 @@ cmd_commit(int argc, char *argv[]) goto done; } + error = got_worktree_histedit_in_progress(&histedit_in_progress, + worktree); + if (error) + goto done; + error = get_worktree_paths_from_argv(&paths, argc, argv, worktree); if (error) goto done; @@ -3299,10 +3304,13 @@ cmd_commit(int argc, char *argv[]) cl_arg.cmdline_log = logmsg; cl_arg.worktree_path = got_worktree_get_root_path(worktree); cl_arg.branch_name = got_worktree_get_head_ref_name(worktree); - if (strncmp(cl_arg.branch_name, "refs/", 5) == 0) - cl_arg.branch_name += 5; - if (strncmp(cl_arg.branch_name, "heads/", 6) == 0) - cl_arg.branch_name += 6; + if (!histedit_in_progress) { + if (strncmp(cl_arg.branch_name, "refs/heads/", 11) != 0) { + error = got_error(GOT_ERR_COMMIT_BRANCH); + goto done; + } + cl_arg.branch_name += 11; + } cl_arg.repo_path = got_repo_get_path(repo); cl_arg.logmsg_path = NULL; error = got_worktree_commit(&id, worktree, &paths, got_author, NULL, blob - 37595c5216a30ac7f817772e3493b9b38e9fa5c7 blob + f37c253a3149dc63c7b93bf00c1c3f5906eddc30 --- include/got_error.h +++ include/got_error.h @@ -113,6 +113,7 @@ #define GOT_ERR_HISTEDIT_CMD 97 #define GOT_ERR_HISTEDIT_PATH 98 #define GOT_ERR_NO_MERGED_PATHS 99 +#define GOT_ERR_COMMIT_BRANCH 100 static const struct got_error { int code; @@ -227,6 +228,8 @@ static const struct got_error { { GOT_ERR_HISTEDIT_PATH, "cannot edit branch history which contains " "changes outside of this work tree's path prefix" }, { GOT_ERR_NO_MERGED_PATHS, "empty list of merged paths" }, + { GOT_ERR_COMMIT_BRANCH, "will not commit to a branch outside the " + "\"refs/heads/\" reference namespace" }, }; /* blob - 579f23ddfca6faf4a1e9709eecf9394ab27b2f18 blob + 55bad574818603f55ad63de1e59ea2d528baa75d --- regress/cmdline/commit.sh +++ regress/cmdline/commit.sh @@ -471,6 +471,52 @@ function test_commit_selected_paths { test_done "$testroot" "$ret" } +function test_commit_outside_refs_heads { + local testroot=`test_init commit_outside_refs_heads` + + got ref -r $testroot/repo refs/remotes/origin/master master + + got checkout -b refs/remotes/origin/master \ + $testroot/repo $testroot/wt > /dev/null + ret="$?" + if [ "$ret" != "0" ]; then + test_done "$testroot" "$ret" + return 1 + fi + + echo "modified alpha" > $testroot/wt/alpha + + (cd $testroot/wt && got commit -m 'change alpha' \ + > $testroot/stdout 2> $testroot/stderr) + ret="$?" + if [ "$ret" == "0" ]; then + echo "commit succeeded unexpectedly" >&2 + test_done "$testroot" "1" + return 1 + fi + + echo -n > $testroot/stdout.expected + cmp -s $testroot/stdout.expected $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + echo -n "got: will not commit to a branch outside the " \ + > $testroot/stderr.expected + echo '"refs/heads/" reference namespace' \ + >> $testroot/stderr.expected + cmp -s $testroot/stderr.expected $testroot/stderr + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stderr.expected $testroot/stderr + fi + test_done "$testroot" "$ret" +} + + run_test test_commit_basic run_test test_commit_new_subdir run_test test_commit_subdir @@ -483,3 +529,4 @@ run_test test_commit_added_and_modified_in_same_dir run_test test_commit_path_prefix run_test test_commit_dir_path run_test test_commit_selected_paths +run_test test_commit_outside_refs_heads