# # # rename "option_list.hh" # to "options_list.hh" # # patch "Makefile.am" # from [bb5a36cadcd3a06c9f180e62205d896b87f88b29] # to [8fe82d118f4a51f79eb60561968f8d0e0f4d3e64] # # patch "app_state.hh" # from [5bc56ca3900e76e54caff2c3bbcea7bc2def2d95] # to [bd83327f6bfc72eb55500a114abf147b687f5c79] # # patch "cmd.hh" # from [50dd9bb2a31124fc8d312e49048de2e5593d9b44] # to [cead5ed02a100c1eb58e54d7b8fec151558e98cf] # # patch "cmd_automate.cc" # from [29294691a83649d5d618d84852a68c4c570e9fb1] # to [a76dbed99c8a929a52baace51d5ad6f674ea9bc4] # # patch "cmd_db.cc" # from [a1c22f05a3f5ee8b4a4669606a0ca28718d015dd] # to [6676067f448fe6a0f8fb250bffbd07edbae0567d] # # patch "cmd_diff_log.cc" # from [4dff01d42fc9b1932194aca278c66d91fbc52e8a] # to [1d2faaa4a2ec5db9fb58ea9c3633c4bfb32c7ff1] # # patch "cmd_files.cc" # from [4ac7c7881b82c1514f9c0ab27d497cb4d26e2f99] # to [17a12906b2273a4befe7c3abce3620f82ce3a240] # # patch "cmd_key_cert.cc" # from [668688efc44c3c21fd32037ef469ea51f2141882] # to [41060424a1f24888e53b762d83bda91837170b30] # # patch "cmd_list.cc" # from [e4ee5d24d48d1dcd64cdba40b3e152efffe42bf2] # to [5c13ba291ec50d8ffccb2452076a6f1f2b7a85b8] # # patch "cmd_merging.cc" # from [81fa693d2d3734313402547c0da9f2b619aed2c4] # to [77ea3cfa91dd9467a850ca55244a3269c0276ac7] # # patch "cmd_netsync.cc" # from [94479e47ba3eb64bdf8059500d9c7b13e9998c74] # to [dee07d1641d2272e86b5094bda944a204bdf2e31] # # patch "cmd_othervcs.cc" # from [eca9c84370f8c095b4c8b09345304abbab248aa2] # to [3f891d529949dc55ec8e87ec81ca11919f6077e6] # # patch "cmd_packet.cc" # from [4e1f5a875df2278072c6f2ebcf3b4b4bccb2867f] # to [3b90d96d799871f9d05f2717b092338500812750] # # patch "cmd_ws_commit.cc" # from [57bad1f9b71387140c5f573d434ca0acda156b05] # to [dc49953a038a915f99272fe0cbaa4cdf9c0ccbf8] # # patch "commands.cc" # from [8db36875dd9383eee4925b427bd7e370814d0d47] # to [46b410973b22fb2a4b857a292f79ff191c45c1c2] # # patch "commands.hh" # from [30a0b56c47bdff213bdff6c48bebdc6843aac84d] # to [fde6d00fecaf5ab640a68502d0fd8974a50d555f] # # patch "monotone.cc" # from [6a8a609a6ef4349accbb5c69295d483a542876ad] # to [16de226e91faac3897a8648d970499332195ca90] # # patch "option.cc" # from [3047efe48698d34f0994458298a29c546f8ba5cb] # to [435ba9737c3a0f316d1a17ac96770c21bc8f1390] # # patch "option.hh" # from [4baeb00258d60503350b00cbb9a309a565676160] # to [e9bf1b5a9fc5e9e4fd8b621cd88ef37f79bf68c6] # # patch "options_list.hh" # from [e7c2f1ebe8b580e242753f1f87b1655895d4ee89] # to [c7b31ec65e0a2190312019011bf57eb8dfb1adf7] # # patch "sha1.cc" # from [f81e2a20ae2fb90e962f570303f71b6401ccf00e] # to [87a4887f50e5639094513256871e37180410163a] # # patch "unit_tests.cc" # from [14e5b4cb7908496abdc59779e8747e2dc2dfaec3] # to [6bdf8e577c7d3908b25a6d3b45a894a5f5b2529b] # ============================================================ --- Makefile.am bb5a36cadcd3a06c9f180e62205d896b87f88b29 +++ Makefile.am 8fe82d118f4a51f79eb60561968f8d0e0f4d3e64 @@ -77,7 +77,7 @@ MOST_SOURCES = \ netio.hh smap.hh gettext.h \ package_revision.c package_revision.h \ package_full_revision.c package_full_revision.h \ - option.cc option.hh option_list.hh \ + option.cc option.hh options.cc options.hh options_list.hh \ i18n.h parallel_iter.hh safe_map.hh pch.hh NETXX_SOURCES = \ ============================================================ --- app_state.hh 5bc56ca3900e76e54caff2c3bbcea7bc2def2d95 +++ app_state.hh bd83327f6bfc72eb55500a114abf147b687f5c79 @@ -22,7 +22,7 @@ class lua_hooks; #include "database.hh" #include "key_store.hh" #include "lua_hooks.hh" -#include "option.hh" +#include "options.hh" #include "paths.hh" #include "vocab.hh" #include "work.hh" @@ -49,7 +49,7 @@ public: key_store keys; workspace work; - option::options opts; + options opts; bool found_workspace; bool branch_is_sticky; ============================================================ --- cmd.hh 50dd9bb2a31124fc8d312e49048de2e5593d9b44 +++ cmd.hh cead5ed02a100c1eb58e54d7b8fec151558e98cf @@ -15,9 +15,10 @@ #include "app_state.hh" #include "commands.hh" #include "constants.hh" -#include "option.hh" +#include "options.hh" #include "sanity.hh" + namespace commands { std::string const & hidden_group(); @@ -34,13 +35,13 @@ namespace commands std::string params_; std::string desc_; bool use_workspace_options; - option::optset options; + options::options_type options; command(std::string const & n, std::string const & g, std::string const & p, std::string const & d, bool u, - option::optset const & o); + options::options_type const & o); virtual ~command(); virtual std::string params(); virtual std::string desc(); @@ -122,7 +123,7 @@ namespace commands { struct cmd_ ## C : public command \ { \ cmd_ ## C() : command(#C, group, params, desc, true, \ - option::optset() % opts) \ + options::options_type() % opts) \ {} \ virtual void exec(app_state & app, \ std::vector const & args); \ @@ -140,7 +141,7 @@ namespace commands { struct cmd_ ## C : public command \ { \ cmd_ ## C() : command(#C, group, "", desc, true, \ - option::optset() % opts) \ + options::options_type() % opts) \ {} \ virtual void exec(app_state & app, \ std::vector const & args); \ @@ -159,7 +160,7 @@ namespace commands { struct cmd_ ## C : public command \ { \ cmd_ ## C() : command(#C, group, params, desc, false, \ - option::optset() % opts) \ + options::options_type() % opts) \ {} \ virtual void exec(app_state & app, \ std::vector const & args); \ ============================================================ --- cmd_automate.cc 29294691a83649d5d618d84852a68c4c570e9fb1 +++ cmd_automate.cc a76dbed99c8a929a52baace51d5ad6f674ea9bc4 @@ -302,7 +302,7 @@ CMD_PARAMS_FN(automate, N_("automation") CMD_PARAMS_FN(automate, N_("automation"), N_("automation interface"), - option::automate_stdio_size) + options::opts::automate_stdio_size) { if (args.size() == 0) throw usage(name); ============================================================ --- cmd_db.cc a1c22f05a3f5ee8b4a4669606a0ca28718d015dd +++ cmd_db.cc 6676067f448fe6a0f8fb250bffbd07edbae0567d @@ -60,7 +60,7 @@ CMD(db, N_("database"), "regenerate_rosters\n" "set_epoch BRANCH EPOCH\n"), N_("manipulate database state"), - option::drop_attr) + options::opts::drop_attr) { if (args.size() == 1) { @@ -121,7 +121,7 @@ CMD(set, N_("vars"), N_("DOMAIN NAME VAL CMD(set, N_("vars"), N_("DOMAIN NAME VALUE"), N_("set the database variable NAME to VALUE, in domain DOMAIN"), - option::none) + options::opts::none) { if (args.size() != 3) throw usage(name); @@ -137,7 +137,7 @@ CMD(unset, N_("vars"), N_("DOMAIN NAME") CMD(unset, N_("vars"), N_("DOMAIN NAME"), N_("remove the database variable NAME in domain DOMAIN"), - option::none) + options::opts::none) { if (args.size() != 2) throw usage(name); @@ -154,7 +154,7 @@ CMD(complete, N_("informative"), N_("(re CMD(complete, N_("informative"), N_("(revision|file|key) PARTIAL-ID"), N_("complete partial id"), - option::verbose) + options::opts::verbose) { if (args.size() != 2) throw usage(name); ============================================================ --- cmd_diff_log.cc 4dff01d42fc9b1932194aca278c66d91fbc52e8a +++ cmd_diff_log.cc 1d2faaa4a2ec5db9fb58ea9c3633c4bfb32c7ff1 @@ -333,8 +333,8 @@ CMD(diff, N_("informative"), N_("[PATH]. "If one revision is given, the diff between the workspace and\n" "that revision is shown. If two revisions are given, the diff between\n" "them is given. If no format is specified, unified is used by default."), - option::revision % option::depth % option::exclude - % option::diff_options) + options::opts::revision % options::opts::depth % options::opts::exclude + % options::opts::diff_options) { bool new_is_archived; ostringstream header; @@ -541,8 +541,8 @@ CMD(log, N_("informative"), N_("[FILE] . CMD(log, N_("informative"), N_("[FILE] ..."), N_("print history in reverse order (filtering by 'FILE'). If one or more\n" "revisions are given, use them as a starting point."), - option::last % option::next % option::revision % option::brief - % option::diffs % option::no_merges % option::no_files) + options::opts::last % options::opts::next % options::opts::revision % options::opts::brief + % options::opts::diffs % options::opts::no_merges % options::opts::no_files) { if (app.opts.revision_selectors.size() == 0) app.require_workspace("try passing a --revision to start at"); ============================================================ --- cmd_files.cc 4ac7c7881b82c1514f9c0ab27d497cb4d26e2f99 +++ cmd_files.cc 17a12906b2273a4befe7c3abce3620f82ce3a240 @@ -25,7 +25,7 @@ using std::vector; // fload, fmerge, and fdiff are simple commands for debugging the line // merger. -CMD(fload, N_("debug"), "", N_("load file contents into db"), option::none) +CMD(fload, N_("debug"), "", N_("load file contents into db"), options::opts::none) { string s = get_stdin(); @@ -40,7 +40,7 @@ CMD(fmerge, N_("debug"), N_(" "), N_("merge 3 files and output result"), - option::none) + options::opts::none) { if (args.size() != 3) throw usage(name); @@ -77,7 +77,7 @@ CMD(fdiff, N_("debug"), N_("SRCNAME DEST CMD(fdiff, N_("debug"), N_("SRCNAME DESTNAME SRCID DESTID"), N_("diff 2 files and output result"), - option::diff_options) + options::opts::diff_options) { if (args.size() != 4) throw usage(name); @@ -113,7 +113,7 @@ CMD(annotate, N_("informative"), N_("PAT CMD(annotate, N_("informative"), N_("PATH"), N_("print annotated copy of the file from REVISION"), - option::revision % option::brief) + options::opts::revision % options::opts::brief) { revision_id rid; @@ -156,7 +156,7 @@ CMD(identify, N_("debug"), N_("[PATH]"), CMD(identify, N_("debug"), N_("[PATH]"), N_("calculate identity of PATH or stdin"), - option::none) + options::opts::none) { if (!(args.size() == 0 || args.size() == 1)) throw usage(name); @@ -181,7 +181,7 @@ CMD(cat, N_("informative"), CMD(cat, N_("informative"), N_("FILENAME"), N_("write file from database to stdout"), - option::revision) + options::opts::revision) { if (args.size() != 1) throw usage(name); ============================================================ --- cmd_key_cert.cc 668688efc44c3c21fd32037ef469ea51f2141882 +++ cmd_key_cert.cc 41060424a1f24888e53b762d83bda91837170b30 @@ -24,7 +24,7 @@ CMD(genkey, N_("key and cert"), N_("KEYI using std::string; CMD(genkey, N_("key and cert"), N_("KEYID"), N_("generate an RSA key-pair"), - option::none) + options::opts::none) { if (args.size() != 1) throw usage(name); @@ -50,7 +50,7 @@ CMD(dropkey, N_("key and cert"), N_("KEY } CMD(dropkey, N_("key and cert"), N_("KEYID"), - N_("drop a public and private key"), option::none) + N_("drop a public and private key"), options::opts::none) { bool key_deleted = false; @@ -91,7 +91,7 @@ CMD(chkeypass, N_("key and cert"), N_("K CMD(chkeypass, N_("key and cert"), N_("KEYID"), N_("change passphrase of a private RSA key"), - option::none) + options::opts::none) { if (args.size() != 1) throw usage(name); @@ -111,7 +111,7 @@ CMD(cert, N_("key and cert"), N_("REVISI } CMD(cert, N_("key and cert"), N_("REVISION CERTNAME [CERTVAL]"), - N_("create a cert for a revision"), option::none) + N_("create a cert for a revision"), options::opts::none) { if ((args.size() != 3) && (args.size() != 2)) throw usage(name); @@ -150,7 +150,7 @@ CMD(trusted, N_("key and cert"), N_("REVISION NAME VALUE SIGNER1 [SIGNER2 [...]]"), N_("test whether a hypothetical cert would be trusted\n" "by current settings"), - option::none) + options::opts::none) { if (args.size() < 4) throw usage(name); @@ -195,7 +195,7 @@ CMD(tag, N_("review"), N_("REVISION TAGN } CMD(tag, N_("review"), N_("REVISION TAGNAME"), - N_("put a symbolic tag cert on a revision"), option::none) + N_("put a symbolic tag cert on a revision"), options::opts::none) { if (args.size() != 2) throw usage(name); @@ -208,7 +208,7 @@ CMD(testresult, N_("review"), N_("ID (pa CMD(testresult, N_("review"), N_("ID (pass|fail|true|false|yes|no|1|0)"), - N_("note the results of running a test on a revision"), option::none) + N_("note the results of running a test on a revision"), options::opts::none) { if (args.size() != 2) throw usage(name); @@ -222,7 +222,7 @@ CMD(approve, N_("review"), N_("REVISION" CMD(approve, N_("review"), N_("REVISION"), N_("approve of a particular revision"), - option::branch) + options::opts::branch) { if (args.size() != 1) throw usage(name); @@ -237,7 +237,7 @@ CMD(comment, N_("review"), N_("REVISION } CMD(comment, N_("review"), N_("REVISION [COMMENT]"), - N_("comment on a particular revision"), option::none) + N_("comment on a particular revision"), options::opts::none) { if (args.size() != 1 && args.size() != 2) throw usage(name); ============================================================ --- cmd_list.cc e4ee5d24d48d1dcd64cdba40b3e152efffe42bf2 +++ cmd_list.cc 5c13ba291ec50d8ffccb2452076a6f1f2b7a85b8 @@ -470,7 +470,7 @@ CMD(list, N_("informative"), N_("show database objects, or the current workspace manifest, \n" "or known, unknown, intentionally ignored, missing, or \n" "changed-state files"), - option::depth % option::exclude) + options::opts::depth % options::opts::exclude) { if (args.size() == 0) throw usage(name); ============================================================ --- cmd_merging.cc 81fa693d2d3734313402547c0da9f2b619aed2c4 +++ cmd_merging.cc 77ea3cfa91dd9467a850ca55244a3269c0276ac7 @@ -76,7 +76,7 @@ CMD(update, N_("workspace"), "", "different revision, preserving uncommitted changes as it does so.\n" "If a revision is given, update the workspace to that revision.\n" "If not, update the workspace to the head of the branch."), - option::branch % option::revision) + options::opts::branch % options::opts::revision) { if (args.size() > 0) throw usage(name); @@ -318,7 +318,7 @@ CMD(merge, N_("tree"), "", N_("merge unm // (Possibility: append the --message/--message-file text to the synthetic // log message constructed in merge_two().) CMD(merge, N_("tree"), "", N_("merge unmerged heads of branch"), - option::branch % option::date % option::author) + options::opts::branch % options::opts::date % options::opts::author) { typedef std::pair revpair; typedef set::const_iterator rid_set_iter; @@ -418,7 +418,7 @@ CMD(propagate, N_("tree"), N_("SOURCE-BR CMD(propagate, N_("tree"), N_("SOURCE-BRANCH DEST-BRANCH"), N_("merge from one branch to another asymmetrically"), - option::date % option::author % option::message % option::msgfile) + options::opts::date % options::opts::author % options::opts::message % options::opts::msgfile) { if (args.size() != 2) throw usage(name); @@ -429,7 +429,7 @@ CMD(merge_into_dir, N_("tree"), N_("SOUR CMD(merge_into_dir, N_("tree"), N_("SOURCE-BRANCH DEST-BRANCH DIR"), N_("merge one branch into a subdirectory in another branch"), - option::date % option::author % option::message % option::msgfile) + options::opts::date % options::opts::author % options::opts::message % options::opts::msgfile) { // This is a special merge operator, but very useful for people // maintaining "slightly disparate but related" trees. It does a one-way @@ -589,7 +589,7 @@ CMD(explicit_merge, N_("tree"), N_("LEFT-REVISION RIGHT-REVISION DEST-BRANCH"), N_("merge two explicitly given revisions, " "placing result in given branch"), - option::date % option::author) + options::opts::date % options::opts::author) { revision_id left, right; string branch; @@ -614,7 +614,7 @@ CMD(show_conflicts, N_("informative"), N CMD(show_conflicts, N_("informative"), N_("REV REV"), N_("Show what conflicts would need to be resolved " "to merge the given revisions."), - option::branch % option::date % option::author) + options::opts::branch % options::opts::date % options::opts::author) { if (args.size() != 2) throw usage(name); @@ -665,7 +665,7 @@ CMD(pluck, N_("workspace"), N_("[-r FROM "\n" "If two revisions are given, applies the changes made to get from the\n" "first revision to the second."), - option::revision % option::depth % option::exclude) + options::opts::revision % options::opts::depth % options::opts::exclude) { // Work out our arguments revision_id from_rid, to_rid; @@ -819,7 +819,7 @@ CMD(heads, N_("tree"), "", N_("show unme } CMD(heads, N_("tree"), "", N_("show unmerged head revisions of branch"), - option::branch) + options::opts::branch) { set heads; if (args.size() != 0) @@ -844,7 +844,7 @@ CMD(get_roster, N_("debug"), N_("REVID") CMD(get_roster, N_("debug"), N_("REVID"), N_("dump the roster associated with the given REVID"), - option::none) + options::opts::none) { revision_id rid; if (args.size() == 0) ============================================================ --- cmd_netsync.cc 94479e47ba3eb64bdf8059500d9c7b13e9998c74 +++ cmd_netsync.cc dee07d1641d2272e86b5094bda944a204bdf2e31 @@ -69,7 +69,7 @@ process_netsync_args(string const & name { rsa_keypair_id key; get_user_key(key, app); - app.signing_key = key; + app.opts.signing_key = key; } } @@ -118,7 +118,7 @@ CMD(push, N_("network"), N_("[ADDRESS[:P CMD(push, N_("network"), N_("[ADDRESS[:PORTNUMBER] [PATTERN]]"), N_("push branches matching PATTERN to netsync server at ADDRESS"), - option::set_default % option::exclude % option::key_to_push) + options::opts::set_default % options::opts::exclude % options::opts::key_to_push) { utf8 addr, include_pattern, exclude_pattern; process_netsync_args(name, args, addr, include_pattern, exclude_pattern, @@ -131,7 +131,7 @@ CMD(pull, N_("network"), N_("[ADDRESS[:P CMD(pull, N_("network"), N_("[ADDRESS[:PORTNUMBER] [PATTERN]]"), N_("pull branches matching PATTERN from netsync server at ADDRESS"), - option::set_default % option::exclude) + options::opts::set_default % options::opts::exclude) { utf8 addr, include_pattern, exclude_pattern; process_netsync_args(name, args, addr, include_pattern, exclude_pattern, @@ -146,7 +146,7 @@ CMD(sync, N_("network"), N_("[ADDRESS[:P CMD(sync, N_("network"), N_("[ADDRESS[:PORTNUMBER] [PATTERN]]"), N_("sync branches matching PATTERN with netsync server at ADDRESS"), - option::set_default % option::exclude % option::key_to_push) + options::opts::set_default % options::opts::exclude % options::opts::key_to_push) { utf8 addr, include_pattern, exclude_pattern; process_netsync_args(name, args, addr, include_pattern, exclude_pattern, @@ -190,8 +190,8 @@ CMD_NO_WORKSPACE(serve, N_("network"), N CMD_NO_WORKSPACE(serve, N_("network"), N_("PATTERN ..."), N_("serve the branches specified by PATTERNs to connecting clients"), - option::bind % option::pidfile % option::exclude % - option::bind_stdio % option::no_transport_auth) + options::opts::bind % options::opts::pidfile % options::opts::exclude % + options::opts::bind_stdio % options::opts::no_transport_auth) { if (args.size() < 1) throw usage(name); ============================================================ --- cmd_othervcs.cc eca9c84370f8c095b4c8b09345304abbab248aa2 +++ cmd_othervcs.cc 3f891d529949dc55ec8e87ec81ca11919f6077e6 @@ -16,7 +16,7 @@ CMD(rcs_import, N_("debug"), N_("RCSFILE N_("parse versions in RCS files\n" "this command doesn't reconstruct or import revisions." "you probably want cvs_import"), - option::branch) + options::opts::branch) { if (args.size() < 1) throw usage(name); @@ -31,7 +31,7 @@ CMD(cvs_import, N_("rcs"), N_("CVSROOT") CMD(cvs_import, N_("rcs"), N_("CVSROOT"), N_("import all versions in CVS repository"), - option::branch) + options::opts::branch) { if (args.size() != 1) throw usage(name); ============================================================ --- cmd_packet.cc 4e1f5a875df2278072c6f2ebcf3b4b4bccb2867f +++ cmd_packet.cc 3b90d96d799871f9d05f2717b092338500812750 @@ -20,7 +20,7 @@ CMD(pubkey, N_("packet i/o"), N_("ID"), CMD(pubkey, N_("packet i/o"), N_("ID"), N_("write public key packet to stdout"), - option::none) + options::opts::none) { if (args.size() != 1) throw usage(name); @@ -49,7 +49,7 @@ CMD(privkey, N_("packet i/o"), N_("ID"), CMD(privkey, N_("packet i/o"), N_("ID"), N_("write private key packet to stdout"), - option::none) + options::opts::none) { if (args.size() != 1) throw usage(name); @@ -68,7 +68,7 @@ CMD(read, N_("packet i/o"), "[FILE1 [FIL CMD(read, N_("packet i/o"), "[FILE1 [FILE2 [...]]]", N_("read packets from files or stdin"), - option::none) + options::opts::none) { packet_db_writer dbw(app); size_t count = 0; ============================================================ --- cmd_ws_commit.cc 57bad1f9b71387140c5f573d434ca0acda156b05 +++ cmd_ws_commit.cc dc49953a038a915f99272fe0cbaa4cdf9c0ccbf8 @@ -65,7 +65,7 @@ CMD(revert, N_("workspace"), N_("[PATH]. CMD(revert, N_("workspace"), N_("[PATH]..."), N_("revert file(s), dir(s) or entire workspace (\".\")"), - option::depth % option::exclude % option::missing) + options::opts::depth % options::opts::exclude % options::opts::missing) { temp_node_id_source nis; roster_t old_roster, new_roster; @@ -188,7 +188,7 @@ CMD(disapprove, N_("review"), N_("REVISI CMD(disapprove, N_("review"), N_("REVISION"), N_("disapprove of a particular revision"), - option::branch) + options::opts::branch) { if (args.size() != 1) throw usage(name); @@ -240,7 +240,7 @@ CMD(add, N_("workspace"), N_("[PATH]..." CMD(add, N_("workspace"), N_("[PATH]..."), - N_("add files to workspace"), option::unknown) + N_("add files to workspace"), options::opts::unknown) { if (!app.opts.unknown && (args.size() < 1)) throw usage(name); @@ -275,7 +275,7 @@ CMD(drop, N_("workspace"), N_("[PATH]... CMD(drop, N_("workspace"), N_("[PATH]..."), N_("drop files from workspace"), - option::execute % option::missing % option::recursive) + options::opts::execute % options::opts::missing % options::opts::recursive) { if (!app.opts.missing && (args.size() < 1)) throw usage(name); @@ -313,7 +313,7 @@ CMD(rename, N_("workspace"), N_("SRC DEST\n" "SRC1 [SRC2 [...]] DEST_DIR"), N_("rename entries in the workspace"), - option::execute) + options::opts::execute) { if (args.size() < 2) throw usage(name); @@ -342,7 +342,7 @@ ALIAS(mv, rename) "that is currently the root\n" "directory will have name PUT_OLD.\n" "Using --execute is strongly recommended."), - option::execute) + options::opts::execute) { if (args.size() != 2) throw usage(name); @@ -354,7 +354,7 @@ CMD(status, N_("informative"), N_("[PATH } CMD(status, N_("informative"), N_("[PATH]..."), N_("show status of workspace"), - option::depth % option::exclude) + options::opts::depth % options::opts::exclude) { roster_t old_roster, new_roster; cset included, excluded; @@ -424,7 +424,7 @@ CMD(checkout, N_("tree"), N_("[DIRECTORY "If a revision is given, that's the one that will be checked out.\n" "Otherwise, it will be the head of the branch (given or implicit).\n" "If no directory is given, the branch name will be used as directory"), - option::branch % option::revision) + options::opts::branch % options::opts::revision) { revision_id ident; system_path dir; @@ -561,7 +561,7 @@ CMD(attr, N_("workspace"), N_("set PATH CMD(attr, N_("workspace"), N_("set PATH ATTR VALUE\nget PATH [ATTR]\ndrop PATH [ATTR]"), N_("set, get or drop file attributes"), - option::none) + options::opts::none) { if (args.size() < 2 || args.size() > 4) throw usage(name); @@ -661,8 +661,8 @@ CMD(commit, N_("workspace"), N_("[PATH]. CMD(commit, N_("workspace"), N_("[PATH]..."), N_("commit workspace to database"), - option::branch % option::message % option::msgfile % option::date - % option::author % option::depth % option::exclude) + options::opts::branch % options::opts::message % options::opts::msgfile % options::opts::date + % options::opts::author % options::opts::depth % options::opts::exclude) { utf8 log_message(""); bool log_message_given; @@ -907,7 +907,7 @@ CMD_NO_WORKSPACE(setup, N_("tree"), N_(" CMD_NO_WORKSPACE(setup, N_("tree"), N_("[DIRECTORY]"), N_("setup a new workspace directory, default to current"), - option::branch) + options::opts::branch) { if (args.size() > 1) throw usage(name); @@ -931,7 +931,7 @@ CMD_NO_WORKSPACE(migrate_workspace, N_(" CMD_NO_WORKSPACE(migrate_workspace, N_("tree"), N_("[DIRECTORY]"), N_("migrate a workspace directory's metadata to the latest format; " "defaults to the current workspace"), - option::none) + options::opts::none) { if (args.size() > 1) throw usage(name); @@ -943,7 +943,7 @@ CMD(refresh_inodeprints, N_("tree"), "", } CMD(refresh_inodeprints, N_("tree"), "", N_("refresh the inodeprint cache"), - option::none) + options::opts::none) { app.require_workspace(); app.work.enable_inodeprints(); ============================================================ --- commands.cc 8db36875dd9383eee4925b427bd7e370814d0d47 +++ commands.cc 46b410973b22fb2a4b857a292f79ff191c45c1c2 @@ -62,7 +62,7 @@ namespace commands string const & p, string const & d, bool u, - option::optset const & o) + options::options_type const & o) : name(n), cmdgroup(g), params_(p), desc_(d), use_workspace_options(u), options(o) { @@ -235,7 +235,7 @@ namespace commands } } - option::optset command_options(string const & cmd) + options::options_type command_options(string const & cmd) { if ((*cmds).find(cmd) != (*cmds).end()) { @@ -243,13 +243,14 @@ namespace commands } else { - return option::optset(); + return options::options_type(); } } } //////////////////////////////////////////////////////////////////////// -CMD(help, N_("informative"), N_("command [ARGS...]"), N_("display command help"), option::none) +CMD(help, N_("informative"), N_("command [ARGS...]"), + N_("display command help"), options::opts::none) { if (args.size() < 1) { @@ -265,7 +266,8 @@ CMD(help, N_("informative"), N_("command throw usage(full_cmd); } -CMD(crash, hidden_group(), "{ N | E | I | exception | signal }", "trigger the specified kind of crash", option::none) +CMD(crash, hidden_group(), "{ N | E | I | exception | signal }", + "trigger the specified kind of crash", options::opts::none) { if (args.size() != 1) throw usage(name); @@ -459,7 +461,9 @@ process_commit_message_args(bool & given if (app.opts.message_given) { - log_message = app.opts.message; + std::string msg; + join_lines(app.opts.message, msg); + log_message = utf8(msg); given = true; } else if (app.opts.msgfile_given) ============================================================ --- commands.hh 30a0b56c47bdff213bdff6c48bebdc6843aac84d +++ commands.hh fde6d00fecaf5ab640a68502d0fd8974a50d555f @@ -15,7 +15,7 @@ #include #include -#include "option.hh" +#include "options.hh" using boost::shared_ptr; @@ -36,7 +36,7 @@ namespace commands { void explain_usage(std::string const & cmd, std::ostream & out); std::string complete_command(std::string const & cmd); int process(app_state & app, std::string const & cmd, std::vector const & args); - option::optset command_options(std::string const & cmd); + options::options_type command_options(std::string const & cmd); }; // Local Variables: ============================================================ --- monotone.cc 6a8a609a6ef4349accbb5c69295d483a542876ad +++ monotone.cc 16de226e91faac3897a8648d970499332195ca90 @@ -126,27 +126,28 @@ void localize_monotone() } // read command-line options and return the command name -string read_options(option::options & opts, vector args) +string read_options(options & opts, vector args) { - opts.from_cmdline(args); + option::concrete_option_set optset = options::opts::all_options().instantiate(&opts); + optset.from_command_line(args); - // consume the command, and perform completion if necessary - string cmd; - if (!opts.args.empty()) - cmd = commands::complete_command(idx(opts.args, 0)()); + // consume the command, and perform completion if necessary + string cmd; + if (!opts.args.empty()) + cmd = commands::complete_command(idx(opts.args, 0)()); - option::optset cmdopts = commands::command_options(cmd); + options::options_type cmdopts = commands::command_options(cmd); + optset = options::opts::globals().instantiate(&opts) % cmdopts.instantiate(&opts); - // reparse options, now that we know what command-specific - // options are allowed. + // reparse options, now that we know what command-specific + // options are allowed. - opts.clear_cmd_options(); - opts.clear_global_options(); - opts.from_cmdline_restricted(args, cmdopts, false); + opts = options(); + optset.from_command_line(args, false); - if (!opts.args.empty()) - opts.args.erase(opts.args.begin()); - return cmd; + if (!opts.args.empty()) + opts.args.erase(opts.args.begin()); + return cmd; } int @@ -256,7 +257,7 @@ cpp_main(int argc, char ** argv) return commands::process(app, cmd, args); } } - catch (option_error const & e) + catch (option::option_error const & e) { N(false, i18n_format("%s") % e.what()); } @@ -269,15 +270,15 @@ cpp_main(int argc, char ** argv) std::ostream & usage_stream = (app.opts.help ? cout : cerr); usage_stream << F("Usage: %s [OPTION...] command [ARG...]") % ui.prog_name << "\n\n"; - usage_stream << app.opts.get_usage_str(app.opts.global_opts()) << "\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. - option::optset cmd_options = commands::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 << app.opts.get_usage_str(cmd_options) << "\n"; + usage_stream << cmd_options.instantiate(&app.opts).get_usage_str() << "\n"; } commands::explain_usage(u.which, usage_stream); ============================================================ --- option.cc 3047efe48698d34f0994458298a29c546f8ba5cb +++ option.cc 435ba9737c3a0f316d1a17ac96770c21bc8f1390 @@ -1,20 +1,16 @@ -#include -#include -#include - -#include "charset.hh" #include "file_io.hh" #include "option.hh" -#include "platform.hh" #include "sanity.hh" #include "ui.hh" using std::map; +using std::pair; using std::set; using std::string; using std::vector; +namespace option { option_error::option_error(std::string const & str) : std::invalid_argument((F("option error: %s") % str).str()) @@ -37,113 +33,14 @@ bad_arg::bad_arg(std::string const & opt : option_error((F("bad argument '%s' to option '%s': %s") % arg % opt % reason).str()) {} -struct bad_arg_internal -{ - string reason; - bad_arg_internal(string const & str = "") : reason(str) {} -}; +bad_arg_internal::bad_arg_internal(string const & str) + : reason(str) +{} -map > & option_groups() +void splitname(string const & from, string & name, string & n) { - static map > val; - bool first(true); - if (first) - { -# define COPTSET(name) -# define GOPTSET(name) -# define COPTVAR(type, name, default_) -# define GOPTVAR(type, name, default_) -# define COPTION(optset, name, hasarg, optstring, description) \ - val[option:: name].insert(option:: name); \ - val[option:: name].insert(option:: optset); -# define GOPTION(optset, name, hasarg, optstring, description) \ - val[option:: name].insert(option:: name); \ - val[option:: name].insert(option:: optset); -# define OPTSET_REL(parent, child) \ - val[option:: child].insert(option:: parent); - -# include "option_list.hh" - -# undef COPTSET -# undef GOPTSET -# undef COPTVAR -# undef GOPTVAR -# undef COPTION -# undef GOPTION -# undef OPTSET_REL - - first = false; - } - return val; -} -void note_relation(option::optid opt, option::optid group) -{ - option_groups()[opt].insert(group); -} - -void option::optset::add(option::optid item) -{ - items.insert(item); -} -option::optset & option::optset::operator%(option::optid item) -{ - add(item); - return *this; -} -bool option::optset::contains(option::optid id) const -{ - set intersect; - set &groups = option_groups()[id]; - set_intersection(items.begin(), items.end(), - groups.begin(), groups.end(), - std::inserter(intersect, intersect.begin())); - return !intersect.empty(); -} -bool option::optset::empty() const -{ - return items.empty(); -} - - -void bind_opt::set(string const & arg) -{ - string addr_part, port_part; - size_t l_colon = arg.find(':'); - size_t r_colon = arg.rfind(':'); - - // not an ipv6 address, as that would have at least two colons - if (l_colon == r_colon) - { - addr_part = (r_colon == string::npos ? arg : arg.substr(0, r_colon)); - port_part = (r_colon == string::npos ? "" : arg.substr(r_colon+1, arg.size() - r_colon)); - } - else - { - // IPv6 addresses have a port specified in the style: [2001:388:0:13::]:80 - size_t squareb = arg.rfind(']'); - if ((arg.find('[') == 0) && (squareb != string::npos)) - { - if (squareb < r_colon) - port_part = (r_colon == string::npos ? "" : arg.substr(r_colon+1, arg.size() - r_colon)); - else - port_part = ""; - addr_part = (squareb == string::npos ? arg.substr(1, arg.size()) : arg.substr(1, squareb-1)); - } - else - { - addr_part = arg; - port_part = ""; - } - } - stdio = false; - address = utf8(addr_part); - port = utf8(port_part); -} - -static void splitname(string const & from, string & name, string & n) -{ // from looks like "foo" or "foo,f" string::size_type comma = from.find(','); name = from.substr(0, comma); @@ -153,212 +50,91 @@ static void splitname(string const & fro n = ""; } -template -bool has_arg() { return true; } -template<> -bool has_arg() { return false; } +concrete_option::concrete_option() + : has_arg(false) +{} +concrete_option::concrete_option(std::string const & names, + std::string const & desc, + bool arg, + boost::function set, + boost::function reset) +{ + description = desc; + splitname(names, longname, shortname); + has_arg = arg; + setter = set; + resetter = reset; +} -void option::options::map_opt(void (option::options::*setter)(string const &), - string const & optname, - option::optid id, - bool has_arg, - string const & description) +bool concrete_option::operator<(concrete_option const & other) const { - opt o; - o.setter = setter; - o.has_arg = has_arg; - o.desc = gettext(description.c_str()); - o.id = id; - string name, n; - splitname(/*gettext*/(optname.c_str()), name, n); - opt_map.insert(make_pair(name, o)); - if (n != "") - opt_map.insert(make_pair(n, o)); + return longname < other.longname && (shortname.empty() || shortname != other.shortname); } -option::options::options() +concrete_option_set::concrete_option_set() +{} +concrete_option_set::concrete_option_set(std::set const & other) + : options(other) +{} +concrete_option_set::concrete_option_set(concrete_option const & opt) { -# define COPTSET(name) \ - name ## _given = false; -# define GOPTSET(name) \ - name ## _given = false; -# define COPTVAR(type, name, default_) \ - name = type ( default_ ); -# define GOPTVAR(type, name, default_) \ - name = type ( default_ ); -# define COPTION(optset, name, hasarg, optstring, description) \ - map_opt(&options::set_ ## name, optstring, \ - option:: name, hasarg, description); \ - all_cmd_option.add( option:: name ); \ - name ## _given = false; -# define GOPTION(optset, name, hasarg, optstring, description) \ - map_opt(&options::set_ ## name, optstring, \ - option:: name, hasarg, description); \ - global_option.add( option:: name ); \ - name ## _given = false; -# define OPTSET_REL(parent, child) - -# include "option_list.hh" - -# undef COPTSET -# undef GOPTSET -# undef COPTVAR -# undef GOPTVAR -# undef COPTION -# undef GOPTION -# undef OPTSET_REL + options.insert(opt); } - -void option::options::clear_cmd_options() +class discard_argument : public boost::function { -# define COPTSET(name) \ - name ## _given = false; -# define GOPTSET(name) -# define COPTVAR(type, name, default_) \ - name = type ( default_ ); -# define GOPTVAR(type, name, default_) -# define COPTION(optset, name, hasarg, optstring, description) \ - name ## _given = false; -# define GOPTION(optset, name, hasarg, optstring, description) -# define OPTSET_REL(parent, child) - -# include "option_list.hh" - -# undef COPTSET -# undef GOPTSET -# undef COPTVAR -# undef GOPTVAR -# undef COPTION -# undef GOPTION -# undef OPTSET_REL + boost::function functor; + public: + discard_argument(boost::function const & from) + : functor(from) + {} + void operator()(std::string const &) + { return functor(); } +}; +concrete_option_set & +concrete_option_set::operator()(string const & names, + string const & desc, + boost::function set, + boost::function reset()) +{ + options.insert(concrete_option(names, desc, false, discard_argument(set), reset)); + return *this; } - -void option::options::clear_global_options() +concrete_option_set & +concrete_option_set::operator()(string const & names, + string const & desc, + boost::function set, + boost::function reset()) { -# define COPTSET(name) -# define GOPTSET(name) \ - name ## _given = false; -# define COPTVAR(type, name, default_) -# define GOPTVAR(type, name, default_) \ - name = type ( default_ ); -# define COPTION(optset, name, hasarg, optstring, description) -# define GOPTION(optset, name, hasarg, optstring, description) \ - name ## _given = false; -# define OPTSET_REL(parent, child) - -# include "option_list.hh" - -# undef COPTSET -# undef GOPTSET -# undef COPTVAR -# undef GOPTVAR -# undef COPTION -# undef GOPTION -# undef OPTSET_REL + options.insert(concrete_option(names, desc, true, set, reset)); + return *this; } - -# define COPTSET(name) -# define GOPTSET(name) -# define COPTVAR(type, name, default_) -# define GOPTVAR(type, name, default_) -# define COPTION(optset, name, hasarg, optstring, description) \ - void option::options::set_ ## name (std::string const & arg) -# define GOPTION(optset, name, hasarg, optstring, description) \ - void option::options::set_ ## name (std::string const & arg) -# define OPTSET_REL(parent, child) - -#define option_bodies -# include "option_list.hh" -#undef option_bodies - -# undef COPTSET -# undef GOPTSET -# undef COPTVAR -# undef GOPTVAR -# undef COPTION -# undef GOPTION -# undef OPTSET_REL - -option::options::opt const & -option::options::getopt(string const & name, optset const & allowed) +concrete_option_set & +concrete_option_set::operator % (concrete_option_set const & other) { - map::iterator i = opt_map.find(name); - if (i == opt_map.end()) - throw unknown_option(name); - else if (!global_option.contains(i->second.id) - && !allowed.contains(i->second.id)) - throw unknown_option(name); - else - return i->second; + std::set combined; + std::set_union(options.begin(), options.end(), + other.options.begin(), other.options.end(), + std::inserter(combined, combined.begin())); + options = combined; + return *this; } - -void -option::options::note_given(optid id) +concrete_option_set & +concrete_option_set::operator % (concrete_option const & opt) { - static map givens; - static bool first(true); - if (first) - { -# define COPTSET(name) \ - givens[option:: name] = &options:: name ## _given; -# define GOPTSET(name) \ - givens[option:: name] = &options:: name ## _given; -# define COPTVAR(type, name, default_) -# define GOPTVAR(type, name, default_) -# define COPTION(optset, name, hasarg, optstring, description) \ - givens[option:: name] = &options:: name ## _given; -# define GOPTION(optset, name, hasarg, optstring, description) \ - givens[option:: name] = &options:: name ## _given; -# define OPTSET_REL(parent, child) - -# include "option_list.hh" - -# undef COPTSET -# undef GOPTSET -# undef COPTVAR -# undef GOPTVAR -# undef COPTION -# undef GOPTION -# undef OPTSET_REL - first = false; - } - - // keep the std:: ; we have a member function called 'set' - std::set const &which = option_groups()[id]; - for (std::set::const_iterator i = which.begin(); - i != which.end(); ++i) - this->*givens[*i] = true; + options.insert(opt); + return *this; } - -void option::options::set(string const & name, - opt const & o, - string const & given) +void concrete_option_set::reset() const { - note_given(o.id); - try + for (std::set::const_iterator i = options.begin(); + i != options.end(); ++i) { - (this->*o.setter)(given); + if (i->resetter) + i->resetter(); } - catch (boost::bad_lexical_cast) - { - throw bad_arg(name, given); - } - catch (bad_arg_internal & e) - { - if (e.reason == "") - throw bad_arg(name, given); - else - throw bad_arg(name, given, e.reason); - } } -void option::options::set(string const & name, string const & given, - optset const & allowed) -{ - set(name, getopt(name, allowed), given); -} - static void tokenize_for_command_line(string const & from, vector & to) { @@ -428,24 +204,62 @@ tokenize_for_command_line(string const & to.push_back(cur); } -void option::options::from_cmdline_restricted(std::vector & args, - optset allowed, - bool allow_xargs) +void concrete_option_set::from_command_line(int argc, char const * const * argv) { + vector arguments; + for (int i = 1; i < argc; ++i) + arguments.push_back(argv[i]); + from_command_line(arguments, true); +} +static concrete_option const & +getopt(map const & by_name, string const & name) +{ + map::const_iterator i = by_name.find(name); + if (i != by_name.end()) + return i->second; + else + throw option::unknown_option(name); +} + +void concrete_option_set::from_command_line(std::vector & args, + bool allow_xargs) +{ + map by_name; + for (std::set::const_iterator i = options.begin(); + i != options.end(); ++i) + { + if (!i->longname.empty()) + by_name.insert(make_pair(i->longname, *i)); + if (!i->shortname.empty()) + by_name.insert(make_pair(i->shortname, *i)); + } + bool seen_dashdash = false; for (unsigned int i = 0; i < args.size(); ++i) { - opt o; + concrete_option o; string name, arg; bool separate_arg(false); - if (idx(args,i).substr(0,2) == "--") + if (idx(args,i) == "--" || seen_dashdash) { + if (!seen_dashdash) + { + seen_dashdash = true; + allow_xargs = false; + continue; + } + name = "--"; + o = getopt(by_name, name); + arg = idx(args,i); + } + else if (idx(args,i).substr(0,2) == "--") + { string::size_type equals = idx(args,i).find('='); if (equals == string::npos) name = idx(args,i).substr(2); else name = idx(args,i).substr(2, equals-2); - o = getopt(name, allowed); + o = getopt(by_name, name); if (!o.has_arg && equals != string::npos) throw extra_arg(name); @@ -466,7 +280,7 @@ void option::options::from_cmdline_restr { name = idx(args,i).substr(1,1); - o = getopt(name, allowed); + o = getopt(by_name, name); if (!o.has_arg && idx(args,i).size() != 2) throw extra_arg(name); @@ -485,10 +299,11 @@ void option::options::from_cmdline_restr } else { - name = ""; - o = getopt(name, allowed); + name = "--"; + o = getopt(by_name, name); arg = idx(args,i); } + if (allow_xargs && (name == "xargs" || name == "@")) { // expand the --xargs in place @@ -507,16 +322,28 @@ void option::options::from_cmdline_restr { if (separate_arg) ++i; - set(name, o, arg); + try + { + if (o.setter) + { + o.setter(arg); + } + } + catch (boost::bad_lexical_cast) + { + throw bad_arg(o.longname, arg); + } + catch (bad_arg_internal & e) + { + if (e.reason == "") + throw bad_arg(o.longname, arg); + else + throw bad_arg(o.longname, arg, e.reason); + } } } } -void option::options::from_cmdline(vector & args, bool allow_xargs) -{ - from_cmdline_restricted(args, all_cmd_option, allow_xargs); -} - static vector wordwrap(string str, unsigned int width) { vector out; @@ -538,72 +365,56 @@ static vector wordwrap(string st return out; } -struct optstrings +static string usagestr(option::concrete_option const & opt) { - string longname; - string shortname; - string desc; -}; -std::string option::options::get_usage_str(optset const & opts) const -{ - // collect the options we want to show (opt_map has separate - // entries for the short and long versions of each option) - map option_strings; - for (map::const_iterator i = opt_map.begin(); - i != opt_map.end(); ++i) - { - if (opts.contains(i->second.id) && !i->first.empty()) - { // i->first.empty() indicates that this is the entry for - // positional args; we don't want to include that here - optstrings & strs = option_strings[i->second.id]; - strs.desc = i->second.desc; - if (i->first.size() == 1) - strs.shortname = i->first; - else - strs.longname = i->first; - } - } + string out; + if (opt.longname == "--") + return ""; + if (!opt.longname.empty() && !opt.shortname.empty()) + out = "--" + opt.longname + " [ -" + opt.shortname + " ]"; + else if (!opt.longname.empty()) + out = "--" + opt.longname; + else if (!opt.shortname.empty()) + out = "-" + opt.shortname; + else + return ""; + if (opt.has_arg) + return out + " "; + else + return out; +} - // combind the name strings like "--long [ -s ]" +std::string concrete_option_set::get_usage_str() const +{ + // combine the name strings like "--long [ -s ]" map to_display; unsigned int namelen = 0; // the longest option name string - for (map::iterator i = option_strings.begin(); - i != option_strings.end(); ++i) + for (std::set::const_iterator i = options.begin(); + i != options.end(); ++i) { - optstrings const & strings = i->second; - string names; - if (!strings.longname.empty() && !strings.shortname.empty()) - { - names = "--" + strings.longname + " [ -" + strings.shortname + " ]"; - } - else if (!strings.longname.empty()) - { - names = "--" + strings.longname; - } - else // short name only - { - names = "-" + strings.shortname; - } - to_display.insert(make_pair(names, strings.desc)); + string names = usagestr(*i); if (names.size() > namelen) namelen = names.size(); } - // " --long [ -s ] description goes here" - // ^ ^^ ^^ ^^ ^ - // | | \ namelen / | | \ descwidth /| <- edge of screen - // ^^^^ ^^^^ - // pre_indent space + // " --long [ -s ] description goes here" + // ^ ^^ ^^ ^^ ^ + // | | \ namelen / | | \ descwidth /| <- edge of screen + // ^^^^ ^^^^ + // pre_indent space string result; int pre_indent = 2; // empty space on the left int space = 2; // space after the longest option, before the description - for (map::const_iterator i = to_display.begin(); - i != to_display.end(); ++i) + int termwidth = guess_terminal_width(); + int descindent = pre_indent + namelen + space; + int descwidth = termwidth - descindent; + for (std::set::const_iterator i = options.begin(); + i != options.end(); ++i) { - string const & names = i->first; - int descindent = pre_indent + namelen + space; - int descwidth = guess_terminal_width() - descindent; - vector desclines = wordwrap(i->second, descwidth); + string names = usagestr(*i); + if (names.empty()) + continue; + vector desclines = wordwrap(i->description, descwidth); result += string(pre_indent, ' ') + names + string(namelen - names.size(), ' ') @@ -622,6 +433,8 @@ std::string option::options::get_usage_s return result; } +} // namespace option + // Local Variables: // mode: C++ // fill-column: 76 ============================================================ --- option.hh 4baeb00258d60503350b00cbb9a309a565676160 +++ option.hh e9bf1b5a9fc5e9e4fd8b621cd88ef37f79bf68c6 @@ -1,5 +1,5 @@ -#ifndef __OPTS_HH__ -#define __OPTS_HH__ +#ifndef __OPTION_HH__ +#define __OPTION_HH__ #include #include @@ -7,168 +7,199 @@ #include #include +#include #include -#include "i18n.h" -#include "paths.hh" -#include "vocab.hh" - -struct option_error : public std::invalid_argument -{ - option_error(std::string const & str); -}; -struct unknown_option : public option_error -{ - unknown_option(std::string const & opt); -}; -struct missing_arg : public option_error -{ - missing_arg(std::string const & opt); -}; -struct extra_arg : public option_error -{ - extra_arg(std::string const & opt); -}; -struct bad_arg : public option_error -{ - bad_arg(std::string const & opt, std::string const & arg); - bad_arg(std::string const & opt, - std::string const & arg, - std::string const & reason); -}; - -struct bind_opt -{ - utf8 address; - utf8 port; - bool stdio; - bind_opt() : stdio(false) {} - void set(std::string const & arg); -}; - namespace option { - enum optid { -# define COPTSET(name) \ - name, -# define GOPTSET(name) \ - name, -# define COPTVAR(type, name, default_) -# define GOPTVAR(type, name, default_) -# define COPTION(optset, name, hasarg, optstring, description) \ - name, -# define GOPTION(optset, name, hasarg, optstring, description) \ - name, -# define OPTSET_REL(parent, child) + struct option_error : public std::invalid_argument + { + option_error(std::string const & str); + }; + struct unknown_option : public option_error + { + unknown_option(std::string const & opt); + }; + struct missing_arg : public option_error + { + missing_arg(std::string const & opt); + }; + struct extra_arg : public option_error + { + extra_arg(std::string const & opt); + }; + struct bad_arg : public option_error + { + bad_arg(std::string const & opt, std::string const & arg); + bad_arg(std::string const & opt, + std::string const & arg, + std::string const & reason); + }; + struct bad_arg_internal + { + std::string reason; + bad_arg_internal(std::string const & str = ""); + }; -# include "option_list.hh" + void splitname(std::string const & from, std::string & name, std::string & n); + struct concrete_option + { + std::string description; + std::string longname; + std::string shortname; + bool has_arg; + boost::function setter; + boost::function resetter; -# undef COPTSET -# undef GOPTSET -# undef COPTVAR -# undef GOPTVAR -# undef COPTION -# undef GOPTION -# undef OPTSET_REL + concrete_option(); + concrete_option(std::string const & names, + std::string const & desc, + bool arg, + boost::function set, + boost::function reset); - none + bool operator<(concrete_option const & other) const; }; - class optset + struct concrete_option_set { - std::set items; - public: - void add(option::optid item); - optset & operator%(option::optid item); - bool contains(option::optid id) const; - bool empty() const; + std::set options; + concrete_option_set(); + concrete_option_set(std::set const & other); + concrete_option_set(concrete_option const & opt); + concrete_option_set & + operator()(std::string const & names, + std::string const & desc, + boost::function set, + boost::function reset() = 0); + concrete_option_set & + operator()(std::string const & names, + std::string const & desc, + boost::function set, + boost::function reset() = 0); + concrete_option_set & operator % (concrete_option_set const & other); + concrete_option_set & operator % (concrete_option const & opt); + void reset() const; + std::string get_usage_str() const; + void from_command_line(std::vector & args, bool allow_xargs = true); + void from_command_line(int argc, char const * const * argv); }; - - struct options + // because std::bind1st can't handle producing a nullary functor + template + struct binder_only : boost::function { - options(); - void clear_cmd_options(); - void clear_global_options(); - void set(std::string const & name, std::string const & given) - { set(name, given, all_cmd_option); } - // if allow_xargs is true, then any instances of --xargs (or -@) in - // args will be replaced with the parsed contents of the referenced file - void from_cmdline(std::vector & args, bool allow_xargs = true); - void from_cmdline_restricted(std::vector & args, - optset allowed, - bool allow_xargs = true); - optset const & global_opts() const { return global_option; } - optset const & specific_opts() const { return all_cmd_option; } + T * obj; + boost::function fun; + binder_only(boost::function const & f, T * o) + : obj(o), fun(f) + {} + void operator()() + { + fun(obj); + } + }; + template + binder_only bind_only(boost::function const & f, T * o) + { + return binder_only(f, o); + } + template + struct option + { + std::string description; + std::string names; + bool has_arg; + boost::function setter; + boost::function resetter; - std::string get_usage_str(optset const & opts) const; + option(std::string const & name, + std::string const & desc, + bool arg, + void(T::*set)(std::string), + void(T::*reset)()) + { + description = desc; + names = name; + has_arg = arg; + setter = set; + resetter = reset; + } -# define COPTSET(name) \ - bool name ## _given; -# define GOPTSET(name) \ - bool name ## _given; -# define COPTVAR(type, name, default_) \ - type name; -# define GOPTVAR(type, name, default_) \ - type name; -# define COPTION(optset, name, hasarg, optstring, description) \ - bool name ## _given; -# define GOPTION(optset, name, hasarg, optstring, description) \ - bool name ## _given; -# define OPTSET_REL(parent, child) + concrete_option instantiate(T * obj) const + { + concrete_option out; + out.description = description; + splitname(names, out.longname, out.shortname); + out.has_arg = has_arg; -# include "option_list.hh" + if (setter) + out.setter = std::bind1st(setter, obj); + if (resetter) + out.resetter = bind_only(resetter, obj); + return out; + } -# undef COPTSET -# undef GOPTSET -# undef COPTVAR -# undef GOPTVAR -# undef COPTION -# undef GOPTION -# undef OPTSET_REL + bool operator<(option const & other) const + { + return names < other.names; + } + }; + template + struct option_set + { + std::set > options; + option_set(){} + option_set(option_set const & other) + : options(other.options) + {} + option_set(option const & opt) + { + options.insert(opt); + } - private: - -# define COPTSET(name) -# define GOPTSET(name) -# define COPTVAR(type, name, default_) -# define GOPTVAR(type, name, default_) -# define COPTION(optset, name, hasarg, optstring, description) \ - void set_ ## name (std::string const & arg); -# define GOPTION(optset, name, hasarg, optstring, description) \ - void set_ ## name (std::string const & arg); -# define OPTSET_REL(parent, child) - -# include "option_list.hh" - -# undef COPTSET -# undef GOPTSET -# undef COPTVAR -# undef GOPTVAR -# undef COPTION -# undef GOPTION -# undef OPTSET_REL - - struct opt + option_set(std::string const & name, + std::string const & desc, + bool arg, + void(T::*set)(std::string), + void(T::*reset)()) { - void (options::*setter)(std::string const &); - std::string desc; - bool has_arg; - option::optid id; - }; - void note_given(optid id); - std::map opt_map; - optset global_option, all_cmd_option; - opt const & getopt(std::string const & name, optset const & allowed); - void set(std::string const & name, std::string const & given, - optset const & allowed); - void set(std::string const & name, - opt const & o, - std::string const & given); - void map_opt(void (options::*setter)(std::string const &), - std::string const & optname, - optid id, - bool has_arg, - std::string const & description); + options.insert(option(name, desc, arg, set, reset)); + } + concrete_option_set instantiate(T * obj) const + { + std::set out; + for (typename std::set >::const_iterator i = options.begin(); + i != options.end(); ++i) + out.insert(i->instantiate(obj)); + return out; + } + option_set & operator % (option_set const & other) + { + std::set > combined; + std::set_union(options.begin(), options.end(), + other.options.begin(), other.options.end(), + std::inserter(combined, combined.begin())); + options = combined; + return *this; + } + option_set & operator % (option_set const & (*fun)()) + { + return *this % fun(); + } + option_set & operator % (option_set & (*fun)()) + { + return *this % fun(); + } + bool empty() const {return options.empty();} }; + } #endif + +// Local Variables: +// mode: C++ +// fill-column: 76 +// c-file-style: "gnu" +// indent-tabs-mode: nil +// End: +// vim: et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s: ============================================================ --- option_list.hh e7c2f1ebe8b580e242753f1f87b1655895d4ee89 +++ options_list.hh c7b31ec65e0a2190312019011bf57eb8dfb1adf7 @@ -1,25 +1,29 @@ -#define COPT(name, string, type, default_, description) \ - COPTVAR(type, name, default_) \ - COPTION(name, name, has_arg(), string, description) -#define GOPT(name, string, type, default_, description) \ - GOPTVAR(type, name, default_) \ - GOPTION(name, name, has_arg(), string, description) +#define OPT(name, string, type, default_, description) \ + OPTVAR(name, type, name, default_) \ + OPTION(name, name, has_arg(), string, description) -GOPT(args, "", std::vector, , "") +#define GOPT(name, string, type, default_, description) \ + OPTVAR(globals, type, name, default_) \ + OPTION(globals, name, has_arg(), string, description) + +OPTSET(globals) + +OPTVAR(globals, std::vector, args, ) +OPTION(globals, positionals, true, "--", "") #ifdef option_bodies { args.push_back(utf8(arg)); } #endif -COPT(author, "author", utf8, , gettext_noop("override author for commit")) +OPT(author, "author", utf8, , gettext_noop("override author for commit")) #ifdef option_bodies { author = arg; } #endif -COPT(automate_stdio_size, "automate-stdio-size", size_t, 1024, +OPT(automate_stdio_size, "automate-stdio-size", size_t, 1024, gettext_noop("block size in bytes for \"automate stdio\" output")) #ifdef option_bodies { @@ -29,21 +33,21 @@ COPT(automate_stdio_size, "automate-stdi } #endif -COPT(bind, "bind", bind_opt, , +OPT(bind, "bind", bind_opt, , gettext_noop("address:port to listen on (default :4691)")) #ifdef option_bodies { bind.set(arg); } #endif -COPT(no_transport_auth, "no-transport-auth", bool, false, +OPT(no_transport_auth, "no-transport-auth", bool, false, gettext_noop("disable transport authentication")) #ifdef option_bodies { no_transport_auth = true; } #endif -COPT(bind_stdio, "stdio", bool, false, gettext_noop("serve netsync on stdio")) +OPT(bind_stdio, "stdio", bool, false, gettext_noop("serve netsync on stdio")) #ifdef option_bodies { // Yes, this sets a field in the structure belonging to the "bind" option. @@ -51,8 +55,8 @@ COPT(bind_stdio, "stdio", bool, false, g } #endif -COPTVAR(utf8, branch_name, ) -COPTION(branch, branch, true, "branch,b", +OPTVAR(branch, utf8, branch_name, ) +OPTION(branch, branch, true, "branch,b", gettext_noop("select branch cert for operation")) #ifdef option_bodies { @@ -60,7 +64,7 @@ COPTION(branch, branch, true, "branch,b" } #endif -COPT(brief, "brief", bool, false, +GOPT(brief, "brief", bool, false, gettext_noop("print a brief version of the normal output")) #ifdef option_bodies { @@ -78,7 +82,7 @@ GOPT(conf_dir, "confdir", system_path, g } #endif -COPT(date, "date", boost::posix_time::ptime, , +OPT(date, "date", boost::posix_time::ptime, , gettext_noop("override date/time for commit")) #ifdef option_bodies { @@ -107,7 +111,7 @@ GOPT(dbname, "db,d", system_path, , gett } #endif -GOPTION(debug, debug, false, "debug", +OPTION(globals, debug, false, "debug", gettext_noop("print debug log to stderr while running")) #ifdef option_bodies { @@ -115,7 +119,7 @@ GOPTION(debug, debug, false, "debug", } #endif -COPT(depth, "depth", long, -1, +OPT(depth, "depth", long, -1, gettext_noop("limit the number of levels of directories to descend")) #ifdef option_bodies { @@ -126,10 +130,10 @@ COPT(depth, "depth", long, -1, #endif -COPTSET(diff_options) +OPTSET(diff_options) -COPTVAR(std::string, external_diff_args, ) -COPTION(diff_options, external_diff_args, true, "diff-args", +OPTVAR(diff_options, std::string, external_diff_args, ) +OPTION(diff_options, external_diff_args, true, "diff-args", gettext_noop("argument to pass external diff hook")) #ifdef option_bodies { @@ -137,30 +141,30 @@ COPTION(diff_options, external_diff_args } #endif -COPTVAR(diff_type, diff_format, unified_diff) -COPTION(diff_options, diff_context, false, "context", +OPTVAR(diff_options, diff_type, diff_format, unified_diff) +OPTION(diff_options, diff_context, false, "context", gettext_noop("use context diff format")) #ifdef option_bodies { diff_format = context_diff; } #endif -COPTION(diff_options, diff_external, false, "external", +OPTION(diff_options, diff_external, false, "external", gettext_noop("use external diff hook for generating diffs")) #ifdef option_bodies { diff_format = external_diff; } #endif -COPTION(diff_options, diff_unified, false, "unified", +OPTION(diff_options, diff_unified, false, "unified", gettext_noop("use unified diff format")) #ifdef option_bodies { diff_format = unified_diff; } #endif -COPTVAR(bool, no_show_encloser, false) -COPTION(diff_options, no_show_encloser, false, "no-show-encloser", +OPTVAR(diff_options, bool, no_show_encloser, false) +OPTION(diff_options, no_show_encloser, false, "no-show-encloser", gettext_noop("do not show the function containing each block of changes")) #ifdef option_bodies { @@ -168,15 +172,15 @@ COPTION(diff_options, no_show_encloser, } #endif -COPT(diffs, "diffs", bool, false, gettext_noop("print diffs along with logs")) +OPT(diffs, "diffs", bool, false, gettext_noop("print diffs along with logs")) #ifdef option_bodies { diffs = true; } #endif -COPTVAR(std::set, attrs_to_drop, ) -COPTION(drop_attr, drop_attr, true, "drop-attr", +OPTVAR(drop_attr, std::set, attrs_to_drop, ) +OPTION(drop_attr, drop_attr, true, "drop-attr", gettext_noop("when rosterifying, drop attrs entries with the given key")) #ifdef option_bodies { @@ -184,7 +188,7 @@ COPTION(drop_attr, drop_attr, true, "dro } #endif -GOPTION(dump, dump, true, "dump", +OPTION(globals, dump, true, "dump", gettext_noop("file to dump debugging log to, on failure")) #ifdef option_bodies { @@ -192,8 +196,8 @@ GOPTION(dump, dump, true, "dump", } #endif -COPTVAR(std::vector, exclude_patterns, ) -COPTION(exclude, exclude, true, "exclude", +OPTVAR(exclude, std::vector, exclude_patterns, ) +OPTION(exclude, exclude, true, "exclude", gettext_noop("leave out anything described by its argument")) #ifdef option_bodies { @@ -201,7 +205,7 @@ COPTION(exclude, exclude, true, "exclude } #endif -COPT(execute, "execute,e", bool, false, +OPT(execute, "execute,e", bool, false, gettext_noop("perform the associated file operation")) #ifdef option_bodies { @@ -224,8 +228,8 @@ GOPT(help, "help,h", bool, false, gettex } #endif -GOPTVAR(rsa_keypair_id, signing_key, ) -GOPTION(key, key, true, "key,k", gettext_noop("set key for signatures")) +OPTVAR(key, rsa_keypair_id, signing_key, ) +OPTION(globals, key, true, "key,k", gettext_noop("set key for signatures")) #ifdef option_bodies { internalize_rsa_keypair_id(utf8(arg), signing_key); @@ -240,8 +244,8 @@ GOPT(key_dir, "keydir", system_path, , } #endif -COPTVAR(std::vector, keys_to_push, ) -COPTION(key_to_push, key_to_push, true, "key-to-push", +OPTVAR(key_to_push, std::vector, keys_to_push, ) +OPTION(key_to_push, key_to_push, true, "key-to-push", gettext_noop("push the specified key even if it hasn't signed anything")) #ifdef option_bodies { @@ -251,7 +255,7 @@ COPTION(key_to_push, key_to_push, true, } #endif -COPT(last, "last", long, -1, +OPT(last, "last", long, -1, gettext_noop("limit log output to the last number of entries")) #ifdef option_bodies { @@ -261,24 +265,24 @@ COPT(last, "last", long, -1, } #endif -GOPTION(log, log, true, "log", gettext_noop("file to write the log to")) +OPTION(globals, log, true, "log", gettext_noop("file to write the log to")) #ifdef option_bodies { ui.redirect_log_to(system_path(arg)); } #endif -COPTSET(messages) -COPTVAR(utf8, message, ) -COPTVAR(utf8, msgfile, ) -COPTION(messages, message, true, "message,m", +OPTSET(messages) +OPTVAR(messages, std::vector, message, ) +OPTVAR(messages, utf8, msgfile, ) +OPTION(messages, message, true, "message,m", gettext_noop("set commit changelog message")) #ifdef option_bodies { - message = utf8(arg); + message.push_back(arg); } #endif -COPTION(messages, msgfile, true, "message-file", +OPTION(messages, msgfile, true, "message-file", gettext_noop("set filename containing commit changelog message")) #ifdef option_bodies { @@ -286,7 +290,7 @@ COPTION(messages, msgfile, true, "messag } #endif -COPT(missing, "missing", bool, false, +OPT(missing, "missing", bool, false, gettext_noop("perform the operations for files missing from workspace")) #ifdef option_bodies { @@ -294,7 +298,7 @@ COPT(missing, "missing", bool, false, } #endif -COPT(next, "next", long, -1, +OPT(next, "next", long, -1, gettext_noop("limit log output to the next number of entries")) #ifdef option_bodies { @@ -304,7 +308,7 @@ COPT(next, "next", long, -1, } #endif -COPT(no_files, "no-files", bool, false, +OPT(no_files, "no-files", bool, false, gettext_noop("exclude files when printing logs")) #ifdef option_bodies { @@ -312,7 +316,7 @@ COPT(no_files, "no-files", bool, false, } #endif -COPT(no_merges, "no-merges", bool, false, +OPT(no_merges, "no-merges", bool, false, gettext_noop("exclude merges when printing logs")) #ifdef option_bodies { @@ -336,7 +340,7 @@ GOPT(nostd, "nostd", bool, false, } #endif -COPT(pidfile, "pid-file", system_path, , +GOPT(pidfile, "pid-file", system_path, , gettext_noop("record process id of server")) #ifdef option_bodies { @@ -372,7 +376,7 @@ gettext_noop("suppress warning, verbose, } #endif -COPT(recursive, "recursive,R", bool, false, +OPT(recursive, "recursive,R", bool, false, gettext_noop("also operate on the contents of any listed directories")) #ifdef option_bodies { @@ -380,8 +384,8 @@ COPT(recursive, "recursive,R", bool, fal } #endif -COPTVAR(std::vector, revision_selectors, ) -COPTION(revision, revision, true, "revision,r", +OPTVAR(revision, std::vector, revision_selectors, ) +OPTION(revision, revision, true, "revision,r", gettext_noop("select revision id for operation")) #ifdef option_bodies { @@ -397,7 +401,7 @@ GOPT(root, "root", system_path, current_ } #endif -COPT(set_default, "set-default", bool, false, +OPT(set_default, "set-default", bool, false, gettext_noop("use the current arguments as the future default")) #ifdef option_bodies { @@ -421,7 +425,7 @@ GOPT(ticker, "ticker", std::string, , } #endif -COPT(unknown, "unknown", bool, false, +OPT(unknown, "unknown", bool, false, gettext_noop("perform the operations for unknown files from workspace")) #ifdef option_bodies { @@ -429,7 +433,7 @@ COPT(unknown, "unknown", bool, false, } #endif -GOPT(verbose, "verbose", bool, false, +OPT(verbose, "verbose", bool, false, gettext_noop("verbose completion output")) #ifdef option_bodies { @@ -445,10 +449,9 @@ GOPT(version, "version", bool, false, } #endif -GOPT(argfile, "xargs,@", std::vector, , - gettext_noop("insert command line arguments taken from the given file")) +OPTION(globals, xargs, true, "xargs,@", + gettext_noop("insert command line arguments taken from the given file")) #ifdef option_bodies { - argfile.push_back(arg); } #endif ============================================================ --- sha1.cc f81e2a20ae2fb90e962f570303f71b6401ccf00e +++ sha1.cc 87a4887f50e5639094513256871e37180410163a @@ -92,7 +92,7 @@ void hook_botan_sha1() Botan::Engine_Core::add_engine(new Monotone_SHA1_Engine); } -CMD(benchmark_sha1, hidden_group(), "", "benchmark SHA-1 cores", option::none) +CMD(benchmark_sha1, hidden_group(), "", "benchmark SHA-1 cores", options::opts::none) { P(F("Benchmarking %s SHA-1 cores") % registry().size()); int mebibytes = 100; ============================================================ --- unit_tests.cc 14e5b4cb7908496abdc59779e8747e2dc2dfaec3 +++ unit_tests.cc 6bdf8e577c7d3908b25a6d3b45a894a5f5b2529b @@ -15,11 +15,16 @@ #include #include #include + +#include +#include +#include + #include #include -#include #include "botan/botan.h" +#include "option.hh" #include "unit_tests.hh" #include "sanity.hh" #include "ui.hh" @@ -37,7 +42,6 @@ typedef boost::unit_test::test_case boos using std::atexit; using boost::unit_test::test_suite; typedef boost::unit_test::test_case boost_unit_test_case; -namespace po = boost::program_options; // This must be a pointer. It is used by the constructor below, which is // used to construct file-scope objects in different files; if it were the @@ -147,60 +151,57 @@ test_suite * init_unit_test_suite(int ar test_suite * init_unit_test_suite(int argc, char * argv[]) { - po::variables_map vm; + bool help(false); + bool list_groups(false); + bool list_tests(false); + bool debug(false); + string log; + vector tests; + using boost::lambda::var; + using boost::lambda::bind; + using boost::lambda::_1; + using boost::function; try { - po::options_description od((FL("Usage: %s [options] [tests]\nOptions") - % argv[0]).str()); - od.add_options() - ("help,h", "display help message") - ("list-groups,l", "list all test groups") - ("list-tests,L", "list all test cases") - ("debug", "write verbose debug log to stderr") - ("log", po::value(), - "write verbose debug log to this file" - " (default is unit_tests.log)"); + option::concrete_option_set os; + os("help,h", "display help message", + function(var(help) = true)) + ("list-groups,l", "list all test groups", + function(var(list_groups) = true)) + ("list-tests,L", "list all test cases", + function(var(list_tests) = true)) + ("debug", "write verbose debug log to stderr", + function(var(debug) = true)) + ("log", "write verbose debug log to this file" + " (default is unit_tests.log)", + function(var(log) = _1)) + ("", "", function(bind(&vector::push_back, + &tests, _1))); - // we have to do this silly thing to get positional arguments to work - // without an extra entry appearing in --help output. even this does - // not prevent the use of --tests= on the command line. bug in library. - po::options_description odx(""); - odx.add(od); - odx.add_options()("tests", po::value< vector >()); - po::positional_options_description pd; - pd.add("tests", -1); + os.from_command_line(argc, argv); - po::store(po::command_line_parser(argc, argv). - options(odx).positional(pd).run(), vm); - po::notify(vm); - if (vm.count("help")) + if (help) { - cout << od << endl; + cout << (FL("Usage: %s [options] [tests]\nOptions") % argv[0]) + << os.get_usage_str() << endl; exit(0); } } - catch (po::ambiguous_option const & e) + catch (option::option_error const & e) { cerr << argv[0] << ": " << e.what() << endl; - vector::const_iterator it = e.alternatives.begin(); - for (; it != e.alternatives.end(); ++it) - cerr << *it << endl; exit(2); } - catch (po::error const & e) + + if (list_groups && list_tests) { - cerr << argv[0] << ": " << e.what() << endl; - exit(2); - } - if (vm.count("list-groups") && vm.count("list-tests")) - { cerr << argv[0] << ": only one of --list-groups and --list-tests at a time" << endl; exit(2); } - if (vm.count("list-groups")) + if (list_groups) { string last; for (unit_test_list_t::const_iterator i = unit_tests->begin(); @@ -214,7 +215,7 @@ test_suite * init_unit_test_suite(int ar exit(0); } - if (vm.count("list-tests")) + if (list_tests) { for (unit_test_list_t::const_iterator i = unit_tests->begin(); i != unit_tests->end(); @@ -226,7 +227,7 @@ test_suite * init_unit_test_suite(int ar // If we get here, we are really running the test suite. test_suite * suite = BOOST_TEST_SUITE("monotone unit tests"); - if (vm.count("tests") == 0) // run all tests + if (tests.size() == 0) // run all tests { string last; for (unit_test_list_t::const_iterator i = unit_tests->begin(); @@ -245,7 +246,6 @@ test_suite * init_unit_test_suite(int ar } else { - vector tests = vm["tests"].as< vector >(); bool unrecognized = false; for(vector::const_iterator i = tests.begin(); @@ -304,15 +304,15 @@ test_suite * init_unit_test_suite(int ar global_sanity.initialize(argc, argv, "C"); // we didn't call setlocale Botan::Init::initialize(); - if (vm.count("debug") == 0) + if (!debug) { // We would _like_ to use ui.redirect_log_to() but it takes a // system_path and we're not set up to use that here. char const * logname; - if (vm.count("log")) - logname = vm["log"].as().c_str(); + if (log.empty()) + logname = "unit_tests.log"; else - logname = "unit_tests.log"; + logname = log.c_str(); std::filebuf * logbuf = new std::filebuf; if (!logbuf->open(logname, std::ios_base::out|std::ios_base::trunc)) @@ -332,7 +332,7 @@ test_suite * init_unit_test_suite(int ar } else { - if (vm.count("log")) + if (!log.empty()) { cerr << argv[0] << ": only one of --debug and --log at a time"