mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-29 08:15:18 -04:00
*** empty log message ***
This commit is contained in:
parent
c4467222e0
commit
9d3475c77b
@ -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);
|
||||||
|
|
||||||
|
// 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;
|
if (!file.is_1_0()) {
|
||||||
vi = versions.begin();
|
// Here's a file that needs to be renamed. But first, identify
|
||||||
while (vi != versions.end()) {
|
// all the other versions of the same file.
|
||||||
SoftFilename &file = (*vi);
|
SceneFiles::iterator start_vi;
|
||||||
_versioned_files.insert(file.get_base());
|
start_vi = vi;
|
||||||
|
while (vi != versions.end() && (*vi).is_same_file(file)) {
|
||||||
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()));
|
|
||||||
}
|
|
||||||
++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);
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
@ -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 ©) :
|
SoftFilename(const SoftFilename ©) :
|
||||||
|
_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 ©) :
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void SoftFilename::
|
void SoftFilename::
|
||||||
operator = (const SoftFilename ©) {
|
operator = (const SoftFilename ©) {
|
||||||
|
_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;
|
||||||
|
}
|
||||||
|
@ -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 ©);
|
SoftFilename(const SoftFilename ©);
|
||||||
void operator = (const SoftFilename ©);
|
void operator = (const SoftFilename ©);
|
||||||
|
|
||||||
|
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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user