mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-02 09:52:27 -04:00
wip: host support
This commit is contained in:
parent
494d61083e
commit
ae8c460b1b
@ -32,6 +32,7 @@
|
|||||||
p3dFileDownload.h p3dFileDownload.I \
|
p3dFileDownload.h p3dFileDownload.I \
|
||||||
p3dFileParams.h p3dFileParams.I \
|
p3dFileParams.h p3dFileParams.I \
|
||||||
p3dFloatObject.h \
|
p3dFloatObject.h \
|
||||||
|
p3dHost.h p3dHost.I \
|
||||||
p3dInstance.h p3dInstance.I \
|
p3dInstance.h p3dInstance.I \
|
||||||
p3dInstanceManager.h p3dInstanceManager.I \
|
p3dInstanceManager.h p3dInstanceManager.I \
|
||||||
p3dIntObject.h \
|
p3dIntObject.h \
|
||||||
@ -62,6 +63,7 @@
|
|||||||
p3dFileDownload.cxx \
|
p3dFileDownload.cxx \
|
||||||
p3dFileParams.cxx \
|
p3dFileParams.cxx \
|
||||||
p3dFloatObject.cxx \
|
p3dFloatObject.cxx \
|
||||||
|
p3dHost.cxx \
|
||||||
p3dInstance.cxx \
|
p3dInstance.cxx \
|
||||||
p3dInstanceManager.cxx \
|
p3dInstanceManager.cxx \
|
||||||
p3dIntObject.cxx \
|
p3dIntObject.cxx \
|
||||||
|
@ -24,6 +24,17 @@ get_filename() const {
|
|||||||
return _filename;
|
return _filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: FileSpec::set_filename
|
||||||
|
// Access: Private
|
||||||
|
// Description: Changes the relative path to this file on disk,
|
||||||
|
// within the package root directory.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
inline void FileSpec::
|
||||||
|
set_filename(const string &filename) {
|
||||||
|
_filename = filename;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: FileSpec::get_pathname
|
// Function: FileSpec::get_pathname
|
||||||
// Access: Private
|
// Access: Private
|
||||||
|
@ -32,6 +32,7 @@ public:
|
|||||||
void load_xml(TiXmlElement *element);
|
void load_xml(TiXmlElement *element);
|
||||||
|
|
||||||
inline const string &get_filename() const;
|
inline const string &get_filename() const;
|
||||||
|
inline void set_filename(const string &filename);
|
||||||
inline string get_pathname(const string &package_dir) const;
|
inline string get_pathname(const string &package_dir) const;
|
||||||
inline size_t get_size() const;
|
inline size_t get_size() const;
|
||||||
|
|
||||||
|
73
direct/src/plugin/p3dHost.I
Normal file
73
direct/src/plugin/p3dHost.I
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
// Filename: p3dHost.I
|
||||||
|
// Created by: drose (21Aug09)
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// PANDA 3D SOFTWARE
|
||||||
|
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||||
|
//
|
||||||
|
// All use of this software is subject to the terms of the revised BSD
|
||||||
|
// license. You should have received a copy of this license along
|
||||||
|
// with this source code in a file named "LICENSE."
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: P3DHost::get_host_dir
|
||||||
|
// Access: Public
|
||||||
|
// Description: Returns the local directory into which files
|
||||||
|
// downloaded from this host will be installed.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
inline const string &P3DHost::
|
||||||
|
get_host_dir() const {
|
||||||
|
return _host_dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: P3DHost::get_host_url
|
||||||
|
// Access: Public
|
||||||
|
// Description: Returns the root URL of this particular host, as
|
||||||
|
// passed from the package file. This is a unique
|
||||||
|
// string that identifies each host.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
inline const string &P3DHost::
|
||||||
|
get_host_url() const {
|
||||||
|
return _host_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: P3DHost::get_host_url_prefix
|
||||||
|
// Access: Public
|
||||||
|
// Description: Returns the root URL of this host, for constructing
|
||||||
|
// full URL sequences. This is the same as
|
||||||
|
// get_host_url(), except it is guaranteed to end in a
|
||||||
|
// slash character.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
inline const string &P3DHost::
|
||||||
|
get_host_url_prefix() const {
|
||||||
|
return _host_url_prefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: P3DHost::get_descriptive_name
|
||||||
|
// Access: Public
|
||||||
|
// Description: Returns the descriptive name provided for this host,
|
||||||
|
// if any. This will be available after
|
||||||
|
// read_contents_file() has been called.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
inline const string &P3DHost::
|
||||||
|
get_descriptive_name() const {
|
||||||
|
return _descriptive_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: P3DHost::has_contents_file
|
||||||
|
// Access: Public
|
||||||
|
// Description: Returns true if a contents.xml file has been
|
||||||
|
// successfully read for this host, false otherwise.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
inline bool P3DHost::
|
||||||
|
has_contents_file() const {
|
||||||
|
return (_xcontents != NULL);
|
||||||
|
}
|
265
direct/src/plugin/p3dHost.cxx
Normal file
265
direct/src/plugin/p3dHost.cxx
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
// Filename: p3dHost.cxx
|
||||||
|
// Created by: drose (21Aug09)
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// PANDA 3D SOFTWARE
|
||||||
|
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||||
|
//
|
||||||
|
// All use of this software is subject to the terms of the revised BSD
|
||||||
|
// license. You should have received a copy of this license along
|
||||||
|
// with this source code in a file named "LICENSE."
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "p3dHost.h"
|
||||||
|
#include "p3dInstanceManager.h"
|
||||||
|
#include "p3dPackage.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: P3DHost::Constructor
|
||||||
|
// Access: Private
|
||||||
|
// Description: Use P3DInstanceManager::get_host() to construct a new
|
||||||
|
// P3DHost.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
P3DHost::
|
||||||
|
P3DHost(P3DInstanceManager *inst_mgr, const string &host_url) :
|
||||||
|
_host_url(host_url)
|
||||||
|
{
|
||||||
|
_host_dir = inst_mgr->get_root_dir();
|
||||||
|
_host_dir += "/host"; // TODO.
|
||||||
|
|
||||||
|
// Ensure that the download URL ends with a slash.
|
||||||
|
_host_url_prefix = _host_url;
|
||||||
|
if (!_host_url_prefix.empty() && _host_url_prefix[_host_url_prefix.size() - 1] != '/') {
|
||||||
|
_host_url_prefix += "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
_xcontents = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: P3DHost::Destructor
|
||||||
|
// Access: Private
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
P3DHost::
|
||||||
|
~P3DHost() {
|
||||||
|
if (_xcontents != NULL) {
|
||||||
|
delete _xcontents;
|
||||||
|
}
|
||||||
|
|
||||||
|
Packages::iterator pi;
|
||||||
|
for (pi = _packages.begin(); pi != _packages.end(); ++pi) {
|
||||||
|
delete (*pi).second;
|
||||||
|
}
|
||||||
|
_packages.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: P3DHost::read_contents_file
|
||||||
|
// Access: Public
|
||||||
|
// Description: Reads the contents.xml file in the indicated
|
||||||
|
// filename. On success, copies the contents.xml file
|
||||||
|
// into the standard location (if it's not there
|
||||||
|
// already).
|
||||||
|
//
|
||||||
|
// Returns true on success, false on failure.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool P3DHost::
|
||||||
|
read_contents_file(const string &contents_filename) {
|
||||||
|
TiXmlDocument doc(contents_filename.c_str());
|
||||||
|
if (!doc.LoadFile()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
TiXmlElement *xcontents = doc.FirstChildElement("contents");
|
||||||
|
if (xcontents == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_xcontents != NULL) {
|
||||||
|
delete _xcontents;
|
||||||
|
}
|
||||||
|
_xcontents = (TiXmlElement *)xcontents->Clone();
|
||||||
|
|
||||||
|
string standard_filename = _host_dir + "/contents.xml";
|
||||||
|
if (standardize_filename(standard_filename) !=
|
||||||
|
standardize_filename(contents_filename)) {
|
||||||
|
copy_file(contents_filename, standard_filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: P3DHost::get_package
|
||||||
|
// Access: Public
|
||||||
|
// Description: Returns a (possibly shared) pointer to the indicated
|
||||||
|
// package.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
P3DPackage *P3DHost::
|
||||||
|
get_package(const string &package_name, const string &package_version) {
|
||||||
|
string key = package_name + "_" + package_version;
|
||||||
|
Packages::iterator pi = _packages.find(key);
|
||||||
|
if (pi != _packages.end()) {
|
||||||
|
return (*pi).second;
|
||||||
|
}
|
||||||
|
|
||||||
|
P3DPackage *package =
|
||||||
|
new P3DPackage(this, package_name, package_version);
|
||||||
|
bool inserted = _packages.insert(Packages::value_type(key, package)).second;
|
||||||
|
assert(inserted);
|
||||||
|
|
||||||
|
return package;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: P3DHost::get_package_desc_file
|
||||||
|
// Access: Public
|
||||||
|
// Description: Fills the indicated FileSpec with the hash
|
||||||
|
// information for the package's desc file, and also
|
||||||
|
// determines the package's platform. Returns true if
|
||||||
|
// successful, false if the package is unknown. This
|
||||||
|
// requires has_contents_file() to return true in order
|
||||||
|
// to be successful.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool P3DHost::
|
||||||
|
get_package_desc_file(FileSpec &desc_file, // out
|
||||||
|
string &package_platform, // out
|
||||||
|
const string &package_name, // in
|
||||||
|
const string &package_version) { // in
|
||||||
|
if (_xcontents == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
|
||||||
|
|
||||||
|
// Scan the contents data for the indicated package. First, we look
|
||||||
|
// for a platform-specific version.
|
||||||
|
TiXmlElement *xpackage = _xcontents->FirstChildElement("package");
|
||||||
|
while (xpackage != NULL) {
|
||||||
|
const char *name = xpackage->Attribute("name");
|
||||||
|
const char *platform = xpackage->Attribute("platform");
|
||||||
|
const char *version = xpackage->Attribute("version");
|
||||||
|
if (name != NULL && platform != NULL && version != NULL &&
|
||||||
|
package_name == name &&
|
||||||
|
inst_mgr->get_platform() == platform &&
|
||||||
|
package_version == version) {
|
||||||
|
// Here's the matching package definition.
|
||||||
|
desc_file.load_xml(xpackage);
|
||||||
|
package_platform = platform;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
xpackage = xpackage->NextSiblingElement("package");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look again, this time looking for a non-platform-specific version.
|
||||||
|
xpackage = _xcontents->FirstChildElement("package");
|
||||||
|
while (xpackage != NULL) {
|
||||||
|
const char *name = xpackage->Attribute("name");
|
||||||
|
const char *platform = xpackage->Attribute("platform");
|
||||||
|
const char *version = xpackage->Attribute("version");
|
||||||
|
if (platform == NULL) {
|
||||||
|
platform = "";
|
||||||
|
}
|
||||||
|
if (name != NULL && version != NULL &&
|
||||||
|
package_name == name &&
|
||||||
|
*platform == '\0' &&
|
||||||
|
package_version == version) {
|
||||||
|
// Here's the matching package definition.
|
||||||
|
desc_file.load_xml(xpackage);
|
||||||
|
package_platform = platform;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
xpackage = xpackage->NextSiblingElement("package");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Couldn't find the named package.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: P3DHost::standardize_filename
|
||||||
|
// Access: Private, Static
|
||||||
|
// Description: Attempts to change the filename into some standard
|
||||||
|
// form for comparison with other filenames. On a
|
||||||
|
// case-insensitive filesystem, this converts the
|
||||||
|
// filename to lowercase. On Windows, it further
|
||||||
|
// replaces forward slashes with backslashes.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
string P3DHost::
|
||||||
|
standardize_filename(const string &filename) {
|
||||||
|
#if defined(_WIN32) || defined(__APPLE__)
|
||||||
|
string new_filename;
|
||||||
|
for (string::const_iterator si = filename.begin();
|
||||||
|
si != filename.end();
|
||||||
|
++si) {
|
||||||
|
char ch = *si;
|
||||||
|
#ifdef _WIN32
|
||||||
|
if (ch == '/') {
|
||||||
|
ch = '\\';
|
||||||
|
}
|
||||||
|
#endif // _WIN32
|
||||||
|
new_filename += tolower(ch);
|
||||||
|
}
|
||||||
|
return new_filename;
|
||||||
|
#else // _WIN32 || __APPLE__
|
||||||
|
return filename;
|
||||||
|
#endif // _WIN32 || __APPLE__
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: P3DHost::copy_file
|
||||||
|
// Access: Private, Static
|
||||||
|
// Description: Copies the data in the file named by from_filename
|
||||||
|
// into the file named by to_filename.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool P3DHost::
|
||||||
|
copy_file(const string &from_filename, const string &to_filename) {
|
||||||
|
ifstream in(from_filename.c_str(), ios::in | ios::binary);
|
||||||
|
|
||||||
|
// Copy to a temporary file first, in case (a) the filenames
|
||||||
|
// actually refer to the same file, or (b) in case we have different
|
||||||
|
// processes writing to the same file, and (c) to prevent
|
||||||
|
// partially overwriting the file should something go wrong.
|
||||||
|
ostringstream strm;
|
||||||
|
strm << to_filename << ".t";
|
||||||
|
#ifdef _WIN32
|
||||||
|
strm << GetCurrentProcessId() << "_" << GetCurrentThreadId();
|
||||||
|
#else
|
||||||
|
strm << getpid();
|
||||||
|
#endif
|
||||||
|
string temp_filename = strm.str();
|
||||||
|
ofstream out(temp_filename.c_str(), ios::out | ios::binary);
|
||||||
|
|
||||||
|
static const size_t buffer_size = 4096;
|
||||||
|
char buffer[buffer_size];
|
||||||
|
|
||||||
|
in.read(buffer, buffer_size);
|
||||||
|
size_t count = in.gcount();
|
||||||
|
while (count != 0) {
|
||||||
|
out.write(buffer, count);
|
||||||
|
if (out.fail()) {
|
||||||
|
unlink(temp_filename.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
in.read(buffer, buffer_size);
|
||||||
|
count = in.gcount();
|
||||||
|
}
|
||||||
|
out.close();
|
||||||
|
|
||||||
|
if (!in.eof()) {
|
||||||
|
unlink(temp_filename.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rename(temp_filename.c_str(), to_filename.c_str()) == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
unlink(temp_filename.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
71
direct/src/plugin/p3dHost.h
Normal file
71
direct/src/plugin/p3dHost.h
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
// Filename: p3dHost.h
|
||||||
|
// Created by: drose (21Aug09)
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// PANDA 3D SOFTWARE
|
||||||
|
// Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||||
|
//
|
||||||
|
// All use of this software is subject to the terms of the revised BSD
|
||||||
|
// license. You should have received a copy of this license along
|
||||||
|
// with this source code in a file named "LICENSE."
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef P3DHOST_H
|
||||||
|
#define P3DHOST_H
|
||||||
|
|
||||||
|
#include "p3d_plugin_common.h"
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
class FileSpec;
|
||||||
|
class P3DInstanceManager;
|
||||||
|
class P3DPackage;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Class : P3DHost
|
||||||
|
// Description : Represents a particular download host serving up
|
||||||
|
// Panda3D packages.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
class P3DHost {
|
||||||
|
private:
|
||||||
|
P3DHost(P3DInstanceManager *inst_mgr, const string &host_url);
|
||||||
|
~P3DHost();
|
||||||
|
|
||||||
|
public:
|
||||||
|
inline const string &get_host_dir() const;
|
||||||
|
inline const string &get_host_url() const;
|
||||||
|
inline const string &get_host_url_prefix() const;
|
||||||
|
inline const string &get_descriptive_name() const;
|
||||||
|
|
||||||
|
inline bool has_contents_file() const;
|
||||||
|
bool read_contents_file(const string &contents_filename);
|
||||||
|
|
||||||
|
P3DPackage *get_package(const string &package_name,
|
||||||
|
const string &package_version);
|
||||||
|
bool get_package_desc_file(FileSpec &desc_file,
|
||||||
|
string &package_platform,
|
||||||
|
const string &package_name,
|
||||||
|
const string &package_version);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static string standardize_filename(const string &filename);
|
||||||
|
static bool copy_file(const string &from_filename, const string &to_filename);
|
||||||
|
|
||||||
|
private:
|
||||||
|
string _host_dir;
|
||||||
|
string _host_url;
|
||||||
|
string _host_url_prefix;
|
||||||
|
string _descriptive_name;
|
||||||
|
TiXmlElement *_xcontents;
|
||||||
|
|
||||||
|
typedef map<string, P3DPackage *> Packages;
|
||||||
|
Packages _packages;
|
||||||
|
|
||||||
|
friend class P3DInstanceManager;
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "p3dHost.I"
|
||||||
|
|
||||||
|
#endif
|
@ -884,12 +884,14 @@ scan_app_desc_file(TiXmlDocument *doc) {
|
|||||||
TiXmlElement *xrequires = xpackage->FirstChildElement("requires");
|
TiXmlElement *xrequires = xpackage->FirstChildElement("requires");
|
||||||
while (xrequires != NULL) {
|
while (xrequires != NULL) {
|
||||||
const char *name = xrequires->Attribute("name");
|
const char *name = xrequires->Attribute("name");
|
||||||
if (name != NULL) {
|
const char *host_url = xrequires->Attribute("host");
|
||||||
|
if (name != NULL && host_url != NULL) {
|
||||||
const char *version = xrequires->Attribute("version");
|
const char *version = xrequires->Attribute("version");
|
||||||
if (version == NULL) {
|
if (version == NULL) {
|
||||||
version = "";
|
version = "";
|
||||||
}
|
}
|
||||||
P3DPackage *package = inst_mgr->get_package(name, version);
|
P3DHost *host = inst_mgr->get_host(host_url);
|
||||||
|
P3DPackage *package = host->get_package(name, version);
|
||||||
add_package(package);
|
add_package(package);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1177,10 +1179,11 @@ make_splash_window() {
|
|||||||
if (!_fparams.has_token("splash_img")) {
|
if (!_fparams.has_token("splash_img")) {
|
||||||
// No specific splash image is specified; get the default splash
|
// No specific splash image is specified; get the default splash
|
||||||
// image.
|
// image.
|
||||||
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
|
if (_panda3d != NULL) {
|
||||||
splash_image_url = inst_mgr->get_download_url();
|
splash_image_url = _panda3d->get_host()->get_host_url_prefix();
|
||||||
splash_image_url += "coreapi/splash.jpg";
|
splash_image_url += "coreapi/splash.jpg";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (splash_image_url.empty()) {
|
if (splash_image_url.empty()) {
|
||||||
// No splash image. Never mind.
|
// No splash image. Never mind.
|
||||||
|
@ -36,18 +36,6 @@ get_root_dir() const {
|
|||||||
return _root_dir;
|
return _root_dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: P3DInstanceManager::get_download_url
|
|
||||||
// Access: Public
|
|
||||||
// Description: Returns the URL of the download server. All
|
|
||||||
// downloadable files will be retrieved from various
|
|
||||||
// subdirectories of this URL root.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
inline const string &P3DInstanceManager::
|
|
||||||
get_download_url() const {
|
|
||||||
return _download_url;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: P3DInstanceManager::get_platform
|
// Function: P3DInstanceManager::get_platform
|
||||||
// Access: Public
|
// Access: Public
|
||||||
@ -74,17 +62,6 @@ get_log_directory() const {
|
|||||||
return _log_directory;
|
return _log_directory;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: P3DInstanceManager::has_contents_file
|
|
||||||
// Access: Public
|
|
||||||
// Description: Returns true if a contents.xml file has been
|
|
||||||
// successfully read, false otherwise.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
inline bool P3DInstanceManager::
|
|
||||||
has_contents_file() const {
|
|
||||||
return (_xcontents != NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: P3DInstanceManager::get_num_instances
|
// Function: P3DInstanceManager::get_num_instances
|
||||||
// Access: Public
|
// Access: Public
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
#include "p3dInstanceManager.h"
|
#include "p3dInstanceManager.h"
|
||||||
#include "p3dInstance.h"
|
#include "p3dInstance.h"
|
||||||
#include "p3dSession.h"
|
#include "p3dSession.h"
|
||||||
#include "p3dPackage.h"
|
#include "p3dHost.h"
|
||||||
#include "p3d_plugin_config.h"
|
#include "p3d_plugin_config.h"
|
||||||
#include "p3dWinSplashWindow.h"
|
#include "p3dWinSplashWindow.h"
|
||||||
#include "p3dUndefinedObject.h"
|
#include "p3dUndefinedObject.h"
|
||||||
@ -51,7 +51,6 @@ P3DInstanceManager() {
|
|||||||
_is_initialized = false;
|
_is_initialized = false;
|
||||||
_next_temp_filename_counter = 0;
|
_next_temp_filename_counter = 0;
|
||||||
_unique_id = 0;
|
_unique_id = 0;
|
||||||
_xcontents = NULL;
|
|
||||||
|
|
||||||
_notify_thread_continue = false;
|
_notify_thread_continue = false;
|
||||||
_started_notify_thread = false;
|
_started_notify_thread = false;
|
||||||
@ -103,13 +102,15 @@ P3DInstanceManager::
|
|||||||
sigaction(SIGPIPE, &_old_sigpipe, NULL);
|
sigaction(SIGPIPE, &_old_sigpipe, NULL);
|
||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
|
|
||||||
if (_xcontents != NULL) {
|
|
||||||
delete _xcontents;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(_instances.empty());
|
assert(_instances.empty());
|
||||||
assert(_sessions.empty());
|
assert(_sessions.empty());
|
||||||
|
|
||||||
|
Hosts::iterator hi;
|
||||||
|
for (hi = _hosts.begin(); hi != _hosts.end(); ++hi) {
|
||||||
|
delete (*hi).second;
|
||||||
|
}
|
||||||
|
_hosts.clear();
|
||||||
|
|
||||||
// Delete any remaining temporary files.
|
// Delete any remaining temporary files.
|
||||||
TempFilenames::iterator ti;
|
TempFilenames::iterator ti;
|
||||||
for (ti = _temp_filenames.begin(); ti != _temp_filenames.end(); ++ti) {
|
for (ti = _temp_filenames.begin(); ti != _temp_filenames.end(); ++ti) {
|
||||||
@ -145,7 +146,7 @@ P3DInstanceManager::
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: P3DInstanceManager::initialize
|
// Function: P3DInstanceManager::initialize
|
||||||
// Access: Public
|
// Access: Public
|
||||||
// Description: Called by the host at application startup. It
|
// Description: Called by the plugin host at application startup. It
|
||||||
// returns true if the DLL is successfully initialized,
|
// returns true if the DLL is successfully initialized,
|
||||||
// false if it should be immediately shut down and
|
// false if it should be immediately shut down and
|
||||||
// redownloaded.
|
// redownloaded.
|
||||||
@ -156,12 +157,7 @@ initialize(const string &contents_filename, const string &download_url,
|
|||||||
const string &log_basename) {
|
const string &log_basename) {
|
||||||
|
|
||||||
_root_dir = find_root_dir();
|
_root_dir = find_root_dir();
|
||||||
_download_url = download_url;
|
|
||||||
#ifdef P3D_PLUGIN_DOWNLOAD
|
|
||||||
if (_download_url.empty()) {
|
|
||||||
_download_url = P3D_PLUGIN_DOWNLOAD;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
_platform = platform;
|
_platform = platform;
|
||||||
if (_platform.empty()) {
|
if (_platform.empty()) {
|
||||||
_platform = DTOOL_PLATFORM;
|
_platform = DTOOL_PLATFORM;
|
||||||
@ -197,7 +193,7 @@ initialize(const string &contents_filename, const string &download_url,
|
|||||||
}
|
}
|
||||||
delete[] buffer_2;
|
delete[] buffer_2;
|
||||||
|
|
||||||
// Also make sure the directory actually exists.
|
// And make sure the directory actually exists.
|
||||||
mkdir_complete(_temp_directory, nout);
|
mkdir_complete(_temp_directory, nout);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
@ -216,11 +212,6 @@ initialize(const string &contents_filename, const string &download_url,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Ensure that the download URL ends with a slash.
|
|
||||||
if (!_download_url.empty() && _download_url[_download_url.size() - 1] != '/') {
|
|
||||||
_download_url += "/";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure that the temp directory ends with a slash.
|
// Ensure that the temp directory ends with a slash.
|
||||||
if (!_temp_directory.empty() && _temp_directory[_temp_directory.size() - 1] != '/') {
|
if (!_temp_directory.empty() && _temp_directory[_temp_directory.size() - 1] != '/') {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@ -251,8 +242,6 @@ initialize(const string &contents_filename, const string &download_url,
|
|||||||
}
|
}
|
||||||
|
|
||||||
nout << "_root_dir = " << _root_dir
|
nout << "_root_dir = " << _root_dir
|
||||||
<< ", contents = " << contents_filename
|
|
||||||
<< ", download = " << _download_url
|
|
||||||
<< ", platform = " << _platform
|
<< ", platform = " << _platform
|
||||||
<< "\n";
|
<< "\n";
|
||||||
|
|
||||||
@ -263,9 +252,11 @@ initialize(const string &contents_filename, const string &download_url,
|
|||||||
|
|
||||||
_is_initialized = true;
|
_is_initialized = true;
|
||||||
|
|
||||||
// Attempt to read the supplied contents.xml file.
|
if (!download_url.empty() && !contents_filename.empty()) {
|
||||||
if (!contents_filename.empty()) {
|
// Attempt to pre-read the supplied contents.xml file, to avoid an
|
||||||
if (!read_contents_file(contents_filename)) {
|
// unnecessary download later.
|
||||||
|
P3DHost *host = get_host(download_url);
|
||||||
|
if (!host->read_contents_file(contents_filename)) {
|
||||||
nout << "Couldn't read " << contents_filename << "\n";
|
nout << "Couldn't read " << contents_filename << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -273,42 +264,6 @@ initialize(const string &contents_filename, const string &download_url,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: P3DInstanceManager::read_contents_file
|
|
||||||
// Access: Public
|
|
||||||
// Description: Reads the contents.xml file in the indicated
|
|
||||||
// filename. On success, copies the contents.xml file
|
|
||||||
// into the standard location (if it's not there
|
|
||||||
// already).
|
|
||||||
//
|
|
||||||
// Returns true on success, false on failure.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
bool P3DInstanceManager::
|
|
||||||
read_contents_file(const string &contents_filename) {
|
|
||||||
TiXmlDocument doc(contents_filename.c_str());
|
|
||||||
if (!doc.LoadFile()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
TiXmlElement *xcontents = doc.FirstChildElement("contents");
|
|
||||||
if (xcontents == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_xcontents != NULL) {
|
|
||||||
delete _xcontents;
|
|
||||||
}
|
|
||||||
_xcontents = (TiXmlElement *)xcontents->Clone();
|
|
||||||
|
|
||||||
string standard_filename = _root_dir + "/contents.xml";
|
|
||||||
if (standardize_filename(standard_filename) !=
|
|
||||||
standardize_filename(contents_filename)) {
|
|
||||||
copy_file(contents_filename, standard_filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: P3DInstanceManager::create_instance
|
// Function: P3DInstanceManager::create_instance
|
||||||
// Access: Public
|
// Access: Public
|
||||||
@ -473,67 +428,23 @@ wait_request() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: P3DInstanceManager::get_package
|
// Function: P3DInstanceManager::get_host
|
||||||
// Access: Public
|
// Access: Public
|
||||||
// Description: Returns a (possibly shared) pointer to the indicated
|
// Description: Returns a (possibly shared) pointer to the indicated
|
||||||
// package.
|
// download host.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
P3DPackage *P3DInstanceManager::
|
P3DHost *P3DInstanceManager::
|
||||||
get_package(const string &package_name, const string &package_version) {
|
get_host(const string &host_url) {
|
||||||
string package_platform = get_platform();
|
Hosts::iterator pi = _hosts.find(host_url);
|
||||||
string key = package_name + "_" + package_platform + "_" + package_version;
|
if (pi != _hosts.end()) {
|
||||||
Packages::iterator pi = _packages.find(key);
|
|
||||||
if (pi != _packages.end()) {
|
|
||||||
return (*pi).second;
|
return (*pi).second;
|
||||||
}
|
}
|
||||||
|
|
||||||
P3DPackage *package =
|
P3DHost *host = new P3DHost(this, host_url);
|
||||||
new P3DPackage(package_name, package_platform, package_version);
|
bool inserted = _hosts.insert(Hosts::value_type(host_url, host)).second;
|
||||||
bool inserted = _packages.insert(Packages::value_type(key, package)).second;
|
|
||||||
assert(inserted);
|
assert(inserted);
|
||||||
|
|
||||||
return package;
|
return host;
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: P3DInstanceManager::get_package_desc_file
|
|
||||||
// Access: Public
|
|
||||||
// Description: Fills the indicated FileSpec with the hash
|
|
||||||
// information for the package's desc file. Returns
|
|
||||||
// true if successful, false if the package is unknown.
|
|
||||||
// This requires has_contents_file() to return true in
|
|
||||||
// order to be successful.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
bool P3DInstanceManager::
|
|
||||||
get_package_desc_file(FileSpec &desc_file,
|
|
||||||
const string &package_name,
|
|
||||||
const string &package_version) {
|
|
||||||
if (_xcontents == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
string package_platform = get_platform();
|
|
||||||
|
|
||||||
// Scan the contents data for the indicated package.
|
|
||||||
TiXmlElement *xpackage = _xcontents->FirstChildElement("package");
|
|
||||||
while (xpackage != NULL) {
|
|
||||||
const char *name = xpackage->Attribute("name");
|
|
||||||
const char *platform = xpackage->Attribute("platform");
|
|
||||||
const char *version = xpackage->Attribute("version");
|
|
||||||
if (name != NULL && platform != NULL && version != NULL &&
|
|
||||||
package_name == name &&
|
|
||||||
package_platform == platform &&
|
|
||||||
package_version == version) {
|
|
||||||
// Here's the matching package definition.
|
|
||||||
desc_file.load_xml(xpackage);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
xpackage = xpackage->NextSiblingElement("package");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Couldn't find the named package.
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -698,89 +609,6 @@ delete_global_ptr() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: P3DInstanceManager::standardize_filename
|
|
||||||
// Access: Private, Static
|
|
||||||
// Description: Attempts to change the filename into some standard
|
|
||||||
// form for comparison with other filenames. On a
|
|
||||||
// case-insensitive filesystem, this converts the
|
|
||||||
// filename to lowercase. On Windows, it further
|
|
||||||
// replaces forward slashes with backslashes.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
string P3DInstanceManager::
|
|
||||||
standardize_filename(const string &filename) {
|
|
||||||
#if defined(_WIN32) || defined(__APPLE__)
|
|
||||||
string new_filename;
|
|
||||||
for (string::const_iterator si = filename.begin();
|
|
||||||
si != filename.end();
|
|
||||||
++si) {
|
|
||||||
char ch = *si;
|
|
||||||
#ifdef _WIN32
|
|
||||||
if (ch == '/') {
|
|
||||||
ch = '\\';
|
|
||||||
}
|
|
||||||
#endif // _WIN32
|
|
||||||
new_filename += tolower(ch);
|
|
||||||
}
|
|
||||||
return new_filename;
|
|
||||||
#else // _WIN32 || __APPLE__
|
|
||||||
return filename;
|
|
||||||
#endif // _WIN32 || __APPLE__
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: P3DInstanceManager::copy_file
|
|
||||||
// Access: Private, Static
|
|
||||||
// Description: Copies the data in the file named by from_filename
|
|
||||||
// into the file named by to_filename.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
bool P3DInstanceManager::
|
|
||||||
copy_file(const string &from_filename, const string &to_filename) {
|
|
||||||
ifstream in(from_filename.c_str(), ios::in | ios::binary);
|
|
||||||
|
|
||||||
// Copy to a temporary file first, in case (a) the filenames
|
|
||||||
// actually refer to the same file, or (b) in case we have different
|
|
||||||
// processes writing to the same file, and (c) to prevent
|
|
||||||
// partially overwriting the file should something go wrong.
|
|
||||||
ostringstream strm;
|
|
||||||
strm << to_filename << ".t";
|
|
||||||
#ifdef _WIN32
|
|
||||||
strm << GetCurrentProcessId() << "_" << GetCurrentThreadId();
|
|
||||||
#else
|
|
||||||
strm << getpid();
|
|
||||||
#endif
|
|
||||||
string temp_filename = strm.str();
|
|
||||||
ofstream out(temp_filename.c_str(), ios::out | ios::binary);
|
|
||||||
|
|
||||||
static const size_t buffer_size = 4096;
|
|
||||||
char buffer[buffer_size];
|
|
||||||
|
|
||||||
in.read(buffer, buffer_size);
|
|
||||||
size_t count = in.gcount();
|
|
||||||
while (count != 0) {
|
|
||||||
out.write(buffer, count);
|
|
||||||
if (out.fail()) {
|
|
||||||
unlink(temp_filename.c_str());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
in.read(buffer, buffer_size);
|
|
||||||
count = in.gcount();
|
|
||||||
}
|
|
||||||
out.close();
|
|
||||||
|
|
||||||
if (!in.eof()) {
|
|
||||||
unlink(temp_filename.c_str());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rename(temp_filename.c_str(), to_filename.c_str()) == 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
unlink(temp_filename.c_str());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: P3DInstanceManager::nt_thread_run
|
// Function: P3DInstanceManager::nt_thread_run
|
||||||
// Access: Private
|
// Access: Private
|
||||||
@ -791,12 +619,12 @@ nt_thread_run() {
|
|||||||
// The notify thread exists because we need to be able to send
|
// The notify thread exists because we need to be able to send
|
||||||
// asynchronous notifications of request events. These request
|
// asynchronous notifications of request events. These request
|
||||||
// events were detected in the various read threads associated with
|
// events were detected in the various read threads associated with
|
||||||
// each session, but we can't call back into the host space from the
|
// each session, but we can't call back into the plugin host space
|
||||||
// read thread, since if the host immediately response to a callback
|
// from the read thread, since if the host immediately response to a
|
||||||
// by calling back into the p3d_plugin space, now we have our read
|
// callback by calling back into the p3d_plugin space, now we have
|
||||||
// thread doing stuff in here that's not related to the read thread.
|
// our read thread doing stuff in here that's not related to the
|
||||||
// Even worse, some of the things it might need to do might require
|
// read thread. Even worse, some of the things it might need to do
|
||||||
// a separate read thread to be running!
|
// might require a separate read thread to be running!
|
||||||
|
|
||||||
_notify_ready.acquire();
|
_notify_ready.acquire();
|
||||||
while (_notify_thread_continue) {
|
while (_notify_thread_continue) {
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
class P3DInstance;
|
class P3DInstance;
|
||||||
class P3DSession;
|
class P3DSession;
|
||||||
class P3DPackage;
|
class P3DHost;
|
||||||
class FileSpec;
|
class FileSpec;
|
||||||
class TiXmlElement;
|
class TiXmlElement;
|
||||||
|
|
||||||
@ -52,13 +52,9 @@ public:
|
|||||||
inline bool is_initialized() const;
|
inline bool is_initialized() const;
|
||||||
|
|
||||||
inline const string &get_root_dir() const;
|
inline const string &get_root_dir() const;
|
||||||
inline const string &get_download_url() const;
|
|
||||||
inline const string &get_platform() const;
|
inline const string &get_platform() const;
|
||||||
inline const string &get_log_directory() const;
|
inline const string &get_log_directory() const;
|
||||||
|
|
||||||
inline bool has_contents_file() const;
|
|
||||||
bool read_contents_file(const string &contents_filename);
|
|
||||||
|
|
||||||
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,
|
||||||
@ -74,11 +70,7 @@ public:
|
|||||||
P3DInstance *check_request();
|
P3DInstance *check_request();
|
||||||
void wait_request();
|
void wait_request();
|
||||||
|
|
||||||
P3DPackage *get_package(const string &package_name,
|
P3DHost *get_host(const string &host_url);
|
||||||
const string &package_version);
|
|
||||||
bool get_package_desc_file(FileSpec &desc_file,
|
|
||||||
const string &package_name,
|
|
||||||
const string &package_version);
|
|
||||||
|
|
||||||
inline int get_num_instances() const;
|
inline int get_num_instances() const;
|
||||||
|
|
||||||
@ -97,10 +89,6 @@ public:
|
|||||||
static P3DInstanceManager *get_global_ptr();
|
static P3DInstanceManager *get_global_ptr();
|
||||||
static void delete_global_ptr();
|
static void delete_global_ptr();
|
||||||
|
|
||||||
private:
|
|
||||||
static string standardize_filename(const string &filename);
|
|
||||||
static bool copy_file(const string &from_filename, const string &to_filename);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The notify thread. This thread runs only for the purpose of
|
// The notify thread. This thread runs only for the purpose of
|
||||||
// generating asynchronous notifications of requests, to callers who
|
// generating asynchronous notifications of requests, to callers who
|
||||||
@ -111,15 +99,12 @@ private:
|
|||||||
private:
|
private:
|
||||||
bool _is_initialized;
|
bool _is_initialized;
|
||||||
string _root_dir;
|
string _root_dir;
|
||||||
string _download_url;
|
|
||||||
string _platform;
|
string _platform;
|
||||||
string _log_directory;
|
string _log_directory;
|
||||||
string _log_basename;
|
string _log_basename;
|
||||||
string _log_pathname;
|
string _log_pathname;
|
||||||
string _temp_directory;
|
string _temp_directory;
|
||||||
|
|
||||||
TiXmlElement *_xcontents;
|
|
||||||
|
|
||||||
P3D_object *_undefined_object;
|
P3D_object *_undefined_object;
|
||||||
P3D_object *_none_object;
|
P3D_object *_none_object;
|
||||||
P3D_object *_true_object;
|
P3D_object *_true_object;
|
||||||
@ -131,8 +116,8 @@ private:
|
|||||||
typedef map<string, P3DSession *> Sessions;
|
typedef map<string, P3DSession *> Sessions;
|
||||||
Sessions _sessions;
|
Sessions _sessions;
|
||||||
|
|
||||||
typedef map<string, P3DPackage *> Packages;
|
typedef map<string, P3DHost *> Hosts;
|
||||||
Packages _packages;
|
Hosts _hosts;
|
||||||
|
|
||||||
typedef set<string> TempFilenames;
|
typedef set<string> TempFilenames;
|
||||||
TempFilenames _temp_filenames;
|
TempFilenames _temp_filenames;
|
||||||
|
@ -81,6 +81,17 @@ get_failed() const {
|
|||||||
return _failed;
|
return _failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: P3DPackage::get_host
|
||||||
|
// Access: Public
|
||||||
|
// Description: Returns the host server which offers this package for
|
||||||
|
// download.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
inline P3DHost *P3DPackage::
|
||||||
|
get_host() const {
|
||||||
|
return _host;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: P3DPackage::get_package_dir
|
// Function: P3DPackage::get_package_dir
|
||||||
// Access: Public
|
// Access: Public
|
||||||
|
@ -36,21 +36,14 @@ static const double extract_portion = 0.05;
|
|||||||
// Description:
|
// Description:
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
P3DPackage::
|
P3DPackage::
|
||||||
P3DPackage(const string &package_name,
|
P3DPackage(P3DHost *host, const string &package_name,
|
||||||
const string &package_platform,
|
|
||||||
const string &package_version) :
|
const string &package_version) :
|
||||||
|
_host(host),
|
||||||
_package_name(package_name),
|
_package_name(package_name),
|
||||||
_package_platform(package_platform),
|
|
||||||
_package_version(package_version)
|
_package_version(package_version)
|
||||||
{
|
{
|
||||||
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
|
|
||||||
|
|
||||||
_package_fullname = _package_name;
|
_package_fullname = _package_name;
|
||||||
_package_dir = inst_mgr->get_root_dir() + string("/packages/") + _package_name;
|
_package_dir = _host->get_host_dir() + string("/packages/") + _package_name;
|
||||||
if (!_package_platform.empty()) {
|
|
||||||
_package_fullname += string("_") + _package_platform;
|
|
||||||
_package_dir += string("/") + _package_platform;
|
|
||||||
}
|
|
||||||
_package_fullname += string("_") + _package_version;
|
_package_fullname += string("_") + _package_version;
|
||||||
_package_dir += string("/") + _package_version;
|
_package_dir += string("/") + _package_version;
|
||||||
|
|
||||||
@ -169,16 +162,14 @@ begin_info_download() {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void P3DPackage::
|
void P3DPackage::
|
||||||
download_contents_file() {
|
download_contents_file() {
|
||||||
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
|
if (_host->has_contents_file()) {
|
||||||
|
|
||||||
if (inst_mgr->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
|
||||||
// package desc file.
|
// package desc file.
|
||||||
download_desc_file();
|
download_desc_file();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
string url = inst_mgr->get_download_url();
|
string url = _host->get_host_url_prefix();
|
||||||
url += "contents.xml";
|
url += "contents.xml";
|
||||||
|
|
||||||
// Download contents.xml to a temporary filename first, in case
|
// Download contents.xml to a temporary filename first, in case
|
||||||
@ -196,15 +187,13 @@ download_contents_file() {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void P3DPackage::
|
void P3DPackage::
|
||||||
contents_file_download_finished(bool success) {
|
contents_file_download_finished(bool success) {
|
||||||
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
|
if (!_host->has_contents_file()) {
|
||||||
|
if (!success || !_host->read_contents_file(_temp_contents_file->get_filename())) {
|
||||||
if (!inst_mgr->has_contents_file()) {
|
|
||||||
if (!success || !inst_mgr->read_contents_file(_temp_contents_file->get_filename())) {
|
|
||||||
nout << "Couldn't read " << *_temp_contents_file << "\n";
|
nout << "Couldn't read " << *_temp_contents_file << "\n";
|
||||||
|
|
||||||
// Maybe we can read an already-downloaded contents.xml file.
|
// Maybe we can read an already-downloaded contents.xml file.
|
||||||
string standard_filename = inst_mgr->get_root_dir() + "/contents.xml";
|
string standard_filename = _host->get_host_dir() + "/contents.xml";
|
||||||
if (!inst_mgr->read_contents_file(standard_filename)) {
|
if (!_host->read_contents_file(standard_filename)) {
|
||||||
// Couldn't even read that. Fail.
|
// Couldn't even read that. Fail.
|
||||||
report_done(false);
|
report_done(false);
|
||||||
delete _temp_contents_file;
|
delete _temp_contents_file;
|
||||||
@ -225,27 +214,31 @@ contents_file_download_finished(bool success) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: P3DPackage::download_desc_file
|
// Function: P3DPackage::download_desc_file
|
||||||
// Access: Private
|
// Access: Private
|
||||||
// Description: Starts downloading the desc file for the package.
|
// Description: Starts downloading the desc file for the package, if
|
||||||
|
// it's needed; or read to local version if it's fresh
|
||||||
|
// enough.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void P3DPackage::
|
void P3DPackage::
|
||||||
download_desc_file() {
|
download_desc_file() {
|
||||||
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
|
|
||||||
|
|
||||||
// Attempt to check the desc file for freshness. If it already
|
// Attempt to check the desc file for freshness. If it already
|
||||||
// exists, and is consistent with the server contents file, we don't
|
// exists, and is consistent with the server contents file, we don't
|
||||||
// need to re-download it.
|
// need to re-download it.
|
||||||
string root_dir = inst_mgr->get_root_dir() + "/packages";
|
|
||||||
FileSpec desc_file;
|
FileSpec desc_file;
|
||||||
if (!inst_mgr->get_package_desc_file(desc_file, _package_name, _package_version)) {
|
if (!_host->get_package_desc_file(desc_file, _package_platform,
|
||||||
|
_package_name, _package_version)) {
|
||||||
nout << "Couldn't find package " << _package_fullname
|
nout << "Couldn't find package " << _package_fullname
|
||||||
<< " in contents file.\n";
|
<< " in contents file.\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
} else if (desc_file.get_pathname(root_dir) != _desc_file_pathname) {
|
// The desc file might have a different path on the host server than
|
||||||
nout << "Wrong pathname for desc file: "
|
// it has locally, because we strip out the platform locally.
|
||||||
<< desc_file.get_pathname(root_dir)
|
// Adjust desc_file to point to the local file.
|
||||||
<< " instead of " << _desc_file_pathname << "\n";
|
string url_filename = desc_file.get_filename();
|
||||||
|
desc_file.set_filename(_desc_file_basename);
|
||||||
|
assert (desc_file.get_pathname(_package_dir) == _desc_file_pathname);
|
||||||
|
|
||||||
} else if (!desc_file.full_verify(root_dir)) {
|
if (!desc_file.full_verify(_package_dir)) {
|
||||||
nout << _desc_file_pathname << " is stale.\n";
|
nout << _desc_file_pathname << " is stale.\n";
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -258,13 +251,8 @@ download_desc_file() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The desc file is not current. Go download it.
|
// The desc file is not current. Go download it.
|
||||||
string url = inst_mgr->get_download_url();
|
string url = _host->get_host_url_prefix();
|
||||||
url += _package_name;
|
url += url_filename;
|
||||||
if (!_package_platform.empty()) {
|
|
||||||
url += "/" + _package_platform;
|
|
||||||
}
|
|
||||||
url += "/" + _package_version;
|
|
||||||
url += "/" + _desc_file_basename;
|
|
||||||
|
|
||||||
start_download(DT_desc_file, url, _desc_file_pathname, false);
|
start_download(DT_desc_file, url, _desc_file_pathname, false);
|
||||||
}
|
}
|
||||||
@ -415,8 +403,7 @@ begin_data_download() {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void P3DPackage::
|
void P3DPackage::
|
||||||
download_compressed_archive(bool allow_partial) {
|
download_compressed_archive(bool allow_partial) {
|
||||||
P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
|
string url = _host->get_host_url_prefix();
|
||||||
string url = inst_mgr->get_download_url();
|
|
||||||
url += _package_name;
|
url += _package_name;
|
||||||
if (!_package_platform.empty()) {
|
if (!_package_platform.empty()) {
|
||||||
url += "/" + _package_platform;
|
url += "/" + _package_platform;
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "fileSpec.h"
|
#include "fileSpec.h"
|
||||||
#include "get_tinyxml.h"
|
#include "get_tinyxml.h"
|
||||||
|
|
||||||
|
class P3DHost;
|
||||||
class P3DInstance;
|
class P3DInstance;
|
||||||
class P3DTemporaryFile;
|
class P3DTemporaryFile;
|
||||||
|
|
||||||
@ -31,23 +32,26 @@ class P3DTemporaryFile;
|
|||||||
// runtime, which consists of a bunch of dll's
|
// runtime, which consists of a bunch of dll's
|
||||||
// downloaded in a single tar file, is a package.
|
// downloaded in a single tar file, is a package.
|
||||||
//
|
//
|
||||||
// The plugin is responsible for managing these packages
|
// The core API is responsible for managing these
|
||||||
// on disk, downloading new versions when needed, and
|
// packages on disk, downloading new versions when
|
||||||
// removing stale versions to limit disk space waste.
|
// needed, and removing stale versions to limit disk
|
||||||
|
// space waste.
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
class P3DPackage {
|
class P3DPackage {
|
||||||
public:
|
private:
|
||||||
P3DPackage(const string &package_name,
|
P3DPackage(P3DHost *host,
|
||||||
const string &package_platform,
|
const string &package_name,
|
||||||
const string &package_version);
|
const string &package_version);
|
||||||
~P3DPackage();
|
~P3DPackage();
|
||||||
|
|
||||||
|
public:
|
||||||
inline bool get_info_ready() const;
|
inline bool get_info_ready() const;
|
||||||
inline size_t get_download_size() const;
|
inline size_t get_download_size() const;
|
||||||
|
|
||||||
inline void activate_download();
|
inline void activate_download();
|
||||||
inline bool get_ready() const;
|
inline bool get_ready() const;
|
||||||
inline bool get_failed() const;
|
inline bool get_failed() const;
|
||||||
|
inline P3DHost *get_host() const;
|
||||||
inline const string &get_package_dir() const;
|
inline const string &get_package_dir() const;
|
||||||
inline const string &get_package_name() const;
|
inline const string &get_package_name() const;
|
||||||
inline const string &get_package_version() const;
|
inline const string &get_package_version() const;
|
||||||
@ -101,6 +105,8 @@ private:
|
|||||||
bool is_extractable(const string &filename) const;
|
bool is_extractable(const string &filename) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
P3DHost *_host;
|
||||||
|
|
||||||
string _package_name;
|
string _package_name;
|
||||||
string _package_version;
|
string _package_version;
|
||||||
string _package_platform;
|
string _package_platform;
|
||||||
@ -132,6 +138,8 @@ private:
|
|||||||
|
|
||||||
friend class Download;
|
friend class Download;
|
||||||
friend class P3DMultifileReader;
|
friend class P3DMultifileReader;
|
||||||
|
|
||||||
|
friend class P3DHost;
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "p3dPackage.I"
|
#include "p3dPackage.I"
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
// There is only one P3DPythonRun object in any given process space.
|
// There is only one P3DPythonRun object in any given process space.
|
||||||
// Makes the statics easier to deal with, and we don't need multiple
|
// Makes the statics easier to deal with, and we don't need multiple
|
||||||
// instances of this think.
|
// instances of this thing.
|
||||||
P3DPythonRun *P3DPythonRun::_global_ptr = NULL;
|
P3DPythonRun *P3DPythonRun::_global_ptr = NULL;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "p3dFileDownload.cxx"
|
#include "p3dFileDownload.cxx"
|
||||||
#include "p3dFileParams.cxx"
|
#include "p3dFileParams.cxx"
|
||||||
#include "p3dFloatObject.cxx"
|
#include "p3dFloatObject.cxx"
|
||||||
|
#include "p3dHost.cxx"
|
||||||
#include "p3dInstance.cxx"
|
#include "p3dInstance.cxx"
|
||||||
#include "p3dInstanceManager.cxx"
|
#include "p3dInstanceManager.cxx"
|
||||||
#include "p3dIntObject.cxx"
|
#include "p3dIntObject.cxx"
|
||||||
|
@ -6,10 +6,9 @@
|
|||||||
/********************************** DO NOT EDIT ****************************/
|
/********************************** DO NOT EDIT ****************************/
|
||||||
|
|
||||||
/* The URL that is the root of the download server that this plugin
|
/* The URL that is the root of the download server that this plugin
|
||||||
should contact. The nppanda3d.dll file should be found at this
|
should contact. The contents.xml file that defines this particular
|
||||||
location; as well as the contents.xml file that defines where the
|
"coreapi" package should be found at this location. */
|
||||||
various Panda3D packages will be found. */
|
#$[]define PANDA_PACKAGE_HOST_URL "$[PANDA_PACKAGE_HOST_URL]"
|
||||||
#$[]define P3D_PLUGIN_DOWNLOAD "$[P3D_PLUGIN_DOWNLOAD]$[if $[notdir $[P3D_PLUGIN_DOWNLOAD]],/]"
|
|
||||||
|
|
||||||
/* The filename(s) to generate output to when the plugin is running.
|
/* The filename(s) to generate output to when the plugin is running.
|
||||||
For debugging purposes only. */
|
For debugging purposes only. */
|
||||||
|
@ -108,7 +108,7 @@ void PPInstance::
|
|||||||
begin() {
|
begin() {
|
||||||
if (!is_plugin_loaded()) {
|
if (!is_plugin_loaded()) {
|
||||||
// Go download the contents file, so we can download the core DLL.
|
// Go download the contents file, so we can download the core DLL.
|
||||||
string url = P3D_PLUGIN_DOWNLOAD;
|
string url = PANDA_PACKAGE_HOST_URL;
|
||||||
if (!url.empty() && url[url.length() - 1] != '/') {
|
if (!url.empty() && url[url.length() - 1] != '/') {
|
||||||
url += '/';
|
url += '/';
|
||||||
}
|
}
|
||||||
@ -837,7 +837,7 @@ get_core_api(TiXmlElement *xplugin) {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
// The DLL file needs to be downloaded. Go get it.
|
// The DLL file needs to be downloaded. Go get it.
|
||||||
string url = P3D_PLUGIN_DOWNLOAD;
|
string url = PANDA_PACKAGE_HOST_URL;
|
||||||
if (!url.empty() && url[url.length() - 1] != '/') {
|
if (!url.empty() && url[url.length() - 1] != '/') {
|
||||||
url += '/';
|
url += '/';
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ run(int argc, char *argv[]) {
|
|||||||
const char *optstr = "+mu:p:ft:s:o:l:h";
|
const char *optstr = "+mu:p:ft:s:o:l:h";
|
||||||
|
|
||||||
bool allow_multiple = false;
|
bool allow_multiple = false;
|
||||||
string download_url = P3D_PLUGIN_DOWNLOAD;
|
string download_url = PANDA_PACKAGE_HOST_URL;
|
||||||
string this_platform = DTOOL_PLATFORM;
|
string this_platform = DTOOL_PLATFORM;
|
||||||
bool force_download = false;
|
bool force_download = false;
|
||||||
|
|
||||||
@ -752,7 +752,7 @@ usage() {
|
|||||||
|
|
||||||
<< " -u url\n"
|
<< " -u url\n"
|
||||||
<< " Specify the URL of the Panda3D download server. The default is\n"
|
<< " Specify the URL of the Panda3D download server. The default is\n"
|
||||||
<< " \"" << P3D_PLUGIN_DOWNLOAD << "\" .\n\n"
|
<< " \"" << PANDA_PACKAGE_HOST_URL << "\" .\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 \""
|
||||||
|
@ -133,8 +133,9 @@ class Packager:
|
|||||||
def __init__(self, packageName, packager):
|
def __init__(self, packageName, packager):
|
||||||
self.packageName = packageName
|
self.packageName = packageName
|
||||||
self.packager = packager
|
self.packager = packager
|
||||||
self.version = None
|
|
||||||
self.platform = None
|
self.platform = None
|
||||||
|
self.version = None
|
||||||
|
self.host = None
|
||||||
self.p3dApplication = False
|
self.p3dApplication = False
|
||||||
self.compressionLevel = 0
|
self.compressionLevel = 0
|
||||||
self.importedMapsDir = 'imported_maps'
|
self.importedMapsDir = 'imported_maps'
|
||||||
@ -672,6 +673,7 @@ class Packager:
|
|||||||
xrequires.SetAttribute('name', package.packageName)
|
xrequires.SetAttribute('name', package.packageName)
|
||||||
if package.version:
|
if package.version:
|
||||||
xrequires.SetAttribute('version', package.version)
|
xrequires.SetAttribute('version', package.version)
|
||||||
|
xrequires.SetAttribute('host', package.host)
|
||||||
xpackage.InsertEndChild(xrequires)
|
xpackage.InsertEndChild(xrequires)
|
||||||
|
|
||||||
doc.InsertEndChild(xpackage)
|
doc.InsertEndChild(xpackage)
|
||||||
@ -699,6 +701,9 @@ class Packager:
|
|||||||
raise PackagerError, message
|
raise PackagerError, message
|
||||||
|
|
||||||
def writeDescFile(self):
|
def writeDescFile(self):
|
||||||
|
""" Makes the package.xml file that describes the package
|
||||||
|
and its contents, for download. """
|
||||||
|
|
||||||
packageDescFullpath = Filename(self.packager.installDir, self.packageDesc)
|
packageDescFullpath = Filename(self.packager.installDir, self.packageDesc)
|
||||||
doc = TiXmlDocument(packageDescFullpath.toOsSpecific())
|
doc = TiXmlDocument(packageDescFullpath.toOsSpecific())
|
||||||
decl = TiXmlDeclaration("1.0", "utf-8", "")
|
decl = TiXmlDeclaration("1.0", "utf-8", "")
|
||||||
@ -724,6 +729,7 @@ class Packager:
|
|||||||
xrequires.SetAttribute('platform', package.platform)
|
xrequires.SetAttribute('platform', package.platform)
|
||||||
if package.version:
|
if package.version:
|
||||||
xrequires.SetAttribute('version', package.version)
|
xrequires.SetAttribute('version', package.version)
|
||||||
|
xrequires.SetAttribute('host', package.host)
|
||||||
xpackage.InsertEndChild(xrequires)
|
xpackage.InsertEndChild(xrequires)
|
||||||
|
|
||||||
xuncompressedArchive = self.getFileSpec(
|
xuncompressedArchive = self.getFileSpec(
|
||||||
@ -743,6 +749,10 @@ class Packager:
|
|||||||
doc.SaveFile()
|
doc.SaveFile()
|
||||||
|
|
||||||
def writeImportDescFile(self):
|
def writeImportDescFile(self):
|
||||||
|
""" Makes the package_import.xml file that describes the
|
||||||
|
package and its contents, for other packages and
|
||||||
|
applications that may wish to "require" this one. """
|
||||||
|
|
||||||
packageImportDescFullpath = Filename(self.packager.installDir, self.packageImportDesc)
|
packageImportDescFullpath = Filename(self.packager.installDir, self.packageImportDesc)
|
||||||
doc = TiXmlDocument(packageImportDescFullpath.toOsSpecific())
|
doc = TiXmlDocument(packageImportDescFullpath.toOsSpecific())
|
||||||
decl = TiXmlDeclaration("1.0", "utf-8", "")
|
decl = TiXmlDeclaration("1.0", "utf-8", "")
|
||||||
@ -754,6 +764,7 @@ class Packager:
|
|||||||
xpackage.SetAttribute('platform', self.platform)
|
xpackage.SetAttribute('platform', self.platform)
|
||||||
if self.version:
|
if self.version:
|
||||||
xpackage.SetAttribute('version', self.version)
|
xpackage.SetAttribute('version', self.version)
|
||||||
|
xpackage.SetAttribute('host', self.host)
|
||||||
|
|
||||||
for package in self.requires:
|
for package in self.requires:
|
||||||
xrequires = TiXmlElement('requires')
|
xrequires = TiXmlElement('requires')
|
||||||
@ -762,6 +773,7 @@ class Packager:
|
|||||||
xrequires.SetAttribute('platform', package.platform)
|
xrequires.SetAttribute('platform', package.platform)
|
||||||
if package.version:
|
if package.version:
|
||||||
xrequires.SetAttribute('version', package.version)
|
xrequires.SetAttribute('version', package.version)
|
||||||
|
xrequires.SetAttribute('host', package.host)
|
||||||
xpackage.InsertEndChild(xrequires)
|
xpackage.InsertEndChild(xrequires)
|
||||||
|
|
||||||
self.components.sort()
|
self.components.sort()
|
||||||
@ -785,6 +797,7 @@ class Packager:
|
|||||||
self.packageName = xpackage.Attribute('name')
|
self.packageName = xpackage.Attribute('name')
|
||||||
self.platform = xpackage.Attribute('platform')
|
self.platform = xpackage.Attribute('platform')
|
||||||
self.version = xpackage.Attribute('version')
|
self.version = xpackage.Attribute('version')
|
||||||
|
self.host = xpackage.Attribute('host')
|
||||||
|
|
||||||
self.requires = []
|
self.requires = []
|
||||||
xrequires = xpackage.FirstChildElement('requires')
|
xrequires = xpackage.FirstChildElement('requires')
|
||||||
@ -792,8 +805,11 @@ class Packager:
|
|||||||
packageName = xrequires.Attribute('name')
|
packageName = xrequires.Attribute('name')
|
||||||
platform = xrequires.Attribute('platform')
|
platform = xrequires.Attribute('platform')
|
||||||
version = xrequires.Attribute('version')
|
version = xrequires.Attribute('version')
|
||||||
|
host = xrequires.Attribute('host')
|
||||||
if packageName:
|
if packageName:
|
||||||
package = self.packager.findPackage(packageName, platform = platform, version = version, requires = self.requires)
|
package = self.packager.findPackage(
|
||||||
|
packageName, platform = platform, version = version,
|
||||||
|
host = host, requires = self.requires)
|
||||||
if package:
|
if package:
|
||||||
self.requires.append(package)
|
self.requires.append(package)
|
||||||
xrequires = xrequires.NextSiblingElement('requires')
|
xrequires = xrequires.NextSiblingElement('requires')
|
||||||
@ -1012,9 +1028,12 @@ class Packager:
|
|||||||
self.installDir = None
|
self.installDir = None
|
||||||
self.persistDir = None
|
self.persistDir = None
|
||||||
|
|
||||||
# A search list of directories and/or URL's to search for
|
# The download URL at which these packages will eventually be
|
||||||
# installed packages. We query it from a config variable
|
# hosted. This may also be changed with the "host" command.
|
||||||
# initially, but we may also be extending it at runtime.
|
self.host = PandaSystem.getPackageHostUrl()
|
||||||
|
self.hostDescriptiveName = None
|
||||||
|
|
||||||
|
# A search list for previously-built local packages.
|
||||||
self.installSearch = ConfigVariableSearchPath('pdef-path')
|
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.
|
||||||
@ -1195,23 +1214,8 @@ class Packager:
|
|||||||
# We must have an actual install directory.
|
# We must have an actual install directory.
|
||||||
assert(self.installDir)
|
assert(self.installDir)
|
||||||
|
|
||||||
## # If the persist dir names an empty or nonexistent directory,
|
if not PandaSystem.getPackageVersionString() or not PandaSystem.getPackageHostUrl():
|
||||||
## # we will be generating a brand new publish with no previous
|
raise PackagerError, 'This script must be run using a version of Panda3D that has been built\nfor distribution. Try using ppackage.p3d or packp3d.p3d instead.'
|
||||||
## # patches.
|
|
||||||
## self.persistDir.makeDir()
|
|
||||||
|
|
||||||
## # Within the persist dir, we make a temporary holding dir for
|
|
||||||
## # generating multifiles.
|
|
||||||
## self.mfTempDir = Filename(self.persistDir, Filename('mftemp/'))
|
|
||||||
## self.mfTempDir.makeDir()
|
|
||||||
|
|
||||||
## # We also need a temporary holding dir for squeezing py files.
|
|
||||||
## self.pyzTempDir = Filename(self.persistDir, Filename('pyz/'))
|
|
||||||
## self.pyzTempDir.makeDir()
|
|
||||||
|
|
||||||
## # Change to the persist directory so the temp files will be
|
|
||||||
## # created there
|
|
||||||
## os.chdir(self.persistDir.toOsSpecific())
|
|
||||||
|
|
||||||
def __expandVariable(self, line, p):
|
def __expandVariable(self, line, p):
|
||||||
""" Given that line[p] is a dollar sign beginning a variable
|
""" Given that line[p] is a dollar sign beginning a variable
|
||||||
@ -1441,6 +1445,32 @@ class Packager:
|
|||||||
value = ExecutionEnvironment.expandString(value.strip())
|
value = ExecutionEnvironment.expandString(value.strip())
|
||||||
ExecutionEnvironment.setEnvironmentVariable(variable, value)
|
ExecutionEnvironment.setEnvironmentVariable(variable, value)
|
||||||
|
|
||||||
|
def parse_host(self, words):
|
||||||
|
"""
|
||||||
|
host "url" ["descriptive name"]
|
||||||
|
"""
|
||||||
|
|
||||||
|
hostDescriptiveName = None
|
||||||
|
try:
|
||||||
|
if len(words) == 2:
|
||||||
|
command, host = words
|
||||||
|
else:
|
||||||
|
command, host, hostDescriptiveName = words
|
||||||
|
except ValueError:
|
||||||
|
raise ArgumentNumber
|
||||||
|
|
||||||
|
if self.currentPackage:
|
||||||
|
self.currentPackage.host = host
|
||||||
|
else:
|
||||||
|
# Outside of a package, the "host" command specifies the
|
||||||
|
# host for all future packages.
|
||||||
|
self.host = host
|
||||||
|
|
||||||
|
# The descriptive name, if specified, is kept until the end,
|
||||||
|
# where it may be passed to make_contents by ppackage.py.
|
||||||
|
if hostDescriptiveName:
|
||||||
|
self.hostDescriptiveName = hostDescriptiveName
|
||||||
|
|
||||||
def parse_model_path(self, words):
|
def parse_model_path(self, words):
|
||||||
"""
|
"""
|
||||||
model_path directory
|
model_path directory
|
||||||
@ -1469,10 +1499,10 @@ class Packager:
|
|||||||
|
|
||||||
def parse_begin_package(self, words):
|
def parse_begin_package(self, words):
|
||||||
"""
|
"""
|
||||||
begin_package packageName [version=v]
|
begin_package packageName [version=v] [host=host]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
args = self.__parseArgs(words, ['version'])
|
args = self.__parseArgs(words, ['version', 'host'])
|
||||||
|
|
||||||
try:
|
try:
|
||||||
command, packageName = words
|
command, packageName = words
|
||||||
@ -1480,8 +1510,10 @@ class Packager:
|
|||||||
raise ArgumentNumber
|
raise ArgumentNumber
|
||||||
|
|
||||||
version = args.get('version', None)
|
version = args.get('version', None)
|
||||||
|
host = args.get('host', None)
|
||||||
|
|
||||||
self.beginPackage(packageName, version = version, p3dApplication = False)
|
self.beginPackage(packageName, version = version, host = host,
|
||||||
|
p3dApplication = False)
|
||||||
|
|
||||||
def parse_end_package(self, words):
|
def parse_end_package(self, words):
|
||||||
"""
|
"""
|
||||||
@ -1539,10 +1571,10 @@ class Packager:
|
|||||||
|
|
||||||
def parse_require(self, words):
|
def parse_require(self, words):
|
||||||
"""
|
"""
|
||||||
require packageName [version=v]
|
require packageName [version=v] [host=url]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
args = self.__parseArgs(words, ['version'])
|
args = self.__parseArgs(words, ['version', 'host'])
|
||||||
|
|
||||||
try:
|
try:
|
||||||
command, packageName = words
|
command, packageName = words
|
||||||
@ -1550,7 +1582,8 @@ class Packager:
|
|||||||
raise ArgumentError
|
raise ArgumentError
|
||||||
|
|
||||||
version = args.get('version', None)
|
version = args.get('version', None)
|
||||||
self.require(packageName, version = version)
|
host = args.get('host', None)
|
||||||
|
self.require(packageName, version = version, host = host)
|
||||||
|
|
||||||
def parse_module(self, words):
|
def parse_module(self, words):
|
||||||
"""
|
"""
|
||||||
@ -1798,7 +1831,8 @@ class Packager:
|
|||||||
del words[-1]
|
del words[-1]
|
||||||
|
|
||||||
|
|
||||||
def beginPackage(self, packageName, version = None, p3dApplication = False):
|
def beginPackage(self, packageName, version = None, host = None,
|
||||||
|
p3dApplication = False):
|
||||||
""" Begins a new package specification. packageName is the
|
""" Begins a new package specification. packageName is the
|
||||||
basename of the package. Follow this with a number of calls
|
basename of the package. Follow this with a number of calls
|
||||||
to file() etc., and close the package with endPackage(). """
|
to file() etc., and close the package with endPackage(). """
|
||||||
@ -1806,20 +1840,33 @@ class Packager:
|
|||||||
if self.currentPackage:
|
if self.currentPackage:
|
||||||
raise PackagerError, 'unmatched end_package %s' % (self.currentPackage.packageName)
|
raise PackagerError, 'unmatched end_package %s' % (self.currentPackage.packageName)
|
||||||
|
|
||||||
# A special case for the Panda3D package. We enforce that the
|
if host is None and not p3dApplication:
|
||||||
# version number matches what we've been compiled with.
|
# Every package that doesn't specify otherwise uses the
|
||||||
|
# current download host.
|
||||||
|
host = self.host
|
||||||
|
|
||||||
|
# A special case when building the "panda3d" package. We
|
||||||
|
# enforce that the version number matches what we've been
|
||||||
|
# compiled with.
|
||||||
if packageName == 'panda3d':
|
if packageName == 'panda3d':
|
||||||
if version is None:
|
if version is None:
|
||||||
version = PandaSystem.getPackageVersionString()
|
version = PandaSystem.getPackageVersionString()
|
||||||
else:
|
if host is None:
|
||||||
|
host = PandaSystem.getPackageHostUrl()
|
||||||
|
|
||||||
if version != PandaSystem.getPackageVersionString():
|
if version != PandaSystem.getPackageVersionString():
|
||||||
message = 'mismatched Panda3D version: requested %s, but Panda3D is built as %s' % (version, PandaSystem.getPackageVersionString())
|
message = 'mismatched Panda3D version: requested %s, but Panda3D is built as %s' % (version, PandaSystem.getPackageVersionString())
|
||||||
raise PackageError, message
|
raise PackageError, message
|
||||||
|
|
||||||
|
if host != PandaSystem.getPackageHostUrl():
|
||||||
|
message = 'mismatched Panda3D host: requested %s, but Panda3D is built as %s' % (host, PandaSystem.getPackageHostUrl())
|
||||||
|
raise PackageError, message
|
||||||
|
|
||||||
package = self.Package(packageName, self)
|
package = self.Package(packageName, self)
|
||||||
self.currentPackage = package
|
self.currentPackage = package
|
||||||
|
|
||||||
package.version = version
|
package.version = version
|
||||||
|
package.host = host
|
||||||
package.p3dApplication = p3dApplication
|
package.p3dApplication = p3dApplication
|
||||||
|
|
||||||
if package.p3dApplication:
|
if package.p3dApplication:
|
||||||
@ -1855,7 +1902,7 @@ class Packager:
|
|||||||
self.currentPackage = None
|
self.currentPackage = None
|
||||||
|
|
||||||
def findPackage(self, packageName, platform = None, version = None,
|
def findPackage(self, packageName, platform = None, version = None,
|
||||||
requires = None):
|
host = None, requires = None):
|
||||||
""" Searches for the named package from a previous publish
|
""" Searches for the named package from a previous publish
|
||||||
operation along the install search path.
|
operation along the install search path.
|
||||||
|
|
||||||
@ -1872,25 +1919,32 @@ class Packager:
|
|||||||
platform = self.platform
|
platform = self.platform
|
||||||
|
|
||||||
# Is it a package we already have resident?
|
# Is it a package we already have resident?
|
||||||
package = self.packages.get((packageName, platform, version), None)
|
package = self.packages.get((packageName, platform, version, host), None)
|
||||||
if package:
|
if package:
|
||||||
return package
|
return package
|
||||||
|
|
||||||
# Look on the searchlist.
|
# Look on the searchlist.
|
||||||
for dirname in self.installSearch.getDirectories():
|
for dirname in self.installSearch.getDirectories():
|
||||||
package = self.__scanPackageDir(dirname, packageName, platform, version, requires = requires)
|
package = self.__scanPackageDir(dirname, packageName, platform, version, host, requires = requires)
|
||||||
if not package:
|
if not package:
|
||||||
package = self.__scanPackageDir(dirname, packageName, None, version, requires = requires)
|
package = self.__scanPackageDir(dirname, packageName, None, version, host, requires = requires)
|
||||||
|
|
||||||
if package:
|
if package:
|
||||||
package = self.packages.setdefault((package.packageName, package.platform, package.version), package)
|
break
|
||||||
self.packages[(packageName, platform, version)] = package
|
|
||||||
|
if not package:
|
||||||
|
# Query the indicated host.
|
||||||
|
package = self.__findPackageOnHost(packageName, platform, version, host, requires = requires)
|
||||||
|
|
||||||
|
if package:
|
||||||
|
package = self.packages.setdefault((package.packageName, package.platform, package.version, package.host), package)
|
||||||
|
self.packages[(packageName, platform, version, host)] = package
|
||||||
return package
|
return package
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def __scanPackageDir(self, rootDir, packageName, platform, version,
|
def __scanPackageDir(self, rootDir, packageName, platform, version,
|
||||||
requires = None):
|
host, requires = None):
|
||||||
""" Scans a directory on disk, looking for *_import.xml files
|
""" Scans a directory on disk, looking for *_import.xml files
|
||||||
that match the indicated packageName and optional version. If a
|
that match the indicated packageName and optional version. If a
|
||||||
suitable xml file is found, reads it and returns the assocated
|
suitable xml file is found, reads it and returns the assocated
|
||||||
@ -1917,6 +1971,9 @@ class Packager:
|
|||||||
packageDir = Filename(packageDir, '*')
|
packageDir = Filename(packageDir, '*')
|
||||||
basename += '_%s' % ('*')
|
basename += '_%s' % ('*')
|
||||||
|
|
||||||
|
# Actually, the host means little for this search, since we're
|
||||||
|
# only looking in a local directory at this point.
|
||||||
|
|
||||||
basename += '_import.xml'
|
basename += '_import.xml'
|
||||||
filename = Filename(packageDir, basename)
|
filename = Filename(packageDir, basename)
|
||||||
filelist = glob.glob(filename.toOsSpecific())
|
filelist = glob.glob(filename.toOsSpecific())
|
||||||
@ -1934,6 +1991,10 @@ class Packager:
|
|||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def __findPackageOnHost(self, packageName, platform, version, host, requires = None):
|
||||||
|
# TODO.
|
||||||
|
return None
|
||||||
|
|
||||||
def __sortPackageImportFilelist(self, filelist):
|
def __sortPackageImportFilelist(self, filelist):
|
||||||
""" Given a list of *_import.xml filenames, sorts them in
|
""" Given a list of *_import.xml filenames, sorts them in
|
||||||
reverse order by version, so that the highest-numbered
|
reverse order by version, so that the highest-numbered
|
||||||
@ -1968,6 +2029,7 @@ class Packager:
|
|||||||
while p < len(version) and version[p] in string.digits:
|
while p < len(version) and version[p] in string.digits:
|
||||||
w += version[p]
|
w += version[p]
|
||||||
p += 1
|
p += 1
|
||||||
|
if w:
|
||||||
words.append(int(w))
|
words.append(int(w))
|
||||||
|
|
||||||
return tuple(words)
|
return tuple(words)
|
||||||
@ -2024,7 +2086,7 @@ class Packager:
|
|||||||
|
|
||||||
self.currentPackage.configs[variable] = value
|
self.currentPackage.configs[variable] = value
|
||||||
|
|
||||||
def require(self, packageName, version = None):
|
def require(self, packageName, version = None, host = None):
|
||||||
""" Indicates a dependency on the named package, supplied as
|
""" Indicates a dependency on the named package, supplied as
|
||||||
a name.
|
a name.
|
||||||
|
|
||||||
@ -2035,13 +2097,17 @@ class Packager:
|
|||||||
if not self.currentPackage:
|
if not self.currentPackage:
|
||||||
raise OutsideOfPackageError
|
raise OutsideOfPackageError
|
||||||
|
|
||||||
# A special case for the Panda3D package. We enforce that the
|
# A special case when requiring the "panda3d" package. We
|
||||||
# version number matches what we've been compiled with.
|
# supply the version number what we've been compiled with as a
|
||||||
|
# default.
|
||||||
if packageName == 'panda3d':
|
if packageName == 'panda3d':
|
||||||
if version is None:
|
if version is None:
|
||||||
version = PandaSystem.getPackageVersionString()
|
version = PandaSystem.getPackageVersionString()
|
||||||
|
if host is None:
|
||||||
|
host = PandaSystem.getPackageHostUrl()
|
||||||
|
|
||||||
package = self.findPackage(packageName, version = version, requires = self.currentPackage.requires)
|
package = self.findPackage(packageName, version = version, host = host,
|
||||||
|
requires = self.currentPackage.requires)
|
||||||
if not package:
|
if not package:
|
||||||
message = 'Unknown package %s, version "%s"' % (packageName, version)
|
message = 'Unknown package %s, version "%s"' % (packageName, version)
|
||||||
raise PackagerError, message
|
raise PackagerError, message
|
||||||
@ -2059,20 +2125,14 @@ class Packager:
|
|||||||
if not self.currentPackage:
|
if not self.currentPackage:
|
||||||
raise OutsideOfPackageError
|
raise OutsideOfPackageError
|
||||||
|
|
||||||
# A special case for the Panda3D package. We enforce that the
|
# A special case when requiring the "panda3d" package. We
|
||||||
# version number matches what we've been compiled with.
|
# complain if the version number doesn't match what we've been
|
||||||
|
# compiled with.
|
||||||
if package.packageName == 'panda3d':
|
if package.packageName == 'panda3d':
|
||||||
if package.version != PandaSystem.getPackageVersionString():
|
if package.version != PandaSystem.getPackageVersionString():
|
||||||
if not PandaSystem.getPackageVersionString():
|
|
||||||
# We haven't been compiled with any particular
|
|
||||||
# version of Panda. This is a warning, not an
|
|
||||||
# error.
|
|
||||||
print "Warning: requiring panda3d version %s, which may or may not match the current build of Panda. Recommend that you use only the official Panda3D build for making distributable applications to ensure compatibility." % (package.version)
|
|
||||||
else:
|
|
||||||
# This particular version of Panda doesn't match
|
|
||||||
# the requested version. Again, a warning, not an
|
|
||||||
# error.
|
|
||||||
print "Warning: requiring panda3d version %s, which does not match the current build of Panda, which is version %s." % (package, PandaSystem.getPackageVersionString())
|
print "Warning: requiring panda3d version %s, which does not match the current build of Panda, which is version %s." % (package, PandaSystem.getPackageVersionString())
|
||||||
|
elif package.host != PandaSystem.getPackageHostUrl():
|
||||||
|
print "Warning: requiring panda3d host %s, which does not match the current build of Panda, which is host %s." % (package, PandaSystem.getPackageHostUrl())
|
||||||
|
|
||||||
self.currentPackage.requirePackage(package)
|
self.currentPackage.requirePackage(package)
|
||||||
|
|
||||||
|
@ -12,17 +12,24 @@ make_contents.py [opts]
|
|||||||
|
|
||||||
Options:
|
Options:
|
||||||
|
|
||||||
-d stage_dir
|
-i install_dir
|
||||||
|
The full path to a local directory that contains the
|
||||||
|
ready-to-be-published files, as populated by one or more
|
||||||
|
iterations of the ppackage script. It is the user's
|
||||||
|
responsibility to copy this directory structure to a server.
|
||||||
|
|
||||||
Specify the staging directory. This is a temporary directory on
|
-n "host descriptive name"
|
||||||
the local machine that contains a copy of the web server
|
Specifies a descriptive name of the download server that will
|
||||||
contents. The default is the current directory.
|
host these contents. This name may be presented to the user when
|
||||||
|
managing installed packages. If this option is omitted, the name
|
||||||
|
is unchanged from the previous pass.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import getopt
|
import getopt
|
||||||
import os
|
import os
|
||||||
|
import types
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import hashlib
|
import hashlib
|
||||||
@ -56,6 +63,7 @@ class FileSpec:
|
|||||||
class ContentsMaker:
|
class ContentsMaker:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.installDir = None
|
self.installDir = None
|
||||||
|
self.hostDescriptiveName = None
|
||||||
|
|
||||||
def build(self):
|
def build(self):
|
||||||
if not self.installDir:
|
if not self.installDir:
|
||||||
@ -67,20 +75,56 @@ class ContentsMaker:
|
|||||||
if not self.packages:
|
if not self.packages:
|
||||||
raise ArgumentError, "No packages found."
|
raise ArgumentError, "No packages found."
|
||||||
|
|
||||||
# Now write the contents.xml file.
|
|
||||||
contentsFileBasename = 'contents.xml'
|
contentsFileBasename = 'contents.xml'
|
||||||
contentsFilePathname = os.path.join(self.installDir, contentsFileBasename)
|
contentsFilePathname = os.path.join(self.installDir, contentsFileBasename)
|
||||||
|
contentsLine = None
|
||||||
|
if self.hostDescriptiveName is not None:
|
||||||
|
if self.hostDescriptiveName:
|
||||||
|
contentsLine = '<contents descriptive_name="%s">' % (
|
||||||
|
self.quoteString(self.hostDescriptiveName))
|
||||||
|
else:
|
||||||
|
contentsLine = self.readContentsLine(contentsFilePathname)
|
||||||
|
if not contentsLine:
|
||||||
|
contentsLine = '<contents>'
|
||||||
|
|
||||||
|
# Now write the contents.xml file.
|
||||||
f = open(contentsFilePathname, 'w')
|
f = open(contentsFilePathname, 'w')
|
||||||
print >> f, '<?xml version="1.0" ?>'
|
print >> f, '<?xml version="1.0" encoding="utf-8" ?>'
|
||||||
print >> f, ''
|
print >> f, ''
|
||||||
print >> f, '<contents>'
|
print >> f, contentsLine
|
||||||
for type, packageName, packagePlatform, packageVersion, file in self.packages:
|
for type, packageName, packagePlatform, packageVersion, file in self.packages:
|
||||||
print >> f, ' <%s name="%s" platform="%s" version="%s" %s />' % (
|
print >> f, ' <%s name="%s" platform="%s" version="%s" %s />' % (
|
||||||
type, packageName, packagePlatform or '', packageVersion, file.getParams())
|
type, packageName, packagePlatform or '', packageVersion, file.getParams())
|
||||||
print >> f, '</contents>'
|
print >> f, '</contents>'
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
|
def readContentsLine(self, contentsFilePathname):
|
||||||
|
""" Reads the previous iteration of contents.xml to get the
|
||||||
|
previous top-level contents line, which contains the
|
||||||
|
hostDescriptiveName. """
|
||||||
|
|
||||||
|
try:
|
||||||
|
f = open(contentsFilePathname, 'r')
|
||||||
|
except OSError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
for line in f.readlines():
|
||||||
|
if line.startswith('<contents'):
|
||||||
|
return line.rstrip()
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def quoteString(self, str):
|
||||||
|
""" Correctly quotes a string for embedding in the xml file. """
|
||||||
|
if isinstance(str, types.UnicodeType):
|
||||||
|
str = str.encode('utf-8')
|
||||||
|
str = str.replace('&', '&')
|
||||||
|
str = str.replace('"', '"')
|
||||||
|
str = str.replace('\'', ''')
|
||||||
|
str = str.replace('<', '<')
|
||||||
|
str = str.replace('>', '>')
|
||||||
|
return str
|
||||||
|
|
||||||
def scanDirectory(self):
|
def scanDirectory(self):
|
||||||
""" Walks through all the files in the stage directory and
|
""" Walks through all the files in the stage directory and
|
||||||
looks for the package directory xml files. """
|
looks for the package directory xml files. """
|
||||||
@ -139,14 +183,17 @@ class ContentsMaker:
|
|||||||
|
|
||||||
|
|
||||||
def makeContents(args):
|
def makeContents(args):
|
||||||
opts, args = getopt.getopt(args, 'd:h')
|
opts, args = getopt.getopt(args, 'i:n:h')
|
||||||
|
|
||||||
cm = ContentsMaker()
|
cm = ContentsMaker()
|
||||||
cm.installDir = '.'
|
cm.installDir = '.'
|
||||||
for option, value in opts:
|
for option, value in opts:
|
||||||
if option == '-d':
|
if option == '-i':
|
||||||
cm.installDir = value
|
cm.installDir = value
|
||||||
|
|
||||||
|
elif option == '-n':
|
||||||
|
cm.hostDescriptiveName = value
|
||||||
|
|
||||||
elif option == '-h':
|
elif option == '-h':
|
||||||
print __doc__
|
print __doc__
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
@ -119,6 +119,7 @@ def makePackedApp(args):
|
|||||||
packager.installDir = appDir
|
packager.installDir = appDir
|
||||||
getModelPath().appendDirectory(root)
|
getModelPath().appendDirectory(root)
|
||||||
|
|
||||||
|
try:
|
||||||
packager.setup()
|
packager.setup()
|
||||||
packager.beginPackage(appBase, p3dApplication = True)
|
packager.beginPackage(appBase, p3dApplication = True)
|
||||||
for requireName in requires:
|
for requireName in requires:
|
||||||
@ -128,6 +129,11 @@ def makePackedApp(args):
|
|||||||
packager.mainModule(mainModule)
|
packager.mainModule(mainModule)
|
||||||
|
|
||||||
packager.endPackage(appBase, p3dApplication = True)
|
packager.endPackage(appBase, p3dApplication = True)
|
||||||
|
except Packager.PackagerError:
|
||||||
|
# Just print the error message and exit gracefully.
|
||||||
|
inst = sys.exc_info()[1]
|
||||||
|
print inst.args[0]
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
def main(appRunner):
|
def main(appRunner):
|
||||||
""" This function is called when this module is invoked as
|
""" This function is called when this module is invoked as
|
||||||
|
@ -38,12 +38,13 @@ Options:
|
|||||||
ready-to-be-published files into. This directory structure may
|
ready-to-be-published files into. This directory structure may
|
||||||
contain multiple different packages from multiple different
|
contain multiple different packages from multiple different
|
||||||
invocations of this script. It is the user's responsibility to
|
invocations of this script. It is the user's responsibility to
|
||||||
copy this directory structure to a web host where it may be
|
copy this directory structure to a server, which will have the
|
||||||
downloaded by the client.
|
URL specified by -u, below.
|
||||||
|
|
||||||
-s search_dir
|
-s search_dir
|
||||||
Additional directories to search for previously-built packages.
|
Additional directories to search for previously-built packages.
|
||||||
This option may be repeated as necessary.
|
This option may be repeated as necessary. These directories may
|
||||||
|
also be specified with the pdef-path Config.prc variable.
|
||||||
|
|
||||||
-d persist_dir
|
-d persist_dir
|
||||||
The full path to a local directory that retains persistant state
|
The full path to a local directory that retains persistant state
|
||||||
@ -54,6 +55,21 @@ Options:
|
|||||||
empty, patches will not be created for this publish; but the
|
empty, patches will not be created for this publish; but the
|
||||||
directory structure will be populated for the next publish.
|
directory structure will be populated for the next publish.
|
||||||
|
|
||||||
|
-u host_url
|
||||||
|
Specifies the URL to the download server that will eventually
|
||||||
|
host these packages (that is, the public URL of the install
|
||||||
|
directory). This may also be overridden with a "host" command
|
||||||
|
appearing within the pdef file. This is used for packages only;
|
||||||
|
it is ignored for p3d applications, which are not specific to a
|
||||||
|
particular host.
|
||||||
|
|
||||||
|
-n "host descriptive name"
|
||||||
|
Specifies a descriptive name of the download server named by -u.
|
||||||
|
This name may be presented to the user when managing installed
|
||||||
|
packages. This may also be overridden with a "host" command
|
||||||
|
appearing within the pdef file. This information is written to
|
||||||
|
the contents.xml file at the top of the install directory.
|
||||||
|
|
||||||
-p platform
|
-p platform
|
||||||
Specify the platform to masquerade as. The default is whatever
|
Specify the platform to masquerade as. The default is whatever
|
||||||
platform Panda has been built for. It is probably unwise to set
|
platform Panda has been built for. It is probably unwise to set
|
||||||
@ -82,7 +98,7 @@ def usage(code, msg = ''):
|
|||||||
packager = Packager.Packager()
|
packager = Packager.Packager()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
opts, args = getopt.getopt(sys.argv[1:], 'i:s:d:p:Hh')
|
opts, args = getopt.getopt(sys.argv[1:], 'i:s:d:p:u:n:Hh')
|
||||||
except getopt.error, msg:
|
except getopt.error, msg:
|
||||||
usage(1, msg)
|
usage(1, msg)
|
||||||
|
|
||||||
@ -95,6 +111,10 @@ for opt, arg in opts:
|
|||||||
packager.persistDir = Filename.fromOsSpecific(arg)
|
packager.persistDir = Filename.fromOsSpecific(arg)
|
||||||
elif opt == '-p':
|
elif opt == '-p':
|
||||||
packager.platform = arg
|
packager.platform = arg
|
||||||
|
elif opt == '-u':
|
||||||
|
package.host = arg
|
||||||
|
elif opt == '-n':
|
||||||
|
package.hostDescriptiveName = arg
|
||||||
|
|
||||||
elif opt == '-h':
|
elif opt == '-h':
|
||||||
usage(0)
|
usage(0)
|
||||||
@ -117,8 +137,14 @@ if not packager.installDir:
|
|||||||
packager.installDir = Filename('install')
|
packager.installDir = Filename('install')
|
||||||
packager.installSearch.prependDirectory(packager.installDir)
|
packager.installSearch.prependDirectory(packager.installDir)
|
||||||
|
|
||||||
packager.setup()
|
try:
|
||||||
packages = packager.readPackageDef(packageDef)
|
packager.setup()
|
||||||
|
packages = packager.readPackageDef(packageDef)
|
||||||
|
except Packager.PackagerError:
|
||||||
|
# Just print the error message and exit gracefully.
|
||||||
|
inst = sys.exc_info()[1]
|
||||||
|
print inst.args[0]
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
# Look to see if we built any true packages, or if all of them were
|
# Look to see if we built any true packages, or if all of them were
|
||||||
# p3d files.
|
# p3d files.
|
||||||
@ -133,5 +159,6 @@ if anyPackages:
|
|||||||
# the root of the install directory.
|
# the root of the install directory.
|
||||||
cm = make_contents.ContentsMaker()
|
cm = make_contents.ContentsMaker()
|
||||||
cm.installDir = packager.installDir.toOsSpecific()
|
cm.installDir = packager.installDir.toOsSpecific()
|
||||||
|
cm.hostDescriptiveName = packager.hostDescriptiveName
|
||||||
cm.build()
|
cm.build()
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user