From 463171195724b551e603ba6ee54455251146eb08 Mon Sep 17 00:00:00 2001 From: David Rose Date: Thu, 19 Nov 2009 23:59:04 +0000 Subject: [PATCH] support host_dir --- direct/src/p3d/AppRunner.py | 7 ++-- direct/src/p3d/HostInfo.py | 69 +++++++++++++++++++++----------- direct/src/p3d/Packager.py | 26 ++++++++---- direct/src/p3d/panda3d.pdef | 2 + direct/src/plugin/p3dHost.I | 1 + direct/src/plugin/p3dHost.cxx | 36 +++++++++-------- direct/src/plugin/p3dHost.h | 3 +- direct/src/plugin/p3dPackage.cxx | 2 + 8 files changed, 91 insertions(+), 55 deletions(-) diff --git a/direct/src/p3d/AppRunner.py b/direct/src/p3d/AppRunner.py index ee3d4bb662..41f7cbbd00 100644 --- a/direct/src/p3d/AppRunner.py +++ b/direct/src/p3d/AppRunner.py @@ -529,10 +529,9 @@ class AppRunner(DirectObject): host = self.getHost(hostUrl) - if not host.readContentsFile(): - if not host.downloadContentsFile(self.http): - message = "Host %s cannot be downloaded, cannot preload %s." % (hostUrl, name) - raise OSError, message + if not host.downloadContentsFile(self.http): + message = "Host %s cannot be downloaded, cannot preload %s." % (hostUrl, name) + raise OSError, message if not platform: platform = None diff --git a/direct/src/p3d/HostInfo.py b/direct/src/p3d/HostInfo.py index 174235f302..fb1ae398df 100644 --- a/direct/src/p3d/HostInfo.py +++ b/direct/src/p3d/HostInfo.py @@ -30,6 +30,10 @@ class HostInfo: self.hostDir = hostDir self.asMirror = asMirror + self.importsDir = None + if self.hostDir: + self.importsDir = Filename(self.hostDir, 'imports') + # hostUrlPrefix is the host URL, but it is guaranteed to end # with a slash. self.hostUrlPrefix = hostUrl @@ -64,12 +68,6 @@ class HostInfo: # will be filled in when the contents file is read. self.packages = {} - if appRunner: - self.__determineHostDir(appRunner) - - assert self.hostDir - self.importsDir = Filename(self.hostDir, 'imports') - def downloadContentsFile(self, http, redownload = False): """ Downloads the contents.xml file for this particular host, synchronously, and then reads it. Returns true on success, @@ -118,18 +116,22 @@ class HostInfo: print "Unable to download %s" % (url) rf = None - filename = Filename(self.hostDir, 'contents.xml') + tempFilename = Filename.temporary('', 'p3d_', '.xml') if rf: - filename.makeDir() - f = open(filename.toOsSpecific(), 'wb') + f = open(tempFilename.toOsSpecific(), 'wb') f.write(rf.getData()) f.close() - if not self.readContentsFile(): - print "Failure reading %s" % (filename) - return False + if not self.readContentsFile(tempFilename): + print "Failure reading %s" % (url) + tempFilename.unlink() + return False - return True + return True + + # Couldn't download the file. Maybe we should look for a + # previously-downloaded copy already on disk? + return False def redownloadContentsFile(self, http): """ Downloads a new contents.xml file in case it has changed. @@ -141,6 +143,7 @@ class HostInfo: print "Redownloading %s" % (url) # Get the hash of the original file. + assert self.hostDir filename = Filename(self.hostDir, 'contents.xml') hv1 = HashVal() hv1.hashFile(filename) @@ -161,21 +164,19 @@ class HostInfo: return False - def readContentsFile(self): + def readContentsFile(self, tempFilename): """ Reads the contents.xml file for this particular host, once - it has been downloaded. Returns true on success, false if the - contents file is not already on disk or is unreadable. """ + it has been downloaded into the indicated temporary file. + Returns true on success, false if the contents file is not + already on disk or is unreadable. On success, copies the file + into the standard location if it's not there already. """ - if self.hasContentsFile: - # No need to read it again. - return True - - filename = Filename(self.hostDir, 'contents.xml') + assert not self.hasContentsFile if not hasattr(PandaModules, 'TiXmlDocument'): return False - doc = PandaModules.TiXmlDocument(filename.toOsSpecific()) + doc = PandaModules.TiXmlDocument(tempFilename.toOsSpecific()) if not doc.LoadFile(): return False @@ -186,6 +187,9 @@ class HostInfo: # Look for our own entry in the hosts table. self.__findHostXml(xcontents) + if not self.hostDir: + self.__determineHostDir(None) + # Get the list of packages available for download and/or import. xpackage = xcontents.FirstChildElement('package') while xpackage: @@ -212,6 +216,13 @@ class HostInfo: self.hasContentsFile = True + # Now copy the contents.xml file into the standard location. + assert self.hostDir + filename = Filename(self.hostDir, 'contents.xml') + if filename != tempFilename: + filename.makeDir() + tempFilename.copyTo(filename) + return True def __findHostXml(self, xcontents): @@ -244,6 +255,10 @@ class HostInfo: if descriptiveName and not self.descriptiveName: self.descriptiveName = descriptiveName + hostDirBasename = xhost.Attribute('host_dir') + if hostDirBasename and not self.hostDir: + self.__determineHostDir(hostDirBasename) + # Get the "download" URL, which is the source from which we # download everything other than the contents.xml file. downloadUrl = xhost.Attribute('download_url') @@ -333,7 +348,7 @@ class HostInfo: return packages - def __determineHostDir(self, appRunner): + def __determineHostDir(self, hostDirBasename): """ Hashes the host URL into a (mostly) unique directory string, which will be the root of the host's install tree. Stores the resulting path, as a Filename, in self.hostDir. @@ -341,6 +356,12 @@ class HostInfo: This code is duplicated in C++, in P3DHost::determine_host_dir(). """ + if hostDirBasename: + # If the contents.xml specified a host_dir parameter, use + # it. + self.hostDir = Filename(self.appRunner.rootDir, hostDirBasename) + return + hostDir = '' # Look for a server name in the URL. Including this string in the @@ -389,4 +410,4 @@ class HostInfo: md.hashString(self.hostUrl) hostDir += md.asHex()[:keepHash * 2] - self.hostDir = Filename(appRunner.rootDir, hostDir) + self.hostDir = Filename(self.appRunner.rootDir, hostDir) diff --git a/direct/src/p3d/Packager.py b/direct/src/p3d/Packager.py index 62b5aa5851..624043f39b 100644 --- a/direct/src/p3d/Packager.py +++ b/direct/src/p3d/Packager.py @@ -218,10 +218,12 @@ class Packager: class HostEntry: def __init__(self, url = None, downloadUrl = None, - descriptiveName = None, mirrors = None): + descriptiveName = None, hostDir = None, + mirrors = None): self.url = url self.downloadUrl = downloadUrl self.descriptiveName = descriptiveName + self.hostDir = hostDir self.mirrors = mirrors or [] self.altHosts = {} @@ -229,6 +231,7 @@ class Packager: self.url = xhost.Attribute('url') self.downloadUrl = xhost.Attribute('download_url') self.descriptiveName = xhost.Attribute('descriptive_name') + self.hostDir = xhost.Attribute('host_dir') self.mirrors = [] xmirror = xhost.FirstChildElement('mirror') while xmirror: @@ -251,6 +254,8 @@ class Packager: xhost.SetAttribute('download_url', self.downloadUrl) if self.descriptiveName: xhost.SetAttribute('descriptive_name', self.descriptiveName) + if self.hostDir: + xhost.SetAttribute('host_dir', self.hostDir) for mirror in self.mirrors: xmirror = TiXmlElement('mirror') @@ -1823,16 +1828,18 @@ class Packager: self.contents = {} def setHost(self, host, downloadUrl = None, - descriptiveName = None, mirrors = None): + descriptiveName = None, hostDir = None, + mirrors = None): """ Specifies the URL that will ultimately host these contents. """ self.host = host self.addHost(host, downloadUrl = downloadUrl, - descriptiveName = descriptiveName, mirrors = mirrors) + descriptiveName = descriptiveName, hostDir = hostDir, + mirrors = mirrors) def addHost(self, host, downloadUrl = None, descriptiveName = None, - mirrors = None): + hostDir = None, mirrors = None): """ Adds a host to the list of known download hosts. This information will be written into any p3d files that reference this host; this can be used to pre-define the possible mirrors @@ -1853,7 +1860,7 @@ class Packager: # Define a new host entry he = self.HostEntry(host, downloadUrl = downloadUrl, descriptiveName = descriptiveName, - mirrors = mirrors) + hostDir = hostDir, mirrors = mirrors) self.hosts[host] = he else: # Update an existing host entry @@ -1861,14 +1868,16 @@ class Packager: he.downloadUrl = downloadUrl if descriptiveName is not None: he.descriptiveName = descriptiveName + if hostDir is not None: + he.hostDir = hostDir if mirrors is not None: he.mirrors = mirrors return he def addAltHost(self, keyword, altHost, origHost = None, - downloadUrl = None, - descriptiveName = None, mirrors = None): + downloadUrl = None, descriptiveName = None, + hostDir = None, mirrors = None): """ Adds an alternate host to any already-known host. This defines an alternate server that may be contacted, if specified on the HTML page, which hosts a different version of @@ -1880,7 +1889,8 @@ class Packager: origHost = self.host self.addHost(altHost, downloadUrl = downloadUrl, - descriptiveName = descriptiveName, mirrors = mirrors) + descriptiveName = descriptiveName, hostDir = hostDir, + mirrors = mirrors) he = self.addHost(origHost) he.altHosts[keyword] = altHost diff --git a/direct/src/p3d/panda3d.pdef b/direct/src/p3d/panda3d.pdef index fe54c74ccf..248b809bdb 100755 --- a/direct/src/p3d/panda3d.pdef +++ b/direct/src/p3d/panda3d.pdef @@ -16,6 +16,8 @@ from pandac.PandaModules import Filename, PandaSystem, getModelPath # Also see coreapi.pdef. +packager.setHost('file:///home/drose/p3dstage', hostDir = 'droseDir') + class panda3d(package): # The main Panda3D package. Contains Python and most of the graphics # code in Panda3D. diff --git a/direct/src/plugin/p3dHost.I b/direct/src/plugin/p3dHost.I index c2d4caf61e..a31a922a2b 100644 --- a/direct/src/plugin/p3dHost.I +++ b/direct/src/plugin/p3dHost.I @@ -21,6 +21,7 @@ //////////////////////////////////////////////////////////////////// inline const string &P3DHost:: get_host_dir() const { + assert(!_host_dir.empty()); return _host_dir; } diff --git a/direct/src/plugin/p3dHost.cxx b/direct/src/plugin/p3dHost.cxx index 565d979ea1..759b195556 100644 --- a/direct/src/plugin/p3dHost.cxx +++ b/direct/src/plugin/p3dHost.cxx @@ -38,8 +38,6 @@ P3DHost(const string &host_url) : _xcontents = NULL; _contents_seq = 0; - - determine_host_dir(); } //////////////////////////////////////////////////////////////////// @@ -99,20 +97,6 @@ get_alt_host(const string &alt_host) { return this; } -//////////////////////////////////////////////////////////////////// -// Function: P3DHost::read_contents_file -// Access: Public -// Description: Reads the contents.xml file in the standard -// filename, if possible. -// -// Returns true on success, false on failure. -//////////////////////////////////////////////////////////////////// -bool P3DHost:: -read_contents_file() { - string standard_filename = _host_dir + "/contents.xml"; - return read_contents_file(standard_filename); -} - //////////////////////////////////////////////////////////////////// // Function: P3DHost::read_contents_file // Access: Public @@ -175,6 +159,11 @@ read_contents_file(const string &contents_filename) { } } + if (_host_dir.empty()) { + determine_host_dir(""); + } + assert(!_host_dir.empty()); + string standard_filename = _host_dir + "/contents.xml"; if (standardize_filename(standard_filename) != standardize_filename(contents_filename)) { @@ -389,11 +378,19 @@ add_mirror(string mirror_url) { // HostInfo.determineHostDir(). //////////////////////////////////////////////////////////////////// void P3DHost:: -determine_host_dir() { +determine_host_dir(const string &host_dir_basename) { P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); _host_dir = inst_mgr->get_root_dir(); _host_dir += "/"; + if (!host_dir_basename.empty()) { + // If the contents.xml specified a host_dir parameter, use it. + _host_dir += host_dir_basename; + return; + } + + // If we didn't get a host_dir parameter, we have to make one up. + string hostname; // Look for a server name in the URL. Including this string in the @@ -471,6 +468,11 @@ read_xhost(TiXmlElement *xhost) { _descriptive_name = descriptive_name; } + const char *host_dir_basename = xhost->Attribute("host_dir"); + if (host_dir_basename != NULL && _host_dir.empty()) { + determine_host_dir(host_dir_basename); + } + // Get the "download" URL, which is the source from which we // download everything other than the contents.xml file. const char *download_url = xhost->Attribute("download_url"); diff --git a/direct/src/plugin/p3dHost.h b/direct/src/plugin/p3dHost.h index 3d4f98db22..d8c465a00a 100644 --- a/direct/src/plugin/p3dHost.h +++ b/direct/src/plugin/p3dHost.h @@ -46,7 +46,6 @@ public: inline int get_contents_seq() const; inline bool check_contents_hash(const string &pathname) const; - bool read_contents_file(); bool read_contents_file(const string &contents_filename); P3DPackage *get_package(const string &package_name, @@ -64,7 +63,7 @@ public: void add_mirror(string mirror_url); private: - void determine_host_dir(); + void determine_host_dir(const string &host_dir_basename); void read_xhost(TiXmlElement *xhost); static string standardize_filename(const string &filename); diff --git a/direct/src/plugin/p3dPackage.cxx b/direct/src/plugin/p3dPackage.cxx index ef5b1e1ea8..2430b5cf9f 100755 --- a/direct/src/plugin/p3dPackage.cxx +++ b/direct/src/plugin/p3dPackage.cxx @@ -268,12 +268,14 @@ begin_info_download() { //////////////////////////////////////////////////////////////////// void P3DPackage:: download_contents_file() { + /* P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr(); if (!_host->has_contents_file() && !inst_mgr->get_verify_contents()) { // If we're allowed to read a contents file without checking the // server first, try it now. _host->read_contents_file(); } + */ if (_host->has_contents_file()) { // We've already got a contents.xml file; go straight to the