# # # patch "cmd_policy.cc" # from [5599e7b4f42f2eef5a2246fc8e24bff25cf93667] # to [9ba12a36360c7f0169d527f7f3b62f703fbb898e] # # patch "cmd_ws_commit.cc" # from [13f57a4e64913aa994832181313cbe2a2fdf6904] # to [070f5da01ff7ecafe52637af02c59aec3adf2387] # # patch "policies/policy_branch.cc" # from [d359facea38e2d4e66e455e26ef1ae4e37c873b8] # to [148c64957fed2c05fc8ee69e2b31ec5552ae1399] # # patch "project.cc" # from [b6041bfe58f791918414f7e694d52d8ce23c9b3f] # to [2a49a114c2342a08940b658300d6b26228b5652a] # # patch "project.hh" # from [6ff3874fafcb15d1262a569e2bbeb395c907abbf] # to [abe7dd2ace5364f0ac9b16d9462e657620d1ebb3] # # patch "tests/policy-basic/__driver__.lua" # from [ae00562af87232e34683118c41515a7dc58a3eeb] # to [9394007aaed10975cc4020aaef40b09547851c2a] # ============================================================ --- cmd_policy.cc 5599e7b4f42f2eef5a2246fc8e24bff25cf93667 +++ cmd_policy.cc 9ba12a36360c7f0169d527f7f3b62f703fbb898e @@ -156,10 +156,8 @@ CMD(create_branch, "create_branch", "", parent.get_policy(ppol, origin::user); std::set admin_keys; { - key_identity_info ident; - ident.id = keys.signing_key; - project.complete_key_identity(keys, app.lua, ident); - admin_keys.insert(typecast_vocab(ident.official_name)); + string k = encode_hexenc(keys.signing_key.inner()(), origin::internal); + admin_keys.insert(external_key_name(k, origin::internal)); } branch_name suffix(branch); suffix.strip_prefix(gov.back().full_policy_name); ============================================================ --- cmd_ws_commit.cc 13f57a4e64913aa994832181313cbe2a2fdf6904 +++ cmd_ws_commit.cc 070f5da01ff7ecafe52637af02c59aec3adf2387 @@ -1119,6 +1119,11 @@ CMD(commit, "commit", "ci", CMD_REF(work workspace work(app); project_t project(db, app.lua, app.opts); + E(project.branch_exists(app.opts.branch), origin::user, + F("branch '%s' does not exist, perhaps you want 'create_branch'") + % app.opts.branch); + + utf8 log_message(""); bool log_message_given; revision_t restricted_rev; ============================================================ --- policies/policy_branch.cc d359facea38e2d4e66e455e26ef1ae4e37c873b8 +++ policies/policy_branch.cc 148c64957fed2c05fc8ee69e2b31ec5552ae1399 @@ -322,7 +322,9 @@ namespace policies { files.insert(make_pair(ident, dat)); if (dir->has_child(cx)) { - roster.set_content(dir->get_child(cx)->self, ident); + file_id current = downcast_to_file_t(dir->get_child(cx))->content; + if (current != ident) + roster.set_content(dir->get_child(cx)->self, ident); } else { ============================================================ --- project.cc b6041bfe58f791918414f7e694d52d8ce23c9b3f +++ project.cc 2a49a114c2342a08940b658300d6b26228b5652a @@ -310,7 +310,9 @@ public: walk_policies(project, policy, child_policies, tag_lister(tags)); } - branch_uid translate_branch(project_t const & project, branch_name const & name) + bool try_translate_branch(project_t const & project, + branch_name const & name, + branch_uid & uid) { L(FL("Translating branch '%s'") % name); map branch_map; @@ -318,7 +320,8 @@ public: map::const_iterator i = branch_map.find(name); if (i != branch_map.end()) { - return i->second.self.get_uid(); + uid = i->second.self.get_uid(); + return true; } L(FL("branch '%s' does not exist") % name); @@ -338,14 +341,26 @@ public: policies::delegation del = info.back().delegation; if (del.is_branch_type()) { - return del.get_branch_spec().get_uid(); + uid = del.get_branch_spec().get_uid(); + return true; } } } } - I(false); + return false; } + branch_uid translate_branch(project_t const & project, branch_name const & name) + { + branch_uid uid; + E(try_translate_branch(project, name, uid), origin::no_fault, + F("branch '%s' does not exist; please inform %s of what " + "command you ran to get this message so we can replace it with " + "a better one") + % name % PACKAGE_BUGREPORT); + return uid; + } + branch_name translate_branch(project_t const & project, branch_uid const & uid) { map branch_map; @@ -370,17 +385,23 @@ public: if (i != branch_map.end()) { uid = i->second.self.get_uid(); + L(FL("found uid '%s' for branch '%s'") % uid % name); set const & raw_signers = i->second.self.get_signers(); for (set::const_iterator k = raw_signers.begin(); k != raw_signers.end(); ++k) { id id; if (try_decode_hexenc((*k)(), id)) - signers.insert(key_id(id)); + { + L(FL("branch has signer '%s'") % *k); + signers.insert(key_id(id)); + } else { key_name kn = typecast_vocab(*k); - signers.insert(i->second.owner->get_key_id(kn)); + key_id id = i->second.owner->get_key_id(kn); + L(FL("branch has signer '%s' (%s)") % kn % id); + signers.insert(id); } } return; @@ -421,7 +442,11 @@ public: } } } - I(false); + E(false, origin::no_fault, + F("branch '%s' does not exist; please inform %s of what " + "command you ran to get this message so we can replace it with " + "a better one") + % name % PACKAGE_BUGREPORT); } void find_governing_policy(project_t const & project, @@ -817,6 +842,13 @@ project_t::get_branch_heads(branch_uid c heads = branch.second; } +bool project_t::branch_exists(branch_name const & name) const +{ + if (project_policy->passthru) + return true; + branch_uid uid; + return project_policy->try_translate_branch(*this, name, uid); +} void project_t::get_branch_heads(branch_name const & name, ============================================================ --- project.hh 6ff3874fafcb15d1262a569e2bbeb395c907abbf +++ project.hh abe7dd2ace5364f0ac9b16d9462e657620d1ebb3 @@ -156,7 +156,7 @@ public: std::multimap *inverse_graph_cache_ptr = NULL) const; - + bool branch_exists(branch_name const & name) const; void get_branch_heads(branch_name const & name, std::set & heads, bool ignore_suspend_certs, ============================================================ --- tests/policy-basic/__driver__.lua ae00562af87232e34683118c41515a7dc58a3eeb +++ tests/policy-basic/__driver__.lua 9394007aaed10975cc4020aaef40b09547851c2a @@ -1,6 +1,61 @@ mtn_setup() -- very basic policy branch test mtn_setup() +function policy_base() + chdir("checkout") + local base = base_revision() + chdir("..") + return base +end +function policy_ci(good) + chdir("checkout") + if good then + check(mtn("commit", "-btest_project.__policy__", "-mgood"), + 0, false, false) + else + check(mtn("commit", "-btest_project.__policy__", "-mbad", "address@hidden"), + 0, false, false) + end + local base = base_revision() + chdir("..") + return base +end +function policy_add(file, contents, good) + chdir("checkout") + addfile(file, contents) + chdir("..") + return policy_ci(good) +end +function policy_mv(from, to, good) + chdir("checkout") + check(mtn("mv", from, to), 0, false, false) + chdir("..") + policy_ci(good) +end +function policy_edit(file, contents, good) + chdir("checkout") + writefile(file, contents) + chdir("..") + return policy_ci(good) +end +function policy_up(revid) + chdir("checkout") + if revid == nil then + check(mtn("up"), 0, false, false) + else + check(mtn("up", "-r", revid), 0, false, false) + end + chdir("..") +end + +dat = 0 +function do_commit(res) + dat = dat + 1 + writefile("the_file", dat) + check(mtn("ci", "-mx", "-btest_project.test_branch"), res, false, false) +end + +-- setup the key and policy check(mtn("genkey", "address@hidden"), 0, false, false, "address@hidden@test.net\n") @@ -12,65 +67,77 @@ check(mtn("checkout", "checkout", "--bra check(mtn("create_branch", "test_project.test_branch"), 0, nil, false) check(mtn("checkout", "checkout", "--branch=test_project.__policy__"), 0) -chdir("checkout") +policy_root = policy_base() -addfile("file0", "data0") -check(mtn("ci", "-mbase", "--branch=test_project.__policy__"), 0, false, false) +-- other setup +addfile("the_file", 0) -base=base_revision() -addfile("file1", "data1") -check(mtn("ci", "-mgood", "--branch=test_project.__policy__"), 0, false, false) -check(mtn("update", "-r", base), 0, false, false) -addfile("file2", "data2") -check(mtn("commit", "-mbad", "address@hidden", - "--branch=test_project.__policy__"), 0, false, false) +-- commit good and bad policy children which conflict +policy_up(policy_root) +good_side = policy_add("file1", "good_data", true) +policy_up(policy_root) +bad_size = policy_add("file1", "bad_data", false) --- the second commit should be ignored -check(mtn("merge", "--branch=test_project.__policy__"), 0, false, true) -check(qgrep("already merged", "stderr")) +-- the bad commit should be ignored +check(mtn("heads", "-btest_project.__policy__"), 0, true, true) +check(qgrep("currently merged", "stderr")) +-- and should not interfere with other work +do_commit(0) -chdir("..") -addfile("branch_file", "datadatadata") -commit("test_project.test_branch", "hackhackhack") -chdir("checkout") -check(mtn("update", "-r", base), 0, false, false) -addfile("file3", "data3") -commit("test_project.__policy__", "twogood") +-- commit another good policy child, which does not conflict +policy_up(policy_root) +good_side_2 = policy_add("file2", "other_good_data", true) --- Can't do stuff now, because the policy branch has two heads. -chdir("..") -addfile("otherfile", "otherdata") -check(mtn("ci", "--branch=test_project.test_branch", "-mx"), 1) -check(mtn("heads", "--branch=test_project.test_branch"), 1) +--this is not ignored, but does not cause issues +check(mtn("heads", "-btest_project.__policy__"), 0, true, true) +check(not qgrep("currently merged", "stderr")) +check(qgrep(good_side, "stdout")) +check(qgrep(good_side_2, "stdout")) +do_commit(0) --- but can do stuff with the --policy-revision option -check(mtn("ci", "-mcommit", "--branch=test_project.test_branch", - "--policy-revision=test_project@" .. base), 0, false, false) -chdir("checkout") +-- changing the policy should merge the heads +check(mtn("create_branch", "test_project.junk_branch"), 0, nil, false) +policy_up() +merged_good = policy_base() +check(mtn("heads", "-btest_project.__policy__"), 0, true, true) +check(qgrep("currently merged", "stderr")) +check(qgrep(merged_good, "stdout")) --- check that we can recover from this -check(mtn("merge", "--branch=test_project.__policy__"), 0, false, false) -check(mtn("update", "-r", base), 0, false, false) -check(mtn("up"), 0, false, false) -check(base ~= base_revision()) +-- commit good unmergeable policy heads +left = policy_add("forkfile", "foo", true) +policy_up(merged_good) +right = policy_add("forkfile", "bar", true) -chdir("..") -addfile("foo", "bar") -commit("test_project.test_branch") -tip = base_revision() +--this is not ignored, and does cause issues +check(mtn("heads", "-btest_project.__policy__"), 0, true, true) +check(not qgrep("currently merged", "stderr")) +check(qgrep(left, "stdout")) +check(qgrep(right, "stdout")) +do_commit(1) -chdir("checkout") +-- but, we can get around it with --policy-revision +check(mtn("ci", "-mx", "-btest_project.test_branch", + "--policy-revision=test_project@"..merged_good), 0, nil, false) --- check that we can delegate using a revision id -mkdir("delegations") -addfile("delegations/tp", "revision_id [" .. base .. "]"); -check(mtn("ci", "-mx", "--branch=test_project.__policy__"), 0, false, false) +-- we can also manually merge the policy and have it work +policy_mv("forkfile", "trash", true) +check(mtn("merge", "-btest_project.__policy__"), 0, true, true) +check(mtn("heads", "-btest_project.__policy__"), 0, true, true) +check(qgrep("currently merged", "stderr")) +do_commit(0) + + +-- check that delegation by revid works +policy_add("delegations/tp", "revision_id ["..merged_good.."]\n", true) + +tip = base_revision() check(mtn("heads", "--branch=test_project.tp.test_branch"), 0, true, false) check(qgrep(tip, "stdout"), 0, false, false) +