Port pdeploy to Python 3

This commit is contained in:
rdb 2015-09-30 14:06:12 +02:00
parent 532bee3b9e
commit 1ccf1cf29b
4 changed files with 75 additions and 73 deletions

View File

@ -5,7 +5,7 @@ to build for as many platforms as possible. """
__all__ = ["Standalone", "Installer"]
import os, sys, subprocess, tarfile, shutil, time, zipfile, socket, getpass, struct
from cStringIO import StringIO
from io import BytesIO, TextIOWrapper
from direct.directnotify.DirectNotifyGlobal import *
from direct.showbase.AppRunnerGlobal import appRunner
from panda3d.core import PandaSystem, HTTPClient, Filename, VirtualFileSystem, Multifile
@ -21,8 +21,8 @@ try:
except ImportError:
pwd = None
# Make sure this matches with the magic in p3dEmbed.cxx.
P3DEMBED_MAGIC = "\xFF\x3D\x3D\x00"
# Make sure this matches with the magic in p3dEmbedMain.cxx.
P3DEMBED_MAGIC = 0xFF3D3D00
# This filter function is used when creating
# an archive that should be owned by root.
@ -161,10 +161,10 @@ class Standalone:
# 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])
p3dembed_data = p3dembed_data.replace(struct.pack('>I', P3DEMBED_MAGIC),
struct.pack('>I', size))
p3dembed_data = p3dembed_data.replace(struct.pack('<I', P3DEMBED_MAGIC),
struct.pack('<I', size))
# Write the output file
Standalone.notify.info("Creating %s..." % output)
@ -173,12 +173,15 @@ class Standalone:
ohandle.write(p3dembed_data)
# Write out the tokens. Set log_basename to the basename by default
tokens = {"log_basename" : self.basename}
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")
for key, value in tokens.items():
ohandle.write(b"\0")
ohandle.write(key.encode('ascii'))
ohandle.write(b"=")
ohandle.write(value.encode())
ohandle.write(b"\0\0")
# Buffer the p3d file to the output file. 1 MB buffer size.
phandle = open(self.p3dfile.toOsSpecific(), "rb")
@ -394,7 +397,7 @@ class Icon:
vfs = VirtualFileSystem.getGlobalPtr()
stream = vfs.openWriteFile(fn, False, True)
icns = open(stream, 'wb')
icns.write('icns\0\0\0\0')
icns.write(b'icns\0\0\0\0')
icon_types = {16: 'is32', 32: 'il32', 48: 'ih32', 128: 'it32'}
mask_types = {16: 's8mk', 32: 'l8mk', 48: 'h8mk', 128: 't8mk'}
@ -407,7 +410,7 @@ class Icon:
if pngtype is None:
continue
icns.write(png_types[size])
icns.write('\0\0\0\0')
icns.write(b'\0\0\0\0')
start = icns.tell()
image.write(stream, "", pngtype)
@ -800,16 +803,18 @@ class Installer:
tempdir, totsize = self.__buildTempLinux(platform)
# Create a control file in memory.
controlfile = StringIO()
print >>controlfile, "Package: %s" % self.shortname.lower()
print >>controlfile, "Version: %s" % self.version
print >>controlfile, "Maintainer: %s <%s>" % (self.authorname, self.authoremail)
print >>controlfile, "Section: games"
print >>controlfile, "Priority: optional"
print >>controlfile, "Architecture: %s" % arch
print >>controlfile, "Installed-Size: %d" % -(-totsize / 1024)
print >>controlfile, "Description: %s" % self.fullname
print >>controlfile, "Depends: libc6, libgcc1, libstdc++6, libx11-6"
controlfile = BytesIO()
cout = TextIOWrapper(controlfile, encoding='utf-8', newline='')
cout.write(u"Package: %s\n" % self.shortname.lower())
cout.write(u"Version: %s\n" % self.version)
cout.write(u"Maintainer: %s <%s>\n" % (self.authorname, self.authoremail))
cout.write(u"Section: games\n")
cout.write(u"Priority: optional\n")
cout.write(u"Architecture: %s\n" % arch)
cout.write(u"Installed-Size: %d\n" % -(-totsize // 1024))
cout.write(u"Description: %s\n" % self.fullname)
cout.write(u"Depends: libc6, libgcc1, libstdc++6, libx11-6\n")
cout.flush()
controlinfo = TarInfoRoot("control")
controlinfo.mtime = modtime
controlinfo.size = controlfile.tell()
@ -820,33 +825,43 @@ class Installer:
if output.exists():
output.unlink()
debfile = open(output.toOsSpecific(), "wb")
debfile.write("!<arch>\x0A")
debfile.write("debian-binary %-12lu0 0 100644 %-10ld\x60\x0A" % (modtime, 4))
debfile.write("2.0\x0A")
debfile.write(b"!<arch>\x0A")
pad_mtime = str(modtime).encode().ljust(12, b' ')
# Write the control.tar.gz to the archive.
debfile.write("control.tar.gz %-12lu0 0 100644 %-10ld\x60\x0A" % (modtime, 0))
# The first entry is a special file that marks it a .deb.
debfile.write(b"debian-binary ")
debfile.write(pad_mtime)
debfile.write(b"0 0 100644 4 \x60\x0A")
debfile.write(b"2.0\x0A")
# Write the control.tar.gz to the archive. We'll leave the
# size 0 for now, and go back and fill it in later.
debfile.write(b"control.tar.gz ")
debfile.write(pad_mtime)
debfile.write(b"0 0 100644 0 \x60\x0A")
ctaroffs = debfile.tell()
ctarfile = tarfile.open("control.tar.gz", "w:gz", debfile, tarinfo = TarInfoRoot)
ctarfile.addfile(controlinfo, controlfile)
ctarfile.close()
ctarsize = debfile.tell() - ctaroffs
if (ctarsize & 1): debfile.write("\x0A")
if (ctarsize & 1): debfile.write(b"\x0A")
# Write the data.tar.gz to the archive.
debfile.write("data.tar.gz %-12lu0 0 100644 %-10ld\x60\x0A" % (modtime, 0))
# Write the data.tar.gz to the archive. Again, leave size 0.
debfile.write(b"data.tar.gz ")
debfile.write(pad_mtime)
debfile.write(b"0 0 100644 0 \x60\x0A")
dtaroffs = debfile.tell()
dtarfile = tarfile.open("data.tar.gz", "w:gz", debfile, tarinfo = TarInfoRoot)
dtarfile.add(Filename(tempdir, "usr").toOsSpecific(), "/usr")
dtarfile.close()
dtarsize = debfile.tell() - dtaroffs
if (dtarsize & 1): debfile.write("\x0A")
if (dtarsize & 1): debfile.write(b"\x0A")
# Write the correct sizes of the archives.
debfile.seek(ctaroffs - 12)
debfile.write("%-10ld" % ctarsize)
debfile.write(str(ctarsize).encode().ljust(10, b' '))
debfile.seek(dtaroffs - 12)
debfile.write("%-10ld" % dtarsize)
debfile.write(str(dtarsize).encode().ljust(10, b' '))
debfile.close()
@ -873,18 +888,20 @@ class Installer:
tempdir, totsize = self.__buildTempLinux(platform)
# Create a pkginfo file in memory.
pkginfo = StringIO()
print >>pkginfo, "# Generated using pdeploy"
print >>pkginfo, "# %s" % time.ctime(modtime)
print >>pkginfo, "pkgname = %s" % self.shortname.lower()
print >>pkginfo, "pkgver = %s" % pkgver
print >>pkginfo, "pkgdesc = %s" % self.fullname
print >>pkginfo, "builddate = %s" % modtime
print >>pkginfo, "packager = %s <%s>" % (self.authorname, self.authoremail)
print >>pkginfo, "size = %d" % totsize
print >>pkginfo, "arch = %s" % arch
pkginfo = BytesIO()
pout = TextIOWrapper(pkginfo, encoding='utf-8', newline='')
pout.write(u"# Generated using pdeploy\n")
pout.write(u"# %s\n" % time.ctime(modtime))
pout.write(u"pkgname = %s\n" % self.shortname.lower())
pout.write(u"pkgver = %s\n" % pkgver)
pout.write(u"pkgdesc = %s\n" % self.fullname)
pout.write(u"builddate = %s\n" % modtime)
pout.write(u"packager = %s <%s>\n" % (self.authorname, self.authoremail))
pout.write(u"size = %d\n" % totsize)
pout.write(u"arch = %s\n" % arch)
if self.licensename != "":
print >>pkginfo, "license = %s" % self.licensename
pout.write(u"license = %s\n" % self.licensename)
pout.flush()
pkginfoinfo = TarInfoRoot(".PKGINFO")
pkginfoinfo.mtime = modtime
pkginfoinfo.size = pkginfo.tell()

View File

@ -513,18 +513,15 @@ class HostInfo:
PackageInfo, returns it. """
if not platform:
# Ensure that we're on the same page with non-specified
# platforms. We have to use the empty string, not None,
# since Python 3 can't sort lists with both strings and None.
platform = ""
platform = None
platforms = self.packages.setdefault((name, version), {})
package = platforms.get(platform, None)
platforms = self.packages.setdefault((name, version or ""), {})
package = platforms.get("", None)
if not package:
package = PackageInfo(self, name, version, platform = platform,
solo = solo, asMirror = self.asMirror,
perPlatform = perPlatform)
platforms[platform] = package
platforms[platform or ""] = package
return package
@ -534,12 +531,12 @@ class HostInfo:
platform, if one is provided by this host, or None if not. """
assert self.hasContentsFile
platforms = self.packages.get((name, version or None), {})
platforms = self.packages.get((name, version or ""), {})
if platform is not None:
if platform:
# In this case, we are looking for a specific platform
# only.
return platforms.get(platform or None, None)
return platforms.get(platform, None)
# We are looking for one matching the current runtime
# platform. First, look for a package matching the current
@ -548,7 +545,7 @@ class HostInfo:
# If not found, look for one matching no particular platform.
if not package:
package = platforms.get(None, None)
package = platforms.get("", None)
return package
@ -564,7 +561,7 @@ class HostInfo:
if name and pn != name:
continue
if platform is None:
if not platform:
for p2 in platforms:
package = self.getPackage(pn, version, platform = p2)
if package:
@ -596,7 +593,7 @@ class HostInfo:
# current platform, or no particular platform.
package = platforms.get(PandaSystem.getPlatform(), None)
if not package:
package = platforms.get(None, None)
package = platforms.get("", None)
if package:
result.append(package)

View File

@ -523,7 +523,8 @@ class PackageInfo:
# In case of unexpected failures on the internet, we will retry
# the full download instead of just giving up.
for retry in range(core.ConfigVariableInt('package-full-dl-retries', 1)):
retries = core.ConfigVariableInt('package-full-dl-retries', 1).getValue()
for retry in range(retries):
self.installPlans.append(planB[:])
pc.stop()

View File

@ -15,6 +15,7 @@ import sys
import os
import io
import encodings
from posixpath import join
_vfs = core.VirtualFileSystem.getGlobalPtr()
@ -331,20 +332,6 @@ def walk(top, topdown = True, onerror = None, followlinks = True):
if not topdown:
yield (top, dirnames, filenames)
def join(path, *args):
for part in args:
if part == '':
continue
if part.startswith('/'):
path = part
elif path.endswith('/'):
path = path + part
else:
path = '/'.join((path, part))
return path
def isfile(path):
return _vfs.isRegularFile(core.Filename.fromOsSpecific(path))