*** empty log message ***

This commit is contained in:
David Rose 2000-11-28 05:58:15 +00:00
parent c4467222e0
commit 9d3475c77b
4 changed files with 390 additions and 314 deletions

View File

@ -35,11 +35,6 @@ SoftCVS() {
clear_runlines(); clear_runlines();
add_runline("[opts]"); add_runline("[opts]");
add_option
("i", "", 80,
"Prompt the user for confirmation before every operation.",
&SoftCVS::dispatch_none, &_interactive);
add_option add_option
("nc", "", 80, ("nc", "", 80,
"Do not attempt to add newly-created files to CVS. The default " "Do not attempt to add newly-created files to CVS. The default "
@ -79,30 +74,61 @@ run() {
exit(1); exit(1);
} }
// Begin the traversal. // Scan all the files in the database.
traverse("."); traverse_root();
// Now consider adjusting the scene files. // Collapse out the higher-versioned scene files.
set<string>::iterator si; collapse_scene_files();
for (si = _scene_files.begin(); si != _scene_files.end(); ++si) {
consider_scene_file(*si); // Now determine which element files are actually referenced by at
// least one of the scene files.
count_references();
// Finally, remove all the element files that are no longer
// referenced by any scenes.
remove_unused_elements();
// Now do all the cvs adding and removing we need.
if (!_no_cvs) {
cvs_add_or_remove("remove", _cvs_remove);
cvs_add_or_remove("add", _cvs_add);
} }
// Finally, add everything to CVS that needs to be added. We do
// this all at once at the end, instead of one at a time as we
// encounter each file, to speed things up a bit.
cvs_add_all();
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: SoftCVS::traverse // Function: SoftCVS::traverse_root
// Access: Private // Access: Private
// Description: Reads the directory indicated by prefix, looking for // Description: Reads all of the toplevel directory names,
// files that are named something like *.2-0.ext, // e.g. SCENES, MATERIALS, etc., and traverses them.
// and renames these to *.1-0.ext.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void SoftCVS:: void SoftCVS::
traverse(const Filename &directory) { traverse_root() {
Filename root(".");
// Get the list of subdirectories.
vector_string subdirs;
if (!root.scan_directory(subdirs)) {
nout << "Unable to scan directory.\n";
return;
}
vector_string::const_iterator di;
for (di = subdirs.begin(); di != subdirs.end(); ++di) {
Filename subdir = (*di);
if (subdir.is_directory() && subdir != "CVS") {
traverse_subdir(subdir);
}
}
}
////////////////////////////////////////////////////////////////////
// Function: SoftCVS::traverse_subdir
// Access: Private
// Description: Reads the directory indicated by prefix and
// identifies all of the SoftImage files stored there.
////////////////////////////////////////////////////////////////////
void SoftCVS::
traverse_subdir(const Filename &directory) {
// Get the list of files in the directory. // Get the list of files in the directory.
vector_string files; vector_string files;
if (!directory.scan_directory(files)) { if (!directory.scan_directory(files)) {
@ -118,74 +144,156 @@ traverse(const Filename &directory) {
in_cvs = scan_cvs(directory, cvs_elements); in_cvs = scan_cvs(directory, cvs_elements);
} }
// Now go through and identify files with version numbers, and bool is_scenes = false;
// collect together those files that are different versions of the bool keep_all = false;
// same file.
vector<SoftFilename> versions; // Now make some special-case behavior based on the particular
// SoftImage subdirectory we're in.
string dirname = directory.get_basename();
if (dirname == "SCENES") {
is_scenes = true;
} else if (dirname == "PICTURES") {
// In the pictures directory, we must keep everything, since the
// scene files don't explicitly reference these but they're still
// important. Textures that are no longer used will pile up; we
// leave this is as the user's problem.
keep_all = true;
}
vector_string::const_iterator fi; vector_string::const_iterator fi;
for (fi = files.begin(); fi != files.end(); ++fi) { for (fi = files.begin(); fi != files.end(); ++fi) {
const string &filename = (*fi); const string &filename = (*fi);
if (!filename.empty() && filename[0] != '.' && if (filename == "CVS") {
!(filename == "CVS")) { // This special filename is not to be considered.
SoftFilename v(filename);
if (v.has_version()) { } else if (filename == "Chapter.rsrc") {
versions.push_back(v); // This special filename should not be considered, except to add
// it to CVS.
if (in_cvs && cvs_elements.count(filename) == 0) {
_cvs_add.push_back(Filename(directory, filename));
}
} else {
SoftFilename soft(directory, filename);
if (in_cvs && cvs_elements.count(filename) != 0) {
// This file is known to be in CVS.
soft.set_in_cvs(true);
}
if (keep_all) {
soft.increment_use_count();
}
if (is_scenes && soft.has_version() && soft.get_extension() == ".dsc") {
_scene_files.push_back(soft);
} else { } else {
// Maybe this is a subdirectory? _element_files.insert(soft);
Filename subdir(directory, filename);
if (subdir.is_directory()) {
traverse(subdir);
} else {
// No, not a subdirectory; maybe a regular file that needs
// to get added to CVS?
if (in_cvs) {
consider_add_cvs(directory, filename, cvs_elements);
}
}
} }
} }
} }
}
if (!versions.empty()) { ////////////////////////////////////////////////////////////////////
// Now sort the versioned filenames in order so we can scan for // Function: SoftCVS::collapse_scene_files
// higher versions. // Access: Private
sort(versions.begin(), versions.end()); // Description: Walks through the list of scene files found, and
// renames the higher-versioned ones to version 1-0,
// removing the intervening versions.
////////////////////////////////////////////////////////////////////
void SoftCVS::
collapse_scene_files() {
// Get a copy of the scene files vector so we can modify it. Also
// empty out the _scene_files at the same time so we can fill it up
// again.
SceneFiles versions;
versions.swap(_scene_files);
vector<SoftFilename>::iterator vi; // And sort them into order so we can easily compare higher and
vi = versions.begin(); // lower versions.
while (vi != versions.end()) { sort(versions.begin(), versions.end());
SoftFilename &file = (*vi);
_versioned_files.insert(file.get_base());
if (!file.is_1_0()) { SceneFiles::iterator vi;
// Here's a file that needs to be renamed. But first, identify vi = versions.begin();
// all the other versions of the same file. while (vi != versions.end()) {
vector<SoftFilename>::iterator start_vi; SoftFilename &file = (*vi);
start_vi = vi;
while (vi != versions.end() && (*vi).is_same_file(file)) {
++vi;
}
if (rename_file(directory, start_vi, vi)) { if (!file.is_1_0()) {
if (in_cvs) { // Here's a file that needs to be renamed. But first, identify
consider_add_cvs(directory, file.get_1_0_filename(), cvs_elements); // all the other versions of the same file.
} SceneFiles::iterator start_vi;
start_vi = vi;
if (file.get_extension() == ".dsc") { while (vi != versions.end() && (*vi).is_same_file(file)) {
_scene_files.insert(Filename(directory, file.get_1_0_filename()));
}
}
} else {
if (in_cvs) {
consider_add_cvs(directory, file.get_filename(), cvs_elements);
}
if (file.get_extension() == ".dsc") {
_scene_files.insert(Filename(directory, file.get_filename()));
}
++vi; ++vi;
} }
rename_file(start_vi, vi);
} else {
++vi;
}
file.make_1_0();
_scene_files.push_back(file);
}
}
////////////////////////////////////////////////////////////////////
// Function: SoftCVS::count_references
// Access: Private
// Description: Walks through the list of scene files and looks for
// the set of element files referenced by the scene
// file. Also add the scene files to CVS if warranted.
////////////////////////////////////////////////////////////////////
void SoftCVS::
count_references() {
SceneFiles::const_iterator vi;
for (vi = _scene_files.begin(); vi != _scene_files.end(); ++vi) {
const SoftFilename &sf = (*vi);
Filename file(sf.get_dirname(), sf.get_filename());
if (!sf.get_in_cvs()) {
_cvs_add.push_back(file);
}
file.set_text();
ifstream in;
if (!file.open_read(in)) {
nout << "Unable to read " << file << "\n";
} else {
nout << "Scanning " << file << "\n";
scan_scene_file(in);
}
}
}
////////////////////////////////////////////////////////////////////
// Function: SoftCVS::remove_unused_elements
// Access: Private
// Description: Remove all the element files that weren't referenced
// by any scene file. Also plan to cvs add all those
// that were referenced.
////////////////////////////////////////////////////////////////////
void SoftCVS::
remove_unused_elements() {
ElementFiles::const_iterator fi;
for (fi = _element_files.begin(); fi != _element_files.end(); ++fi) {
const SoftFilename &sf = (*fi);
Filename file(sf.get_dirname(), sf.get_filename());
if (sf.get_use_count() == 0) {
nout << file << " is unused.\n";
if (!file.unlink()) {
nout << "Unable to remove " << file << ".\n";
} else if (sf.get_in_cvs()) {
_cvs_remove.push_back(file);
}
} else if (!sf.get_in_cvs()) {
_cvs_add.push_back(file);
} }
} }
} }
@ -200,18 +308,20 @@ traverse(const Filename &directory) {
// false otherwise. // false otherwise.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
bool SoftCVS:: bool SoftCVS::
rename_file(const string &dirname, rename_file(SoftCVS::SceneFiles::iterator begin,
vector<SoftFilename>::const_iterator begin, SoftCVS::SceneFiles::iterator end) {
vector<SoftFilename>::const_iterator end) {
int length = end - begin; int length = end - begin;
nassertr(length > 0, false); nassertr(length > 0, false);
string source_filename = (*begin).get_filename(); SoftFilename &orig = (*begin);
string dest_filename = (*begin).get_1_0_filename();
string dirname = orig.get_dirname();
string source_filename = orig.get_filename();
string dest_filename = orig.get_1_0_filename();
if (length > 2) { if (length > 2) {
nout << source_filename << " supercedes:\n"; nout << source_filename << " supercedes:\n";
vector<SoftFilename>::const_iterator p; SceneFiles::const_iterator p;
for (p = begin + 1; p != end; ++p) { for (p = begin + 1; p != end; ++p) {
nout << " " << (*p).get_filename() << "\n"; nout << " " << (*p).get_filename() << "\n";
} }
@ -221,36 +331,44 @@ rename_file(const string &dirname,
<< (*(begin + 1)).get_filename() << ".\n"; << (*(begin + 1)).get_filename() << ".\n";
} else { } else {
if (_interactive) { nout << source_filename << " renamed.\n";
nout << source_filename << " needs renaming.\n";
} else {
nout << source_filename << " renamed.\n";
}
}
if (_interactive) {
if (!prompt_yesno("Rename this file (y/n)? ")) {
return false;
}
} }
// Now remove all of the "wrong" files. // Now remove all of the "wrong" files.
vector<SoftFilename>::const_iterator p;
bool cvs_has_1_0 = false;
SceneFiles::const_iterator p;
for (p = begin + 1; p != end; ++p) { for (p = begin + 1; p != end; ++p) {
Filename file = dirname + "/" + (*p).get_filename(); Filename file((*p).get_dirname(), (*p).get_filename());
if (!file.unlink()) { if (!file.unlink()) {
nout << "Unable to remove " << file << ".\n"; nout << "Unable to remove " << file << ".\n";
} else if ((*p).is_1_0()) {
cvs_has_1_0 = true;
// We don't cvs remove the 1.0 version.
} else {
_cvs_remove.push_back(file);
} }
} }
// And rename the good one. // And rename the good one.
Filename source = dirname + "/" + source_filename; Filename source(dirname, source_filename);
Filename dest = dirname + "/" + dest_filename; Filename dest(dirname, dest_filename);
if (!source.rename_to(dest)) { if (!source.rename_to(dest)) {
nout << "Unable to rename " << source << " to " << dest_filename << ".\n"; nout << "Unable to rename " << source << " to " << dest_filename << ".\n";
exit(1); exit(1);
} }
if (orig.get_in_cvs()) {
// We do have to cvs remove the old one.
_cvs_remove.push_back(source);
}
if (!cvs_has_1_0) {
// And we have to cvs add the new one.
_cvs_add.push_back(dest);
}
return true; return true;
} }
@ -267,13 +385,6 @@ scan_cvs(const string &dirname, set<string> &cvs_elements) {
Filename cvs_entries = dirname + "/CVS/Entries"; Filename cvs_entries = dirname + "/CVS/Entries";
if (!cvs_entries.exists()) { if (!cvs_entries.exists()) {
// Try to CVSify the directory. // Try to CVSify the directory.
if (_interactive) {
nout << "Directory " << dirname << " is not CVS-controlled.\n";
if (!prompt_yesno("Add the directory to CVS (y/n)? ")) {
return false;
}
}
if (!cvs_add(dirname)) { if (!cvs_add(dirname)) {
return false; return false;
} }
@ -282,7 +393,7 @@ scan_cvs(const string &dirname, set<string> &cvs_elements) {
ifstream in; ifstream in;
cvs_entries.set_text(); cvs_entries.set_text();
if (!cvs_entries.open_read(in)) { if (!cvs_entries.open_read(in)) {
cerr << "Unable to read CVS directory.\n"; nout << "Unable to read CVS directory.\n";
return true; return true;
} }
@ -293,7 +404,14 @@ scan_cvs(const string &dirname, set<string> &cvs_elements) {
size_t slash = line.find('/', 1); size_t slash = line.find('/', 1);
if (slash != string::npos) { if (slash != string::npos) {
string filename = line.substr(1, slash - 1); string filename = line.substr(1, slash - 1);
cvs_elements.insert(filename);
if (line.substr(slash + 1, 2) == "-1") {
// If the first number after the slash is -1, the file used
// to be here but was recently cvs removed. It counts as no
// longer being an element.
} else {
cvs_elements.insert(filename);
}
} }
} }
@ -303,102 +421,20 @@ scan_cvs(const string &dirname, set<string> &cvs_elements) {
return true; return true;
} }
////////////////////////////////////////////////////////////////////
// Function: SoftCVS::consider_add_cvs
// Access: Private
// Description: Considers adding the indicated file to the CVS
// repository, if it is not already there.
////////////////////////////////////////////////////////////////////
void SoftCVS::
consider_add_cvs(const string &dirname, const string &filename,
const set<string> &cvs_elements) {
if (cvs_elements.count(filename) != 0) {
// Already in CVS!
return;
}
string path = dirname + "/" + filename;
if (_interactive) {
if (!prompt_yesno("Add " + path + " to CVS (y/n)? ")) {
return;
}
}
_cvs_paths.push_back(path);
}
////////////////////////////////////////////////////////////////////
// Function: SoftCVS::consider_scene_file
// Access: Private
// Description: Checks to see if the indicated file is a scene file,
// and that it contains references to a higher-version
// filename. If so, offers to adjust it.
////////////////////////////////////////////////////////////////////
void SoftCVS::
consider_scene_file(Filename path) {
path.set_text();
ifstream in;
if (!path.open_read(in)) {
nout << "Could not read " << path << ".\n";
return;
}
// Scan the scene file into memory.
ostringstream scene;
if (!scan_scene_file(in, scene)) {
// The scene file doesn't need to change.
return;
}
// The scene file should change.
if (_interactive) {
nout << "Scene file " << path << " needs to be updated.\n";
if (!prompt_yesno("Modify this file (y/n)? ")) {
return;
}
}
// Rewrite the scene file.
in.close();
path.unlink();
ofstream out;
if (!path.open_write(out)) {
nout << "Could not write " << path << ".\n";
return;
}
string data = scene.str();
out.write(data.data(), data.length());
if (out.fail()) {
nout << "Error writing " << path << ".\n";
return;
}
nout << "Updated scene file " << path << ".\n";
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: SoftCVS::scan_scene_file // Function: SoftCVS::scan_scene_file
// Access: Private // Access: Private
// Description: Copies a scene file from the input stream to the // Description: Copies a scene file from the input stream to the
// output stream, looking for stale file references // output stream, looking for references to element
// (i.e. filenames whose version number is greater than // files. For each reference found, increments the
// 1-0). If any such filenames are found, replaces them // appropriate element file's reference count.
// with the equivalent 1-0 filename, and returns true;
// otherwise, returns false.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
bool SoftCVS:: void SoftCVS::
scan_scene_file(istream &in, ostream &out) { scan_scene_file(istream &in) {
bool any_changed = false; int c = in.get();
int c;
c = in.get();
while (!in.eof() && !in.fail()) { while (!in.eof() && !in.fail()) {
// Skip whitespace. // Skip whitespace.
while (isspace(c) && !in.eof() && !in.fail()) { while (isspace(c) && !in.eof() && !in.fail()) {
out.put(c);
c = in.get(); c = in.get();
} }
@ -410,23 +446,22 @@ scan_scene_file(istream &in, ostream &out) {
} }
if (!word.empty()) { if (!word.empty()) {
// Here's the name of a "versioned" element. Should we rename SoftFilename v("", word);
// it? Only if the version is not 1-0, and this kind of element
// is versioned by filename. (Some elements are not versioned // Increment the use count on all matching elements of the multiset.
// by filename; instead, they keep the same filename but store pair<set<SoftFilename>::iterator, set<SoftFilename>::iterator> range;
// multiple versions within themselves. Trouble.) range = _element_files.equal_range(v);
SoftFilename v(word);
if (v.has_version() && !v.is_1_0() && set<SoftFilename>::iterator ei;
_versioned_files.count(v.get_base()) != 0) { for (ei = range.first; ei != range.second; ++ei) {
out << v.get_1_0_filename(); // We cheat and get a non-const reference to the filename out
any_changed = true; // of the set. We can safely do this because incrementing the
} else { // use count won't change its position in the set.
out << word; SoftFilename &file = (SoftFilename &)(*ei);
file.increment_use_count();
} }
} }
} }
return any_changed;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -450,21 +485,21 @@ cvs_add(const string &path) {
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: SoftCVS::cvs_add_all // Function: SoftCVS::cvs_add_or_remove
// Access: Private // Access: Private
// Description: Invokes CVS to add all of the files in _cvs_paths to // Description: Invokes CVS to add (or remove) all of the files in
// the repository. Returns true on success, false on // the indicated vector. Returns true on success, false
// failure. // on failure.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
bool SoftCVS:: bool SoftCVS::
cvs_add_all() { cvs_add_or_remove(const string &cvs_command, const vector_string &paths) {
static const int max_command = 4096; static const int max_command = 4096;
if (!_cvs_paths.empty()) { if (!paths.empty()) {
string command = _cvs_binary + " add"; string command = _cvs_binary + " " + cvs_command;
vector_string::const_iterator pi; vector_string::const_iterator pi;
pi = _cvs_paths.begin(); pi = paths.begin();
while (pi != _cvs_paths.end()) { while (pi != paths.end()) {
const string &path = (*pi); const string &path = (*pi);
if ((int)command.length() + 1 + (int)path.length() >= max_command) { if ((int)command.length() + 1 + (int)path.length() >= max_command) {
@ -477,7 +512,7 @@ cvs_add_all() {
return false; return false;
} }
command = _cvs_binary + " add"; command = _cvs_binary + " " + cvs_command;
} }
command += ' '; command += ' ';
@ -496,62 +531,6 @@ cvs_add_all() {
return true; return true;
} }
////////////////////////////////////////////////////////////////////
// Function: SoftCVS::prompt_yesno
// Access: Private
// Description: Asks the user a yes-or-no question. Returns true if
// the answer is yes, false otherwise.
////////////////////////////////////////////////////////////////////
bool SoftCVS::
prompt_yesno(const string &message) {
while (true) {
string result = prompt(message);
nassertr(!result.empty(), false);
if (result.size() == 1) {
if (tolower(result[0]) == 'y') {
return true;
} else if (tolower(result[0]) == 'n') {
return false;
}
}
nout << "*** Invalid response: " << result << "\n\n";
}
}
////////////////////////////////////////////////////////////////////
// Function: SoftCVS::prompt
// Access: Private
// Description: Issues a prompt to the user and waits for a typed
// response. Returns the response (which will not be
// empty).
////////////////////////////////////////////////////////////////////
string SoftCVS::
prompt(const string &message) {
nout << flush;
while (true) {
cerr << message << flush;
string response;
getline(cin, response);
// Remove leading and trailing whitespace.
size_t p = 0;
while (p < response.length() && isspace(response[p])) {
p++;
}
size_t q = response.length();
while (q > p && isspace(response[q - 1])) {
q--;
}
if (q > p) {
return response.substr(p, q - p);
}
}
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
SoftCVS prog; SoftCVS prog;
prog.parse_command_line(argc, argv); prog.parse_command_line(argc, argv);

View File

@ -30,30 +30,32 @@ public:
void run(); void run();
private: private:
void traverse(const Filename &directory); typedef vector<SoftFilename> SceneFiles;
typedef multiset<SoftFilename> ElementFiles;
bool rename_file(const string &dirname, void traverse_root();
vector<SoftFilename>::const_iterator begin, void traverse_subdir(const Filename &directory);
vector<SoftFilename>::const_iterator end);
void collapse_scene_files();
void count_references();
void remove_unused_elements();
bool rename_file(SceneFiles::iterator begin, SceneFiles::iterator end);
bool scan_cvs(const string &dirname, set<string> &cvs_elements); bool scan_cvs(const string &dirname, set<string> &cvs_elements);
void consider_add_cvs(const string &dirname, const string &filename,
const set<string> &cvs_elements); void scan_scene_file(istream &in);
void consider_scene_file(Filename path);
bool scan_scene_file(istream &in, ostream &out);
bool cvs_add(const string &path); bool cvs_add(const string &path);
bool cvs_add_all(); bool cvs_add_or_remove(const string &cvs_command,
const vector_string &paths);
bool prompt_yesno(const string &message); SceneFiles _scene_files;
string prompt(const string &message); ElementFiles _element_files;
set<string> _scene_files; vector_string _cvs_add;
set<string> _versioned_files; vector_string _cvs_remove;
vector_string _cvs_paths;
protected: protected:
bool _interactive;
bool _no_cvs; bool _no_cvs;
string _cvs_binary; string _cvs_binary;
}; };

View File

@ -13,12 +13,17 @@
// Description: // Description:
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
SoftFilename:: SoftFilename::
SoftFilename(const string &filename) : SoftFilename(const string &dirname, const string &filename) :
_dirname(dirname),
_filename(filename) _filename(filename)
{ {
_has_version = false; _has_version = false;
_major = 0; _major = 0;
_minor = 0; _minor = 0;
_in_cvs = false;
_use_count = 0;
_base = _filename;
// Scan for a version number and an optional extension after each // Scan for a version number and an optional extension after each
// dot in the filename. // dot in the filename.
@ -56,12 +61,15 @@ SoftFilename(const string &filename) :
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
SoftFilename:: SoftFilename::
SoftFilename(const SoftFilename &copy) : SoftFilename(const SoftFilename &copy) :
_dirname(copy._dirname),
_filename(copy._filename), _filename(copy._filename),
_has_version(copy._has_version), _has_version(copy._has_version),
_base(copy._base), _base(copy._base),
_major(copy._major), _major(copy._major),
_minor(copy._minor), _minor(copy._minor),
_ext(copy._ext) _ext(copy._ext),
_in_cvs(copy._in_cvs),
_use_count(copy._use_count)
{ {
} }
@ -72,12 +80,26 @@ SoftFilename(const SoftFilename &copy) :
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void SoftFilename:: void SoftFilename::
operator = (const SoftFilename &copy) { operator = (const SoftFilename &copy) {
_dirname = copy._dirname;
_filename = copy._filename; _filename = copy._filename;
_has_version = copy._has_version; _has_version = copy._has_version;
_base = copy._base; _base = copy._base;
_major = copy._major; _major = copy._major;
_minor = copy._minor; _minor = copy._minor;
_ext = copy._ext; _ext = copy._ext;
_in_cvs = copy._in_cvs;
_use_count = copy._use_count;
}
////////////////////////////////////////////////////////////////////
// Function: SoftFilename::get_dirname
// Access: Public
// Description: Returns the name of the directory this file was
// found in.
////////////////////////////////////////////////////////////////////
const string &SoftFilename::
get_dirname() const {
return _dirname;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -184,6 +206,19 @@ is_1_0() const {
return (_major == 1 && _minor == 0); return (_major == 1 && _minor == 0);
} }
////////////////////////////////////////////////////////////////////
// Function: SoftFilename::make_1_0
// Access: Public
// Description: Makes this a 1_0 filename.
////////////////////////////////////////////////////////////////////
void SoftFilename::
make_1_0() {
_has_version = true;
_major = 1;
_minor = 0;
_filename = get_1_0_filename();
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: SoftFilename::is_same_file // Function: SoftFilename::is_same_file
// Access: Public // Access: Public
@ -200,31 +235,75 @@ is_same_file(const SoftFilename &other) const {
// Function: SoftFilename::Ordering operator // Function: SoftFilename::Ordering operator
// Access: Public // Access: Public
// Description: Puts filenames in order such that the files with the // Description: Puts filenames in order such that the files with the
// same base and extension are sorted together; and // same base are sorted together, ignoring extension;
// within files with the same base and exntension, files // and within files with the same base, files are sorted
// are sorted in decreasing version number order so that // in decreasing version number order so that the most
// the most recent version appears first. // recent version appears first.
//
// The ordering operator is only defined for files that
// have a version number.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
bool SoftFilename:: bool SoftFilename::
operator < (const SoftFilename &other) const { operator < (const SoftFilename &other) const {
nassertr(_has_version, false);
nassertr(other._has_version, false);
if (_base != other._base) { if (_base != other._base) {
return _base < other._base; return _base < other._base;
} }
if (_ext != other._ext) {
return _ext < other._ext; if (_has_version != other._has_version) {
// If one has a version and the other one doesn't, the one without
// a version comes first.
return _has_version < other._has_version;
} }
if (_major != other._major) {
return _major > other._major; if (_has_version) {
} if (_major != other._major) {
if (_minor != other._minor) { return _major > other._major;
return _minor > other._minor; }
if (_minor != other._minor) {
return _minor > other._minor;
}
} }
return false; return false;
} }
////////////////////////////////////////////////////////////////////
// Function: SoftFilename::set_in_cvs
// Access: Public
// Description: Sets the flag that indicates whether this file is
// known to be entered into the CVS database.
////////////////////////////////////////////////////////////////////
void SoftFilename::
set_in_cvs(bool in_cvs) {
_in_cvs = in_cvs;
}
////////////////////////////////////////////////////////////////////
// Function: SoftFilename::get_in_cvs
// Access: Public
// Description: Returns true if this file is known to be entered in
// the CVS database, false if it is not.
////////////////////////////////////////////////////////////////////
bool SoftFilename::
get_in_cvs() const {
return _in_cvs;
}
////////////////////////////////////////////////////////////////////
// Function: SoftFilename::increment_use_count
// Access: Public
// Description: Indicates that this filename is referenced by one
// more scene file.
////////////////////////////////////////////////////////////////////
void SoftFilename::
increment_use_count() {
_use_count++;
}
////////////////////////////////////////////////////////////////////
// Function: SoftFilename::get_use_count
// Access: Public
// Description: Returns the number of scene files that referenced
// this filename.
////////////////////////////////////////////////////////////////////
int SoftFilename::
get_use_count() const {
return _use_count;
}

View File

@ -11,15 +11,21 @@
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Class : SoftFilename // Class : SoftFilename
// Description : This encapsulates a SoftImage versioned filename, of // Description : This encapsulates a SoftImage versioned filename, of
// the form base.v-v.ext: it consists of a base, a major // the form base.v-v.ext: it consists of a directory
// and minor version number, and an optional extension. // name, a base, a major and minor version number, and
// an optional extension.
//
// It also keeps track of whether the named file has
// been added to CVS, and how many scene files it is
// referenced by,
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
class SoftFilename { class SoftFilename {
public: public:
SoftFilename(const string &filename); SoftFilename(const string &dirname, const string &filename);
SoftFilename(const SoftFilename &copy); SoftFilename(const SoftFilename &copy);
void operator = (const SoftFilename &copy); void operator = (const SoftFilename &copy);
const string &get_dirname() const;
const string &get_filename() const; const string &get_filename() const;
bool has_version() const; bool has_version() const;
@ -32,17 +38,27 @@ public:
string get_non_extension() const; string get_non_extension() const;
bool is_1_0() const; bool is_1_0() const;
void make_1_0();
bool is_same_file(const SoftFilename &other) const; bool is_same_file(const SoftFilename &other) const;
bool operator < (const SoftFilename &other) const; bool operator < (const SoftFilename &other) const;
void set_in_cvs(bool in_cvs);
bool get_in_cvs() const;
void increment_use_count();
int get_use_count() const;
private: private:
string _dirname;
string _filename; string _filename;
bool _has_version; bool _has_version;
string _base; string _base;
int _major; int _major;
int _minor; int _minor;
string _ext; string _ext;
bool _in_cvs;
int _use_count;
}; };
#endif #endif