Panda3D
cvsSourceDirectory.cxx
1 // Filename: cvsSourceDirectory.cxx
2 // Created by: drose (31Oct00)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "cvsSourceDirectory.h"
16 #include "cvsSourceTree.h"
17 #include "string_utils.h"
18 
19 #include "pnotify.h"
20 
21 ////////////////////////////////////////////////////////////////////
22 // Function: CVSSourceDirectory::Constructor
23 // Access: Public
24 // Description:
25 ////////////////////////////////////////////////////////////////////
26 CVSSourceDirectory::
27 CVSSourceDirectory(CVSSourceTree *tree, CVSSourceDirectory *parent,
28  const string &dirname) :
29  _tree(tree),
30  _parent(parent),
31  _dirname(dirname)
32 {
33  if (_parent == (CVSSourceDirectory *)NULL) {
34  _depth = 0;
35  } else {
36  _depth = _parent->_depth + 1;
37  }
38 }
39 
40 ////////////////////////////////////////////////////////////////////
41 // Function: CVSSourceDirectory::Destructor
42 // Access: Public
43 // Description:
44 ////////////////////////////////////////////////////////////////////
45 CVSSourceDirectory::
46 ~CVSSourceDirectory() {
47  Children::iterator ci;
48  for (ci = _children.begin(); ci != _children.end(); ++ci) {
49  delete (*ci);
50  }
51 }
52 
53 ////////////////////////////////////////////////////////////////////
54 // Function: CVSSourceDirectory::get_dirname
55 // Access: Public
56 // Description: Returns the local name of this particular directory.
57 ////////////////////////////////////////////////////////////////////
59 get_dirname() const {
60  return _dirname;
61 }
62 
63 ////////////////////////////////////////////////////////////////////
64 // Function: CVSSourceDirectory::get_fullpath
65 // Access: Public
66 // Description: Returns the full pathname to this particular
67 // directory.
68 ////////////////////////////////////////////////////////////////////
70 get_fullpath() const {
71  if (_parent == (CVSSourceDirectory *)NULL) {
72  return _tree->get_root_fullpath();
73  }
74  return Filename(_parent->get_fullpath(), _dirname);
75 }
76 
77 ////////////////////////////////////////////////////////////////////
78 // Function: CVSSourceDirectory::get_path
79 // Access: Public
80 // Description: Returns the relative pathname to this particular
81 // directory, as seen from the root of the tree.
82 ////////////////////////////////////////////////////////////////////
84 get_path() const {
85  if (_parent == (CVSSourceDirectory *)NULL) {
86  return _dirname;
87  }
88  return Filename(_parent->get_path(), _dirname);
89 }
90 
91 ////////////////////////////////////////////////////////////////////
92 // Function: CVSSourceDirectory::get_rel_to
93 // Access: Public
94 // Description: Returns the relative path to the other directory from
95 // this one. This does not include a trailing slash.
96 ////////////////////////////////////////////////////////////////////
98 get_rel_to(const CVSSourceDirectory *other) const {
99  const CVSSourceDirectory *a = this;
100  const CVSSourceDirectory *b = other;
101 
102  if (a == b) {
103  return ".";
104  }
105 
106  string prefix, postfix;
107  while (a->_depth > b->_depth) {
108  prefix += "../";
109  a = a->_parent;
110  nassertr(a != (CVSSourceDirectory *)NULL, string());
111  }
112 
113  while (b->_depth > a->_depth) {
114  postfix = b->_dirname + "/" + postfix;
115  b = b->_parent;
116  nassertr(b != (CVSSourceDirectory *)NULL, string());
117  }
118 
119  while (a != b) {
120  prefix += "../";
121  postfix = b->_dirname + "/" + postfix;
122  a = a->_parent;
123  b = b->_parent;
124  nassertr(a != (CVSSourceDirectory *)NULL, string());
125  nassertr(b != (CVSSourceDirectory *)NULL, string());
126  }
127 
128  string result = prefix + postfix;
129  nassertr(!result.empty(), string());
130  return result.substr(0, result.length() - 1);
131 }
132 
133 ////////////////////////////////////////////////////////////////////
134 // Function: CVSSourceDirectory::get_num_children
135 // Access: Public
136 // Description: Returns the number of subdirectories below this
137 // directory.
138 ////////////////////////////////////////////////////////////////////
141  return _children.size();
142 }
143 
144 ////////////////////////////////////////////////////////////////////
145 // Function: CVSSourceDirectory::get_child
146 // Access: Public
147 // Description: Returns the nth subdirectory below this directory.
148 ////////////////////////////////////////////////////////////////////
150 get_child(int n) const {
151  nassertr(n >= 0 && n < (int)_children.size(), NULL);
152  return _children[n];
153 }
154 
155 ////////////////////////////////////////////////////////////////////
156 // Function: CVSSourceDirectory::find_relpath
157 // Access: Public
158 // Description: Returns the source directory that corresponds to the
159 // given relative path from this directory, or NULL if
160 // there is no match.
161 ////////////////////////////////////////////////////////////////////
163 find_relpath(const string &relpath) {
164  if (relpath.empty()) {
165  return this;
166  }
167 
168  size_t slash = relpath.find('/');
169  string first = relpath.substr(0, slash);
170  string rest;
171  if (slash != string::npos) {
172  rest = relpath.substr(slash + 1);
173  }
174 
175  if (first.empty() || first == ".") {
176  return find_relpath(rest);
177 
178  } else if (first == "..") {
179  if (_parent != NULL) {
180  return _parent->find_relpath(rest);
181  }
182  // Tried to back out past the root directory.
183  return (CVSSourceDirectory *)NULL;
184  }
185 
186  // Check for a child with the name indicated by first.
187  Children::const_iterator ci;
188  for (ci = _children.begin(); ci != _children.end(); ++ci) {
189  if (cmp_nocase((*ci)->get_dirname(), first) == 0) {
190  return (*ci)->find_relpath(rest);
191  }
192  }
193 
194  // No match.
195  return (CVSSourceDirectory *)NULL;
196 }
197 
198 ////////////////////////////////////////////////////////////////////
199 // Function: CVSSourceDirectory::find_dirname
200 // Access: Public
201 // Description: Returns the source directory that corresponds to the
202 // given local directory name, or NULL if there is no
203 // match.
204 ////////////////////////////////////////////////////////////////////
206 find_dirname(const string &dirname) {
207  if (cmp_nocase(dirname, _dirname) == 0) {
208  return this;
209  }
210 
211  Children::const_iterator ci;
212  for (ci = _children.begin(); ci != _children.end(); ++ci) {
213  CVSSourceDirectory *result = (*ci)->find_dirname(dirname);
214  if (result != (CVSSourceDirectory *)NULL) {
215  return result;
216  }
217  }
218 
219  return (CVSSourceDirectory *)NULL;
220 }
221 
222 ////////////////////////////////////////////////////////////////////
223 // Function: CVSSourceDirectory::scan
224 // Access: Public
225 // Description: Recursively scans the contents of the source
226 // directory. Fullpath is the full path name to the
227 // directory; key_filename is the name of a file that
228 // must exist in each subdirectory for it to be
229 // considered part of the hierarchy. Returns true on
230 // success, false on failure.
231 ////////////////////////////////////////////////////////////////////
233 scan(const Filename &directory, const string &key_filename) {
234  vector_string contents;
235  if (!directory.scan_directory(contents)) {
236  nout << "Unable to scan directory " << directory << "\n";
237  return false;
238  }
239 
240  vector_string::const_iterator fi;
241  for (fi = contents.begin(); fi != contents.end(); ++fi) {
242  const string &basename = (*fi);
243 
244  // Is this possibly a subdirectory name?
245  Filename next_path(directory, basename);
246  Filename key(next_path, key_filename);
247 
248  if (key.exists()) {
249  CVSSourceDirectory *subdir =
250  new CVSSourceDirectory(_tree, this, basename);
251  _children.push_back(subdir);
252 
253  if (!subdir->scan(next_path, key_filename)) {
254  return false;
255  }
256 
257  } else {
258  // It's not a subdirectory; call it a regular file.
259  _tree->add_file(basename, this);
260  }
261  }
262 
263  return true;
264 }
CVSSourceDirectory * find_dirname(const string &dirname)
Returns the source directory that corresponds to the given local directory name, or NULL if there is ...
int get_num_children() const
Returns the number of subdirectories below this directory.
Filename get_root_fullpath()
Returns the full path from the root to the top of the source hierarchy.
CVSSourceDirectory * find_relpath(const string &relpath)
Returns the source directory that corresponds to the given relative path from this directory...
string get_dirname() const
Returns the local name of this particular directory.
Filename get_rel_to(const CVSSourceDirectory *other) const
Returns the relative path to the other directory from this one.
Filename get_path() const
Returns the relative pathname to this particular directory, as seen from the root of the tree...
Filename get_fullpath() const
Returns the full pathname to this particular directory.
This represents one particular directory in the hierarchy of source directory files.
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:44
This represents the root of the tree of source directory files.
Definition: cvsSourceTree.h:39
void add_file(const string &basename, CVSSourceDirectory *dir)
Adds a new file to the set of known files.
bool scan_directory(vector_string &contents) const
Attempts to open the named filename as if it were a directory and looks for the non-hidden files with...
Definition: filename.cxx:1854
CVSSourceDirectory * get_child(int n) const
Returns the nth subdirectory below this directory.
bool scan(const Filename &directory, const string &key_filename)
Recursively scans the contents of the source directory.
bool exists() const
Returns true if the filename exists on the disk, false otherwise.
Definition: filename.cxx:1356