monotone

monotone Mtn Source Tree

Root/app_state.cc

1// Copyright (C) 2002 Graydon Hoare <graydon@pobox.com>
2//
3// This program is made available under the GNU GPL version 2.0 or
4// greater. See the accompanying file COPYING for details.
5//
6// This program is distributed WITHOUT ANY WARRANTY; without even the
7// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
8// PURPOSE.
9
10#include <cstdlib> // for strtoul()
11#include <iostream>
12#include <string>
13#include <vector>
14
15#include <boost/filesystem/convenience.hpp>
16#include <boost/filesystem/exception.hpp>
17#include <boost/filesystem/operations.hpp>
18#include <boost/filesystem/path.hpp>
19
20#include "botan/pubkey.h"
21#include "botan/rsa.h"
22
23#include "app_state.hh"
24#include "charset.hh"
25#include "database.hh"
26#include "file_io.hh"
27#include "platform.hh"
28#include "sanity.hh"
29#include "ui.hh"
30#include "work.hh"
31
32using std::exception;
33using std::map;
34using std::string;
35using std::vector;
36using std::vector;
37
38static string const database_option("database");
39static string const branch_option("branch");
40static string const key_option("key");
41static string const keydir_option("keydir");
42
43app_state::app_state()
44 : branch_name(""), db(system_path()),
45 keys(this), recursive(false),
46 stdhooks(true), rcfiles(true), diffs(false),
47 no_merges(false), set_default(false),
48 verbose(false), date_set(false),
49 search_root(current_root_path()),
50 depth(-1), last(-1), next(-1),
51 diff_format(unified_diff), diff_args_provided(false),
52 diff_show_encloser(true),
53 execute(false), bind_address(""), bind_port(""),
54 bind_stdio(false), use_transport_auth(true),
55 missing(false), unknown(false),
56 confdir(get_default_confdir()),
57 have_set_key_dir(false), no_files(false),
58 requested_help(false)
59{
60 db.set_app(this);
61 lua.set_app(this);
62 keys.set_key_dir(confdir / "keys");
63 set_prog_name(utf8(string("mtn")));
64}
65
66app_state::~app_state()
67{
68}
69
70void
71app_state::set_is_explicit_option (int option_id)
72{
73 explicit_option_map[option_id] = true;
74}
75
76bool
77app_state::is_explicit_option(int option_id) const
78{
79 map<int, bool>::const_iterator i = explicit_option_map.find(option_id);
80 if (i == explicit_option_map.end()) return false;
81 return i->second;
82}
83
84void
85app_state::allow_workspace()
86{
87 L(FL("initializing from directory %s") % fs::initial_path().string());
88 found_workspace = find_and_go_to_workspace(search_root);
89
90 if (found_workspace)
91 {
92 // We read the options, but we don't process them here. That's
93 // done with process_options().
94 read_options();
95
96 if (global_sanity.filename.empty())
97 {
98 bookkeeping_path dump_path;
99 get_local_dump_path(dump_path);
100 L(FL("setting dump path to %s") % dump_path);
101 // The 'true' means that, e.g., if we're running checkout,
102 // then it's okay for dumps to go into our starting working
103 // dir's _MTN rather than the new workspace dir's _MTN.
104 global_sanity.filename = system_path(dump_path, false);
105 }
106 }
107 load_rcfiles();
108}
109
110void
111app_state::process_options()
112{
113 if (found_workspace) {
114 if (!options[database_option]().empty())
115 {
116 system_path dbname = system_path(options[database_option]);
117 db.set_filename(dbname);
118 }
119
120 if (!options[keydir_option]().empty())
121 {
122 system_path keydir = system_path(options[keydir_option]);
123 set_key_dir(keydir);
124 }
125
126 if (branch_name().empty() && !options[branch_option]().empty())
127 branch_name = options[branch_option];
128
129 L(FL("branch name is '%s'") % branch_name());
130
131 if (!options[key_option]().empty())
132 internalize_rsa_keypair_id(options[key_option],
133 signing_key);
134 }
135}
136
137void
138app_state::require_workspace(string const & explanation)
139{
140 N(found_workspace,
141 F("workspace required but not found%s%s")
142 % (explanation.empty() ? "" : "\n") % explanation);
143 write_options();
144}
145
146void
147app_state::create_workspace(system_path const & new_dir)
148{
149 N(!new_dir.empty(), F("invalid directory ''"));
150
151 L(FL("creating workspace in %s") % new_dir);
152
153 mkdir_p(new_dir);
154 go_to_workspace(new_dir);
155
156 N(!directory_exists(bookkeeping_root),
157 F("monotone bookkeeping directory '%s' already exists in '%s'")
158 % bookkeeping_root % new_dir);
159
160 L(FL("creating bookkeeping directory '%s' for workspace in '%s'")
161 % bookkeeping_root % new_dir);
162
163 mkdir_p(bookkeeping_root);
164
165 make_branch_sticky();
166
167 write_options();
168
169 blank_user_log();
170
171 if (lua.hook_use_inodeprints())
172 enable_inodeprints();
173
174 load_rcfiles();
175}
176
177void
178app_state::set_database(system_path const & filename)
179{
180 if (!filename.empty()) db.set_filename(filename);
181
182 options[database_option] = filename.as_internal();
183}
184
185void
186app_state::set_key_dir(system_path const & filename)
187{
188 if (!filename.empty())
189 {
190 keys.set_key_dir(filename);
191 have_set_key_dir = true;
192 }
193
194 options[keydir_option] = filename.as_internal();
195}
196
197void
198app_state::set_branch(utf8 const & branch)
199{
200 branch_name = branch();
201}
202
203void
204app_state::make_branch_sticky()
205{
206 options[branch_option] = branch_name();
207 if (found_workspace)
208 {
209 // Already have a workspace, can (must) write options directly,
210 // because no-one else will do so. If we don't have a workspace
211 // yet, then require_workspace (for instance) will call
212 // write_options when it finds one.
213 write_options();
214 }
215}
216
217void
218app_state::set_signing_key(utf8 const & key)
219{
220 internalize_rsa_keypair_id(key, signing_key);
221
222 options[key_option] = key;
223}
224
225void
226app_state::add_key_to_push(utf8 const & key)
227{
228 rsa_keypair_id k;
229 internalize_rsa_keypair_id(key, k);
230 keys_to_push.push_back(k);
231}
232
233void
234app_state::set_root(system_path const & path)
235{
236 require_path_is_directory
237 (path,
238 F("search root '%s' does not exist") % path,
239 F("search root '%s' is not a directory\n") % path);
240 search_root = path;
241 L(FL("set search root to %s") % search_root);
242}
243
244void
245app_state::set_message(utf8 const & m)
246{
247 message = m;
248}
249
250void
251app_state::set_message_file(utf8 const & m)
252{
253 message_file = m;
254}
255
256void
257app_state::set_date(utf8 const & d)
258{
259 try
260 {
261 // boost::posix_time can parse "basic" ISO times, of the form
262 // 20000101T120000, but not "extended" ISO times, of the form
263 // 2000-01-01T12:00:00. So convert one to the other.
264 string tmp = d();
265 string::size_type pos = 0;
266 while ((pos = tmp.find_first_of("-:")) != string::npos)
267 tmp.erase(pos, 1);
268 date = boost::posix_time::from_iso_string(tmp);
269 date_set = true;
270 }
271 catch (exception &e)
272 {
273 N(false, F("failed to parse date string '%s': %s")
274 % d % e.what());
275 }
276}
277
278void
279app_state::set_author(utf8 const & a)
280{
281 author = a;
282}
283
284void
285app_state::set_depth(long d)
286{
287 N(d >= 0,
288 F("negative depth not allowed\n"));
289 depth = d;
290}
291
292void
293app_state::set_last(long l)
294{
295 N(l > 0,
296 F("illegal argument to --last: cannot be zero or negative\n"));
297 last = l;
298}
299
300void
301app_state::set_next(long l)
302{
303 N(l > 0,
304 F("illegal argument to --next: cannot be zero or negative\n"));
305 next = l;
306}
307
308void
309app_state::set_pidfile(system_path const & p)
310{
311 pidfile = p;
312}
313
314void
315app_state::add_revision(utf8 const & selector)
316{
317 revision_selectors.push_back(selector);
318}
319
320void
321app_state::add_exclude(utf8 const & exclude_pattern)
322{
323 exclude_patterns.push_back(exclude_pattern);
324}
325
326void
327app_state::set_diff_format(diff_type dtype)
328{
329 diff_format = dtype;
330}
331
332void
333app_state::set_diff_args(utf8 const & args)
334{
335 diff_args_provided = true;
336 diff_args = args;
337}
338
339void
340app_state::set_stdhooks(bool b)
341{
342 stdhooks = b;
343}
344
345void
346app_state::set_rcfiles(bool b)
347{
348 rcfiles = b;
349}
350
351void
352app_state::set_verbose(bool b)
353{
354 verbose = b;
355}
356
357void
358app_state::set_recursive(bool r)
359{
360 recursive = r;
361}
362
363void
364app_state::set_prog_name(utf8 const & name)
365{
366 prog_name = name;
367 ui.set_prog_name(name());
368}
369
370void
371app_state::add_rcfile(utf8 const & filename)
372{
373 extra_rcfiles.push_back(filename);
374}
375
376void
377app_state::set_confdir(system_path const & cd)
378{
379 confdir = cd;
380 if (!have_set_key_dir)
381 keys.set_key_dir(cd / "keys");
382}
383
384system_path
385app_state::get_confdir()
386{
387 return confdir;
388}
389
390// rc files are loaded after we've changed to the workspace so that
391// _MTN/monotonerc can be loaded between ~/.monotone/monotonerc and other
392// rcfiles.
393
394void
395app_state::load_rcfiles()
396{
397 // Built-in rc settings are defaults.
398
399 if (stdhooks)
400 lua.add_std_hooks();
401
402 // ~/.monotone/monotonerc overrides that, and
403 // _MTN/monotonerc overrides *that*.
404
405 if (rcfiles)
406 {
407 system_path default_rcfile;
408 bookkeeping_path workspace_rcfile;
409 lua.default_rcfilename(default_rcfile);
410 lua.workspace_rcfilename(workspace_rcfile);
411 lua.load_rcfile(default_rcfile, false);
412 lua.load_rcfile(workspace_rcfile, false);
413 }
414
415 // Command-line rcfiles override even that.
416
417 for (vector<utf8>::const_iterator i = extra_rcfiles.begin();
418 i != extra_rcfiles.end(); ++i)
419 {
420 lua.load_rcfile(*i);
421 }
422 db.set_vcache_max_size();
423}
424
425void
426app_state::read_options()
427{
428 bookkeeping_path o_path;
429 get_options_path(o_path);
430 try
431 {
432 if (path_exists(o_path))
433 {
434 data dat;
435 read_data(o_path, dat);
436 read_options_map(dat, options);
437 }
438 }
439 catch(exception &)
440 {
441 W(F("Failed to read options file %s") % o_path);
442 }
443}
444
445void
446app_state::write_options()
447{
448 bookkeeping_path o_path;
449 get_options_path(o_path);
450 try
451 {
452 data dat;
453 write_options_map(dat, options);
454 write_data(o_path, dat);
455 }
456 catch(exception &)
457 {
458 W(F("Failed to write options file %s") % o_path);
459 }
460}
461
462// Local Variables:
463// mode: C++
464// fill-column: 76
465// c-file-style: "gnu"
466// indent-tabs-mode: nil
467// End:
468// 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