source: branches/0.9-stable/bin/Parameter.cc @ 1335

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

avoid error message: Unknwon error 0

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 5.5 KB
Line 
1// $Id: Parameter.cc 1335 2011-01-28 06:26:41Z peter $
2
3/*
4  Copyright (C) 2006, 2007, 2008 Jari Häkkinen, Peter Johansson
5  Copyright (C) 2009, 2010, 2011 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 <config.h> // this header file is created by configure
24
25#include "Parameter.h"
26
27#include "lib/OptionVersion.h"
28#include "lib/utility.h" // to avoid inclusion of yat file
29
30#include "yat/ColumnStream.h"
31#include "yat/Exception.h"
32#include "yat/OptionArg.h"
33#include "yat/OptionHelp.h"
34#include "yat/OptionSwitch.h"
35
36#include <cassert>
37#include <cerrno>
38#include <cstddef>
39#include <cstring>
40#include <fstream>
41#include <iostream>
42#include <sstream>
43#include <stdexcept>
44#include <string>
45#include <sys/stat.h>
46
47namespace theplu {
48namespace svndigest {
49
50  Parameter::Parameter(void)
51    : cmd_( std::string("Mandatory arguments to long options ") + 
52            std::string("are mandatory for short options too.")), 
53      config_file_(cmd_, "config-file", 
54                   "configuration file [<ROOT>/.svndigest/config]"),
55      generate_config_(cmd_, "g,generate-config", 
56                       "write configuration to standard output"),
57      help_(cmd_),
58      ignore_cache_(cmd_, "ignore-cache", 
59                    std::string("ignore cache files and analyze ") +
60                    std::string("everything from repository")),
61      root_(cmd_, "r,root", 
62            "svn controlled directory to perform statistics on [.]"),
63      verbose_(cmd_, "v,verbose", "explain what is being done"),
64      version_(cmd_, "version", "print version information and exit", &verbose_)
65  {
66  }
67
68
69  void Parameter::parse(int argc, char* argv[])
70  {
71    init();
72    cmd_.parse(argc, argv);
73    set_default();
74    // analyse arguments
75    analyse();
76  }
77
78
79  Parameter::~Parameter(void)
80  {
81  }
82
83
84  void Parameter::analyse(void)
85  {
86    std::string save_wd = pwd();
87
88    // check root but not if -g option given
89    if (!generate_config()) {
90      check_existence(root_.value());
91      check_readable(root_.value());
92      check_is_dir(root_.value());
93
94      chdir(root_.value());
95      root_full_ = pwd();
96      chdir(save_wd);
97
98      // take care of when root is a symlink (see ticket #477)
99      struct stat stats;
100      lstat(root_.value().c_str(), &stats);
101      if (S_ISLNK(stats.st_mode))
102        root_basename_ = file_name(root_.value());
103      else
104        root_basename_ = file_name(root_full_);
105    }
106
107    // check config file
108    struct stat nodestat;
109    // true also if there is a broken symlink named...
110    bool config_exists = !lstat(config_file_.value().c_str(), &nodestat);
111    // the latter case in order to catch broken symlink
112    if (config_file_.present() || config_exists)
113      // throws if file does not exists
114      check_existence(config_file_.value());
115    if (config_exists) {
116      // throws if file is not readable
117      check_readable(config_file_.value());
118      stat(config_file_.value().c_str(), &nodestat);
119      if (S_ISDIR(nodestat.st_mode)) {
120        std::stringstream ss;
121        ss << cmd_.program_name() << ": '" << config_file_.value() 
122           << "' is a directory";
123        throw yat::utility::cmd_error(ss.str());
124      }
125    }
126    analyse2();
127  }
128
129
130  void Parameter::check_existence(std::string path) const
131  {
132    if (node_exist(path))
133      return;
134    std::stringstream ss;
135    ss << cmd_.program_name() << ": cannot stat '" << path << "': " 
136       << strerror(errno);
137    throw yat::utility::cmd_error(ss.str());
138  }
139
140 
141  void Parameter::check_is_dir(std::string path) const
142  {
143    if (node_exist(path)) {
144      struct stat buf;
145      stat(path.c_str(), &buf);
146      if (S_ISDIR(buf.st_mode))
147        return;
148      errno = ENOTDIR;
149    }
150    std::stringstream ss;
151    assert(errno);
152    ss << cmd_.program_name() << ": '" << path << "': " 
153       << strerror(errno);
154    throw yat::utility::cmd_error(ss.str());
155  }
156
157 
158  void Parameter::check_readable(std::string path) const
159  {
160    if (!access_rights(path, "r"))
161      return;
162    std::stringstream ss;
163    ss << cmd_.program_name() << ": cannot open '" << path << "': " 
164       << strerror(errno);
165    throw yat::utility::cmd_error(ss.str());
166  }
167 
168
169  std::string Parameter::config_file(void) const
170  {
171    return config_file_.value();
172  }
173
174
175  bool Parameter::generate_config(void) const
176  {
177    return generate_config_.present();
178  }
179
180
181  bool Parameter::ignore_cache(void) const
182  {
183    return ignore_cache_.present();
184  }
185
186
187  void Parameter::init(void)
188  {
189    // we like the options sorted alphabetically
190    cmd_.sort();
191    config_file_.print_arg("=FILE");
192    root_.print_arg("=ROOT");
193    std::stringstream ss;
194    ss << "Report bugs to " << PACKAGE_BUGREPORT << ".\n"
195       << PACKAGE << " home page: <" << PACKAGE_URL << ">.\n";
196    help_.post_arguments() = ss.str();
197    init2();
198  }
199
200
201  std::string Parameter::root(void) const
202  {
203    return root_full_;
204  }
205
206
207  const std::string& Parameter::root_basename(void) const
208  {
209    assert(root_basename_.size());
210    return root_basename_;
211  }
212
213
214  void Parameter::set_default(void)
215  {
216    if (!root_.present())
217      root_.value(".");
218
219    if (!config_file_.present())
220      config_file_.value(concatenate_path(root_.value(),".svndigest/config"));
221
222    set_default2();
223  }
224
225
226  bool Parameter::verbose(void) const
227  {
228    return verbose_.present();
229  }
230
231
232}} // of namespace svndigest and namespace theplu
Note: See TracBrowser for help on using the repository browser.