Changeset 1293


Ignore:
Timestamp:
Nov 14, 2010, 6:34:10 AM (9 years ago)
Author:
Peter Johansson
Message:

rewrite svndigest-copy-cache in C++. closes #463

Location:
trunk
Files:
2 added
13 edited
2 copied

Legend:

Unmodified
Added
Removed
  • trunk/NEWS

    r1280 r1293  
    44
    55Version 0.10 (released NOT YET)
     6  - svndigest-copy-cache now only traverses svn controlled directories
     7    and respects svndigest:ignore propery (ticket #463).
    68
    79  A complete list of closed tickets can be found here [[br]]
  • trunk/bin/AbstractParameter.cc

    r1291 r1293  
    2323#include <config.h> // this header file is created by configure
    2424
    25 #include "Parameter.h"
     25#include "AbstractParameter.h"
    2626
    2727#include "lib/OptionVersion.h"
     
    4848namespace svndigest {
    4949
    50   Parameter::Parameter(void)
     50  AbstractParameter::AbstractParameter(void)
    5151    : cmd_( std::string("Mandatory arguments to long options ") +
    5252            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"),
    5753      help_(cmd_),
    58       ignore_cache_(cmd_, "ignore-cache",
    59                     std::string("ignore cache files and analyze ") +
    60                     std::string("everything from repository")),
    6154      root_(cmd_, "r,root",
    6255            "svn controlled directory to perform statistics on [.]"),
     
    6760
    6861
    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)
     62  AbstractParameter::~AbstractParameter(void)
    8063  {
    8164  }
    8265
    8366
    84   void Parameter::analyse(void)
     67  void AbstractParameter::analyse(void)
    8568  {
    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();
     69    // call pure virtual function
     70    analyse1();
    12771  }
    12872
    12973
    130   void Parameter::check_existence(std::string path) const
     74  void AbstractParameter::analyse_root(const std::string root)
     75  {
     76    check_existence(root);
     77    check_readable(root);
     78    check_is_dir(root);
     79   
     80    std::string save_wd = pwd();
     81    chdir(root);
     82    root_full_ = pwd();
     83    chdir(save_wd);
     84   
     85    // take care of when root is a symlink (see ticket #477)
     86    struct stat stats;
     87    lstat(root.c_str(), &stats);
     88    if (S_ISLNK(stats.st_mode))
     89      root_basename_ = file_name(root);
     90    else
     91      root_basename_ = file_name(root_full_);
     92  }
     93
     94
     95  void AbstractParameter::check_existence(std::string path) const
    13196  {
    13297    if (node_exist(path))
     
    139104
    140105 
    141   void Parameter::check_is_dir(std::string path) const
     106  void AbstractParameter::check_is_dir(std::string path) const
    142107  {
    143108    if (node_exist(path)) {
     
    154119
    155120 
    156   void Parameter::check_readable(std::string path) const
     121  void AbstractParameter::check_readable(std::string path) const
    157122  {
    158123    if (!access_rights(path, "r"))
     
    165130 
    166131
    167   std::string Parameter::config_file(void) const
    168   {
    169     return config_file_.value();
    170   }
    171 
    172 
    173   bool Parameter::generate_config(void) const
    174   {
    175     return generate_config_.present();
    176   }
    177 
    178 
    179   bool Parameter::ignore_cache(void) const
    180   {
    181     return ignore_cache_.present();
    182   }
    183 
    184 
    185   void Parameter::init(void)
     132  void AbstractParameter::init(void)
    186133  {
    187134    // we like the options sorted alphabetically
    188135    cmd_.sort();
    189     config_file_.print_arg("=FILE");
    190136    root_.print_arg("=ROOT");
    191137    std::stringstream ss;
     
    193139       << PACKAGE << " home page: <" << PACKAGE_URL << ">.\n";
    194140    help_.post_arguments() = ss.str();
    195     init2();
     141    init1();
    196142  }
    197143
    198144
    199   std::string Parameter::root(void) const
     145  void AbstractParameter::parse(int argc, char* argv[])
     146  {
     147    init();
     148    cmd_.parse(argc, argv);
     149    set_default();
     150    // analyse arguments
     151    analyse();
     152  }
     153
     154
     155  std::string AbstractParameter::root(void) const
    200156  {
    201157    return root_full_;
     
    203159
    204160
    205   const std::string& Parameter::root_basename(void) const
     161  const std::string& AbstractParameter::root_basename(void) const
    206162  {
    207163    assert(root_basename_.size());
     
    210166
    211167
    212   void Parameter::set_default(void)
     168  void AbstractParameter::set_default(void)
    213169  {
    214170    if (!root_.present())
    215171      root_.value(".");
    216172
    217     if (!config_file_.present())
    218       config_file_.value(concatenate_path(root_.value(),".svndigest/config"));
    219 
    220     set_default2();
     173    set_default1();
    221174  }
    222175
    223176
    224   bool Parameter::verbose(void) const
     177  bool AbstractParameter::verbose(void) const
    225178  {
    226179    return verbose_.present();
  • trunk/bin/AbstractParameter.h

    r1291 r1293  
    1 #ifndef _theplu_svndigest_parameter_
    2 #define _theplu_svndigest_parameter_
     1#ifndef _theplu_svndigest_abstract_parameter_
     2#define _theplu_svndigest_abstract_parameter_
    33
    44// $Id$
     
    4545
    4646  // class for command line options.
    47   class Parameter {
     47  class AbstractParameter {
    4848  public:
    49     Parameter(void);
    50     virtual ~Parameter(void);
     49    AbstractParameter(void);
     50    virtual ~AbstractParameter(void);
    5151    void parse( int argc, char *argv[]);
    52 
    53     std::string config_file(void) const;
    54    
    55     bool generate_config(void) const ;
    56     bool ignore_cache(void) const;
    5752
    5853    /**
     
    7368    yat::utility::CommandLine cmd_;
    7469    yat::utility::OptionHelp help_;
     70    yat::utility::OptionArg<std::string> root_;
     71
     72    // check that root is OK, i.e., an existing, readable and
     73    // accessible directory. throw cmd_error if not.
     74    void analyse_root(const std::string root);
    7575
    7676    // throw cmd_error if path doesn't exist
     
    8383  private:
    8484    void analyse(void);
    85     virtual void analyse2(void)=0;
     85    virtual void analyse1(void)=0;
    8686    void init(void);
    8787    // called at end of init(void)
    88     virtual void init2(void) = 0;
     88    virtual void init1(void) = 0;
    8989    void set_default(void);
    90     virtual void set_default2(void)=0;
     90    virtual void set_default1(void)=0;
    9191
    92     yat::utility::OptionArg<std::string> config_file_;
    93     yat::utility::OptionSwitch generate_config_;
    94     yat::utility::OptionSwitch ignore_cache_;
    95     yat::utility::OptionArg<std::string> root_;
    9692    std::string root_basename_;
    9793    std::string root_full_;
  • trunk/bin/Makefile.am

    r1290 r1293  
    2121# along with svndigest. If not, see <http://www.gnu.org/licenses/>.
    2222
    23 bin_PROGRAMS = svndigest svncopyright
     23bin_PROGRAMS = svndigest svndigest-copy-cache svncopyright
    2424
    25 svndigest_SOURCES = Parameter.cc svndigestParameter.cc svndigest.cc
    26 svncopyright_SOURCES = Parameter.cc svncopyrightParameter.cc svncopyright.cc
     25svndigest_SOURCES = AbstractParameter.cc Parameter.cc \
     26  svndigestParameter.cc svndigest.cc
     27svndigest_copy_cache_SOURCES = AbstractParameter.cc \
     28  svndigest_copy_cacheParameter.cc svndigest-copy-cache.cc
     29svncopyright_SOURCES = AbstractParameter.cc Parameter.cc \
     30  svncopyrightParameter.cc svncopyright.cc
    2731
    2832noinst_HEADERS = Parameter.h svncopyrightParameter.h svndigestParameter.h
    29 
    30 bin_SCRIPTS = svndigest-copy-cache
    31 EXTRA_DIST = svndigest-copy-cache.as
    3233
    3334LDADD = $(top_builddir)/lib/libsvndigest_core.a \
     
    3940
    4041svndigest_LDADD = $(top_builddir)/lib/libsvndigest.a $(LDADD) $(PLPLOT_LIBS)
    41 ##svndigest_LDFLAGS = $(AM_LDFLAGS) $(PLPLOT_LDFLAGS)
    42 ##svndigest_CPPFLAGS  = $(AM_CPPFLAGS) $(PLPLOT_CPPFLAGS)
    43 
    44 .as.in:
    45   $(AUTOM4TE) -l M4sh -o $@ $(M4SH_OPTIONS) $<
    46 
    47 MAINTAINERCLEANFILES = svndigest-copy-cache.in
    4842
    4943clean-local:
  • trunk/bin/Parameter.cc

    r1264 r1293  
    2525#include "Parameter.h"
    2626
    27 #include "lib/OptionVersion.h"
    28 #include "lib/utility.h" // to avoid inclusion of yat file
     27#include "lib/utility.h"
    2928
    3029#include "yat/ColumnStream.h"
     
    4948
    5049  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",
     50    : config_file_(cmd_, "config-file",
    5451                   "configuration file [<ROOT>/.svndigest/config]"),
    5552      generate_config_(cmd_, "g,generate-config",
    5653                       "write configuration to standard output"),
    57       help_(cmd_),
    5854      ignore_cache_(cmd_, "ignore-cache",
    5955                    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_)
     56                    std::string("everything from repository"))
    6557  {
    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();
    7658  }
    7759
     
    8264
    8365
    84   void Parameter::analyse(void)
     66  void Parameter::analyse1(void)
    8567  {
    8668    std::string save_wd = pwd();
     
    8870    // check root but not if -g option given
    8971    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_);
     72      analyse_root(root_.value());
    10573    }
    10674
     
    12896
    12997
    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     }
    149     std::stringstream ss;
    150     ss << cmd_.program_name() << ": '" << path << "': "
    151        << strerror(errno);
    152     throw yat::utility::cmd_error(ss.str());
    153   }
    154 
    155  
    156   void Parameter::check_readable(std::string path) const
    157   {
    158     if (!access_rights(path, "r"))
    159       return;
    160     std::stringstream ss;
    161     ss << cmd_.program_name() << ": cannot open '" << path << "': "
    162        << strerror(errno);
    163     throw yat::utility::cmd_error(ss.str());
    164   }
    165  
    166 
    16798  std::string Parameter::config_file(void) const
    16899  {
     
    183114
    184115
    185   void Parameter::init(void)
     116  void Parameter::init1(void)
    186117  {
    187     // we like the options sorted alphabetically
    188     cmd_.sort();
    189118    config_file_.print_arg("=FILE");
    190     root_.print_arg("=ROOT");
    191     std::stringstream ss;
    192     ss << "Report bugs to " << PACKAGE_BUGREPORT << ".\n"
    193        << PACKAGE << " home page: <" << PACKAGE_URL << ">.\n";
    194     help_.post_arguments() = ss.str();
    195119    init2();
    196120  }
    197121
    198122
    199   std::string Parameter::root(void) const
     123  void Parameter::set_default1(void)
    200124  {
    201     return root_full_;
    202   }
    203 
    204 
    205   const std::string& Parameter::root_basename(void) const
    206   {
    207     assert(root_basename_.size());
    208     return root_basename_;
    209   }
    210 
    211 
    212   void Parameter::set_default(void)
    213   {
    214     if (!root_.present())
    215       root_.value(".");
    216 
    217125    if (!config_file_.present())
    218126      config_file_.value(concatenate_path(root_.value(),".svndigest/config"));
     
    222130
    223131
    224   bool Parameter::verbose(void) const
    225   {
    226     return verbose_.present();
    227   }
    228 
    229 
    230132}} // of namespace svndigest and namespace theplu
  • trunk/bin/Parameter.h

    r1264 r1293  
    2424*/
    2525
     26#include "AbstractParameter.h"
     27
    2628#include "lib/OptionVersion.h"
    2729
    2830#include "yat/CommandLine.h"
    2931#include "yat/OptionArg.h"
    30 #include "yat/OptionHelp.h"
    3132#include "yat/OptionSwitch.h"
    3233
     
    3536
    3637namespace theplu {
    37 namespace yat {
    38 namespace utility {
    39   class OptionHelp;
    40   class OptionSwitch;
    41 }}
    4238namespace svndigest {
    4339
    44   class OptionVersion;
    45 
    46   // class for command line options.
    47   class Parameter {
     40  // base class for svndigestParameter and svncopyrightParameter
     41  class Parameter : public AbstractParameter
     42  {
    4843  public:
    4944    Parameter(void);
    5045    virtual ~Parameter(void);
    51     void parse( int argc, char *argv[]);
    5246
    5347    std::string config_file(void) const;
     
    5650    bool ignore_cache(void) const;
    5751
    58     /**
    59        @return Dereferenced absolute path to root directory
    60     */
    61     std::string root(void) const;
    62 
    63     /**
    64        If --root argument is a link we return the file_name(argument).
    65        Otherwise we return file_name(root()). See root(void).
    66 
    67        \return basename of --root argument.
    68      */
    69     const std::string& root_basename(void) const;
    70     bool verbose(void) const;
    71 
    72   protected:
    73     yat::utility::CommandLine cmd_;
    74     yat::utility::OptionHelp help_;
    75 
    76     // throw cmd_error if path doesn't exist
    77     void check_existence(std::string path) const;
    78     // throw cmd_error if path is not dir
    79     void check_is_dir(std::string path) const;
    80     // throw cmd_error if path is not readable
    81     void check_readable(std::string path) const;
    82 
    8352  private:
    84     void analyse(void);
     53    void analyse1(void);
    8554    virtual void analyse2(void)=0;
    86     void init(void);
     55    void init1(void);
    8756    // called at end of init(void)
    8857    virtual void init2(void) = 0;
    89     void set_default(void);
     58    void set_default1(void);
    9059    virtual void set_default2(void)=0;
    9160
     
    9362    yat::utility::OptionSwitch generate_config_;
    9463    yat::utility::OptionSwitch ignore_cache_;
    95     yat::utility::OptionArg<std::string> root_;
    96     std::string root_basename_;
    97     std::string root_full_;
    98     yat::utility::OptionSwitch verbose_;
    99   protected:
    100     OptionVersion version_;
    101 
    10264  };
    10365
  • trunk/bin/svncopyrightParameter.cc

    r1119 r1293  
    4545  void svncopyrightParameter::init2(void)
    4646  {
     47    root_.description("svn wc to perform copyright update on");
    4748    help_.synopsis() =
    4849      "Update copyright statement in files under subversion control\n";
  • trunk/configure.ac

    r1259 r1293  
    6969AC_CONFIG_HEADERS([config.h])
    7070AM_INIT_AUTOMAKE([1.11 color-tests std-options parallel-tests])
    71 
    72 dnl create bin/svndigest-copy-cache.in at autoconf time and let
    73 dnl config.status create bin/svndigest-copy-cache from
    74 dnl bin/svndigest-copy-cache.in
    75 m4_pushdef([FILE], [svndigest-copy-cache])
    76 m4_pushdef([my_m4sh_options], [-m 0644])
    77 dnl me cd down in bin to have same output as when created from Makefile
    78 m4_syscmd([cd bin && autom4te -l M4sh -o ]FILE[.in ]my_m4sh_options FILE[.as])
    79 AC_CONFIG_FILES([bin/]FILE[], [chmod +x bin/]FILE[ && chmod a-w bin/]FILE[])
    80 dnl export options so we can use the same in Makefile
    81 AC_SUBST([M4SH_OPTIONS], ['my_m4sh_options'])
    82 m4_popdef([my_m4sh_options])
    83 m4_popdef([FILE])
    84 AM_MISSING_PROG([AUTOM4TE], [autom4te])
    8571
    8672# Set default programming language
  • trunk/doc/readme.txt

    r1280 r1293  
    248248will not create any directories in `TARGET` tree except that
    249249`.svndigest` directories are created when necessary.
    250 
    251 Also, `svndigest-copy-cache` is ignorant about svn wc and will parse
    252 through `ROOT` directory and all its sub-directories, looking for
    253 svndigest cache files, regardless whether they belong to the same svn
    254 working copy or not. Therefore, having other svn wc in subdirectories
    255 of `ROOT` might give an unexpected result.
  • trunk/lib/File.cc

    r1290 r1293  
    6161
    6262
     63  std::string File::cache_name(void) const
     64  {
     65    std::string dir = concatenate_path(directory_name(path()), ".svndigest/");
     66    return dir + name() + ".svndigest-cache";
     67  }
     68
     69
    6370  std::string File::href(void) const
    6471  {
     
    8996      std::cout << "Parsing '" << path_ << "'" << std::endl;
    9097    stats_.reset();
    91     std::string cache_dir = directory_name(path()) + std::string(".svndigest/");
    92     std::string cache_file = cache_dir + name()+std::string(".svndigest-cache");
     98    std::string cache_file = cache_name();
     99    std::string cache_dir = directory_name(cache_file);
    93100    if (!ignore && node_exist(cache_file)){
    94101      std::ifstream is(cache_file.c_str());
  • trunk/lib/File.h

    r1290 r1293  
    4141    File(const unsigned int level, const std::string& path,
    4242         const std::string& output="");
     43
     44    /**
     45       \return absolute path to cache file
     46    */
     47    std::string cache_name(void) const;
    4348
    4449    /**
  • trunk/lib/Makefile.am

    r1290 r1293  
    3030noinst_LIBRARIES = libsvndigest.a libsvndigest_core.a
    3131
    32 noinst_HEADERS = AddStats.h Alias.h BlameStats.h ClassicStats.h \
    33   Colors.h Commitment.h Configuration.h CopyrightVisitor.h css.h \
     32noinst_HEADERS = AddStats.h Alias.h BlameStats.h CacheCopyer.h ClassicStats.h \
     33  Colors.h Commitment.h Configuration.h \
     34  CopyrightVisitor.h css.h \
    3435  Date.h Directory.h DirectoryPrinter.h File.h FilePrinter.h \
    3536  first_page.h Functor.h \
     
    5354
    5455libsvndigest_core_a_SOURCES = AddStats.cc Alias.cc BlameStats.cc \
    55   ClassicStats.cc Colors.cc \
     56  CacheCopyer.cc ClassicStats.cc Colors.cc \
    5657  Commitment.cc Configuration.cc CopyrightVisitor.cc \
    5758  css.cc Date.cc Directory.cc File.cc \
  • trunk/test/Makefile.am

    r1290 r1293  
    3434
    3535option_test_SOURCES = option.cc $(top_srcdir)/bin/Parameter.cc \
    36   $(top_srcdir)/bin/svndigestParameter.cc
     36  $(top_srcdir)/bin/AbstractParameter.cc $(top_srcdir)/bin/svndigestParameter.cc
    3737
    3838distributed_TESTS =
  • trunk/test/init.sh.in

    r1280 r1293  
    5151
    5252test -z "$SVNDIGEST" && SVNDIGEST="${abs_top_builddir}/bin/svndigest";
     53test -z "$SVNDIGEST_COPY_CACHE" \
     54&& SVNDIGEST_COPY_CACHE="${abs_top_builddir}/bin/svndigest-copy-cache";
    5355test -z "$SVNCOPYRIGHT" && SVNCOPYRIGHT="${abs_top_builddir}/bin/svncopyright";
    5456test -z "$srcdir" && srcdir="@srcdir@";
     
    105107}
    106108
     109SVNDIGEST_COPY_CACHE_run ()
     110{
     111    foo_prog="$SVNDIGEST_COPY_CACHE --verbose"
     112    foo_run $@
     113}
     114
    107115SVNCOPYRIGHT_run ()
    108116{
  • trunk/test/svndigest_copy_cache_test.sh

    r1094 r1293  
    2525
    2626for opt in --version --help; do
    27   $abs_top_builddir/bin/svndigest-copy-cache $opt > out.tmp 2> error.tmp
    28   test -n "`cat out.tmp`" || exit_fail
    29   test -z "`cat error.tmp`" || exit_fail
    30   rm -f *.tmp
     27  SVNDIGEST_COPY_CACHE_run 0 $opt
     28  test -n "`cat stdout`" || exit_fail
     29  test -z "`cat stderr`" || exit_fail
    3130done
    3231
     
    3433rm -rf $pristine
    3534$SVN co ${repo_url}/trunk $pristine
    36 $abs_top_builddir/bin/svndigest-copy-cache -v -r $rootdir -t $pristine
    3735
     36SVNDIGEST_run 0 -r $rootdir --no-report
     37SVNDIGEST_COPY_CACHE_run 0 -r $rootdir -t $pristine
     38
     39find $pristine | grep svndigest-cache || exit_fail
    3840rm -rf $pristine
    3941exit_success
Note: See TracChangeset for help on using the changeset viewer.