some cleanup

This commit is contained in:
David Rose 2009-08-15 00:13:55 +00:00
parent 9b4f4aa8c6
commit 936ff2455e
11 changed files with 284 additions and 159 deletions

View File

@ -1155,7 +1155,7 @@ report_package_info_ready(P3DPackage *package) {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void P3DInstance:: void P3DInstance::
start_next_download() { 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]; P3DPackage *package = _downloading_packages[_download_package_index];
if (package->get_failed()) { if (package->get_failed()) {
// Too bad. TODO: fail. // Too bad. TODO: fail.
@ -1211,12 +1211,10 @@ start_next_download() {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void P3DInstance:: void P3DInstance::
report_package_progress(P3DPackage *package, double progress) { 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]) { package != _downloading_packages[_download_package_index]) {
// Got a report from an unexpected package. // Quietly ignore a download progress report from an unexpected
nout << "Got download progress report from " << package->get_package_name() // package.
<< ", not at download head (head is " << _download_package_index
<< ")\n";
return; return;
} }

View File

@ -22,7 +22,6 @@
#include "p3dNoneObject.h" #include "p3dNoneObject.h"
#include "p3dBoolObject.h" #include "p3dBoolObject.h"
#include "find_root_dir.h" #include "find_root_dir.h"
#include "mkdir_complete.h"
#include "fileSpec.h" #include "fileSpec.h"
#include "get_tinyxml.h" #include "get_tinyxml.h"

View File

@ -45,7 +45,7 @@ P3DPackage(const string &package_name,
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
_package_fullname = _package_name; _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()) { if (!_package_platform.empty()) {
_package_fullname += string("_") + _package_platform; _package_fullname += string("_") + _package_platform;
_package_dir += string("/") + _package_platform; _package_dir += string("/") + _package_platform;

View File

@ -25,6 +25,9 @@
#include "p3dConcreteSequence.h" #include "p3dConcreteSequence.h"
#include "p3dConcreteStruct.h" #include "p3dConcreteStruct.h"
#include "binaryXml.h" #include "binaryXml.h"
#include "mkdir_complete.h"
#include <ctype.h>
#ifndef _WIN32 #ifndef _WIN32
#include <fcntl.h> #include <fcntl.h>
@ -49,6 +52,7 @@ P3DSession(P3DInstance *inst) {
_session_key = inst->get_session_key(); _session_key = inst->get_session_key();
_python_version = inst->get_python_version(); _python_version = inst->get_python_version();
_start_dir = inst_mgr->get_root_dir() + "/start";
_p3dpython_running = false; _p3dpython_running = false;
_started_read_thread = false; _started_read_thread = false;
@ -660,6 +664,28 @@ start_p3dpython(P3DInstance *inst) {
_python_root_dir = inst->_panda3d->get_package_dir(); _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; string p3dpython = P3D_PLUGIN_P3DPYTHON;
if (p3dpython.empty()) { if (p3dpython.empty()) {
p3dpython = _python_root_dir + "/p3dpython"; p3dpython = _python_root_dir + "/p3dpython";
@ -692,42 +718,58 @@ start_p3dpython(P3DInstance *inst) {
// Define some new environment variables. // Define some new environment variables.
env += "PATH="; env += "PATH=";
env += _python_root_dir; env += search_path;
env += '\0'; env += '\0';
env += "LD_LIBRARY_PATH="; env += "LD_LIBRARY_PATH=";
env += _python_root_dir; env += search_path;
env += '\0'; env += '\0';
env += "DYLD_LIBRARY_PATH="; env += "DYLD_LIBRARY_PATH=";
env += _python_root_dir; env += search_path;
env += '\0'; env += '\0';
env += "PYTHONPATH="; env += "PYTHONPATH=";
env += _python_root_dir; env += search_path;
env += '\0'; env += '\0';
env += "PYTHONHOME="; env += "PYTHONHOME=";
env += _python_root_dir; env += _python_root_dir;
env += '\0'; env += '\0';
env += "PRC_DIR="; env += "PRC_PATH=";
env += _python_root_dir; env += search_path;
env += '\0'; env += '\0';
env += "PANDA_PRC_DIR="; env += "PANDA_PRC_PATH=";
env += _python_root_dir; env += search_path;
env += '\0'; 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"; nout << "Attempting to start python from " << p3dpython << "\n";
#ifdef _WIN32 #ifdef _WIN32
_p3dpython_handle = win_create_process _p3dpython_handle = win_create_process
(p3dpython, _python_root_dir, env, _output_filename, (p3dpython, _start_dir, env, _output_filename,
_pipe_read, _pipe_write); _pipe_read, _pipe_write);
bool started_p3dpython = (_p3dpython_handle != INVALID_HANDLE_VALUE); bool started_p3dpython = (_p3dpython_handle != INVALID_HANDLE_VALUE);
#else #else
_p3dpython_pid = posix_create_process _p3dpython_pid = posix_create_process
(p3dpython, _python_root_dir, env, _output_filename, (p3dpython, _start_dir, env, _output_filename,
_pipe_read, _pipe_write); _pipe_read, _pipe_write);
bool started_p3dpython = (_p3dpython_pid > 0); bool started_p3dpython = (_p3dpython_pid > 0);
#endif #endif

View File

@ -92,6 +92,7 @@ private:
string _python_version; string _python_version;
string _output_filename; string _output_filename;
string _python_root_dir; string _python_root_dir;
string _start_dir;
typedef map<int, P3DInstance *> Instances; typedef map<int, P3DInstance *> Instances;
Instances _instances; Instances _instances;

View File

@ -56,13 +56,17 @@ int Panda3D::
run(int argc, char *argv[]) { run(int argc, char *argv[]) {
extern char *optarg; extern char *optarg;
extern int optind; 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 download_url = P3D_PLUGIN_DOWNLOAD;
string this_platform = DTOOL_PLATFORM; string this_platform = DTOOL_PLATFORM;
bool force_download = false; bool force_download = false;
Filename output_filename;
P3D_window_type window_type = P3D_WT_toplevel; P3D_window_type window_type = P3D_WT_toplevel;
int win_x = 0, win_y = 0; int win_x = 0, win_y = 0;
int win_width = 0, win_height = 0; int win_width = 0, win_height = 0;
@ -71,6 +75,10 @@ run(int argc, char *argv[]) {
while (flag != EOF) { while (flag != EOF) {
switch (flag) { switch (flag) {
case 'm':
allow_multiple = true;
break;
case 'u': case 'u':
download_url = optarg; download_url = optarg;
break; break;
@ -83,10 +91,6 @@ run(int argc, char *argv[]) {
force_download = true; force_download = true;
break; break;
case 'l':
output_filename = Filename::from_os_specific(optarg);
break;
case 't': case 't':
if (strcmp(optarg, "toplevel") == 0) { if (strcmp(optarg, "toplevel") == 0) {
window_type = P3D_WT_toplevel; window_type = P3D_WT_toplevel;
@ -118,6 +122,7 @@ run(int argc, char *argv[]) {
case 'h': case 'h':
case '?': case '?':
case '+':
default: default:
usage(); usage();
return 1; return 1;
@ -143,7 +148,24 @@ run(int argc, char *argv[]) {
return 1; 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; P3D_window_handle parent_window;
if (window_type == P3D_WT_embedded) { if (window_type == P3D_WT_embedded) {
@ -168,8 +190,8 @@ run(int argc, char *argv[]) {
#endif #endif
// Subdivide the window into num_x_spans * num_y_spans sub-windows. // Subdivide the window into num_x_spans * num_y_spans sub-windows.
int num_y_spans = int(sqrt((double)num_instances)); int num_y_spans = int(sqrt((double)num_instance_filenames));
int num_x_spans = (num_instances + num_y_spans - 1) / num_y_spans; int num_x_spans = (num_instance_filenames + num_y_spans - 1) / num_y_spans;
int inst_width = win_width / num_x_spans; int inst_width = win_width / num_x_spans;
int inst_height = win_height / num_y_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 yi = 0; yi < num_y_spans; ++yi) {
for (int xi = 0; xi < num_x_spans; ++xi) { for (int xi = 0; xi < num_x_spans; ++xi) {
int i = yi * num_x_spans + xi; int i = yi * num_x_spans + xi;
if (i >= num_instances) { if (i >= num_instance_filenames) {
continue; continue;
} }
@ -186,20 +208,20 @@ run(int argc, char *argv[]) {
int inst_y = win_y + yi * inst_height; int inst_y = win_y + yi * inst_height;
P3D_instance *inst = create_instance 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, inst_x, inst_y, inst_width, inst_height, parent_window,
output_filename); instance_args, num_instance_args);
_instances.insert(inst); _instances.insert(inst);
} }
} }
} else { } else {
// Not an embedded window. Create each window with the same parameters. // 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 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, win_x, win_y, win_width, win_height, parent_window,
output_filename); instance_args, num_instance_args);
_instances.insert(inst); _instances.insert(inst);
} }
} }
@ -579,12 +601,8 @@ make_parent_window(P3D_window_handle &parent_window,
P3D_instance *Panda3D:: P3D_instance *Panda3D::
create_instance(const string &arg, P3D_window_type window_type, create_instance(const string &arg, P3D_window_type window_type,
int win_x, int win_y, int win_width, int win_height, int win_x, int win_y, int win_width, int win_height,
P3D_window_handle parent_window, P3D_window_handle parent_window, char **args, int num_args) {
const Filename &output_filename) {
string os_output_filename = output_filename.to_os_specific();
P3D_token tokens[] = { P3D_token tokens[] = {
{ "output_filename", os_output_filename.c_str() },
{ "src", arg.c_str() }, { "src", arg.c_str() },
}; };
int num_tokens = sizeof(tokens) / sizeof(P3D_token); int num_tokens = sizeof(tokens) / sizeof(P3D_token);
@ -645,18 +663,24 @@ void Panda3D::
usage() { usage() {
cerr cerr
<< "\nUsage:\n" << "\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" << "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" << "in a .p3d file. In the first form, without a -m option, it\n"
<< "but it is possible to run multiple bundles simultaneously.\n\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" << "Options:\n\n"
<< " -l output.log\n" << " -m\n"
<< " Specify the name of the file to receive the log output of the\n" << " Indicates that multiple application filenames will be passed on\n"
<< " plugin process(es). The default is to send this output to the\n" << " the command line. All applications will be run at the same\n"
<< " console.\n\n" << " time, but additional arguments may not be passed to any of the\n"
<< " applictions.\n\n"
<< " -t [toplevel|embedded|fullscreen|hidden]\n" << " -t [toplevel|embedded|fullscreen|hidden]\n"
<< " Specify the type of graphic window to create. If you specify\n" << " Specify the type of graphic window to create. If you specify\n"

View File

@ -59,7 +59,7 @@ private:
int win_x, int win_y, int win_width, int win_x, int win_y, int win_width,
int win_height, int win_height,
P3D_window_handle parent_window, P3D_window_handle parent_window,
const Filename &output_filename); char **args, int num_args);
void delete_instance(P3D_instance *instance); void delete_instance(P3D_instance *instance);
void usage(); void usage();

View File

@ -9,6 +9,7 @@ import glob
import marshal import marshal
import new import new
import string import string
import types
from direct.showbase import Loader from direct.showbase import Loader
from direct.showutil import FreezeTool from direct.showutil import FreezeTool
from direct.directnotify.DirectNotifyGlobal import * from direct.directnotify.DirectNotifyGlobal import *
@ -31,11 +32,13 @@ class Packager:
class PackFile: class PackFile:
def __init__(self, package, filename, def __init__(self, package, filename,
newName = None, deleteTemp = False, newName = None, deleteTemp = False,
compress = None, extract = None, executable = None): explicit = False, compress = None, extract = None,
executable = None):
assert isinstance(filename, Filename) assert isinstance(filename, Filename)
self.filename = Filename(filename) self.filename = Filename(filename)
self.newName = newName self.newName = newName
self.deleteTemp = deleteTemp self.deleteTemp = deleteTemp
self.explicit = explicit
self.compress = compress self.compress = compress
self.extract = extract self.extract = extract
self.executable = executable self.executable = executable
@ -58,7 +61,7 @@ class Packager:
if self.executable: if self.executable:
# Look up the filename along the system PATH, if necessary. # 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 # Convert the filename to an unambiguous filename for
# searching. # searching.
@ -73,19 +76,27 @@ class Packager:
if self.newName in package.skipFilenames: if self.newName in package.skipFilenames:
return True return True
basename = Filename(self.newName).getBasename() if not self.explicit:
if not package.packager.caseSensitive: # Make sure it's not one of our auto-excluded system
basename = basename.lower() # files. (But only make this check if this file was
if basename in package.packager.excludeSystemFiles: # not explicitly added.)
return True
for exclude in package.packager.excludeSystemGlobs: basename = Filename(self.newName).getBasename()
if exclude.matches(basename): if not package.packager.caseSensitive:
basename = basename.lower()
if basename in package.packager.excludeSystemFiles:
return True return True
for exclude in package.packager.excludeSystemGlobs:
if exclude.matches(basename):
return True
for exclude in package.excludedFilenames: # Also check if it was explicitly excluded. As above,
if exclude.matches(self.filename): # omit this check for an explicitly-added file: if you
return True # both include and exclude a file, the file is
# included.
for exclude in package.excludedFilenames:
if exclude.matches(self.filename):
return True
return False return False
@ -115,12 +126,15 @@ class Packager:
self.version = None self.version = None
self.platform = None self.platform = None
self.p3dApplication = False self.p3dApplication = False
self.displayName = None
self.compressionLevel = 0 self.compressionLevel = 0
self.importedMapsDir = 'imported_maps' self.importedMapsDir = 'imported_maps'
self.mainModule = None self.mainModule = None
self.requires = [] 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 # This is the set of files and modules, already included
# by required packages, that we can skip. # by required packages, that we can skip.
self.skipFilenames = {} self.skipFilenames = {}
@ -369,7 +383,7 @@ class Packager:
filename = Filename.fromOsSpecific(filename) filename = Filename.fromOsSpecific(filename)
filename.resolveFilename(path) filename.resolveFilename(path)
self.addFile(filename, newName = filename.getBasename(), self.addFile(filename, newName = filename.getBasename(),
executable = True) explicit = False, executable = True)
def __parseDependenciesWindows(self, tempFile): def __parseDependenciesWindows(self, tempFile):
""" Reads the indicated temporary file, the output from """ Reads the indicated temporary file, the output from
@ -451,7 +465,7 @@ class Packager:
filename = Filename.fromOsSpecific(filename) filename = Filename.fromOsSpecific(filename)
filename.resolveFilename(path) filename.resolveFilename(path)
self.addFile(filename, newName = filename.getBasename(), self.addFile(filename, newName = filename.getBasename(),
executable = True) explicit = False, executable = True)
def __parseDependenciesOSX(self, tempFile): def __parseDependenciesOSX(self, tempFile):
""" Reads the indicated temporary file, the output from """ Reads the indicated temporary file, the output from
@ -522,7 +536,7 @@ class Packager:
filename = Filename.fromOsSpecific(filename) filename = Filename.fromOsSpecific(filename)
filename.resolveFilename(path) filename.resolveFilename(path)
self.addFile(filename, newName = filename.getBasename(), self.addFile(filename, newName = filename.getBasename(),
executable = True) explicit = False, executable = True)
def __parseDependenciesPosix(self, tempFile): def __parseDependenciesPosix(self, tempFile):
""" Reads the indicated temporary file, the output from """ Reads the indicated temporary file, the output from
@ -560,7 +574,8 @@ class Packager:
newName += '/' + filename.getBasename() newName += '/' + filename.getBasename()
# Sometimes the PYTHONPATH has the wrong case in it. # Sometimes the PYTHONPATH has the wrong case in it.
filename.makeTrueCase() filename.makeTrueCase()
self.addFile(filename, newName = newName, extract = True) self.addFile(filename, newName = newName,
explicit = False, extract = True)
freezer.extras = [] freezer.extras = []
@ -579,11 +594,14 @@ class Packager:
if self.version: if self.version:
xpackage.SetAttribute('version', self.version) xpackage.SetAttribute('version', self.version)
if self.displayName:
xpackage.SetAttribute('display_name', self.displayName)
xpackage.SetAttribute('main_module', self.mainModule) 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: for package in self.requires:
xrequires = TiXmlElement('requires') xrequires = TiXmlElement('requires')
xrequires.SetAttribute('name', package.packageName) xrequires.SetAttribute('name', package.packageName)
@ -628,8 +646,11 @@ class Packager:
if self.version: if self.version:
xpackage.SetAttribute('version', self.version) xpackage.SetAttribute('version', self.version)
if self.displayName: for variable, value in self.configs.items():
xpackage.SetAttribute('display_name', self.displayName) if isinstance(value, types.UnicodeType):
xpackage.SetAttribute(variable, value.encode('utf-8'))
else:
xpackage.SetAttribute(variable, str(value))
for package in self.requires: for package in self.requires:
xrequires = TiXmlElement('requires') xrequires = TiXmlElement('requires')
@ -872,7 +893,8 @@ class Packager:
self.importedMapsDir, filename.getBasenameWoExtension(), self.importedMapsDir, filename.getBasenameWoExtension(),
uniqueId, filename.getExtension()) uniqueId, filename.getExtension())
self.addFile(filename, newName = newName, compress = False) self.addFile(filename, newName = newName, explicit = False,
compress = False)
def addComponent(self, file): def addComponent(self, file):
if file.platformSpecific: if file.platformSpecific:
@ -916,24 +938,25 @@ class Packager:
self.persistDir = None self.persistDir = None
# A search list of directories and/or URL's to search for # A search list of directories and/or URL's to search for
# installed packages. # installed packages. We query it from a config variable
self.installSearch = [] # 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. # The system PATH, for searching dll's and exe's.
self.dllPath = DSearchPath() self.executablePath = DSearchPath()
if PandaSystem.getPlatform().startswith('win'): if PandaSystem.getPlatform().startswith('win'):
self.addWindowsSearchPath(self.dllPath, "PATH") self.addWindowsSearchPath(self.executablePath, "PATH")
elif PandaSystem.getPlatform().startswith('osx'): elif PandaSystem.getPlatform().startswith('osx'):
self.addPosixSearchPath(self.dllPath, "DYLD_LIBRARY_PATH") self.addPosixSearchPath(self.executablePath, "DYLD_LIBRARY_PATH")
self.addPosixSearchPath(self.dllPath, "LD_LIBRARY_PATH") self.addPosixSearchPath(self.executablePath, "LD_LIBRARY_PATH")
self.addPosixSearchPath(self.dllPath, "PATH") self.addPosixSearchPath(self.executablePath, "PATH")
self.dllPath.appendDirectory('/lib') self.executablePath.appendDirectory('/lib')
self.dllPath.appendDirectory('/usr/lib') self.executablePath.appendDirectory('/usr/lib')
else: else:
self.addPosixSearchPath(self.dllPath, "LD_LIBRARY_PATH") self.addPosixSearchPath(self.executablePath, "LD_LIBRARY_PATH")
self.addPosixSearchPath(self.dllPath, "PATH") self.addPosixSearchPath(self.executablePath, "PATH")
self.dllPath.appendDirectory('/lib') self.executablePath.appendDirectory('/lib')
self.dllPath.appendDirectory('/usr/lib') self.executablePath.appendDirectory('/usr/lib')
# The platform string. # The platform string.
self.platform = PandaSystem.getPlatform() self.platform = PandaSystem.getPlatform()
@ -1286,6 +1309,32 @@ class Packager:
value = ExecutionEnvironment.expandString(value.strip()) value = ExecutionEnvironment.expandString(value.strip())
ExecutionEnvironment.setEnvironmentVariable(variable, value) 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): def parse_begin_package(self, words):
""" """
begin_package packageName [version=v] begin_package packageName [version=v]
@ -1338,20 +1387,23 @@ class Packager:
self.endPackage(packageName, p3dApplication = True) self.endPackage(packageName, p3dApplication = True)
def parse_display_name(self, words): def parse_config(self, words):
""" """
display_name "name" config variable=value
""" """
try: try:
command, displayName = words command, assign = words
except ValueError: 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: variable = variable.strip()
raise OutsideOfPackageError self.config(variable, value)
self.currentPackage.displayName = displayName
def parse_require(self, words): def parse_require(self, words):
""" """
@ -1368,32 +1420,6 @@ class Packager:
version = args.get('version', None) version = args.get('version', None)
self.require(packageName, version = version) 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): def parse_module(self, words):
""" """
module moduleName [newName] module moduleName [newName]
@ -1624,10 +1650,10 @@ class Packager:
return package return package
# Look on the searchlist. # Look on the searchlist.
for path in self.installSearch: for dirname in self.installSearch.getDirectories():
package = self.__scanPackageDir(path, packageName, platform, version, requires = requires) package = self.__scanPackageDir(dirname, packageName, platform, version, requires = requires)
if not package: if not package:
package = self.__scanPackageDir(path, packageName, None, version, requires = requires) package = self.__scanPackageDir(dirname, packageName, None, version, requires = requires)
if package: if package:
package = self.packages.setdefault((package.packageName, package.platform, package.version), package) package = self.packages.setdefault((package.packageName, package.platform, package.version), package)
@ -1727,9 +1753,9 @@ class Packager:
if not requires: if not requires:
return True return True
# Really, we only check the panda3d package for now. The # Really, we only check the panda3d package. The other
# other packages will list this as a dependency, and this is # packages will list this as a dependency, and this is all
# all that matters. # that matters.
panda1 = self.__findPackageInList('panda3d', [package] + package.requires) panda1 = self.__findPackageInList('panda3d', [package] + package.requires)
panda2 = self.__findPackageInList('panda3d', requires) panda2 = self.__findPackageInList('panda3d', requires)
@ -1760,6 +1786,17 @@ class Packager:
return None 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): def require(self, packageName, version = None):
""" Indicates a dependency on the named package, supplied as """ Indicates a dependency on the named package, supplied as
a name. a name.
@ -1878,7 +1915,7 @@ class Packager:
basename = freezer.generateCode(basename, compileToExe = compileToExe) basename = freezer.generateCode(basename, compileToExe = compileToExe)
package.addFile(Filename(basename), newName = dirname + basename, package.addFile(Filename(basename), newName = dirname + basename,
deleteTemp = True, extract = True) deleteTemp = True, explicit = True, extract = True)
package.addExtensionModules() package.addExtensionModules()
if not package.platform: if not package.platform:
package.platform = PandaSystem.getPlatform() package.platform = PandaSystem.getPlatform()
@ -1924,6 +1961,7 @@ class Packager:
files = glob.glob(filename.toOsSpecific()) files = glob.glob(filename.toOsSpecific())
if not files: if not files:
files = [filename.toOsSpecific()] files = [filename.toOsSpecific()]
explicit = (len(files) == 1)
newName = None newName = None
prefix = '' prefix = ''
@ -1946,7 +1984,7 @@ class Packager:
self.currentPackage.addFile( self.currentPackage.addFile(
filename, newName = name, extract = extract, filename, newName = name, extract = extract,
executable = executable) explicit = explicit, executable = executable)
def exclude(self, filename): def exclude(self, filename):
""" Marks the indicated filename as not to be included. The """ Marks the indicated filename as not to be included. The
@ -1996,7 +2034,8 @@ class Packager:
# It's a file name. Add it. # It's a file name. Add it.
ext = filename.getExtension() ext = filename.getExtension()
if ext == 'py': if ext == 'py':
self.currentPackage.addFile(filename, newName = newName) self.currentPackage.addFile(filename, newName = newName,
explicit = False)
else: else:
if ext == 'pz': if ext == 'pz':
# Strip off an implicit .pz extension. # Strip off an implicit .pz extension.
@ -2006,4 +2045,5 @@ class Packager:
ext = newFilename.getExtension() ext = newFilename.getExtension()
if ext in self.knownExtensions: if ext in self.knownExtensions:
self.currentPackage.addFile(filename, newName = newName) self.currentPackage.addFile(filename, newName = newName,
explicit = False)

View File

@ -78,7 +78,7 @@ def makePackedApp(args):
elif option == '-r': elif option == '-r':
requires.append(value) requires.append(value)
elif option == '-s': elif option == '-s':
packager.installSearch.append(Filename.fromOsSpecific(value)) packager.installSearch.appendDirectory(Filename.fromOsSpecific(value))
elif option == '-x': elif option == '-x':
versionIndependent = True versionIndependent = True
elif option == '-h': elif option == '-h':

View File

@ -83,7 +83,7 @@ for opt, arg in opts:
if opt == '-i': if opt == '-i':
packager.installDir = Filename.fromOsSpecific(arg) packager.installDir = Filename.fromOsSpecific(arg)
elif opt == '-s': elif opt == '-s':
packager.installSearch.append(Filename.fromOsSpecific(arg)) packager.installSearch.appendDirectory(Filename.fromOsSpecific(arg))
elif opt == '-d': elif opt == '-d':
packager.persistDir = Filename.fromOsSpecific(arg) packager.persistDir = Filename.fromOsSpecific(arg)
elif opt == '-p': elif opt == '-p':
@ -108,7 +108,7 @@ packageDef = Filename.fromOsSpecific(args[0])
if not packager.installDir: if not packager.installDir:
packager.installDir = Filename('install') packager.installDir = Filename('install')
packager.installSearch = [packager.installDir] + packager.installSearch packager.installSearch.prependDirectory(packager.installDir)
packager.setup() packager.setup()
packages = packager.readPackageDef(packageDef) packages = packager.readPackageDef(packageDef)

View File

@ -65,6 +65,8 @@ class AppRunner(DirectObject):
self.windowOpened = False self.windowOpened = False
self.windowPrc = None self.windowPrc = None
self.fullDiskAccess = False
self.Undefined = Undefined self.Undefined = Undefined
self.ConcreteStruct = ConcreteStruct self.ConcreteStruct = ConcreteStruct
@ -139,22 +141,36 @@ class AppRunner(DirectObject):
vfs = VirtualFileSystem.getGlobalPtr() vfs = VirtualFileSystem.getGlobalPtr()
# Clear *all* the mount points, including "/", so that we no # Unmount directories we don't need. This doesn't provide
# longer access the disk directly. # actual security, since it only disables this stuff for users
vfs.unmountAll() # 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 # Make sure the directories on our standard Python path
# read-only, so we can still load Python. # are mounted read-only, so we can still load Python.
for dirname in sys.path: # Note: read-only actually doesn't have any effect on the
vfs.mount(dirname, dirname, vfs.MFReadOnly) # 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 # Also mount some standard directories read-write
# app-data directories). # (temporary and app-data directories).
tdir = Filename.temporary('', '') tdir = Filename.temporary('', '')
for dirname in set([ tdir.getDirname(), for dirname in set([ tdir.getDirname(),
Filename.getTempDirectory().cStr(), Filename.getTempDirectory().cStr(),
Filename.getUserAppdataDirectory().cStr(), Filename.getUserAppdataDirectory().cStr(),
Filename.getCommonAppdataDirectory().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) vfs.mount(dirname, dirname, 0)
# Now set up Python to import this stuff. # Now set up Python to import this stuff.
@ -257,12 +273,30 @@ class AppRunner(DirectObject):
raise ArgumentError, "No such file: %s" % (p3dFilename) raise ArgumentError, "No such file: %s" % (p3dFilename)
fname.makeAbsolute() fname.makeAbsolute()
self.initPackedAppEnvironment()
mf = Multifile() mf = Multifile()
if not mf.openRead(fname): if not mf.openRead(fname):
raise ArgumentError, "Not a Panda Multifile: %s" % (p3dFilename) 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. # Mount the Multifile under /mf, by convention.
vfs.mount(mf, MultifileRoot, vfs.MFReadOnly) vfs.mount(mf, MultifileRoot, vfs.MFReadOnly)
@ -278,19 +312,6 @@ class AppRunner(DirectObject):
data = open(pathname, 'r').read() data = open(pathname, 'r').read()
loadPrcFileData(pathname, data) 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 self.gotP3DFilename = True
# Send this call to the main thread; don't call it directly. # Send this call to the main thread; don't call it directly.