|
@@ -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.
|
|
|
|
|
- traverse(".");
|
|
|
|
|
|
|
+ // Scan all the files in the database.
|
|
|
|
|
+ traverse_root();
|
|
|
|
|
+
|
|
|
|
|
+ // Collapse out the higher-versioned scene files.
|
|
|
|
|
+ collapse_scene_files();
|
|
|
|
|
+
|
|
|
|
|
+ // 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 consider adjusting the scene files.
|
|
|
|
|
- set<string>::iterator si;
|
|
|
|
|
- for (si = _scene_files.begin(); si != _scene_files.end(); ++si) {
|
|
|
|
|
- consider_scene_file(*si);
|
|
|
|
|
|
|
+ // 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_root
|
|
|
|
|
+// Access: Private
|
|
|
|
|
+// Description: Reads all of the toplevel directory names,
|
|
|
|
|
+// e.g. SCENES, MATERIALS, etc., and traverses them.
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+void SoftCVS::
|
|
|
|
|
+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
|
|
|
|
|
|
|
+// Function: SoftCVS::traverse_subdir
|
|
|
// Access: Private
|
|
// Access: Private
|
|
|
-// Description: Reads the directory indicated by prefix, looking for
|
|
|
|
|
-// files that are named something like *.2-0.ext,
|
|
|
|
|
-// and renames these to *.1-0.ext.
|
|
|
|
|
|
|
+// Description: Reads the directory indicated by prefix and
|
|
|
|
|
+// identifies all of the SoftImage files stored there.
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
|
void SoftCVS::
|
|
void SoftCVS::
|
|
|
-traverse(const Filename &directory) {
|
|
|
|
|
|
|
+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
|
|
|
|
|
- // collect together those files that are different versions of the
|
|
|
|
|
- // same file.
|
|
|
|
|
- vector<SoftFilename> versions;
|
|
|
|
|
|
|
+ bool is_scenes = false;
|
|
|
|
|
+ bool keep_all = false;
|
|
|
|
|
+
|
|
|
|
|
+ // 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] != '.' &&
|
|
|
|
|
- !(filename == "CVS")) {
|
|
|
|
|
- SoftFilename v(filename);
|
|
|
|
|
- if (v.has_version()) {
|
|
|
|
|
- versions.push_back(v);
|
|
|
|
|
|
|
+ if (filename == "CVS") {
|
|
|
|
|
+ // This special filename is not to be considered.
|
|
|
|
|
+
|
|
|
|
|
+ } else if (filename == "Chapter.rsrc") {
|
|
|
|
|
+ // 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?
|
|
|
|
|
- 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);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ _element_files.insert(soft);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- if (!versions.empty()) {
|
|
|
|
|
- // Now sort the versioned filenames in order so we can scan for
|
|
|
|
|
- // higher versions.
|
|
|
|
|
- sort(versions.begin(), versions.end());
|
|
|
|
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
|
|
+// Function: SoftCVS::collapse_scene_files
|
|
|
|
|
+// Access: Private
|
|
|
|
|
+// 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);
|
|
|
|
|
+
|
|
|
|
|
+ // And sort them into order so we can easily compare higher and
|
|
|
|
|
+ // lower versions.
|
|
|
|
|
+ sort(versions.begin(), versions.end());
|
|
|
|
|
+
|
|
|
|
|
+ SceneFiles::iterator vi;
|
|
|
|
|
+ vi = versions.begin();
|
|
|
|
|
+ while (vi != versions.end()) {
|
|
|
|
|
+ SoftFilename &file = (*vi);
|
|
|
|
|
|
|
|
- vector<SoftFilename>::iterator vi;
|
|
|
|
|
- vi = versions.begin();
|
|
|
|
|
- while (vi != versions.end()) {
|
|
|
|
|
- SoftFilename &file = (*vi);
|
|
|
|
|
- _versioned_files.insert(file.get_base());
|
|
|
|
|
-
|
|
|
|
|
- if (!file.is_1_0()) {
|
|
|
|
|
- // Here's a file that needs to be renamed. But first, identify
|
|
|
|
|
- // all the other versions of the same file.
|
|
|
|
|
- vector<SoftFilename>::iterator start_vi;
|
|
|
|
|
- start_vi = vi;
|
|
|
|
|
- while (vi != versions.end() && (*vi).is_same_file(file)) {
|
|
|
|
|
- ++vi;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (rename_file(directory, start_vi, vi)) {
|
|
|
|
|
- if (in_cvs) {
|
|
|
|
|
- consider_add_cvs(directory, file.get_1_0_filename(), cvs_elements);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (file.get_extension() == ".dsc") {
|
|
|
|
|
- _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()));
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ if (!file.is_1_0()) {
|
|
|
|
|
+ // Here's a file that needs to be renamed. But first, identify
|
|
|
|
|
+ // all the other versions of the same file.
|
|
|
|
|
+ SceneFiles::iterator start_vi;
|
|
|
|
|
+ start_vi = vi;
|
|
|
|
|
+ while (vi != versions.end() && (*vi).is_same_file(file)) {
|
|
|
++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,
|
|
|
|
|
- vector<SoftFilename>::const_iterator begin,
|
|
|
|
|
- vector<SoftFilename>::const_iterator end) {
|
|
|
|
|
|
|
+rename_file(SoftCVS::SceneFiles::iterator begin,
|
|
|
|
|
+ SoftCVS::SceneFiles::iterator end) {
|
|
|
int length = end - begin;
|
|
int length = end - begin;
|
|
|
nassertr(length > 0, false);
|
|
nassertr(length > 0, false);
|
|
|
|
|
|
|
|
- string source_filename = (*begin).get_filename();
|
|
|
|
|
- string dest_filename = (*begin).get_1_0_filename();
|
|
|
|
|
|
|
+ SoftFilename &orig = (*begin);
|
|
|
|
|
+
|
|
|
|
|
+ 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 << " needs renaming.\n";
|
|
|
|
|
- } else {
|
|
|
|
|
- nout << source_filename << " renamed.\n";
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (_interactive) {
|
|
|
|
|
- if (!prompt_yesno("Rename this file (y/n)? ")) {
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ nout << source_filename << " renamed.\n";
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 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 dest = dirname + "/" + dest_filename;
|
|
|
|
|
|
|
+ Filename source(dirname, source_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
|
|
|
|
|
-// (i.e. filenames whose version number is greater than
|
|
|
|
|
-// 1-0). If any such filenames are found, replaces them
|
|
|
|
|
-// with the equivalent 1-0 filename, and returns true;
|
|
|
|
|
-// otherwise, returns false.
|
|
|
|
|
|
|
+// output stream, looking for references to element
|
|
|
|
|
+// files. For each reference found, increments the
|
|
|
|
|
+// appropriate element file's reference count.
|
|
|
////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////
|
|
|
-bool SoftCVS::
|
|
|
|
|
-scan_scene_file(istream &in, ostream &out) {
|
|
|
|
|
- bool any_changed = false;
|
|
|
|
|
- int c;
|
|
|
|
|
-
|
|
|
|
|
- c = in.get();
|
|
|
|
|
|
|
+void SoftCVS::
|
|
|
|
|
+scan_scene_file(istream &in) {
|
|
|
|
|
+ int 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
|
|
|
|
|
- // it? Only if the version is not 1-0, and this kind of element
|
|
|
|
|
- // is versioned by filename. (Some elements are not versioned
|
|
|
|
|
- // by filename; instead, they keep the same filename but store
|
|
|
|
|
- // multiple versions within themselves. Trouble.)
|
|
|
|
|
- SoftFilename v(word);
|
|
|
|
|
- if (v.has_version() && !v.is_1_0() &&
|
|
|
|
|
- _versioned_files.count(v.get_base()) != 0) {
|
|
|
|
|
- out << v.get_1_0_filename();
|
|
|
|
|
- any_changed = true;
|
|
|
|
|
- } else {
|
|
|
|
|
- out << word;
|
|
|
|
|
|
|
+ SoftFilename v("", word);
|
|
|
|
|
+
|
|
|
|
|
+ // Increment the use count on all matching elements of the multiset.
|
|
|
|
|
+ pair<set<SoftFilename>::iterator, set<SoftFilename>::iterator> range;
|
|
|
|
|
+ range = _element_files.equal_range(v);
|
|
|
|
|
+
|
|
|
|
|
+ set<SoftFilename>::iterator ei;
|
|
|
|
|
+ for (ei = range.first; ei != range.second; ++ei) {
|
|
|
|
|
+ // We cheat and get a non-const reference to the filename out
|
|
|
|
|
+ // of the set. We can safely do this because incrementing the
|
|
|
|
|
+ // use count won't change its position in the set.
|
|
|
|
|
+ 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
|
|
|
|
|
-// the repository. Returns true on success, false on
|
|
|
|
|
-// failure.
|
|
|
|
|
|
|
+// Description: Invokes CVS to add (or remove) all of the files in
|
|
|
|
|
+// the indicated vector. Returns true on success, false
|
|
|
|
|
+// 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()) {
|
|
|
|
|
- string command = _cvs_binary + " add";
|
|
|
|
|
|
|
+ if (!paths.empty()) {
|
|
|
|
|
+ string command = _cvs_binary + " " + cvs_command;
|
|
|
vector_string::const_iterator pi;
|
|
vector_string::const_iterator pi;
|
|
|
- pi = _cvs_paths.begin();
|
|
|
|
|
- while (pi != _cvs_paths.end()) {
|
|
|
|
|
|
|
+ pi = paths.begin();
|
|
|
|
|
+ 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);
|