# # # patch "automate.cc" # from [67f9c8a05bfa66bf3761cbb0798a9648f3088baa] # to [90f779d3805f2fd9b36e01310fac6c3885f4304a] # # patch "options.hh" # from [e3783797c78b59fa4679c2a417bdb59ef19b60e3] # to [9ca1ad470e21a92ba2c0a0280281c548bb31e013] # # patch "options_list.hh" # from [09854be32f901676c97f66d3014c5e786d6b18fd] # to [8430618df5f22ba903a7f388c84a9056c636ae85] # ============================================================ --- automate.cc 67f9c8a05bfa66bf3761cbb0798a9648f3088baa +++ automate.cc 90f779d3805f2fd9b36e01310fac6c3885f4304a @@ -2410,7 +2410,7 @@ automate_stdio_shared_setup(app_state & // set a fixed ticker type regardless what the user wants to // see, because anything else would screw the stdio-encoded output if (ft == force_stdio_ticker) - app.opts.ticker = "stdio"; + app.opts.ticker.unchecked_set("stdio"); } std::pair automate_stdio_helpers:: ============================================================ --- options.hh e3783797c78b59fa4679c2a417bdb59ef19b60e3 +++ options.hh 9ca1ad470e21a92ba2c0a0280281c548bb31e013 @@ -47,6 +47,60 @@ public: operator long() const { return value; } }; +class enum_string +{ + std::string allowed; + std::string value; +public: + enum_string() { } + enum_string(std::string const & a) : allowed(a) + { + size_t x = allowed.find(","); + value = allowed.substr(0, x); + } + void set(std::string const & v) + { + if (v.find(",") != std::string::npos + || allowed.find(v) == std::string::npos) + { + throw option::bad_arg_internal((F("must be one of the following: %s") + % allowed).str()); + } + else + value = v; + } + void unchecked_set(std::string const & v) { value = v; } + operator std::string() const { return value; } + bool operator<(enum_string const & e) const { return value < e.value; } + bool operator==(std::string const & s) const { return value == s; } + bool empty() const { return value.empty(); } +}; +class enum_string_set +{ + std::string allowed; + std::set value; +public: + enum_string_set() { } + enum_string_set(std::string const & a) : allowed(a) { } + void add(std::string const & v) + { + enum_string e(allowed); + e.set(v); + value.insert(e); + } + operator std::set() const { return value; } + std::set::const_iterator find(std::string const & s) const + { + enum_string e(allowed); + e.set(s); + return value.find(e); + } + std::set::const_iterator end() const + { + return value.end(); + } +}; + struct options { options(); ============================================================ --- options_list.hh 09854be32f901676c97f66d3014c5e786d6b18fd +++ options_list.hh 8430618df5f22ba903a7f388c84a9056c636ae85 @@ -133,6 +133,13 @@ void set_simple_option(std::set template<> void set_simple_option(std::set & t, std::string const & arg) { t.insert(arg); } +template<> +void set_simple_option(enum_string & t, std::string const & arg) +{ t.set(arg); } +template<> +void set_simple_option(enum_string_set & t, std::string const & arg) +{ t.add(arg); } + # define SIMPLE_OPTION_BODY(name) { set_simple_option(name, arg); } #else # define SIMPLE_OPTION_BODY(name) @@ -158,6 +165,12 @@ void set_simple_option(std::set OPTSET(name) \ GROUPED_SIMPLE_OPTION(name, name, optstring, type, description) +#define SIMPLE_INITIALIZED_OPTION(name, optstring, type, init, description) \ + OPTSET(name) \ + OPTVAR(name, type, name, init) \ + OPTION(name, name, has_arg(), optstring, description) \ + SIMPLE_OPTION_BODY(name) + // Like SIMPLE_OPTION, but the declared option is a member of the globals #define GLOBAL_SIMPLE_OPTION(name, optstring, type, description) \ OPTSET_REL(globals, name) \ @@ -363,28 +376,14 @@ SIMPLE_OPTION(move_conflicting_paths, gettext_noop("move conflicting, unversioned paths into _MTN/resolutions " "before proceeding with any workspace change")) -GOPT(ssh_sign, "ssh-sign", std::string, "yes", +OPTSET_REL(globals, ssh_sign) +SIMPLE_INITIALIZED_OPTION(ssh_sign, "ssh-sign", enum_string, "yes,no,only,check", gettext_noop("controls use of ssh-agent. valid arguments are: " "'yes' to use ssh-agent to make signatures if possible, " "'no' to force use of monotone's internal code, " "'only' to force use of ssh-agent, " "'check' to sign with both and compare")) -#ifdef option_bodies -{ - if (arg.empty()) - throw bad_arg_internal(F("--ssh-sign requires a value " - "['yes', 'no', 'only', or 'check']").str()); - if (arg != "yes" - && arg != "no" - && arg != "check" - && arg != "only") // XXX what does "only" do? not documented - throw bad_arg_internal(F("--ssh-sign must be set to 'yes', 'no', " - "'only', or 'check'").str()); - ssh_sign = arg; -} -#endif - SIMPLE_OPTION(force_duplicate_key, "force-duplicate-key", bool, gettext_noop("force genkey to not error out when the named key " "already exists")) @@ -538,17 +537,9 @@ SIMPLE_OPTION(set_default, "set-default/ gettext_noop("use the current netsync arguments and options " "as the future default")) -GOPT(ticker, "ticker", std::string, , +OPTSET_REL(globals, ticker) +SIMPLE_INITIALIZED_OPTION(ticker, "ticker", enum_string, "count,dot,none", gettext_noop("set ticker style (count|dot|none)")) -#ifdef option_bodies -{ - ticker = arg; - if (ticker != "none" && - ticker != "dot" && - ticker != "count") - throw bad_arg_internal(F("argument must be 'none', 'dot', or 'count'").str()); -} -#endif SIMPLE_OPTION(from, "from/clear-from", args_vector, gettext_noop("revision(s) to start logging at")) @@ -626,17 +617,8 @@ SIMPLE_OPTION(branches_file, "branches-f SIMPLE_OPTION(branches_file, "branches-file", system_path, gettext_noop("file mapping branch names from original to new values ")) -OPT(refs, "refs", std::set, , - gettext_noop("include git refs for 'revs', 'roots' or 'leaves'")) -#ifdef option_bodies -{ - if (arg == "revs" || arg == "roots" || arg == "leaves") - refs.insert(arg); - else - throw bad_arg_internal - (F("git ref type must be 'revs', 'roots', or 'leaves'").str()); -} -#endif +SIMPLE_INITIALIZED_OPTION(refs, "refs", enum_string_set, "revs,roots,leaves", + gettext_noop("include git refs for 'revs', 'roots' or 'leaves'")) SIMPLE_OPTION(log_revids, "log-revids/no-log-revids", bool, gettext_noop("include revision ids in commit logs"))