source: trunk/bin/Parameter.cc @ 809

Last change on this file since 809 was 795, checked in by Peter Johansson, 12 years ago

refs #388

Create a sub-directory 'lib/yat' in which files from yat are
placed. The files may be updated via 'make fetch', see file README for
more details on how to change which files are updated/copied through
this mechanism.

The reason we do not use subversion's external mechanism is that we
don't want the files to be synchronised with yat automatically. We
want the update to be moderated by some developer.

I chose to fetch files using the svn client rather than wget because
the svn allows us to get an Id string with information from the yat
repository. 'wget' would just download the file as it appears on the
server that is the string is not expanded.

The file 'config_public.h' is created by configure just as in
yat. This implies that automake adds $(top_builddir)/lib/yat to the
include path so unless in a VPATH build $(top_srcdir)/lib/yat is in
the include path. As we have already added $(top_srcdir)/lib to the
include path, and there are both a lib/utility.h and a
lib/yat/utility.h it is not obvious which file is included when having
'include "utility.h"'. For this reason, when being in bin/ and test/
it is needed to include "../lib/utility.h" rather than "utility.h"
when we want to include 'lib/utility.h'.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.5 KB
Line 
1// $Id: Parameter.cc 795 2009-06-30 03:57:27Z peter $
2
3/*
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
7
8  svndigest is free software; you can redistribute it and/or modify it
9  under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 3 of the License, or
11  (at your option) any later version.
12
13  svndigest is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  General Public License for more details.
17
18  You should have received a copy of the GNU General Public License
19  along with svndigest. If not, see <http://www.gnu.org/licenses/>.
20*/
21
22#include "Parameter.h"
23
24#include "OptionVersion.h"
25#include "../lib/utility.h" // to avoid inclusion of yat file
26
27#include "yat/ColumnStream.h"
28#include "yat/Exception.h"
29#include "yat/OptionArg.h"
30#include "yat/OptionHelp.h"
31#include "yat/OptionSwitch.h"
32
33#include <config.h> // this header file is created by configure
34
35#include <cassert>
36#include <cerrno>
37#include <cstddef>
38#include <cstring>
39#include <fstream>
40#include <iostream>
41#include <sstream>
42#include <stdexcept>
43#include <string>
44#include <sys/stat.h>
45
46namespace theplu {
47namespace svndigest {
48
49  Parameter::Parameter( int argc, char *argv[])
50    : cmd_(
51     "Mandatory arguments to long options are mandatory for short options too.") 
52  {
53    init();
54    try {
55      cmd_.parse(argc, argv);
56    }
57    catch (yat::utility::cmd_error& e) {
58      std::cerr << e.what() << std::endl;
59      exit (-1);
60    }
61
62    // set default values
63    if (!root_->present())
64      root_->value(".");
65
66    if (!target_->present())
67      target_->value(".");
68
69    if (!config_file_->present())
70      config_file_->value(concatenate_path(root_->value(),".svndigest/config"));
71
72    // analyse arguments
73    analyse();
74  }
75
76
77  Parameter::~Parameter(void)
78  {
79    delete config_file_;
80    delete copyright_;
81    delete force_;
82    delete generate_config_;
83    delete help_;
84    delete ignore_cache_;
85    delete report_;
86    delete revisions_;
87    delete root_;
88    delete target_;
89    delete verbose_;
90    delete version_;
91  }
92
93
94  void Parameter::analyse(void)
95  {
96    std::string save_wd = pwd();
97
98    // check root but not if -g option given
99    if (!generate_config()) {
100      check_existence(root_->value());
101      check_readable(root_->value());
102      if (chdir(root_->value().c_str())) {
103        std::stringstream ss;
104        ss << "svndigest: cannot read `" << root_->value() << "': " 
105           << strerror(errno);
106        throw yat::utility::cmd_error(ss.str());
107      }
108      root_->value(pwd());
109      chdir(save_wd.c_str());
110
111      // check target (only if we write report)
112      if (report()) {
113        check_existence(target_->value());
114        check_readable(target_->value());
115        std::string base_root = file_name(root_->value());
116        std::string path = concatenate_path(target_->value(),base_root); 
117        if (access_rights(target_->value().c_str(), "w")) {
118          std::stringstream ss;
119          ss << "svndigest: cannot create directory `" << path
120             << "': " << strerror(errno);
121          throw yat::utility::cmd_error(ss.str());
122        }
123        if (node_exist(path) && !force()) {
124          std::stringstream ss;
125          ss << "svndigest: cannot create directory `" << path << "' "
126             << strerror(EEXIST);
127          throw yat::utility::cmd_error(ss.str());
128        }
129        if (chdir(target_->value().c_str())) {
130          std::stringstream ss;
131          ss << "svndigest: cannot read `" << target_->value() << "': " 
132             << strerror(errno);
133          throw yat::utility::cmd_error(ss.str());
134        }
135        target_->value(pwd());
136        chdir(save_wd.c_str());
137      }
138    }
139
140    // check config file
141    struct stat nodestat;
142    // true also if there is a broken symlink named...
143    bool config_exists = !lstat(config_file_->value().c_str(), &nodestat);
144    // the latter case in order to catch broken symlink
145    if (config_file_->present() || config_exists)
146      // throws if file does not exists
147      check_existence(config_file_->value());
148    if (config_exists) {
149      // throws if file is not readable
150      check_readable(config_file_->value());
151      stat(config_file_->value().c_str(), &nodestat);
152      if (!S_ISREG(nodestat.st_mode)) {
153        std::stringstream ss;
154        ss << "svndigest: `" << config_file_->value() 
155           << "' is not a regular file";
156        throw yat::utility::cmd_error(ss.str());
157      }
158    }
159  }
160
161
162  void Parameter::check_existence(std::string path) const
163  {
164    if (node_exist(path))
165      return;
166    std::stringstream ss;
167    ss << "svndigest: cannot stat `" << path << "': " << strerror(errno);
168    throw yat::utility::cmd_error(ss.str());
169  }
170
171 
172  void Parameter::check_readable(std::string path) const
173  {
174    if (!access_rights(path, "r"))
175      return;
176    std::stringstream ss;
177    ss << "svndigest: cannot open `" << path << "': " << strerror(errno);
178    throw yat::utility::cmd_error(ss.str());
179  }
180 
181
182  std::string Parameter::config_file(void) const
183  {
184    return config_file_->value();
185  }
186
187
188  bool Parameter::copyright(void) const
189  {
190    return copyright_->present();
191  }
192
193
194  bool Parameter::force(void) const
195  {
196    return force_->present();
197  }
198
199
200  bool Parameter::generate_config(void) const
201  {
202    return generate_config_->present();
203  }
204
205
206  bool Parameter::ignore_cache(void) const
207  {
208    return ignore_cache_->present();
209  }
210
211
212  void Parameter::init(void)
213  {
214    // don't use argv[0] because user may rename the binary
215    cmd_.program_name() = PACKAGE_NAME;
216    config_file_=new yat::utility::OptionArg<std::string>(cmd_, "config-file",
217                                "configuration file [<ROOT>/.svndigest/config]");
218    config_file_->print_arg("=FILE");
219    std::stringstream ss;
220    copyright_ = new yat::utility::OptionSwitch(cmd_, "copyright", 
221                                  "update copyright statement");
222
223    ss << "if sub-directory named <ROOT> exists in target directory, remove "
224       << "sub-directory before writing results";
225    force_ = new yat::utility::OptionSwitch(cmd_, "f,force", ss.str());
226    ss.str("");
227
228    help_ = new yat::utility::OptionHelp(cmd_);
229    generate_config_ = 
230      new yat::utility::OptionSwitch(cmd_, "g,generate-config", 
231                       "write configuration file to standard output");
232
233    ss.str("");
234    ss << "ignore cache files and analyze everything from repository";
235    ignore_cache_ = new yat::utility::OptionSwitch(cmd_, "ignore-cache", ss.str());
236         
237    report_ = new yat::utility::OptionSwitch(cmd_, "report", "create no HTML report", true);
238
239    ss.str("");
240    ss << "use revision numbers as time scale instead of dates [dates]";
241    revisions_ = new yat::utility::OptionSwitch(cmd_, "revisions", ss.str());
242
243    root_=
244      new yat::utility::OptionArg<std::string>(cmd_, "r,root", 
245                     "svn controlled directory to perform statistics on [.]");
246    root_->print_arg("=ROOT");
247    target_ = new yat::utility::OptionArg<std::string>(cmd_, "t,target", 
248                                         "output directory [.]");
249    target_->print_arg("=TARGET");
250   
251    verbose_ = new yat::utility::OptionSwitch(cmd_, "v,verbose", "explain what is being done");
252    version_ = new OptionVersion(cmd_, "version", 
253                                 "print version information and exit", verbose_);
254
255    ss.str("");
256    ss << "Report bugs to " << PACKAGE_BUGREPORT << ".\n";
257    help_->post_arguments() = ss.str();
258    help_->synopsis() = 
259      "Generate statistical report for a subversion repository\n";
260  }
261
262
263  bool Parameter::report(void) const
264  {
265    return report_->value();
266  }
267
268
269  bool Parameter::revisions(void) const
270  {
271    return revisions_->present();
272  }
273
274
275  std::string Parameter::root(void) const
276  {
277    return root_->value();
278  }
279
280 
281  std::string Parameter::targetdir(void) const
282  {
283    return target_->value();
284  }
285
286 
287  bool Parameter::verbose(void) const
288  {
289    return verbose_->present();
290  }
291
292
293}} // of namespace svndigest and namespace theplu
Note: See TracBrowser for help on using the repository browser.