monotone

monotone Mtn Source Tree

Root/src/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 // In Botan 1.9.9, the DataSink_Stream cannot be instantiated per
160 // se. As 1.10.1 is already out, let's simply disable support for
161 // that specific (testing) version of botan.
162 E(linked_botan_version != BOTAN_VERSION_CODE_FOR(1,9,9), origin::system,
163 F("monotone does not support Botan 1.9.9"));
164
165#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,7,7)
166 // motonote binary compiled against botan younger than 1.7.7
167 E(linked_botan_version >= BOTAN_VERSION_CODE_FOR(1,6,3), origin::system,
168 F("this monotone binary requires Botan 1.6.3 or newer"));
169 E(linked_botan_version < BOTAN_VERSION_CODE_FOR(1,7,7), origin::system,
170 F("this monotone binary does not work with Botan 1.7.7 or newer"));
171
172#elif BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,7,22)
173 // motonote binary compiled against botan 1.7.7 - 1.7.21
174 E(linked_botan_version >= BOTAN_VERSION_CODE_FOR(1,7,7), origin::system,
175 F("this monotone binary requires Botan 1.7.7 or newer"));
176 // While compiling against 1.7.22 or newer is recommended, because it
177 // enables new features of Botan, the monotone binary compiled against
178 // Botan 1.7.21 and before should still work with newer Botan version,
179 // including all of the stable branch 1.8.x, up to and including
180 // 1.9.3.
181 E(linked_botan_version < BOTAN_VERSION_CODE_FOR(1,9,4), origin::system,
182 F("this monotone binary does not work with Botan 1.9.4 or newer"));
183
184#elif BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,9,4)
185 // motonote binary compiled against botan 1.7.22 - 1.9.3
186 E(linked_botan_version >= BOTAN_VERSION_CODE_FOR(1,7,22), origin::system,
187 F("this monotone binary requires Botan 1.7.22 or newer"));
188 E(linked_botan_version < BOTAN_VERSION_CODE_FOR(1,9,4), origin::system,
189 F("this monotone binary does not work with Botan 1.9.4 or newer"));
190
191#elif BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,9,11)
192 // motonote binary compiled against botan 1.9.4 - 1.9.10
193#pragma message ( "The resulting monotone binary won't be able to run with any stable release of botan." )
194 E(linked_botan_version >= BOTAN_VERSION_CODE_FOR(1,9,4), origin::system,
195 F("this monotone binary requires Botan 1.9.4 or newer"));
196 E(linked_botan_version < BOTAN_VERSION_CODE_FOR(1,9,11), origin::system,
197 F("this monotone binary does not work with Botan 1.9.11 or newer"));
198
199#else
200 // motonote binary compiled against botan 1.9.11 and newer
201 E(linked_botan_version >= BOTAN_VERSION_CODE_FOR(1,9,11), origin::system,
202 F("this monotone binary requires Botan 1.9.11 or newer"));
203#endif
204
205
206 app_state app;
207 try
208 {
209 // read global options first
210 // command specific options will be read below
211 app.reset_info.cmdline_args = args;
212
213 options::opts::all_options().instantiate(&app.opts)
214 .from_command_line(app.reset_info.cmdline_args,
215 option::concrete_option_set::preparse);
216
217 if (app.opts.version_given)
218 {
219 print_version();
220 return 0;
221 }
222
223 // at this point we allow a workspace (meaning search for it,
224 // and if found, change directory to it
225 // Certain commands may subsequently require a workspace or fail
226 // if we didn't find one at this point.
227 if (app.opts.no_workspace)
228 {
229 workspace::found = false;
230 }
231 else
232 {
233 workspace::found = find_and_go_to_workspace(app.opts.root);
234 }
235
236 // Load all available monotonercs. If we found a workspace above,
237 // we'll pick up _MTN/monotonerc as well as the user's monotonerc.
238 app.lua.load_rcfiles(app.opts);
239
240 // figure out what command is being run
241 // this needs to be after the hooks are loaded, because new
242 // command names may have been added with the alias_command()
243 // lua extension function
244 commands::command_id cmd_id;
245 if (!app.opts.args.empty())
246 {
247 cmd_id = commands::complete_command(app.opts.args);
248 }
249
250 // check if the user specified default arguments for this command
251 if (!cmd_id.empty())
252 app.lua.hook_get_default_command_options(cmd_id,
253 app.reset_info.default_args);
254
255 if (app.opts.log_given)
256 {
257 ui.redirect_log_to(app.opts.log);
258 }
259 global_sanity.set_verbosity(app.opts.verbosity, true);
260 if (app.opts.dump_given)
261 {
262 global_sanity.set_dump_path(app.opts.dump.as_external());
263 }
264 else if (workspace::found)
265 {
266 bookkeeping_path dump_path;
267 workspace::get_local_dump_path(dump_path);
268
269 // The 'false' means that, e.g., if we're running checkout,
270 // then it's okay for dumps to go into our starting working
271 // dir's _MTN rather than the new workspace dir's _MTN.
272 global_sanity.set_dump_path(system_path(dump_path, false)
273 .as_external());
274 }
275 else if (app.opts.conf_dir_given || !app.opts.no_default_confdir)
276 global_sanity.set_dump_path((app.opts.conf_dir / "dump")
277 .as_external());
278
279 app.lua.hook_note_mtn_startup(args);
280
281 // stop here if they asked for help
282 if (app.opts.help)
283 throw usage(cmd_id);
284
285 // main options processed, now invoke the
286 // sub-command w/ remaining args
287 if (cmd_id.empty())
288 throw usage(commands::command_id());
289
290
291 // as soon as a command requires a workspace, this is set to true
292 workspace::used = false;
293
294 commands::process(app, cmd_id, app.opts.args);
295
296 workspace::maybe_set_options(app.opts, app.lua);
297
298 // The command will raise any problems itself through
299 // exceptions. If we reach this point, it is because it
300 // worked correctly.
301 return 0;
302 }
303 catch (usage & u)
304 {
305 ui.inform_usage(u, app.opts);
306 return app.opts.help ? 0 : 2;
307 }
308 }
309 catch (std::exception const & ex)
310 {
311 return ui.fatal_exception(ex);
312 }
313 catch (...)
314 {
315 return ui.fatal_exception();
316 }
317
318 // control cannot reach this point
319 ui.fatal("impossible: reached end of cpp_main");
320 return 3;
321}
322
323// Local Variables:
324// mode: C++
325// fill-column: 76
326// c-file-style: "gnu"
327// indent-tabs-mode: nil
328// End:
329// 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