--- /dev/null
+'''Tools for building AppImages.'''
+from os import system, makedirs, chmod, stat, chdir, getcwd
+from shutil import rmtree, copy, copytree
+from urllib.request import urlretrieve
+from stat import S_IEXEC
+from glob import glob
+from textwrap import dedent
+import sys
+
+
+apprun_content = '''#!/bin/sh
+SELF=$(readlink -f "$0")
+HERE=${SELF%/*}
+export PATH="${HERE}/usr/bin/:${HERE}/usr/sbin/:${HERE}/usr/games/\
+:${HERE}/bin/:${HERE}/sbin/${PATH:+:$PATH}"
+export LD_LIBRARY_PATH="${HERE}/usr/bin/:${HERE}/usr/lib/\
+:${HERE}/usr/lib/i386-linux-gnu/:${HERE}/usr/lib/x86_64-linux-gnu/\
+:${HERE}/usr/lib32/:${HERE}/usr/lib64/:${HERE}/lib/\
+:${HERE}/lib/i386-linux-gnu/:${HERE}/lib/x86_64-linux-gnu/:${HERE}/lib32/\
+:${HERE}/lib64/${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
+export PYTHONPATH="${HERE}/usr/bin/:${HERE}/usr/share/pyshared/${PYTHONPATH\
+:+:$PYTHONPATH}"
+export XDG_DATA_DIRS="${HERE}/usr/share/${XDG_DATA_DIRS:+:$XDG_DATA_DIRS}"
+export PERLLIB="${HERE}/usr/share/perl5/:${HERE}/usr/lib/perl5/${PERLLIB:+\
+:$PERLLIB}"
+export GSETTINGS_SCHEMA_DIR="${HERE}/usr/share/glib-2.0/schemas/\
+${GSETTINGS_SCHEMA_DIR:+:$GSETTINGS_SCHEMA_DIR}"
+export QT_PLUGIN_PATH="${HERE}/usr/lib/qt4/plugins/\
+:${HERE}/usr/lib/i386-linux-gnu/qt4/plugins/\
+:${HERE}/usr/lib/x86_64-linux-gnu/qt4/plugins/:${HERE}/usr/lib32/qt4/plugins/\
+:${HERE}/usr/lib64/qt4/plugins/:${HERE}/usr/lib/qt5/plugins/\
+:${HERE}/usr/lib/i386-linux-gnu/qt5/plugins/\
+:${HERE}/usr/lib/x86_64-linux-gnu/qt5/plugins/:${HERE}/usr/lib32/qt5/plugins/\
+:${HERE}/usr/lib64/qt5/plugins/${QT_PLUGIN_PATH:+:$QT_PLUGIN_PATH}"
+EXEC=$(grep -e '^Exec=.*' "${HERE}"/*.desktop | head -n 1 | cut -d "=" -f 2 | \
+cut -d " " -f 1)
+exec "${EXEC}" "$@"'''
+
+
+desktop_content_tmpl = '''[Desktop Entry]
+Name=%s
+Exec=%s
+Icon=icon
+Type=Application
+Categories=Game;'''
+
+
+class AppImageBuilder:
+
+ def __init__(self, name):
+ self._name = name
+
+ def build(self, execname, longname=None, branch='',
+ ver='0.0.0', build_path='build/', ico=None, zsync_path=None):
+ '''Build an AppImage.'''
+ longname = longname or self._name
+ dirname = self._name.capitalize() + '.AppDir'
+ with InsideDir(build_path):
+ rmtree(dirname, ignore_errors=True)
+ makedirs(dirname)
+ with InsideDir(build_path + '/' + dirname):
+ with open('AppRun', 'w') as f_apprun: f_apprun.write(apprun_content)
+ chmod('AppRun', stat('AppRun').st_mode | S_IEXEC)
+ desktop_content = desktop_content_tmpl % (longname, execname)
+ with open(self._name + '.desktop', 'w') as fdesktop:
+ fdesktop.write(desktop_content)
+ if ico:
+ copy(ico, './icon.png')
+ copytree('../../%smanylinux1_x86_64' % build_path, './usr/bin')
+ src = 'https://github.com/AppImage/AppImageUpdate/releases/' + \
+ 'download/continuous/appimageupdatetool-x86_64.AppImage'
+ dst = './usr/bin/appimageupdatetool-x86_64.AppImage'
+ self._download(src, dst) # for AppImage's self-updating
+ with InsideDir(build_path):
+ src = 'https://github.com/AppImage/AppImageKit/releases/' + \
+ 'download/12/appimagetool-x86_64.AppImage'
+ tool = 'appimagetool-x86_64.AppImage'
+ self._download(src, tool)
+ hbranch = ('-' + branch) if branch else ''
+ tgt_name = 'Yocto%s-x86_64.AppImage' % hbranch
+ with open(dirname + '/usr/bin/appimage_name.txt', 'w') as fan:
+ fan.write(tgt_name)
+ with open(dirname + '/usr/bin/appimage_version.txt', 'w') as fav:
+ fav.write(ver)
+ if zsync_path:
+ tmpl = './%s %s %s -u "zsync|%s' + \
+ '%s%s-x86_64.AppImage.zsync"'
+ cmd = tmpl % (tool, dirname, tgt_name, zsync_path,
+ self._name.capitalize(), hbranch)
+ print(cmd)
+ system(cmd)
+
+ def _download(self, path, fname):
+ urlretrieve(path, fname)
+ chmod(fname, stat(fname).st_mode | S_IEXEC)
+
+ def __redirect(self, callback): # redirect output to console
+ from os import ttyname # here because it doesn't work on windows
+ with open(ttyname(0), 'w') as fout:
+ sys.stdout = fout
+ callback(glob('/tmp/.mount_%s*' % self._name.capitalize())[0])
+
+ def __update(self, _dir):
+ print('Current version: ' + self.__get_ver(_dir))
+ print('Update in progress...')
+ with open(_dir + '/usr/bin/appimage_name.txt') as fname:
+ name = fname.read().strip()
+ system('appimageupdatetool-x86_64.AppImage ' + name)
+ msg = '''\
+ Update finished.
+ Launch again with --version to check your version.'''
+ print(dedent(msg))
+
+ def __get_ver(self, _dir):
+ with open(_dir + '/usr/bin/appimage_version.txt') as fver:
+ return fver.read().strip()
+
+ def update(self):
+ '''Updates the current AppImage.'''
+ self.__redirect(self.__update)
+
+ # def __print_ver(_dir):
+ # print(self.__get_ver(_dir))
+
+ # def version(self):
+ # '''Prints the version of the current AppImage.'''
+ # self.__redirect(self.__print_ver)
+
+
+class InsideDir:
+ '''Context manager for working inside a directory.'''
+
+ def __init__(self, dir_):
+ self.dir = dir_
+ self.old_dir = getcwd()
+
+ def __enter__(self):
+ chdir(self.dir)
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ chdir(self.old_dir)