def getHostWithDir(self, hostDir): """ Returns the HostInfo object that corresponds to the indicated on-disk host directory. This would be used when reading a host directory from disk, instead of downloading it from a server. Supply the full path to the host directory, as a Filename. Returns None if the contents.xml in the indicated host directory cannot be read or doesn't seem consistent. """ host = HostInfo(None, hostDir = hostDir, appRunner = self) if not host.hasContentsFile: if not host.readContentsFile(): # Couldn't read the contents.xml file return None if not host.hostUrl: # The contents.xml file there didn't seem to indicate the # same host directory. return None host2 = self.hosts.get(host.hostUrl) if host2 is None: # No such host already; store this one. self.hosts[host.hostUrl] = host return host if host2.hostDir != host.hostDir: # Hmm, we already have that host somewhere else. return None # We already have that host, and it's consistent. return host2
def getHostWithDir(self, hostDir): """ Returns the HostInfo object that corresponds to the indicated on-disk host directory. This would be used when reading a host directory from disk, instead of downloading it from a server. Supply the full path to the host directory, as a Filename. Returns None if the contents.xml in the indicated host directory cannot be read or doesn't seem consistent. """ host = HostInfo(None, hostDir=hostDir, appRunner=self) if not host.hasContentsFile: if not host.readContentsFile(): # Couldn't read the contents.xml file return None if not host.hostUrl: # The contents.xml file there didn't seem to indicate the # same host directory. return None host2 = self.hosts.get(host.hostUrl) if host2 is None: # No such host already; store this one. self.hosts[host.hostUrl] = host return host if host2.hostDir != host.hostDir: # Hmm, we already have that host somewhere else. return None # We already have that host, and it's consistent. return host2
def getHost(self, hostUrl): if hostUrl in self.hosts: return self.hosts[hostUrl] host = HostInfo(hostUrl, appRunner=appRunner, hostDir=self.hostDir, asMirror=False, perPlatform=False) if not host.hasContentsFile: if not host.readContentsFile(): if not host.downloadContentsFile(self.http): Installer.notify.error("couldn't read host %s" % host.hostUrl) return None self.hosts[hostUrl] = host return host
def __init__(self, p3dfile, tokens={}): self.p3dfile = Filename(p3dfile) self.basename = self.p3dfile.getBasenameWoExtension() self.tokens = tokens self.tempDir = Filename.temporary("", self.basename, "") + "/" self.tempDir.makeDir() self.host = HostInfo(PandaSystem.getPackageHostUrl(), appRunner=appRunner, hostDir=self.tempDir, asMirror=False, perPlatform=True) self.http = HTTPClient.getGlobalPtr() if not self.host.hasContentsFile: if not self.host.readContentsFile(): if not self.host.downloadContentsFile(self.http): Standalone.notify.error("couldn't read host") return
def getHost(self, hostUrl, hostDir=None): """ Returns a new HostInfo object corresponding to the indicated host URL. If we have already seen this URL previously, returns the same object. This returns the literal referenced host. To return the mapped host, which is the one we should actually download from, see getHostWithAlt(). """ if not hostUrl: hostUrl = self.pandaHostUrl host = self.hosts.get(hostUrl, None) if not host: host = HostInfo(hostUrl, appRunner=self, hostDir=hostDir) self.hosts[hostUrl] = host return host
def __init__(self, p3dfile, tokens={}): self.p3dfile = Filename(p3dfile) self.basename = self.p3dfile.getBasenameWoExtension() self.tokens = tokens self.tempDir = Filename.temporary("", self.basename, "") + "/" self.tempDir.makeDir() self.host = HostInfo( PandaSystem.getPackageHostUrl(), appRunner=appRunner, hostDir=self.tempDir, asMirror=False, perPlatform=True ) self.http = HTTPClient.getGlobalPtr() if not self.host.hasContentsFile: if not self.host.readContentsFile(): if not self.host.downloadContentsFile(self.http): Standalone.notify.error("couldn't read host") return
class Standalone: """ This class creates a standalone executable from a given .p3d file. """ notify = directNotify.newCategory("Standalone") def __init__(self, p3dfile, tokens={}): self.p3dfile = Filename(p3dfile) self.basename = self.p3dfile.getBasenameWoExtension() self.tokens = tokens self.tempDir = Filename.temporary("", self.basename, "") + "/" self.tempDir.makeDir() self.host = HostInfo( PandaSystem.getPackageHostUrl(), appRunner=appRunner, hostDir=self.tempDir, asMirror=False, perPlatform=True ) self.http = HTTPClient.getGlobalPtr() if not self.host.hasContentsFile: if not self.host.readContentsFile(): if not self.host.downloadContentsFile(self.http): Standalone.notify.error("couldn't read host") return def __del__(self): try: appRunner.rmtree(self.tempDir) except: try: shutil.rmtree(self.tempDir.toOsSpecific()) except: pass def buildAll(self, outputDir="."): """ Builds standalone executables for every known platform, into the specified output directory. """ platforms = set() for package in self.host.getPackages(name="p3dembed"): platforms.add(package.platform) if len(platforms) == 0: Standalone.notify.warning("No platforms found to build for!") outputDir = Filename(outputDir + "/") outputDir.makeDir() for platform in platforms: if platform.startswith("win"): self.build(Filename(outputDir, platform + "/" + self.basename + ".exe"), platform) else: self.build(Filename(outputDir, platform + "/" + self.basename), platform) def build(self, output, platform=None, extraTokens={}): """ Builds a standalone executable and stores it into the path indicated by the 'output' argument. You can specify to build for a different platform by altering the 'platform' argument. """ if platform == None: platform = PandaSystem.getPlatform() vfs = VirtualFileSystem.getGlobalPtr() for package in self.host.getPackages(name="p3dembed", platform=platform): if not package.downloadDescFile(self.http): Standalone.notify.warning(" -> %s failed for platform %s" % (package.packageName, package.platform)) continue if not package.downloadPackage(self.http): Standalone.notify.warning(" -> %s failed for platform %s" % (package.packageName, package.platform)) continue # Figure out where p3dembed might be now. if package.platform.startswith("win"): # Use p3dembedw unless console_environment was set. if extraTokens.get("console_environment", self.tokens.get("console_environment", 0)) != 0: p3dembed = Filename(self.host.hostDir, "p3dembed/%s/p3dembed.exe" % package.platform) else: p3dembed = Filename(self.host.hostDir, "p3dembed/%s/p3dembedw.exe" % package.platform) # Fallback for older p3dembed versions if not vfs.exists(p3dembed): Filename(self.host.hostDir, "p3dembed/%s/p3dembed.exe" % package.platform) else: p3dembed = Filename(self.host.hostDir, "p3dembed/%s/p3dembed" % package.platform) if not vfs.exists(p3dembed): Standalone.notify.warning(" -> %s failed for platform %s" % (package.packageName, package.platform)) continue return self.embed(output, p3dembed, extraTokens) Standalone.notify.error("Failed to build standalone for platform %s" % platform) def embed(self, output, p3dembed, extraTokens={}): """ Embeds the p3d file into the provided p3dembed executable. This function is not really useful - use build() or buildAll() instead. """ # Load the p3dembed data into memory size = p3dembed.getFileSize() p3dembed_data = VirtualFileSystem.getGlobalPtr().readFile(p3dembed, True) assert len(p3dembed_data) == size # Find the magic size string and replace it with the real size, # regardless of the endianness of the p3dembed executable. hex_size = hex(size)[2:].rjust(8, "0") enc_size = "".join([chr(int(hex_size[i] + hex_size[i + 1], 16)) for i in range(0, len(hex_size), 2)]) p3dembed_data = p3dembed_data.replace(P3DEMBED_MAGIC, enc_size) p3dembed_data = p3dembed_data.replace(P3DEMBED_MAGIC[::-1], enc_size[::-1]) # Write the output file Standalone.notify.info("Creating %s..." % output) output.makeDir() ohandle = open(output.toOsSpecific(), "wb") ohandle.write(p3dembed_data) # Write out the tokens. Set log_basename to the basename by default tokens = {"log_basename": self.basename} tokens.update(self.tokens) tokens.update(extraTokens) for token in tokens.items(): ohandle.write("\0%s=%s" % token) ohandle.write("\0\0") # Buffer the p3d file to the output file. 1 MB buffer size. phandle = open(self.p3dfile.toOsSpecific(), "rb") buf = phandle.read(1024 * 1024) while len(buf) != 0: ohandle.write(buf) buf = phandle.read(1024 * 1024) ohandle.close() phandle.close() os.chmod(output.toOsSpecific(), 0755) def getExtraFiles(self, platform): """ Returns a list of extra files that will need to be included with the standalone executable in order for it to run, such as dependent libraries. The returned paths are full absolute paths. """ package = self.host.getPackages(name="p3dembed", platform=platform)[0] if not package.downloadDescFile(self.http): Standalone.notify.warning(" -> %s failed for platform %s" % (package.packageName, package.platform)) return [] if not package.downloadPackage(self.http): Standalone.notify.warning(" -> %s failed for platform %s" % (package.packageName, package.platform)) return [] filenames = [] vfs = VirtualFileSystem.getGlobalPtr() for e in package.extracts: if e.basename not in [ "p3dembed", "p3dembed.exe", "p3dembed.exe.manifest", "p3dembedw.exe", "p3dembedw.exe.manifest", ]: filename = Filename(package.getPackageDir(), e.filename) filename.makeAbsolute() if vfs.exists(filename): filenames.append(filename) else: Standalone.notify.error("%s mentioned in xml, but does not exist" % e.filename) return filenames
class Standalone: """ This class creates a standalone executable from a given .p3d file. """ notify = directNotify.newCategory("Standalone") def __init__(self, p3dfile, tokens={}): self.p3dfile = Filename(p3dfile) self.basename = self.p3dfile.getBasenameWoExtension() self.tokens = tokens self.tempDir = Filename.temporary("", self.basename, "") + "/" self.tempDir.makeDir() self.host = HostInfo(PandaSystem.getPackageHostUrl(), appRunner=appRunner, hostDir=self.tempDir, asMirror=False, perPlatform=True) self.http = HTTPClient.getGlobalPtr() if not self.host.hasContentsFile: if not self.host.readContentsFile(): if not self.host.downloadContentsFile(self.http): Standalone.notify.error("couldn't read host") return def __del__(self): try: appRunner.rmtree(self.tempDir) except: try: shutil.rmtree(self.tempDir.toOsSpecific()) except: pass def buildAll(self, outputDir="."): """ Builds standalone executables for every known platform, into the specified output directory. """ platforms = set() for package in self.host.getPackages(name="p3dembed"): platforms.add(package.platform) if len(platforms) == 0: Standalone.notify.warning("No platforms found to build for!") outputDir = Filename(outputDir + "/") outputDir.makeDir() for platform in platforms: if platform.startswith("win"): self.build( Filename(outputDir, platform + "/" + self.basename + ".exe"), platform) else: self.build(Filename(outputDir, platform + "/" + self.basename), platform) def build(self, output, platform=None, extraTokens={}): """ Builds a standalone executable and stores it into the path indicated by the 'output' argument. You can specify to build for a different platform by altering the 'platform' argument. """ if platform == None: platform = PandaSystem.getPlatform() vfs = VirtualFileSystem.getGlobalPtr() for package in self.host.getPackages(name="p3dembed", platform=platform): if not package.downloadDescFile(self.http): Standalone.notify.warning( " -> %s failed for platform %s" % (package.packageName, package.platform)) continue if not package.downloadPackage(self.http): Standalone.notify.warning( " -> %s failed for platform %s" % (package.packageName, package.platform)) continue # Figure out where p3dembed might be now. if package.platform.startswith("win"): # Use p3dembedw unless console_environment was set. if extraTokens.get("console_environment", self.tokens.get("console_environment", 0)) != 0: p3dembed = Filename( self.host.hostDir, "p3dembed/%s/p3dembed.exe" % package.platform) else: p3dembed = Filename( self.host.hostDir, "p3dembed/%s/p3dembedw.exe" % package.platform) # Fallback for older p3dembed versions if not vfs.exists(p3dembed): Filename(self.host.hostDir, "p3dembed/%s/p3dembed.exe" % package.platform) else: p3dembed = Filename(self.host.hostDir, "p3dembed/%s/p3dembed" % package.platform) if not vfs.exists(p3dembed): Standalone.notify.warning( " -> %s failed for platform %s" % (package.packageName, package.platform)) continue return self.embed(output, p3dembed, extraTokens) Standalone.notify.error("Failed to build standalone for platform %s" % platform) def embed(self, output, p3dembed, extraTokens={}): """ Embeds the p3d file into the provided p3dembed executable. This function is not really useful - use build() or buildAll() instead. """ # Load the p3dembed data into memory size = p3dembed.getFileSize() p3dembed_data = VirtualFileSystem.getGlobalPtr().readFile( p3dembed, True) assert len(p3dembed_data) == size # Find the magic size string and replace it with the real size, # regardless of the endianness of the p3dembed executable. hex_size = hex(size)[2:].rjust(8, "0") enc_size = "".join([ chr(int(hex_size[i] + hex_size[i + 1], 16)) for i in range(0, len(hex_size), 2) ]) p3dembed_data = p3dembed_data.replace(P3DEMBED_MAGIC, enc_size) p3dembed_data = p3dembed_data.replace(P3DEMBED_MAGIC[::-1], enc_size[::-1]) # Write the output file Standalone.notify.info("Creating %s..." % output) output.makeDir() ohandle = open(output.toOsSpecific(), "wb") ohandle.write(p3dembed_data) # Write out the tokens. Set log_basename to the basename by default tokens = {"log_basename": self.basename} tokens.update(self.tokens) tokens.update(extraTokens) for token in tokens.items(): ohandle.write("\0%s=%s" % token) ohandle.write("\0\0") # Buffer the p3d file to the output file. 1 MB buffer size. phandle = open(self.p3dfile.toOsSpecific(), "rb") buf = phandle.read(1024 * 1024) while len(buf) != 0: ohandle.write(buf) buf = phandle.read(1024 * 1024) ohandle.close() phandle.close() os.chmod(output.toOsSpecific(), 0755) def getExtraFiles(self, platform): """ Returns a list of extra files that will need to be included with the standalone executable in order for it to run, such as dependent libraries. The returned paths are full absolute paths. """ package = self.host.getPackages(name="p3dembed", platform=platform)[0] if not package.downloadDescFile(self.http): Standalone.notify.warning(" -> %s failed for platform %s" % (package.packageName, package.platform)) return [] if not package.downloadPackage(self.http): Standalone.notify.warning(" -> %s failed for platform %s" % (package.packageName, package.platform)) return [] filenames = [] vfs = VirtualFileSystem.getGlobalPtr() for e in package.extracts: if e.basename not in [ "p3dembed", "p3dembed.exe", "p3dembed.exe.manifest", "p3dembedw.exe", "p3dembedw.exe.manifest" ]: filename = Filename(package.getPackageDir(), e.filename) filename.makeAbsolute() if vfs.exists(filename): filenames.append(filename) else: Standalone.notify.error( "%s mentioned in xml, but does not exist" % e.filename) return filenames