Changes in / [20:30]


Ignore:
Location:
/trunk
Files:
11 added
1 deleted
16 edited

Legend:

Unmodified
Added
Removed
  • /trunk/AUTHORS

    r20 r30  
    11$Id$
    22
    3 This package is developed and maintained by people at the Deparment
     3This package is developed and maintained by people at the Department
    44of Theoretical Physics at Lund University, Sweden.
    55
    66Jari Häkkinen
    77Peter Johansson
     8
     9
     10
     11A major part of the Gnuplot interface was written by Rajarshi Guha
     12(see README for details).
  • /trunk/Makefile.am

    r20 r30  
    33## $Id$
    44
    5 SUBDIRS = lib test
     5SUBDIRS = lib bin test
  • /trunk/README

    r20 r30  
    11// $Id$
     2
     3Acknowledgements
     4
     5svnstat uses a C++ interface to Gnuplot written by Rajarshi Guha. The
     6interface is integrated in the svnstat code with some modifications
     7(see below). The original code used for svnstat can be found in
     8directory ./gnuplot_i++.
     9
     10Rajarshi Guha's "A C++ Interface to Gnuplot" can be found through
     11http://jijo.cjb.net/ . The C++ interface is based on "gnuplot
     12interfaces in ANSI C" written by Nicolas Devillard. The C implemention
     13is available through http://ndevilla.free.fr/ .
     14
     15Changes made to the C++ Gnuplot interface files (gnuplot_i.hpp and
     16gnuplot_i.cc):
     17
     18i) Changed filename gnuplot_i.hpp to gnuplot_i.h, and consequently
     19   changed #include directive in gnuplot_i.cc.
     20
     21ii) Encapsulated the interface into namespace theplu::svnstat.
     22
     23iii) Added 'Id' tags in both files.
     24
     25iv) Changed the initial #ifndef/#define idiom to avoid potential
     26   clash with the original implementation.
     27
     28v) gnuplot_i.h: Removed the 'using namespace std;' statement, since we
     29   don't want to expose the std namespace to everyone using the
     30   Gnuplot interface. This triggered subsequent changes to code lines
     31   with string and vector<> usage.
     32
     33vi) Resolved signed/unsigned compiler warnings in gnuplot_i.cc on
     34   lines 235, 278, 418, and 482
     35
     36vii) gnuplot_i.cc: Changed order of code in Gnuplot destructor, now
     37   the pipe is closed first. I have not done a full scale
     38   investigation on why this is needed, but on MacOSX the files are
     39   removed before gnuplot plots data when the original code order is
     40   kept.
  • /trunk/configure.ac

    r20 r30  
    3232
    3333AC_CONFIG_FILES([Makefile
    34                  lib/Makefile
    35      test/Makefile])
     34                bin/Makefile
     35                lib/Makefile
     36                test/Makefile])
    3637
    3738AC_OUTPUT
  • /trunk/lib/Directory.cc

    r20 r30  
    66
    77#include <algorithm>
     8#include <fstream>
    89#include <iostream>
    910#include <iterator>
     
    1213#include <errno.h>  // Needed to check error state below.
    1314#include <dirent.h>
     15#include <sys/stat.h>
    1416
    1517namespace theplu{
    1618namespace svnstat{
    1719
    18   Directory::Directory(const std::string& path)
    19     : Node(path)
     20  Directory::Directory(const std::string& path, const std::string& output)
     21    : Node(path,output)
    2022  {
    2123    using namespace std;
    22     DIR* directory=opendir(path.c_str());
     24    DIR* directory=opendir(path.c_str());    // C API from dirent.h
    2325    if (!directory) {
    2426      // Jari, throw exception
     
    2830    list<string> entries;
    2931    struct dirent* entry;
    30     errno=0;  // Global variable used by C to track errors.
    31     while ((entry=readdir(directory)))
    32       entries.push_back(string(entry->d_name)); // Jari, push backing
     32    errno=0;  // Global variable used by C to track errors, from errno.h
     33    while ((entry=readdir(directory)))       // C API from dirent.h
     34      entries.push_back(string(entry->d_name));
    3335    if (errno) {
    3436      // Jari, throw exception
     
    4143    for (list<string>::iterator i=entries.begin(); i!=entries.end(); i++)
    4244      if ((*i)!=string(".") && (*i)!=string("..") && (*i)!=string(".svn")) {
    43         /// Jari, should test if directory in some other way
    4445        string fullpath(path_+'/'+(*i));
    45         DIR* dirtest=opendir(fullpath.c_str());
    46         if (!dirtest)
    47           daughters_.push_back(new File(fullpath));
     46        struct stat nodestat;                // C api from sys/stat.h
     47        lstat(fullpath.c_str(),&nodestat);   // C api from sys/stat.h
     48        if (S_ISDIR(nodestat.st_mode))       // C api from sys/stat.h
     49          daughters_.push_back(new Directory(fullpath, output_name_+"_"));
    4850        else
    49           daughters_.push_back(new Directory(fullpath));
     51          daughters_.push_back(new File(fullpath,output_name_+"_"));
    5052      }
    5153  }
     
    5456  Directory::~Directory(void)
    5557  {
    56     // Jari, change this to some STL algo?
    57     for (std::list<Node*>::iterator i=daughters_.begin();
    58          i!=daughters_.end(); i++)
     58    for (NodeIterator i=daughters_.begin(); i!=daughters_.end(); i++)
    5959      delete *i;
    6060  }
     
    6565    stats_.reset();
    6666
    67     for (std::list<Node*>::iterator i=daughters_.begin();
    68          i!=daughters_.end(); i++)
     67    for (NodeIterator i=daughters_.begin(); i!=daughters_.end(); i++)
    6968      stats_ += (*i)->parse();
    7069    return stats_;
     
    7271
    7372
    74   void Directory::print(void) {
    75     // Jari, temporary using this to print directory tree
    76     for_each(daughters_.begin(),daughters_.end(), std::mem_fun(&Node::print));
     73  void Directory::print(const std::string& path) const
     74  {
     75    std::string output(path + output_name_ + ".html");
     76    std::ofstream os(output.c_str());
     77    print_header(os);
     78    os << std::endl;
     79    stats_.print(os);
     80    os << std::endl;
     81
     82    for (NodeConstIter_ i=daughters_.begin();i!=daughters_.end();i++){
     83      (*i)->print_link(os);
     84      os << "<br/>" << std::endl;
     85    }
     86
     87    print_footer(os);
     88    os.close();
     89
     90    // Peter, use STL algo.
     91    for (NodeConstIter_ i=daughters_.begin();i!=daughters_.end();i++)
     92      (*i)->print(path);
    7793  }
    7894
    79 
    8095  void Directory::purge(void) {
    81     for (std::list<Node*>::iterator i=daughters_.begin(); i!=daughters_.end(); )
     96    for (NodeIterator i=daughters_.begin(); i!=daughters_.end(); )
    8297      if (!((*i)->subversion_controlled())) {
    8398        delete *i;
  • /trunk/lib/Directory.h

    r20 r30  
    2121    /// @brief Constructor
    2222    ///
    23     /// Recursively create a directory tree starting from \a
    24     /// path. Nodes named '.', '..', and '.svn' are ignored and not
     23    /// Recursively create a directory tree starting from \a path. All
     24    /// entries except explicit directories are treated as File nodes,
     25    /// i.e. symbolic links to directories are treated as File
     26    /// nodes. This will ensure that the directory structure is a tree
     27    /// and double counting of branches is avoided.
     28    ///
     29    /// @note Nodes named '.', '..', and '.svn' are ignored and not
    2530    /// traversed.
    2631    ///
    27     Directory(const std::string& path);
     32    Directory(const std::string& path, const std::string& output="");
    2833
    2934    ///
     
    3439    const Stats& parse(void);
    3540
    36     void print(void);
     41    void print(const std::string&) const;
    3742
    3843    void purge(void);
     
    4449    Directory(const Directory&);
    4550
     51    typedef std::list<Node*>::iterator NodeIterator;
     52    typedef std::list<Node*>::const_iterator NodeConstIter_;
    4653    std::list<Node*> daughters_;
    4754  };
  • /trunk/lib/File.cc

    r20 r30  
    2222  }
    2323
     24  void File::info(void)
     25  {
     26    std::string system_call = "svn info " + path_ + " > svnstat.tmp";
     27    int system_return = system(system_call.c_str());
     28    if (system_return){
     29      // Jari, throw exception.
     30      std::cerr << "svnstat: svn info " << path_ << std::endl;     
     31      exit(-1);
     32    }
     33    std::ifstream is("svnstat.tmp");
     34    std::string line;
     35    while (getline(is,line)){
     36      std::stringstream ss(line);
     37      std::string tag;
     38      getline(ss,tag,':');
     39      if (tag == std::string("Last Changed Author"))
     40        ss >> author_;
     41      else if (tag == std::string("Last Changed Rev"))
     42        ss >> revision_;
     43    }
     44  }
     45
     46
    2447  const Stats& File::parse(void)
    2548  {
    2649    stats_.reset();
     50    info();
     51
    2752    if (binary_){
    2853      stats_.add(author_,revision_);
     
    4166      getline(is,line,' ');
    4267      if (line==std::string("binary")){
    43   is.close();
    44   binary_ = true;
    45   return parse();
     68        is.close();
     69        binary_ = true;
     70        return parse();
    4671      }
    4772    }
     
    5176    while (getline(is,line, '\n')){
    5277      if (!line.size()) // skip empty line
    53   continue;
     78        continue;
    5479      std::stringstream ss(line);
    5580      u_int revision;
     
    6388  }
    6489
    65   void File::print(void) {
    66     // Jari, temporary using this to print directory tree
    67     std::cout << "File '" << path_ << "'" << std::endl;
     90  void File::print(const std::string& path) const
     91  {
     92    std::string output(path + output_name_ + ".html");
     93    std::ofstream os(output.c_str());
     94    print_header(os);
     95    os << std::endl;
     96    stats_.print(os);
     97    os << std::endl;
     98    print_footer(os);
     99    os.close();
     100
    68101  }
    69102
  • /trunk/lib/File.h

    r20 r30  
    1717    /// @brief Default Constructor
    1818    ///
    19     inline File(const std::string& path) : Node(path), binary_(false) {}
     19    File(const std::string& path, const std::string& output="")
     20      : Node(path,output), binary_(false) {}
    2021
    2122    ///
     
    2627    const Stats& parse(void);
    2728
    28     void print(void);
     29    ///
     30    ///
     31    ///
     32    void print(const std::string& path) const;
    2933
    3034  private:
    31     ///
    32     /// @brief Copy Constructor, not implemented
    33     ///
    34     File(const File&);
    35 
    3635    ///
    3736    /// @brief Parsing svn blame output
     
    4140    bool blame(void) const;
    4241   
    43    
     42    ///
     43    /// @brief Copy Constructor, not implemented
     44    ///
     45    File(const File&);
     46
     47    ///
     48    /// Extracts information from 'svn info <node>'
     49    ///
     50    /// @note <node> must be in subversion control.
     51    ///
     52    void info(void);
     53
     54    std::string author_;
    4455    bool binary_;
     56    u_int revision_;
    4557 
    4658  };
  • /trunk/lib/Makefile.am

    r20 r30  
    44
    55noinst_LIBRARIES = libsvnstat.a
    6 libsvnstat_a_SOURCES = Directory.cc File.cc Node.cc Stats.cc
     6libsvnstat_a_SOURCES = Directory.cc File.cc gnuplot_i.cc Node.cc Stats.cc
  • /trunk/lib/Node.cc

    r20 r30  
    44#include "utility.h"
    55
     6#include <ctime>
    67#include <fstream>
    78#include <iostream>
     
    1112namespace svnstat{
    1213
    13   void Node::info(void)
    14   {
    15     std::string system_call = "svn info " + path_ + " > svnstat.tmp";
    16     int system_return = system(system_call.c_str());
    17     if (system_return){
    18       // Jari, throw exception.
    19       std::cerr << "Error: svn info " << path_ << std::endl;     
    20       exit(-1);
    21     }
    22     std::cerr << "Ok: svn info " << path_ << std::endl;     
    23     std::ifstream is("svnstat.tmp");
    24     std::string line;
    25     while (getline(is,line)){
    26       std::stringstream ss(line);
    27       std::string tag;
    28       getline(ss,tag,':');
    29       if (tag == std::string("Repository UUID"))
    30         ss >> uuid_;
    31       else if (tag == std::string("Last Changed Author"))
    32         ss >> author_;
    33       else if (tag == std::string("Last Changed Rev"))
    34         ss >> revision_;
    35     }
    36   }
     14  Node::Node(const std::string& path, const std::string& output)
     15    : path_(path)
     16  {
     17    output_name_ = output + name();
     18  }
     19
     20
     21  std::string Node::name(void) const
     22  {
     23    std::stringstream ss(path_);
     24    std::string name;
     25    while (getline(ss,name,'/')) {}
     26    return name;
     27  }
     28
     29
     30  void Node::print_footer(std::ostream& os) const
     31  {
     32    os << "</body>\n"
     33       << "</html>";
     34  }
     35
     36
     37  void Node::print_header(std::ostream& os) const
     38  {
     39    os << "<html>\n"
     40       << "<head>\n"
     41       << "<title> svnstat " << name() << "\n"
     42       << "</head>\n"
     43       << "<body bgcolor='FFFBFB'\n";
     44  }
    3745
    3846
  • /trunk/lib/Node.h

    r20 r30  
    66#include "Stats.h"
    77
     8#include <ostream>
    89#include <string>
    910
     
    2021    /// @brief Constructor
    2122    ///
    22     inline Node(const std::string& path) : path_(path) {}
     23    Node(const std::string& path, const std::string& output="");
    2324
    2425    ///
     
    2627    ///
    2728    virtual inline ~Node(void) {};
    28 
    29     ///
    30     /// Extracts information from 'svn info <node>'
    31     ///
    32     /// @note <node> must be in subversion control.
    33     ///
    34     void info(void);
    3529
    3630    ///
     
    4236    /// Function printing HTML in directory path
    4337    ///
    44     virtual void print(void)=0;
     38    virtual void print(const std::string& path) const=0;
    4539
     40    ///
     41    /// Prints a html link.
     42    ///
     43    inline void print_link(std::ostream& os) const
     44    { os << "<a href=\"" << output_name_ << ".html\">" << name() << "</a>"; }
     45 
     46    ///
     47    ///
     48    ///
    4649    inline virtual void purge(void) { /* Nothing to be done */ };
    4750
     
    5558
    5659  protected:
    57     std::string author_;
     60    ///
     61    /// Function returning everything after the last '/'
     62    ///
     63    /// @return name of node (not full path)
     64    ///
     65    std::string name(void) const;
     66
     67    ///
     68    /// @brief print html footer of page
     69    ///
     70    void print_footer(std::ostream&) const;
     71   
     72    ///
     73    /// @brief print html header of page
     74    ///
     75    void print_header(std::ostream&) const;
     76
     77    std::string output_name_; //without suffix
    5878    std::string path_;
    59     u_int revision_;
    6079    Stats stats_;
    61     std::string uuid_;
    6280
    6381  private:
     
    6684    ///
    6785    Node(const Node&);
     86
    6887  };
    6988
  • /trunk/lib/Stats.cc

    r20 r30  
    77#include <numeric>
    88#include <string>
     9#include <utility>
    910#include <vector>
     11
     12#include <iostream>
    1013
    1114namespace theplu{
     
    5962  }
    6063
     64  void Stats::print(std::ostream& os) const
     65  {
     66    std::vector<std::pair<std::string, std::vector<u_int> > > accum;
     67    for (MapConstIter_ i= map_.begin(); i != map_.end(); i++){
     68      std::pair<std::string, std::vector<u_int> > element(*i);
     69      std::partial_sum(element.second.begin(),element.second.end(),
     70                       element.second.begin());
     71      accum.push_back(element);
     72    }
     73    sort(accum.begin(),accum.end(), CodingMore());
     74    os << "<table>\n";
     75    for (size_t i = 0; i<accum.size(); i++){
     76      os << "<tr><td>\n" << accum[i].first << "</td><td>"
     77         << accum[i].second.back() << "</td></tr>";
     78    }
     79    os << "</table>\n";
     80
     81    os << "<p>[Plot to be here.]</p>\n";         
     82  }
     83
    6184  Stats& Stats::operator+=(const Stats& other)
    6285  {
    63     for (_MapConstIt o_i= other.map_.begin(); o_i != other.map_.end(); ++o_i)
     86    for (MapConstIter_ o_i= other.map_.begin(); o_i != other.map_.end(); ++o_i)
    6487    {
    65       std::pair<_MapIt,bool> result = map_.insert(*o_i);
     88      std::pair<MapIter_,bool> result = map_.insert(*o_i);
    6689      if (!result.second)
    67   map_[(*(result.first)).first] =
    68     VectorPlus<u_int>()( (*(result.first)).second, (*o_i).second );
     90        map_[(*(result.first)).first] =
     91          VectorPlus<u_int>()( (*(result.first)).second, (*o_i).second );
    6992 
    7093    }
  • /trunk/lib/Stats.h

    r20 r30  
    2222   
    2323    ///
     24    /// @brief adding a line to user from revision to the stats
     25    ///
     26    void add(const std::string& user, const u_int& revision);
     27
     28    ///
     29    /// @bief print statistics
     30    ///
     31    void print(std::ostream&) const;
     32
     33    ///
     34    /// @brief Clear all statistics
     35    ///
     36    inline void reset(void) { map_.clear(); }
     37
     38    ///
     39    /// @return resulting Stats
     40    ///
     41    Stats& operator+=(const Stats&);
     42
     43  private:
     44    ///
     45    /// Copy constructor (not implemented)
     46    ///
     47    Stats(const Stats& other);
     48
     49    ///
    2450    /// @return accumulated vector of total
    2551    ///
     
    3157    std::vector<u_int> accumulated(const std::string& user);
    3258
    33     ///
    34     /// @brief adding a line to user from revision to the stats
    35     ///
    36     void add(const std::string& user, const u_int& revision);
    37 
    38     inline void reset(void) { map_.clear(); }
    39 
    40 
    41     ///
    42     /// @return resulting Stats
    43     ///
    44     Stats& operator+=(const Stats&);
    45 
    46   private:
    47     Stats(const Stats& other);
    48 
    4959    // Peter, if the vector is sparse make it a map
    50     typedef std::map<std::string, std::vector<u_int> > _Map;
    51     typedef _Map::iterator _MapIt;
    52     typedef _Map::const_iterator _MapConstIt;
    53     _Map map_;
     60    typedef std::map<std::string, std::vector<u_int> > Map_;
     61    typedef Map_::iterator MapIter_;
     62    typedef Map_::const_iterator MapConstIter_;
     63    Map_ map_;
    5464  };
    5565}}
  • /trunk/lib/utility.h

    r20 r30  
    66#include <algorithm>
    77#include <functional>
     8#include <string>
    89#include <utility>
    910#include <vector>
     
    1213namespace svnstat{
    1314
    14   ///
    15   /// Calculating sum of two vectors.
    16   ///
    17   /// @return resulting vector
    18   ///
    19   template <class T >
    20     struct VectorPlus :
    21   public std::binary_function<std::vector<T>,std::vector<T>,std::vector<T> >
    22     {
    23       std::vector<T> operator()(const std::vector<T>& u,
    24         const std::vector<T>& v) const
    25       {
    26   if ( u.size() > v.size() ){
    27     std::vector<T> res(u.size());
    28     transform(u.begin(), u.end(), v.begin(), res.begin(), std::plus<T>());
    29     copy(u.begin()+v.size(), u.end(), res.begin()+v.size());
    30     return res;
    31   }
     15  ///
     16  /// Calculating sum of two vectors.
     17  ///
     18  /// @return resulting vector
     19  ///
     20  template <class T >
     21  struct VectorPlus :
     22    public std::binary_function<std::vector<T>,std::vector<T>,std::vector<T> >
     23  {
     24    std::vector<T> operator()(const std::vector<T>& u,
     25                              const std::vector<T>& v) const
     26    {
     27      if ( u.size() > v.size() ){
     28        std::vector<T> res(u.size());
     29        transform(u.begin(), u.end(), v.begin(), res.begin(), std::plus<T>());
     30        copy(u.begin()+v.size(), u.end(), res.begin()+v.size());
     31        return res;
     32      }
    3233 
    33   std::vector<T> res(v.size());
    34   transform(v.begin(), v.end(), u.begin(), res.begin(), std::plus<T>());
    35   if ( v.size() > u.size() )
    36     copy(u.begin()+v.size(), u.end(), res.begin()+v.size());
    37   return res;
    38       }
     34      std::vector<T> res(v.size());
     35      transform(v.begin(), v.end(), u.begin(), res.begin(), std::plus<T>());
     36      if ( v.size() > u.size() )
     37        copy(v.begin()+u.size(), v.end(), res.begin()+u.size());
     38      return res;
     39    }
    3940
    40     };
     41  };
    4142
    4243  ///
     
    4445  ///
    4546  template <class Key, class T>
    46     struct PairValuePlus :
    47   public std::binary_function<std::vector<T>,
    48     std::pair<const Key, std::vector<T> >,
    49     std::vector<T> >
    50     {
    51       std::vector<T> operator()(const std::vector<T>& sum,
    52         const std::pair<const Key,std::vector<T> >& p)
    53       {
    54   return VectorPlus<T>()(sum, p.second);
    55       }
    56     };
     47  struct PairValuePlus :
     48    public std::binary_function<std::vector<T>,
     49                                std::pair<const Key, std::vector<T> >,
     50                                std::vector<T> >
     51  {
     52    std::vector<T> operator()(const std::vector<T>& sum,
     53                              const std::pair<const Key,std::vector<T> >& p)
     54    {
     55      return VectorPlus<T>()(sum, p.second);
     56    }
     57  };
     58
     59  ///
     60  struct CodingMore :
     61    public std::binary_function<std::pair<std::string,std::vector<u_int> >,
     62                                std::pair<std::string,std::vector<u_int> >,
     63                                bool >
     64  {
     65    inline bool operator()
     66      (const std::pair<std::string,std::vector<u_int> >& a,
     67       const std::pair<std::string,std::vector<u_int> >& b)
     68    {
     69      if (a.second.back() > b.second.back())
     70        return true;
     71      else if (a.second.back() < b.second.back())
     72        return false;
     73      return a.first < b.first;
     74    }
     75  };
     76
    5777}}
    5878
    59 #endif // end of namespace svnstat end of namespace theplu
     79// end of namespace svnstat end of namespace theplu
     80#endif
  • /trunk/test/Makefile.am

    r20 r30  
    33# $Id$
    44
    5 TESTS = svnstat tree
     5TESTS = directory file gnuplot_pipe stats tree
    66
    77check_PROGRAMS = $(TESTS)
     
    1111INCLUDES = -I@top_srcdir@/lib
    1212
    13 svnstat_SOURCES = svnstat.cc
     13
     14directory_SOURCES = directory.cc
     15file_SOURCES = file.cc
     16gnuplot_pipe_SOURCES = gnuplot_pipe.cc
     17stats_SOURCES = stats.cc
    1418tree_SOURCES = tree.cc
     19
     20clean-local:
     21  rm -rf svnstat_output
  • /trunk/test/tree.cc

    r20 r30  
    1010  using namespace theplu::svnstat;
    1111
    12   bool print = (argc>1 && argv[1]==std::string("-p"));
     12  //  bool print = (argc>1 && argv[1]==std::string("-p"));
    1313  bool ok = true;
    1414
    15   Directory tree(std::string("."));
     15  Directory tree(std::string("c++_tools"));
    1616
    17   std::cout << "================ Before purge" << std::endl;
    18   if (print)
    19     tree.print();
    20 
    21   std::cout << "================ Purging" << std::endl;
    2217  tree.purge();
    23 
    24   std::cout << "================ After purge" << std::endl;
    25   if (print)
    26     tree.print();
    27 
     18  tree.parse();
     19  ok = ok && !system("mkdir svnstat_output >& /dev/null");
     20  tree.print("svnstat_output/");
     21 
    2822  return (ok ? 0 : -1);
    2923}
Note: See TracChangeset for help on using the changeset viewer.