Browse Source

support host_dir

David Rose 16 years ago
parent
commit
4631711957

+ 3 - 4
direct/src/p3d/AppRunner.py

@@ -529,10 +529,9 @@ class AppRunner(DirectObject):
 
 
         host = self.getHost(hostUrl)
         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:
         if not platform:
             platform = None
             platform = None

+ 45 - 24
direct/src/p3d/HostInfo.py

@@ -30,6 +30,10 @@ class HostInfo:
         self.hostDir = hostDir
         self.hostDir = hostDir
         self.asMirror = asMirror
         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
         # hostUrlPrefix is the host URL, but it is guaranteed to end
         # with a slash.
         # with a slash.
         self.hostUrlPrefix = hostUrl
         self.hostUrlPrefix = hostUrl
@@ -64,12 +68,6 @@ class HostInfo:
         # will be filled in when the contents file is read.
         # will be filled in when the contents file is read.
         self.packages = {}
         self.packages = {}
 
 
-        if appRunner:
-            self.__determineHostDir(appRunner)
-
-        assert self.hostDir
-        self.importsDir = Filename(self.hostDir, 'imports')
-
     def downloadContentsFile(self, http, redownload = False):
     def downloadContentsFile(self, http, redownload = False):
         """ Downloads the contents.xml file for this particular host,
         """ Downloads the contents.xml file for this particular host,
         synchronously, and then reads it.  Returns true on success,
         synchronously, and then reads it.  Returns true on success,
@@ -118,18 +116,22 @@ class HostInfo:
                     print "Unable to download %s" % (url)
                     print "Unable to download %s" % (url)
                     rf = None
                     rf = None
 
 
-        filename = Filename(self.hostDir, 'contents.xml')
+        tempFilename = Filename.temporary('', 'p3d_', '.xml')
         if rf:
         if rf:
-            filename.makeDir()
-            f = open(filename.toOsSpecific(), 'wb')
+            f = open(tempFilename.toOsSpecific(), 'wb')
             f.write(rf.getData())
             f.write(rf.getData())
             f.close()
             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):
     def redownloadContentsFile(self, http):
         """ Downloads a new contents.xml file in case it has changed.
         """ Downloads a new contents.xml file in case it has changed.
@@ -141,6 +143,7 @@ class HostInfo:
         print "Redownloading %s" % (url)
         print "Redownloading %s" % (url)
 
 
         # Get the hash of the original file.
         # Get the hash of the original file.
+        assert self.hostDir
         filename = Filename(self.hostDir, 'contents.xml')
         filename = Filename(self.hostDir, 'contents.xml')
         hv1 = HashVal()
         hv1 = HashVal()
         hv1.hashFile(filename)
         hv1.hashFile(filename)
@@ -161,21 +164,19 @@ class HostInfo:
             return False
             return False
 
 
 
 
-    def readContentsFile(self):
+    def readContentsFile(self, tempFilename):
         """ Reads the contents.xml file for this particular host, once
         """ 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'):
         if not hasattr(PandaModules, 'TiXmlDocument'):
             return False
             return False
         
         
-        doc = PandaModules.TiXmlDocument(filename.toOsSpecific())
+        doc = PandaModules.TiXmlDocument(tempFilename.toOsSpecific())
         if not doc.LoadFile():
         if not doc.LoadFile():
             return False
             return False
         
         
@@ -186,6 +187,9 @@ class HostInfo:
         # Look for our own entry in the hosts table.
         # Look for our own entry in the hosts table.
         self.__findHostXml(xcontents)
         self.__findHostXml(xcontents)
 
 
+        if not self.hostDir:
+            self.__determineHostDir(None)
+
         # Get the list of packages available for download and/or import.
         # Get the list of packages available for download and/or import.
         xpackage = xcontents.FirstChildElement('package')
         xpackage = xcontents.FirstChildElement('package')
         while xpackage:
         while xpackage:
@@ -212,6 +216,13 @@ class HostInfo:
 
 
         self.hasContentsFile = True
         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
         return True
 
 
     def __findHostXml(self, xcontents):
     def __findHostXml(self, xcontents):
@@ -244,6 +255,10 @@ class HostInfo:
         if descriptiveName and not self.descriptiveName:
         if descriptiveName and not self.descriptiveName:
             self.descriptiveName = 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
         # Get the "download" URL, which is the source from which we
         # download everything other than the contents.xml file.
         # download everything other than the contents.xml file.
         downloadUrl = xhost.Attribute('download_url')
         downloadUrl = xhost.Attribute('download_url')
@@ -333,7 +348,7 @@ class HostInfo:
 
 
         return packages
         return packages
 
 
-    def __determineHostDir(self, appRunner):
+    def __determineHostDir(self, hostDirBasename):
         """ Hashes the host URL into a (mostly) unique directory
         """ Hashes the host URL into a (mostly) unique directory
         string, which will be the root of the host's install tree.
         string, which will be the root of the host's install tree.
         Stores the resulting path, as a Filename, in self.hostDir.
         Stores the resulting path, as a Filename, in self.hostDir.
@@ -341,6 +356,12 @@ class HostInfo:
         This code is duplicated in C++, in
         This code is duplicated in C++, in
         P3DHost::determine_host_dir(). """
         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 = ''
         hostDir = ''
 
 
         # Look for a server name in the URL.  Including this string in the
         # Look for a server name in the URL.  Including this string in the
@@ -389,4 +410,4 @@ class HostInfo:
         md.hashString(self.hostUrl)
         md.hashString(self.hostUrl)
         hostDir += md.asHex()[:keepHash * 2]
         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:
     class HostEntry:
         def __init__(self, url = None, downloadUrl = None,
         def __init__(self, url = None, downloadUrl = None,
-                     descriptiveName = None, mirrors = None):
+                     descriptiveName = None, hostDir = None,
+                     mirrors = None):
             self.url = url
             self.url = url
             self.downloadUrl = downloadUrl
             self.downloadUrl = downloadUrl
             self.descriptiveName = descriptiveName
             self.descriptiveName = descriptiveName
+            self.hostDir = hostDir
             self.mirrors = mirrors or []
             self.mirrors = mirrors or []
             self.altHosts = {}
             self.altHosts = {}
 
 
@@ -229,6 +231,7 @@ class Packager:
             self.url = xhost.Attribute('url')
             self.url = xhost.Attribute('url')
             self.downloadUrl = xhost.Attribute('download_url')
             self.downloadUrl = xhost.Attribute('download_url')
             self.descriptiveName = xhost.Attribute('descriptive_name')
             self.descriptiveName = xhost.Attribute('descriptive_name')
+            self.hostDir = xhost.Attribute('host_dir')
             self.mirrors = []
             self.mirrors = []
             xmirror = xhost.FirstChildElement('mirror')
             xmirror = xhost.FirstChildElement('mirror')
             while xmirror:
             while xmirror:
@@ -251,6 +254,8 @@ class Packager:
                 xhost.SetAttribute('download_url', self.downloadUrl)
                 xhost.SetAttribute('download_url', self.downloadUrl)
             if self.descriptiveName:
             if self.descriptiveName:
                 xhost.SetAttribute('descriptive_name', self.descriptiveName)
                 xhost.SetAttribute('descriptive_name', self.descriptiveName)
+            if self.hostDir:
+                xhost.SetAttribute('host_dir', self.hostDir)
 
 
             for mirror in self.mirrors:
             for mirror in self.mirrors:
                 xmirror = TiXmlElement('mirror')
                 xmirror = TiXmlElement('mirror')
@@ -1823,16 +1828,18 @@ class Packager:
         self.contents = {}
         self.contents = {}
 
 
     def setHost(self, host, downloadUrl = None,
     def setHost(self, host, downloadUrl = None,
-                descriptiveName = None, mirrors = None):
+                descriptiveName = None, hostDir = None,
+                mirrors = None):
         """ Specifies the URL that will ultimately host these
         """ Specifies the URL that will ultimately host these
         contents. """
         contents. """
 
 
         self.host = host
         self.host = host
         self.addHost(host, downloadUrl = downloadUrl,
         self.addHost(host, downloadUrl = downloadUrl,
-                     descriptiveName = descriptiveName, mirrors = mirrors)
+                     descriptiveName = descriptiveName, hostDir = hostDir,
+                     mirrors = mirrors)
 
 
     def addHost(self, host, downloadUrl = None, descriptiveName = None,
     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
         """ Adds a host to the list of known download hosts.  This
         information will be written into any p3d files that reference
         information will be written into any p3d files that reference
         this host; this can be used to pre-define the possible mirrors
         this host; this can be used to pre-define the possible mirrors
@@ -1853,7 +1860,7 @@ class Packager:
             # Define a new host entry
             # Define a new host entry
             he = self.HostEntry(host, downloadUrl = downloadUrl,
             he = self.HostEntry(host, downloadUrl = downloadUrl,
                                 descriptiveName = descriptiveName,
                                 descriptiveName = descriptiveName,
-                                mirrors = mirrors)
+                                hostDir = hostDir, mirrors = mirrors)
             self.hosts[host] = he
             self.hosts[host] = he
         else:
         else:
             # Update an existing host entry
             # Update an existing host entry
@@ -1861,14 +1868,16 @@ class Packager:
                 he.downloadUrl = downloadUrl
                 he.downloadUrl = downloadUrl
             if descriptiveName is not None:
             if descriptiveName is not None:
                 he.descriptiveName = descriptiveName
                 he.descriptiveName = descriptiveName
+            if hostDir is not None:
+                he.hostDir = hostDir
             if mirrors is not None:
             if mirrors is not None:
                 he.mirrors = mirrors
                 he.mirrors = mirrors
 
 
         return he
         return he
         
         
     def addAltHost(self, keyword, altHost, origHost = None,
     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
         """ Adds an alternate host to any already-known host.  This
         defines an alternate server that may be contacted, if
         defines an alternate server that may be contacted, if
         specified on the HTML page, which hosts a different version of
         specified on the HTML page, which hosts a different version of
@@ -1880,7 +1889,8 @@ class Packager:
             origHost = self.host
             origHost = self.host
 
 
         self.addHost(altHost, downloadUrl = downloadUrl,
         self.addHost(altHost, downloadUrl = downloadUrl,
-                     descriptiveName = descriptiveName, mirrors = mirrors)
+                     descriptiveName = descriptiveName, hostDir = hostDir,
+                     mirrors = mirrors)
         he = self.addHost(origHost)
         he = self.addHost(origHost)
         he.altHosts[keyword] = altHost
         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.
 # Also see coreapi.pdef.
 
 
+packager.setHost('file:///home/drose/p3dstage', hostDir = 'droseDir')
+
 class panda3d(package):
 class panda3d(package):
     # The main Panda3D package.  Contains Python and most of the graphics
     # The main Panda3D package.  Contains Python and most of the graphics
     # code in Panda3D.
     # code in Panda3D.

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

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

+ 19 - 17
direct/src/plugin/p3dHost.cxx

@@ -38,8 +38,6 @@ P3DHost(const string &host_url) :
 
 
   _xcontents = NULL;
   _xcontents = NULL;
   _contents_seq = 0;
   _contents_seq = 0;
-
-  determine_host_dir();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -99,20 +97,6 @@ get_alt_host(const string &alt_host) {
   return this;
   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
 //     Function: P3DHost::read_contents_file
 //       Access: Public
 //       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";
   string standard_filename = _host_dir + "/contents.xml";
   if (standardize_filename(standard_filename) != 
   if (standardize_filename(standard_filename) != 
       standardize_filename(contents_filename)) {
       standardize_filename(contents_filename)) {
@@ -389,11 +378,19 @@ add_mirror(string mirror_url) {
 //               HostInfo.determineHostDir().
 //               HostInfo.determineHostDir().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void P3DHost::
 void P3DHost::
-determine_host_dir() {
+determine_host_dir(const string &host_dir_basename) {
   P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
   P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
   _host_dir = inst_mgr->get_root_dir();
   _host_dir = inst_mgr->get_root_dir();
   _host_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;
   string hostname;
 
 
   // Look for a server name in the URL.  Including this string in the
   // 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;
     _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
   // Get the "download" URL, which is the source from which we
   // download everything other than the contents.xml file.
   // download everything other than the contents.xml file.
   const char *download_url = xhost->Attribute("download_url");
   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 int get_contents_seq() const;
   inline bool check_contents_hash(const string &pathname) const;
   inline bool check_contents_hash(const string &pathname) const;
 
 
-  bool read_contents_file();
   bool read_contents_file(const string &contents_filename);
   bool read_contents_file(const string &contents_filename);
 
 
   P3DPackage *get_package(const string &package_name, 
   P3DPackage *get_package(const string &package_name, 
@@ -64,7 +63,7 @@ public:
   void add_mirror(string mirror_url);
   void add_mirror(string mirror_url);
 
 
 private:
 private:
-  void determine_host_dir();
+  void determine_host_dir(const string &host_dir_basename);
   void read_xhost(TiXmlElement *xhost);
   void read_xhost(TiXmlElement *xhost);
 
 
   static string standardize_filename(const string &filename);
   static string standardize_filename(const string &filename);

+ 2 - 0
direct/src/plugin/p3dPackage.cxx

@@ -268,12 +268,14 @@ begin_info_download() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void P3DPackage::
 void P3DPackage::
 download_contents_file() {
 download_contents_file() {
+  /*
   P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
   P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
   if (!_host->has_contents_file() && !inst_mgr->get_verify_contents()) {
   if (!_host->has_contents_file() && !inst_mgr->get_verify_contents()) {
     // If we're allowed to read a contents file without checking the
     // If we're allowed to read a contents file without checking the
     // server first, try it now.
     // server first, try it now.
     _host->read_contents_file();
     _host->read_contents_file();
   }
   }
+  */
 
 
   if (_host->has_contents_file()) {
   if (_host->has_contents_file()) {
     // We've already got a contents.xml file; go straight to the
     // We've already got a contents.xml file; go straight to the