1 | #ifndef __REVISION_HH__␊ |
2 | #define __REVISION_HH__␊ |
3 | ␊ |
4 | // Copyright (C) 2004 Graydon Hoare <graydon@pobox.com>␊ |
5 | //␊ |
6 | // This program is made available under the GNU GPL version 2.0 or␊ |
7 | // greater. See the accompanying file COPYING for details.␊ |
8 | //␊ |
9 | // This program is distributed WITHOUT ANY WARRANTY; without even the␊ |
10 | // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR␊ |
11 | // PURPOSE.␊ |
12 | ␊ |
13 | #include <set>␊ |
14 | ␊ |
15 | #include <boost/shared_ptr.hpp>␊ |
16 | ␊ |
17 | #include "cset.hh"␊ |
18 | #include "vocab.hh"␊ |
19 | #include "database.hh"␊ |
20 | #include "commands.hh"␊ |
21 | ␊ |
22 | class app_state;␊ |
23 | ␊ |
24 | // a revision is a text object. It has a precise, normalizable serial form␊ |
25 | // as UTF-8 text. it also has some sub-components. not all of these␊ |
26 | // sub-components are separately serialized (they could be but there is no␊ |
27 | // call for it). a grammar (aside from the parsing code) for the serialized␊ |
28 | // form will show up here eventually. until then, here is an example.␊ |
29 | //␊ |
30 | // new_manifest [16afa28e8783987223993d67f54700f0ecfedfaa]␊ |
31 | //␊ |
32 | // old_revision [d023242b16cbdfd46686a5d217af14e3c339f2b4]␊ |
33 | //␊ |
34 | // delete "deleted-file.cc"␊ |
35 | //␊ |
36 | // rename "old-file.cc"␊ |
37 | // to "new-file.cc"␊ |
38 | //␊ |
39 | // add_file "added-file.cc"␊ |
40 | // content [da39a3ee5e6b4b0d3255bfef95601890afd80709]␊ |
41 | //␊ |
42 | // patch "changed-file.cc"␊ |
43 | // from [588fd8a7bcde43a46f0bde1dd1d13e9e77cf25a1]␊ |
44 | // to [559133b166c3154c864f912e9f9452bfc452dfdd]␊ |
45 | //␊ |
46 | // patch "new-file.cc"␊ |
47 | // from [95b50ede90037557fd0fbbfad6a9fdd67b0bf413]␊ |
48 | // to [bd39086b9da776fc22abd45734836e8afb59c8c0]␊ |
49 | ␊ |
50 | typedef std::map<revision_id, boost::shared_ptr<cset> >␊ |
51 | edge_map;␊ |
52 | ␊ |
53 | typedef edge_map::value_type␊ |
54 | edge_entry;␊ |
55 | ␊ |
56 | enum made_for { made_for_nobody, made_for_workspace, made_for_database };␊ |
57 | ␊ |
58 | struct␊ |
59 | revision_t␊ |
60 | {␊ |
61 | void check_sane() const;␊ |
62 | bool is_merge_node() const;␊ |
63 | // trivial revisions are ones that have no effect -- e.g., commit should␊ |
64 | // refuse to commit them, saying that there are no changes to commit.␊ |
65 | bool is_nontrivial() const;␊ |
66 | revision_t() : made_for(made_for_nobody) {}␊ |
67 | revision_t(revision_t const & other);␊ |
68 | revision_t const & operator=(revision_t const & other);␊ |
69 | manifest_id new_manifest;␊ |
70 | edge_map edges;␊ |
71 | // workspace::put_work_rev refuses to apply a rev that doesn't have this␊ |
72 | // set to "workspace", and database::put_revision refuses to apply a rev␊ |
73 | // that doesn't have it set to "database". the default constructor sets␊ |
74 | // it to "nobody".␊ |
75 | enum made_for made_for;␊ |
76 | };␊ |
77 | ␊ |
78 | inline revision_id const &␊ |
79 | edge_old_revision(edge_entry const & e)␊ |
80 | {␊ |
81 | return e.first;␊ |
82 | }␊ |
83 | ␊ |
84 | inline revision_id const &␊ |
85 | edge_old_revision(edge_map::const_iterator i)␊ |
86 | {␊ |
87 | return i->first;␊ |
88 | }␊ |
89 | ␊ |
90 | inline cset const &␊ |
91 | edge_changes(edge_entry const & e)␊ |
92 | {␊ |
93 | return *(e.second);␊ |
94 | }␊ |
95 | ␊ |
96 | inline cset const &␊ |
97 | edge_changes(edge_map::const_iterator i)␊ |
98 | {␊ |
99 | return *(i->second);␊ |
100 | }␊ |
101 | ␊ |
102 | template <> void␊ |
103 | dump(revision_t const & rev, std::string & out);␊ |
104 | ␊ |
105 | void␊ |
106 | read_revision(data const & dat,␊ |
107 | revision_t & rev);␊ |
108 | ␊ |
109 | void␊ |
110 | read_revision(revision_data const & dat,␊ |
111 | revision_t & rev);␊ |
112 | ␊ |
113 | void␊ |
114 | write_revision(revision_t const & rev,␊ |
115 | data & dat);␊ |
116 | ␊ |
117 | void␊ |
118 | write_revision(revision_t const & rev,␊ |
119 | revision_data & dat);␊ |
120 | ␊ |
121 | void calculate_ident(revision_t const & cs,␊ |
122 | revision_id & ident);␊ |
123 | ␊ |
124 | // sanity checking␊ |
125 | ␊ |
126 | void␊ |
127 | find_common_ancestor_for_merge(revision_id const & left,␊ |
128 | revision_id const & right,␊ |
129 | revision_id & anc,␊ |
130 | app_state & app);␊ |
131 | ␊ |
132 | bool␊ |
133 | is_ancestor(revision_id const & ancestor,␊ |
134 | revision_id const & descendent,␊ |
135 | app_state & app);␊ |
136 | ␊ |
137 | void␊ |
138 | toposort(std::set<revision_id> const & revisions,␊ |
139 | std::vector<revision_id> & sorted,␊ |
140 | app_state & app);␊ |
141 | ␊ |
142 | void␊ |
143 | erase_ancestors(std::set<revision_id> & revisions, app_state & app);␊ |
144 | ␊ |
145 | struct is_failure␊ |
146 | {␊ |
147 | virtual bool operator()(revision_id const & rid) = 0;␊ |
148 | virtual ~is_failure() {};␊ |
149 | };␊ |
150 | void␊ |
151 | erase_ancestors_and_failures(std::set<revision_id> & revisions,␊ |
152 | is_failure & p,␊ |
153 | app_state & app);␊ |
154 | ␊ |
155 | void␊ |
156 | ancestry_difference(revision_id const & a, std::set<revision_id> const & bs,␊ |
157 | std::set<revision_id> & new_stuff,␊ |
158 | app_state & app);␊ |
159 | ␊ |
160 | ␊ |
161 | // FIXME: can probably optimize this passing a lookaside cache of the active␊ |
162 | // frontier set of shared_ptr<roster_t>s, while traversing history.␊ |
163 | void␊ |
164 | select_nodes_modified_by_rev(revision_t const & rev,␊ |
165 | roster_t const roster,␊ |
166 | std::set<node_id> & nodes_modified,␊ |
167 | app_state & app);␊ |
168 | ␊ |
169 | void␊ |
170 | make_revision(revision_id const & old_rev_id,␊ |
171 | roster_t const & old_roster,␊ |
172 | roster_t const & new_roster,␊ |
173 | revision_t & rev);␊ |
174 | ␊ |
175 | void␊ |
176 | make_revision(parent_map const & old_rosters,␊ |
177 | roster_t const & new_roster,␊ |
178 | revision_t & rev);␊ |
179 | ␊ |
180 | // This overload takes a base roster and a changeset instead.␊ |
181 | void␊ |
182 | make_revision(revision_id const & old_rev_id,␊ |
183 | roster_t const & old_roster,␊ |
184 | cset const & changes,␊ |
185 | revision_t & rev);␊ |
186 | ␊ |
187 | // These functions produce a faked "new_manifest" id and discard all␊ |
188 | // content-only changes from the cset. They are only to be used to␊ |
189 | // construct a revision that will be written to the workspace. Don't use␊ |
190 | // them for revisions written to the database or presented to the user.␊ |
191 | void␊ |
192 | make_revision_for_workspace(revision_id const & old_rev_id,␊ |
193 | cset const & changes,␊ |
194 | revision_t & rev);␊ |
195 | ␊ |
196 | void␊ |
197 | make_revision_for_workspace(revision_id const & old_rev_id,␊ |
198 | roster_t const & old_roster,␊ |
199 | roster_t const & new_roster,␊ |
200 | revision_t & rev);␊ |
201 | ␊ |
202 | void␊ |
203 | make_revision_for_workspace(parent_map const & old_rosters,␊ |
204 | roster_t const & new_roster,␊ |
205 | revision_t & rev);␊ |
206 | ␊ |
207 | void␊ |
208 | make_restricted_revision(parent_map const & old_rosters,␊ |
209 | roster_t const & new_roster,␊ |
210 | node_restriction const & mask,␊ |
211 | revision_t & rev);␊ |
212 | ␊ |
213 | void␊ |
214 | make_restricted_revision(parent_map const & old_rosters,␊ |
215 | roster_t const & new_roster,␊ |
216 | node_restriction const & mask,␊ |
217 | revision_t & rev,␊ |
218 | cset & excluded,␊ |
219 | commands::command_id const & cmd_name);␊ |
220 | ␊ |
221 | void␊ |
222 | build_changesets_from_manifest_ancestry(app_state & app);␊ |
223 | ␊ |
224 | void␊ |
225 | build_roster_style_revs_from_manifest_style_revs(app_state & app);␊ |
226 | ␊ |
227 | void␊ |
228 | regenerate_caches(app_state & app);␊ |
229 | ␊ |
230 | // basic_io access to printers and parsers␊ |
231 | ␊ |
232 | namespace basic_io { struct printer; struct parser; }␊ |
233 | ␊ |
234 | void␊ |
235 | print_revision(basic_io::printer & printer,␊ |
236 | revision_t const & rev);␊ |
237 | ␊ |
238 | void␊ |
239 | parse_revision(basic_io::parser & parser,␊ |
240 | revision_t & rev);␊ |
241 | ␊ |
242 | void␊ |
243 | print_edge(basic_io::printer & printer,␊ |
244 | edge_entry const & e);␊ |
245 | ␊ |
246 | void␊ |
247 | parse_edge(basic_io::parser & parser,␊ |
248 | edge_map & es);␊ |
249 | ␊ |
250 | // Local Variables:␊ |
251 | // mode: C++␊ |
252 | // fill-column: 76␊ |
253 | // c-file-style: "gnu"␊ |
254 | // indent-tabs-mode: nil␊ |
255 | // End:␊ |
256 | // vim: et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s:␊ |
257 | ␊ |
258 | #endif // __REVISION_HH__␊ |