source: trunk/bin/Parameter.cc @ 715

Last change on this file since 715 was 715, checked in by Peter Johansson, 13 years ago

fixing ugly bug in Parameter. target dir behaved completely whacko (likely introduced in [705]).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.1 KB
Line 
1// $Id: Parameter.cc 715 2008-11-30 02:51:45Z peter $
2
3/*
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://dev.thep.lu.se/svndigest
8
9  svndigest is free software; you can redistribute it and/or modify it
10  under the terms of the GNU General Public License as published by
11  the Free Software Foundation; either version 3 of the License, or
12  (at your option) any later version.
13
14  svndigest is distributed in the hope that it will be useful, but
15  WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  General Public License for more details.
18
19  You should have received a copy of the GNU General Public License
20  along with svndigest. If not, see <http://www.gnu.org/licenses/>.
21*/
22
23#include "Parameter.h"
24
25#include "ColumnStream.h"
26#include "OptionArg.h"
27#include "OptionHelp.h"
28#include "OptionSwitch.h"
29#include "OptionVersion.h"
30#include "utility.h"
31#include <config.h> // this header file is created by configure
32
33#include <cassert>
34#include <cerrno>
35#include <cstddef>
36#include <fstream>
37#include <iostream>
38#include <sstream>
39#include <stdexcept>
40#include <string>
41#include <sys/stat.h>
42
43namespace theplu {
44namespace svndigest {
45
46  Parameter::Parameter( int argc, char *argv[])
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());
119        }
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());
125        }
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());
131        }
132        target_->value(pwd());
133        chdir(save_wd.c_str());
134      }
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());
154      }
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 
178
179  std::string Parameter::config_file(void) const
180  {
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");
247   
248    verbose_ = new OptionSwitch(cmd_, "v,verbose", "explain what is being done");
249    version_ = new OptionVersion(cmd_);
250
251    ss.str("");
252    ss << "Report bugs to " << PACKAGE_BUGREPORT << ".\n";
253    help_->post_arguments() = ss.str();
254    help_->synopsis() = 
255      "Generate statistical report for a subversion repository\n";
256  }
257
258
259  bool Parameter::report(void) const
260  {
261    return report_->value();
262  }
263
264
265  bool Parameter::revisions(void) const
266  {
267    return revisions_->present();
268  }
269
270
271  std::string Parameter::root(void) const
272  {
273    return root_->value();
274  }
275
276 
277  std::string Parameter::targetdir(void) const
278  {
279    return target_->value();
280  }
281
282 
283  bool Parameter::verbose(void) const
284  {
285    return verbose_->present();
286  }
287
288
289}} // of namespace svndigest and namespace theplu
Note: See TracBrowser for help on using the repository browser.