monotone

monotone Mtn Source Tree

Root/src/work.hh

1// Copyright (C) 2012 Stephen Leake <stephen_leake@stephe-leake.org>
2// Copyright (C) 2002 Graydon Hoare <graydon@pobox.com>
3//
4// This program is made available under the GNU GPL version 2.0 or
5// greater. See the accompanying file COPYING for details.
6//
7// This program is distributed WITHOUT ANY WARRANTY; without even the
8// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
9// PURPOSE.
10
11#ifndef __WORK_HH__
12#define __WORK_HH__
13
14#include <set>
15#include "paths.hh"
16#include "rev_types.hh"
17
18class path_restriction;
19class node_restriction;
20struct content_merge_adaptor;
21class lua_hooks;
22struct i18n_format;
23struct options;
24class app_state;
25
26//
27// this file defines structures to deal with the "workspace" of a tree
28//
29// at present the presence or absence of a workspace is intrinsically global
30// state, because it affects things like file_path construction (over in
31// paths.cc) and the current working directory. also, there are a bunch of
32// operations, mostly during program initialization, that are conditional on
33// whether or not we are inside a workspace. this has two visible
34// consequences to this api: first, you cannot create more than one
35// workspace object, and second, the workspace class has many class methods
36// as well as many instance methods. class methods can be used when you're
37// not sure yet whether or not there is a workspace. instance methods can
38// only be used if there definitely is a workspace; the workspace object
39// constructor will throw an E() if there isn't one. (this can also be
40// triggered by the class method require_workspace, for the sake of a few
41// places that need to do that but not create the workspace object yet.)
42//
43
44//
45// workspace book-keeping files are stored in a directory called _MTN, off
46// the root of the workspace source tree (analogous to the CVS or .svn
47// directories). there is no hierarchy of _MTN directories; only one exists,
48// and it is always at the root. it contains the following files:
49//
50
51// _MTN/revision -- this file can be thought of as an approximation to the
52// revision that would be added to the database if one
53// were to execute 'mtn commit' with the current set of
54// changes. it records the id of the revision that was
55// checked out (the "parent revision") plus a cset
56// describing pathname and attribute modifications
57// relative to that revision. if the workspace is the
58// result of a merge, the revision will have more than
59// one parent and thus more than one cset. files
60// changed solely in content do not appear in
61// _MTN/revision; this is the major difference between
62// the revision in this file and the revision that 'mtn
63// commit' adds to the database.
64// _MTN/options -- the database, branch and key options currently in use
65// _MTN/log -- user edited log file
66// _MTN/inodeprints -- file fingerprint cache, see below
67//
68// as work proceeds, the files in the workspace either change their
69// sha1 fingerprints from those listed in the revision's manifest, or else are
70// added or deleted or renamed (and the paths of those changes recorded in
71// '_MTN/revision').
72//
73// many operations need to work with a revision that accurately describes
74// both pathname and content changes. constructing this revision is the
75// function of update_current_roster_from_filesystem(). this operation
76// intrinsically requires reading every file in the workspace, which can be
77// slow. _MTN/inodeprints, if present, is used to speed up this process; it
78// records information accessible via stat() that is expected to change
79// whenever a file is modified. this expectation is not true under all
80// conditions, but works in practice (it is, for instance, the same
81// expectation used by "make"). nonetheless, this mode is off by default.
82
83bool directory_is_workspace(system_path const & dir);
84
85namespace bisect
86{
87 enum type { start, good, bad, skipped, update };
88 typedef std::pair<type, revision_id> entry;
89};
90
91struct workspace
92{
93 // This is a public flag because it's set from monotone.cc using a
94 // function (find_and_go_to_workspace) which cannot presently be moved
95 // from paths.cc.
96 static bool found;
97 // This is set to true when a workspace object was created and used
98 // for a particular command
99 static bool used;
100
101private:
102 // This is used by get_options and set_options. The branch option is set
103 // to sticky (meaning it will be persisted in the workspace options) in
104 // several cases:
105 // - when update switches to a different branch
106 // - when commit switches to a different branch
107 // - when creating a new workspace
108 // - when the given branch option is empty and the workspace branch option
109 // is not, to retain the previous workspace branch option
110 static bool branch_is_sticky;
111
112 // This is used by a lot of instance methods.
113 lua_hooks & lua;
114
115 // Give a nice error if the parent revisions aren't in the db
116 void require_parents_in_db(database & db, revision_t const & rev);
117
118 // Interfaces.
119public:
120 static void require_workspace();
121 static void require_workspace(i18n_format const & explanation);
122
123 static void create_workspace(options const & opts,
124 lua_hooks & lua,
125 system_path const & new_dir);
126
127 // Constructor. In normal usage, calling this transitions from the state
128 // where there may or may not be a workspace to the state where there
129 // definitely is.
130 explicit workspace(app_state & app);
131 explicit workspace(app_state & app, i18n_format const & explanation);
132 explicit workspace(lua_hooks & lua, i18n_format const & explanation);
133
134 // Methods for manipulating the workspace's content.
135 void find_missing(roster_t const & new_roster_shape,
136 node_restriction const & mask,
137 std::set<file_path> & missing);
138
139 void find_unknown_and_ignored(database & db,
140 path_restriction const & mask,
141 bool recurse,
142 std::vector<file_path> const & roots,
143 std::set<file_path> & unknown,
144 std::set<file_path> & ignored);
145
146 void perform_additions(database & db,
147 std::set<file_path> const & targets,
148 bool recursive = false,
149 bool respect_ignore = true);
150
151 void perform_deletions(database & db,
152 std::set<file_path> const & targets,
153 bool recursive,
154 bool bookkeep_only);
155
156 void perform_rename(database & db,
157 std::set<file_path> const & src_paths,
158 file_path const & dst_dir,
159 bool bookkeep_only);
160
161 void perform_pivot_root(database & db,
162 file_path const & new_root,
163 file_path const & put_old,
164 bool bookkeep_only,
165 bool move_conflicting_paths);
166
167 void perform_content_update(roster_t const & old_roster,
168 roster_t const & new_roster,
169 cset const & cs,
170 content_merge_adaptor const & ca,
171 bool const messages = true,
172 bool const move_conflicting_paths = false);
173
174 void init_attributes(file_path const & path, editable_roster_base & er);
175
176 bool has_changes(database & db);
177
178 // write out a new (partial) revision describing the current workspace;
179 // the important pieces of this are the base revision id and the "shape"
180 // changeset (representing tree rearrangements).
181 void put_work_rev(revision_t const & rev);
182
183 // read the (partial) revision describing the current workspace.
184 void get_work_rev(revision_t & rev);
185
186 // read the revision id that was the parent of this workspace before
187 // the last update occured. this is used for the u: (update) selector
188 void get_update_id(revision_id & update_id);
189
190 // write the revision id that was the parent of this workspace before
191 // update completes. this is used for the u: (update) selector
192 void put_update_id(revision_id const & update_id);
193
194 // convenience wrappers around the above functions.
195
196 // This returns the current roster, except it does not bother updating the
197 // hashes in that roster -- the "shape" is correct, all files and dirs
198 // exist and under the correct names -- but do not trust file content
199 // hashes. If you need the current roster with correct file content
200 // hashes, call update_current_roster_from_filesystem on the result of
201 // this function. Under almost all conditions, NIS should be a
202 // temp_node_id_source.
203 void get_current_roster_shape(database & db, node_id_source & nis,
204 roster_t & ros);
205
206 // This returns a map whose keys are revision_ids and whose values are
207 // rosters, there being one such pair for each parent of the current
208 // revision.
209 void get_parent_rosters(database & db, parent_map & parents);
210
211 // This updates the file-content hashes in ROSTER, which is assumed to be
212 // the "current" roster returned by one of the above get_*_roster_shape
213 // functions. If a node_restriction is provided, only the files matching
214 // the restriction have their hashes updated.
215 void update_current_roster_from_filesystem(roster_t & ros);
216 void update_current_roster_from_filesystem(roster_t & ros,
217 node_restriction const & mask);
218
219
220 // the "user log" is a file the user can edit as they program to record
221 // changes they make to their source code. Upon commit the file is read
222 // and passed to the edit_comment lua hook. If the commit is a success,
223 // the user log is then blanked. If the commit does not succeed, no
224 // change is made to the user log file.
225
226 void read_user_log(utf8 & dat);
227 void write_user_log(utf8 const & dat);
228 void blank_user_log();
229 bool has_contents_user_log();
230
231 // The full commit text from the edit_comment lua hook is saved before
232 // attempting to extract the various Author: Date: Branch: and Changelog:
233 // values from it in case these values don't appear where they are
234 // expected. Once all the values have been extracted the backup file is
235 // removed.
236
237 void load_commit_text(utf8 & dat);
238 void save_commit_text(utf8 const & dat);
239 void clear_commit_text();
240
241 // the "options map" is another administrative file, stored in
242 // _MTN/options. it keeps a list of name/value pairs which are considered
243 // "persistent options", associated with a particular workspace and
244 // implied unless overridden on the command line.
245 static void get_options(options & opts);
246 // like above, just that it reads the options from the given workspace,
247 // not the one we found earlier
248 static void get_options(system_path const & workspace_root,
249 options & opts);
250 static void set_options(options const & opts,
251 lua_hooks & lua,
252 bool branch_is_sticky = false);
253 static void maybe_set_options(options const & opts, lua_hooks & lua);
254 static void print_option(utf8 const & opt, std::ostream & output);
255
256 // the "bisect" infromation file is a file that records current status
257 // information for the bisect search.
258
259 void get_bisect_info(std::vector<bisect::entry> & bisect);
260 void put_bisect_info(std::vector<bisect::entry> const & bisect);
261 void remove_bisect_info();
262
263 // the "workspace format version" is a nonnegative integer value, stored
264 // in _MTN/format as an unadorned decimal number. at any given time
265 // monotone supports actual use of only one workspace format.
266 // check_format throws an error if the workspace exists but its format
267 // number is not equal to the currently supported format number. it is
268 // automatically called for all commands defined with CMD() (not
269 // CMD_NO_WORKSPACE()). migrate_format is called only on explicit user
270 // request (mtn ws migrate) and will convert a workspace from any older
271 // format to the new one. finally, write_format is called only when a
272 // workspace is created, and simply writes the current workspace format
273 // number to _MTN/format. unlike most routines in this class, these
274 // functions are defined in their own file, work_migration.cc.
275 static void check_format();
276 static void write_format();
277 void migrate_format();
278
279 // the "local dump file' is a debugging file, stored in _MTN/debug. if we
280 // crash, we save some debugging information here.
281
282 static void get_local_dump_path(bookkeeping_path & d_path);
283
284 // the 'inodeprints file' contains inode fingerprints
285
286 bool in_inodeprints_mode();
287 void read_inodeprints(data & dat);
288 void write_inodeprints(data const & dat);
289
290 void enable_inodeprints();
291 void maybe_update_inodeprints(database &);
292 void maybe_update_inodeprints(database &,
293 node_restriction const & mask);
294
295 // the 'ignore file', .mtn-ignore in the root of the workspace, contains a
296 // set of regular expressions that match pathnames. any file or directory
297 // that exists, is unknown, and matches one of these regexps is treated as
298 // if it did not exist, instead of being an unknown file.
299 bool ignore_file(file_path const & path);
300};
301
302// This object turns the workspace ignore_file method into a path predicate,
303// suitable for passing to restriction constructors (for instance).
304struct ignored_file : public path_predicate<file_path>
305{
306 ignored_file(workspace & work) : work(work) {}
307 bool operator()(file_path const &) const;
308
309private:
310 workspace & work;
311};
312
313#endif // __WORK_HH__
314
315// Local Variables:
316// mode: C++
317// fill-column: 76
318// c-file-style: "gnu"
319// indent-tabs-mode: nil
320// End:
321// vim: et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s:

Archive Download this file

Branches

Tags

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