# # # patch "commands.cc" # from [7dd728ae752fa4940c65085f5a208e8cc6a12e9a] # to [c6b586adb73a7375a303a9e388152b3dad56ca34] # # patch "mtn_cvs/Makefile.am" # from [81f7f9adfc77c2e7d65669ecc9169850fbbeac78] # to [09bb01b17cbf25fbe3d7744d461b035aef617307] # # patch "mtn_cvs/mtn_automate.cc" # from [f7ca4a67ed3e283b91a4bb3779e40ac79c9e8a89] # to [536e4833addf58effaf4baf7140530ee230f497e] # # patch "mtn_cvs/mtn_cvs.cc" # from [8da608fa00e819ea3d87c83d1c8186acf493628e] # to [0a6d98189e233c13cb8a11fe8364fbdc41243841] # # patch "mtn_cvs/mtn_pipe.cc" # from [1c1fd5cd881e1e26451e1a75bf81f30690857431] # to [e7301e40a135e59b2e38b710ef9a6e6f21e60379] # # patch "mtn_cvs/mtncvs_state.cc" # from [79a1b44a8208a8adb1e22b7612fa83a1c4dd235e] # to [99c95e36c223a1a3884cf1687586ac07ba2204d2] # ============================================================ --- commands.cc 7dd728ae752fa4940c65085f5a208e8cc6a12e9a +++ commands.cc c6b586adb73a7375a303a9e388152b3dad56ca34 @@ -42,6 +42,7 @@ using std::vector; using std::strlen; using std::vector; +#ifndef LIBMTN_COMPILE CMD_GROUP(__root__, "__root__", "", NULL, "", ""); // @@ -95,6 +96,7 @@ CMD_GROUP(user, "user", "", CMD_REF(__ro CMD_GROUP(user, "user", "", CMD_REF(__root__), N_("Commands defined by the user"), ""); +#endif // this file defines the task-oriented "top level" commands which can be // issued as part of a monotone command line. the command line can only @@ -766,6 +768,7 @@ namespace commands L(FL("executing command '%s'") % visibleid); +#ifndef LIBMTN_COMPILE // at this point we process the data from _MTN/options if // the command needs it. if (cmd->use_workspace_options()) @@ -773,6 +776,7 @@ namespace commands workspace::check_ws_format(); workspace::get_ws_options(app.opts); } +#endif cmd->exec(app, ident, args); } ============================================================ --- mtn_cvs/Makefile.am 81f7f9adfc77c2e7d65669ecc9169850fbbeac78 +++ mtn_cvs/Makefile.am 09bb01b17cbf25fbe3d7744d461b035aef617307 @@ -7,7 +7,7 @@ libmtn_a_SOURCES=../netxx_pipe.cc ../san ../simplestring_xform.cc ../constants.cc ../xdelta.cc \ ../commands.cc ../basic_io.cc botan/md5.cpp piece_table.cc \ ../mtn-sanity.cc ../package_revision.c ../option.cc \ - ../file_io.cc ../ssh_agent.cc + ../file_io.cc ../ssh_agent.cc ../specialized_lexical_cast.cc ../gzip.cc bin_PROGRAMS = mtn_cvs ============================================================ --- mtn_cvs/mtn_automate.cc f7ca4a67ed3e283b91a4bb3779e40ac79c9e8a89 +++ mtn_cvs/mtn_automate.cc 536e4833addf58effaf4baf7140530ee230f497e @@ -1,9 +1,10 @@ // -*- mode: C++; c-file-style: "gnu"; indent-tabs-mode: nil -*- // copyright (C) 2006 Christof Petig // all rights reserved. // licensed to the public under the terms of the GNU GPL (>= 2) // see the file COPYING for details +#include "../base.hh" #include "mtn_automate.hh" #include #include @@ -166,7 +167,9 @@ static void print_cset(basic_io::printer { basic_io::stanza st; st.push_file_pair(syms::add_file, i->first); - st.push_hex_pair(syms::content, i->second.inner()); + hexenc hex; + encode_hexenc(i->second.inner(), hex); + st.push_hex_pair(syms::content, hex); printer.print_stanza(st); } @@ -175,8 +178,11 @@ static void print_cset(basic_io::printer { basic_io::stanza st; st.push_file_pair(syms::patch, i->first); - st.push_hex_pair(syms::from, i->second.first.inner()); - st.push_hex_pair(syms::to, i->second.second.inner()); + hexenc hex; + encode_hexenc(i->second.first.inner(), hex); + st.push_hex_pair(syms::from, hex); + encode_hexenc(i->second.second.inner(), hex); + st.push_hex_pair(syms::to, hex); printer.print_stanza(st); } @@ -212,7 +218,9 @@ revision_id mtn_automate::put_revision(r // changeset stanza basic_io::stanza st; - st.push_hex_pair(syms::old_revision, parent.inner()); + hexenc hex; + encode_hexenc(parent.inner(), hex); + st.push_hex_pair(syms::old_revision, hex); printer.print_stanza(st); print_cset(printer, changes); std::vector args(1,printer.buf); @@ -498,10 +506,12 @@ mtn_automate::revision_t mtn_automate::g return result; } +#if 0 template <> void dump(file_path const& fp, string & out) { out=fp.as_internal(); } +#endif static std::string print_sync_info(mtn_automate::sync_map_t const& data) { basic_io::printer printer; ============================================================ --- mtn_cvs/mtn_cvs.cc 8da608fa00e819ea3d87c83d1c8186acf493628e +++ mtn_cvs/mtn_cvs.cc 0a6d98189e233c13cb8a11fe8364fbdc41243841 @@ -26,6 +26,8 @@ #include #include #include +#include "../botan_pipe_cache.hh" +#include "../simplestring_xform.hh" // options are split into two categories. the first covers global options, // which globally affect program behaviour. the second covers options @@ -57,31 +59,13 @@ // level handlers in main.cc, at least we'll get a friendly error message. -// Wrapper class to ensure Botan is properly initialized and deinitialized. -struct botan_library -{ - botan_library() { - Botan::InitializerOptions options("thread_safe=0 selftest=0 seed_rng=1 " - "use_engines=0 secure_memory=1 " - "fips140=0"); - Botan::LibraryInitializer::initialize(options); - } - ~botan_library() { - Botan::LibraryInitializer::deinitialize(); - } -}; - -// Similarly, for the global ui object. (We do not want to use global -// con/destructors for this, as they execute outside the protection of -// main.cc's signal handlers.) +// Wrapper class which ensures proper setup and teardown of the global ui +// object. (We do not want to use global con/destructors for this, as they +// execute outside the protection of main.cc's signal handlers.) struct ui_library { - ui_library() { - ui.initialize(); - } - ~ui_library() { - ui.deinitialize(); - } + ui_library() { ui.initialize(); } + ~ui_library() { ui.deinitialize(); } }; // fake app_state ctor/dtor, we do not use this class at all @@ -89,8 +73,8 @@ lua_hooks::~lua_hooks() {} app_state::~app_state() {} lua_hooks::lua_hooks(app_state * app) {} lua_hooks::~lua_hooks() {} -database::database(app_state &app) : imp(), lua(app.lua) {} -database::~database() {} +//database::database(app_state &app) : imp(), lua(app.lua) {} +//database::~database() {} //ssh_agent::ssh_agent() {} //ssh_agent::~ssh_agent() {} @@ -99,6 +83,9 @@ CMD_GROUP(network, "network", "", CMD_RE CMD_GROUP(network, "network", "", CMD_REF(__root__), N_("Commands that access the network"), ""); +CMD_GROUP(informative, "informative", "", CMD_REF(__root__), + N_("Commands for information retrieval"), + ""); // missing: compression level (-z), cvs-branch (-r), since (-D) CMD(pull, "pull", "", CMD_REF(network), @@ -106,7 +93,7 @@ CMD(pull, "pull", "", CMD_REF(network), N_("(re-)import a module from a remote cvs repository"), "", options::opts::branch | options::opts::since | options::opts::full) { - if (args.size() == 1 || args.size() > 3) throw usage(name); + if (args.size() == 1 || args.size() > 3) throw usage(execid); std::string repository,module,branch; if (args.size() >= 2) @@ -126,7 +113,7 @@ CMD(push, "push", "", CMD_REF(network), N_("commit changes in local database to a remote cvs repository"), "", options::opts::branch | options::opts::revision | options::opts::first) { - if (args.size() == 1 || args.size() > 3) throw usage(name); + if (args.size() == 1 || args.size() > 3) throw usage(execid); std::string repository,module,branch; if (args.size() >= 2) @@ -148,11 +135,11 @@ CMD(takeover, "takeover", "", CMD_REF(wo N_("put a CVS working directory under monotone's control"), "", options::opts::branch) { - if (args.size() > 1) throw usage(name); + if (args.size() > 1) throw usage(execid); std::string module; if (args.size() == 1) module = idx(args, 0)(); mtncvs_state &myapp=mtncvs_state::upcast(app); - N(!myapp.opts.branch_name().empty(), F("no destination branch specified\n")); + N(!myapp.opts.branchname().empty(), F("no destination branch specified\n")); cvs_sync::takeover(myapp, module); } @@ -164,7 +151,7 @@ CMD(test, "test", "", CMD_REF(debug), "" N_("attempt to parse certs"), "", options::opts::revision) { - if (args.size()) throw usage(name); + if (args.size()) throw usage(execid); mtncvs_state &myapp=mtncvs_state::upcast(app); cvs_sync::test(myapp); } @@ -224,31 +211,52 @@ void localize_monotone() } } -// read command-line options and return the command name -string read_options(options & opts, vector args) +// define the global objects needed by botan_pipe_cache.hh +pipe_cache_cleanup * global_pipe_cleanup_object; +Botan::Pipe * unfiltered_pipe; +static unsigned char unfiltered_pipe_cleanup_mem[sizeof(cached_botan_pipe)]; + +option::concrete_option_set +read_global_options(options & opts, args_vector & args) { option::concrete_option_set optset = options::opts::all_options().instantiate(&opts); optset.from_command_line(args); + + return optset; +} - // consume the command, and perform completion if necessary - string cmd; - if (!opts.args.empty()) - cmd = commands::complete_command(idx(opts.args, 0)()); +// read command-line options and return the command name +commands::command_id read_options(options & opts, option::concrete_option_set & optset, args_vector & args) +{ + commands::command_id cmd; - // reparse options, now that we know what command-specific - // options are allowed. + if (!opts.args.empty()) + { + // There are some arguments remaining in the command line. Try first + // to see if they are a command. + cmd = commands::complete_command(opts.args); + I(!cmd.empty()); - options::options_type cmdopts = commands::command_options(opts.args); - optset.reset(); + // Reparse options now that we know what command-specific options + // are allowed. + options::options_type cmdopts = commands::command_options(cmd); + optset.reset(); + optset = (options::opts::globals() | cmdopts).instantiate(&opts); + optset.from_command_line(args, false); - optset = (options::opts::globals() | cmdopts).instantiate(&opts); - optset.from_command_line(args, false); + // Remove the command name from the arguments. Rember that the group + // is not taken into account. + I(opts.args.size() >= cmd.size() - 1); - if (!opts.args.empty()) - opts.args.erase(opts.args.begin()); + for (args_vector::size_type i = 1; i < cmd.size(); i++) + { + I(cmd[i]().find(opts.args[0]()) == 0); + opts.args.erase(opts.args.begin()); + } + } - return cmd; + return cmd; } int @@ -274,38 +282,48 @@ cpp_main(int argc, char ** argv) global_sanity.initialize(argc, argv, setlocale(LC_ALL, 0)); // Set up secure memory allocation etc - botan_library acquire_botan; + Botan::LibraryInitializer acquire_botan("thread_safe=0 selftest=0 " + "seed_rng=1 use_engines=0 " + "secure_memory=1 fips140=0"); + // and caching for botan pipes + pipe_cache_cleanup acquire_botan_pipe_caching; + unfiltered_pipe = new Botan::Pipe; + new (unfiltered_pipe_cleanup_mem) cached_botan_pipe(unfiltered_pipe); + // Record where we are. This has to happen before any use of // boost::filesystem. save_initial_path(); // decode all argv values into a UTF-8 array - vector args; + args_vector args; for (int i = 1; i < argc; ++i) { external ex(argv[i]); utf8 ut; system_to_utf8(ex, ut); - args.push_back(ut()); + args.push_back(arg_type(ut)); } // find base name of executable, convert to utf8, and save it in the // global ui object { - string prog_name = fs::path(argv[0]).leaf(); + utf8 argv0_u; + system_to_utf8(external(argv[0]), argv0_u); + string prog_name = system_path(argv0_u).basename()(); if (prog_name.rfind(".exe") == prog_name.size() - 4) prog_name = prog_name.substr(0, prog_name.size() - 4); - utf8 prog_name_u; - system_to_utf8(external(prog_name), prog_name_u); - ui.prog_name = prog_name_u(); + ui.prog_name = prog_name; I(!ui.prog_name.empty()); } mtncvs_state app; try { - string cmd = read_options(app.opts, args); + // read global options first + // command specific options will be read below + args_vector opt_args(args); + option::concrete_option_set optset = read_global_options(app.opts, opt_args); if (app.opts.version_given) { @@ -313,33 +331,39 @@ cpp_main(int argc, char ** argv) return 0; } + // at this point we allow a workspace (meaning search for it, + // and if found, change directory to it + // Certain commands may subsequently require a workspace or fail + // if we didn't find one at this point. +// workspace::found = find_and_go_to_workspace(app.opts.root); + + // Load all available monotonercs. If we found a workspace above, + // we'll pick up _MTN/monotonerc as well as the user's monotonerc. +// app.lua.load_rcfiles(app.opts); + + // now grab any command specific options and parse the command + // this needs to happen after the monotonercs have been read + commands::command_id cmd = read_options(app.opts, optset, opt_args); + // stop here if they asked for help if (app.opts.help) { throw usage(cmd); // cmd may be empty, and that's fine. } - // at this point we allow a workspace (meaning search for it - // and if found read _MTN/options, but don't use the data quite - // yet, and read all the monotonercs). Processing the data - // from _MTN/options happens later. - // Certain commands may subsequently require a workspace or fail - // if we didn't find one at this point. -// app.allow_workspace(); - -// if (!app.found_workspace && global_sanity.filename.empty()) -// global_sanity.filename = (app.get_confdir() / "dump").as_external(); - // main options processed, now invoke the // sub-command w/ remaining args if (cmd.empty()) { - throw usage(""); + throw usage(commands::command_id()); } else { - vector args(app.opts.args.begin(), app.opts.args.end()); - return commands::process(app.downcast(), cmd, args); + commands::process(app.downcast(), cmd, app.opts.args); + // The command will raise any problems itself through + // exceptions. If we reach this point, it is because it + // worked correctly. + return 0; } } catch (option::option_error const & e) @@ -354,15 +378,20 @@ cpp_main(int argc, char ** argv) // merrily down your pipes. std::ostream & usage_stream = (app.opts.help ? cout : cerr); + string visibleid; + if (!u.which.empty()) + visibleid = join_words(vector< utf8 >(u.which.begin() + 1, + u.which.end()))(); + usage_stream << F("Usage: %s [OPTION...] command [ARG...]") % ui.prog_name << "\n\n"; usage_stream << options::opts::globals().instantiate(&app.opts).get_usage_str() << "\n"; // Make sure to hide documentation that's not part of // the current command. - options::options_type cmd_options = commands::toplevel_command_options(u.which); + options::options_type cmd_options = commands::command_options(u.which); if (!cmd_options.empty()) { - usage_stream << F("Options specific to '%s %s':") % ui.prog_name % u.which << "\n\n"; + usage_stream << F("Options specific to '%s %s':") % ui.prog_name % visibleid << "\n\n"; usage_stream << cmd_options.instantiate(&app.opts).get_usage_str() << "\n"; } ============================================================ --- mtn_cvs/mtn_pipe.cc 1c1fd5cd881e1e26451e1a75bf81f30690857431 +++ mtn_cvs/mtn_pipe.cc e7301e40a135e59b2e38b710ef9a6e6f21e60379 @@ -1,9 +1,10 @@ // -*- mode: C++; c-file-style: "gnu"; indent-tabs-mode: nil -*- // copyright (C) 2006 Christof Petig // all rights reserved. // licensed to the public under the terms of the GNU GPL (>= 2) // see the file COPYING for details +#include "../base.hh" #include "mtn_pipe.hh" #include #include ============================================================ --- mtn_cvs/mtncvs_state.cc 79a1b44a8208a8adb1e22b7612fa83a1c4dd235e +++ mtn_cvs/mtncvs_state.cc 99c95e36c223a1a3884cf1687586ac07ba2204d2 @@ -1,32 +1,33 @@ // -*- mode: C++; c-file-style: "gnu"; indent-tabs-mode: nil -*- // copyright (C) 2006 Christof Petig // all rights reserved. // licensed to the public under the terms of the GNU GPL (>= 2) // see the file COPYING for details +#include "../base.hh" #include "mtncvs_state.hh" #define D(x) << #x " " << x << ' ' #include -std::ostream& operator<<(std::ostream &o, std::vector const& v) +std::ostream& operator<<(std::ostream &o, std::vector const& v); +#if 0 { //std::copy(v.begin(),v.end(),output_iterator o << '{'; - for(std::vector::const_iterator i=v.begin();i!=v.end();++i) + for(std::vector::const_iterator i=v.begin();i!=v.end();++i) o << (*i) << ','; return o << '}'; } +#endif void mtncvs_state::dump() -{ std::cerr D(opts.full) D(opts.since) D(opts.mtn_binary) D(opts.branch_name) << '\n'; +{ std::cerr D(opts.full) D(opts.since) D(opts.mtn_binary) D(opts.branchname) << '\n'; std::cerr D(opts.mtn_options) << '\n'; } void mtncvs_state::open() -{ std::vector args; - for (std::vector::const_iterator i=opts.mtn_options.begin();i!=opts.mtn_options.end();++i) - args.push_back((*i)()); - std::string binary=opts.mtn_binary(); +{ std::vector const& args= opts.mtn_options; + std::string binary=opts.mtn_binary; if (binary.empty()) binary="mtn"; I(!is_open()); L(FL("mtncvs_state: opening mtn binary %s") % binary);