def buildAPP(self, output, platform):

        output = Filename(output)
        if output.isDirectory() and output.getExtension() != "app":
            output = Filename(output, "%s.app" % self.fullname)
        Installer.notify.info("Creating %s..." % output)

        # Create the executable for the application bundle
        exefile = Filename(output, "Contents/MacOS/" + self.shortname)
        exefile.makeDir()
        if self.includeRequires:
            extraTokens = {"host_dir": "../Resources"}
        else:
            extraTokens = {}
        self.standalone.build(exefile, platform, extraTokens)
        hostDir = Filename(output, "Contents/Resources/")
        hostDir.makeDir()
        self.installPackagesInto(hostDir, platform)

        # Create the application plist file.
        # Although it might make more sense to use Python's plistlib module here,
        # it is not available on non-OSX systems before Python 2.6.
        plist = open(Filename(output, "Contents/Info.plist").toOsSpecific(), "w")
        print >> plist, '<?xml version="1.0" encoding="UTF-8"?>'
        print >> plist, '<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">'
        print >> plist, '<plist version="1.0">'
        print >> plist, "<dict>"
        print >> plist, "\t<key>CFBundleDevelopmentRegion</key>"
        print >> plist, "\t<string>English</string>"
        print >> plist, "\t<key>CFBundleDisplayName</key>"
        print >> plist, "\t<string>%s</string>" % self.fullname
        print >> plist, "\t<key>CFBundleExecutable</key>"
        print >> plist, "\t<string>%s</string>" % exefile.getBasename()
        print >> plist, "\t<key>CFBundleIdentifier</key>"
        print >> plist, "\t<string>%s.%s</string>" % (self.authorid, self.shortname)
        print >> plist, "\t<key>CFBundleInfoDictionaryVersion</key>"
        print >> plist, "\t<string>6.0</string>"
        print >> plist, "\t<key>CFBundleName</key>"
        print >> plist, "\t<string>%s</string>" % self.shortname
        print >> plist, "\t<key>CFBundlePackageType</key>"
        print >> plist, "\t<string>APPL</string>"
        print >> plist, "\t<key>CFBundleShortVersionString</key>"
        print >> plist, "\t<string>%s</string>" % self.version
        print >> plist, "\t<key>CFBundleVersion</key>"
        print >> plist, "\t<string>%s</string>" % self.version
        print >> plist, "\t<key>LSHasLocalizedDisplayName</key>"
        print >> plist, "\t<false/>"
        print >> plist, "\t<key>NSAppleScriptEnabled</key>"
        print >> plist, "\t<false/>"
        print >> plist, "\t<key>NSPrincipalClass</key>"
        print >> plist, "\t<string>NSApplication</string>"
        print >> plist, "</dict>"
        print >> plist, "</plist>"
        plist.close()

        return output
    def buildArch(self, output, platform):
        """ Builds an ArchLinux package and stores it in the path
        indicated by the 'output' argument. It will be built for the
        architecture specified by the 'arch' argument.
        If 'output' is a directory, the deb file will be stored in it. """

        arch = platform.rsplit("_", 1)[-1]
        assert arch in ("i386", "amd64")
        arch = {"i386": "i686", "amd64": "x86_64"}[arch]
        pkgver = self.version + "-1"

        output = Filename(output)
        if output.isDirectory():
            output = Filename(output, "%s-%s-%s.pkg.tar.gz" % (self.shortname.lower(), pkgver, arch))
        Installer.notify.info("Creating %s..." % output)
        modtime = int(time.time())

        # Create a temporary directory and write the launcher and dependencies to it.
        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
        if self.licensename != "":
            print >> pkginfo, "license = %s" % self.licensename
        pkginfoinfo = TarInfoRoot(".PKGINFO")
        pkginfoinfo.mtime = modtime
        pkginfoinfo.size = pkginfo.tell()
        pkginfo.seek(0)

        # Create the actual package now.
        pkgfile = tarfile.open(output.toOsSpecific(), "w:gz", tarinfo=TarInfoRoot)
        pkgfile.addfile(pkginfoinfo, pkginfo)
        pkgfile.add(tempdir.toOsSpecific(), "/")
        if not self.licensefile.empty():
            pkgfile.add(self.licensefile.toOsSpecific(), "/usr/share/licenses/%s/LICENSE" % self.shortname.lower())
        pkgfile.close()

        return output
Exemplo n.º 3
0
    shortname = appFilename.getBasenameWoExtension()

if shortname.lower() != shortname or " " in shortname:
    print "\nProvided short name should be lowercase, and may not contain spaces!\n"

if version == "" and deploy_mode == "installer":
    print '\nA version number is required in "installer" mode.\n'
    sys.exit(1)

if not outputDir:
    print "\nYou must name the output directory with the -o parameter.\n"
    sys.exit(1)
if not outputDir.exists():
    print "\nThe specified output directory does not exist!\n"
    sys.exit(1)
elif not outputDir.isDirectory():
    print "\nThe specified output directory is a file!\n"
    sys.exit(1)

if deploy_mode == "standalone":
    s = Standalone(appFilename, tokens)
    s.basename = shortname

    if currentPlatform:
        platform = PandaSystem.getPlatform()
        if platform.startswith("win"):
            s.build(Filename(outputDir, shortname + ".exe"), platform)
        else:
            s.build(Filename(outputDir, shortname), platform)
    elif len(platforms) == 0:
        s.buildAll(outputDir)
    def buildNSIS(self, output, platform):
        # Check if we have makensis first
        makensis = None
        if sys.platform.startswith("win"):
            syspath = os.defpath.split(";") + os.environ["PATH"].split(";")
            for p in set(syspath):
                p1 = os.path.join(p, "makensis.exe")
                p2 = os.path.join(os.path.dirname(p), "nsis", "makensis.exe")
                if os.path.isfile(p1):
                    makensis = p1
                    break
                elif os.path.isfile(p2):
                    makensis = p2
                    break
            if not makensis:
                import pandac

                makensis = os.path.dirname(os.path.dirname(pandac.__file__))
                makensis = os.path.join(makensis, "nsis", "makensis.exe")
                if not os.path.isfile(makensis):
                    makensis = None
        else:
            for p in os.defpath.split(":") + os.environ["PATH"].split(":"):
                if os.path.isfile(os.path.join(p, "makensis")):
                    makensis = os.path.join(p, "makensis")

        if makensis == None:
            Installer.notify.warning("Makensis utility not found, no Windows installer will be built!")
            return None

        output = Filename(output)
        if output.isDirectory():
            output = Filename(output, "%s %s.exe" % (self.fullname, self.version))
        Installer.notify.info("Creating %s..." % output)
        output.makeAbsolute()
        extrafiles = self.standalone.getExtraFiles(platform)

        exefile = Filename(Filename.getTempDirectory(), self.shortname + ".exe")
        exefile.unlink()
        if self.includeRequires:
            extraTokens = {"host_dir": "."}
        else:
            extraTokens = {}
        self.standalone.build(exefile, platform, extraTokens)

        # Temporary directory to store the hostdir in
        hostDir = Filename(self.tempDir, platform + "/")
        if not hostDir.exists():
            hostDir.makeDir()
            self.installPackagesInto(hostDir, platform)

        nsifile = Filename(Filename.getTempDirectory(), self.shortname + ".nsi")
        nsifile.unlink()
        nsi = open(nsifile.toOsSpecific(), "w")

        # Some global info
        nsi.write('Name "%s"\n' % self.fullname)
        nsi.write('OutFile "%s"\n' % output.toOsSpecific())
        nsi.write('InstallDir "$PROGRAMFILES\\%s"\n' % self.fullname)
        nsi.write("SetCompress auto\n")
        nsi.write("SetCompressor lzma\n")
        nsi.write("ShowInstDetails nevershow\n")
        nsi.write("ShowUninstDetails nevershow\n")
        nsi.write('InstType "Typical"\n')

        # Tell Vista that we require admin rights
        nsi.write("RequestExecutionLevel admin\n")
        nsi.write("\n")
        nsi.write("Function launch\n")
        nsi.write('  ExecShell "open" "$INSTDIR\\%s.exe"\n' % self.shortname)
        nsi.write("FunctionEnd\n")
        nsi.write("\n")
        nsi.write('!include "MUI2.nsh"\n')
        nsi.write("!define MUI_ABORTWARNING\n")
        nsi.write("!define MUI_FINISHPAGE_RUN\n")
        nsi.write("!define MUI_FINISHPAGE_RUN_FUNCTION launch\n")
        nsi.write('!define MUI_FINISHPAGE_RUN_TEXT "Run %s"\n' % self.fullname)
        nsi.write("\n")
        nsi.write("Var StartMenuFolder\n")
        nsi.write("!insertmacro MUI_PAGE_WELCOME\n")
        if not self.licensefile.empty():
            abs = Filename(self.licensefile)
            abs.makeAbsolute()
            nsi.write('!insertmacro MUI_PAGE_LICENSE "%s"\n' % abs.toOsSpecific())
        nsi.write("!insertmacro MUI_PAGE_DIRECTORY\n")
        nsi.write("!insertmacro MUI_PAGE_STARTMENU Application $StartMenuFolder\n")
        nsi.write("!insertmacro MUI_PAGE_INSTFILES\n")
        nsi.write("!insertmacro MUI_PAGE_FINISH\n")
        nsi.write("!insertmacro MUI_UNPAGE_WELCOME\n")
        nsi.write("!insertmacro MUI_UNPAGE_CONFIRM\n")
        nsi.write("!insertmacro MUI_UNPAGE_INSTFILES\n")
        nsi.write("!insertmacro MUI_UNPAGE_FINISH\n")
        nsi.write('!insertmacro MUI_LANGUAGE "English"\n')

        # This section defines the installer.
        nsi.write('Section "" SecCore\n')
        nsi.write('  SetOutPath "$INSTDIR"\n')
        nsi.write('  File "%s"\n' % exefile.toOsSpecific())
        for f in extrafiles:
            nsi.write('  File "%s"\n' % f.toOsSpecific())
        curdir = ""
        for root, dirs, files in self.os_walk(hostDir.toOsSpecific()):
            for name in files:
                file = Filename.fromOsSpecific(os.path.join(root, name))
                file.makeAbsolute()
                file.makeRelativeTo(hostDir)
                outdir = file.getDirname().replace("/", "\\")
                if curdir != outdir:
                    nsi.write('  SetOutPath "$INSTDIR\\%s"\n' % outdir)
                    curdir = outdir
                nsi.write('  File "%s"\n' % os.path.join(root, name))
        nsi.write('  WriteUninstaller "$INSTDIR\\Uninstall.exe"\n')
        nsi.write("  ; Start menu items\n")
        nsi.write("  !insertmacro MUI_STARTMENU_WRITE_BEGIN Application\n")
        nsi.write('    CreateDirectory "$SMPROGRAMS\\$StartMenuFolder"\n')
        nsi.write(
            '    CreateShortCut "$SMPROGRAMS\\$StartMenuFolder\\%s.lnk" "$INSTDIR\\%s.exe"\n'
            % (self.fullname, self.shortname)
        )
        nsi.write('    CreateShortCut "$SMPROGRAMS\\$StartMenuFolder\\Uninstall.lnk" "$INSTDIR\\Uninstall.exe"\n')
        nsi.write("  !insertmacro MUI_STARTMENU_WRITE_END\n")
        nsi.write("SectionEnd\n")

        # This section defines the uninstaller.
        nsi.write("Section Uninstall\n")
        nsi.write('  Delete "$INSTDIR\\%s.exe"\n' % self.shortname)
        for f in extrafiles:
            nsi.write('  Delete "%s"\n' % f.getBasename())
        nsi.write('  Delete "$INSTDIR\\Uninstall.exe"\n')
        nsi.write('  RMDir /r "$INSTDIR"\n')
        nsi.write("  ; Start menu items\n")
        nsi.write("  !insertmacro MUI_STARTMENU_GETFOLDER Application $StartMenuFolder\n")
        nsi.write('  Delete "$SMPROGRAMS\\$StartMenuFolder\\Uninstall.lnk"\n')
        nsi.write('  RMDir "$SMPROGRAMS\\$StartMenuFolder"\n')
        nsi.write("SectionEnd")
        nsi.close()

        cmd = [makensis]
        for o in ["V2"]:
            if sys.platform.startswith("win"):
                cmd.append("/" + o)
            else:
                cmd.append("-" + o)
        cmd.append(nsifile.toOsSpecific())
        print cmd
        try:
            retcode = subprocess.call(cmd, shell=False)
            if retcode != 0:
                self.notify.warning("Failure invoking NSIS command.")
        except OSError:
            self.notify.warning("Unable to invoke NSIS command.")

        nsifile.unlink()
        return output
    def buildPKG(self, output, platform):
        appfn = self.buildAPP(output, platform)
        appname = "/Applications/" + appfn.getBasename()
        output = Filename(output)
        if output.isDirectory():
            output = Filename(output, "%s %s.pkg" % (self.fullname, self.version))
        Installer.notify.info("Creating %s..." % output)

        Filename(output, "Contents/Resources/en.lproj/").makeDir()
        if self.licensefile:
            shutil.copyfile(
                self.licensefile.toOsSpecific(), Filename(output, "Contents/Resources/License.txt").toOsSpecific()
            )
        pkginfo = open(Filename(output, "Contents/PkgInfo").toOsSpecific(), "w")
        pkginfo.write("pkmkrpkg1")
        pkginfo.close()
        pkginfo = open(Filename(output, "Contents/Resources/package_version").toOsSpecific(), "w")
        pkginfo.write("major: 1\nminor: 9")
        pkginfo.close()

        # Although it might make more sense to use Python's plistlib here,
        # it is not available on non-OSX systems before Python 2.6.
        plist = open(Filename(output, "Contents/Info.plist").toOsSpecific(), "w")
        plist.write('<?xml version="1.0" encoding="UTF-8"?>\n')
        plist.write(
            '<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n'
        )
        plist.write('<plist version="1.0">\n')
        plist.write("<dict>\n")
        plist.write("\t<key>CFBundleIdentifier</key>\n")
        plist.write("\t<string>%s.pkg.%s</string>\n" % (self.authorid, self.shortname))
        plist.write("\t<key>CFBundleShortVersionString</key>\n")
        plist.write("\t<string>%s</string>\n" % self.version)
        plist.write("\t<key>IFMajorVersion</key>\n")
        plist.write("\t<integer>1</integer>\n")
        plist.write("\t<key>IFMinorVersion</key>\n")
        plist.write("\t<integer>9</integer>\n")
        plist.write("\t<key>IFPkgFlagAllowBackRev</key>\n")
        plist.write("\t<false/>\n")
        plist.write("\t<key>IFPkgFlagAuthorizationAction</key>\n")
        plist.write("\t<string>RootAuthorization</string>\n")
        plist.write("\t<key>IFPkgFlagDefaultLocation</key>\n")
        plist.write("\t<string>/</string>\n")
        plist.write("\t<key>IFPkgFlagFollowLinks</key>\n")
        plist.write("\t<true/>\n")
        plist.write("\t<key>IFPkgFlagIsRequired</key>\n")
        plist.write("\t<false/>\n")
        plist.write("\t<key>IFPkgFlagOverwritePermissions</key>\n")
        plist.write("\t<false/>\n")
        plist.write("\t<key>IFPkgFlagRelocatable</key>\n")
        plist.write("\t<false/>\n")
        plist.write("\t<key>IFPkgFlagRestartAction</key>\n")
        plist.write("\t<string>None</string>\n")
        plist.write("\t<key>IFPkgFlagRootVolumeOnly</key>\n")
        plist.write("\t<true/>\n")
        plist.write("\t<key>IFPkgFlagUpdateInstalledLanguages</key>\n")
        plist.write("\t<false/>\n")
        plist.write("\t<key>IFPkgFormatVersion</key>\n")
        plist.write("\t<real>0.10000000149011612</real>\n")
        plist.write("\t<key>IFPkgPathMappings</key>\n")
        plist.write("\t<dict>\n")
        plist.write("\t\t<key>%s</key>\n" % appname)
        plist.write("\t\t<string>{pkmk-token-2}</string>\n")
        plist.write("\t</dict>\n")
        plist.write("</dict>\n")
        plist.write("</plist>\n")
        plist.close()

        plist = open(Filename(output, "Contents/Resources/TokenDefinitions.plist").toOsSpecific(), "w")
        plist.write('<?xml version="1.0" encoding="UTF-8"?>\n')
        plist.write(
            '<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n'
        )
        plist.write('<plist version="1.0">\n')
        plist.write("<dict>\n")
        plist.write("\t<key>pkmk-token-2</key>\n")
        plist.write("\t<array>\n")
        plist.write("\t\t<dict>\n")
        plist.write("\t\t\t<key>identifier</key>\n")
        plist.write("\t\t\t<string>%s.%s</string>\n" % (self.authorid, self.shortname))
        plist.write("\t\t\t<key>path</key>\n")
        plist.write("\t\t\t<string>%s</string>\n" % appname)
        plist.write("\t\t\t<key>searchPlugin</key>\n")
        plist.write("\t\t\t<string>CommonAppSearch</string>\n")
        plist.write("\t\t</dict>\n")
        plist.write("\t</array>\n")
        plist.write("</dict>\n")
        plist.write("</plist>\n")
        plist.close()

        plist = open(Filename(output, "Contents/Resources/en.lproj/Description.plist").toOsSpecific(), "w")
        plist.write('<?xml version="1.0" encoding="UTF-8"?>\n')
        plist.write(
            '<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n'
        )
        plist.write('<plist version="1.0">\n')
        plist.write("<dict>\n")
        plist.write("\t<key>IFPkgDescriptionDescription</key>\n")
        plist.write("\t<string></string>\n")
        plist.write("\t<key>IFPkgDescriptionTitle</key>\n")
        plist.write("\t<string>%s</string>\n" % self.fullname)
        plist.write("</dict>\n")
        plist.write("</plist>\n")
        plist.close()

        if hasattr(tarfile, "PAX_FORMAT"):
            archive = tarfile.open(
                Filename(output, "Contents/Archive.pax.gz").toOsSpecific(),
                "w:gz",
                format=tarfile.PAX_FORMAT,
                tarinfo=TarInfoRootOSX,
            )
        else:
            archive = tarfile.open(
                Filename(output, "Contents/Archive.pax.gz").toOsSpecific(), "w:gz", tarinfo=TarInfoRootOSX
            )
        archive.add(appfn.toOsSpecific(), appname)
        archive.close()

        # Put the .pkg into a zipfile
        archive = Filename(output.getDirname(), "%s %s.zip" % (self.fullname, self.version))
        dir = Filename(output.getDirname())
        dir.makeAbsolute()
        zip = zipfile.ZipFile(archive.toOsSpecific(), "w")
        for root, dirs, files in self.os_walk(output.toOsSpecific()):
            for name in files:
                file = Filename.fromOsSpecific(os.path.join(root, name))
                file.makeAbsolute()
                file.makeRelativeTo(dir)
                zip.write(os.path.join(root, name), str(file))
        zip.close()

        return output
    def buildDEB(self, output, platform):
        """ Builds a .deb archive and stores it in the path indicated
        by the 'output' argument. It will be built for the architecture
        specified by the 'arch' argument.
        If 'output' is a directory, the deb file will be stored in it. """

        arch = platform.rsplit("_", 1)[-1]
        output = Filename(output)
        if output.isDirectory():
            output = Filename(output, "%s_%s_%s.deb" % (self.shortname.lower(), self.version, arch))
        Installer.notify.info("Creating %s..." % output)
        modtime = int(time.time())

        # Create a temporary directory and write the launcher and dependencies to it.
        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"
        controlinfo = TarInfoRoot("control")
        controlinfo.mtime = modtime
        controlinfo.size = controlfile.tell()
        controlfile.seek(0)

        # Open the deb file and write to it. It's actually
        # just an AR file, which is very easy to make.
        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")

        # Write the control.tar.gz to the archive.
        debfile.write("control.tar.gz  %-12lu0     0     100644  %-10ld\x60\x0A" % (modtime, 0))
        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")

        # Write the data.tar.gz to the archive.
        debfile.write("data.tar.gz     %-12lu0     0     100644  %-10ld\x60\x0A" % (modtime, 0))
        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")

        # Write the correct sizes of the archives.
        debfile.seek(ctaroffs - 12)
        debfile.write("%-10ld" % ctarsize)
        debfile.seek(dtaroffs - 12)
        debfile.write("%-10ld" % dtarsize)

        debfile.close()

        return output
Exemplo n.º 7
0
    shortname = appFilename.getBasenameWoExtension()

if shortname.lower() != shortname or ' ' in shortname:
    print '\nProvided short name should be lowercase, and may not contain spaces!\n'

if version == '' and deploy_mode == 'installer':
    print '\nA version number is required in "installer" mode.\n'
    sys.exit(1)

if not outputDir:
    print '\nYou must name the output directory with the -o parameter.\n'
    sys.exit(1)
if not outputDir.exists():
    print '\nThe specified output directory does not exist!\n'
    sys.exit(1)
elif not outputDir.isDirectory():
    print '\nThe specified output directory is a file!\n'
    sys.exit(1)

if deploy_mode == 'standalone':
    s = Standalone(appFilename, tokens)
    s.basename = shortname

    if currentPlatform:
        platform = PandaSystem.getPlatform()
        if platform.startswith("win"):
            s.build(Filename(outputDir, shortname + ".exe"), platform)
        else:
            s.build(Filename(outputDir, shortname), platform)
    elif len(platforms) == 0:
        s.buildAll(outputDir)
    def buildNSIS(self, output, platform):
        # Check if we have makensis first
        makensis = None
        if (sys.platform.startswith("win")):
            syspath = os.defpath.split(";") + os.environ["PATH"].split(";")
            for p in set(syspath):
                p1 = os.path.join(p, "makensis.exe")
                p2 = os.path.join(os.path.dirname(p), "nsis", "makensis.exe")
                if os.path.isfile(p1):
                    makensis = p1
                    break
                elif os.path.isfile(p2):
                    makensis = p2
                    break
            if not makensis:
                import pandac
                makensis = os.path.dirname(os.path.dirname(pandac.__file__))
                makensis = os.path.join(makensis, "nsis", "makensis.exe")
                if not os.path.isfile(makensis): makensis = None
        else:
            for p in os.defpath.split(":") + os.environ["PATH"].split(":"):
                if os.path.isfile(os.path.join(p, "makensis")):
                    makensis = os.path.join(p, "makensis")

        if makensis == None:
            Installer.notify.warning(
                "Makensis utility not found, no Windows installer will be built!"
            )
            return None

        output = Filename(output)
        if output.isDirectory():
            output = Filename(output,
                              "%s %s.exe" % (self.fullname, self.version))
        Installer.notify.info("Creating %s..." % output)
        output.makeAbsolute()
        extrafiles = self.standalone.getExtraFiles(platform)

        exefile = Filename(Filename.getTempDirectory(),
                           self.shortname + ".exe")
        exefile.unlink()
        if self.includeRequires:
            extraTokens = {"host_dir": "."}
        else:
            extraTokens = {}
        self.standalone.build(exefile, platform, extraTokens)

        # Temporary directory to store the hostdir in
        hostDir = Filename(self.tempDir, platform + "/")
        if not hostDir.exists():
            hostDir.makeDir()
            self.installPackagesInto(hostDir, platform)

        nsifile = Filename(Filename.getTempDirectory(),
                           self.shortname + ".nsi")
        nsifile.unlink()
        nsi = open(nsifile.toOsSpecific(), "w")

        # Some global info
        nsi.write('Name "%s"\n' % self.fullname)
        nsi.write('OutFile "%s"\n' % output.toOsSpecific())
        nsi.write('InstallDir "$PROGRAMFILES\\%s"\n' % self.fullname)
        nsi.write('SetCompress auto\n')
        nsi.write('SetCompressor lzma\n')
        nsi.write('ShowInstDetails nevershow\n')
        nsi.write('ShowUninstDetails nevershow\n')
        nsi.write('InstType "Typical"\n')

        # Tell Vista that we require admin rights
        nsi.write('RequestExecutionLevel admin\n')
        nsi.write('\n')
        nsi.write('Function launch\n')
        nsi.write('  ExecShell "open" "$INSTDIR\\%s.exe"\n' % self.shortname)
        nsi.write('FunctionEnd\n')
        nsi.write('\n')
        nsi.write('!include "MUI2.nsh"\n')
        nsi.write('!define MUI_ABORTWARNING\n')
        nsi.write('!define MUI_FINISHPAGE_RUN\n')
        nsi.write('!define MUI_FINISHPAGE_RUN_FUNCTION launch\n')
        nsi.write('!define MUI_FINISHPAGE_RUN_TEXT "Run %s"\n' % self.fullname)
        nsi.write('\n')
        nsi.write('Var StartMenuFolder\n')
        nsi.write('!insertmacro MUI_PAGE_WELCOME\n')
        if not self.licensefile.empty():
            abs = Filename(self.licensefile)
            abs.makeAbsolute()
            nsi.write('!insertmacro MUI_PAGE_LICENSE "%s"\n' %
                      abs.toOsSpecific())
        nsi.write('!insertmacro MUI_PAGE_DIRECTORY\n')
        nsi.write(
            '!insertmacro MUI_PAGE_STARTMENU Application $StartMenuFolder\n')
        nsi.write('!insertmacro MUI_PAGE_INSTFILES\n')
        nsi.write('!insertmacro MUI_PAGE_FINISH\n')
        nsi.write('!insertmacro MUI_UNPAGE_WELCOME\n')
        nsi.write('!insertmacro MUI_UNPAGE_CONFIRM\n')
        nsi.write('!insertmacro MUI_UNPAGE_INSTFILES\n')
        nsi.write('!insertmacro MUI_UNPAGE_FINISH\n')
        nsi.write('!insertmacro MUI_LANGUAGE "English"\n')

        # This section defines the installer.
        nsi.write('Section "" SecCore\n')
        nsi.write('  SetOutPath "$INSTDIR"\n')
        nsi.write('  File "%s"\n' % exefile.toOsSpecific())
        for f in extrafiles:
            nsi.write('  File "%s"\n' % f.toOsSpecific())
        curdir = ""
        for root, dirs, files in self.os_walk(hostDir.toOsSpecific()):
            for name in files:
                file = Filename.fromOsSpecific(os.path.join(root, name))
                file.makeAbsolute()
                file.makeRelativeTo(hostDir)
                outdir = file.getDirname().replace('/', '\\')
                if curdir != outdir:
                    nsi.write('  SetOutPath "$INSTDIR\\%s"\n' % outdir)
                    curdir = outdir
                nsi.write('  File "%s"\n' % os.path.join(root, name))
        nsi.write('  WriteUninstaller "$INSTDIR\\Uninstall.exe"\n')
        nsi.write('  ; Start menu items\n')
        nsi.write('  !insertmacro MUI_STARTMENU_WRITE_BEGIN Application\n')
        nsi.write('    CreateDirectory "$SMPROGRAMS\\$StartMenuFolder"\n')
        nsi.write(
            '    CreateShortCut "$SMPROGRAMS\\$StartMenuFolder\\%s.lnk" "$INSTDIR\\%s.exe"\n'
            % (self.fullname, self.shortname))
        nsi.write(
            '    CreateShortCut "$SMPROGRAMS\\$StartMenuFolder\\Uninstall.lnk" "$INSTDIR\\Uninstall.exe"\n'
        )
        nsi.write('  !insertmacro MUI_STARTMENU_WRITE_END\n')
        nsi.write('SectionEnd\n')

        # This section defines the uninstaller.
        nsi.write('Section Uninstall\n')
        nsi.write('  Delete "$INSTDIR\\%s.exe"\n' % self.shortname)
        for f in extrafiles:
            nsi.write('  Delete "%s"\n' % f.getBasename())
        nsi.write('  Delete "$INSTDIR\\Uninstall.exe"\n')
        nsi.write('  RMDir /r "$INSTDIR"\n')
        nsi.write('  ; Start menu items\n')
        nsi.write(
            '  !insertmacro MUI_STARTMENU_GETFOLDER Application $StartMenuFolder\n'
        )
        nsi.write('  Delete "$SMPROGRAMS\\$StartMenuFolder\\Uninstall.lnk"\n')
        nsi.write('  RMDir "$SMPROGRAMS\\$StartMenuFolder"\n')
        nsi.write('SectionEnd')
        nsi.close()

        cmd = [makensis]
        for o in ["V2"]:
            if sys.platform.startswith("win"):
                cmd.append("/" + o)
            else:
                cmd.append("-" + o)
        cmd.append(nsifile.toOsSpecific())
        print cmd
        try:
            retcode = subprocess.call(cmd, shell=False)
            if retcode != 0:
                self.notify.warning("Failure invoking NSIS command.")
        except OSError:
            self.notify.warning("Unable to invoke NSIS command.")

        nsifile.unlink()
        return output
    def buildPKG(self, output, platform):
        appfn = self.buildAPP(output, platform)
        appname = "/Applications/" + appfn.getBasename()
        output = Filename(output)
        if output.isDirectory():
            output = Filename(output,
                              "%s %s.pkg" % (self.fullname, self.version))
        Installer.notify.info("Creating %s..." % output)

        Filename(output, "Contents/Resources/en.lproj/").makeDir()
        if self.licensefile:
            shutil.copyfile(
                self.licensefile.toOsSpecific(),
                Filename(output,
                         "Contents/Resources/License.txt").toOsSpecific())
        pkginfo = open(
            Filename(output, "Contents/PkgInfo").toOsSpecific(), "w")
        pkginfo.write("pkmkrpkg1")
        pkginfo.close()
        pkginfo = open(
            Filename(output,
                     "Contents/Resources/package_version").toOsSpecific(), "w")
        pkginfo.write("major: 1\nminor: 9")
        pkginfo.close()

        # Although it might make more sense to use Python's plistlib here,
        # it is not available on non-OSX systems before Python 2.6.
        plist = open(
            Filename(output, "Contents/Info.plist").toOsSpecific(), "w")
        plist.write('<?xml version="1.0" encoding="UTF-8"?>\n')
        plist.write(
            '<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n'
        )
        plist.write('<plist version="1.0">\n')
        plist.write('<dict>\n')
        plist.write('\t<key>CFBundleIdentifier</key>\n')
        plist.write('\t<string>%s.pkg.%s</string>\n' %
                    (self.authorid, self.shortname))
        plist.write('\t<key>CFBundleShortVersionString</key>\n')
        plist.write('\t<string>%s</string>\n' % self.version)
        plist.write('\t<key>IFMajorVersion</key>\n')
        plist.write('\t<integer>1</integer>\n')
        plist.write('\t<key>IFMinorVersion</key>\n')
        plist.write('\t<integer>9</integer>\n')
        plist.write('\t<key>IFPkgFlagAllowBackRev</key>\n')
        plist.write('\t<false/>\n')
        plist.write('\t<key>IFPkgFlagAuthorizationAction</key>\n')
        plist.write('\t<string>RootAuthorization</string>\n')
        plist.write('\t<key>IFPkgFlagDefaultLocation</key>\n')
        plist.write('\t<string>/</string>\n')
        plist.write('\t<key>IFPkgFlagFollowLinks</key>\n')
        plist.write('\t<true/>\n')
        plist.write('\t<key>IFPkgFlagIsRequired</key>\n')
        plist.write('\t<false/>\n')
        plist.write('\t<key>IFPkgFlagOverwritePermissions</key>\n')
        plist.write('\t<false/>\n')
        plist.write('\t<key>IFPkgFlagRelocatable</key>\n')
        plist.write('\t<false/>\n')
        plist.write('\t<key>IFPkgFlagRestartAction</key>\n')
        plist.write('\t<string>None</string>\n')
        plist.write('\t<key>IFPkgFlagRootVolumeOnly</key>\n')
        plist.write('\t<true/>\n')
        plist.write('\t<key>IFPkgFlagUpdateInstalledLanguages</key>\n')
        plist.write('\t<false/>\n')
        plist.write('\t<key>IFPkgFormatVersion</key>\n')
        plist.write('\t<real>0.10000000149011612</real>\n')
        plist.write('\t<key>IFPkgPathMappings</key>\n')
        plist.write('\t<dict>\n')
        plist.write('\t\t<key>%s</key>\n' % appname)
        plist.write('\t\t<string>{pkmk-token-2}</string>\n')
        plist.write('\t</dict>\n')
        plist.write('</dict>\n')
        plist.write('</plist>\n')
        plist.close()

        plist = open(
            Filename(
                output,
                "Contents/Resources/TokenDefinitions.plist").toOsSpecific(),
            "w")
        plist.write('<?xml version="1.0" encoding="UTF-8"?>\n')
        plist.write(
            '<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n'
        )
        plist.write('<plist version="1.0">\n')
        plist.write('<dict>\n')
        plist.write('\t<key>pkmk-token-2</key>\n')
        plist.write('\t<array>\n')
        plist.write('\t\t<dict>\n')
        plist.write('\t\t\t<key>identifier</key>\n')
        plist.write('\t\t\t<string>%s.%s</string>\n' %
                    (self.authorid, self.shortname))
        plist.write('\t\t\t<key>path</key>\n')
        plist.write('\t\t\t<string>%s</string>\n' % appname)
        plist.write('\t\t\t<key>searchPlugin</key>\n')
        plist.write('\t\t\t<string>CommonAppSearch</string>\n')
        plist.write('\t\t</dict>\n')
        plist.write('\t</array>\n')
        plist.write('</dict>\n')
        plist.write('</plist>\n')
        plist.close()

        plist = open(
            Filename(output, "Contents/Resources/en.lproj/Description.plist").
            toOsSpecific(), "w")
        plist.write('<?xml version="1.0" encoding="UTF-8"?>\n')
        plist.write(
            '<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n'
        )
        plist.write('<plist version="1.0">\n')
        plist.write('<dict>\n')
        plist.write('\t<key>IFPkgDescriptionDescription</key>\n')
        plist.write('\t<string></string>\n')
        plist.write('\t<key>IFPkgDescriptionTitle</key>\n')
        plist.write('\t<string>%s</string>\n' % self.fullname)
        plist.write('</dict>\n')
        plist.write('</plist>\n')
        plist.close()

        if hasattr(tarfile, "PAX_FORMAT"):
            archive = tarfile.open(Filename(
                output, "Contents/Archive.pax.gz").toOsSpecific(),
                                   "w:gz",
                                   format=tarfile.PAX_FORMAT,
                                   tarinfo=TarInfoRootOSX)
        else:
            archive = tarfile.open(Filename(
                output, "Contents/Archive.pax.gz").toOsSpecific(),
                                   "w:gz",
                                   tarinfo=TarInfoRootOSX)
        archive.add(appfn.toOsSpecific(), appname)
        archive.close()

        # Put the .pkg into a zipfile
        archive = Filename(output.getDirname(),
                           "%s %s.zip" % (self.fullname, self.version))
        dir = Filename(output.getDirname())
        dir.makeAbsolute()
        zip = zipfile.ZipFile(archive.toOsSpecific(), 'w')
        for root, dirs, files in self.os_walk(output.toOsSpecific()):
            for name in files:
                file = Filename.fromOsSpecific(os.path.join(root, name))
                file.makeAbsolute()
                file.makeRelativeTo(dir)
                zip.write(os.path.join(root, name), str(file))
        zip.close()

        return output
    def buildDEB(self, output, platform):
        """ Builds a .deb archive and stores it in the path indicated
        by the 'output' argument. It will be built for the architecture
        specified by the 'arch' argument.
        If 'output' is a directory, the deb file will be stored in it. """

        arch = platform.rsplit("_", 1)[-1]
        output = Filename(output)
        if output.isDirectory():
            output = Filename(
                output,
                "%s_%s_%s.deb" % (self.shortname.lower(), self.version, arch))
        Installer.notify.info("Creating %s..." % output)
        modtime = int(time.time())

        # Create a temporary directory and write the launcher and dependencies to it.
        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"
        controlinfo = TarInfoRoot("control")
        controlinfo.mtime = modtime
        controlinfo.size = controlfile.tell()
        controlfile.seek(0)

        # Open the deb file and write to it. It's actually
        # just an AR file, which is very easy to make.
        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")

        # Write the control.tar.gz to the archive.
        debfile.write(
            "control.tar.gz  %-12lu0     0     100644  %-10ld\x60\x0A" %
            (modtime, 0))
        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")

        # Write the data.tar.gz to the archive.
        debfile.write(
            "data.tar.gz     %-12lu0     0     100644  %-10ld\x60\x0A" %
            (modtime, 0))
        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")

        # Write the correct sizes of the archives.
        debfile.seek(ctaroffs - 12)
        debfile.write("%-10ld" % ctarsize)
        debfile.seek(dtaroffs - 12)
        debfile.write("%-10ld" % dtarsize)

        debfile.close()

        return output