Panda3D

cvsSourceDirectory.cxx

00001 // Filename: cvsSourceDirectory.cxx
00002 // Created by:  drose (31Oct00)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "cvsSourceDirectory.h"
00016 #include "cvsSourceTree.h"
00017 #include "string_utils.h"
00018 
00019 #include "pnotify.h"
00020 
00021 ////////////////////////////////////////////////////////////////////
00022 //     Function: CVSSourceDirectory::Constructor
00023 //       Access: Public
00024 //  Description:
00025 ////////////////////////////////////////////////////////////////////
00026 CVSSourceDirectory::
00027 CVSSourceDirectory(CVSSourceTree *tree, CVSSourceDirectory *parent,
00028                    const string &dirname) :
00029   _tree(tree),
00030   _parent(parent),
00031   _dirname(dirname)
00032 {
00033   if (_parent == (CVSSourceDirectory *)NULL) {
00034     _depth = 0;
00035   } else {
00036     _depth = _parent->_depth + 1;
00037   }
00038 }
00039 
00040 ////////////////////////////////////////////////////////////////////
00041 //     Function: CVSSourceDirectory::Destructor
00042 //       Access: Public
00043 //  Description:
00044 ////////////////////////////////////////////////////////////////////
00045 CVSSourceDirectory::
00046 ~CVSSourceDirectory() {
00047   Children::iterator ci;
00048   for (ci = _children.begin(); ci != _children.end(); ++ci) {
00049     delete (*ci);
00050   }
00051 }
00052 
00053 ////////////////////////////////////////////////////////////////////
00054 //     Function: CVSSourceDirectory::get_dirname
00055 //       Access: Public
00056 //  Description: Returns the local name of this particular directory.
00057 ////////////////////////////////////////////////////////////////////
00058 string CVSSourceDirectory::
00059 get_dirname() const {
00060   return _dirname;
00061 }
00062 
00063 ////////////////////////////////////////////////////////////////////
00064 //     Function: CVSSourceDirectory::get_fullpath
00065 //       Access: Public
00066 //  Description: Returns the full pathname to this particular
00067 //               directory.
00068 ////////////////////////////////////////////////////////////////////
00069 Filename CVSSourceDirectory::
00070 get_fullpath() const {
00071   if (_parent == (CVSSourceDirectory *)NULL) {
00072     return _tree->get_root_fullpath();
00073   }
00074   return Filename(_parent->get_fullpath(), _dirname);
00075 }
00076 
00077 ////////////////////////////////////////////////////////////////////
00078 //     Function: CVSSourceDirectory::get_path
00079 //       Access: Public
00080 //  Description: Returns the relative pathname to this particular
00081 //               directory, as seen from the root of the tree.
00082 ////////////////////////////////////////////////////////////////////
00083 Filename CVSSourceDirectory::
00084 get_path() const {
00085   if (_parent == (CVSSourceDirectory *)NULL) {
00086     return _dirname;
00087   }
00088   return Filename(_parent->get_path(), _dirname);
00089 }
00090 
00091 ////////////////////////////////////////////////////////////////////
00092 //     Function: CVSSourceDirectory::get_rel_to
00093 //       Access: Public
00094 //  Description: Returns the relative path to the other directory from
00095 //               this one.  This does not include a trailing slash.
00096 ////////////////////////////////////////////////////////////////////
00097 Filename CVSSourceDirectory::
00098 get_rel_to(const CVSSourceDirectory *other) const {
00099   const CVSSourceDirectory *a = this;
00100   const CVSSourceDirectory *b = other;
00101 
00102   if (a == b) {
00103     return ".";
00104   }
00105 
00106   string prefix, postfix;
00107   while (a->_depth > b->_depth) {
00108     prefix += "../";
00109     a = a->_parent;
00110     nassertr(a != (CVSSourceDirectory *)NULL, string());
00111   }
00112 
00113   while (b->_depth > a->_depth) {
00114     postfix = b->_dirname + "/" + postfix;
00115     b = b->_parent;
00116     nassertr(b != (CVSSourceDirectory *)NULL, string());
00117   }
00118 
00119   while (a != b) {
00120     prefix += "../";
00121     postfix = b->_dirname + "/" + postfix;
00122     a = a->_parent;
00123     b = b->_parent;
00124     nassertr(a != (CVSSourceDirectory *)NULL, string());
00125     nassertr(b != (CVSSourceDirectory *)NULL, string());
00126   }
00127 
00128   string result = prefix + postfix;
00129   nassertr(!result.empty(), string());
00130   return result.substr(0, result.length() - 1);
00131 }
00132 
00133 ////////////////////////////////////////////////////////////////////
00134 //     Function: CVSSourceDirectory::get_num_children
00135 //       Access: Public
00136 //  Description: Returns the number of subdirectories below this
00137 //               directory.
00138 ////////////////////////////////////////////////////////////////////
00139 int CVSSourceDirectory::
00140 get_num_children() const {
00141   return _children.size();
00142 }
00143 
00144 ////////////////////////////////////////////////////////////////////
00145 //     Function: CVSSourceDirectory::get_child
00146 //       Access: Public
00147 //  Description: Returns the nth subdirectory below this directory.
00148 ////////////////////////////////////////////////////////////////////
00149 CVSSourceDirectory *CVSSourceDirectory::
00150 get_child(int n) const {
00151   nassertr(n >= 0 && n < (int)_children.size(), NULL);
00152   return _children[n];
00153 }
00154 
00155 ////////////////////////////////////////////////////////////////////
00156 //     Function: CVSSourceDirectory::find_relpath
00157 //       Access: Public
00158 //  Description: Returns the source directory that corresponds to the
00159 //               given relative path from this directory, or NULL if
00160 //               there is no match.
00161 ////////////////////////////////////////////////////////////////////
00162 CVSSourceDirectory *CVSSourceDirectory::
00163 find_relpath(const string &relpath) {
00164   if (relpath.empty()) {
00165     return this;
00166   }
00167 
00168   size_t slash = relpath.find('/');
00169   string first = relpath.substr(0, slash);
00170   string rest;
00171   if (slash != string::npos) {
00172     rest = relpath.substr(slash + 1);
00173   }
00174 
00175   if (first.empty() || first == ".") {
00176     return find_relpath(rest);
00177 
00178   } else if (first == "..") {
00179     if (_parent != NULL) {
00180       return _parent->find_relpath(rest);
00181     }
00182     // Tried to back out past the root directory.
00183     return (CVSSourceDirectory *)NULL;
00184   }
00185 
00186   // Check for a child with the name indicated by first.
00187   Children::const_iterator ci;
00188   for (ci = _children.begin(); ci != _children.end(); ++ci) {
00189     if (cmp_nocase((*ci)->get_dirname(), first) == 0) {
00190       return (*ci)->find_relpath(rest);
00191     }
00192   }
00193 
00194   // No match.
00195   return (CVSSourceDirectory *)NULL;
00196 }
00197 
00198 ////////////////////////////////////////////////////////////////////
00199 //     Function: CVSSourceDirectory::find_dirname
00200 //       Access: Public
00201 //  Description: Returns the source directory that corresponds to the
00202 //               given local directory name, or NULL if there is no
00203 //               match.
00204 ////////////////////////////////////////////////////////////////////
00205 CVSSourceDirectory *CVSSourceDirectory::
00206 find_dirname(const string &dirname) {
00207   if (cmp_nocase(dirname, _dirname) == 0) {
00208     return this;
00209   }
00210 
00211   Children::const_iterator ci;
00212   for (ci = _children.begin(); ci != _children.end(); ++ci) {
00213     CVSSourceDirectory *result = (*ci)->find_dirname(dirname);
00214     if (result != (CVSSourceDirectory *)NULL) {
00215       return result;
00216     }
00217   }
00218 
00219   return (CVSSourceDirectory *)NULL;
00220 }
00221 
00222 ////////////////////////////////////////////////////////////////////
00223 //     Function: CVSSourceDirectory::scan
00224 //       Access: Public
00225 //  Description: Recursively scans the contents of the source
00226 //               directory.  Fullpath is the full path name to the
00227 //               directory; key_filename is the name of a file that
00228 //               must exist in each subdirectory for it to be
00229 //               considered part of the hierarchy.  Returns true on
00230 //               success, false on failure.
00231 ////////////////////////////////////////////////////////////////////
00232 bool CVSSourceDirectory::
00233 scan(const Filename &directory, const string &key_filename) {
00234   vector_string contents;
00235   if (!directory.scan_directory(contents)) {
00236     nout << "Unable to scan directory " << directory << "\n";
00237     return false;
00238   }
00239 
00240   vector_string::const_iterator fi;
00241   for (fi = contents.begin(); fi != contents.end(); ++fi) {
00242     const string &basename = (*fi);
00243 
00244     // Is this possibly a subdirectory name?
00245     Filename next_path(directory, basename);
00246     Filename key(next_path, key_filename);
00247 
00248     if (key.exists()) {
00249       CVSSourceDirectory *subdir =
00250         new CVSSourceDirectory(_tree, this, basename);
00251       _children.push_back(subdir);
00252 
00253       if (!subdir->scan(next_path, key_filename)) {
00254         return false;
00255       }
00256 
00257     } else {
00258       // It's not a subdirectory; call it a regular file.
00259       _tree->add_file(basename, this);
00260     }
00261   }
00262 
00263   return true;
00264 }
 All Classes Functions Variables Enumerations