Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-10-25 09:32:36

0001 #include <cstdlib>
0002 
0003 #include <iostream>
0004 #include <iomanip>
0005 #include "boost/filesystem.hpp"
0006 #include "boost/version.hpp"
0007 #include "boost/program_options.hpp"
0008 
0009 #include "Options.h"
0010 
0011 using namespace std;
0012 namespace fs = boost::filesystem;
0013 namespace po = boost::program_options;  // used to read the options from command line
0014 
0015 namespace AllInOneConfig {
0016 
0017   void check_file(string file) {
0018     // check that the config file exists
0019     if (!fs::exists(file)) {
0020       cerr << "Didn't find configuration file " << file << '\n';
0021       exit(EXIT_FAILURE);
0022     }
0023   }
0024 
0025   void set_verbose(bool flag) {
0026     if (!flag)
0027       cout.setstate(ios_base::failbit);
0028   }
0029 
0030   void set_silent(bool flag) {
0031     if (flag)
0032       cerr.setstate(ios_base::failbit);
0033   }
0034 
0035   ////////////////////////////////////////////////////////////////////////////////
0036   /// Constructor for PO:
0037   /// - contains a parser for the help itself
0038   /// - contains a parser for the options (unless help was displayed)
0039   /// - and contains a hidden/position option to get the JSON config file
0040   Options::Options(bool getter) : help{"Helper"}, desc{"Options"}, hide{"Hidden"} {
0041     // define all options
0042     help.add_options()("help,h", "Help screen")("example,e", "Print example of config in JSON format")(
0043         "tutorial,t", "Explain how to use the command");
0044 
0045     // then (except for getJSON) the running options
0046     if (!getter)
0047       desc.add_options()(
0048           "dry,d", po::bool_switch(&dry)->default_value(false), "Set up everything, but don't run anything")(
0049           "verbose,v", po::bool_switch()->default_value(false)->notifier(set_verbose), "Enable standard output stream")(
0050           "silent,s", po::bool_switch()->default_value(false)->notifier(set_silent), "Disable standard error stream");
0051 
0052     // and finally / most importantly, the config file as apositional argument
0053     hide.add_options()("config,c", po::value<string>(&config)->required()->notifier(check_file), "JSON config file");
0054     pos_hide.add("config", 1);  // 1 means one (positional) argument
0055     if (getter) {
0056       // in case of getIMFO, adding a second positional argument for the key
0057       hide.add_options()("key,k", po::value<string>(&key)->required(), "key");
0058       pos_hide.add("key", 1);
0059     }
0060   }
0061 
0062   void Options::helper(int argc, char* argv[]) {
0063     po::options_description options;
0064     options.add(help).add(desc);
0065 
0066     po::command_line_parser parser_helper{argc, argv};
0067     parser_helper
0068         .options(help)          // don't parse required options before parsing help
0069         .allow_unregistered();  // ignore unregistered options,
0070 
0071     // defines actions
0072     po::variables_map vm;
0073     po::store(parser_helper.run(), vm);
0074     po::notify(vm);  // necessary for config to be given the value from the cmd line
0075 
0076     if (vm.count("help")) {
0077       fs::path executable = argv[0];
0078       cout << "Basic syntax:\n  " << executable.filename().string() << " config.JSON\n"
0079            << options << '\n'
0080            << "Boost " << BOOST_LIB_VERSION << endl;
0081       exit(EXIT_SUCCESS);
0082     }
0083 
0084     if (vm.count("example")) {
0085       static const char *bold = "\e[1m", *normal = "\e[0m";
0086       cout << bold << "Example of HTC condor config:" << normal << '\n' << endl;
0087       system("cat $CMSSW_BASE/src/Alignment/OfflineValidation/bin/.default.sub");
0088       cout << '\n' << bold << "Example of JSON config (for `validateAlignment` only):" << normal << '\n' << endl;
0089       system("cat $CMSSW_BASE/src/Alignment/OfflineValidation/bin/.example.JSON");
0090       cout << '\n'
0091            << bold << "NB: " << normal
0092            << " for examples of inputs to GCPs, DMRs, etc., just make a dry run of the example" << endl;
0093       exit(EXIT_SUCCESS);
0094     }
0095     // TODO: make examples for each executables? (could be examples used in release validation...)
0096 
0097     if (vm.count("tutorial")) {
0098       cout << "   ______________________\n"
0099            << "  < Oops! not ready yet! >\n"
0100            << "   ----------------------\n"
0101            << "          \\   ^__^\n"
0102            << "           \\  (oo)\\_______\n"
0103            << "              (__)\\       )\\/\\\n"
0104            << "                  ||----w |\n"
0105            << "                  ||     ||\n"
0106            << flush;
0107       exit(EXIT_SUCCESS);
0108     }
0109   }
0110 
0111   void Options::parser(int argc, char* argv[]) {
0112     po::options_description cmd_line;
0113     cmd_line.add(desc).add(hide);
0114 
0115     po::command_line_parser parser{argc, argv};
0116     parser.options(cmd_line).positional(pos_hide);
0117 
0118     po::variables_map vm;
0119     po::store(parser.run(), vm);
0120     po::notify(vm);  // necessary for config to be given the value from the cmd line
0121   }
0122 
0123 }  // end of namespace AllInOneConfig