# # # delete "tests/db_kill_branch_certs_locally_command" # # delete "tests/db_kill_branch_certs_locally_command/__driver__.lua" # # delete "tests/db_kill_tag_locally" # # delete "tests/db_kill_tag_locally/__driver__.lua" # # add_dir "tests/db_kill_certs_locally" # # add_file "tests/db_kill_certs_locally/__driver__.lua" # content [23e4a6565a97a0882eb001fba64c2a7c4fc07073] # # patch "cmd_db.cc" # from [0875bc8882c861722b83089736d55d53469fa0c7] # to [817d6efef439b40502eec5b8d7adc678758e032d] # # patch "cmd_key_cert.cc" # from [a411628241629ecb7dcfbc490502701b62a63321] # to [ce2c4a9003657ab329cfd61894ac09f78b2b4f28] # # patch "database.cc" # from [0bc6ce7bb27323c3724ee95f099985a3abad21f3] # to [15e02283dd92688ab83eee556e4b8b0eb5500554] # # patch "database.hh" # from [5d4aef04a21ec365ba5aa77082d0dd83d915aaef] # to [137101a2c4ac6255f11286362dbc1a64507c8719] # # patch "tests/cert_no_branch/__driver__.lua" # from [1d92c8fbb7e211bd844e462d21ba72d853af4199] # to [1ff1912c0631df6a123e3d2178b83beba91cfb9f] # # patch "tests/update_to_off-branch_rev/__driver__.lua" # from [09660e5a0d63ff6671afc6a288be58071beecd2e] # to [1527c638c97122225cffa06b84effc5c7abf81cb] # ============================================================ --- tests/db_kill_certs_locally/__driver__.lua 23e4a6565a97a0882eb001fba64c2a7c4fc07073 +++ tests/db_kill_certs_locally/__driver__.lua 23e4a6565a97a0882eb001fba64c2a7c4fc07073 @@ -0,0 +1,52 @@ +mtn_setup() + +do + local num = 0 + function commit_one(branch) + num = num + 1 + addfile("file_" .. num, num) + commit(branch) + return base_revision() + end +end + +-- rename a branch + +rev1 = commit_one("somebranch") +rev2 = commit_one("somebranch") +rev3 = commit_one("testbranch") + +check(mtn("ls", "branches"), 0, true) +check(qgrep("somebranch", "stdout")) +check(qgrep("testbranch", "stdout")) + +check(mtn("cert", "b:somebranch", "branch", "otherbranch"), 0, nil, false) + +check(mtn("ls", "branches"), 0, true) +check(qgrep("somebranch", "stdout")) +check(qgrep("otherbranch", "stdout")) +check(qgrep("testbranch", "stdout")) + +check(mtn("heads", "-b", "otherbranch"), 0, true, false) +check(qgrep(rev2, "stdout")) + +check(mtn("db", "kill_certs_locally", "i:", "branch", "somebranch"), 0, nil, false) + +check(mtn("ls", "branches"), 0, true) +check(not qgrep("somebranch", "stdout")) +check(qgrep("otherbranch", "stdout")) +check(qgrep("testbranch", "stdout")) + + +-- delete some tags + +check(mtn("ls", "tags")) +check(mtn("tag", rev1, "sometag")) +check(mtn("tag", rev2, "sometag")) + +check(mtn("ls", "tags"), 0, true) +check(qgrep(rev1:sub(0,10), "stdout")) +check(qgrep(rev2:sub(0,10), "stdout")) + +check(mtn("db", "kill_certs_locally", "t:*", "tag"), 0, nil, false) +check(mtn("ls", "tags")) ============================================================ --- cmd_db.cc 0875bc8882c861722b83089736d55d53469fa0c7 +++ cmd_db.cc 817d6efef439b40502eec5b8d7adc678758e032d @@ -9,6 +9,7 @@ #include "base.hh" #include +#include #include #include "charset.hh" @@ -239,29 +240,50 @@ CMD(db_kill_rev_locally, "kill_rev_local db.delete_existing_rev_and_certs(revid); } -CMD(db_kill_branch_certs_locally, "kill_branch_certs_locally", "", CMD_REF(db), - "BRANCH", - N_("Kills branch certificates from the local database"), - "", - options::opts::none) +CMD(db_kill_certs_locally, "kill_certs_locally", "", CMD_REF(db), + "SELECTOR CERTNAME [CERTVAL]", + N_("Deletes the specified certs from the local database"), + N_("Deletes all certs which are on the given revision(s) and " + "have the given name and if a value is specified then also " + "the given value"), + options::opts::revision) { - if (args.size() != 1) + if (args.size() < 2 || args.size() > 3) throw usage(execid); + string selector = idx(args,0)(); + cert_name name = typecast_vocab(idx(args,1)); + database db(app); - db.delete_branch_named(typecast_vocab(idx(args, 0))); -} + project_t project(db); -CMD(db_kill_tag_locally, "kill_tag_locally", "", CMD_REF(db), "TAG", - N_("Kills a tag from the local database"), - "", - options::opts::none) -{ - if (args.size() != 1) - throw usage(execid); + set revisions; + complete(app.opts, app.lua, project, selector, revisions); - database db(app); - db.delete_tag_named(typecast_vocab(idx(args, 0))); + + transaction_guard guard(db); + if (args.size() == 2) + { + L(FL("deleting all certs named '%s' on %d revisions") + % name % revisions.size()); + for (set::const_iterator r = revisions.begin(); + r != revisions.end(); ++r) + { + db.delete_certs_locally(*r, name); + } + } + else + { + cert_value value = typecast_vocab(idx(args,2)); + L(FL("deleting all certs with name '%s' and value '%s' on %d revisions") + % name % value % revisions.size()); + for (set::const_iterator r = revisions.begin(); + r != revisions.end(); ++r) + { + db.delete_certs_locally(*r, name, value); + } + } + guard.commit(); } CMD(db_check, "check", "", CMD_REF(db), "", ============================================================ --- cmd_key_cert.cc a411628241629ecb7dcfbc490502701b62a63321 +++ cmd_key_cert.cc ce2c4a9003657ab329cfd61894ac09f78b2b4f28 @@ -174,9 +174,10 @@ CMD(cert, "cert", "", CMD_REF(key_and_ce } CMD(cert, "cert", "", CMD_REF(key_and_cert), - N_("REVISION CERTNAME [CERTVAL]"), - N_("Creates a certificate for a revision"), - "", + N_("SELECTOR CERTNAME [CERTVAL]"), + N_("Creates a certificate for a revision or set of revisions"), + N_("Creates a certificate with the given name and value on each revision " + "that matches the given selector"), options::opts::none) { database db(app); @@ -188,8 +189,8 @@ CMD(cert, "cert", "", CMD_REF(key_and_ce transaction_guard guard(db); - revision_id rid; - complete(app.opts, app.lua, project, idx(args, 0)(), rid); + set revisions; + complete(app.opts, app.lua, project, idx(args, 0)(), revisions); cert_name cname = typecast_vocab(idx(args, 1)); @@ -204,8 +205,11 @@ CMD(cert, "cert", "", CMD_REF(key_and_ce read_data_stdin(dat); val = typecast_vocab(dat); } - - project.put_cert(keys, rid, cname, val); + for (set::const_iterator r = revisions.begin(); + r != revisions.end(); ++r) + { + project.put_cert(keys, *r, cname, val); + } guard.commit(); } ============================================================ --- database.cc 0bc6ce7bb27323c3724ee95f099985a3abad21f3 +++ database.cc 15e02283dd92688ab83eee556e4b8b0eb5500554 @@ -3103,28 +3103,18 @@ database::recalc_branch_leaves(cert_valu } } -/// Deletes all certs referring to a particular branch. -void -database::delete_branch_named(cert_value const & branch) +void database::delete_certs_locally(revision_id const & rev, + cert_name const & name) { - L(FL("Deleting all references to branch %s") % branch); - imp->execute(query("DELETE FROM revision_certs WHERE name='branch' AND value =?") - % blob(branch())); - imp->execute(query("DELETE FROM branch_leaves WHERE branch = ?") - % blob(branch())); - imp->cert_stamper.note_change(); - imp->execute(query("DELETE FROM branch_epochs WHERE branch=?") - % blob(branch())); + imp->execute(query("DELETE FROM revision_certs WHERE revision_id = ? AND name = ?") + % blob(rev.inner()()) % text(name())); } - -/// Deletes all certs referring to a particular tag. -void -database::delete_tag_named(cert_value const & tag) +void database::delete_certs_locally(revision_id const & rev, + cert_name const & name, + cert_value const & value) { - L(FL("Deleting all references to tag %s") % tag); - imp->execute(query("DELETE FROM revision_certs WHERE name='tag' AND value =?") - % blob(tag())); - imp->cert_stamper.note_change(); + imp->execute(query("DELETE FROM revision_certs WHERE revision_id = ? AND name = ? AND value = ?") + % blob(rev.inner()()) % text(name()) % blob(value())); } // crypto key management ============================================================ --- database.hh 5d4aef04a21ec365ba5aa77082d0dd83d915aaef +++ database.hh 137101a2c4ac6255f11286362dbc1a64507c8719 @@ -432,10 +432,12 @@ public: void fix_bad_certs(bool drop_not_fixable); // for kill_rev_locally: void delete_existing_rev_and_certs(revision_id const & rid); - // for kill_branch_certs_locally: - void delete_branch_named(cert_value const & branch); - // for kill_tag_locally: - void delete_tag_named(cert_value const & tag); + // for kill_certs_locally: + void delete_certs_locally(revision_id const & rev, + cert_name const & name); + void delete_certs_locally(revision_id const & rev, + cert_name const & name, + cert_value const & value); public: // branches ============================================================ --- tests/cert_no_branch/__driver__.lua 1d92c8fbb7e211bd844e462d21ba72d853af4199 +++ tests/cert_no_branch/__driver__.lua 1ff1912c0631df6a123e3d2178b83beba91cfb9f @@ -10,7 +10,7 @@ rev = base_revision() rev = base_revision() -- delete the branch cert from the revision -check(mtn("db", "kill_branch_certs_locally", "testbranch"), 0, false, false) +check(mtn("db", "kill_certs_locally", rev, "branch", "testbranch"), 0, false, false) -- ensure we don't find a branch option remove("_MTN") ============================================================ --- tests/update_to_off-branch_rev/__driver__.lua 09660e5a0d63ff6671afc6a288be58071beecd2e +++ tests/update_to_off-branch_rev/__driver__.lua 1527c638c97122225cffa06b84effc5c7abf81cb @@ -18,7 +18,7 @@ revs.n = base_revision() writefile("testfile", "double double") commit("nobranch") revs.n = base_revision() -check(mtn("db", "kill_branch_certs_locally", "nobranch")) +check(mtn("db", "kill_certs_locally", "i:", "branch", "nobranch"), 0, nil, false) check(mtn("checkout", "--branch=testbranch", "--revision", revs.t, "codir"), 0, false, false) check(grep('^ *branch "testbranch"', "codir/_MTN/options"), 0, false, false)