28 _key_filename =
"Sources.pp";
30 _user_aborted =
false;
35 add_runline(
"[opts] file [file ... ]");
39 "Force the copy to happen without any input from the user. If a file " 40 "with the same name exists anywhere in the source hierarchy, it will " 41 "be overwritten without prompting; if a file does not yet exist, it " 42 "will be created in the directory named by -d or by -m, as appropriate.",
43 &CVSCopy::dispatch_none, &_force);
47 "The opposite of -f, this will prompt the user before each action. " 48 "The default is only to prompt the user when an action is ambiguous " 50 &CVSCopy::dispatch_none, &_interactive);
54 "Copy model files that are not already present somewhere in the tree " 55 "to the indicated directory. The default is the current directory.",
56 &CVSCopy::dispatch_filename, &_got_model_dirname, &_model_dirname);
60 "Copy texture map files to the indicated directory. The default " 61 "is src/maps from the root directory.",
62 &CVSCopy::dispatch_filename, &_got_map_dirname, &_map_dirname);
65 (
"root",
"dirname", 80,
66 "Specify the root of the CVS source hierarchy. The default is to " 67 "use the ppremake convention of locating the directory above the -d " 68 "directory that contains a file called Package.pp.",
69 &CVSCopy::dispatch_filename, &_got_root_dirname, &_root_dirname);
72 (
"key",
"filename", 80,
73 "Specify the name of the file that must exist in each directory for " 74 "it to be considered part of the CVS source hierarchy. The default " 75 "is the ppremake convention, \"Sources.pp\". Other likely candidates " 76 "are \"CVS\" to search a CVS hierarchy, or \".\" to include " 77 "all subdirectories indiscriminately.",
78 &CVSCopy::dispatch_filename,
nullptr, &_key_filename);
82 "Do not attempt to add newly-created files to CVS. The default " 84 &CVSCopy::dispatch_none, &_no_cvs);
87 (
"cvs",
"cvs_binary", 80,
88 "Specify how to run the cvs program for adding newly-created files. " 89 "The default is simply \"cvs\".",
90 &CVSCopy::dispatch_string,
nullptr, &_cvs_binary);
109 CopiedFiles::const_iterator ci;
110 ci = _copied_files.find(source);
111 if (ci != _copied_files.end()) {
117 nout <<
"Source filename " << source <<
" does not exist!\n";
121 string basename = filter_filename(source.
get_basename());
125 nassertr(path.is_valid(), path);
127 _copied_files[source] = path;
130 bool new_file = !dest.
exists();
131 if (!new_file && verify_file(source, dest, path._dir, extra_data)) {
133 nout << path.get_path() <<
" is unchanged.\n";
137 nout <<
"Copying " << basename <<
" to " << path.get_path() <<
"\n";
139 if (!copy_file(source, dest, path._dir, extra_data, new_file)) {
168 string result = prompt(
"Error occurred during copy! Continue (y/n)? ");
169 nassertr(!result.empty(),
false);
170 if (result.size() == 1) {
171 if (tolower(result[0]) ==
'y') {
173 }
else if (tolower(result[0]) ==
'n') {
174 _user_aborted =
true;
179 nout <<
"*** Invalid response: " << result <<
"\n\n";
190 handle_args(Args &args) {
192 nout <<
"You must specify the file(s) to copy from on the command line.\n";
196 for (Args::const_iterator ai = args.begin();
211 post_command_line() {
212 if (!scan_hierarchy()) {
217 if (_model_dir ==
nullptr) {
218 if (_got_model_dirname) {
219 nout <<
"Warning: model directory " << _model_dirname
220 <<
" is not within the source hierarchy.\n";
224 if (_got_map_dirname) {
227 if (_map_dir ==
nullptr) {
228 nout <<
"Warning: map directory " << _map_dirname
229 <<
" is not within the source hierarchy.\n";
235 if (_map_dir ==
nullptr) {
238 _map_dir = _model_dir;
262 if (source == dest) {
280 while (!s.eof() && !s.fail() && !d.eof() && !d.fail()) {
288 if (s.fail() || d.fail()) {
295 if (!s.eof() || !d.eof()) {
311 if (source == dest) {
321 nout <<
"Cannot read " << source <<
"\n";
327 nout <<
"Cannot write " << dest <<
"\n";
333 while (!in.eof() && !in.fail() && !out.fail()) {
338 if (!in.eof() && in.fail()) {
339 nout <<
"Error reading " << source <<
"\n";
343 nout <<
"Error writing " << dest <<
"\n";
361 nout <<
"Invalid directory: " << filename.
get_dirname() <<
"\n";
365 string command = _cvs_binary +
" add -kb " +
367 nout << command <<
"\n";
368 int result = system(command.c_str());
373 nout <<
"Failure invoking cvs.\n";
385 protect_from_shell(
const string &source) {
388 for (string::const_iterator pi = source.begin(); pi != source.end(); ++pi) {
426 filter_filename(
const string &source) {
438 if (!_got_root_dirname) {
441 if (!scan_for_root(_model_dirname)) {
449 return _tree.
scan(_key_filename);
458 scan_for_root(
const string &dirname) {
459 Filename sources = dirname +
"/Sources.pp";
461 nout <<
"Couldn't find " << sources <<
" in source directory.\n";
464 Filename package = dirname + "/Package.pp";
465 if (package.exists()) {
467 _root_dirname = dirname;
471 return scan_for_root(dirname +
"/..");
479 prompt(
const string &message) {
482 std::cerr << message << std::flush;
483 std::string response;
484 std::getline(std::cin, response);
488 while (p < response.length() && isspace(response[p])) {
492 size_t q = response.length();
493 while (q > p && isspace(response[q - 1])) {
498 return response.substr(p, q - p);
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool open_write(std::ofstream &stream, bool truncate=true) const
Opens the indicated ifstream for writing the file, if possible.
std::string get_dirname() const
Returns the directory part of the filename.
CVSSourceTree::FilePath import(const Filename &source, void *extra_data, CVSSourceDirectory *suggested_dir)
Checks for the given filename somewhere in the directory hierarchy, and chooses a place to import it.
Filename get_root_dirname() const
Returns the local directory name of the root of the tree.
void set_binary()
Indicates that the filename represents a binary file.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void set_root(const Filename &root_path)
Sets the root of the source directory.
bool open_read(std::ifstream &stream) const
Opens the indicated ifstream for reading the file, if possible.
Filename get_root_fullpath()
Returns the full path from the root to the top of the source hierarchy.
FilePath choose_directory(const std::string &basename, CVSSourceDirectory *suggested_dir, bool force, bool interactive)
Determines where an externally referenced model file of the indicated name should go.
CVSSourceDirectory * find_directory(const Filename &path)
Returns the source directory that corresponds to the given path, or NULL if there is no such director...
This represents one particular directory in the hierarchy of source directory files.
The name of a file, such as a texture file or an Egg file.
std::string get_fullpath() const
Returns the entire filename: directory, basename, extension.
static bool temp_chdir(const Filename &path)
Temporarily changes the current directory to the named path.
bool unlink() const
Permanently deletes the file associated with the filename, if possible.
bool continue_after_error()
Prompts the user (unless -f was specified) if he wants to continue the copy operation after some erro...
std::string get_basename() const
Returns the basename part of the filename.
CVSSourceDirectory * find_relpath(const std::string &relpath)
Returns the source directory that corresponds to the given relative path from the root,...
bool scan(const Filename &key_filename)
Scans the complete source directory starting at the indicated pathname.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static void restore_cwd()
Restores the current directory after changing it from temp_chdir().
bool exists() const
Returns true if the filename exists on the disk, false otherwise.
static Filename from_os_specific(const std::string &os_specific, Type type=T_general)
This named constructor returns a Panda-style filename (that is, using forward slashes,...