Ignore:
Timestamp:
Apr 9, 2009, 10:18:54 PM (12 years ago)
Author:
Jari Häkkinen
Message:

Merged trunk changes r645:782 to replacing_gnuplot branch.

Location:
branches/replacing_gnuplot
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/replacing_gnuplot

    • Property svn:ignore
      •  

        old new  
        88autom4te.cache
        99INSTALL
        10 COPYING
        1110aclocal.m4
        1211Makefile
  • branches/replacing_gnuplot/bin/Parameter.cc

    r646 r784  
    22
    33/*
    4   Copyright (C) 2006, 2007 Jari Häkkinen, Peter Johansson
    5   Copyright (C) 2008 Peter Johansson
    6 
    7   This file is part of svndigest, http://trac.thep.lu.se/svndigest
     4  Copyright (C) 2006, 2007, 2008 Jari Häkkinen, Peter Johansson
     5
     6  This file is part of svndigest, http://dev.thep.lu.se/svndigest
    87
    98  svndigest is free software; you can redistribute it and/or modify it
    109  under the terms of the GNU General Public License as published by
    11   the Free Software Foundation; either version 2 of the License, or
     10  the Free Software Foundation; either version 3 of the License, or
    1211  (at your option) any later version.
    1312
     
    1817
    1918  You should have received a copy of the GNU General Public License
    20   along with this program; if not, write to the Free Software
    21   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
    22   02111-1307, USA.
     19  along with svndigest. If not, see <http://www.gnu.org/licenses/>.
    2320*/
    2421
     
    2623
    2724#include "ColumnStream.h"
    28 #include "subversion_info.h"
     25#include "OptionArg.h"
     26#include "OptionHelp.h"
     27#include "OptionSwitch.h"
     28#include "OptionVersion.h"
    2929#include "utility.h"
    3030#include <config.h> // this header file is created by configure
    3131
     32#include <cassert>
     33#include <cerrno>
    3234#include <cstddef>
     35#include <cstring>
    3336#include <fstream>
    3437#include <iostream>
     
    4245
    4346  Parameter::Parameter( int argc, char *argv[])
    44     : config_file_(""), copyright_(false), force_(false),
    45       generate_config_(false), ignore_cache_(false), report_(true),
    46       revisions_(false), root_("."), root_node_("."), targetdir_("."),
    47       verbose_(false)
    48   {
    49     for (int i=1; i<argc; ++i) {
    50       std::stringstream ss(argv[i]);
    51       std::string myargv("");
    52       std::string value("");
    53       getline(ss, myargv, '=');
    54       getline(ss, value);
    55 
    56       if (myargv=="--config-file"){
    57         if (value.size()) {
    58           config_file_.value()= value;
     47    : cmd_(
     48     "Mandatory arguments to long options are mandatory for short options too.")
     49  {
     50    init();
     51    try {
     52      cmd_.parse(argc, argv);
     53    }
     54    catch (cmd_error& e) {
     55      std::cerr << e.what() << std::endl;
     56      exit (-1);
     57    }
     58
     59    // set default values
     60    if (!root_->present())
     61      root_->value(".");
     62
     63    if (!target_->present())
     64      target_->value(".");
     65
     66    if (!config_file_->present())
     67      config_file_->value(concatenate_path(root_->value(),".svndigest/config"));
     68
     69    // analyse arguments
     70    analyse();
     71  }
     72
     73
     74  Parameter::~Parameter(void)
     75  {
     76    delete config_file_;
     77    delete copyright_;
     78    delete force_;
     79    delete generate_config_;
     80    delete help_;
     81    delete ignore_cache_;
     82    delete report_;
     83    delete revisions_;
     84    delete root_;
     85    delete target_;
     86    delete verbose_;
     87    delete version_;
     88  }
     89
     90
     91  void Parameter::analyse(void)
     92  {
     93    std::string save_wd = pwd();
     94
     95    // check root but not if -g option given
     96    if (!generate_config()) {
     97      check_existence(root_->value());
     98      check_readable(root_->value());
     99      if (chdir(root_->value().c_str())) {
     100        std::stringstream ss;
     101        ss << "svndigest: cannot read `" << root_->value() << "': "
     102           << strerror(errno);
     103        throw cmd_error(ss.str());
     104      }
     105      root_->value(pwd());
     106      chdir(save_wd.c_str());
     107
     108      // check target (only if we write report)
     109      if (report()) {
     110        check_existence(target_->value());
     111        check_readable(target_->value());
     112        std::string base_root = file_name(root_->value());
     113        std::string path = concatenate_path(target_->value(),base_root);
     114        if (access_rights(target_->value().c_str(), "w")) {
     115          std::stringstream ss;
     116          ss << "svndigest: cannot create directory `" << path
     117             << "': " << strerror(errno);
     118          throw cmd_error(ss.str());
    59119        }
    60         else if (++i<argc){
    61           config_file_.value()= std::string(argv[i]);
     120        if (node_exist(path) && !force()) {
     121          std::stringstream ss;
     122          ss << "svndigest: cannot create directory `" << path << "' "
     123             << strerror(EEXIST);
     124          throw cmd_error(ss.str());
    62125        }
    63         else {
    64           missing_argument(myargv);
     126        if (chdir(target_->value().c_str())) {
     127          std::stringstream ss;
     128          ss << "svndigest: cannot read `" << target_->value() << "': "
     129             << strerror(errno);
     130          throw cmd_error(ss.str());
    65131        }
     132        target_->value(pwd());
     133        chdir(save_wd.c_str());
    66134      }
    67       else if (myargv=="--copyright"){
    68           copyright_.value()=true;
     135    }
     136
     137    // check config file
     138    struct stat nodestat;
     139    // true also if there is a broken symlink named...
     140    bool config_exists = !lstat(config_file_->value().c_str(), &nodestat);
     141    // the latter case in order to catch broken symlink
     142    if (config_file_->present() || config_exists)
     143      // throws if file does not exists
     144      check_existence(config_file_->value());
     145    if (config_exists) {
     146      // throws if file is not readable
     147      check_readable(config_file_->value());
     148      stat(config_file_->value().c_str(), &nodestat);
     149      if (!S_ISREG(nodestat.st_mode)) {
     150        std::stringstream ss;
     151        ss << "svndigest: `" << config_file_->value()
     152           << "' is not a regular file";
     153        throw cmd_error(ss.str());
    69154      }
    70       else if (myargv=="-f" || myargv=="--force"){
    71           force_.value()=true;
    72       }
    73       else if (myargv=="-g" || myargv=="--generate-config"){
    74           generate_config_.value()=true;
    75       }
    76       else if (myargv=="-h" || myargv=="--help"){
    77         help();
    78         exit(0);      // always exit after printing help
    79       }
    80       else if (myargv=="--ignore-cache"){
    81           ignore_cache_.value()=true;
    82       }
    83       else if (myargv=="-r" || myargv=="--root"){
    84         if (value.size()) {
    85           root_.value()= value;
    86         }
    87         else if (++i<argc){
    88           root_.value()= std::string(argv[i]);
    89         }
    90         else {
    91           missing_argument(myargv);
    92         }
    93       }
    94       else if (myargv=="--report") {
    95           report_.value()=true;
    96       }
    97       else if (myargv=="--no-report") {
    98           report_.value()=false;
    99       }
    100       else if (myargv=="--revisions") {
    101           revisions_.value()=true;
    102       }
    103       else if (myargv=="-t" || myargv=="--target"){
    104         if (value.size()) {
    105           targetdir_.value()= value;
    106         }
    107         else if (++i<argc){
    108           targetdir_.value()= std::string(argv[i]);
    109         }
    110         else {
    111           missing_argument(myargv);
    112         }
    113       }
    114       else if (myargv=="-v" || myargv=="--verbose"){
    115           verbose_.value()=true;
    116       }
    117       else if (myargv=="--version"){
    118         version();
    119         exit(0);
    120       }
    121       else if (myargv=="-vf" || myargv=="-fv"){
    122           verbose_.value()=true;
    123           force_.value()=true;
    124       }
    125       else {
    126         throw std::runtime_error("svndigest: invalid option: " + myargv +
    127                                  "\nTry `svndigest --help' for usage.");
    128       }
    129   }
    130 
    131     analyse();
    132   }
    133 
    134 
    135   void Parameter::analyse(void)
    136   {
    137     using namespace std;
    138 
    139     string workdir(pwd()); // remember current working directory (cwd).
    140 
    141     if (!node_exist(root_.value()))
    142       throw runtime_error(string("svndigest: cannot stat `" + root_.value() +
    143                                  "': no such file or directory"));
    144 
    145     if (access_rights(root_.value(), "r"))
    146       throw runtime_error(string("svndigest: cannot open `" + root_.value() +
    147                                  "' for reading: Permission denied"));
    148 
    149     // Check whether root is directory or file
    150     struct stat nodestat;
    151     stat(root_.value().c_str(), &nodestat);
    152     if (S_ISDIR(nodestat.st_mode)) {
    153       chdir(root_.value().c_str());
    154       root_node_.value() = root_.value() = pwd();
    155     }
    156     else {
    157       std::string fname = file_name(root_.value());
    158       root_.value() = directory_name(root_.value());
    159       chdir(root_.value().c_str());
    160       root_.value() = pwd();
    161       root_node_.value() = root_.value() + "/" + fname;
    162     }
    163 
    164     // need to get back to cwd if relative paths are used.
    165     if (chdir(workdir.c_str()))
    166       runtime_error(string("svndigest: Failed to access cwd: ") + workdir);
    167 
    168     // Checking that targetdir_ exists and retrieve the absolute path
    169     // to targetdir_
    170     if (report()) {
    171       if (chdir(targetdir_.value().c_str()))
    172         throw runtime_error(string("svndigest: Target directory (") +
    173                             targetdir_.value() + ") access failed.");
    174       targetdir_.value() = pwd();
    175       // Checking write permissions for targetdir_
    176       if (access_rights(targetdir_.value(),"w"))
    177         throw runtime_error(string("svndigest: No write permission on target ") +
    178                             "directory (" + targetdir_.value() +").");
    179     }
    180 
    181     // return back to cwd
    182     if (chdir(workdir.c_str()))
    183       throw runtime_error(string("svndigest: Failed to access cwd: ") + workdir);
    184 
    185   }
    186 
     155    }
     156  }
     157
     158
     159  void Parameter::check_existence(std::string path) const
     160  {
     161    if (node_exist(path))
     162      return;
     163    std::stringstream ss;
     164    ss << "svndigest: cannot stat `" << path << "': " << strerror(errno);
     165    throw cmd_error(ss.str());
     166  }
     167
     168 
     169  void Parameter::check_readable(std::string path) const
     170  {
     171    if (!access_rights(path, "r"))
     172      return;
     173    std::stringstream ss;
     174    ss << "svndigest: cannot open `" << path << "': " << strerror(errno);
     175    throw cmd_error(ss.str());
     176  }
     177 
    187178
    188179  std::string Parameter::config_file(void) const
    189180  {
    190     // not default
    191     if (!config_file_.value().empty())
    192       return config_file_.value();
     181    return config_file_->value();
     182  }
     183
     184
     185  bool Parameter::copyright(void) const
     186  {
     187    return copyright_->present();
     188  }
     189
     190
     191  bool Parameter::force(void) const
     192  {
     193    return force_->present();
     194  }
     195
     196
     197  bool Parameter::generate_config(void) const
     198  {
     199    return generate_config_->present();
     200  }
     201
     202
     203  bool Parameter::ignore_cache(void) const
     204  {
     205    return ignore_cache_->present();
     206  }
     207
     208
     209  void Parameter::init(void)
     210  {
     211    // don't use argv[0] because user may rename the binary
     212    cmd_.program_name() = PACKAGE_NAME;
     213    config_file_=new OptionArg<std::string>(cmd_, "config-file",
     214                                "configuration file [<ROOT>/.svndigest/config]");
     215    config_file_->print_arg("=FILE");
     216    std::stringstream ss;
     217    copyright_ = new OptionSwitch(cmd_, "copyright",
     218                                  "update copyright statement");
     219
     220    ss << "if sub-directory named <ROOT> exists in target directory, remove "
     221       << "sub-directory before writing results";
     222    force_ = new OptionSwitch(cmd_, "f,force", ss.str());
     223    ss.str("");
     224
     225    help_ = new OptionHelp(cmd_);
     226    generate_config_ =
     227      new OptionSwitch(cmd_, "g,generate-config",
     228                       "write configuration file to standard output");
     229
     230    ss.str("");
     231    ss << "ignore cache files and analyze everything from repository";
     232    ignore_cache_ = new OptionSwitch(cmd_, "ignore-cache", ss.str());
     233         
     234    report_ = new OptionSwitch(cmd_, "report", "create no HTML report", true);
     235
     236    ss.str("");
     237    ss << "use revision numbers as time scale instead of dates [dates]";
     238    revisions_ = new OptionSwitch(cmd_, "revisions", ss.str());
     239
     240    root_=
     241      new OptionArg<std::string>(cmd_, "r,root",
     242                     "svn controlled directory to perform statistics on [.]");
     243    root_->print_arg("=ROOT");
     244    target_ = new OptionArg<std::string>(cmd_, "t,target",
     245                                         "output directory [.]");
     246    target_->print_arg("=TARGET");
    193247   
    194     // default behaviour
    195     return root()+"/.svndigest/config";
    196   }
    197 
    198 
    199   void Parameter::help(void) const
    200   {
    201     ColumnStream cs(std::cout, 1);
    202     cs.width(0)=79;
    203     cs.margin(0)=0;
    204     ColumnStream cs2(std::cout, 2);
    205     // Widest line should fit exactly
    206     cs2.width(0)=21;
    207     cs2.width(1)=52;
    208     cs2.margin(0)=2;
    209     // Gnits standard suggest three characters gap between option and description
    210     cs2.margin(1)=3;
    211 
    212     std::cout << "Usage: svndigest [OPTION]...\n"
    213               << "\n";
    214 
    215     cs << "Generate statistical report for a subversion repository.\n";
    216 
    217     cs << "\nMandatory arguments to long options are mandatory for "
    218        << "short options too.\n";
    219 
    220     cs2  << "    --config-file=ARG\tconfiguration file "
    221          << "[<ROOT>/.svndigest/config]\n"
    222          << "    --copyright\tupdate copyright statement\n"
    223          << "-f, --force\tif sub-directory named <ROOT> exists in "
    224          << "target directory, remove sub-directory before writing results\n"
    225          << "-g, --generate-config\twrite configuration file "
    226          << "to standard output and exit\n"
    227          << "-h, --help\tdisplay this help and exit\n"
    228          << "    --ignore-cache\tignore cache files and analyze "
    229          << "everything from repository\n"
    230          << "    --no-report\tcreate no HTML report\n"
    231          << "    --revisions\tuse revision numbers as time scale "
    232          << "instead of dates [dates]\n"
    233          << "-r, --root=ROOT\tsvn controlled directory to perform "
    234          << "statistics calculation on [" << root_.default_value() << "]\n"
    235          << "-t, --target=TARGET\toutput directory ["
    236          << targetdir_.default_value() << "]\n"
    237          << "-v, --verbose\texplain what is being done\n"
    238          << "    --version\tprint version information and exit\n";
    239 
    240     std::cout << "\nReport bugs to <" << PACKAGE_BUGREPORT << ">."
    241               << std::endl;
    242   }
    243 
    244 
    245   void Parameter::missing_argument(std::string opt) const
    246   {
    247     if (opt.size()>0 && opt[0]=='-')
    248       opt = opt.substr(1);
    249     if (opt.size()>0 && opt[0]=='-')
    250       opt = opt.substr(1);
    251     std::stringstream ss;
    252     ss << "svndigest: option requires an argument -- " << opt << "\n"
    253        << "Try `svndigest --help' for usage.";
    254     throw std::runtime_error(ss.str());
    255   }
    256 
    257   void Parameter::version(bool verbose) const
    258   {
    259     ColumnStream cs(std::cout, 1);
    260     cs.width(0)=79;
    261     cs << PACKAGE_STRING << version_string() << "\n";
    262     cs << "\nCopyright (C) " << svn_year()
    263        << " Jari H\u00E4kkinen and Peter Johansson.\n"
    264        << "This is free software. You may redistribute copies of it under "
    265        << "the terms of the GNU General Public License "
    266        << "<http://www.gnu.org/licenses/gpl.html>.\n"
    267        << "There is NO WARRANTY; to the extent permitted by law.\n";
    268   }
     248    verbose_ = new OptionSwitch(cmd_, "v,verbose", "explain what is being done");
     249    version_ = new OptionVersion(cmd_, "version",
     250                                 "print version information and exit", verbose_);
     251
     252    ss.str("");
     253    ss << "Report bugs to " << PACKAGE_BUGREPORT << ".\n";
     254    help_->post_arguments() = ss.str();
     255    help_->synopsis() =
     256      "Generate statistical report for a subversion repository\n";
     257  }
     258
     259
     260  bool Parameter::report(void) const
     261  {
     262    return report_->value();
     263  }
     264
     265
     266  bool Parameter::revisions(void) const
     267  {
     268    return revisions_->present();
     269  }
     270
     271
     272  std::string Parameter::root(void) const
     273  {
     274    return root_->value();
     275  }
     276
     277 
     278  std::string Parameter::targetdir(void) const
     279  {
     280    return target_->value();
     281  }
     282
     283 
     284  bool Parameter::verbose(void) const
     285  {
     286    return verbose_->present();
     287  }
     288
    269289
    270290}} // of namespace svndigest and namespace theplu
Note: See TracChangeset for help on using the changeset viewer.