# # # add_file "policies/outdatable_policy.cc" # content [125510369150147d3fad868c6687bba1f54bf717] # # add_file "policies/outdatable_policy.hh" # content [051c44077c0704de5b638e083bc406b63a950f83] # # patch "Makefile.am" # from [b784cd8fd757827539a7ec66b4d3014d1580791d] # to [2f44a194e9f4c98dc10a5e99d272c1ff6e7ce91a] # # patch "network/netsync_session.cc" # from [2dd04be8333c8671258e1c2bc595ffdeef41ff29] # to [a2f4a48210709137a6c0ed3355a81e0e0384045b] # # patch "outdated_indicator.cc" # from [ba676108726aaf7eba3b7e7e357165696e15a599] # to [d2a291d777cf8fc623aba344f077260aa5f6640d] # # patch "outdated_indicator.hh" # from [8f8a6bd36595e3c846be40ad59f550983a00f2a0] # to [8e9f3eda60d383421cf8e280722f83aada2ca29a] # # patch "policies/base_policy.cc" # from [daaf24d8ed1627929a264e8a687e62e83b0807ad] # to [9128088b7d91014132ff664c9b30436c0301e565] # # patch "policies/base_policy.hh" # from [84e52ef58478b40d3f33f5c58871b8e97cc45c89] # to [5de53362e991cda313d70744f0de7fbd45d996d3] # # patch "policies/delegation.cc" # from [eb6d79d94d11c13697ce1e48e2b6c699a5cf2117] # to [4969a762c4563f86f09e836b09ab0604d6d870de] # # patch "policies/policy_branch.cc" # from [9f5cf990e17f3b68ea31d5bbf7829343098ae714] # to [36bc813f78bbd215ee977774e0322b2269e70c32] # # patch "policies/policy_branch.hh" # from [f333957457d5b6a866e7f7186651f0f194e4e60d] # to [5405e1469504270f42366daf42c3265d83846472] # # patch "project.cc" # from [0d4f00a7c962d3dbbff1d23bf80e825b9eb19d02] # to [1f3b828df6a7fa1aafa0a180b7215a85d29ebe03] # # patch "project.hh" # from [abe7dd2ace5364f0ac9b16d9462e657620d1ebb3] # to [ba427de548b87bf2525cdec6a1279e2ab61def87] # ============================================================ --- policies/outdatable_policy.cc 125510369150147d3fad868c6687bba1f54bf717 +++ policies/outdatable_policy.cc 125510369150147d3fad868c6687bba1f54bf717 @@ -0,0 +1,42 @@ +// Copyright (C) 2010 and later by various people +// see monotone commit logs for details and authors +// +// This program is made available under the GNU GPL version 2.0 or +// greater. See the accompanying file COPYING for details. +// +// This program is distributed WITHOUT ANY WARRANTY; without even the +// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. + +#include "base.hh" +#include "policies/outdatable_policy.hh" + +namespace policies { + outdatable_policy::outdatable_policy() { } + outdatable_policy::outdatable_policy(policy const & p) + : policy(p) + { } + outdatable_policy const & outdatable_policy::operator=(policy const & pol) + { + this->policy::operator=(pol); + ind = outdated_indicator(); + return *this; + } + + bool outdatable_policy::outdated() const + { + return ind.outdated(); + } + void outdatable_policy::set_indicator(outdated_indicator const & new_ind) + { + ind = new_ind; + } +} + +// Local Variables: +// mode: C++ +// fill-column: 76 +// c-file-style: "gnu" +// indent-tabs-mode: nil +// End: +// vim: et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s: ============================================================ --- policies/outdatable_policy.hh 051c44077c0704de5b638e083bc406b63a950f83 +++ policies/outdatable_policy.hh 051c44077c0704de5b638e083bc406b63a950f83 @@ -0,0 +1,41 @@ +// Copyright (C) 2008 and later by various people +// see monotone commit logs for details and authors +// +// This program is made available under the GNU GPL version 2.0 or +// greater. See the accompanying file COPYING for details. +// +// This program is distributed WITHOUT ANY WARRANTY; without even the +// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. + +#ifndef __POLICIES_OUTDATABLE_POLICY__ +#define __POLICIES_OUTDATABLE_POLICY__ + +#include "outdated_indicator.hh" +#include "policies/policy.hh" + +class outdated_indicator; + +namespace policies { + class outdatable_policy : public policy + { + outdated_indicator ind; + public: + outdatable_policy(); + explicit outdatable_policy(policy const & p); + outdatable_policy const & operator=(policy const & p); + + bool outdated() const; + void set_indicator(outdated_indicator const & new_ind); + }; +} + +#endif + +// Local Variables: +// mode: C++ +// fill-column: 76 +// c-file-style: "gnu" +// indent-tabs-mode: nil +// End: +// vim: et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s: ============================================================ --- Makefile.am b784cd8fd757827539a7ec66b4d3014d1580791d +++ Makefile.am 2f44a194e9f4c98dc10a5e99d272c1ff6e7ce91a @@ -82,6 +82,7 @@ MOST_SOURCES = \ policies/branch.hh policies/branch.cc \ policies/delegation.hh policies/delegation.cc \ policies/editable_policy.hh policies/editable_policy.cc \ + policies/outdatable_policy.hh policies/outdatable_policy.cc \ policies/policy.hh policies/policy.cc \ policies/policy_branch.hh policies/policy_branch.cc \ merkle_tree.cc merkle_tree.hh \ ============================================================ --- network/netsync_session.cc 2dd04be8333c8671258e1c2bc595ffdeef41ff29 +++ network/netsync_session.cc a2f4a48210709137a6c0ed3355a81e0e0384045b @@ -622,6 +622,16 @@ netsync_session::request_service() // user requested set all_branches, ok_branches; project.get_branch_list(all_branches); + { + set policies; + project.get_subpolicies(branch_name(), policies); + branch_name suffix("__policy__", origin::internal); + for (set::const_iterator i = policies.begin(); + i != policies.end(); ++i) + { + all_branches.insert(*i / suffix); + } + } for (set::const_iterator i = all_branches.begin(); i != all_branches.end(); i++) { ============================================================ --- outdated_indicator.cc ba676108726aaf7eba3b7e7e357165696e15a599 +++ outdated_indicator.cc d2a291d777cf8fc623aba344f077260aa5f6640d @@ -58,7 +58,7 @@ bool {} bool -outdated_indicator::outdated() +outdated_indicator::outdated() const { if (parent) { ============================================================ --- outdated_indicator.hh 8f8a6bd36595e3c846be40ad59f550983a00f2a0 +++ outdated_indicator.hh 8e9f3eda60d383421cf8e280722f83aada2ca29a @@ -33,7 +33,7 @@ public: public: outdated_indicator(); explicit outdated_indicator(boost::shared_ptr p); - bool outdated(); + bool outdated() const; }; ============================================================ --- policies/base_policy.cc daaf24d8ed1627929a264e8a687e62e83b0807ad +++ policies/base_policy.cc 9128088b7d91014132ff664c9b30436c0301e565 @@ -26,21 +26,22 @@ namespace policies { class database; namespace policies { - base_policy::base_policy(database & db, options const & opts, lua_hooks & lua): - _empty(true) + base_policy::base_policy(options const & opts, lua_hooks & lua): + _opts(opts), _lua(lua), _empty(true) { - load(db, opts, lua); + reload(); } bool base_policy::empty() const { return _empty; } - void base_policy::load(database & db, options const & opts, lua_hooks & lua) + void base_policy::reload() { + delegations.clear(); typedef map > override_map; - for (override_map::const_iterator i = opts.policy_revisions.begin(); - i != opts.policy_revisions.end(); ++i) + for (override_map::const_iterator i = _opts.policy_revisions.begin(); + i != _opts.policy_revisions.end(); ++i) { id r; decode_hexenc(i->second, r); @@ -50,7 +51,7 @@ namespace policies { typedef map hook_map; hook_map hm; - lua.hook_get_projects(hm); + _lua.hook_get_projects(hm); for (hook_map::const_iterator i = hm.begin(); i != hm.end(); ++i) { if (delegations.find(i->first) == delegations.end()) ============================================================ --- policies/base_policy.hh 84e52ef58478b40d3f33f5c58871b8e97cc45c89 +++ policies/base_policy.hh 5de53362e991cda313d70744f0de7fbd45d996d3 @@ -21,11 +21,13 @@ namespace policies { // The top-level policy, defined by command-line options and lua hooks. class base_policy : public policy { + options const & _opts; + lua_hooks & _lua; bool _empty; - void load(database & db, options const & opts, lua_hooks & lua); public: - base_policy(database & db, options const & opts, lua_hooks & lua); + base_policy(options const & opts, lua_hooks & lua); bool empty() const; + void reload(); inline bool outdated() const { return false; } // Use lua hooks to write out the given policy. ============================================================ --- policies/delegation.cc eb6d79d94d11c13697ce1e48e2b6c699a5cf2117 +++ policies/delegation.cc 4969a762c4563f86f09e836b09ab0604d6d870de @@ -17,6 +17,8 @@ using std::string; using std::string; +using boost::shared_ptr; + namespace basic_io { namespace syms { static symbol revision_id("revision_id"); @@ -98,9 +100,11 @@ namespace policies { case branch_type: { policy_branch br(project, parent, branch_desc); - policy_ptr ret(new policy()); + shared_ptr ret(new outdatable_policy()); if (br.try_get_policy(*ret)) - return ret; + { + return ret; + } else { W(F("Policy branch '%s' has %d heads and cannot be automatically merged") ============================================================ --- policies/policy_branch.cc 9f5cf990e17f3b68ea31d5bbf7829343098ae714 +++ policies/policy_branch.cc 36bc813f78bbd215ee977774e0322b2269e70c32 @@ -177,10 +177,10 @@ namespace policies { } namespace { - void get_heads(project_t const & project, - branch const & spec, - policy_ptr const & spec_owner, - std::set & heads) + outdated_indicator get_heads(project_t const & project, + branch const & spec, + policy_ptr const & spec_owner, + std::set & heads) { heads.clear(); std::set keys; @@ -199,10 +199,10 @@ namespace policies { keys.insert(spec_owner->get_key_id(name)); } } - project.get_branch_heads(spec.get_uid(), - keys, - heads, - false); + return project.get_branch_heads(spec.get_uid(), + keys, + heads, + false); } void get_rosters(project_t const & project, std::set const & heads, @@ -267,7 +267,7 @@ namespace policies { bool policy_branch::reload(project_t const & project) { std::set heads; - get_heads(project, spec, spec_owner, heads); + _indicator = get_heads(project, spec, spec_owner, heads); _num_heads = heads.size(); parent_map rosters; get_rosters(project, heads, rosters); @@ -280,19 +280,32 @@ namespace policies { my_policy.set_parent(spec_owner); return true; } - bool policy_branch::try_get_policy(policy & pol) const + bool policy_branch::try_get_policy(outdatable_policy & pol) const { if (!loaded) - return false; - pol = my_policy; - return true; + { + pol.set_indicator(_indicator); + return false; + } + else + { + pol = my_policy; + pol.set_indicator(_indicator); + return true; + } } - void policy_branch::get_policy(policy & pol, origin::type ty) const + void policy_branch::get_policy(outdatable_policy & pol, origin::type ty) const { E(try_get_policy(pol), ty, F("cannot sanely combine %d heads of policy") % _num_heads); } + void policy_branch::get_policy(policy & pol, origin::type ty) const + { + outdatable_policy p; + get_policy(p, ty); + pol = p; + } namespace { class content_putter ============================================================ --- policies/policy_branch.hh f333957457d5b6a866e7f7186651f0f194e4e60d +++ policies/policy_branch.hh 5405e1469504270f42366daf42c3265d83846472 @@ -14,9 +14,11 @@ #include #include "origin_type.hh" +#include "outdated_indicator.hh" #include "policies/branch.hh" #include "policies/delegation.hh" #include "policies/editable_policy.hh" +#include "policies/outdatable_policy.hh" class key_store; @@ -33,6 +35,7 @@ namespace policies { size_t _num_heads; editable_policy my_policy; bool loaded; + outdated_indicator _indicator; bool reload(project_t const & project); public: policy_branch(project_t const & project, @@ -44,8 +47,9 @@ namespace policies { size_t num_heads() const; // return false if we can't get a coherent policy, due to // having multiple heads and they can't be auto-merged - bool try_get_policy(policy & pol) const; + bool try_get_policy(outdatable_policy & pol) const; // wraper that will E() for you + void get_policy(outdatable_policy & pol, origin::type ty) const; void get_policy(policy & pol, origin::type ty) const; // return false if the commit fails, due to // having multiple heads that can't be auto-merged ============================================================ --- project.cc 0d4f00a7c962d3dbbff1d23bf80e825b9eb19d02 +++ project.cc 1f3b828df6a7fa1aafa0a180b7215a85d29ebe03 @@ -98,14 +98,16 @@ typedef map > child_policy_map; +typedef boost::function, branch_name const &, + policies::delegation const &)> policy_walker; + // walk the tree of policies, resolving children if needed -void walk_policies(project_t const & project, - shared_ptr root, - child_policy_map & children, - boost::function, branch_name const &, - policies::delegation const &)> fn, - branch_name current_prefix = branch_name(), - policies::delegation del = policies::delegation()) +void walk_policies_internal(project_t const & project, + shared_ptr root, + child_policy_map & children, + policy_walker fn, + branch_name current_prefix, + policies::delegation del) { L(FL("Walking policies; root = %d, current prefix = '%s'") % (bool)root % current_prefix); @@ -130,18 +132,58 @@ void walk_policies(project_t const & pro child_policy_map::iterator c = children.find(child_key); if (c == children.end()) { + L(FL("loaded new policy '%s'") % child_prefix); pair x = children.insert(make_pair(child_key, i->second.resolve(project, root))); c = x.first; } + else if (!c->second || c->second->outdated()) + { + if (c->second) + L(FL("policy '%s' did not resolve; reloading") % child_prefix); + else + L(FL("policy '%s' marked outdated; reloading (will reload all children)") + % child_prefix); + c->second = i->second.resolve(project, root); + } - walk_policies(project, c->second, children, fn, child_prefix, i->second); + walk_policies_internal(project, c->second, children, fn, child_prefix, i->second); } L(FL("Done walking under prefix '%s'") % current_prefix); } +void walk_policies(project_t const & project, + shared_ptr root_policy, + child_policy_map & children, + policy_walker fn) +{ + if (root_policy->outdated()) + { + L(FL("root policy is marked outdated; reloading (will reload all children)...")); + shared_ptr bp + = boost::dynamic_pointer_cast(root_policy); + bp->reload(); + } + walk_policies_internal(project, root_policy, children, fn, + branch_name(), policies::delegation()); + + set dead_policies; + for (child_policy_map::const_iterator i = children.begin(); + i != children.end(); ++i) + { + policies::policy_ptr p = i->first.parent.lock(); + if (!p || p->outdated()) + dead_policies.insert(i->first); + } + for (set::const_iterator i = dead_policies.begin(); + i != dead_policies.end(); ++i) + { + children.erase(*i); + } +} + struct branch_info { branch self; @@ -516,7 +558,7 @@ project_t::project_t(database & db, lua_ project_t::project_t(database & db, lua_hooks & lua, options & opts) : db(db) { - shared_ptr bp(new policies::base_policy(db, opts, lua)); + shared_ptr bp(new policies::base_policy(opts, lua)); project_policy.reset(new policy_info(bp->empty(), bp)); } @@ -839,7 +881,7 @@ namespace } } -void +outdated_indicator project_t::get_branch_heads(branch_uid const & uid, std::set const & signers, std::set & heads, @@ -857,6 +899,7 @@ project_t::get_branch_heads(branch_uid c inverse_graph_cache_ptr); heads = branch.second; + return branch.first; } bool project_t::branch_exists(branch_name const & name) const ============================================================ --- project.hh abe7dd2ace5364f0ac9b16d9462e657620d1ebb3 +++ project.hh ba427de548b87bf2525cdec6a1279e2ab61def87 @@ -149,12 +149,12 @@ public: branch_name translate_branch(branch_uid const & branch); // internal for policy stuff - void get_branch_heads(branch_uid const & uid, - std::set const & signers, - std::set & heads, - bool ignore_suspend_certs, - std::multimap - *inverse_graph_cache_ptr = NULL) const; + outdated_indicator get_branch_heads(branch_uid const & uid, + std::set const & signers, + std::set & heads, + bool ignore_suspend_certs, + std::multimap + *inverse_graph_cache_ptr = NULL) const; bool branch_exists(branch_name const & name) const; void get_branch_heads(branch_name const & name,