Panda3D
|
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 }