monotone

monotone Mtn Source Tree

Root/work.cc

1// copyright (C) 2002, 2003 graydon hoare <graydon@pobox.com>
2// all rights reserved.
3// licensed to the public under the terms of the GNU GPL (>= 2)
4// see the file COPYING for details
5
6#include <boost/regex.hpp>
7#include <sstream>
8
9#include "app_state.hh"
10#include "basic_io.hh"
11#include "change_set.hh"
12#include "file_io.hh"
13#include "sanity.hh"
14#include "transforms.hh"
15#include "vocab.hh"
16#include "work.hh"
17
18// working copy / book-keeping file code
19
20using namespace boost;
21using namespace std;
22
23std::string const work_file_name("work");
24
25class
26addition_builder
27 : public tree_walker
28{
29 app_state & app;
30 change_set::path_rearrangement & pr;
31 path_set ps;
32public:
33 addition_builder(app_state & a,
34 change_set::path_rearrangement & pr,
35 path_set & p)
36 : app(a), pr(pr), ps(p)
37 {}
38 virtual void visit_file(file_path const & path);
39};
40
41void
42addition_builder::visit_file(file_path const & path)
43{
44 if (app.lua.hook_ignore_file(path))
45 {
46 P(F("skipping ignorable file %s\n") % path);
47 return;
48 }
49
50 if (ps.find(path) != ps.end())
51 {
52 P(F("skipping %s, already accounted for in working copy\n") % path);
53 return;
54 }
55
56 P(F("adding %s to working copy add set\n") % path);
57 ps.insert(path);
58 pr.added_files.insert(path);
59}
60
61void
62build_additions(vector<file_path> const & paths,
63 manifest_map const & man,
64 app_state & app,
65 change_set::path_rearrangement & pr)
66{
67 change_set::path_rearrangement pr_new, pr_concatenated;
68 change_set cs_new;
69
70 path_set ps;
71 extract_path_set(man, ps);
72 apply_path_rearrangement(pr, ps);
73
74 addition_builder build(app, pr_new, ps);
75
76 for (vector<file_path>::const_iterator i = paths.begin(); i != paths.end(); ++i)
77 {
78 N((*i)() != "", F("invalid path ''"));
79 N(directory_exists(*i) || file_exists(*i),
80 F("path %s does not exist\n") % *i);
81
82 walk_tree(*i, build);
83 }
84
85 normalize_path_rearrangement(pr_new);
86 concatenate_rearrangements(pr, pr_new, pr_concatenated);
87 pr = pr_concatenated;
88}
89
90static bool
91known_preimage_path(file_path const & p,
92 path_set const & ps,
93 bool & path_is_directory)
94{
95 std::string path_as_dir = p() + "/";
96 for (path_set::const_iterator i = ps.begin(); i != ps.end(); ++i)
97 {
98 if (*i == p)
99 {
100 path_is_directory = false;
101 return true;
102 }
103 else if ((*i)().find(path_as_dir) == 0)
104 {
105 path_is_directory = true;
106 return true;
107 }
108 }
109 return false;
110}
111
112void
113build_deletions(vector<file_path> const & paths,
114 manifest_map const & man,
115 app_state & app,
116 change_set::path_rearrangement & pr)
117{
118 change_set::path_rearrangement pr_new, pr_concatenated;
119 path_set ps;
120 extract_path_set(man, ps);
121 apply_path_rearrangement(pr, ps);
122
123 for (vector<file_path>::const_iterator i = paths.begin(); i != paths.end(); ++i)
124 {
125 bool dir_p = false;
126
127 N((*i)() != "", F("invalid path ''"));
128
129 if (! known_preimage_path(*i, ps, dir_p))
130 {
131 P(F("skipping %s, not currently tracked\n") % *i);
132 continue;
133 }
134
135 P(F("adding %s to working copy delete set\n") % *i);
136
137 if (dir_p)
138 pr_new.deleted_dirs.insert(*i);
139 else
140 pr_new.deleted_files.insert(*i);
141 }
142
143 normalize_path_rearrangement(pr_new);
144 concatenate_rearrangements(pr, pr_new, pr_concatenated);
145 pr = pr_concatenated;
146}
147
148void
149build_rename(file_path const & src,
150 file_path const & dst,
151 manifest_map const & man,
152 change_set::path_rearrangement & pr)
153{
154 N(src() != "", F("invalid source path ''"));
155 N(dst() != "", F("invalid destination path ''"));
156
157 change_set::path_rearrangement pr_new, pr_concatenated;
158 path_set ps;
159 extract_path_set(man, ps);
160 apply_path_rearrangement(pr, ps);
161
162 bool dir_p = false;
163
164 if (! known_preimage_path(src, ps, dir_p))
165 {
166 P(F("skipping %s, not currently tracked\n") % src);
167 return;
168 }
169
170 P(F("adding %s -> %s to working copy rename set\n") % src % dst);
171 if (dir_p)
172 pr_new.renamed_dirs.insert(std::make_pair(src, dst));
173 else
174 pr_new.renamed_files.insert(std::make_pair(src, dst));
175
176 normalize_path_rearrangement(pr_new);
177 concatenate_rearrangements(pr, pr_new, pr_concatenated);
178 pr = pr_concatenated;
179}
180
181
182void
183extract_path_set(manifest_map const & man,
184 path_set & paths)
185{
186 paths.clear();
187 for (manifest_map::const_iterator i = man.begin();
188 i != man.end(); ++i)
189 paths.insert(manifest_entry_path(i));
190}
191
192// user log file
193
194string const user_log_file_name("log");
195
196void
197get_user_log_path(local_path & ul_path)
198{
199 ul_path = (mkpath(book_keeping_dir) / mkpath(user_log_file_name)).string();
200 L(F("user log path is %s\n") % ul_path);
201}
202
203void
204read_user_log(data & dat)
205{
206 local_path ul_path;
207 get_user_log_path(ul_path);
208
209 if (file_exists(ul_path))
210 {
211 read_data(ul_path, dat);
212 }
213}
214
215void
216blank_user_log()
217{
218 data empty;
219 local_path ul_path;
220 get_user_log_path(ul_path);
221 write_data(ul_path, empty);
222}
223
224bool
225has_contents_user_log()
226{
227 data user_log_message;
228 read_user_log(user_log_message);
229 return user_log_message().length() > 0;
230}
231
232// options map file
233
234string const options_file_name("options");
235
236
237void
238get_options_path(local_path & o_path)
239{
240 o_path = (mkpath(book_keeping_dir) / mkpath(options_file_name)).string();
241 L(F("options path is %s\n") % o_path);
242}
243
244void
245read_options_map(data const & dat, options_map & options)
246{
247 std::istringstream iss(dat());
248 basic_io::input_source src(iss, "MT/options");
249 basic_io::tokenizer tok(src);
250 basic_io::parser parser(tok);
251
252 // don't clear the options which will have settings from the command line
253 // options.clear();
254
255 std::string opt, val;
256 while (parser.symp())
257 {
258 parser.sym(opt);
259 parser.str(val);
260 // options[opt] = val;
261 // use non-replacing insert verses replacing with options[opt] = val;
262 options.insert(make_pair(opt, val));
263 }
264}
265
266void
267write_options_map(data & dat, options_map const & options)
268{
269 std::ostringstream oss;
270 basic_io::printer pr(oss);
271
272 basic_io::stanza st;
273 for (options_map::const_iterator i = options.begin();
274 i != options.end(); ++i)
275 st.push_str_pair(i->first, i->second());
276
277 pr.print_stanza(st);
278 dat = oss.str();
279}
280
281// local dump file
282
283string const local_dump_file_name("debug");
284
285void get_local_dump_path(local_path & d_path)
286{
287 d_path = (mkpath(book_keeping_dir) / mkpath(local_dump_file_name)).string();
288 L(F("local dump path is %s\n") % d_path);
289}
290
291// attribute map file
292
293string const attr_file_name(".mt-attrs");
294
295void
296get_attr_path(file_path & a_path)
297{
298 a_path = (mkpath(attr_file_name)).string();
299 L(F("attribute map path is %s\n") % a_path);
300}
301
302namespace
303{
304 namespace syms
305 {
306 std::string const file("file");
307 }
308}
309
310void
311read_attr_map(data const & dat, attr_map & attr)
312{
313 std::istringstream iss(dat());
314 basic_io::input_source src(iss, ".mt-attrs");
315 basic_io::tokenizer tok(src);
316 basic_io::parser parser(tok);
317
318 std::string file, name, value;
319
320 attr.clear();
321
322 while (parser.symp(syms::file))
323 {
324 parser.sym();
325 parser.str(file);
326 file_path fp(file);
327
328 while (parser.symp() &&
329 !parser.symp(syms::file))
330 {
331 parser.sym(name);
332 parser.str(value);
333 attr[fp][name] = value;
334 }
335 }
336}
337
338void
339write_attr_map(data & dat, attr_map const & attr)
340{
341 std::ostringstream oss;
342 basic_io::printer pr(oss);
343
344 for (attr_map::const_iterator i = attr.begin();
345 i != attr.end(); ++i)
346 {
347 basic_io::stanza st;
348 st.push_str_pair(syms::file, i->first());
349
350 for (std::map<std::string, std::string>::const_iterator j = i->second.begin();
351 j != i->second.end(); ++j)
352 st.push_str_pair(j->first, j->second);
353
354 pr.print_stanza(st);
355 }
356
357 dat = oss.str();
358}
359
360
361void
362apply_attributes(app_state & app, attr_map const & attr)
363{
364 for (attr_map::const_iterator i = attr.begin();
365 i != attr.end(); ++i)
366 for (std::map<std::string, std::string>::const_iterator j = i->second.begin();
367 j != i->second.end(); ++j)
368 app.lua.hook_apply_attribute (j->first,
369 i->first,
370 j->second);
371}
372
373string const encoding_attribute("encoding");
374string const binary_encoding("binary");
375string const default_encoding("default");
376
377static bool find_in_attr_map(attr_map const & attr,
378 file_path const & file,
379 std::string const & attr_key,
380 std::string & attr_val)
381{
382 attr_map::const_iterator f = attr.find(file);
383 if (f == attr.end())
384 return false;
385
386 std::map<std::string, std::string>::const_iterator a = f->second.find(attr_key);
387 if (a == f->second.end())
388 return false;
389
390 attr_val = a->second;
391 return true;
392}
393
394bool get_attribute_from_db(file_path const & file,
395 std::string const & attr_key,
396 manifest_map const & man,
397 std::string & attr_val,
398 app_state & app)
399{
400 file_path fp;
401 get_attr_path(fp);
402 manifest_map::const_iterator i = man.find(fp);
403 if (i == man.end())
404 return false;
405
406 file_id fid = manifest_entry_id(i);
407 if (!app.db.file_version_exists(fid))
408 return false;
409
410 file_data attr_data;
411 app.db.get_file_version(fid, attr_data);
412
413 attr_map attr;
414 read_attr_map(data(attr_data.inner()()), attr);
415
416 return find_in_attr_map(attr, file, attr_key, attr_val);
417}
418
419bool get_attribute_from_working_copy(file_path const & file,
420 std::string const & attr_key,
421 std::string & attr_val)
422{
423 file_path fp;
424 get_attr_path(fp);
425 if (!file_exists(fp))
426 return false;
427
428 data attr_data;
429 read_data(fp, attr_data);
430
431 attr_map attr;
432 read_attr_map(attr_data, attr);
433
434 return find_in_attr_map(attr, file, attr_key, attr_val);
435}

Archive Download this file

Branches

Tags

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