Esempio n. 1
0
    def __init__(self, pathname, ignoreUsageXml=False):
        self.pathname = pathname
        self.filenames = []
        self.fileSize = 0
        self.nested = []
        self.nestedSize = 0

        xusage = None
        if not ignoreUsageXml:
            # Look for a usage.xml file in this directory.  If we find
            # one, we read it for the file size and then stop here, as
            # an optimization.
            usageFilename = Filename(pathname, 'usage.xml')
            doc = TiXmlDocument(usageFilename.toOsSpecific())
            if doc.LoadFile():
                xusage = doc.FirstChildElement('usage')
                if xusage:
                    diskSpace = xusage.Attribute('disk_space')
                    try:
                        diskSpace = int(diskSpace or '')
                    except ValueError:
                        diskSpace = None
                    if diskSpace is not None:
                        self.fileSize = diskSpace
                        return

        files = vfs.scanDirectory(self.pathname)
        if files is None:
            files = []
        for vfile in files:
            if hasattr(vfile, 'getMount'):
                if not isinstance(vfile.getMount(), VirtualFileMountSystem):
                    # Not a real file; ignore it.
                    continue

            if vfile.isDirectory():
                # A nested directory.
                subdir = ScanDirectoryNode(vfile.getFilename(),
                                           ignoreUsageXml=ignoreUsageXml)
                self.nested.append(subdir)
                self.nestedSize += subdir.getTotalSize()

            elif vfile.isRegularFile():
                # A nested file.
                self.filenames.append(vfile.getFilename())
                self.fileSize += vfile.getFileSize()

            else:
                # Some other wacky file thing.
                self.filenames.append(vfile.getFilename())

        if xusage:
            # Now update the usage.xml file with the newly-determined
            # disk space.
            xusage.SetAttribute('disk_space', str(self.getTotalSize()))
            tfile = Filename.temporary(pathname.cStr(), '.xml')
            if doc.SaveFile(tfile.toOsSpecific()):
                tfile.renameTo(usageFilename)
Esempio n. 2
0
    def getUsage(self):
        """ Returns the xusage element that is read from the usage.xml
        file, or None if there is no usage.xml file. """

        if not hasattr(PandaModules, 'TiXmlDocument'):
            return None

        filename = Filename(self.getPackageDir(), self.UsageBasename)
        doc = TiXmlDocument(filename.toOsSpecific())
        if not doc.LoadFile():
            return None

        xusage = doc.FirstChildElement('usage')
        if not xusage:
            return None

        return copy.copy(xusage)
Esempio n. 3
0
    def readConfigXml(self):
        """ Reads the config.xml file that may be present in the root
        directory. """

        if not hasattr(PandaModules, 'TiXmlDocument'):
            return
        from pandac.PandaModules import TiXmlDocument

        filename = Filename(self.rootDir, self.ConfigBasename)
        doc = TiXmlDocument(filename.toOsSpecific())
        if not doc.LoadFile():
            return

        xconfig = doc.FirstChildElement('config')
        if xconfig:
            maxDiskUsage = xconfig.Attribute('max_disk_usage')
            try:
                self.maxDiskUsage = int(maxDiskUsage or '')
            except ValueError:
                pass
Esempio n. 4
0
    def writeConfigXml(self):
        """ Rewrites the config.xml to the root directory.  This isn't
        called automatically; an application may call this after
        adjusting some parameters (such as self.maxDiskUsage). """

        from pandac.PandaModules import TiXmlDocument, TiXmlDeclaration, TiXmlElement

        filename = Filename(self.rootDir, self.ConfigBasename)
        doc = TiXmlDocument(filename.toOsSpecific())
        decl = TiXmlDeclaration("1.0", "utf-8", "")
        doc.InsertEndChild(decl)

        xconfig = TiXmlElement('config')
        xconfig.SetAttribute('max_disk_usage', str(self.maxDiskUsage))
        doc.InsertEndChild(xconfig)

        # Write the file to a temporary filename, then atomically move
        # it to its actual filename, to avoid race conditions when
        # updating this file.
        tfile = Filename.temporary(self.rootDir.cStr(), '.xml')
        if doc.SaveFile(tfile.toOsSpecific()):
            tfile.renameTo(filename)
Esempio n. 5
0
    def markUsed(self):
        """ Marks the package as having been used.  This is normally
        called automatically by installPackage(). """

        if not hasattr(PandaModules, 'TiXmlDocument'):
            return

        if self.host.appRunner and self.host.appRunner.verifyContents == self.host.appRunner.P3DVCNever:
            # Not allowed to write any files to the package directory.
            return

        if self.updated:
            # If we've just installed a new version of the package,
            # re-measure the actual disk space used.
            self.diskSpace = self.__measureDiskSpace()

        filename = Filename(self.getPackageDir(), self.UsageBasename)
        doc = TiXmlDocument(filename.toOsSpecific())
        if not doc.LoadFile():
            decl = TiXmlDeclaration("1.0", "utf-8", "")
            doc.InsertEndChild(decl)

        xusage = doc.FirstChildElement('usage')
        if not xusage:
            doc.InsertEndChild(TiXmlElement('usage'))
            xusage = doc.FirstChildElement('usage')

        now = int(time.time())

        count = xusage.Attribute('count_app')
        try:
            count = int(count or '')
        except ValueError:
            count = 0
            xusage.SetAttribute('first_use', str(now))
        count += 1
        xusage.SetAttribute('count_app', str(count))

        xusage.SetAttribute('last_use', str(now))

        if self.updated:
            xusage.SetAttribute('last_update', str(now))
            self.updated = False
        else:
            # Since we haven't changed the disk space, we can just
            # read it from the previous xml file.
            diskSpace = xusage.Attribute('disk_space')
            try:
                diskSpace = int(diskSpace or '')
            except ValueError:
                # Unless it wasn't set already.
                self.diskSpace = self.__measureDiskSpace()

        xusage.SetAttribute('disk_space', str(self.diskSpace))

        # Write the file to a temporary filename, then atomically move
        # it to its actual filename, to avoid race conditions when
        # updating this file.
        tfile = Filename.temporary(self.getPackageDir().cStr(), '.xml')
        if doc.SaveFile(tfile.toOsSpecific()):
            tfile.renameTo(filename)
    def installPackagesInto(self, hostDir, platform):
        """ Installs the packages required by the .p3d file into
        the specified directory, for the given platform. """

        if not self.includeRequires:
            return

        pkgTree = PackageTree(platform, hostDir, self.hostUrl)
        pkgTree.installPackage("images", None, self.standalone.host.hostUrl)

        for name, version, hostUrl in self.requires:
            pkgTree.installPackage(name, version, hostUrl)

        # Remove the extracted files from the compressed archive, to save space.
        vfs = VirtualFileSystem.getGlobalPtr()
        for package in pkgTree.packages.values():
            if package.uncompressedArchive:
                archive = Filename(package.getPackageDir(),
                                   package.uncompressedArchive.filename)
                if not archive.exists():
                    continue

                mf = Multifile()
                # Make sure that it isn't mounted before altering it, just to be safe
                vfs.unmount(archive)
                os.chmod(archive.toOsSpecific(), 0644)
                if not mf.openReadWrite(archive):
                    Installer.notify.warning("Failed to open archive %s" %
                                             (archive))
                    continue

                # We don't iterate over getNumSubfiles because we're
                # removing subfiles while we're iterating over them.
                subfiles = mf.getSubfileNames()
                for subfile in subfiles:
                    # We do *NOT* call vfs.exists here in case the package is mounted.
                    if Filename(package.getPackageDir(), subfile).exists():
                        Installer.notify.debug(
                            "Removing already-extracted %s from multifile" %
                            (subfile))
                        mf.removeSubfile(subfile)

                # This seems essential for mf.close() not to crash later.
                mf.repack()

                # If we have no subfiles left, we can just remove the multifile.
                #if mf.getNumSubfiles() == 0:
                #    Installer.notify.info("Removing empty archive %s" % (package.uncompressedArchive.filename))
                #    mf.close()
                #    archive.unlink()
                #else:
                mf.close()
                try:
                    os.chmod(archive.toOsSpecific(), 0444)
                except:
                    pass

        # Write out our own contents.xml file.
        doc = TiXmlDocument()
        decl = TiXmlDeclaration("1.0", "utf-8", "")
        doc.InsertEndChild(decl)

        xcontents = TiXmlElement("contents")
        for package in pkgTree.packages.values():
            xpackage = TiXmlElement('package')
            xpackage.SetAttribute('name', package.packageName)
            if package.platform:
                xpackage.SetAttribute('platform', package.platform)
                assert package.platform == platform
            if package.packageVersion:
                xpackage.SetAttribute('version', version)
                xpackage.SetAttribute(
                    'filename', package.packageName + "/" +
                    package.packageVersion + "/" + package.descFileBasename)
            else:
                xpackage.SetAttribute(
                    'filename',
                    package.packageName + "/" + package.descFileBasename)
            xcontents.InsertEndChild(xpackage)

        doc.InsertEndChild(xcontents)
        doc.SaveFile(Filename(hostDir, "contents.xml").toOsSpecific())