TEST(ProgramOptions, ParseErrors)
{
  ProgramOptions po;
  ProgramOptions::Option& help = po.add("help").mnemonic('?');
  ProgramOptions::Option& input = po.add("input").mnemonic('i').requiresValue("INPUT");
  ProgramOptions::Option& output = po.add("output").mnemonic('o').requiresValue("OUTPUT");

  const char* argv1[] = { "program.exe", "--input" };
  EXPECT_THROW(po.parse(2, argv1), ProgramOptionNeedsValue);

  const char* argv2[] = { "program.exe", "-i" };
  EXPECT_THROW(po.parse(2, argv2), ProgramOptionNeedsValue);

  const char* argv3[] = { "program.exe", "--test" };
  EXPECT_THROW(po.parse(2, argv3), InvalidProgramOption);

  const char* argv4[] = { "program.exe", "-?a" };
  po.reset();
  EXPECT_FALSE(help.enabled());
  EXPECT_THROW(po.parse(2, argv4), InvalidProgramOption);
  EXPECT_TRUE(help.enabled());  // -? is parsed anyway, -a is the invalid option

  const char* argv5[] = { "program.exe", "-io", "input-and-output.txt" };
  po.reset();
  EXPECT_THROW(po.parse(2, argv5), ProgramOptionNeedsValue);
  po.reset();
  EXPECT_THROW(po.parse(3, argv5), InvalidProgramOptionsCombination);
  EXPECT_TRUE(input.enabled());
  EXPECT_TRUE(output.enabled());
  EXPECT_EQ("input-and-output.txt", input.value());
  EXPECT_EQ("", output.value());
}
TEST(ProgramOptions, Parse)
{
  ProgramOptions po;
  ProgramOptions::Option& help = po.add("help").mnemonic('?');
  ProgramOptions::Option& input = po.add("input").mnemonic('i').requiresValue("INPUT");
  ProgramOptions::Option& output = po.add("output").mnemonic('o').requiresValue("OUTPUT");

  const char* argv1[] = { "program.exe", "-?" };
  po.parse(2, argv1);
  EXPECT_TRUE(help.enabled());

  const char* argv2[] = { "program.exe", "--help" };
  po.reset();
  po.parse(2, argv2);
  EXPECT_TRUE(help.enabled());

  const char* argv3[] = { "program.exe", "--input", "hello.cpp", "--output", "hello.exe" };
  po.reset();
  po.parse(5, argv3);
  EXPECT_FALSE(help.enabled());
  EXPECT_TRUE(input.enabled());
  EXPECT_TRUE(output.enabled());
  EXPECT_EQ("hello.cpp", input.value());
  EXPECT_EQ("hello.exe", output.value());

  const char* argv4[] = { "program.exe", "--input=hi.c", "--output=out.exe" };
  po.reset();
  po.parse(3, argv4);
  EXPECT_FALSE(help.enabled());
  EXPECT_TRUE(input.enabled());
  EXPECT_TRUE(output.enabled());
  EXPECT_EQ("hi.c", input.value());
  EXPECT_EQ("out.exe", output.value());

  const char* argv5[] = { "program.exe", "-?i", "input.md", "-o", "output.html", "extra-file.txt" };
  po.reset();
  po.parse(6, argv5);
  EXPECT_TRUE(help.enabled());
  EXPECT_TRUE(input.enabled());
  EXPECT_TRUE(output.enabled());
  EXPECT_EQ("input.md", input.value());
  EXPECT_EQ("output.html", output.value());
  ASSERT_EQ(1, po.values().size());
  EXPECT_EQ("extra-file.txt", po.values()[0]);

  const char* argv6[] = { "program.exe", "value1", "value2", "-o", "output", "value3", "--input=input", "value4" };
  po.reset();
  po.parse(8, argv6);
  ASSERT_EQ(4, po.values().size());
  EXPECT_EQ("value1", po.values()[0]);
  EXPECT_EQ("value2", po.values()[1]);
  EXPECT_EQ("value3", po.values()[2]);
  EXPECT_EQ("value4", po.values()[3]);
}
TEST(ProgramOptions, Reset)
{
  ProgramOptions po;
  ProgramOptions::Option& help = po.add("help");
  ProgramOptions::Option& file = po.add("file").requiresValue("FILE");
  EXPECT_FALSE(help.enabled());
  EXPECT_FALSE(file.enabled());
  EXPECT_EQ("", file.value());

  const char* argv[] = { "program.exe", "--help", "--file=readme.txt" };
  po.parse(3, argv);
  EXPECT_TRUE(help.enabled());
  EXPECT_TRUE(file.enabled());
  EXPECT_EQ("readme.txt", file.value());

  po.reset();
  EXPECT_FALSE(help.enabled());
  EXPECT_FALSE(file.enabled());
  EXPECT_EQ("", file.value());
}
Example #4
0
static void ParseProgramOptions (int argc, char* argv[]) {
  string level = "info";

  ProgramOptionsDescription description("STANDARD options");

  ProgramOptionsDescription hidden("HIDDEN options");

  hidden
    ("colors", "activate color support")
    ("no-pretty-print", "disable pretty printting")          
    ("auto-complete", "enable auto completion, use no-auto-complete to disable")
  ;

  description
    ("help,h", "help message")
    ("quite,s", "no banner")
    ("log.level,l", &level,  "log level")
    ("server", &ServerAddressPort, "server address and port")
    ("startup.directory", &StartupPath, "startup paths containing the Ruby files; multiple directories can be separated by cola")
    ("startup.modules-path", &StartupModules, "one or more directories separated by cola")
    ("pager", &OutputPager, "output pager")
    ("use-pager", "use pager")
    ("pretty-print", "pretty print values")          
    ("no-colors", "deactivate color support")
    ("no-auto-complete", "disable auto completion")
    // ("unit-tests", &UnitTests, "do not start as shell, run unit tests instead")
    (hidden, true)
  ;

  ProgramOptions options;

  if (! options.parse(description, argc, argv)) {
    cerr << options.lastError() << "\n";
    exit(EXIT_FAILURE);
  }

  // check for help
  set<string> help = options.needHelp("help");

  if (! help.empty()) {
    cout << description.usage(help) << endl;
    exit(EXIT_SUCCESS);
  }

  // set the logging
  TRI_SetLogLevelLogging(level.c_str());
  TRI_CreateLogAppenderFile("-");

  // set colors
  if (options.has("colors")) {
    NoColors = false;
  }

  if (options.has("no-colors")) {
    NoColors = true;
  }

  if (options.has("auto-complete")) {
    NoAutoComplete = false;
  }

  if (options.has("no-auto-complete")) {
    NoAutoComplete = true;
  }

  if (options.has("pretty-print")) {
    PrettyPrint = true;
  }

  if (options.has("no-pretty-print")) {
    PrettyPrint = false;
  }

  if (options.has("use-pager")) {
    UsePager = true;
  }

  if (options.has("quite")) {
    Quite = true;
  }
}
Example #5
0
int main(int argc, const char* argv[])
{
    ProgramOptions  opts;
    if( opts.parse(argc, argv) ) {
        return 1;
    }

    {
        Debug_DisablePhase("Load Repository");
        Debug_DisablePhase("Load Root");
        Debug_DisablePhase("Load Dependencies");
        Debug_DisablePhase("Enumerate Build");
        Debug_DisablePhase("Run Build");

        if( const char* e = getenv("MINICARGO_DEBUG") )
        {
            while( *e )
            {
                const char* colon = ::std::strchr(e, ':');
                size_t len = colon ? colon - e : ::std::strlen(e);

                Debug_EnablePhase(::std::string(e, len).c_str());

                if( colon )
                    e = colon + 1;
                else
                    e = e + len;
            }
        }
    }

    try
    {
        Debug_SetPhase("Load Repository");
        // Load package database
        Repository repo;
        // TODO: load repository from a local cache
        if( opts.vendor_dir )
        {
            repo.load_vendored(opts.vendor_dir);
        }

        auto bs_override_dir = opts.override_directory ? ::helpers::path(opts.override_directory) : ::helpers::path();

        // 1. Load the Cargo.toml file from the passed directory
        Debug_SetPhase("Load Root");
        auto dir = ::helpers::path(opts.directory ? opts.directory : ".");
        auto m = PackageManifest::load_from_toml( dir / "Cargo.toml" );

        // 2. Load all dependencies
        Debug_SetPhase("Load Dependencies");
        m.load_dependencies(repo, !bs_override_dir.is_valid());

        // 3. Build dependency tree and build program.
        BuildOptions    build_opts;
        build_opts.build_script_overrides = ::std::move(bs_override_dir);
        build_opts.output_dir = opts.output_directory ? ::helpers::path(opts.output_directory) : ::helpers::path("output");
        build_opts.lib_search_dirs.reserve(opts.lib_search_dirs.size());
        build_opts.emit_mmir = opts.emit_mmir;
        build_opts.target_name = opts.target;
        for(const auto* d : opts.lib_search_dirs)
            build_opts.lib_search_dirs.push_back( ::helpers::path(d) );
        Debug_SetPhase("Enumerate Build");
        auto build_list = BuildList(m, build_opts);
        Debug_SetPhase("Run Build");
        if( !build_list.build(::std::move(build_opts), opts.build_jobs) )
        {
            ::std::cerr << "BUILD FAILED" << ::std::endl;
            if(opts.pause_before_quit) {
                ::std::cout << "Press enter to exit..." << ::std::endl;
                ::std::cin.get();
            }
            return 1;
        }
    }
    catch(const ::std::exception& e)
    {
        ::std::cerr << "EXCEPTION: " << e.what() << ::std::endl;
        if(opts.pause_before_quit) {
            ::std::cout << "Press enter to exit..." << ::std::endl;
            ::std::cin.get();
        }
        return 1;
    }

    if(opts.pause_before_quit) {
        ::std::cout << "Press enter to exit..." << ::std::endl;
        ::std::cin.get();
    }
    return 0;
}
Example #6
0
void ArangoClient::parse (ProgramOptions& options,
                          ProgramOptionsDescription& description,
                          string const& example,
                          int argc,
                          char* argv[],
                          string const& initFilename) {
  // if options are invalid, exit directly
  if (! options.parse(description, argc, argv)) {
    LOG_FATAL_AND_EXIT("%s", options.lastError().c_str());
  }

  // setup the logging
  TRI_SetLogLevelLogging(_logLevel.c_str());
  TRI_CreateLogAppenderFile("-", 0, TRI_LOG_SEVERITY_UNKNOWN, false);
  TRI_SetLineNumberLogging(false);
  TRI_SetThreadIdentifierLogging(false);

  // parse config file
  string configFile = "";
  bool allowLocal = false;

  if (! _configFile.empty()) {
    if (StringUtils::tolower(_configFile) == string("none")) {
      LOG_DEBUG("using no init file at all");
    }
    else {
      configFile = _configFile;
    }
  }

  else {
    char* d = TRI_LocateConfigDirectory();

    if (d != 0) {
      string sysDir = string(d) + initFilename;
      TRI_FreeString(TRI_CORE_MEM_ZONE, d);

      if (FileUtils::exists(sysDir)) {
        configFile = sysDir;
        allowLocal = true;
      }
      else {
        LOG_DEBUG("no system init file '%s'", sysDir.c_str());
      }
    }
  }

  if (! configFile.empty()) {
    if (allowLocal) {
      string localConfigFile = configFile + ".local";

      if (FileUtils::exists(localConfigFile)) {
        LOG_DEBUG("using init override file '%s'", localConfigFile.c_str());

        if (! options.parse(description, localConfigFile)) {
          LOG_FATAL_AND_EXIT("cannot parse config file '%s': %s", localConfigFile.c_str(), options.lastError().c_str());
        }
      }
    }

    LOG_DEBUG("using init file '%s'", configFile.c_str());

    if (! options.parse(description, configFile)) {
      LOG_FATAL_AND_EXIT("cannot parse config file '%s': %s", configFile.c_str(), options.lastError().c_str());
    }
  }

  // configuration is parsed and valid if we got to this point
  
  // check for --help
  set<string> help = options.needHelp("help");

  if (! help.empty()) {
    if (! example.empty()) {
      cout << "USAGE: " << argv[0] << " " << example << endl << endl;
    }
    cout << description.usage(help) << endl;

    // --help always returns success
    TRI_EXIT_FUNCTION(EXIT_SUCCESS, NULL);
  }


  // set temp path
  if (options.has("temp-path")) {
    TRI_SetUserTempPath((char*) _tempPath.c_str());
  }

  if (options.has("server.username")) {
    // if a username is specified explicitly, assume authentication is desired
    _disableAuthentication = false;
  }

  // check if have a password
  _hasPassword = options.has("server.password") 
              || _disableAuthentication
              || options.has("jslint") 
              || options.has("javascript.unit-tests");

  // set colors
  if (options.has("colors")) {
    _noColors = false;
  }

  if (options.has("no-colors")) {
    _noColors = true;
  }

  // set auto-completion
  if (options.has("auto-complete")) {
    _noAutoComplete = false;
  }

  if (options.has("no-auto-complete")) {
    _noAutoComplete = true;
  }

  // set pretty print
  if (options.has("pretty-print")) {
    _prettyPrint = true;
  }

  if (options.has("no-pretty-print")) {
    _prettyPrint = false;
  }

  // set pager
  if (options.has("use-pager")) {
    _usePager = true;
  }

  // set quiet
  if (options.has("quiet")) {
    _quiet = true;
  }

  // .............................................................................
  // server options
  // .............................................................................

  if (_serverOptions) {

    // check connection args
    if (_connectTimeout <= 0) {
      LOG_FATAL_AND_EXIT("invalid value for --server.connect-timeout, must be positive");
    }

    if (_requestTimeout <= 0) {
      LOG_FATAL_AND_EXIT("invalid value for --server.request-timeout, must be positive");
    }

    // must specify a user name
    if (_username.size() == 0) {
      LOG_FATAL_AND_EXIT("no value specified for --server.username");
    }

    // no password given on command-line
    if (! _hasPassword) {
      usleep(10 * 1000);
      printContinuous("Please specify a password: "******"");
    }
  }
}
Example #7
0
void ArangoClient::parse (ProgramOptions& options,
                          ProgramOptionsDescription& description,
                          int argc,
                          char* argv[],
                          string const& initFilename) {
  if (! options.parse(description, argc, argv)) {
    LOGGER_FATAL_AND_EXIT(options.lastError());
  }

  // check for help
  set<string> help = options.needHelp("help");

  if (! help.empty()) {
    cout << description.usage(help) << endl;
    TRI_EXIT_FUNCTION(EXIT_SUCCESS, NULL);
  }

  // setup the logging
  TRI_SetLogLevelLogging(_logLevel.c_str());
  TRI_CreateLogAppenderFile("-", 0, TRI_LOG_SEVERITY_UNKNOWN, false);
  TRI_SetLineNumberLogging(false);
  TRI_SetThreadIdentifierLogging(false);

  // parse config file
  string configFile = "";

  if (! _configFile.empty()) {
    if (StringUtils::tolower(_configFile) == string("none")) {
      LOGGER_DEBUG("using no init file at all");
    }
    else {
      configFile = _configFile;
    }
  }


#ifdef _SYSCONFDIR_
  else {
    // use packaged config file from etc/relative
    string sysDir = string(_SYSCONFDIR_);
    string systemConfigFile = initFilename;

    if (! sysDir.empty()) {
      if (sysDir[sysDir.size() - 1] != TRI_DIR_SEPARATOR_CHAR) {
        sysDir += TRI_DIR_SEPARATOR_CHAR + systemConfigFile;
      }
      else {
        sysDir += systemConfigFile;
      }

      if (FileUtils::exists(sysDir)) {
        configFile = sysDir;
      }
      else {
        LOGGER_DEBUG("no system init file '" << sysDir << "'");
      }
    }
  }
#endif

  if (! configFile.empty()) {
    LOGGER_DEBUG("using init file '" << configFile << "'");

    if (! options.parse(description, configFile)) {
      LOGGER_FATAL_AND_EXIT("cannot parse config file '" << configFile << "': " << options.lastError());
    }
  }

  // set temp path
  if (options.has("temp-path")) {
    TRI_SetUserTempPath((char*) _tempPath.c_str());
  }

  // check if have a password
  _hasPassword = options.has("server.password") 
              || _disableAuthentication
              || options.has("jslint") 
              || options.has("javascript.unit-tests");

  // set colors
  if (options.has("colors")) {
    _noColors = false;
  }

  if (options.has("no-colors")) {
    _noColors = true;
  }

  // set auto-completion
  if (options.has("auto-complete")) {
    _noAutoComplete = false;
  }

  if (options.has("no-auto-complete")) {
    _noAutoComplete = true;
  }

  // set pretty print
  if (options.has("pretty-print")) {
    _prettyPrint = true;
  }

  if (options.has("no-pretty-print")) {
    _prettyPrint = false;
  }

  // set pager
  if (options.has("use-pager")) {
    _usePager = true;
  }

  // set quiet
  if (options.has("quiet")) {
    _quiet = true;
  }

  // .............................................................................
  // server options
  // .............................................................................

  if (_serverOptions) {

    // check connection args
    if (_connectTimeout <= 0) {
      LOGGER_FATAL_AND_EXIT("invalid value for --server.connect-timeout, must be positive");
    }

    if (_requestTimeout <= 0) {
      LOGGER_FATAL_AND_EXIT("invalid value for --server.request-timeout, must be positive");
    }

    // must specify a user name
    if (_username.size() == 0) {
      LOGGER_FATAL_AND_EXIT("no value specified for --server.username");
    }

    // no password given on command-line
    if (! _hasPassword) {
      usleep(10 * 1000);
      printContinuous("Please specify a password: "******"");
    }
  }
}
Example #8
0
void ArangoClient::parse (ProgramOptions& options,
                          ProgramOptionsDescription& description, 
                          int argc,
                          char* argv[],
                          string const& initFilename) {
  if (! options.parse(description, argc, argv)) {
    cerr << options.lastError() << "\n";
    exit(EXIT_FAILURE);
  }

  // check for help
  set<string> help = options.needHelp("help");

  if (! help.empty()) {
    cout << description.usage(help) << endl;
    exit(EXIT_SUCCESS);
  }

  // setup the logging
  TRI_SetLogLevelLogging(_logLevel.c_str());
  TRI_CreateLogAppenderFile("-");
  TRI_SetLineNumberLogging(false);
  TRI_SetThreadIdentifierLogging(false);

  // parse config file
  string configFile = "";

  if (! _configFile.empty()) {
    if (StringUtils::tolower(_configFile) == string("none")) {
      LOGGER_INFO << "using no init file at all";
    }
    else {
      configFile = _configFile;
    }
  }

#ifdef _SYSCONFDIR_

  else {
    string sysDir = string(_SYSCONFDIR_);
    string systemConfigFile = initFilename;

    if (! sysDir.empty()) {
      if (sysDir[sysDir.size() - 1] != '/') {
        sysDir += "/" + systemConfigFile;
      }
      else {
        sysDir += systemConfigFile;
      }

      if (FileUtils::exists(sysDir)) {
        configFile = sysDir;
      }
      else {
        LOGGER_DEBUG << "no system init file '" << sysDir << "'";
      }
    }
  }
  
#endif

  if (! configFile.empty()) {
    LOGGER_DEBUG << "using init file '" << configFile << "'";

    if (! options.parse(description, configFile)) {
      cout << "cannot parse config file '" << configFile << "': " << options.lastError() << endl;
      exit(EXIT_FAILURE);
    }
  }

  // check if have a password
  _hasPassword = options.has("server.password") || options.has("server.disable-authentication");

  // set colors
  if (options.has("colors")) {
    _noColors = false;
  }

  if (options.has("no-colors")) {
    _noColors = true;
  }

  // set auto-completion
  if (options.has("auto-complete")) {
    _noAutoComplete = false;
  }

  if (options.has("no-auto-complete")) {
    _noAutoComplete = true;
  }

  // set pretty print
  if (options.has("pretty-print")) {
    _prettyPrint = true;
  }

  if (options.has("no-pretty-print")) {
    _prettyPrint = false;
  }

  // set pager
  if (options.has("use-pager")) {
    _usePager = true;
  }

  // set quiet
  if (options.has("quiet")) {
    _quiet = true;
  }

  // .............................................................................
  // server options
  // .............................................................................

  if (_serverOptions) {

    // check connection args
    if (_connectTimeout <= 0) {
      cerr << "invalid value for --server.connect-timeout, must be positive" << endl;
      exit(EXIT_FAILURE);
    }

    if (_requestTimeout <= 0) {
      cerr << "invalid value for --server.request-timeout, must be positive" << endl;
      exit(EXIT_FAILURE);
    }
  
    // must specify a user name
    if (_username.size() == 0) {
      cerr << "no value specified for --server.username" << endl;
      exit(EXIT_FAILURE);
    }

    // no password given on command-line
    if (! _hasPassword) {
      cout << "Please specify a password: " << flush;

      // now prompt for it
#ifdef TRI_HAVE_TERMIOS_H
      TRI_SetStdinVisibility(false);
      getline(cin, _password);

      TRI_SetStdinVisibility(true);
#else
      getline(cin, _password);
#endif
    }
  }
}