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  */
125 get_num_children() const {
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 }
CVSSourceDirectory::get_child
CVSSourceDirectory * get_child(int n) const
Returns the nth subdirectory below this directory.
Definition: cvsSourceDirectory.cxx:133
Filename::scan_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
string_utils.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
cvsSourceTree.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Filename::exists
bool exists() const
Returns true if the filename exists on the disk, false otherwise.
Definition: filename.cxx:1267
CVSSourceDirectory::get_rel_to
Filename get_rel_to(const CVSSourceDirectory *other) const
Returns the relative path to the other directory from this one.
Definition: cvsSourceDirectory.cxx:86
CVSSourceDirectory::scan
bool scan(const Filename &directory, const std::string &key_filename)
Recursively scans the contents of the source directory.
Definition: cvsSourceDirectory.cxx:206
cvsSourceDirectory.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
CVSSourceDirectory::get_path
Filename get_path() const
Returns the relative pathname to this particular directory, as seen from the root of the tree.
Definition: cvsSourceDirectory.cxx:74
CVSSourceDirectory::get_fullpath
Filename get_fullpath() const
Returns the full pathname to this particular directory.
Definition: cvsSourceDirectory.cxx:62
pnotify.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
CVSSourceDirectory::get_num_children
int get_num_children() const
Returns the number of subdirectories below this directory.
Definition: cvsSourceDirectory.cxx:125
CVSSourceDirectory::find_dirname
CVSSourceDirectory * find_dirname(const std::string &dirname)
Returns the source directory that corresponds to the given local directory name, or NULL if there is ...
Definition: cvsSourceDirectory.cxx:183
CVSSourceDirectory
This represents one particular directory in the hierarchy of source directory files.
Definition: cvsSourceDirectory.h:35
CVSSourceDirectory::get_dirname
std::string get_dirname() const
Returns the local name of this particular directory.
Definition: cvsSourceDirectory.cxx:54
CVSSourceTree::get_root_fullpath
Filename get_root_fullpath()
Returns the full path from the root to the top of the source hierarchy.
Definition: cvsSourceTree.cxx:176
CVSSourceTree
This represents the root of the tree of source directory files.
Definition: cvsSourceTree.h:34
CVSSourceTree::add_file
void add_file(const std::string &basename, CVSSourceDirectory *dir)
Adds a new file to the set of known files.
Definition: cvsSourceTree.cxx:199
Filename
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
CVSSourceDirectory::find_relpath
CVSSourceDirectory * find_relpath(const std::string &relpath)
Returns the source directory that corresponds to the given relative path from this directory,...
Definition: cvsSourceDirectory.cxx:143