monotone

monotone Mtn Source Tree

Root/monotone.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
11#include "base.hh"
12#include <iterator>
13#include <fstream>
14#include <sstream>
15#include <locale.h>
16#include <stdlib.h>
17
18#include <sqlite3.h>
19#include <botan/botan.h>
20
21#include "app_state.hh"
22#include "database.hh"
23#include "botan_pipe_cache.hh"
24#include "commands.hh"
25#include "sanity.hh"
26#include "file_io.hh"
27#include "charset.hh"
28#include "ui.hh"
29#include "mt_version.hh"
30#include "option.hh"
31#include "paths.hh"
32#include "simplestring_xform.hh"
33#include "platform.hh"
34#include "work.hh"
35
36using std::string;
37using std::ios_base;
38using std::ostringstream;
39using std::set;
40using std::string;
41using std::vector;
42using std::ios_base;
43
44// main option processing and exception handling code
45
46// options are split into two categories. the first covers global options,
47// which globally affect program behaviour. the second covers options
48// specific to one or more commands. these command-specific options are
49// defined in a single group, with the intent that any command-specific
50// option means the same thing for any command that uses it.
51//
52// "ui" is a global object, through which all messages to the user go.
53// see ui.hh for it
54//
55// "cmds" is a static table in commands.cc which associates top-level
56// commands, given on the command-line, to various version control tasks.
57//
58// "app_state" is a non-static object type which contains all the
59// application state (filesystem, database, network, lua interpreter,
60// etc). you can make more than one of these, and feed them to a command in
61// the command table.
62
63// this file defines cpp_main, which does option processing and sub-command
64// dispatching, and provides the outermost exception catch clauses. it is
65// called by main, in unix/main.cc or win32/main.cc; that function is
66// responsible for trapping fatal conditions reported by the operating
67// system (signals, win32 structured exceptions, etc).
68
69// this program should *never* unexpectedly terminate without dumping some
70// diagnostics. if the fatal condition is an invariant check or anything
71// else that produces a C++ exception caught in this file, the debug logs
72// will be dumped out. if the fatal condition is only caught in the lower-
73// level handlers in main.cc, at least we'll get a friendly error message.
74
75// define the global objects needed by botan_pipe_cache.hh
76pipe_cache_cleanup * global_pipe_cleanup_object;
77Botan::Pipe * unfiltered_pipe;
78static unsigned char unfiltered_pipe_cleanup_mem[sizeof(cached_botan_pipe)];
79
80void
81mtn_terminate_handler()
82{
83 ui.fatal(F("std::terminate() - "
84 "exception thrown while handling another exception"));
85 exit(3);
86}
87
88int
89cpp_main(int argc, char ** argv)
90{
91 // go-go gadget i18n
92 char const * localename = setlocale(LC_ALL, "");
93 bindtextdomain(PACKAGE, get_locale_dir().c_str());
94 textdomain(PACKAGE);
95
96 // set up global ui object - must occur before anything that might try to
97 // issue a diagnostic
98 ui_library acquire_ui;
99
100 std::set_terminate(&mtn_terminate_handler);
101
102 // we want to catch any early informative_failures due to charset
103 // conversion etc
104 try
105 {
106 // Set up the global sanity object. No destructor is needed and
107 // therefore no wrapper object is needed either. This has the
108 // side effect of making the 'prog_name' global usable.
109 global_sanity.initialize(argc, argv, localename);
110
111 // Set up secure memory allocation etc
112 Botan::LibraryInitializer acquire_botan("thread_safe=0 selftest=0 "
113 "seed_rng=1 use_engines=0 "
114 "secure_memory=1 fips140=0");
115
116 // and caching for botan pipes
117 pipe_cache_cleanup acquire_botan_pipe_caching;
118 unfiltered_pipe = new Botan::Pipe;
119 new (unfiltered_pipe_cleanup_mem) cached_botan_pipe(unfiltered_pipe);
120
121 class _DbCacheEmptier {
122 public:
123 _DbCacheEmptier() { }
124 ~_DbCacheEmptier() { database::reset_cache(); }
125 } db_cache_emptier;
126
127 // Record where we are. This has to happen before any use of
128 // paths.hh objects.
129 save_initial_path();
130
131 // decode all argv values into a UTF-8 array
132 args_vector args;
133 for (int i = 1; i < argc; ++i)
134 {
135 external ex(argv[i]);
136 utf8 ut;
137 system_to_utf8(ex, ut);
138 args.push_back(arg_type(ut));
139 }
140
141#ifdef SUPPORT_SQLITE_BEFORE_3003014
142 E(sqlite3_libversion_number() >= 3003008, origin::system,
143 F("This monotone binary requires at least SQLite 3.3.8 to run."));
144#else
145 E(sqlite3_libversion_number() >= 3003014, origin::system,
146 F("This monotone binary requires at least SQLite 3.3.14 to run."));
147#endif
148
149 // check the botan library version we got linked against.
150 u32 linked_botan_version = BOTAN_VERSION_CODE_FOR(
151 Botan::version_major(), Botan::version_minor(),
152 Botan::version_patch());
153
154 // Botan 1.7.14 has an incompatible API change, which got reverted
155 // again in 1.7.15. Thus we do not care to support 1.7.14.
156 E(linked_botan_version != BOTAN_VERSION_CODE_FOR(1,7,14), origin::system,
157 F("Monotone does not support Botan 1.7.14."));
158
159#if BOTAN_VERSION_CODE <= BOTAN_VERSION_CODE_FOR(1,7,6)
160 E(linked_botan_version >= BOTAN_VERSION_CODE_FOR(1,6,3), origin::system,
161 F("This monotone binary requires Botan 1.6.3 or newer."));
162 E(linked_botan_version <= BOTAN_VERSION_CODE_FOR(1,7,6), origin::system,
163 F("This monotone binary does not work with Botan newer than 1.7.6."));
164#elif BOTAN_VERSION_CODE <= BOTAN_VERSION_CODE_FOR(1,7,22)
165 E(linked_botan_version > BOTAN_VERSION_CODE_FOR(1,7,6), origin::system,
166 F("This monotone binary requires Botan 1.7.7 or newer."));
167 // While compiling against 1.7.22 or newer is recommended, because
168 // it enables new features of Botan, the monotone binary compiled
169 // against Botan 1.7.21 and before should still work with newer Botan
170 // versions, including all of the stable branch 1.8.x.
171 E(linked_botan_version < BOTAN_VERSION_CODE_FOR(1,9,0), origin::system,
172 F("This monotone binary does not work with Botan 1.9.x."));
173#else
174 E(linked_botan_version > BOTAN_VERSION_CODE_FOR(1,7,22), origin::system,
175 F("This monotone binary requires Botan 1.7.22 or newer."));
176 E(linked_botan_version < BOTAN_VERSION_CODE_FOR(1,9,0), origin::system,
177 F("This monotone binary does not work with Botan 1.9.x."));
178#endif
179
180 app_state app;
181 try
182 {
183 // read global options first
184 // command specific options will be read below
185 app.reset_info.cmdline_args = args;
186
187 options::opts::all_options().instantiate(&app.opts)
188 .from_command_line(app.reset_info.cmdline_args,
189 option::concrete_option_set::preparse);
190
191 if (app.opts.version_given)
192 {
193 print_version();
194 return 0;
195 }
196
197 // at this point we allow a workspace (meaning search for it,
198 // and if found, change directory to it
199 // Certain commands may subsequently require a workspace or fail
200 // if we didn't find one at this point.
201 if (app.opts.no_workspace)
202 {
203 workspace::found = false;
204 }
205 else
206 {
207 workspace::found = find_and_go_to_workspace(app.opts.root);
208 }
209
210 // Load all available monotonercs. If we found a workspace above,
211 // we'll pick up _MTN/monotonerc as well as the user's monotonerc.
212 app.lua.load_rcfiles(app.opts);
213
214 // figure out what command is being run
215 // this needs to be after the hooks are loaded, because new
216 // command names may have been added with the alias_command()
217 // lua extension function
218 commands::command_id cmd_id;
219 if (!app.opts.args.empty())
220 {
221 cmd_id = commands::complete_command(app.opts.args);
222 }
223
224 // check if the user specified default arguments for this command
225 if (!cmd_id.empty())
226 app.lua.hook_get_default_command_options(cmd_id,
227 app.reset_info.default_args);
228
229 if (app.opts.log_given)
230 {
231 ui.redirect_log_to(app.opts.log);
232 }
233 global_sanity.set_verbosity(app.opts.verbosity, true);
234 if (app.opts.dump_given)
235 {
236 global_sanity.set_dump_path(app.opts.dump.as_external());
237 }
238 else if (workspace::found)
239 {
240 bookkeeping_path dump_path;
241 workspace::get_local_dump_path(dump_path);
242
243 // The 'false' means that, e.g., if we're running checkout,
244 // then it's okay for dumps to go into our starting working
245 // dir's _MTN rather than the new workspace dir's _MTN.
246 global_sanity.set_dump_path(system_path(dump_path, false)
247 .as_external());
248 }
249 else if (app.opts.conf_dir_given || !app.opts.no_default_confdir)
250 global_sanity.set_dump_path((app.opts.conf_dir / "dump")
251 .as_external());
252
253 app.lua.hook_note_mtn_startup(args);
254
255 // stop here if they asked for help
256 if (app.opts.help)
257 throw usage(cmd_id);
258
259 // main options processed, now invoke the
260 // sub-command w/ remaining args
261 if (cmd_id.empty())
262 throw usage(commands::command_id());
263
264
265 // as soon as a command requires a workspace, this is set to true
266 workspace::used = false;
267
268 commands::process(app, cmd_id, app.opts.args);
269
270 workspace::maybe_set_options(app.opts, app.lua);
271
272 // The command will raise any problems itself through
273 // exceptions. If we reach this point, it is because it
274 // worked correctly.
275 return 0;
276 }
277 catch (usage & u)
278 {
279 ui.inform_usage(u, app.opts);
280 return app.opts.help ? 0 : 2;
281 }
282 }
283 catch (std::exception const & ex)
284 {
285 return ui.fatal_exception(ex);
286 }
287 catch (...)
288 {
289 return ui.fatal_exception();
290 }
291
292 // control cannot reach this point
293 ui.fatal("impossible: reached end of cpp_main");
294 return 3;
295}
296
297// Local Variables:
298// mode: C++
299// fill-column: 76
300// c-file-style: "gnu"
301// indent-tabs-mode: nil
302// End:
303// 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