super mirror

This commit is contained in:
David Rose 2009-09-23 23:31:38 +00:00
parent d2307eb838
commit 508b92005f
20 changed files with 209 additions and 49 deletions

View File

@ -102,6 +102,13 @@ class AppRunner(DirectObject):
# the instance starts up. # the instance starts up.
self.rootDir = None self.rootDir = None
# self.superMirrorUrl, if nonempty, is the "super mirror" URL
# that should be contacted first before trying the actual
# host. This is primarily used for "downloading" from a
# locally-stored Panda3D installation. This is also filled in
# when the instance starts up.
self.superMirrorUrl = None
# A list of the Panda3D packages that have been loaded. # A list of the Panda3D packages that have been loaded.
self.installedPackages = [] self.installedPackages = []
@ -430,11 +437,7 @@ class AppRunner(DirectObject):
interactiveConsole = self.interactiveConsole interactiveConsole = self.interactiveConsole
self.interactiveConsole = False self.interactiveConsole = False
try: __import__(moduleName)
__import__(moduleName)
except ImportError:
message = "No %s found in application." % (moduleName)
raise StandardError, message
main = sys.modules[moduleName] main = sys.modules[moduleName]
if hasattr(main, 'main') and callable(main.main): if hasattr(main, 'main') and callable(main.main):
main.main(self) main.main(self)
@ -469,15 +472,17 @@ class AppRunner(DirectObject):
needsResponse = False) needsResponse = False)
self.deferredEvals = [] self.deferredEvals = []
def setInstanceInfo(self, rootDir): def setInstanceInfo(self, rootDir, superMirrorUrl):
""" Called by the browser to set some global information about """ Called by the browser to set some global information about
the instance. """ the instance. """
# At the present, this only includes rootDir, which is the # rootDir is the root Panda3D install directory on the local
# root Panda3D install directory on the local machine. # machine.
self.rootDir = Filename.fromOsSpecific(rootDir) self.rootDir = Filename.fromOsSpecific(rootDir)
# The "super mirror" URL, generally used only by panda3d.exe.
self.superMirrorUrl = superMirrorUrl
def addPackageInfo(self, name, platform, version, hostUrl): def addPackageInfo(self, name, platform, version, hostUrl):
""" Called by the browser to list all of the "required" """ Called by the browser to list all of the "required"
packages that were preloaded before starting the packages that were preloaded before starting the
@ -809,7 +814,7 @@ def dummyAppRunner(tokens = [], argv = None):
if AppRunnerGlobal.appRunner: if AppRunnerGlobal.appRunner:
print "Already have AppRunner, not creating a new one." print "Already have AppRunner, not creating a new one."
return return AppRunnerGlobal.appRunner
appRunner = AppRunner() appRunner = AppRunner()
appRunner.dummy = True appRunner.dummy = True

View File

@ -25,6 +25,7 @@ class HostInfo:
assert appRunner or hostDir assert appRunner or hostDir
self.hostUrl = hostUrl self.hostUrl = hostUrl
self.appRunner = appRunner
self.hostDir = hostDir self.hostDir = hostDir
self.asMirror = asMirror self.asMirror = asMirror

View File

@ -532,16 +532,24 @@ class PackageInfo:
if not urlbase: if not urlbase:
urlbase = self.descFileDirname + '/' + fileSpec.filename urlbase = self.descFileDirname + '/' + fileSpec.filename
# Build up a list of URL's to try downloading from. # Build up a list of URL's to try downloading from. Unlike
# the C++ implementation in P3DPackage.cxx, here we build the
# URL's in forward order.
tryUrls = [] tryUrls = []
if self.host.appRunner and self.host.appRunner.superMirrorUrl:
# We start with the "super mirror", if it's defined.
url = self.host.appRunner.superMirrorUrl + urlbase
tryUrls.append(url)
if self.host.mirrors: if self.host.mirrors:
# Choose a mirror at random first, then a different # Choose two mirrors at random.
# mirror.
mirrors = self.host.mirrors[:] mirrors = self.host.mirrors[:]
for i in range(2): for i in range(2):
mirror = random.choice(mirrors) mirror = random.choice(mirrors)
mirrors.remove(mirror) mirrors.remove(mirror)
tryUrls.append(mirror + urlbase) url = mirror + urlbase
tryUrls.append(url)
if not mirrors: if not mirrors:
break break

View File

@ -458,7 +458,7 @@ class Packager:
continue continue
if mdef.exclude and mdef.implicit: if mdef.exclude and mdef.implicit:
# Don't bother mentioning implicity-excluded # Don't bother mentioning implicitly-excluded
# (i.e. missing) modules. # (i.e. missing) modules.
continue continue
@ -1529,10 +1529,8 @@ class Packager:
# The following are config settings that the caller may adjust # The following are config settings that the caller may adjust
# before calling any of the command methods. # before calling any of the command methods.
# These should each be a Filename, or None if they are not # This should be set to a Filename.
# filled in.
self.installDir = None self.installDir = None
self.persistDir = None
# The download URL at which these packages will eventually be # The download URL at which these packages will eventually be
# hosted. # hosted.

View File

@ -14,6 +14,12 @@ from pandac.PandaModules import getModelPath, Filename, ConfigVariableFilename
# and then a number of smaller, optional packages, which may or may # and then a number of smaller, optional packages, which may or may
# not be needed by any one particular application. # not be needed by any one particular application.
packager.setHost('file:///home/drose/p3dstage',
mirrors = ['file:///home/drose/p3dstage_mirror1',
'file:///home/drose/p3dstage_mirror2',
'file:///home/drose/p3dstage_mirror3',
'file:///home/drose/p3dstage_mirror4'])
class coreapi(solo): class coreapi(solo):
# The special "coreapi" package. As a "solo", this is just a # The special "coreapi" package. As a "solo", this is just a
# single .dll (or dylib, or whatever). # single .dll (or dylib, or whatever).
@ -102,6 +108,7 @@ class panda3d(package):
'direct.gui.*', 'direct.gui.*',
'direct.interval.*', 'direct.interval.*',
'direct.particles.*', 'direct.particles.*',
'direct.p3d.*',
'direct.showbase.*', 'direct.showbase.*',
'direct.showutil.*', 'direct.showutil.*',
'direct.stdpy.*') 'direct.stdpy.*')

View File

@ -61,15 +61,6 @@ Options:
This option may be repeated as necessary. These directories may This option may be repeated as necessary. These directories may
also be specified with the pdef-path Config.prc variable. also be specified with the pdef-path Config.prc variable.
-d persist_dir
The full path to a local directory that retains persistant state
between publishes. This directory structure keeps files that are
used to build patches for future releases. You should keep this
directory structure around for as long as you plan to support
this package. If this directory structure does not exist or is
empty, patches will not be created for this publish; but the
directory structure will be populated for the next publish.
-u host_url -u host_url
Specifies the URL to the download server that will eventually Specifies the URL to the download server that will eventually
host these packages (that is, the public URL of the install host these packages (that is, the public URL of the install
@ -119,7 +110,7 @@ packager = Packager.Packager()
buildPatches = False buildPatches = False
try: try:
opts, args = getopt.getopt(sys.argv[1:], 'i:ps:d:DP:u:n:h') opts, args = getopt.getopt(sys.argv[1:], 'i:ps:DP:u:n:h')
except getopt.error, msg: except getopt.error, msg:
usage(1, msg) usage(1, msg)
@ -130,8 +121,6 @@ for opt, arg in opts:
buildPatches = True buildPatches = True
elif opt == '-s': elif opt == '-s':
packager.installSearch.appendDirectory(Filename.fromOsSpecific(arg)) packager.installSearch.appendDirectory(Filename.fromOsSpecific(arg))
elif opt == '-d':
packager.persistDir = Filename.fromOsSpecific(arg)
elif opt == '-D': elif opt == '-D':
packager.allowPythonDev = True packager.allowPythonDev = True
elif opt == '-P': elif opt == '-P':

View File

@ -36,6 +36,7 @@ static const string default_plugin_filename = "p3d_plugin";
P3D_initialize_func *P3D_initialize; P3D_initialize_func *P3D_initialize;
P3D_finalize_func *P3D_finalize; P3D_finalize_func *P3D_finalize;
P3D_set_super_mirror_func *P3D_set_super_mirror;
P3D_new_instance_func *P3D_new_instance; P3D_new_instance_func *P3D_new_instance;
P3D_instance_start_func *P3D_instance_start; P3D_instance_start_func *P3D_instance_start;
P3D_instance_finish_func *P3D_instance_finish; P3D_instance_finish_func *P3D_instance_finish;
@ -187,6 +188,7 @@ load_plugin(const string &p3d_plugin_filename,
// Now get all of the function pointers. // Now get all of the function pointers.
P3D_initialize = (P3D_initialize_func *)get_func(module, "P3D_initialize"); P3D_initialize = (P3D_initialize_func *)get_func(module, "P3D_initialize");
P3D_finalize = (P3D_finalize_func *)get_func(module, "P3D_finalize"); P3D_finalize = (P3D_finalize_func *)get_func(module, "P3D_finalize");
P3D_set_super_mirror = (P3D_set_super_mirror_func *)get_func(module, "P3D_set_super_mirror");
P3D_new_instance = (P3D_new_instance_func *)get_func(module, "P3D_new_instance"); P3D_new_instance = (P3D_new_instance_func *)get_func(module, "P3D_new_instance");
P3D_instance_start = (P3D_instance_start_func *)get_func(module, "P3D_instance_start"); P3D_instance_start = (P3D_instance_start_func *)get_func(module, "P3D_instance_start");
P3D_instance_finish = (P3D_instance_finish_func *)get_func(module, "P3D_instance_finish"); P3D_instance_finish = (P3D_instance_finish_func *)get_func(module, "P3D_instance_finish");
@ -226,6 +228,7 @@ load_plugin(const string &p3d_plugin_filename,
// Ensure that all of the function pointers have been found. // Ensure that all of the function pointers have been found.
if (P3D_initialize == NULL || if (P3D_initialize == NULL ||
P3D_finalize == NULL || P3D_finalize == NULL ||
P3D_set_super_mirror == NULL ||
P3D_new_instance == NULL || P3D_new_instance == NULL ||
P3D_instance_start == NULL || P3D_instance_start == NULL ||
P3D_instance_finish == NULL || P3D_instance_finish == NULL ||
@ -265,6 +268,7 @@ load_plugin(const string &p3d_plugin_filename,
<< "Some function pointers not found:" << "Some function pointers not found:"
<< "\nP3D_initialize = " << P3D_initialize << "\nP3D_initialize = " << P3D_initialize
<< "\nP3D_finalize = " << P3D_finalize << "\nP3D_finalize = " << P3D_finalize
<< "\nP3D_set_super_mirror = " << P3D_set_super_mirror
<< "\nP3D_new_instance = " << P3D_new_instance << "\nP3D_new_instance = " << P3D_new_instance
<< "\nP3D_instance_start = " << P3D_instance_start << "\nP3D_instance_start = " << P3D_instance_start
<< "\nP3D_instance_finish = " << P3D_instance_finish << "\nP3D_instance_finish = " << P3D_instance_finish
@ -358,6 +362,7 @@ unload_dso() {
P3D_initialize = NULL; P3D_initialize = NULL;
P3D_finalize = NULL; P3D_finalize = NULL;
P3D_set_super_mirror = NULL;
P3D_new_instance = NULL; P3D_new_instance = NULL;
P3D_instance_start = NULL; P3D_instance_start = NULL;
P3D_instance_finish = NULL; P3D_instance_finish = NULL;

View File

@ -22,6 +22,7 @@ using namespace std;
extern P3D_initialize_func *P3D_initialize; extern P3D_initialize_func *P3D_initialize;
extern P3D_finalize_func *P3D_finalize; extern P3D_finalize_func *P3D_finalize;
extern P3D_set_super_mirror_func *P3D_set_super_mirror;
extern P3D_new_instance_func *P3D_new_instance; extern P3D_new_instance_func *P3D_new_instance;
extern P3D_instance_start_func *P3D_instance_start; extern P3D_instance_start_func *P3D_instance_start;
extern P3D_instance_finish_func *P3D_instance_finish; extern P3D_instance_finish_func *P3D_instance_finish;

View File

@ -847,10 +847,6 @@ start_download(P3DDownload *download) {
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
// Since we're downloading something, we might as well check all
// contents files from this point on.
inst_mgr->reset_verify_contents();
int download_id = inst_mgr->get_unique_id(); int download_id = inst_mgr->get_unique_id();
download->set_download_id(download_id); download->set_download_id(download_id);
@ -912,6 +908,9 @@ make_xml() {
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
xinstance->SetAttribute("root_dir", inst_mgr->get_root_dir()); xinstance->SetAttribute("root_dir", inst_mgr->get_root_dir());
if (!inst_mgr->get_super_mirror().empty()) {
xinstance->SetAttribute("super_mirror", inst_mgr->get_super_mirror());
}
TiXmlElement *xfparams = _fparams.make_xml(); TiXmlElement *xfparams = _fparams.make_xml();
xinstance->LinkEndChild(xfparams); xinstance->LinkEndChild(xfparams);

View File

@ -122,6 +122,16 @@ get_trusted_environment() const {
return _trusted_environment; return _trusted_environment;
} }
////////////////////////////////////////////////////////////////////
// Function: P3DInstanceManager::get_super_mirror
// Access: Public
// Description: Returns the "super mirror" URL. See p3d_plugin.h.
////////////////////////////////////////////////////////////////////
inline const string &P3DInstanceManager::
get_super_mirror() const {
return _super_mirror_url;
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: P3DInstanceManager::get_num_instances // Function: P3DInstanceManager::get_num_instances
// Access: Public // Access: Public

View File

@ -296,6 +296,21 @@ initialize(const string &contents_filename, const string &download_url,
return true; return true;
} }
////////////////////////////////////////////////////////////////////
// Function: P3DInstanceManager::set_super_mirror
// Access: Public
// Description: Specifies the "super mirror" URL. See p3d_plugin.h.
////////////////////////////////////////////////////////////////////
void P3DInstanceManager::
set_super_mirror(const string &super_mirror_url) {
_super_mirror_url = super_mirror_url;
// Make sure it ends with a slash.
if (!_super_mirror_url.empty() && _super_mirror_url[_super_mirror_url.size() - 1] != '/') {
_super_mirror_url += '/';
}
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: P3DInstanceManager::create_instance // Function: P3DInstanceManager::create_instance
// Access: Public // Access: Public

View File

@ -67,6 +67,9 @@ public:
inline const string &get_log_pathname() const; inline const string &get_log_pathname() const;
inline bool get_trusted_environment() const; inline bool get_trusted_environment() const;
void set_super_mirror(const string &super_mirror_url);
inline const string &get_super_mirror() const;
P3DInstance * P3DInstance *
create_instance(P3D_request_ready_func *func, create_instance(P3D_request_ready_func *func,
const P3D_token tokens[], size_t num_tokens, const P3D_token tokens[], size_t num_tokens,
@ -129,6 +132,7 @@ private:
string _log_pathname; string _log_pathname;
string _temp_directory; string _temp_directory;
bool _trusted_environment; bool _trusted_environment;
string _super_mirror_url;
P3D_object *_undefined_object; P3D_object *_undefined_object;
P3D_object *_none_object; P3D_object *_none_object;

View File

@ -945,6 +945,22 @@ start_download(P3DPackage::DownloadType dtype, const string &urlbase,
} }
} }
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
if (dtype == DT_contents_file && inst_mgr->get_verify_contents()) {
// When we're dowloading the contents file with verify_contents
// true, we always go straight to the authoritative host, not even
// to the super-mirror.
} else {
// In other cases, if the "super mirror" is enabled, we try that
// first.
if (!inst_mgr->get_super_mirror().empty()) {
string url = inst_mgr->get_super_mirror() + urlbase;
download->_try_urls.push_back(url);
}
}
// OK, start the download. // OK, start the download.
assert(!download->_try_urls.empty()); assert(!download->_try_urls.empty());
url = download->_try_urls.back(); url = download->_try_urls.back();

View File

@ -1116,8 +1116,13 @@ set_instance_info(P3DCInstance *inst, TiXmlElement *xinstance) {
root_dir = ""; root_dir = "";
} }
const char *super_mirror = xinstance->Attribute("super_mirror");
if (super_mirror == NULL) {
super_mirror = "";
}
PyObject *result = PyObject_CallMethod PyObject *result = PyObject_CallMethod
(_runner, (char *)"setInstanceInfo", (char *)"s", root_dir); (_runner, (char *)"setInstanceInfo", (char *)"ss", root_dir, super_mirror);
if (result == NULL) { if (result == NULL) {
PyErr_Print(); PyErr_Print();

View File

@ -850,8 +850,9 @@ start_p3dpython(P3DInstance *inst) {
_env += python_path; _env += python_path;
_env += '\0'; _env += '\0';
// Let's leave PYTHONHOME empty. Setting it adds junk to our
// carefully-constructed PYTHONPATH.
_env += "PYTHONHOME="; _env += "PYTHONHOME=";
_env += _python_root_dir;
_env += '\0'; _env += '\0';
_env += "PRC_PATH="; _env += "PRC_PATH=";

View File

@ -84,11 +84,23 @@ P3D_finalize() {
P3DInstanceManager::delete_global_ptr(); P3DInstanceManager::delete_global_ptr();
} }
void
P3D_set_super_mirror(const char *super_mirror_url) {
assert(P3DInstanceManager::get_global_ptr()->is_initialized());
if (super_mirror_url == NULL) {
super_mirror_url = "";
}
ACQUIRE_LOCK(_api_lock);
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
inst_mgr->set_super_mirror(super_mirror_url);
RELEASE_LOCK(_api_lock);
}
P3D_instance * P3D_instance *
P3D_new_instance(P3D_request_ready_func *func, P3D_new_instance(P3D_request_ready_func *func,
const P3D_token tokens[], size_t num_tokens, const P3D_token tokens[], size_t num_tokens,
int argc, const char *argv[], void *user_data) { int argc, const char *argv[], void *user_data) {
nout << "new_instance\n";
assert(P3DInstanceManager::get_global_ptr()->is_initialized()); assert(P3DInstanceManager::get_global_ptr()->is_initialized());
ACQUIRE_LOCK(_api_lock); ACQUIRE_LOCK(_api_lock);
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
@ -101,7 +113,6 @@ P3D_new_instance(P3D_request_ready_func *func,
bool bool
P3D_instance_start(P3D_instance *instance, bool is_local, P3D_instance_start(P3D_instance *instance, bool is_local,
const char *p3d_filename) { const char *p3d_filename) {
nout << "instance_start\n";
assert(P3DInstanceManager::get_global_ptr()->is_initialized()); assert(P3DInstanceManager::get_global_ptr()->is_initialized());
if (p3d_filename == NULL) { if (p3d_filename == NULL) {
p3d_filename = ""; p3d_filename = "";
@ -138,7 +149,6 @@ P3D_instance_setup_window(P3D_instance *instance,
int win_x, int win_y, int win_x, int win_y,
int win_width, int win_height, int win_width, int win_height,
P3D_window_handle parent_window) { P3D_window_handle parent_window) {
nout << "setup_window\n";
assert(P3DInstanceManager::get_global_ptr()->is_initialized()); assert(P3DInstanceManager::get_global_ptr()->is_initialized());
P3DWindowParams wparams(window_type, win_x, win_y, P3DWindowParams wparams(window_type, win_x, win_y,
win_width, win_height, parent_window); win_width, win_height, parent_window);

View File

@ -145,6 +145,22 @@ P3D_initialize_func(int api_version, const char *contents_filename,
typedef void typedef void
P3D_finalize_func(); P3D_finalize_func();
/* This function defines a "super mirror" URL: a special URL that is
consulted first whenever downloading any package referenced by a
p3d file. This setting is global, and affects all package
downloads across all instances. The main purpose of this is to
facilitate local distribution of the Panda3D runtime build, to
allow applications to ship themselves totally self-contained. If
you install the appropriate Panda3D package files into a directory
on disk, and set the "super mirror" to a file:// URL that
references that directory, then users will be able to run your p3d
file without necessarily having an internet connection.
This normally should be set only by the panda3d standalone runtime
executable, not by a web plugin. */
typedef void
P3D_set_super_mirror_func(const char *super_mirror_url);
/********************** INSTANCE MANAGEMENT **************************/ /********************** INSTANCE MANAGEMENT **************************/
/* The following interfaces define the API to manage individual /* The following interfaces define the API to manage individual
@ -852,6 +868,7 @@ P3D_instance_handle_event_func(P3D_instance *instance, P3D_event_data event);
/* Define all of the actual prototypes for the above functions. */ /* Define all of the actual prototypes for the above functions. */
EXPCL_P3D_PLUGIN P3D_initialize_func P3D_initialize; EXPCL_P3D_PLUGIN P3D_initialize_func P3D_initialize;
EXPCL_P3D_PLUGIN P3D_finalize_func P3D_finalize; EXPCL_P3D_PLUGIN P3D_finalize_func P3D_finalize;
EXPCL_P3D_PLUGIN P3D_set_super_mirror_func P3D_set_super_mirror;
EXPCL_P3D_PLUGIN P3D_new_instance_func P3D_new_instance; EXPCL_P3D_PLUGIN P3D_new_instance_func P3D_new_instance;
EXPCL_P3D_PLUGIN P3D_instance_start_func P3D_instance_start; EXPCL_P3D_PLUGIN P3D_instance_start_func P3D_instance_start;

View File

@ -22,6 +22,7 @@
// definition, even though we don't link with dtool. // definition, even though we don't link with dtool.
#include "dtool_platform.h" #include "dtool_platform.h"
#include <ctype.h>
#include <sstream> #include <sstream>
#ifdef _WIN32 #ifdef _WIN32
#include <windows.h> #include <windows.h>
@ -66,10 +67,11 @@ run(int argc, char *argv[]) {
// We prefix a "+" sign to tell gnu getopt not to parse options // We prefix a "+" sign to tell gnu getopt not to parse options
// following the first not-option parameter. (These will be passed // following the first not-option parameter. (These will be passed
// into the sub-process.) // into the sub-process.)
const char *optstr = "+mu:p:fw:t:s:o:l:ih"; const char *optstr = "+mu:M:p:fw:t:s:o:l:ih";
bool allow_multiple = false; bool allow_multiple = false;
string download_url = PANDA_PACKAGE_HOST_URL; string download_url = PANDA_PACKAGE_HOST_URL;
string super_mirror_url;
string this_platform = DTOOL_PLATFORM; string this_platform = DTOOL_PLATFORM;
bool verify_contents = false; bool verify_contents = false;
@ -89,6 +91,10 @@ run(int argc, char *argv[]) {
download_url = optarg; download_url = optarg;
break; break;
case 'M':
super_mirror_url = optarg;
break;
case 'p': case 'p':
this_platform = optarg; this_platform = optarg;
break; break;
@ -181,16 +187,36 @@ run(int argc, char *argv[]) {
return 1; return 1;
} }
// Make sure it ends with a slash. // Make sure the download URL ends with a slash.
if (!download_url.empty() && download_url[download_url.length() - 1] != '/') { if (!download_url.empty() && download_url[download_url.length() - 1] != '/') {
download_url += '/'; download_url += '/';
} }
// If the "super mirror" URL is a filename, convert it to a file:// url.
if (!super_mirror_url.empty()) {
if (!is_url(super_mirror_url)) {
Filename filename = Filename::from_os_specific(super_mirror_url);
filename.make_absolute();
string path = filename.to_os_generic();
if (!path.empty() && path[0] != '/') {
// On Windows, a leading drive letter must be preceded by an
// additional slash.
path = "/" + path;
}
super_mirror_url = "file://" + path;
}
}
if (!get_plugin(download_url, this_platform, verify_contents)) { if (!get_plugin(download_url, this_platform, verify_contents)) {
cerr << "Unable to load Panda3D plugin.\n"; cerr << "Unable to load Panda3D plugin.\n";
return 1; return 1;
} }
// Set up the "super mirror" URL, if specified.
if (!super_mirror_url.empty()) {
P3D_set_super_mirror(super_mirror_url.c_str());
}
int num_instance_filenames, num_instance_args; int num_instance_filenames, num_instance_args;
char **instance_filenames, **instance_args; char **instance_filenames, **instance_args;
@ -682,16 +708,14 @@ P3D_instance *Panda3D::
create_instance(const string &p3d, P3D_window_type window_type, create_instance(const string &p3d, 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, char **args, int num_args) { P3D_window_handle parent_window, char **args, int num_args) {
// If the supplied parameter name is a real file, pass it in on the // Check to see if the p3d filename we were given is a URL, or a
// parameter list. Otherwise, assume it's a URL and let the plugin // local file.
// download it.
Filename p3d_filename = Filename::from_os_specific(p3d); Filename p3d_filename = Filename::from_os_specific(p3d);
string os_p3d_filename = p3d; string os_p3d_filename = p3d;
bool is_local = false; bool is_local = !is_url(p3d);
if (p3d_filename.exists()) { if (is_local) {
p3d_filename.make_absolute(); p3d_filename.make_absolute();
os_p3d_filename = p3d_filename.to_os_specific(); os_p3d_filename = p3d_filename.to_os_specific();
is_local = true;
} }
// Build up the token list. // Build up the token list.
@ -832,8 +856,17 @@ usage() {
<< " code.\n\n" << " code.\n\n"
<< " -u url\n" << " -u url\n"
<< " Specify the URL of the Panda3D download server. The default is\n"
<< " \"" << PANDA_PACKAGE_HOST_URL << "\" .\n\n" << " Specify the URL of the Panda3D download server. This is the host\n"
<< " from which the plugin itself will be downloaded if necessary. The\n"
<< " default is\n \"" << PANDA_PACKAGE_HOST_URL << "\" .\n\n"
<< " -M super_mirror_url\n"
<< " Specifies the \"super mirror\" URL, the special URL that is consulted\n"
<< " first before downloading any package file referenced by a p3d file.\n"
<< " This is primarily intended to support pre-installing a downloadable\n"
<< " Panda3D tree on the local machine, to allow p3d applications to\n"
<< " execute without requiring an internet connection.\n\n"
<< " -p platform\n" << " -p platform\n"
<< " Specify the platform to masquerade as. The default is \"" << " Specify the platform to masquerade as. The default is \""
@ -888,6 +921,39 @@ parse_int_pair(char *arg, int &x, int &y) {
return false; return false;
} }
////////////////////////////////////////////////////////////////////
// Function: Panda3D::is_url
// Access: Private, Static
// Description: Returns true if the indicated string appears to be a
// URL, with a leading http:// or file:// or whatever,
// or false if it must be a local filename instead.
////////////////////////////////////////////////////////////////////
bool Panda3D::
is_url(const string &param) {
// We define a URL prefix as a sequence of at least two letters,
// followed by a colon, followed by at least one slash.
size_t p = 0;
while (p < param.size() && isalpha(param[p])) {
++p;
}
if (p < 2) {
// Not enough letters.
return false;
}
if (p >= param.size() || param[p] != ':') {
// No colon.
return false;
}
++p;
if (p >= param.size() || param[p] != '/') {
// No slash.
return false;
}
// It matches the rules.
return true;
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: Panda3D::report_downloading_package // Function: Panda3D::report_downloading_package
// Access: Private // Access: Private

View File

@ -65,6 +65,7 @@ private:
void usage(); void usage();
bool parse_token(char *arg); bool parse_token(char *arg);
bool parse_int_pair(char *arg, int &x, int &y); bool parse_int_pair(char *arg, int &x, int &y);
static bool is_url(const string &param);
void report_downloading_package(P3D_instance *instance); void report_downloading_package(P3D_instance *instance);
void report_download_complete(P3D_instance *instance); void report_download_complete(P3D_instance *instance);

View File

@ -786,6 +786,8 @@ class Freezer:
continue continue
if origName in self.previousModules: if origName in self.previousModules:
continue continue
if origName in self.modules:
continue
# This module is missing. Let it be missing in the # This module is missing. Let it be missing in the
# runtime also. # runtime also.