# # # add_file "branch_name.cc" # content [288529d51201f24a6dd1ea352defc66befb2b304] # # add_file "branch_name.hh" # content [751f519e79515bf9ec5e1172f418af9c34a83acb] # # patch "Makefile.am" # from [a1c9004e8f1f6471a1782204ace485b42face6b5] # to [946b1ee0318dde6676b4e619488fffe6caf01067] # # patch "cert.hh" # from [6de8a02eb770625c1dfba467a931058f740bac0f] # to [9d0811e4460bcb08264babe5171b2cf310ea83be] # # patch "cmd_policy.cc" # from [bd8d8bddfa2e6fa840bafe44732b4cf00e7c440b] # to [12ab8bee009b15977984a06d63f9b875a5b10b66] # # patch "editable_policy.cc" # from [3545edd983f18f4c77385297b4d3dd504e54534d] # to [fbbf12bf1b3bf07a6148fd9f5ef9a7981e4d776a] # # patch "editable_policy.hh" # from [a49c2cc57a5404f185f07bee9146ad39cc9c7e6e] # to [4ec915784541263f8dc823826d7dd28af1cdcb20] # # patch "lua_hooks.hh" # from [a7595133ffd4347f983d86411d1ca2076a49a0b9] # to [91db152b519bef0ec55c023fa28a6018d80199b6] # # patch "options.hh" # from [c3d069fcf7845b6e8cf8a2819d73e98c69aaee8b] # to [d0cbcfd434b9bcf5a97c592b4a711ecb51e5a7fa] # # patch "options_list.hh" # from [468dbcbd8c5a75bce502c11b4f6e5f5fd798957e] # to [4ad99d6da1771dc3b31fa2f94c1084fe4702c356] # # patch "policy.cc" # from [48d32a6adb58c25296fc25688a6c6f9e18bfb87f] # to [89987029ecec54fb9f5fa4e30c6c44b249fe3e10] # # patch "policy.hh" # from [e1f8fbf5b500089012a4de045742fbc9a1620437] # to [18aaebbe4df42d9a4f3446f7a5ac0404947ea89c] # # patch "project.cc" # from [319b71ee6f05f67d52deb90870b6753f3ca07442] # to [765971106387dbf944b79a1e3c2698366cb82de3] # # patch "project.hh" # from [fa7c27b6f3d64d5d47985123ec5ea2bc66cf4184] # to [11a4e111004808faec2e5c48f10b8e6598c68de4] # # patch "vocab_terms.hh" # from [d9280226ff11880a60d45693e4191b399fb804b7] # to [c350da1cd3e0e1a3ab46c09631581a24e695c4e5] # ============================================================ --- branch_name.cc 288529d51201f24a6dd1ea352defc66befb2b304 +++ branch_name.cc 288529d51201f24a6dd1ea352defc66befb2b304 @@ -0,0 +1,86 @@ +#include "base.hh" +#include "branch_name.hh" + +using std::string; + +branch_name::branch_name() + : matches_prefix(false) +{ } + +branch_name::branch_name(string const & s) + : data(s), matches_prefix(false) +{ } + +string +branch_name::operator()() const +{ return data; } + +string::size_type +branch_name::size() const +{ return data.size(); } + +bool +branch_name::has_prefix(branch_name const & pre) const +{ + if (data.size() == pre.data.size()) + return data == pre.data; + else if (data.size() > pre.data.size()) + return data.substr(0, pre.data.size()) == pre.data + && data[pre.data.size()] == '.'; + else + return false; +} + +bool +branch_name::strip_prefix(branch_name const & pre) +{ + if (!has_prefix(pre)) + return false; + + if (data.size() == pre.data.size()) + data.clear(); + else + data.erase(0, pre.data.size() + 1); + return true; +} + +void +branch_name::prepend(branch_name const & pre) +{ + data = pre.data + "." + data; +} + +void +branch_name::append(branch_name const & post) +{ + data += "."; + data += post.data; +} + +bool +operator < (branch_name const & lhs, + branch_name const & rhs) +{ + return lhs != rhs && lhs.data < rhs.data; +} +bool +operator == (branch_name const & lhs, + branch_name const & rhs) +{ + if (lhs.matches_prefix && lhs.has_prefix(rhs)) + return true; + if (rhs.matches_prefix && rhs.has_prefix(lhs)) + return true; + return rhs.data == lhs.data; +} + +std::ostream & +operator << (std::ostream & s, branch_name const & b) +{ + return s << b(); +} + +template <> void dump(branch_name const & obj, string & out) +{ + out = obj(); +} ============================================================ --- branch_name.hh 751f519e79515bf9ec5e1172f418af9c34a83acb +++ branch_name.hh 751f519e79515bf9ec5e1172f418af9c34a83acb @@ -0,0 +1,51 @@ +#ifndef __BRANCH_NAME_HH__ +#define __BRANCH_NAME_HH__ + +class branch_name; + +bool operator < (branch_name const & lhs, + branch_name const & rhs); + +bool operator == (branch_name const & lhs, + branch_name const & rhs); + +inline bool operator > (branch_name const & lhs, + branch_name const & rhs) +{ return rhs < lhs; } + +inline bool operator != (branch_name const & lhs, + branch_name const & rhs) +{ return !(lhs == rhs); } + + +class branch_name +{ + friend bool operator < (branch_name const & lhs, + branch_name const & rhs); + + friend bool operator == (branch_name const & lhs, + branch_name const & rhs); + + std::string data; +public: + bool matches_prefix; + + branch_name(); + explicit branch_name(std::string const & s); + std::string operator()() const; + + std::string::size_type size() const; + + // note that a branch name is a prefix of itself + bool has_prefix(branch_name const & pre) const; + bool strip_prefix(branch_name const & pre); + + void prepend(branch_name const & pre); + void append(branch_name const & post); +}; + +std::ostream & operator << (std::ostream & s, branch_name const & b); + +template<> void dump(branch_name const & obj, std::string & out); + +#endif ============================================================ --- Makefile.am a1c9004e8f1f6471a1782204ace485b42face6b5 +++ Makefile.am 946b1ee0318dde6676b4e619488fffe6caf01067 @@ -26,6 +26,7 @@ MOST_SOURCES = \ $(SANITY_CORE_SOURCES) $(LUAEXT_SOURCES) platform-wrapped.hh \ rev_types.hh mtn-sanity.cc mtn-sanity.hh ui.cc ui.hh \ app_state.cc app_state.hh \ + branch_name.cc branch_name.hh \ botan_pipe_cache.hh \ commands.cc commands.hh $(CMD_SOURCES) \ diff_patch.cc diff_patch.hh \ ============================================================ --- cert.hh 6de8a02eb770625c1dfba467a931058f740bac0f +++ cert.hh 9d0811e4460bcb08264babe5171b2cf310ea83be @@ -14,6 +14,7 @@ #include #include "vector.hh" +#include "branch_name.hh" #include "vocab.hh" #include "dates.hh" ============================================================ --- cmd_policy.cc bd8d8bddfa2e6fa840bafe44732b4cf00e7c440b +++ cmd_policy.cc 12ab8bee009b15977984a06d63f9b875a5b10b66 @@ -59,7 +59,7 @@ CMD(create_project, "create_project", "" data policy_spec; editable_policy ep(db, admin_keys); ep.get_branch("__policy__")->write(policy_spec); - ep.commit(keys, app.lua, utf8(N_("Create new policy branch"))); + ep.commit(keys, utf8(N_("Create new policy branch"))); write_data(project_file, policy_spec, project_dir); P(F("Wrote project spec to %s") % project_file); @@ -77,12 +77,12 @@ CMD(create_subpolicy, "create_subpolicy" database db(app); key_store keys(app); project_t project(db, app.lua, app.opts); - branch_prefix prefix(idx(args, 0)()); + branch_name prefix(idx(args, 0)()); branch_name name(prefix() + ".__policy__"); - branch_policy policy_policy; - branch_prefix parent_prefix; - E(project.get_policy_branch_policy_of(name, policy_policy, parent_prefix), + editable_policy parent; + branch_name parent_prefix; + E(project.get_policy_branch_policy_of(name, parent, parent_prefix), F("Cannot find parent policy for %s") % prefix); P(F("Parent policy: %s") % parent_prefix); @@ -97,7 +97,6 @@ CMD(create_subpolicy, "create_subpolicy" admin_keys.insert(keys.signing_key); - editable_policy parent(db, policy_policy); editable_policy child(db, admin_keys); shared_ptr del = parent.get_delegation(subprefix, true); @@ -105,8 +104,8 @@ CMD(create_subpolicy, "create_subpolicy" del->committers = admin_keys; transaction_guard guard(db); - child.commit(keys, app.lua, utf8(N_("Create new policy branch"))); - parent.commit(keys, app.lua, utf8(N_("Add new delegation"))); + child.commit(keys, utf8(N_("Create new policy branch"))); + parent.commit(keys, utf8(N_("Add new delegation"))); guard.commit(); } @@ -125,9 +124,9 @@ CMD(create_branch, "create_branch", "", project_t project(db, app.lua, app.opts); branch_name branch(idx(args, 0)()); - branch_policy parent_policy; - branch_prefix parent_prefix; - E(project.get_policy_branch_policy_of(branch, parent_policy, parent_prefix), + editable_policy parent; + branch_name parent_prefix; + E(project.get_policy_branch_policy_of(branch, parent, parent_prefix), F("Cannot find a parent policy for %s") % branch); P(F("Parent policy: %s") % parent_prefix); @@ -143,26 +142,25 @@ CMD(create_branch, "create_branch", "", admin_keys.insert(keys.signing_key); - editable_policy parent(db, parent_policy); shared_ptr br = parent.get_branch(relative_name); N(!br, F("A branch %s already exists under policy %s") % relative_name % parent_prefix); br = parent.get_branch(relative_name, true); - parent.commit(keys, app.lua, utf8(N_("Declare new branch"))); + parent.commit(keys, utf8(N_("Declare new branch"))); } CMD_FWD_DECL(list); -void list_policy(project_t const & proj, branch_prefix const & prefix, bool recursive) +void list_policy(project_t const & proj, branch_name const & prefix, bool recursive) { std::cout< subpolicies; + std::set subpolicies; proj.get_subpolicies(prefix, subpolicies); - for (std::set::const_iterator i = subpolicies.begin(); + for (std::set::const_iterator i = subpolicies.begin(); i != subpolicies.end(); ++i) { list_policy(proj, *i, recursive); @@ -183,9 +181,9 @@ CMD(policies, "policies", "", CMD_REF(li if (args.empty()) { - std::set subpolicies; - project.get_subpolicies(branch_prefix(), subpolicies); - for (std::set::const_iterator i = subpolicies.begin(); + std::set subpolicies; + project.get_subpolicies(branch_name(), subpolicies); + for (std::set::const_iterator i = subpolicies.begin(); i != subpolicies.end(); ++i) { list_policy(project, *i, app.opts.recursive); @@ -197,7 +195,7 @@ CMD(policies, "policies", "", CMD_REF(li i != args.end(); ++i) { branch_name const bn((*i)()); - branch_prefix const bp((*i)()); + branch_name const bp((*i)()); N(project.policy_exists(bp), F("Policy %s does not exist.") % *i); list_policy(project, bp, app.opts.recursive); ============================================================ --- editable_policy.cc 3545edd983f18f4c77385297b4d3dd504e54534d +++ editable_policy.cc fbbf12bf1b3bf07a6148fd9f5ef9a7981e4d776a @@ -112,6 +112,34 @@ public: editable_policy_impl(database & db) : db(db) {} + editable_policy_impl(editable_policy_impl const & other) + : db(other.db), old_rev_id(other.old_rev_id), + old_roster(other.old_roster), + files(other.files), + new_revision(other.new_revision) + { + for (tag_holder::container::const_iterator i = other.tags.begin(); + i != other.tags.end(); ++i) + { + tag_holder::info_type x = *i; + x.new_value.reset(new editable_policy::tag(*x.new_value)); + tags.insert(x); + } + for (branch_holder::container::const_iterator i = other.branches.begin(); + i != other.branches.end(); ++i) + { + branch_holder::info_type x = *i; + x.new_value.reset(new editable_policy::branch(*x.new_value)); + branches.insert(x); + } + for (delegation_holder::container::const_iterator i = other.delegations.begin(); + i != other.delegations.end(); ++i) + { + delegation_holder::info_type x = *i; + x.new_value.reset(new editable_policy::delegation(*x.new_value)); + delegations.insert(x); + } + } revision_id old_rev_id; roster_t old_roster; @@ -186,9 +214,51 @@ editable_policy::editable_policy(databas revision_id const & rev) : impl(new editable_policy_impl(db)) { + init(rev); +} + +editable_policy::editable_policy(database & db, + branch_policy const & policy_policy) + : impl(new editable_policy_impl(db)) +{ + branch br; + br.uid = policy_policy.branch_cert_value; + br.committers = policy_policy.committers; + init(br); +} + +editable_policy::editable_policy(database & db, + editable_policy::delegation const & del) + : impl(new editable_policy_impl(db)) +{ + branch br; + br.uid = del.uid; + br.committers = del.committers; + init(br); +} + +editable_policy::editable_policy() +{ } + +editable_policy::editable_policy(editable_policy const & other) + : impl(new editable_policy_impl(*other.impl)), uid(other.uid) +{ +} + +editable_policy const & +editable_policy::operator = (editable_policy const & other) +{ + impl.reset(new editable_policy_impl(*other.impl)); + uid = other.uid; + return *this; +} + +void +editable_policy::init(revision_id const & rev) +{ vector > certs; impl->db.get_revision_certs(rev, branch_cert_name, certs); - erase_bogus_certs(db, certs); + erase_bogus_certs(impl->db, certs); if (certs.size() == 1) { uid = branch_uid(idx(certs,0).inner().value()); @@ -199,16 +269,14 @@ editable_policy::editable_policy(databas load_policy(impl); } -editable_policy::editable_policy(database & db, - branch_policy const & policy_policy) - : impl(new editable_policy_impl(db)) +void +editable_policy::init(editable_policy::branch const & br) { - uid = policy_policy.branch_cert_value; + uid = br.uid; set heads; - get_branch_heads(policy_policy, false, db, heads, NULL); + get_branch_heads(br, false, impl->db, heads, NULL); E(heads.size() == 1, - F("Policy branch %s does not have exactly 1 head") - % policy_policy.branch_cert_value); + F("Policy branch %s does not have exactly 1 head") % uid); impl->old_rev_id = *heads.begin(); impl->db.get_roster(impl->old_rev_id, impl->old_roster); load_policy(impl); @@ -461,7 +529,6 @@ editable_policy::commit(key_store & keys revision_id editable_policy::commit(key_store & keys, - lua_hooks & lua, utf8 const & changelog, string author) { @@ -563,7 +630,7 @@ editable_policy::rename_tag(string const } -shared_ptr +editable_policy::delegation_t editable_policy::get_delegation(string const & name, bool create) { delegation_holder::by_current::iterator i = impl->delegations.find(name); @@ -578,7 +645,7 @@ editable_policy::get_delegation(string c return item.new_value; } -shared_ptr +editable_policy::branch_t editable_policy::get_branch(string const & name, bool create) { branch_holder::by_current::iterator i = impl->branches.find(name); @@ -593,7 +660,7 @@ editable_policy::get_branch(string const return item.new_value; } -shared_ptr +editable_policy::tag_t editable_policy::get_tag(string const & name, bool create) { tag_holder::by_current::iterator i = impl->tags.find(name); @@ -607,3 +674,76 @@ editable_policy::get_tag(string const & impl->tags.insert(item); return item.new_value; } + + +editable_policy::delegation_map +editable_policy::get_all_delegations() +{ + delegation_map ret; + for (delegation_holder::by_current::iterator i = impl->delegations.begin(); + i != impl->delegations.end(); ++i) + { + ret.insert(make_pair(i->new_name, i->new_value)); + } + return ret; +} + +editable_policy::const_delegation_map +editable_policy::get_all_delegations() const +{ + const_delegation_map ret; + for (delegation_holder::by_current::iterator i = impl->delegations.begin(); + i != impl->delegations.end(); ++i) + { + ret.insert(make_pair(i->new_name, const_delegation_t(i->new_value))); + } + return ret; +} + +editable_policy::branch_map +editable_policy::get_all_branches() +{ + branch_map ret; + for (branch_holder::by_current::iterator i = impl->branches.begin(); + i != impl->branches.end(); ++i) + { + ret.insert(make_pair(i->new_name, i->new_value)); + } + return ret; +} + +editable_policy::const_branch_map +editable_policy::get_all_branches() const +{ + const_branch_map ret; + for (branch_holder::by_current::iterator i = impl->branches.begin(); + i != impl->branches.end(); ++i) + { + ret.insert(make_pair(i->new_name, const_branch_t(i->new_value))); + } + return ret; +} + +editable_policy::tag_map +editable_policy::get_all_tags() +{ + tag_map ret; + for (tag_holder::by_current::iterator i = impl->tags.begin(); + i != impl->tags.end(); ++i) + { + ret.insert(make_pair(i->new_name, i->new_value)); + } + return ret; +} + +editable_policy::const_tag_map +editable_policy::get_all_tags() const +{ + const_tag_map ret; + for (tag_holder::by_current::iterator i = impl->tags.begin(); + i != impl->tags.end(); ++i) + { + ret.insert(make_pair(i->new_name, const_tag_t(i->new_value))); + } + return ret; +} ============================================================ --- editable_policy.hh a49c2cc57a5404f185f07bee9146ad39cc9c7e6e +++ editable_policy.hh 4ec915784541263f8dc823826d7dd28af1cdcb20 @@ -9,6 +9,7 @@ // This files defines higher-level editing operations on // policy-branch revisions. +#include #include #include @@ -33,6 +34,8 @@ public: void write(data & dat); void read(data const & dat); }; + typedef boost::shared_ptr tag_t; + typedef boost::shared_ptr const_tag_t; class branch { public: @@ -41,7 +44,9 @@ public: void write(data & dat); void read(data const & dat); }; - class delegation + typedef boost::shared_ptr branch_t; + typedef boost::shared_ptr const_branch_t; + class delegation // union { branch, revision_id } { public: revision_id rev; @@ -50,6 +55,8 @@ public: void write(data & dat); void read(data const & dat); }; + typedef boost::shared_ptr delegation_t; + typedef boost::shared_ptr const_delegation_t; // Create a new policy. editable_policy(database & db, @@ -61,9 +68,17 @@ public: // Edit an existing policy branch. This will fail if the branch // doesn't have exactly one head. editable_policy(database & db, branch_policy const & policy_policy); + editable_policy(database & db, delegation const & del); + editable_policy(); + editable_policy(editable_policy const & other); + editable_policy const & operator = (editable_policy const & other); +private: + void init(revision_id const & rev); + void init(branch const & br); +public: + revision_id commit(key_store & keys, - lua_hooks & lua, utf8 const & changelog, std::string author = ""); revision_id calculate_id(); @@ -79,14 +94,27 @@ public: void rename_tag(std::string const & from, std::string const & to); - boost::shared_ptr + delegation_t get_delegation(std::string const & name, bool create = false); - boost::shared_ptr + branch_t get_branch(std::string const & name, bool create = false); - boost::shared_ptr + tag_t get_tag(std::string const & name, bool create = false); + + typedef std::map delegation_map; + typedef std::map const_delegation_map; + delegation_map get_all_delegations(); + const_delegation_map get_all_delegations() const; + typedef std::map branch_map; + typedef std::map const_branch_map; + branch_map get_all_branches(); + const_branch_map get_all_branches() const; + typedef std::map tag_map; + typedef std::map const_tag_map; + tag_map get_all_tags(); + const_tag_map get_all_tags() const; }; #endif ============================================================ --- lua_hooks.hh a7595133ffd4347f983d86411d1ca2076a49a0b9 +++ lua_hooks.hh 91db152b519bef0ec55c023fa28a6018d80199b6 @@ -16,6 +16,7 @@ #include #include +#include "branch_name.hh" #include "file_io.hh" #include "option.hh" #include "vocab.hh" ============================================================ --- options.hh c3d069fcf7845b6e8cf8a2819d73e98c69aaee8b +++ options.hh d0cbcfd434b9bcf5a97c592b4a711ecb51e5a7fa @@ -13,6 +13,7 @@ #include +#include "branch_name.hh" #include "option.hh" #include "paths.hh" #include "dates.hh" ============================================================ --- options_list.hh 468dbcbd8c5a75bce502c11b4f6e5f5fd798957e +++ options_list.hh 4ad99d6da1771dc3b31fa2f94c1084fe4702c356 @@ -63,7 +63,7 @@ OPTION(globals, positionals, true, "--", } #endif -typedef std::map > policy_revision_arg_map; +typedef std::map > policy_revision_arg_map; GOPT(policy_revisions, "policy-revision", policy_revision_arg_map, , gettext_noop("address@hidden, use a specific policy revision")) #ifdef option_bodies @@ -71,9 +71,9 @@ GOPT(policy_revisions, "policy-revision" size_t at = arg.find('@'); if (at == std::string::npos) throw bad_arg_internal(F("no '@' found").str()); - branch_prefix bp(arg.substr(0, at)); + branch_name bn(arg.substr(0, at)); hexenc rid(arg.substr(at+1)); - policy_revisions.insert(std::make_pair(bp, rid)); + policy_revisions.insert(std::make_pair(bn, rid)); } #endif ============================================================ --- policy.cc 48d32a6adb58c25296fc25688a6c6f9e18bfb87f +++ policy.cc 89987029ecec54fb9f5fa4e30c6c44b249fe3e10 @@ -36,221 +36,113 @@ policy_branch::policy_branch(database & { } -policy_branch +shared_ptr policy_branch::empty_policy(database & db) { - return policy_branch(db); + return (new policy_branch(db))->shared_from_this(); } -policy_branch::policy_branch(data const & spec, - branch_prefix const & prefix, +policy_branch::policy_branch(editable_policy::delegation const & del, database & db) - : prefix(prefix), db(db) + : db(db), delayed(new editable_policy::delegation(del)) { - init(spec); } -shared_ptr -policy_branch::maybe_get_branch_policy(branch_name const & name) +policy_branch::policy_branch(shared_ptr pol, + database & db) + : db(db), policy(pol) { - map bm = branches(); - map::const_iterator i = bm.find(name); - if (i != bm.end()) - return shared_ptr(new branch_policy(i->second)); - else - return shared_ptr(); } -policy_branch::policy_branch(revision_id const & rid, - branch_prefix const & prefix, - database & db) - : prefix(prefix), db(db) +shared_ptr +policy_branch::create(editable_policy::delegation const & del, + database & db) { - rev.reset(new policy_revision(db, rid, prefix)); + return (new policy_branch(del, db))->shared_from_this(); } -policy_branch::policy_branch(std::map const & delegations, - branch_prefix const & my_prefix, - database & db) - : prefix(my_prefix), db(db) +shared_ptr +policy_branch::create(shared_ptr pol, + database & db) { - rev.reset(new policy_revision(delegations, db)); + return (new policy_branch(pol, db))->shared_from_this(); } -void -policy_branch::init(data const & spec) +bool +policy_branch::init() { - bool seen_revid = false; - bool seen_branchspec = false; - revision_id rev_id; + if (policy) + return true; + if (!delayed) + return false; - basic_io::input_source src(spec(), "policy spec"); - basic_io::tokenizer tok(src); - basic_io::parser pa(tok); + policy.reset(new editable_policy(db, *delayed)); + delayed.reset(); - while (pa.symp()) + editable_policy::const_delegation_map dels = policy->get_all_delegations(); + for (editable_policy::const_delegation_map::const_iterator i = dels.begin(); + i != dels.end(); ++i) { - if(pa.symp(basic_io::syms::branch_uid)) - { - seen_branchspec = true; - pa.sym(); - string branch; - pa.str(branch); - my_branch_cert_value = branch_uid(branch); - } - else if (pa.symp(basic_io::syms::committer)) - { - seen_branchspec = true; - pa.sym(); - string key; - pa.str(key); - my_committers.insert(rsa_keypair_id(key)); - } - else if (pa.symp(basic_io::syms::revision_id)) - { - seen_revid = true; - pa.sym(); - string rid; - pa.hex(rid); - rev_id = revision_id(decode_hexenc(rid)); - } - else - { - N(false, F("Unable to understand policy spec file for %s") % prefix); - } + delegations.insert(make_pair(i->first, create(*i->second, db))); } - I(src.lookahead == EOF); - - E(seen_revid || seen_branchspec, - F("Policy spec file for %s seems to be empty") % prefix); - - E(seen_revid != seen_branchspec, - F("Policy spec file for %s contains both a revision id and a branch spec") - % prefix); - - if (!null_id(rev_id)) - { - rev.reset(new policy_revision(db, rev_id, prefix)); - } + return true; } - -policy_revision::policy_revision(database & db, - revision_id const & rev, - branch_prefix const & prefix) +shared_ptr +policy_branch::get_policy() { - roster_t roster; - db.get_roster(rev, roster); + I(init()); + return policy; +} - file_path branch_dir = file_path_internal("branches"); - file_path delegation_dir = file_path_internal("delegations"); +shared_ptr +policy_branch::maybe_get_branch_policy(branch_name const & name) +{ + I(init()); + branchmap bm = branches(); + branchmap::const_iterator i = bm.find(name); + if (i != bm.end()) + return shared_ptr(new editable_policy::branch(i->second)); + else + return shared_ptr(); +} - if (roster.has_node(branch_dir)) - { - dir_t branch_node = downcast_to_dir_t(roster.get_node(branch_dir)); - for (dir_map::const_iterator i = branch_node->children.begin(); - i != branch_node->children.end(); ++i) - { - branch_name branch; - if (i->first() != "__main__") - { - branch = branch_name(prefix() + "." + i->first()); - } - else - { - branch = branch_name(prefix()); - } - file_id ident = downcast_to_file_t(i->second)->content; - file_data spec; - db.get_file_version(ident, spec); +template +class longer +{ +public: + bool operator()(T const & l, T const & r) + { + return l.size() > r.size(); + } +}; - branch_uid branch_cert_value; - set committers; - - basic_io::input_source src(spec.inner()(), "branch spec"); - basic_io::tokenizer tok(src); - basic_io::parser pa(tok); - - while (pa.symp()) - { - if (pa.symp(basic_io::syms::branch_uid)) - { - pa.sym(); - string branch; - pa.str(branch); - branch_cert_value = branch_uid(branch); - } - else if (pa.symp(basic_io::syms::committer)) - { - pa.sym(); - string key; - pa.str(key); - committers.insert(rsa_keypair_id(key)); - } - else - { - N(false, - F("Unable to understand branch spec file for %s in revision %s") - % i->first() % rev); - } - } - - branches.insert(make_pair(branch, - branch_policy(branch, - branch_cert_value, - committers))); - } - } - if (roster.has_node(delegation_dir)) +boost::shared_ptr +policy_branch::walk(branch_name target, + branch_name & result) +{ + I(init()); + typedef map, longer > match_map; + match_map matches; + for (delegation_map::const_iterator i = delegations.begin(); + i != delegations.end(); ++i) { - dir_t delegation_node = downcast_to_dir_t(roster.get_node(delegation_dir)); - for (dir_map::const_iterator i = delegation_node->children.begin(); - i != delegation_node->children.end(); ++i) - { - branch_prefix subprefix(prefix() + "." + i->first()); - file_id ident = downcast_to_file_t(i->second)->content; - file_data spec; - db.get_file_version(ident, spec); - - delegations.insert(make_pair(subprefix, - policy_branch(spec.inner(), - subprefix, - db))); - } + if (target.has_prefix(branch_name(i->first))) + { + matches.insert(*i); + } } -} - -policy_revision::policy_revision(std::map const & del, - database & db) -{ - for (std::map::const_iterator i = del.begin(); - i != del.end(); ++i) + if (matches.empty()) { - delegations.insert(std::make_pair(i->first, - policy_branch(i->second, - i->first, - db))); + return shared_from_this(); } -} - -map -policy_revision::all_branches() -{ - typedef map branch_policies; - typedef map policy_branches; - branch_policies out = branches; - for (policy_branches::iterator i = delegations.begin(); - i != delegations.end(); ++i) + else { - branch_policies del = i->second.branches(); - for (branch_policies::const_iterator i = del.begin(); - i != del.end(); ++i) - { - out.insert(*i); - } + result.append(matches.begin()->first); + target.strip_prefix(matches.begin()->first); + return matches.begin()->second->walk(target, result);; } - return out; } namespace @@ -342,19 +234,33 @@ get_branch_heads(branch_policy const & p multimap * inverse_graph_cache_ptr) { + editable_policy::branch br; + br.uid = pol.branch_cert_value; + br.committers = pol.committers; + return get_branch_heads(br, ignore_suspend_certs, db, heads, + inverse_graph_cache_ptr); +} + +outdated_indicator +get_branch_heads(editable_policy::branch const & br, + bool ignore_suspend_certs, + database & db, + std::set & heads, + multimap + * inverse_graph_cache_ptr) +{ + cert_value const certval(br.uid()); outdated_indicator ret; ret = db.get_revisions_with_cert(cert_name(branch_cert_name), - cert_value(pol.branch_cert_value()), heads); + certval, heads); - not_in_managed_branch p(db, cert_value(pol.branch_cert_value()), - pol.committers); + not_in_managed_branch p(db, certval, br.committers); erase_ancestors_and_failures(db, heads, p, inverse_graph_cache_ptr); if (!ignore_suspend_certs) { - suspended_in_managed_branch s(db, cert_value(pol.branch_cert_value()), - pol.committers); + suspended_in_managed_branch s(db, certval, br.committers); std::set::iterator it = heads.begin(); while (it != heads.end()) { @@ -377,6 +283,16 @@ revision_is_in_branch(branch_policy cons pol.committers); return !p(rid); } +bool +revision_is_in_branch(editable_policy::branch const & br, + revision_id const & rid, + database & db) +{ + not_in_managed_branch p(db, + cert_value(br.uid()), + br.committers); + return !p(rid); +} bool maybe_get_policy_branch_head(branch_uid const & name, @@ -409,78 +325,60 @@ bool maybe_get_policy_branch_head(branch } -shared_ptr policy_branch::get_policy() +policy_branch::branchmap +policy_branch::branches() { - if (!rev) - { - revision_id rid; - if (maybe_get_policy_branch_head(my_branch_cert_value, - my_committers, db, rid)) - { - rev.reset(new policy_revision(db, rid, prefix)); - } - } - return rev; + branchmap out; + branches(branch_name(), out); + return out; } -map policy_branch::branches() +void +policy_branch::branches(branch_name const & prefix, + policy_branch::branchmap & branchlist) { - shared_ptr policy = get_policy(); - if (policy) + I(init()); + editable_policy::const_branch_map br = policy->get_all_branches(); + for (editable_policy::const_branch_map::const_iterator i = br.begin(); + i != br.end(); ++i) { - return policy->all_branches(); + branch_name name = prefix; + name.append(branch_name(i->first)); + branchlist.insert(make_pair(name, *i->second)); } - else - return map(); + for (delegation_map::const_iterator i = delegations.begin(); + i != delegations.end(); ++i) + { + branch_name new_prefix = prefix; + new_prefix.append(branch_name(i->first)); + i->second->branches(new_prefix, branchlist); + } } - - -policy_revision const * -policy_branch::get_nearest_policy(branch_name const & name, - branch_policy & policy_policy, - branch_prefix & policy_prefix, - std::string const & accumulated_prefix) +policy_branch::tagmap +policy_branch::tags() { - shared_ptr policy = get_policy(); - if (!policy) - return NULL; - - policy_policy = branch_policy(branch_name(), - my_branch_cert_value, - my_committers); - return policy->get_nearest_policy(name, policy_policy, policy_prefix, - prefix()); + tagmap out; + tags(branch_name(), out); + return out; } - -policy_revision const * -policy_revision::get_nearest_policy(branch_name const & name, - branch_policy & policy_policy, - branch_prefix & policy_prefix, - std::string const & accumulated_prefix) +void +policy_branch::tags(branch_name const & prefix, + policy_branch::tagmap & taglist) { - for (std::map::iterator - i = delegations.begin(); i != delegations.end(); ++i) + I(init()); + editable_policy::const_tag_map br = policy->get_all_tags(); + for (editable_policy::const_tag_map::const_iterator i = br.begin(); + i != br.end(); ++i) { - std::string mypref(i->first()); - if (name().find(mypref) == 0) - { - return i->second.get_nearest_policy(name, - policy_policy, - policy_prefix, - ""); - } + branch_name name = prefix; + name.append(branch_name(i->first)); + taglist.insert(make_pair(name, *i->second)); } - policy_prefix = branch_prefix(accumulated_prefix); - return this; -} - -void -policy_revision::get_delegation_names(std::set & names) const -{ - names.clear(); - for (std::map::const_iterator i = delegations.begin(); + for (delegation_map::const_iterator i = delegations.begin(); i != delegations.end(); ++i) { - names.insert(i->first); + branch_name new_prefix = prefix; + new_prefix.append(branch_name(i->first)); + i->second->tags(new_prefix, taglist); } } ============================================================ --- policy.hh e1f8fbf5b500089012a4de045742fbc9a1620437 +++ policy.hh 18aaebbe4df42d9a4f3446f7a5ac0404947ea89c @@ -8,8 +8,11 @@ #include #include +#include +#include "branch_name.hh" #include "database.hh" +#include "editable_policy.hh" #include "vocab.hh" @@ -63,71 +66,74 @@ get_branch_heads(branch_policy const & p std::set & heads, std::multimap * inverse_graph_cache_ptr); +outdated_indicator +get_branch_heads(editable_policy::branch const & br, + bool ignore_suspend_certs, + database & db, + std::set & heads, + std::multimap + * inverse_graph_cache_ptr); bool revision_is_in_branch(branch_policy const & pol, revision_id const & rid, database & db); +bool +revision_is_in_branch(editable_policy::branch const & br, + revision_id const & rid, + database & db); -class policy_revision; - -class policy_branch +class policy_branch : public boost::enable_shared_from_this { - branch_prefix prefix; - branch_uid my_branch_cert_value; - std::set my_committers; - database & db; - boost::shared_ptr rev; - void init(data const & spec); + boost::shared_ptr policy; + boost::shared_ptr delayed; + typedef std::map > delegation_map; + delegation_map delegations; + // Load from the db. + bool init(); + policy_branch(database & db); public: - static policy_branch empty_policy(database & db); - policy_branch(data const & spec, - branch_prefix const & prefix, + static boost::shared_ptr empty_policy(database & db); + +private: + policy_branch(editable_policy::delegation const & del, database & db); - policy_branch(revision_id const & rid, - branch_prefix const & prefix, + + policy_branch(boost::shared_ptr pol, database & db); - policy_branch(std::map const & delegations, - branch_prefix const & my_prefix, - database & db); - boost::shared_ptr get_policy(); - std::map branches(); +public: + static boost::shared_ptr + create(editable_policy::delegation const & del, + database & db); + static boost::shared_ptr + create(boost::shared_ptr pol, + database & db); - boost::shared_ptr - maybe_get_branch_policy(branch_name const & name); - policy_revision const * - get_nearest_policy(branch_name const & name, - branch_policy & policy_policy, - branch_prefix & policy_prefix, - std::string const & accumulated_prefix); -}; + boost::shared_ptr get_policy(); -class policy_revision -{ - std::map branches; - std::map delegations; -public: - policy_revision(database & db, - revision_id const & rev, - branch_prefix const & prefix); - policy_revision(std::map const & del, - database & db); - std::map all_branches(); + boost::shared_ptr walk(branch_name target, + branch_name & result); - void get_delegation_names(std::set & names) const; + typedef std::map branchmap; - policy_revision const * - get_nearest_policy(branch_name const & name, - branch_policy & policy_policy, - branch_prefix & policy_prefix, - std::string const & accumulated_prefix); -}; + branchmap branches(); + typedef std::map tagmap; + tagmap tags(); +private: + void + branches(branch_name const & prefix, branchmap & branchlist); + void + tags(branch_name const & prefix, tagmap & taglist); +public: + boost::shared_ptr + maybe_get_branch_policy(branch_name const & name); +}; #endif ============================================================ --- project.cc 319b71ee6f05f67d52deb90870b6753f3ca07442 +++ project.cc 765971106387dbf944b79a1e3c2698366cb82de3 @@ -29,59 +29,32 @@ public: class policy_info { public: - policy_branch policy; + shared_ptr policy; bool passthru; - policy_info(data const & spec, - branch_prefix const & prefix, - database & db) - : policy(spec, prefix, db), passthru(false) - { - } - policy_info(revision_id const & rev, - branch_prefix const & prefix, - database & db) - : policy(rev, prefix, db), passthru(false) - { - } explicit policy_info(database & db) - : policy(policy_branch::empty_policy(db)), passthru(true) + : policy(policy_branch::empty_policy(db)), + passthru(true) { } - policy_info(map const & delegations, database & db) - : policy(delegations, branch_prefix(), db), passthru(false) + policy_info(shared_ptr const & ep, database & db) + : policy(policy_branch::create(ep, db)), passthru(false) { } }; -project_t::project_t(branch_prefix const & project_name, - data const & project_spec, - database & db) - : db(db), project_policy(new policy_info(project_spec, project_name, db)) -{} - -project_t::project_t(branch_prefix const & project_name, - revision_id const & policy_rev, - database & db) - : db(db), project_policy(new policy_info(policy_rev, project_name, db)) -{} - -project_t::project_t(database & db) - : db(db), project_policy(new policy_info(db)) -{} - project_t::project_t(database & db, lua_hooks & lua, options & opts) : db(db)//, project_policy(db, lua, opts) { - std::map delegations; + shared_ptr ep(new editable_policy(db, set())); + std::map delegations; - for (map >::const_iterator + for (map >::const_iterator i = opts.policy_revisions.begin(); i != opts.policy_revisions.end(); ++i) { data dat("revision_id ["+i->second()+"]\n"); - delegations.insert(make_pair(i->first, - dat)); + ep->get_delegation(i->first(), true)->read(dat); } std::map defs; @@ -89,57 +62,58 @@ project_t::project_t(database & db, lua_ for (map::const_iterator i = defs.begin(); i != defs.end(); ++i) { - delegations.insert(make_pair(branch_prefix(i->first), - i->second)); + ep->get_delegation(i->first, true)->read(i->second); } if (delegations.empty()) project_policy.reset(new policy_info(db)); else - project_policy.reset(new policy_info(delegations, db)); + project_policy.reset(new policy_info(ep, db)); } bool project_t::get_policy_branch_policy_of(branch_name const & name, - branch_policy & policy_branch_policy, - branch_prefix & policy_prefix) + editable_policy & policy_branch_policy, + branch_name & policy_prefix) { - std::string acc; - return project_policy->policy.get_nearest_policy(name, - policy_branch_policy, - policy_prefix, - acc) != NULL; + shared_ptr result; + result = project_policy->policy->walk(name, policy_prefix); + if (!result) + return false; + policy_branch_policy = *result->get_policy(); + return true; } bool -project_t::policy_exists(branch_prefix const & name) const +project_t::policy_exists(branch_name const & name) const { if (project_policy->passthru) return name().empty(); - branch_policy pol; - branch_prefix prefix; - std::string tmp; - bool got = project_policy->policy.get_nearest_policy(branch_name(name()), - pol, prefix, tmp) != NULL; - return got && prefix() == name(); + branch_name got; + shared_ptr sub = project_policy->policy->walk(name, got); + return sub && name == got; } void -project_t::get_subpolicies(branch_prefix const & name, - std::set & names) const +project_t::get_subpolicies(branch_name const & name, + std::set & names) const { if (project_policy->passthru) return; - branch_policy pol; - branch_prefix prefix; - std::string tmp; - policy_revision const * pr = - project_policy->policy.get_nearest_policy(branch_name(name()), - pol, prefix, tmp); - if (pr != NULL) + branch_name got; + shared_ptr sub = project_policy->policy->walk(name, got); + if (sub && got == name) { - pr->get_delegation_names(names); + shared_ptr pol = sub->get_policy(); + editable_policy::const_delegation_map dels = pol->get_all_delegations(); + for (editable_policy::const_delegation_map::const_iterator i = dels.begin(); + i != dels.end(); ++i) + { + branch_name n(name); + n.append(branch_name(i->first)); + names.insert(n); + } } } @@ -149,8 +123,8 @@ project_t::get_branch_list(std::setpassthru) { - map branches = project_policy->policy.branches(); - for (map::const_iterator i = branches.begin(); + policy_branch::branchmap branches = project_policy->policy->branches(); + for (policy_branch::branchmap::const_iterator i = branches.begin(); i != branches.end(); ++i) { names.insert(i->first); @@ -189,8 +163,8 @@ project_t::get_branch_list(globish const { if (!project_policy->passthru) { - map branches = project_policy->policy.branches(); - for (map::const_iterator i = branches.begin(); + policy_branch::branchmap branches = project_policy->policy->branches(); + for (policy_branch::branchmap::const_iterator i = branches.begin(); i != branches.end(); ++i) { if (glob.matches(i->first())) @@ -234,12 +208,11 @@ project_t::get_branch_list(std::set branchlist; - branchlist branches = project_policy->policy.branches(); - for (branchlist::const_iterator i = branches.begin(); + policy_branch::branchmap branches = project_policy->policy->branches(); + for (policy_branch::branchmap::const_iterator i = branches.begin(); i != branches.end(); ++i) { - branch_ids.insert(i->second.branch_cert_value); + branch_ids.insert(i->second.uid); } } @@ -248,11 +221,10 @@ project_t::translate_branch(branch_name { if (project_policy->passthru) return branch_uid(name()); - typedef map branchlist; - branchlist branches = project_policy->policy.branches(); - branchlist::iterator i = branches.find(name); + policy_branch::branchmap branches = project_policy->policy->branches(); + policy_branch::branchmap::iterator i = branches.find(name); I(i != branches.end()); - return i->second.branch_cert_value; + return i->second.uid; } branch_name @@ -260,12 +232,11 @@ project_t::translate_branch(branch_uid c { if (project_policy->passthru) return branch_name(uid()); - typedef map branchlist; - branchlist branches = project_policy->policy.branches(); - for (branchlist::const_iterator i = branches.begin(); + policy_branch::branchmap branches = project_policy->policy->branches(); + for (policy_branch::branchmap::const_iterator i = branches.begin(); i != branches.end(); ++i) { - if (i->second.branch_cert_value == uid) + if (i->second.uid == uid) return i->first; } I(false); @@ -355,8 +326,8 @@ project_t::get_branch_heads(branch_name } else { - shared_ptr bp; - bp = project_policy->policy.maybe_get_branch_policy(name); + shared_ptr bp; + bp = project_policy->policy->maybe_get_branch_policy(name); E(bp, F("Cannot find policy for branch %s.") % name); branch.first = ::get_branch_heads(*bp, ignore_suspend_certs, db, @@ -396,8 +367,8 @@ project_t::revision_is_in_branch(revisio } else { - shared_ptr bp; - bp = project_policy->policy.maybe_get_branch_policy(branch); + shared_ptr bp; + bp = project_policy->policy->maybe_get_branch_policy(branch); E(bp, F("Cannot find policy for branch %s.") % branch); return ::revision_is_in_branch(*bp, id, db); } @@ -558,6 +529,15 @@ project_t::get_tags(set & tags) } else { + policy_branch::tagmap got = project_policy->policy->tags(); + for (policy_branch::tagmap::const_iterator i = got.begin(); + i != got.end(); ++i) + { + tags.insert(tag_t(i->second.rev, + utf8(i->first()), + rsa_keypair_id())); + } + return outdated_indicator(); } } @@ -570,6 +550,16 @@ project_t::put_tag(key_store & keys, cert_revision_tag(db, keys, id, name); else { + shared_ptr policy_br; + branch_name tag_name(name); + branch_name policy_name; + policy_br = project_policy->policy->walk(tag_name, policy_name); + E(policy_br && policy_br != project_policy->policy, + F("Cannot find a parent policy for tag %s") % tag_name); + tag_name.strip_prefix(policy_name); + editable_policy ep(*policy_br->get_policy()); + ep.get_tag(tag_name(), true)->rev = id; + ep.commit(keys, utf8((F("Set tag %s to %s") % tag_name % id).str())); } } ============================================================ --- project.hh fa7c27b6f3d64d5d47985123ec5ea2bc66cf4184 +++ project.hh 11a4e111004808faec2e5c48f10b8e6598c68de4 @@ -7,7 +7,9 @@ #include #include +#include "branch_name.hh" #include "cert.hh" +#include "editable_policy.hh" #include "outdated_indicator.hh" #include "vocab.hh" @@ -15,7 +17,6 @@ class lua_hooks; class key_store; class options; class lua_hooks; - class branch_policy; class tag_t @@ -34,8 +35,6 @@ class policy_info; class policy_info; -class project_set; - class project_t { // In the hypothetical future situation where one monotone process is @@ -55,23 +54,15 @@ private: std::set branches; outdated_indicator indicator; - explicit project_t(database & db); - friend class project_set; public: - project_t(branch_prefix const & project_name, - data const & project_spec, - database & db); - project_t(branch_prefix const & project_name, - revision_id const & policy_rev, - database & db); project_t(database & db, lua_hooks & lua, options & opts); bool get_policy_branch_policy_of(branch_name const & name, - branch_policy & policy_branch_policy, - branch_prefix & policy_prefix); - bool policy_exists(branch_prefix const & name) const; - void get_subpolicies(branch_prefix const & name, - std::set & names) const; + editable_policy & policy_branch_policy, + branch_name & policy_prefix); + bool policy_exists(branch_name const & name) const; + void get_subpolicies(branch_name const & name, + std::set & names) const; void get_branch_list(std::set & names, bool check_heads = false); ============================================================ --- vocab_terms.hh d9280226ff11880a60d45693e4191b399fb804b7 +++ vocab_terms.hh c350da1cd3e0e1a3ab46c09631581a24e695c4e5 @@ -20,8 +20,6 @@ ATOMIC_NOVERIFY(inodeprint); // fingerp ATOMIC_NOVERIFY(delta); // xdelta between 2 datas ATOMIC_NOVERIFY(inodeprint); // fingerprint of an inode -ATOMIC_NOVERIFY(branch_name); // utf-8 -ATOMIC_NOVERIFY(branch_prefix); // a partial branch name ATOMIC_NOVERIFY(branch_uid); // what goes in the database ATOMIC(cert_name); // symbol-of-your-choosing