From 936ff2455e5de76f9f98e5673544a08be0bf7d2b Mon Sep 17 00:00:00 2001 From: David Rose Date: Sat, 15 Aug 2009 00:13:55 +0000 Subject: [PATCH] some cleanup --- direct/src/plugin/p3dInstance.cxx | 10 +- direct/src/plugin/p3dInstanceManager.cxx | 1 - direct/src/plugin/p3dPackage.cxx | 2 +- direct/src/plugin/p3dSession.cxx | 62 +++++-- direct/src/plugin/p3dSession.h | 1 + direct/src/plugin_standalone/panda3d.cxx | 78 ++++++--- direct/src/plugin_standalone/panda3d.h | 2 +- direct/src/showutil/Packager.py | 202 ++++++++++++++--------- direct/src/showutil/packp3d.py | 2 +- direct/src/showutil/ppackage.py | 4 +- direct/src/showutil/runp3d.py | 79 +++++---- 11 files changed, 284 insertions(+), 159 deletions(-) diff --git a/direct/src/plugin/p3dInstance.cxx b/direct/src/plugin/p3dInstance.cxx index 200375a180..26c5e0583f 100644 --- a/direct/src/plugin/p3dInstance.cxx +++ b/direct/src/plugin/p3dInstance.cxx @@ -1155,7 +1155,7 @@ report_package_info_ready(P3DPackage *package) { //////////////////////////////////////////////////////////////////// void P3DInstance:: start_next_download() { - while (_download_package_index < _downloading_packages.size()) { + while (_download_package_index < (int)_downloading_packages.size()) { P3DPackage *package = _downloading_packages[_download_package_index]; if (package->get_failed()) { // Too bad. TODO: fail. @@ -1211,12 +1211,10 @@ start_next_download() { //////////////////////////////////////////////////////////////////// void P3DInstance:: report_package_progress(P3DPackage *package, double progress) { - if (_download_package_index >= _downloading_packages.size() || + if (_download_package_index >= (int)_downloading_packages.size() || package != _downloading_packages[_download_package_index]) { - // Got a report from an unexpected package. - nout << "Got download progress report from " << package->get_package_name() - << ", not at download head (head is " << _download_package_index - << ")\n"; + // Quietly ignore a download progress report from an unexpected + // package. return; } diff --git a/direct/src/plugin/p3dInstanceManager.cxx b/direct/src/plugin/p3dInstanceManager.cxx index e7aa854a71..a7b89345bc 100644 --- a/direct/src/plugin/p3dInstanceManager.cxx +++ b/direct/src/plugin/p3dInstanceManager.cxx @@ -22,7 +22,6 @@ #include "p3dNoneObject.h" #include "p3dBoolObject.h" #include "find_root_dir.h" -#include "mkdir_complete.h" #include "fileSpec.h" #include "get_tinyxml.h" diff --git a/direct/src/plugin/p3dPackage.cxx b/direct/src/plugin/p3dPackage.cxx index a54da05b53..597bc0aee6 100755 --- a/direct/src/plugin/p3dPackage.cxx +++ b/direct/src/plugin/p3dPackage.cxx @@ -45,7 +45,7 @@ P3DPackage(const string &package_name, P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); _package_fullname = _package_name; - _package_dir = inst_mgr->get_root_dir() + string("/") + _package_name; + _package_dir = inst_mgr->get_root_dir() + string("/packages/") + _package_name; if (!_package_platform.empty()) { _package_fullname += string("_") + _package_platform; _package_dir += string("/") + _package_platform; diff --git a/direct/src/plugin/p3dSession.cxx b/direct/src/plugin/p3dSession.cxx index cae2e475be..9692686ade 100644 --- a/direct/src/plugin/p3dSession.cxx +++ b/direct/src/plugin/p3dSession.cxx @@ -25,6 +25,9 @@ #include "p3dConcreteSequence.h" #include "p3dConcreteStruct.h" #include "binaryXml.h" +#include "mkdir_complete.h" + +#include #ifndef _WIN32 #include @@ -49,6 +52,7 @@ P3DSession(P3DInstance *inst) { _session_key = inst->get_session_key(); _python_version = inst->get_python_version(); + _start_dir = inst_mgr->get_root_dir() + "/start"; _p3dpython_running = false; _started_read_thread = false; @@ -660,6 +664,28 @@ start_p3dpython(P3DInstance *inst) { _python_root_dir = inst->_panda3d->get_package_dir(); + mkdir_complete(_start_dir, nout); + + // Build up a search path that includes all of the required packages + // that have already been installed. + string search_path; + size_t pi = 0; + assert(pi < inst->_packages.size()); + search_path = inst->_packages[pi]->get_package_dir(); + ++pi; + while (pi < inst->_packages.size()) { +#ifdef _WIN32 + search_path += ';'; +#else + search_path += ':'; +#endif // _WIN32 + + search_path += inst->_packages[pi]->get_package_dir(); + ++pi; + } + + nout << "Search path is " << search_path << "\n"; + string p3dpython = P3D_PLUGIN_P3DPYTHON; if (p3dpython.empty()) { p3dpython = _python_root_dir + "/p3dpython"; @@ -692,42 +718,58 @@ start_p3dpython(P3DInstance *inst) { // Define some new environment variables. env += "PATH="; - env += _python_root_dir; + env += search_path; env += '\0'; env += "LD_LIBRARY_PATH="; - env += _python_root_dir; + env += search_path; env += '\0'; env += "DYLD_LIBRARY_PATH="; - env += _python_root_dir; + env += search_path; env += '\0'; env += "PYTHONPATH="; - env += _python_root_dir; + env += search_path; env += '\0'; env += "PYTHONHOME="; env += _python_root_dir; env += '\0'; - env += "PRC_DIR="; - env += _python_root_dir; + env += "PRC_PATH="; + env += search_path; env += '\0'; - env += "PANDA_PRC_DIR="; - env += _python_root_dir; + env += "PANDA_PRC_PATH="; + env += search_path; env += '\0'; + + // Define each package's root directory in an environment variable + // named after the package, for the convenience of the packages in + // setting up their config files. + for (size_t pi = 0; pi < inst->_packages.size(); ++pi) { + P3DPackage *package = inst->_packages[pi]; + const string package_name = package->get_package_name(); + for (string::const_iterator si = package_name.begin(); + si != package_name.end(); + ++si) { + env += toupper(*si); + } + env += string("_ROOT="); + env += package->get_package_dir(); + env += '\0'; + } nout << "Attempting to start python from " << p3dpython << "\n"; #ifdef _WIN32 _p3dpython_handle = win_create_process - (p3dpython, _python_root_dir, env, _output_filename, + (p3dpython, _start_dir, env, _output_filename, _pipe_read, _pipe_write); bool started_p3dpython = (_p3dpython_handle != INVALID_HANDLE_VALUE); #else _p3dpython_pid = posix_create_process - (p3dpython, _python_root_dir, env, _output_filename, + (p3dpython, _start_dir, env, _output_filename, _pipe_read, _pipe_write); bool started_p3dpython = (_p3dpython_pid > 0); #endif diff --git a/direct/src/plugin/p3dSession.h b/direct/src/plugin/p3dSession.h index dbe3f1d0cb..7dc4017b74 100644 --- a/direct/src/plugin/p3dSession.h +++ b/direct/src/plugin/p3dSession.h @@ -92,6 +92,7 @@ private: string _python_version; string _output_filename; string _python_root_dir; + string _start_dir; typedef map Instances; Instances _instances; diff --git a/direct/src/plugin_standalone/panda3d.cxx b/direct/src/plugin_standalone/panda3d.cxx index 169fecf518..975325187f 100644 --- a/direct/src/plugin_standalone/panda3d.cxx +++ b/direct/src/plugin_standalone/panda3d.cxx @@ -56,13 +56,17 @@ int Panda3D:: run(int argc, char *argv[]) { extern char *optarg; extern int optind; - const char *optstr = "u:p:fl:t:s:o:h"; + // We prefix a "+" sign to tell gnu getopt not to parse options + // following the first not-option parameter. (These will be passed + // into the sub-process.) + const char *optstr = "+mu:p:ft:s:o:h"; + + bool allow_multiple = false; string download_url = P3D_PLUGIN_DOWNLOAD; string this_platform = DTOOL_PLATFORM; bool force_download = false; - Filename output_filename; P3D_window_type window_type = P3D_WT_toplevel; int win_x = 0, win_y = 0; int win_width = 0, win_height = 0; @@ -71,6 +75,10 @@ run(int argc, char *argv[]) { while (flag != EOF) { switch (flag) { + case 'm': + allow_multiple = true; + break; + case 'u': download_url = optarg; break; @@ -83,10 +91,6 @@ run(int argc, char *argv[]) { force_download = true; break; - case 'l': - output_filename = Filename::from_os_specific(optarg); - break; - case 't': if (strcmp(optarg, "toplevel") == 0) { window_type = P3D_WT_toplevel; @@ -118,6 +122,7 @@ run(int argc, char *argv[]) { case 'h': case '?': + case '+': default: usage(); return 1; @@ -143,7 +148,24 @@ run(int argc, char *argv[]) { return 1; } - int num_instances = argc - 1; + int num_instance_filenames, num_instance_args; + char **instance_filenames, **instance_args; + + if (allow_multiple) { + // With -m, the remaining arguments are all instance filenames. + num_instance_filenames = argc - 1; + instance_filenames = argv + 1; + num_instance_args = 0; + instance_args = argv + argc; + + } else { + // Without -m, there is one instance filename, and everything else + // gets delivered to that instance. + num_instance_filenames = 1; + instance_filenames = argv + 1; + num_instance_args = argc - 2; + instance_args = argv + 2; + } P3D_window_handle parent_window; if (window_type == P3D_WT_embedded) { @@ -168,8 +190,8 @@ run(int argc, char *argv[]) { #endif // Subdivide the window into num_x_spans * num_y_spans sub-windows. - int num_y_spans = int(sqrt((double)num_instances)); - int num_x_spans = (num_instances + num_y_spans - 1) / num_y_spans; + int num_y_spans = int(sqrt((double)num_instance_filenames)); + int num_x_spans = (num_instance_filenames + num_y_spans - 1) / num_y_spans; int inst_width = win_width / num_x_spans; int inst_height = win_height / num_y_spans; @@ -177,7 +199,7 @@ run(int argc, char *argv[]) { for (int yi = 0; yi < num_y_spans; ++yi) { for (int xi = 0; xi < num_x_spans; ++xi) { int i = yi * num_x_spans + xi; - if (i >= num_instances) { + if (i >= num_instance_filenames) { continue; } @@ -186,20 +208,20 @@ run(int argc, char *argv[]) { int inst_y = win_y + yi * inst_height; P3D_instance *inst = create_instance - (argv[i + 1], P3D_WT_embedded, + (instance_filenames[i], P3D_WT_embedded, inst_x, inst_y, inst_width, inst_height, parent_window, - output_filename); + instance_args, num_instance_args); _instances.insert(inst); } } } else { // Not an embedded window. Create each window with the same parameters. - for (int i = 0; i < num_instances; ++i) { + for (int i = 0; i < num_instance_filenames; ++i) { P3D_instance *inst = create_instance - (argv[i + 1], window_type, + (instance_filenames[i], window_type, win_x, win_y, win_width, win_height, parent_window, - output_filename); + instance_args, num_instance_args); _instances.insert(inst); } } @@ -579,12 +601,8 @@ make_parent_window(P3D_window_handle &parent_window, P3D_instance *Panda3D:: create_instance(const string &arg, P3D_window_type window_type, int win_x, int win_y, int win_width, int win_height, - P3D_window_handle parent_window, - const Filename &output_filename) { - - string os_output_filename = output_filename.to_os_specific(); + P3D_window_handle parent_window, char **args, int num_args) { P3D_token tokens[] = { - { "output_filename", os_output_filename.c_str() }, { "src", arg.c_str() }, }; int num_tokens = sizeof(tokens) / sizeof(P3D_token); @@ -645,18 +663,24 @@ void Panda3D:: usage() { cerr << "\nUsage:\n" - << " panda3d [opts] file.p3d [file_b.p3d file_c.p3d ...]\n\n" + << " panda3d [opts] file.p3d [args]\n\n" + << " panda3d -m [opts] file_a.p3d file_b.p3d [file_c.p3d ...]\n\n" << "This program is used to execute a Panda3D application bundle stored\n" - << "in a .p3d file. Normally you only run one p3d bundle at a time,\n" - << "but it is possible to run multiple bundles simultaneously.\n\n" + << "in a .p3d file. In the first form, without a -m option, it\n" + << "executes one application; remaining arguments following the\n" + << "application name are passed into the application. In the second\n" + << "form, with a -m option, it can execute multiple applications\n" + << "simultaneously, though in this form arguments cannot be passed into\n" + << "the applications.\n\n" << "Options:\n\n" - << " -l output.log\n" - << " Specify the name of the file to receive the log output of the\n" - << " plugin process(es). The default is to send this output to the\n" - << " console.\n\n" + << " -m\n" + << " Indicates that multiple application filenames will be passed on\n" + << " the command line. All applications will be run at the same\n" + << " time, but additional arguments may not be passed to any of the\n" + << " applictions.\n\n" << " -t [toplevel|embedded|fullscreen|hidden]\n" << " Specify the type of graphic window to create. If you specify\n" diff --git a/direct/src/plugin_standalone/panda3d.h b/direct/src/plugin_standalone/panda3d.h index e91aa206b4..d1791927bb 100755 --- a/direct/src/plugin_standalone/panda3d.h +++ b/direct/src/plugin_standalone/panda3d.h @@ -59,7 +59,7 @@ private: int win_x, int win_y, int win_width, int win_height, P3D_window_handle parent_window, - const Filename &output_filename); + char **args, int num_args); void delete_instance(P3D_instance *instance); void usage(); diff --git a/direct/src/showutil/Packager.py b/direct/src/showutil/Packager.py index 1ddfff7ebb..61644746f5 100644 --- a/direct/src/showutil/Packager.py +++ b/direct/src/showutil/Packager.py @@ -9,6 +9,7 @@ import glob import marshal import new import string +import types from direct.showbase import Loader from direct.showutil import FreezeTool from direct.directnotify.DirectNotifyGlobal import * @@ -31,11 +32,13 @@ class Packager: class PackFile: def __init__(self, package, filename, newName = None, deleteTemp = False, - compress = None, extract = None, executable = None): + explicit = False, compress = None, extract = None, + executable = None): assert isinstance(filename, Filename) self.filename = Filename(filename) self.newName = newName self.deleteTemp = deleteTemp + self.explicit = explicit self.compress = compress self.extract = extract self.executable = executable @@ -58,7 +61,7 @@ class Packager: if self.executable: # Look up the filename along the system PATH, if necessary. - self.filename.resolveFilename(packager.dllPath) + self.filename.resolveFilename(packager.executablePath) # Convert the filename to an unambiguous filename for # searching. @@ -73,19 +76,27 @@ class Packager: if self.newName in package.skipFilenames: return True - basename = Filename(self.newName).getBasename() - if not package.packager.caseSensitive: - basename = basename.lower() - if basename in package.packager.excludeSystemFiles: - return True + if not self.explicit: + # Make sure it's not one of our auto-excluded system + # files. (But only make this check if this file was + # not explicitly added.) - for exclude in package.packager.excludeSystemGlobs: - if exclude.matches(basename): + basename = Filename(self.newName).getBasename() + if not package.packager.caseSensitive: + basename = basename.lower() + if basename in package.packager.excludeSystemFiles: return True + for exclude in package.packager.excludeSystemGlobs: + if exclude.matches(basename): + return True - for exclude in package.excludedFilenames: - if exclude.matches(self.filename): - return True + # Also check if it was explicitly excluded. As above, + # omit this check for an explicitly-added file: if you + # both include and exclude a file, the file is + # included. + for exclude in package.excludedFilenames: + if exclude.matches(self.filename): + return True return False @@ -115,12 +126,15 @@ class Packager: self.version = None self.platform = None self.p3dApplication = False - self.displayName = None self.compressionLevel = 0 self.importedMapsDir = 'imported_maps' self.mainModule = None self.requires = [] + # This is the set of config variables assigned to the + # package. + self.configs = {} + # This is the set of files and modules, already included # by required packages, that we can skip. self.skipFilenames = {} @@ -369,7 +383,7 @@ class Packager: filename = Filename.fromOsSpecific(filename) filename.resolveFilename(path) self.addFile(filename, newName = filename.getBasename(), - executable = True) + explicit = False, executable = True) def __parseDependenciesWindows(self, tempFile): """ Reads the indicated temporary file, the output from @@ -451,7 +465,7 @@ class Packager: filename = Filename.fromOsSpecific(filename) filename.resolveFilename(path) self.addFile(filename, newName = filename.getBasename(), - executable = True) + explicit = False, executable = True) def __parseDependenciesOSX(self, tempFile): """ Reads the indicated temporary file, the output from @@ -522,7 +536,7 @@ class Packager: filename = Filename.fromOsSpecific(filename) filename.resolveFilename(path) self.addFile(filename, newName = filename.getBasename(), - executable = True) + explicit = False, executable = True) def __parseDependenciesPosix(self, tempFile): """ Reads the indicated temporary file, the output from @@ -560,7 +574,8 @@ class Packager: newName += '/' + filename.getBasename() # Sometimes the PYTHONPATH has the wrong case in it. filename.makeTrueCase() - self.addFile(filename, newName = newName, extract = True) + self.addFile(filename, newName = newName, + explicit = False, extract = True) freezer.extras = [] @@ -579,11 +594,14 @@ class Packager: if self.version: xpackage.SetAttribute('version', self.version) - if self.displayName: - xpackage.SetAttribute('display_name', self.displayName) - xpackage.SetAttribute('main_module', self.mainModule) + for variable, value in self.configs.items(): + if isinstance(value, types.UnicodeType): + xpackage.SetAttribute(variable, value.encode('utf-8')) + else: + xpackage.SetAttribute(variable, str(value)) + for package in self.requires: xrequires = TiXmlElement('requires') xrequires.SetAttribute('name', package.packageName) @@ -628,8 +646,11 @@ class Packager: if self.version: xpackage.SetAttribute('version', self.version) - if self.displayName: - xpackage.SetAttribute('display_name', self.displayName) + for variable, value in self.configs.items(): + if isinstance(value, types.UnicodeType): + xpackage.SetAttribute(variable, value.encode('utf-8')) + else: + xpackage.SetAttribute(variable, str(value)) for package in self.requires: xrequires = TiXmlElement('requires') @@ -872,7 +893,8 @@ class Packager: self.importedMapsDir, filename.getBasenameWoExtension(), uniqueId, filename.getExtension()) - self.addFile(filename, newName = newName, compress = False) + self.addFile(filename, newName = newName, explicit = False, + compress = False) def addComponent(self, file): if file.platformSpecific: @@ -916,24 +938,25 @@ class Packager: self.persistDir = None # A search list of directories and/or URL's to search for - # installed packages. - self.installSearch = [] + # installed packages. We query it from a config variable + # initially, but we may also be extending it at runtime. + self.installSearch = ConfigVariableSearchPath('pdef-path') # The system PATH, for searching dll's and exe's. - self.dllPath = DSearchPath() + self.executablePath = DSearchPath() if PandaSystem.getPlatform().startswith('win'): - self.addWindowsSearchPath(self.dllPath, "PATH") + self.addWindowsSearchPath(self.executablePath, "PATH") elif PandaSystem.getPlatform().startswith('osx'): - self.addPosixSearchPath(self.dllPath, "DYLD_LIBRARY_PATH") - self.addPosixSearchPath(self.dllPath, "LD_LIBRARY_PATH") - self.addPosixSearchPath(self.dllPath, "PATH") - self.dllPath.appendDirectory('/lib') - self.dllPath.appendDirectory('/usr/lib') + self.addPosixSearchPath(self.executablePath, "DYLD_LIBRARY_PATH") + self.addPosixSearchPath(self.executablePath, "LD_LIBRARY_PATH") + self.addPosixSearchPath(self.executablePath, "PATH") + self.executablePath.appendDirectory('/lib') + self.executablePath.appendDirectory('/usr/lib') else: - self.addPosixSearchPath(self.dllPath, "LD_LIBRARY_PATH") - self.addPosixSearchPath(self.dllPath, "PATH") - self.dllPath.appendDirectory('/lib') - self.dllPath.appendDirectory('/usr/lib') + self.addPosixSearchPath(self.executablePath, "LD_LIBRARY_PATH") + self.addPosixSearchPath(self.executablePath, "PATH") + self.executablePath.appendDirectory('/lib') + self.executablePath.appendDirectory('/usr/lib') # The platform string. self.platform = PandaSystem.getPlatform() @@ -1286,6 +1309,32 @@ class Packager: value = ExecutionEnvironment.expandString(value.strip()) ExecutionEnvironment.setEnvironmentVariable(variable, value) + def parse_model_path(self, words): + """ + model_path directory + """ + newName = None + + try: + command, dirName = words + except ValueError: + raise ArgumentError + + getModelPath().appendDirectory(Filename.fromOsSpecific(dirName)) + + def parse_reset_model_path(self, words): + """ + reset_model_path + """ + newName = None + + try: + (command,) = words + except ValueError: + raise ArgumentError + + getModelPath().clear() + def parse_begin_package(self, words): """ begin_package packageName [version=v] @@ -1338,20 +1387,23 @@ class Packager: self.endPackage(packageName, p3dApplication = True) - def parse_display_name(self, words): + def parse_config(self, words): """ - display_name "name" + config variable=value """ - + try: - command, displayName = words + command, assign = words except ValueError: - raise ArgumentError + raise ArgumentNumber + + try: + variable, value = assign.split('=', 1) + except ValueError: + raise PackagerError, 'Equals sign required in assignment' - if not self.currentPackage: - raise OutsideOfPackageError - - self.currentPackage.displayName = displayName + variable = variable.strip() + self.config(variable, value) def parse_require(self, words): """ @@ -1368,32 +1420,6 @@ class Packager: version = args.get('version', None) self.require(packageName, version = version) - def parse_model_path(self, words): - """ - model_path directory - """ - newName = None - - try: - command, dirName = words - except ValueError: - raise ArgumentError - - getModelPath().appendDirectory(Filename.fromOsSpecific(dirName)) - - def parse_reset_model_path(self, words): - """ - reset_model_path - """ - newName = None - - try: - (command,) = words - except ValueError: - raise ArgumentError - - getModelPath().clear() - def parse_module(self, words): """ module moduleName [newName] @@ -1624,10 +1650,10 @@ class Packager: return package # Look on the searchlist. - for path in self.installSearch: - package = self.__scanPackageDir(path, packageName, platform, version, requires = requires) + for dirname in self.installSearch.getDirectories(): + package = self.__scanPackageDir(dirname, packageName, platform, version, requires = requires) if not package: - package = self.__scanPackageDir(path, packageName, None, version, requires = requires) + package = self.__scanPackageDir(dirname, packageName, None, version, requires = requires) if package: package = self.packages.setdefault((package.packageName, package.platform, package.version), package) @@ -1727,9 +1753,9 @@ class Packager: if not requires: return True - # Really, we only check the panda3d package for now. The - # other packages will list this as a dependency, and this is - # all that matters. + # Really, we only check the panda3d package. The other + # packages will list this as a dependency, and this is all + # that matters. panda1 = self.__findPackageInList('panda3d', [package] + package.requires) panda2 = self.__findPackageInList('panda3d', requires) @@ -1760,6 +1786,17 @@ class Packager: return None + def config(self, variable, value): + """ Sets the indicated p3d config variable to the given value. + This will be written into the p3d_info.xml file at the top of + the application, or to the package desc file for a package + file. """ + + if not self.currentPackage: + raise OutsideOfPackageError + + self.currentPackage.configs[variable] = value + def require(self, packageName, version = None): """ Indicates a dependency on the named package, supplied as a name. @@ -1878,7 +1915,7 @@ class Packager: basename = freezer.generateCode(basename, compileToExe = compileToExe) package.addFile(Filename(basename), newName = dirname + basename, - deleteTemp = True, extract = True) + deleteTemp = True, explicit = True, extract = True) package.addExtensionModules() if not package.platform: package.platform = PandaSystem.getPlatform() @@ -1924,6 +1961,7 @@ class Packager: files = glob.glob(filename.toOsSpecific()) if not files: files = [filename.toOsSpecific()] + explicit = (len(files) == 1) newName = None prefix = '' @@ -1946,7 +1984,7 @@ class Packager: self.currentPackage.addFile( filename, newName = name, extract = extract, - executable = executable) + explicit = explicit, executable = executable) def exclude(self, filename): """ Marks the indicated filename as not to be included. The @@ -1996,7 +2034,8 @@ class Packager: # It's a file name. Add it. ext = filename.getExtension() if ext == 'py': - self.currentPackage.addFile(filename, newName = newName) + self.currentPackage.addFile(filename, newName = newName, + explicit = False) else: if ext == 'pz': # Strip off an implicit .pz extension. @@ -2006,4 +2045,5 @@ class Packager: ext = newFilename.getExtension() if ext in self.knownExtensions: - self.currentPackage.addFile(filename, newName = newName) + self.currentPackage.addFile(filename, newName = newName, + explicit = False) diff --git a/direct/src/showutil/packp3d.py b/direct/src/showutil/packp3d.py index 0ca7e24df4..1e298d603b 100755 --- a/direct/src/showutil/packp3d.py +++ b/direct/src/showutil/packp3d.py @@ -78,7 +78,7 @@ def makePackedApp(args): elif option == '-r': requires.append(value) elif option == '-s': - packager.installSearch.append(Filename.fromOsSpecific(value)) + packager.installSearch.appendDirectory(Filename.fromOsSpecific(value)) elif option == '-x': versionIndependent = True elif option == '-h': diff --git a/direct/src/showutil/ppackage.py b/direct/src/showutil/ppackage.py index a1cb6139cd..9f9c3aba3a 100755 --- a/direct/src/showutil/ppackage.py +++ b/direct/src/showutil/ppackage.py @@ -83,7 +83,7 @@ for opt, arg in opts: if opt == '-i': packager.installDir = Filename.fromOsSpecific(arg) elif opt == '-s': - packager.installSearch.append(Filename.fromOsSpecific(arg)) + packager.installSearch.appendDirectory(Filename.fromOsSpecific(arg)) elif opt == '-d': packager.persistDir = Filename.fromOsSpecific(arg) elif opt == '-p': @@ -108,7 +108,7 @@ packageDef = Filename.fromOsSpecific(args[0]) if not packager.installDir: packager.installDir = Filename('install') -packager.installSearch = [packager.installDir] + packager.installSearch +packager.installSearch.prependDirectory(packager.installDir) packager.setup() packages = packager.readPackageDef(packageDef) diff --git a/direct/src/showutil/runp3d.py b/direct/src/showutil/runp3d.py index 4e25fa6fff..d92050c927 100755 --- a/direct/src/showutil/runp3d.py +++ b/direct/src/showutil/runp3d.py @@ -65,6 +65,8 @@ class AppRunner(DirectObject): self.windowOpened = False self.windowPrc = None + self.fullDiskAccess = False + self.Undefined = Undefined self.ConcreteStruct = ConcreteStruct @@ -139,22 +141,36 @@ class AppRunner(DirectObject): vfs = VirtualFileSystem.getGlobalPtr() - # Clear *all* the mount points, including "/", so that we no - # longer access the disk directly. - vfs.unmountAll() + # Unmount directories we don't need. This doesn't provide + # actual security, since it only disables this stuff for users + # who go through the vfs; a malicious programmer can always + # get to the underlying true file I/O operations. Still, it + # can help prevent honest developers from accidentally getting + # stuck where they don't belong. + if not self.fullDiskAccess: + # Clear *all* the mount points, including "/", so that we + # no longer access the disk directly. + vfs.unmountAll() - # Make sure the directories on our standard Python path are mounted - # read-only, so we can still load Python. - for dirname in sys.path: - vfs.mount(dirname, dirname, vfs.MFReadOnly) + # Make sure the directories on our standard Python path + # are mounted read-only, so we can still load Python. + # Note: read-only actually doesn't have any effect on the + # vfs right now; careless application code can still write + # to these directories inadvertently. + for dirname in sys.path: + vfs.mount(dirname, dirname, vfs.MFReadOnly) - # Also mount some standard directories read-write (temporary and - # app-data directories). - tdir = Filename.temporary('', '') - for dirname in set([ tdir.getDirname(), - Filename.getTempDirectory().cStr(), - Filename.getUserAppdataDirectory().cStr(), - Filename.getCommonAppdataDirectory().cStr() ]): + # Also mount some standard directories read-write + # (temporary and app-data directories). + tdir = Filename.temporary('', '') + for dirname in set([ tdir.getDirname(), + Filename.getTempDirectory().cStr(), + Filename.getUserAppdataDirectory().cStr(), + Filename.getCommonAppdataDirectory().cStr() ]): + vfs.mount(dirname, dirname, 0) + + # And we might need the current working directory. + dirname = ExecutionEnvironment.getCwd() vfs.mount(dirname, dirname, 0) # Now set up Python to import this stuff. @@ -257,12 +273,30 @@ class AppRunner(DirectObject): raise ArgumentError, "No such file: %s" % (p3dFilename) fname.makeAbsolute() - self.initPackedAppEnvironment() - mf = Multifile() if not mf.openRead(fname): raise ArgumentError, "Not a Panda Multifile: %s" % (p3dFilename) + # Now load the p3dInfo file. + self.p3dInfo = None + self.p3dPackage = None + i = mf.findSubfile('p3d_info.xml') + if i >= 0: + stream = mf.openReadSubfile(i) + self.p3dInfo = readXmlStream(stream) + mf.closeReadSubfile(stream) + if self.p3dInfo: + self.p3dPackage = self.p3dInfo.FirstChildElement('package') + + if self.p3dPackage: + fullDiskAccess = self.p3dPackage.Attribute('full_disk_access') + try: + self.fullDiskAccess = int(fullDiskAccess) + except ValueError: + pass + + self.initPackedAppEnvironment() + # Mount the Multifile under /mf, by convention. vfs.mount(mf, MultifileRoot, vfs.MFReadOnly) @@ -278,19 +312,6 @@ class AppRunner(DirectObject): data = open(pathname, 'r').read() loadPrcFileData(pathname, data) - # Now load the p3dInfo file. - self.p3dInfo = None - self.p3dPackage = None - i = mf.findSubfile('p3d_info.xml') - if i >= 0: - stream = mf.openReadSubfile(i) - self.p3dInfo = readXmlStream(stream) - mf.closeReadSubfile(stream) - if self.p3dInfo: - p3dPackage = self.p3dInfo.FirstChild('package') - if p3dPackage: - self.p3dPackage = p3dPackage.ToElement() - self.gotP3DFilename = True # Send this call to the main thread; don't call it directly.