Răsfoiți Sursa

Add useful pdeploy script that can easily deploy any app to cdrom, web, or create installers for all platforms

rdb 16 ani în urmă
părinte
comite
4a39c66fff
2 a modificat fișierele cu 150 adăugiri și 10 ștergeri
  1. 12 10
      direct/src/p3d/InstallerMaker.py
  2. 138 0
      direct/src/p3d/pdeploy.py

+ 12 - 10
direct/src/p3d/InstallerMaker.py

@@ -19,10 +19,11 @@ class InstallerMaker:
         self.shortname = shortname
         self.fullname = fullname
         self.version = str(version)
-        # All paths given must be OS-specific!
-        self.p3dfile = p3dfile
         self.licensename = ""
-        self.licensefile = ""
+        # All paths given must be a Filename instance!
+        assert isinstance(p3dfile, Filename)
+        self.p3dfile = p3dfile
+        self.licensefile = Filename()
 
     def build(self):
         """ Creates the installer. Call this after you have set all the parameters. """
@@ -48,15 +49,16 @@ class InstallerMaker:
         controlfile.close()
         os.makedirs(os.path.join(tempdir, "usr", "bin"))
         os.makedirs(os.path.join(tempdir, "usr", "share", "games", self.shortname))
-        if self.licensefile != "":
+        if not self.licensefile.empty():
             os.makedirs(os.path.join(tempdir, "usr", "share", "doc", self.shortname))
         launcherfile = open(os.path.join(tempdir, "usr", "bin", self.shortname), "w")
         launcherfile.write("#!/bin/sh\n")
-        launcherfile.write("/usr/bin/panda3d /usr/share/games/%s/data.p3d\n" % self.shortname)
+        launcherfile.write("/usr/bin/env panda3d /usr/share/games/%s/data.p3d\n" % self.shortname)
         launcherfile.close()
-        shutil.copyfile(self.p3dfile, os.path.join(tempdir, "usr", "share", "games", self.shortname, "data.p3d"))
-        if self.licensefile != "":
-            shutil.copyfile(self.licensefile, os.path.join(tempdir, "usr", "share", "doc", self.shortname, "copyright"))
+        os.chmod(os.path.join(tempdir, "usr", "bin", self.shortname), 0755)
+        shutil.copyfile(self.p3dfile.toOsSpecific(), os.path.join(tempdir, "usr", "share", "games", self.shortname, "data.p3d"))
+        if not self.licensefile.empty():
+            shutil.copyfile(self.licensefile.toOsSpecific(), os.path.join(tempdir, "usr", "share", "doc", self.shortname, "copyright"))
 
         # Create a control.tar.gz file in memory
         controltargz = CachedFile()
@@ -139,8 +141,8 @@ class InstallerMaker:
         nsi.write('\n')
         nsi.write('Var StartMenuFolder\n')
         nsi.write('!insertmacro MUI_PAGE_WELCOME\n')
-        if self.licensefile != "":
-            nsi.write('!insertmacro MUI_PAGE_LICENSE "%s"\n' % self.licensefile)
+        if not self.licensefile.empty():
+            nsi.write('!insertmacro MUI_PAGE_LICENSE "%s"\n' % self.licensefile.toOsSpecific())
         nsi.write('!insertmacro MUI_PAGE_DIRECTORY\n')
         nsi.write('!insertmacro MUI_PAGE_STARTMENU Application $StartMenuFolder\n')
         nsi.write('!insertmacro MUI_PAGE_INSTFILES\n')

+ 138 - 0
direct/src/p3d/pdeploy.py

@@ -0,0 +1,138 @@
+#! /usr/bin/env python
+
+"""
+
+This command will help you to distribute your Panda game, consisting
+of a .p3d file, into an installable package or an HTML webpage.
+
+Usage:
+
+  %s [opts] app.p3d installer|web
+
+Modes:
+
+  installer
+    In this mode, installable packages will be created for as many
+    platforms as possible. To create Windows installers on
+    non-Windows platforms, you need to have the "makensis" utility
+    on your system PATH environment variable.
+
+  web
+    An HTML webpage will be generated that can be used to view
+    the provided p3d file in a browser.
+
+Options:
+
+  -v version_number
+     This should define the version number of your application
+     or game. In some deploy modes, this argument is required.
+     This should only contain alphanumeric characters, dots and
+     dashes, as the result of the deployment may be in valid
+     on some platforms otherwise.
+
+  -n your_app
+     Short, lowercase name of the application or game. Can only
+     contain alphanumeric characters, underscore or dash. This
+     name will also define the output file(s) of the process.
+     If omitted, the basename of the p3d file is used.
+
+  -N "Your Application"
+     Full name of the application or game. This one will be used
+     to display to the end-user.
+     If omitted, the short name is used.
+
+  -l "License Name"
+     Specifies the name of the software license that the game
+     or application is licensed under.
+
+  -L licensefile.txt
+     This should point to a file that contains the full text
+     describing the software license that the game or application
+     is licensed under.
+
+"""
+
+DEPLOY_MODES = ["installer", "web"]
+
+import sys
+import os
+import getopt
+from direct.p3d import InstallerMaker
+from pandac.PandaModules import Filename
+
+class ArgumentError(StandardError):
+    pass
+
+def deployApp(args):
+    opts, args = getopt.getopt(args, 'l:L:n:N:v:h')
+    
+    version = ""
+    shortname = ""
+    fullname = ""
+    licensename = ""
+    licensefile = Filename()
+    
+    for option, value in opts:
+        if option == '-v':
+            version = value.strip()
+        if option == '-n':
+            shortname = value.strip()
+        elif option == '-L':
+            fullname = value.strip()
+        if option == '-l':
+            licensename = value
+        elif option == '-L':
+            licensefile = Filename.fromOsSpecific(value)
+        elif option == '-h':
+            print __doc__ % (os.path.split(sys.argv[0])[1])
+            sys.exit(1)
+
+    if not args or len(args) < 2:
+        raise ArgumentError, "No target app and/or deploy type specified.  Use:\n%s app.p3d %s" % (os.path.split(sys.argv[0])[1], '|'.join(DEPLOY_MODES))
+
+    if len(args) > 2:
+        raise ArgumentError, "Too many arguments."
+
+    appFilename = Filename.fromOsSpecific(args[0])
+    if appFilename.getExtension().lower() != 'p3d':
+        raise ArgumentError, 'Application filename must end in ".p3d".'
+
+    deploy_mode = args[1].lower()
+    if deploy_mode not in DEPLOY_MODES:
+        raise ArgumentError, 'Invalid deploy type, must be one of "%s".' % '", "'.join(DEPLOY_MODES)
+
+    if shortname.lower() != shortname or ' ' in shortname:
+        raise ArgumentError, 'Provided short name should be lowercase, and may not contain spaces!'
+
+    if shortname == '':
+        shortname = appFilename.getBasenameWoExtension()
+
+    if fullname == '':
+        fullname = shortname
+
+    if version == '' and deploy_mode == 'installer':
+        raise ArgumentError, 'A version number is required in "installer" mode!'
+
+    try:
+        if deploy_mode == 'installer':
+            im = InstallerMaker.InstallerMaker(shortname, fullname, appFilename, version)
+            im.licensename = licensename
+            im.licensefile = licensefile
+            im.build()
+        elif deploy_mode == 'web':
+            raise NotImplementedError, 'The "web" mode is yet implemented.'
+        
+    except: raise
+    #except InstallerMaker.InstallerMakerError:
+    #    # Just print the error message and exit gracefully.
+    #    inst = sys.exc_info()[1]
+    #    print inst.args[0]
+    #    sys.exit(1)
+
+if __name__ == '__main__':
+    try:
+        deployApp(sys.argv[1:])
+    except ArgumentError, e:
+        print e.args[0]
+        sys.exit(1)
+