monotone

monotone Mtn Source Tree

Root/update.cc

1
2// copyright (C) 2002, 2003 graydon hoare <graydon@pobox.com>
3// all rights reserved.
4// licensed to the public under the terms of the GNU GPL (>= 2)
5// see the file COPYING for details
6
7#include <set>
8#include <map>
9#include <vector>
10#include <string>
11#include <boost/lexical_cast.hpp>
12
13#include "app_state.hh"
14#include "database.hh"
15#include "manifest.hh"
16#include "sanity.hh"
17#include "cert.hh"
18#include "transforms.hh"
19#include "ui.hh"
20#include "update.hh"
21#include "vocab.hh"
22
23// these functions just encapsulate the (somewhat complex) logic behind
24// picking an update target. the actual updating takes place in
25// commands.cc, along with most other file-modifying actions.
26
27using boost::lexical_cast;
28
29using namespace std;
30
31static void
32get_test_results_for_manifest(manifest_id const & id,
33 map<rsa_keypair_id, bool> & results,
34 app_state & app)
35{
36 vector< manifest<cert> > certs;
37 app.db.get_manifest_certs(id, testresult_cert_name, certs);
38 erase_bogus_certs(certs, app);
39 for (vector< manifest<cert> >::const_iterator i = certs.begin();
40 i != certs.end(); ++i)
41 {
42 cert_value cv;
43 decode_base64(i->inner().value, cv);
44 try
45{
46 bool test_ok = lexical_cast<bool>(cv());
47 results.insert(make_pair(i->inner().key, test_ok));
48}
49 catch(boost::bad_lexical_cast & e)
50{
51 W(F("failed to decode boolean testresult cert value '%s'\n") % cv);
52}
53 }
54}
55
56static void
57find_deepest_acceptable_descendent(manifest_id const & base,
58 cert_value const & branch,
59 app_state & app,
60 set<manifest_id> & chosen)
61{
62 chosen.clear();
63 chosen.insert(base);
64
65 set<manifest_id> visited;
66 set<manifest_id> frontier = chosen;
67 while(! frontier.empty())
68 {
69 set<manifest_id> next_frontier;
70 set<manifest_id> selected_children;
71
72 for (set<manifest_id>::const_iterator i = frontier.begin();
73 i != frontier.end(); ++i)
74{
75 // quick check to prevent cycles
76 if (visited.find(*i) != visited.end())
77 continue;
78 visited.insert(*i);
79
80 // step 1: get children of i
81 base64<cert_value> val;
82 vector< manifest<cert> > certs;
83 set<manifest_id> children;
84
85 encode_base64(cert_value(i->inner()()), val);
86 app.db.get_manifest_certs(ancestor_cert_name, val, certs);
87 erase_bogus_certs(certs, app);
88 for(vector< manifest<cert> >::const_iterator j = certs.begin();
89 j != certs.end(); ++j)
90 {
91 children.insert(manifest_id(j->inner().ident));
92 }
93
94 // step 2: weed out edges which cross a branch boundary
95 set<manifest_id> same_branch_children;
96 encode_base64(branch, val);
97 for (set<manifest_id>::const_iterator j = children.begin();
98 j != children.end(); ++j)
99 {
100 app.db.get_manifest_certs(*j, branch_cert_name, val, certs);
101 erase_bogus_certs(certs, app);
102 if (certs.empty())
103W(F("update edge %s -> %s ignored since it exits branch %s\n")
104 % *i % *j % branch);
105 else
106same_branch_children.insert(*j);
107 }
108
109 // step 3: weed out disapproved edges
110 for (set<manifest_id>::const_iterator j = same_branch_children.begin();
111 j != same_branch_children.end(); ++j)
112 {
113 encode_base64(cert_value(i->inner()()), val);
114 app.db.get_manifest_certs(*j, disapproval_cert_name, val, certs);
115 erase_bogus_certs(certs, app);
116 if (certs.empty())
117next_frontier.insert(*j);
118 else
119W(F("update edge %s -> %s ignored due to %d valid disapproval certs\n")
120 % *i % *j % certs.size());
121 }
122
123 // step 4: pull aside acceptable testresult changes
124 map<rsa_keypair_id, bool> old_results;
125 get_test_results_for_manifest(*i, old_results, app);
126 for (set<manifest_id>::const_iterator j = next_frontier.begin();
127 j != next_frontier.end(); ++j)
128 {
129 map<rsa_keypair_id, bool> new_results;
130 get_test_results_for_manifest(*j, new_results, app);
131 if (app.lua.hook_accept_testresult_change(old_results, new_results))
132selected_children.insert(*j);
133 else
134W(F("update edge %s -> %s ignored due to unacceptable testresults\n")
135 % *i % *j);
136 }
137}
138
139 if (! selected_children.empty())
140chosen = selected_children;
141
142 frontier = next_frontier;
143 }
144}
145
146void pick_update_target(manifest_id const & base_ident,
147app_state & app,
148manifest_id & chosen)
149{
150 set<manifest_id> chosen_set;
151 N(app.branch_name() != "",
152 F("cannot determine branch for update"));
153
154 find_deepest_acceptable_descendent(base_ident, cert_value(app.branch_name()),
155 app, chosen_set);
156
157 N(chosen_set.size() != 0,
158 F("no candidates remain after selection"));
159
160 N(chosen_set.size() == 1,
161 F("multiple candidates remain after selection"));
162
163 chosen = *(chosen_set.begin());
164}
165
166

Archive Download this file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status