# # # patch "app_state.cc" # from [e4fb02a8f19d796ac56f6a71c970795cc38ca5ec] # to [45d430553fae0fd9945c522f5b01d01163e46473] # # patch "cert.cc" # from [1635b3eb6deec329254ceed67527e4e5a853f7e9] # to [5f5bd00cd30ea0a126415b8c3096fb9167130abb] # # patch "cmd_diff_log.cc" # from [0b3b6640b02148e33843f175d78e503d039a887b] # to [4dff01d42fc9b1932194aca278c66d91fbc52e8a] # # patch "cmd_files.cc" # from [2b02d86f5d17375dc71a639c44b2de2471be6a4f] # to [4ac7c7881b82c1514f9c0ab27d497cb4d26e2f99] # # patch "cmd_key_cert.cc" # from [92378b2ad7b10d2c5c2fb432a52c14bc88bf322f] # to [8839c3105c7ab057a34996ad3dcd31c10bda8b94] # # patch "cmd_list.cc" # from [c2bd912e10c6518eb435a765d6085c6433006ffc] # to [9225c40c26da038298687494e33b2d09b3f60b60] # # patch "cmd_merging.cc" # from [09aeeda6808b4a9585ed3deba54f10f614971eac] # to [81fa693d2d3734313402547c0da9f2b619aed2c4] # # patch "cmd_netsync.cc" # from [15d5c9b709562f438cd8cde781f1bd4727953121] # to [c8cc983fd27b020b3f615bb1cf955e3f4c214501] # # patch "cmd_othervcs.cc" # from [0ea15c34e85e85d97d15c74f0e8d10749e9a60aa] # to [eca9c84370f8c095b4c8b09345304abbab248aa2] # # patch "cmd_ws_commit.cc" # from [812083b7054c02abb252f535ecce089b0a17bdfb] # to [86b9e07d0b1cce52da89ea39709c828bde81da88] # # patch "netsync.cc" # from [e90bd2aeb5deabd6e153bd9921ab8154fb7af8d3] # to [0e2f2ddb0eaf07ed09d96fcb649d6fb367692ec8] # # patch "option.cc" # from [f9bcfadfb5ea6629f70cb0a3cc106b000abf3800] # to [3047efe48698d34f0994458298a29c546f8ba5cb] # # patch "option.hh" # from [2bdce8881c879e3c45bfe5873454d53a5eb6362f] # to [4baeb00258d60503350b00cbb9a309a565676160] # # patch "option_list.hh" # from [15ae68787ffb067dd009a23b1e1b6ca502f01949] # to [e7c2f1ebe8b580e242753f1f87b1655895d4ee89] # # patch "revision.cc" # from [7c35aac3cb803f98fc5c9cfa5aad9eedb7478792] # to [dd09d28abc5ea243ff9a0a95750a03b735a280e6] # ============================================================ --- app_state.cc e4fb02a8f19d796ac56f6a71c970795cc38ca5ec +++ app_state.cc 45d430553fae0fd9945c522f5b01d01163e46473 @@ -101,7 +101,7 @@ app_state::process_options() L(FL("branch name is '%s'") % opts.branch_name); - if (!opts.signing_key_given) + if (!opts.key_given) internalize_rsa_keypair_id(key_option, opts.signing_key); } @@ -116,7 +116,7 @@ app_state::write_options() if (branch_is_sticky) branch_option = opts.branch_name; - if (opts.signing_key_given) + if (opts.key_given) externalize_rsa_keypair_id(opts.signing_key, key_option); work.set_ws_options(database_option, branch_option, key_option, keydir_option); ============================================================ --- cert.cc 1635b3eb6deec329254ceed67527e4e5a853f7e9 +++ cert.cc 5f5bd00cd30ea0a126415b8c3096fb9167130abb @@ -446,7 +446,7 @@ get_user_key(rsa_keypair_id & key, app_s get_user_key(rsa_keypair_id & key, app_state & app) { - if (app.opts.signing_key_given) + if (app.opts.key_given) { key = app.opts.signing_key; return; @@ -475,7 +475,7 @@ guess_branch(revision_id const & ident, app_state & app, cert_value & branchname) { - if ((app.opts.branch_name() != "") && app.opts.branch_name_given) + if ((app.opts.branch_name() != "") && app.opts.branch_given) { branchname = app.opts.branch_name(); } ============================================================ --- cmd_diff_log.cc 0b3b6640b02148e33843f175d78e503d039a887b +++ cmd_diff_log.cc 4dff01d42fc9b1932194aca278c66d91fbc52e8a @@ -334,8 +334,7 @@ CMD(diff, N_("informative"), N_("[PATH]. "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_format % option::no_show_encloser - % option::external_diff_args) + % option::diff_options) { bool new_is_archived; ostringstream header; @@ -350,12 +349,12 @@ CMD(diff, N_("informative"), N_("[PATH]. // initialize before transaction so we have a database to work with. - if (app.opts.revision.size() == 0) + if (app.opts.revision_selectors.size() == 0) app.require_workspace(); - else if (app.opts.revision.size() == 1) + else if (app.opts.revision_selectors.size() == 1) app.require_workspace(); - if (app.opts.revision.size() == 0) + if (app.opts.revision_selectors.size() == 0) { roster_t new_roster, old_roster; revision_id old_rid; @@ -364,7 +363,7 @@ CMD(diff, N_("informative"), N_("[PATH]. app.work.get_revision_id(old_rid); node_restriction mask(args_to_paths(args), - args_to_paths(app.opts.exclude), + args_to_paths(app.opts.exclude_patterns), app.opts.depth, old_roster, new_roster, app); @@ -376,12 +375,12 @@ CMD(diff, N_("informative"), N_("[PATH]. new_is_archived = false; header << "# old_revision [" << old_rid << "]" << "\n"; } - else if (app.opts.revision.size() == 1) + else if (app.opts.revision_selectors.size() == 1) { roster_t new_roster, old_roster; revision_id r_old_id; - complete(app, idx(app.opts.revision, 0)(), r_old_id); + complete(app, idx(app.opts.revision_selectors, 0)(), r_old_id); N(app.db.revision_exists(r_old_id), F("no such revision '%s'") % r_old_id); @@ -393,7 +392,7 @@ CMD(diff, N_("informative"), N_("[PATH]. // N(r_new.edges.size() == 1, F("current revision has no ancestor")); node_restriction mask(args_to_paths(args), - args_to_paths(app.opts.exclude), + args_to_paths(app.opts.exclude_patterns), app.opts.depth, old_roster, new_roster, app); @@ -405,13 +404,13 @@ CMD(diff, N_("informative"), N_("[PATH]. new_is_archived = false; header << "# old_revision [" << r_old_id << "]" << "\n"; } - else if (app.opts.revision.size() == 2) + else if (app.opts.revision_selectors.size() == 2) { roster_t new_roster, old_roster; revision_id r_old_id, r_new_id; - complete(app, idx(app.opts.revision, 0)(), r_old_id); - complete(app, idx(app.opts.revision, 1)(), r_new_id); + complete(app, idx(app.opts.revision_selectors, 0)(), r_old_id); + complete(app, idx(app.opts.revision_selectors, 1)(), r_new_id); N(app.db.revision_exists(r_old_id), F("no such revision '%s'") % r_old_id); @@ -422,7 +421,7 @@ CMD(diff, N_("informative"), N_("[PATH]. app.db.get_roster(r_new_id, new_roster); node_restriction mask(args_to_paths(args), - args_to_paths(app.opts.exclude), + args_to_paths(app.opts.exclude_patterns), app.opts.depth, old_roster, new_roster, app); @@ -545,27 +544,27 @@ CMD(log, N_("informative"), N_("[FILE] . option::last % option::next % option::revision % option::brief % option::diffs % option::no_merges % option::no_files) { - if (app.opts.revision.size() == 0) + if (app.opts.revision_selectors.size() == 0) app.require_workspace("try passing a --revision to start at"); temp_node_id_source nis; set frontier; revision_id first_rid; - if (app.opts.revision.size() == 0) + if (app.opts.revision_selectors.size() == 0) { app.work.get_revision_id(first_rid); frontier.insert(first_rid); } else { - for (vector::const_iterator i = app.opts.revision.begin(); - i != app.opts.revision.end(); i++) + for (vector::const_iterator i = app.opts.revision_selectors.begin(); + i != app.opts.revision_selectors.end(); i++) { set rids; complete(app, (*i)(), rids); frontier.insert(rids.begin(), rids.end()); - if (i == app.opts.revision.begin()) + if (i == app.opts.revision_selectors.begin()) first_rid = *rids.begin(); } } @@ -577,7 +576,7 @@ CMD(log, N_("informative"), N_("[FILE] . // User wants to trace only specific files roster_t old_roster, new_roster; - if (app.opts.revision.size() == 0) + if (app.opts.revision_selectors.size() == 0) app.work.get_base_and_current_roster_shape(old_roster, new_roster, nis); else app.db.get_roster(first_rid, new_roster); @@ -585,7 +584,7 @@ CMD(log, N_("informative"), N_("[FILE] . // FIXME_RESTRICTIONS: should this add paths from the rosters of // all selected revs? mask = node_restriction(args_to_paths(args), - args_to_paths(app.opts.exclude), + args_to_paths(app.opts.exclude_patterns), app.opts.depth, old_roster, new_roster, app); } ============================================================ --- cmd_files.cc 2b02d86f5d17375dc71a639c44b2de2471be6a4f +++ cmd_files.cc 4ac7c7881b82c1514f9c0ab27d497cb4d26e2f99 @@ -77,8 +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_format % option::no_show_encloser - % option::external_diff_args) + option::diff_options) { if (args.size() != 4) throw usage(name); @@ -118,20 +117,20 @@ CMD(annotate, N_("informative"), N_("PAT { revision_id rid; - if (app.opts.revision.size() == 0) + if (app.opts.revision_selectors.size() == 0) app.require_workspace(); - if ((args.size() != 1) || (app.opts.revision.size() > 1)) + if ((args.size() != 1) || (app.opts.revision_selectors.size() > 1)) throw usage(name); file_path file = file_path_external(idx(args, 0)); split_path sp; file.split(sp); - if (app.opts.revision.size() == 0) + if (app.opts.revision_selectors.size() == 0) app.work.get_revision_id(rid); else - complete(app, idx(app.opts.revision, 0)(), rid); + complete(app, idx(app.opts.revision_selectors, 0)(), rid); N(!null_id(rid), F("no revision for file '%s' in database") % file); @@ -187,16 +186,16 @@ CMD(cat, N_("informative"), if (args.size() != 1) throw usage(name); - if (app.opts.revision.size() == 0) + if (app.opts.revision_selectors.size() == 0) app.require_workspace(); transaction_guard guard(app.db, false); revision_id rid; - if (app.opts.revision.size() == 0) + if (app.opts.revision_selectors.size() == 0) app.work.get_revision_id(rid); else - complete(app, idx(app.opts.revision, 0)(), rid); + complete(app, idx(app.opts.revision_selectors, 0)(), rid); N(app.db.revision_exists(rid), F("no such revision '%s'") % rid); ============================================================ --- cmd_key_cert.cc 92378b2ad7b10d2c5c2fb432a52c14bc88bf322f +++ cmd_key_cert.cc 8839c3105c7ab057a34996ad3dcd31c10bda8b94 @@ -221,7 +221,7 @@ CMD(approve, N_("review"), N_("REVISION" CMD(approve, N_("review"), N_("REVISION"), N_("approve of a particular revision"), - option::branch_name) + option::branch) { if (args.size() != 1) throw usage(name); ============================================================ --- cmd_list.cc c2bd912e10c6518eb435a765d6085c6433006ffc +++ cmd_list.cc 9225c40c26da038298687494e33b2d09b3f60b60 @@ -238,7 +238,7 @@ ls_branches(string name, app_state & app inc = idx(args,0); else if (args.size() > 1) throw usage(name); - combine_and_check_globish(app.opts.exclude, exc); + combine_and_check_globish(app.opts.exclude_patterns, exc); globish_matcher match(inc, exc); vector names; app.db.get_branches(names); @@ -347,7 +347,7 @@ ls_known(app_state & app, vector c app.work.get_base_and_current_roster_shape(old_roster, new_roster, nis); node_restriction mask(args_to_paths(args), - args_to_paths(app.opts.exclude), + args_to_paths(app.opts.exclude_patterns), app.opts.depth, new_roster, app); @@ -374,7 +374,7 @@ ls_unknown_or_ignored(app_state & app, b app.require_workspace(); vector roots = args_to_paths(args); - path_restriction mask(roots, args_to_paths(app.opts.exclude), + path_restriction mask(roots, args_to_paths(app.opts.exclude_patterns), app.opts.depth, app); path_set unknown, ignored; @@ -401,7 +401,7 @@ ls_missing(app_state & app, vector roster_t current_roster_shape; app.work.get_current_roster_shape(current_roster_shape, nis); node_restriction mask(args_to_paths(args), - args_to_paths(app.opts.exclude), + args_to_paths(app.opts.exclude_patterns), app.opts.depth, current_roster_shape, app); @@ -429,7 +429,7 @@ ls_changed(app_state & app, vector app.work.get_base_and_current_roster_shape(old_roster, new_roster, nis); node_restriction mask(args_to_paths(args), - args_to_paths(app.opts.exclude), + args_to_paths(app.opts.exclude_patterns), app.opts.depth, old_roster, new_roster, app); ============================================================ --- cmd_merging.cc 09aeeda6808b4a9585ed3deba54f10f614971eac +++ cmd_merging.cc 81fa693d2d3734313402547c0da9f2b619aed2c4 @@ -76,12 +76,12 @@ 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_name % option::revision) + option::branch % option::revision) { if (args.size() > 0) throw usage(name); - if (app.opts.revision.size() > 1) + if (app.opts.revision_selectors.size() > 1) throw usage(name); app.require_workspace(); @@ -97,7 +97,7 @@ CMD(update, N_("workspace"), "", // Figure out where we're going revision_id chosen_rid; - if (app.opts.revision.size() == 0) + if (app.opts.revision_selectors.size() == 0) { P(F("updating along branch '%s'") % app.opts.branch_name); set candidates; @@ -120,7 +120,7 @@ CMD(update, N_("workspace"), "", } else { - complete(app, app.opts.revision[0](), chosen_rid); + complete(app, app.opts.revision_selectors[0](), chosen_rid); N(app.db.revision_exists(chosen_rid), F("no such revision '%s'") % chosen_rid); } @@ -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_name % option::date % option::author) + option::branch % option::date % option::author) { typedef std::pair revpair; typedef set::const_iterator rid_set_iter; @@ -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_name % option::date % option::author) + option::branch % option::date % option::author) { if (args.size() != 2) throw usage(name); @@ -670,9 +670,9 @@ CMD(pluck, N_("workspace"), N_("[-r FROM // Work out our arguments revision_id from_rid, to_rid; - if (app.opts.revision.size() == 1) + if (app.opts.revision_selectors.size() == 1) { - complete(app, idx(app.opts.revision, 0)(), to_rid); + complete(app, idx(app.opts.revision_selectors, 0)(), to_rid); N(app.db.revision_exists(to_rid), F("no such revision '%s'") % to_rid); std::set parents; @@ -685,12 +685,12 @@ CMD(pluck, N_("workspace"), N_("[-r FROM % ui.prog_name % to_rid); from_rid = *parents.begin(); } - else if (app.opts.revision.size() == 2) + else if (app.opts.revision_selectors.size() == 2) { - complete(app, idx(app.opts.revision, 0)(), from_rid); + complete(app, idx(app.opts.revision_selectors, 0)(), from_rid); N(app.db.revision_exists(from_rid), F("no such revision '%s'") % from_rid); - complete(app, idx(app.opts.revision, 1)(), to_rid); + complete(app, idx(app.opts.revision_selectors, 1)(), to_rid); N(app.db.revision_exists(to_rid), F("no such revision '%s'") % to_rid); } @@ -748,7 +748,7 @@ CMD(pluck, N_("workspace"), N_("[-r FROM roster_t to_true_roster; app.db.get_roster(to_rid, to_true_roster); node_restriction mask(args_to_paths(args), - args_to_paths(app.opts.exclude), + args_to_paths(app.opts.exclude_patterns), app.opts.depth, *from_roster, to_true_roster, app); make_restricted_csets(*from_roster, to_true_roster, @@ -819,7 +819,7 @@ CMD(heads, N_("tree"), "", N_("show unme } CMD(heads, N_("tree"), "", N_("show unmerged head revisions of branch"), - option::branch_name) + option::branch) { set heads; if (args.size() != 0) ============================================================ --- cmd_netsync.cc 15d5c9b709562f438cd8cde781f1bd4727953121 +++ cmd_netsync.cc c8cc983fd27b020b3f615bb1cf955e3f4c214501 @@ -61,7 +61,7 @@ process_netsync_args(string const & name int pattern_offset = (serve_mode ? 0 : 1); vector patterns(args.begin() + pattern_offset, args.end()); combine_and_check_globish(patterns, include_pattern); - combine_and_check_globish(app.opts.exclude, exclude_pattern); + combine_and_check_globish(app.opts.exclude_patterns, exclude_pattern); if (use_defaults && (!app.db.var_exists(default_include_pattern_key) || app.opts.set_default)) ============================================================ --- cmd_othervcs.cc 0ea15c34e85e85d97d15c74f0e8d10749e9a60aa +++ cmd_othervcs.cc eca9c84370f8c095b4c8b09345304abbab248aa2 @@ -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_name) + option::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_name) + option::branch) { if (args.size() != 1) throw usage(name); ============================================================ --- cmd_ws_commit.cc 812083b7054c02abb252f535ecce089b0a17bdfb +++ cmd_ws_commit.cc 86b9e07d0b1cce52da89ea39709c828bde81da88 @@ -71,14 +71,14 @@ CMD(revert, N_("workspace"), N_("[PATH]. roster_t old_roster, new_roster; cset included, excluded; - N(app.opts.missing || !args.empty() || !app.opts.exclude.empty(), + N(app.opts.missing || !args.empty() || !app.opts.exclude_patterns.empty(), F("you must pass at least one path to 'revert' (perhaps '.')")); app.require_workspace(); app.work.get_base_and_current_roster_shape(old_roster, new_roster, nis); - node_restriction mask(args_to_paths(args), args_to_paths(app.opts.exclude), + node_restriction mask(args_to_paths(args), args_to_paths(app.opts.exclude_patterns), app.opts.depth, old_roster, new_roster, app); @@ -188,7 +188,7 @@ CMD(disapprove, N_("review"), N_("REVISI CMD(disapprove, N_("review"), N_("REVISION"), N_("disapprove of a particular revision"), - option::branch_name) + option::branch) { if (args.size() != 1) throw usage(name); @@ -251,7 +251,7 @@ CMD(add, N_("workspace"), N_("[PATH]..." if (app.opts.unknown) { vector roots = args_to_paths(args); - path_restriction mask(roots, args_to_paths(app.opts.exclude), app.opts.depth, app); + path_restriction mask(roots, args_to_paths(app.opts.exclude_patterns), app.opts.depth, app); path_set ignored; // if no starting paths have been specified use the workspace root @@ -289,7 +289,7 @@ CMD(drop, N_("workspace"), N_("[PATH]... roster_t current_roster_shape; app.work.get_current_roster_shape(current_roster_shape, nis); node_restriction mask(args_to_paths(args), - args_to_paths(app.opts.exclude), + args_to_paths(app.opts.exclude_patterns), app.opts.depth, current_roster_shape, app); app.work.find_missing(current_roster_shape, mask, paths); @@ -367,7 +367,7 @@ CMD(status, N_("informative"), N_("[PATH app.work.get_base_and_current_roster_shape(old_roster, new_roster, nis); node_restriction mask(args_to_paths(args), - args_to_paths(app.opts.exclude), + args_to_paths(app.opts.exclude_patterns), app.opts.depth, old_roster, new_roster, app); @@ -422,17 +422,17 @@ 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_name % option::revision) + option::branch % option::revision) { revision_id ident; system_path dir; transaction_guard guard(app.db, false); - if (args.size() > 1 || app.opts.revision.size() > 1) + if (args.size() > 1 || app.opts.revision_selectors.size() > 1) throw usage(name); - if (app.opts.revision.size() == 0) + if (app.opts.revision_selectors.size() == 0) { // use branch head revision N(!app.opts.branch_name().empty(), @@ -452,10 +452,10 @@ CMD(checkout, N_("tree"), N_("[DIRECTORY } ident = *(heads.begin()); } - else if (app.opts.revision.size() == 1) + else if (app.opts.revision_selectors.size() == 1) { // use specified revision - complete(app, idx(app.opts.revision, 0)(), ident); + complete(app, idx(app.opts.revision_selectors, 0)(), ident); N(app.db.revision_exists(ident), F("no such revision '%s'") % ident); @@ -659,7 +659,7 @@ CMD(commit, N_("workspace"), N_("[PATH]. CMD(commit, N_("workspace"), N_("[PATH]..."), N_("commit workspace to database"), - option::branch_name % option::message % option::msgfile % option::date + option::branch % option::message % option::msgfile % option::date % option::author % option::depth % option::exclude) { utf8 log_message(""); @@ -675,7 +675,7 @@ CMD(commit, N_("workspace"), N_("[PATH]. app.work.get_base_and_current_roster_shape(old_roster, new_roster, nis); node_restriction mask(args_to_paths(args), - args_to_paths(app.opts.exclude), + args_to_paths(app.opts.exclude_patterns), app.opts.depth, old_roster, new_roster, app); @@ -899,7 +899,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_name) + option::branch) { if (args.size() > 1) throw usage(name); ============================================================ --- netsync.cc e90bd2aeb5deabd6e153bd9921ab8154fb7af8d3 +++ netsync.cc 0e2f2ddb0eaf07ed09d96fcb649d6fb367692ec8 @@ -3069,8 +3069,8 @@ session::rebuild_merkle_trees(app_state // Add any keys specified on the command line. for (vector::const_iterator key - = app.opts.key_to_push.begin(); - key != app.opts.key_to_push.end(); ++key) + = app.opts.keys_to_push.begin(); + key != app.opts.keys_to_push.end(); ++key) { if (inserted_keys.find(*key) == inserted_keys.end()) { ============================================================ --- option.cc f9bcfadfb5ea6629f70cb0a3cc106b000abf3800 +++ option.cc 3047efe48698d34f0994458298a29c546f8ba5cb @@ -1,3 +1,5 @@ +#include + #include #include @@ -41,6 +43,70 @@ struct bad_arg_internal bad_arg_internal(string const & str = "") : reason(str) {} }; + + +map > & option_groups() +{ + 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; @@ -113,83 +179,107 @@ option::options::options() option::options::options() { -# define GOPT(varname, optname, type, default_, description) \ - map_opt(&options::set_ ## varname, optname, \ - option:: varname, has_arg(), description); \ - global_option.add( option:: varname ); \ - varname = type ( default_ ); \ - varname ## _given = false; -# define COPT(varname, optname, type, default_, description) \ - map_opt(&options::set_ ## varname, optname, \ - option:: varname, has_arg(), description); \ - all_cmd_option.add( option:: varname ); \ - varname = type ( default_ ); \ - varname ## _given = false; +# 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 GOPT -# undef COPT + +# undef COPTSET +# undef GOPTSET +# undef COPTVAR +# undef GOPTVAR +# undef COPTION +# undef GOPTION +# undef OPTSET_REL } void option::options::clear_cmd_options() { -# define GOPT(varname, optname, type, default_, description) -# define COPT(varname, optname, type, default_, description) \ - varname = type ( default_ ); \ - varname ## _given = false; +# 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 GOPT -# undef COPT + +# undef COPTSET +# undef GOPTSET +# undef COPTVAR +# undef GOPTVAR +# undef COPTION +# undef GOPTION +# undef OPTSET_REL } void option::options::clear_global_options() { -# define GOPT(varname, optname, type, default_, description) \ - varname = type ( default_ ); \ - varname ## _given = false; -# define COPT(varname, optname, type, default_, description) +# 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 GOPT -# undef COPT + +# undef COPTSET +# undef GOPTSET +# undef COPTVAR +# undef GOPTVAR +# undef COPTION +# undef GOPTION +# undef OPTSET_REL } -#define GOPT(varname, optname, type, default_, description) \ - void option::options::set_ ## varname (std::string const & arg) \ - { \ - varname ## _given = true; \ - try {set_ ## varname ## _helper (arg); } \ - catch (boost::bad_lexical_cast) \ - { throw bad_arg( #varname, arg); } \ - catch (bad_arg_internal & e) \ - { \ - if (e.reason == "") \ - throw bad_arg( #varname, arg); \ - else \ - throw bad_arg( #varname, arg, e.reason); \ - } \ - } \ - void option::options::set_ ## varname ## _helper (string const & arg) -#define COPT(varname, optname, type, default_, description) \ - void option::options::set_ ## varname (std::string const & arg) \ - { \ - varname ## _given = true; \ - try {set_ ## varname ## _helper (arg); } \ - catch (boost::bad_lexical_cast) \ - { throw bad_arg( #varname, arg); } \ - catch (bad_arg_internal & e) \ - { \ - if (e.reason == "") \ - throw bad_arg( #varname, arg); \ - else \ - throw bad_arg( #varname, arg, e.reason); \ - } \ - } \ - void option::options::set_ ## varname ## _helper (string const & arg) +# 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 GOPT -#undef COPT +# 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) { @@ -203,10 +293,70 @@ option::options::getopt(string const & n return i->second; } +void +option::options::note_given(optid id) +{ + 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; +} + +void option::options::set(string const & name, + opt const & o, + string const & given) +{ + note_given(o.id); + try + { + (this->*o.setter)(given); + } + 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) { - (this->*getopt(name, allowed).setter)(given); + set(name, getopt(name, allowed), given); } static void @@ -351,12 +501,13 @@ void option::options::from_cmdline_restr if (separate_arg) args.erase(args.begin() + i); args.insert(args.begin()+i, fargs.begin(), fargs.end()); + --i; } else { if (separate_arg) ++i; - (this->*o.setter)(arg); + set(name, o, arg); } } } ============================================================ --- option.hh 2bdce8881c879e3c45bfe5873454d53a5eb6362f +++ option.hh 4baeb00258d60503350b00cbb9a309a565676160 @@ -48,36 +48,38 @@ namespace option { namespace option { enum optid { -# define GOPT(varname, optname, type, default_, description) \ - varname, -# define COPT(varname, optname, type, default_, description) \ - GOPT(varname, optname, type, default_, description) +# 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) + # include "option_list.hh" -# undef GOPT -# undef COPT + +# undef COPTSET +# undef GOPTSET +# undef COPTVAR +# undef GOPTVAR +# undef COPTION +# undef GOPTION +# undef OPTSET_REL + none }; class optset { std::set items; public: - void add(option::optid item) - { - items.insert(item); - } - optset & operator%(option::optid item) - { - add(item); - return *this; - } - bool contains(option::optid id) const - { - return items.find(id) != items.end(); - } - bool empty() const - { - return items.empty(); - } + void add(option::optid item); + optset & operator%(option::optid item); + bool contains(option::optid id) const; + bool empty() const; }; struct options @@ -98,25 +100,52 @@ namespace option { std::string get_usage_str(optset const & opts) const; -# define GOPT(varname, optname, type, default_, description) \ - type varname; \ - bool varname ## _given; -# define COPT(varname, optname, type, default_, description) \ - GOPT(varname, optname, type, default_, description) +# 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) + # include "option_list.hh" -# undef GOPT -# undef COPT + +# undef COPTSET +# undef GOPTSET +# undef COPTVAR +# undef GOPTVAR +# undef COPTION +# undef GOPTION +# undef OPTSET_REL + private: -# define GOPT(varname, optname, type, default_, description) \ - void set_ ## varname (std::string const & arg); \ - void set_ ## varname ## _helper (std::string const & arg); -# define COPT(varname, optname, type, default_, description) \ - void set_ ## varname (std::string const & arg); \ - void set_ ## varname ## _helper (std::string const & arg); + +# 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 GOPT -# undef COPT +# undef COPTSET +# undef GOPTSET +# undef COPTVAR +# undef GOPTVAR +# undef COPTION +# undef GOPTION +# undef OPTSET_REL + struct opt { void (options::*setter)(std::string const &); @@ -124,11 +153,15 @@ namespace option { 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, ============================================================ --- option_list.hh 15ae68787ffb067dd009a23b1e1b6ca502f01949 +++ option_list.hh e7c2f1ebe8b580e242753f1f87b1655895d4ee89 @@ -1,3 +1,10 @@ +#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) + GOPT(args, "", std::vector, , "") #ifdef option_bodies { @@ -5,8 +12,7 @@ GOPT(args, "", std::vector, , "") } #endif -COPT(author, "author", utf8, , - gettext_noop("override author for commit")) +COPT(author, "author", utf8, , gettext_noop("override author for commit")) #ifdef option_bodies { author = arg; @@ -30,9 +36,24 @@ COPT(bind, "bind", bind_opt, , bind.set(arg); } #endif +COPT(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")) +#ifdef option_bodies +{ + // Yes, this sets a field in the structure belonging to the "bind" option. + bind.stdio = true; +} +#endif -COPT(branch_name, "branch,b", utf8, , - gettext_noop("select branch cert for operation")) +COPTVAR(utf8, branch_name, ) +COPTION(branch, branch, true, "branch,b", + gettext_noop("select branch cert for operation")) #ifdef option_bodies { branch_name = utf8(arg); @@ -86,11 +107,10 @@ GOPT(dbname, "db,d", system_path, , gett } #endif -GOPT(debug, "debug", bool, false, - gettext_noop("print debug log to stderr while running")) +GOPTION(debug, debug, false, "debug", + gettext_noop("print debug log to stderr while running")) #ifdef option_bodies { - debug = true; global_sanity.set_debug(); } #endif @@ -105,28 +125,48 @@ COPT(depth, "depth", long, -1, } #endif -COPT(external_diff_args, "diff-args", std::string, , - gettext_noop("argument to pass external diff hook")) + +COPTSET(diff_options) + +COPTVAR(std::string, external_diff_args, ) +COPTION(diff_options, external_diff_args, true, "diff-args", + gettext_noop("argument to pass external diff hook")) #ifdef option_bodies { external_diff_args = arg; } #endif -COPT(diff_format, "diff-type", diff_type, unified_diff, - gettext_noop("argument to pass external diff hook")) +COPTVAR(diff_type, diff_format, unified_diff) +COPTION(diff_options, diff_context, false, "context", + gettext_noop("use context diff format")) #ifdef option_bodies { - if (arg == _("context")) - diff_format = context_diff; - else if (arg == _("external")) - diff_format = external_diff; - else if (arg == _("unified")) - diff_format = unified_diff; - else - throw bad_arg_internal(F("unknown diff type").str()); + diff_format = context_diff; } #endif +COPTION(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", + 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", + gettext_noop("do not show the function containing each block of changes")) +#ifdef option_bodies +{ + no_show_encloser = true; +} +#endif COPT(diffs, "diffs", bool, false, gettext_noop("print diffs along with logs")) #ifdef option_bodies @@ -135,33 +175,34 @@ COPT(diffs, "diffs", bool, false, gettex } #endif -COPT(drop_attr, "drop-attr", std::set, , - gettext_noop("when rosterifying, drop attrs entries with the given key")) +COPTVAR(std::set, attrs_to_drop, ) +COPTION(drop_attr, drop_attr, true, "drop-attr", + gettext_noop("when rosterifying, drop attrs entries with the given key")) #ifdef option_bodies { - drop_attr.insert(arg); + attrs_to_drop.insert(arg); } #endif -GOPT(dump, "dump", system_path, , - gettext_noop("file to dump debugging log to, on failure")) +GOPTION(dump, dump, true, "dump", + gettext_noop("file to dump debugging log to, on failure")) #ifdef option_bodies { - dump = system_path(arg); - global_sanity.filename = system_path(dump).as_external(); + global_sanity.filename = system_path(arg).as_external(); } #endif -COPT(exclude, "exclude", std::vector, , - gettext_noop("leave out anything described by its argument")) +COPTVAR(std::vector, exclude_patterns, ) +COPTION(exclude, exclude, true, "exclude", + gettext_noop("leave out anything described by its argument")) #ifdef option_bodies { - exclude.push_back(utf8(arg)); + exclude_patterns.push_back(utf8(arg)); } #endif COPT(execute, "execute,e", bool, false, - gettext_noop("perform the associated file operation")) + gettext_noop("perform the associated file operation")) #ifdef option_bodies { execute = true; @@ -176,16 +217,15 @@ GOPT(full_version, "full-version", bool, } #endif -GOPT(help, "help,h", bool, false, - gettext_noop("display help message")) +GOPT(help, "help,h", bool, false, gettext_noop("display help message")) #ifdef option_bodies { help = true; } #endif -GOPT(signing_key, "key,k", rsa_keypair_id, , - gettext_noop("set key for signatures")) +GOPTVAR(rsa_keypair_id, signing_key, ) +GOPTION(key, key, true, "key,k", gettext_noop("set key for signatures")) #ifdef option_bodies { internalize_rsa_keypair_id(utf8(arg), signing_key); @@ -200,13 +240,14 @@ GOPT(key_dir, "keydir", system_path, , } #endif -COPT(key_to_push, "key-to-push", std::vector, , - gettext_noop("push the specified key even if it hasn't signed anything")) +COPTVAR(std::vector, keys_to_push, ) +COPTION(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 { rsa_keypair_id keyid; internalize_rsa_keypair_id(utf8(arg), keyid); - key_to_push.push_back(keyid); + keys_to_push.push_back(keyid); } #endif @@ -220,25 +261,25 @@ COPT(last, "last", long, -1, } #endif -GOPT(log, "log", system_path, , - gettext_noop("file to write the log to")) +GOPTION(log, log, true, "log", gettext_noop("file to write the log to")) #ifdef option_bodies { - log = system_path(arg); - ui.redirect_log_to(log); + ui.redirect_log_to(system_path(arg)); } #endif -COPT(message, "message,m", utf8, , - gettext_noop("set commit changelog message")) +COPTSET(messages) +COPTVAR(utf8, message, ) +COPTVAR(utf8, msgfile, ) +COPTION(messages, message, true, "message,m", + gettext_noop("set commit changelog message")) #ifdef option_bodies { - message = arg; + message = utf8(arg); } #endif - -COPT(msgfile, "message-file", utf8, , - gettext_noop("set filename containing commit changelog message")) +COPTION(messages, msgfile, true, "message-file", + gettext_noop("set filename containing commit changelog message")) #ifdef option_bodies { msgfile = utf8(arg); @@ -287,14 +328,6 @@ gettext_noop("do not load ~/.monotone/mo } #endif -COPT(no_show_encloser, "no-show-encloser", bool, false, - gettext_noop("do not show the function containing each block of changes")) -#ifdef option_bodies -{ - no_show_encloser = true; -} -#endif - GOPT(nostd, "nostd", bool, false, gettext_noop("do not load standard lua hooks")) #ifdef option_bodies @@ -303,14 +336,6 @@ GOPT(nostd, "nostd", bool, false, } #endif -COPT(no_transport_auth, "no-transport-auth", bool, false, - gettext_noop("disable transport authentication")) -#ifdef option_bodies -{ - no_transport_auth = true; -} -#endif - COPT(pidfile, "pid-file", system_path, , gettext_noop("record process id of server")) #ifdef option_bodies @@ -355,11 +380,12 @@ COPT(recursive, "recursive,R", bool, fal } #endif -COPT(revision, "revision,r", std::vector, , +COPTVAR(std::vector, revision_selectors, ) +COPTION(revision, revision, true, "revision,r", gettext_noop("select revision id for operation")) #ifdef option_bodies { - revision.push_back(arg); + revision_selectors.push_back(arg); } #endif @@ -379,14 +405,6 @@ COPT(set_default, "set-default", bool, f } #endif -COPT(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. - bind.stdio = true; -} -#endif - GOPT(ticker, "ticker", std::string, , gettext_noop("set ticker style (count|dot|none)")) #ifdef option_bodies @@ -399,7 +417,7 @@ GOPT(ticker, "ticker", std::string, , else if (ticker == "count") ui.set_tick_writer(new tick_write_count); else - help = true; + throw bad_arg_internal(F("argument must be 'none', 'dot', or 'count'").str()); } #endif ============================================================ --- revision.cc 7c35aac3cb803f98fc5c9cfa5aad9eedb7478792 +++ revision.cc dd09d28abc5ea243ff9a0a95750a03b735a280e6 @@ -1434,7 +1434,7 @@ anc_graph::construct_revisions_from_ance k != fattrs.end(); ++k) { string key = k->first; - if (app.opts.drop_attr.find(key) != app.opts.drop_attr.end()) + if (app.opts.attrs_to_drop.find(key) != app.opts.attrs_to_drop.end()) { // ignore it }