소스 검색

support host_dir

David Rose 16 년 전
부모
커밋
4631711957

+ 3 - 4
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

+ 45 - 24
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)

+ 18 - 8
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
 

+ 2 - 0
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.

+ 1 - 0
direct/src/plugin/p3dHost.I

@@ -21,6 +21,7 @@
 ////////////////////////////////////////////////////////////////////
 inline const string &P3DHost::
 get_host_dir() const {
+  assert(!_host_dir.empty());
   return _host_dir;
 }
 

+ 19 - 17
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");

+ 1 - 2
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);

+ 2 - 0
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