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