From 62237fea461e0d0d887899c356a5d243bd78be78 Mon Sep 17 00:00:00 2001 From: ngld Date: Sat, 28 Oct 2017 10:28:39 +0200 Subject: [PATCH 01/30] Fixed a few packaging issues on Ubuntu --- releng/pypi/auto-build.sh | 3 +++ releng/ubuntu/Dockerfile | 2 +- releng/ubuntu/auto-build.sh | 2 +- releng/ubuntu/debian/control | 2 +- releng/ubuntu/debian/patches/remove_requires_from_setup | 2 +- setup.py | 2 +- 6 files changed, 8 insertions(+), 5 deletions(-) diff --git a/releng/pypi/auto-build.sh b/releng/pypi/auto-build.sh index 113476e8..dd97c9e2 100644 --- a/releng/pypi/auto-build.sh +++ b/releng/pypi/auto-build.sh @@ -17,6 +17,9 @@ if [ -d dist ]; then rm -rf dist/* fi +npm install +npm install es6-shim + python3 configure.py ninja dist diff --git a/releng/ubuntu/Dockerfile b/releng/ubuntu/Dockerfile index 4709381a..c9342cbd 100644 --- a/releng/ubuntu/Dockerfile +++ b/releng/ubuntu/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:xenial +FROM ubuntu:artful RUN apt-get update && apt-get upgrade -y && \ apt-get install -y build-essential sudo gnupg debhelper pbuilder apt-file \ diff --git a/releng/ubuntu/auto-build.sh b/releng/ubuntu/auto-build.sh index 3cee38ab..d60f6dbc 100644 --- a/releng/ubuntu/auto-build.sh +++ b/releng/ubuntu/auto-build.sh @@ -25,7 +25,7 @@ cd ../../../../work export QT_SELECT=5 VERSION="$(python3 setup.py get_version)" -UBUNTU_VERSION="xenial" +UBUNTU_VERSION="artful" rsync -au ../src/releng/ubuntu/cache/node_modules/ node_modules/ python3 configure.py diff --git a/releng/ubuntu/debian/control b/releng/ubuntu/debian/control index ce06492d..7fc408e3 100644 --- a/releng/ubuntu/debian/control +++ b/releng/ubuntu/debian/control @@ -9,7 +9,7 @@ Homepage: https://github.com/ngld/knossos Package: knossos Architecture: all -Depends: ${misc:Depends}, ${python3:Depends}, libsdl2-2.0-0, libopenal1, p7zip-full, python3-pyqt5, python3-pyqt5.qtwebkit +Depends: ${misc:Depends}, ${python3:Depends}, libsdl2-2.0-0, libopenal1, p7zip-full, python3-pyqt5, python3-pyqt5.qtwebengine, python3-pyqt5.qtwebchannel, python3-requests-toolbelt, python3-ply Description: Simple mod manager for FreeSpace 2 Open The original idea and prototype were created by Hellzed. ngld rewrote the manager in Python and extended it. diff --git a/releng/ubuntu/debian/patches/remove_requires_from_setup b/releng/ubuntu/debian/patches/remove_requires_from_setup index fa528f01..76e508da 100644 --- a/releng/ubuntu/debian/patches/remove_requires_from_setup +++ b/releng/ubuntu/debian/patches/remove_requires_from_setup @@ -28,7 +28,7 @@ Index: knossos-0.4.0/setup.py keywords='fso freespace', packages=['knossos', 'knossos.ui', 'knossos.third_party'], -- install_requires=['six', 'requests', 'semantic_version', 'raven', 'PyQt5'], +- install_requires=['six', 'requests', 'requests_toolbelt', 'ply', 'semantic_version', 'raven', 'PyQt5'], + install_requires=[], # List additional groups of dependencies here (e.g. development dependencies). diff --git a/setup.py b/setup.py index 4a2b3140..4c20e73d 100644 --- a/setup.py +++ b/setup.py @@ -98,7 +98,7 @@ keywords='fso freespace', packages=['knossos', 'knossos.ui', 'knossos.third_party'], - install_requires=['six', 'requests', 'semantic_version', 'raven', 'PyQt5'], + install_requires=['six', 'requests', 'requests_toolbelt', 'ply', 'semantic_version', 'raven', 'PyQt5'], # List additional groups of dependencies here (e.g. development dependencies). # You can install these using the following syntax, for example: From 1790bf662126ed98d7f9899522de2a4993170e9a Mon Sep 17 00:00:00 2001 From: ngld Date: Sat, 28 Oct 2017 10:29:10 +0200 Subject: [PATCH 02/30] Switch to the next version. --- knossos/center.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/knossos/center.py b/knossos/center.py index ab70c007..1b3b31e3 100644 --- a/knossos/center.py +++ b/knossos/center.py @@ -24,7 +24,7 @@ # The version should follow the http://semver.org guidelines. # Only remove the -dev tag if you're making a release! -VERSION = '0.6.0-dev' +VERSION = '0.7.0-dev' UPDATE_LINK = 'https://dev.tproxy.de/knossos' INNOEXTRACT_LINK = 'https://dev.tproxy.de/knossos/innoextract.txt' DEBUG = os.getenv('KN_DEBUG', '0').strip() == '1' From 4478777e598fc25159107f9efd48f48c2d736bb0 Mon Sep 17 00:00:00 2001 From: asarium Date: Sun, 29 Oct 2017 09:22:40 +0100 Subject: [PATCH 03/30] Hide tool buttons for engine mods They don't work anyway so there is no point in showing them for engine mods. --- html/templates/kn-mod-home.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/html/templates/kn-mod-home.vue b/html/templates/kn-mod-home.vue index 85532631..03ec6db2 100644 --- a/html/templates/kn-mod-home.vue +++ b/html/templates/kn-mod-home.vue @@ -91,7 +91,7 @@ export default { - + From fd65838be4bb50e7252dcbac9170c5cf87c1c6ae Mon Sep 17 00:00:00 2001 From: ngld Date: Sun, 29 Oct 2017 10:38:17 +0100 Subject: [PATCH 04/30] Simplify the dropdown conditions --- html/templates/kn-mod-home.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/html/templates/kn-mod-home.vue b/html/templates/kn-mod-home.vue index 03ec6db2..e92a6e2a 100644 --- a/html/templates/kn-mod-home.vue +++ b/html/templates/kn-mod-home.vue @@ -91,7 +91,7 @@ export default { - + From 506303c8a7247c14811d714ddec3b936f5743542 Mon Sep 17 00:00:00 2001 From: ngld Date: Sun, 29 Oct 2017 17:48:08 +0100 Subject: [PATCH 05/30] Small UI fixes. --- html/templates/kn-mod-explore.vue | 2 +- html/templates/kn-mod-home.vue | 6 +++--- ui/hell.ui | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/html/templates/kn-mod-explore.vue b/html/templates/kn-mod-explore.vue index 84574ca2..aa22e9a1 100644 --- a/html/templates/kn-mod-explore.vue +++ b/html/templates/kn-mod-explore.vue @@ -77,7 +77,7 @@ export default { - + - - + + diff --git a/ui/hell.ui b/ui/hell.ui index 977c941a..4819f435 100644 --- a/ui/hell.ui +++ b/ui/hell.ui @@ -13,7 +13,7 @@ 1116 - 800 + 700 @@ -22,14 +22,14 @@ - + 0 0 - + about:blank From d55d20e91e45b3c2e9468653917d8da003907b37 Mon Sep 17 00:00:00 2001 From: asarium Date: Wed, 1 Nov 2017 13:06:33 +0100 Subject: [PATCH 06/30] Add support for limiting download bandwidth This uses a token bucket for limiting how fast files are downloaded by Knossos. The settings GUI could be improved but it should work well for most use cases and I simply don't have the HTML/JS knowledge to implement a better speed selection. I also added a new settings section for downloads since the "Knossos" section started to get a little big. --- Pipfile | 1 + html/templates/kn-settings-page.vue | 39 +++++++++++++----- knossos/center.py | 1 + knossos/launcher.py | 2 + knossos/settings.py | 3 ++ knossos/util.py | 62 ++++++++++++++++++++++++++++- 6 files changed, 98 insertions(+), 10 deletions(-) diff --git a/Pipfile b/Pipfile index 81265e57..7aaf8d18 100644 --- a/Pipfile +++ b/Pipfile @@ -13,4 +13,5 @@ raven = "*" pyqt5 = "*" requests-toolbelt = "*" ply = "*" +token-bucket = "*" diff --git a/html/templates/kn-settings-page.vue b/html/templates/kn-settings-page.vue index 71baa0a9..faba29b8 100644 --- a/html/templates/kn-settings-page.vue +++ b/html/templates/kn-settings-page.vue @@ -44,7 +44,7 @@ export default { save() { this.fso.joystick_ff_strength = this.ff_enabled ? 100 : 0; - for(let set of ['base_path', 'max_downloads', 'use_raven', 'engine_stability']) { + for(let set of ['base_path', 'max_downloads', 'use_raven', 'engine_stability', 'download_bandwidth']) { if(this.knossos[set] != this.old_settings.knossos[set]) { fs2mod.saveSetting(set, JSON.stringify(this.knossos[set])); } @@ -90,7 +90,7 @@ export default {
Click the arrows to reveal each group's options. Click SAVE when done.
-
Basic Knossos settings for downloads, errors, and data
+
Settings for basic Knossos options, errors, and data
@@ -99,13 +99,6 @@ export default {
-
- -
- -
-
-
@@ -125,6 +118,34 @@ export default {
+ +
Configuration of how Knossos handles downloads
+
+ +
+ +
+
+ +
+ +
+ +
+
+
+
Set your default video settings and resolution
diff --git a/knossos/center.py b/knossos/center.py index 1b3b31e3..6afbb5df 100644 --- a/knossos/center.py +++ b/knossos/center.py @@ -53,6 +53,7 @@ 'base_dirs': [], 'hash_cache': None, 'max_downloads': 3, + 'download_bandwidth': -1.0, # negative numbers are used to specify no limit 'repos': [('https://fsnebula.org/storage/repo.json', 'FSNebula')], 'nebula_link': 'https://fsnebula.org/api/1/', 'update_notify': True, diff --git a/knossos/launcher.py b/knossos/launcher.py index f907b196..775d0ad5 100644 --- a/knossos/launcher.py +++ b/knossos/launcher.py @@ -171,6 +171,8 @@ def run_knossos(): return util.DL_POOL.set_capacity(center.settings['max_downloads']) + if center.settings['download_bandwidth'] > 0.0: + util.SPEED_LIMIT_BUCKET.set_rate(center.settings['download_bandwidth']) center.app = app center.installed = repo.InstalledRepo() diff --git a/knossos/settings.py b/knossos/settings.py index 8bfae500..383960df 100644 --- a/knossos/settings.py +++ b/knossos/settings.py @@ -553,6 +553,9 @@ def save_setting(name, value): if name == 'max_downloads': if value != center.settings['max_downloads']: util.DL_POOL.set_capacity(value) + if name == 'download_bandwidth': + if value > 0.0: + util.SPEED_LIMIT_BUCKET.set_rate(value) elif name == 'language': # NOTE: This is deliberately not translated. QtWidgets.QMessageBox.information(None, 'Knossos', 'Please restart Knossos to complete the language change.') diff --git a/knossos/util.py b/knossos/util.py index 890e34f9..88d4affd 100644 --- a/knossos/util.py +++ b/knossos/util.py @@ -29,6 +29,7 @@ import glob import semantic_version import requests +import token_bucket from collections import OrderedDict from threading import Condition, Event, Thread from collections import deque @@ -109,9 +110,39 @@ DL_POOL = None _DL_CANCEL = Event() _DL_CANCEL.clear() +SPEED_LIMIT_BUCKET = None translate = QtCore.QCoreApplication.translate +class BlockingTokenBucket(object): + def __init__(self, rate): + self.limiter = None + self.rate = None + + self.set_rate(rate) + + def set_rate(self, rate): + self.limiter = token_bucket.Limiter(rate, rate, token_bucket.MemoryStorage()) + self.rate = rate + + def wait_for_consume(self, tokens, cancel_event): + while tokens > 0: + # If the number of tokens is more than what is available in the bucket then we would never be able to + # consume the tokens. This will retrieve the tokens in smaller steps if the number of requested tokens + # is larger than the available token rate + consuming = min(tokens, self.rate) + + # Busy waiting is not optimal but our token bucket does not support anything else + while not self.limiter.consume(b"default", consuming): + if cancel_event.is_set(): + return False + time.sleep(0.01) + + tokens -= consuming + + return True + + class ResizableSemaphore(object): _capacity = 0 _free = 0 @@ -329,6 +360,34 @@ def post(link, data, headers=None, random_ua=False): return result.text +def _limited_request_iter(result, chunk_size): + iterator = result.iter_content(chunk_size) + while True: + if not SPEED_LIMIT_BUCKET.wait_for_consume(chunk_size, _DL_CANCEL): + return + + yield next(iterator) + + +def _get_download_iterator(result, chunk_size): + if center.settings['download_bandwidth'] < 0.0: + # There is no bandwidth limit so just use the normal download method + return result.iter_content(chunk_size) + else: + return _limited_request_iter(result, chunk_size) + + +def _get_download_chunk_size(): + DEFAULT_CHUNK_SIZE = 512 * 1024 + if center.settings['download_bandwidth'] < 0.0: + # If there is no bandwidth limit then this should work reasonably well + return DEFAULT_CHUNK_SIZE + else: + # If there is a bandwidth limit then for small limits a too large chunk size will make the GUI appear frozen + # while the chunk is being downloaded. This will make sure that the GUI is updated twice a second + return min(int(center.settings['download_bandwidth'] / 2), DEFAULT_CHUNK_SIZE) + + def download(link, dest, headers=None, random_ua=False): global HTTP_SESSION, DL_POOL, _DL_CANCEL @@ -368,7 +427,7 @@ def download(link, dest, headers=None, random_ua=False): try: start = dest.tell() sc = SpeedCalc() - for chunk in result.iter_content(512 * 1024): + for chunk in _get_download_iterator(result, _get_download_chunk_size()): dest.write(chunk) if sc.push(dest.tell()) != -1: @@ -807,6 +866,7 @@ def from_version(version, op='=='): DL_POOL = ResizableSemaphore(10) HTTP_SESSION.headers['User-Agent'] = get_user_agent() +SPEED_LIMIT_BUCKET = BlockingTokenBucket(3 * 1024 * 1024) if not center.DEBUG: logging.getLogger('requests.packages.urllib3.connectionpool').propagate = False From 4c99087ac18ecc0a72ffecffbbc1ff40bae453f3 Mon Sep 17 00:00:00 2001 From: ngld Date: Thu, 2 Nov 2017 00:02:52 +0100 Subject: [PATCH 07/30] Added dependency checks and matched the coding style. --- configure.py | 1 + html/templates/kn-settings-page.vue | 20 ++++++++++---------- setup.py | 2 +- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/configure.py b/configure.py index 190dbf58..4f13c2e7 100644 --- a/configure.py +++ b/configure.py @@ -78,6 +78,7 @@ check_module('requests') check_module('requests_toolbelt') check_module('ply') +check_module('token_bucket') if sys.platform == 'win32': check_module('comtypes') diff --git a/html/templates/kn-settings-page.vue b/html/templates/kn-settings-page.vue index faba29b8..7a71b171 100644 --- a/html/templates/kn-settings-page.vue +++ b/html/templates/kn-settings-page.vue @@ -131,16 +131,16 @@ export default {
diff --git a/setup.py b/setup.py index 4c20e73d..d76d345f 100644 --- a/setup.py +++ b/setup.py @@ -98,7 +98,7 @@ keywords='fso freespace', packages=['knossos', 'knossos.ui', 'knossos.third_party'], - install_requires=['six', 'requests', 'requests_toolbelt', 'ply', 'semantic_version', 'raven', 'PyQt5'], + install_requires=['six', 'requests', 'requests_toolbelt', 'ply', 'semantic_version', 'raven', 'PyQt5', 'token_bucket'], # List additional groups of dependencies here (e.g. development dependencies). # You can install these using the following syntax, for example: From 0c142e74494d971976146d115185b925942dd06b Mon Sep 17 00:00:00 2001 From: ngld Date: Wed, 8 Nov 2017 20:47:27 +0100 Subject: [PATCH 08/30] Fix left, center and right BBCode tags --- html/js/bbparser.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/html/js/bbparser.js b/html/js/bbparser.js index 04bb54f9..ce5ae9cc 100644 --- a/html/js/bbparser.js +++ b/html/js/bbparser.js @@ -22,9 +22,9 @@ const parser = XBBCode.create({ sub: '{content}', tt: '{content}', pre: '
{content}
', - left: '{content}', - right: '{content}', - center: '{content}', + left: '
{content}
', + right: '
{content}
', + center: '
{content}
', table: '{content}
', tr: '{content}', td: '{content}', From 3991e7e25983c9ffac282dfb1e1e06bf144323d1 Mon Sep 17 00:00:00 2001 From: ngld Date: Thu, 9 Nov 2017 19:34:19 +0100 Subject: [PATCH 09/30] Replace the deprecated logging.warn() with logging.warning() --- knossos/integration.py | 2 +- knossos/repo.py | 2 +- knossos/settings.py | 2 +- knossos/tasks.py | 8 ++++---- knossos/web.py | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/knossos/integration.py b/knossos/integration.py index da994a0a..6272b796 100644 --- a/knossos/integration.py +++ b/knossos/integration.py @@ -223,7 +223,7 @@ def init(): if hasattr(gi, 'require_version'): gi.require_version('Unity', '6.0') except Exception: - logging.warn('Failed to specify Unity version. Most likely Unity is not available.') + logging.warning('Failed to specify Unity version. Most likely Unity is not available.') from gi.repository import Unity except ImportError: diff --git a/knossos/repo.py b/knossos/repo.py index a4b3a6f0..e54a707d 100644 --- a/knossos/repo.py +++ b/knossos/repo.py @@ -676,7 +676,7 @@ def check_env(self): return True if not isinstance(self.environment, str): - logging.warn('Invalid value for environment check in mod %s (%s)!' % (self._mod.mid, self._mod.version)) + logging.warning('Invalid value for environment check in mod %s (%s)!' % (self._mod.mid, self._mod.version)) return True bvars = {} diff --git a/knossos/settings.py b/knossos/settings.py index 383960df..4c34f10d 100644 --- a/knossos/settings.py +++ b/knossos/settings.py @@ -482,7 +482,7 @@ def get_fso_flags(fs2_bin): global fso_flags if not os.path.isfile(fs2_bin): - logging.warn('Tried to get flags for missing executable "%s"!' % fs2_bin) + logging.warning('Tried to get flags for missing executable "%s"!' % fs2_bin) return None if fs2_bin in _flag_cache: diff --git a/knossos/tasks.py b/knossos/tasks.py index 9e48d72b..d779b512 100644 --- a/knossos/tasks.py +++ b/knossos/tasks.py @@ -98,7 +98,7 @@ def __init__(self): def init1(self): if center.settings['base_path'] is None: - logging.warn('A CheckTask was launched even though no base path was set!') + logging.warning('A CheckTask was launched even though no base path was set!') else: center.installed.clear() self.add_work((center.settings['base_path'],)) @@ -119,7 +119,7 @@ def work1(self, path): elif base.lower() == 'mod.json': mod_file = sub except FileNotFoundError: - logging.warn('The directory "%s" does not exist anymore!' % path) + logging.warning('The directory "%s" does not exist anymore!' % path) if mod_file: try: @@ -1174,7 +1174,7 @@ def __init__(self, gog_path, dest_path): fso = center.mods.query('FSO') run_task(InstallTask(fso.resolve_deps())) except repo.ModNotFound: - logging.warn('Installing retail files but FSO is missing!') + logging.warning('Installing retail files but FSO is missing!') def work(self, paths): gog_path, dest_path = paths @@ -1335,7 +1335,7 @@ def __init__(self, gog_path, dest_path): fso = center.mods.query('FSO') run_task(InstallTask(fso.resolve_deps())) except repo.ModNotFound: - logging.warn('Installing retail files but FSO is missing!') + logging.warning('Installing retail files but FSO is missing!') def work(self, paths): gog_path, dest_path = paths diff --git a/knossos/web.py b/knossos/web.py index 86d651d7..2632ffd2 100644 --- a/knossos/web.py +++ b/knossos/web.py @@ -457,7 +457,7 @@ def searchRetailData(self): else: steam_config = os.path.join(steam_path, 'config/config.vdf') if not os.path.isfile(steam_config): - logging.warn('config.vdf is not where I expected it!') + logging.warning('config.vdf is not where I expected it!') else: folders.append(os.path.join(steam_config, 'steamapps', 'common', 'Freespace 2')) From 8c177a7650fc2f350565e53803876b2b3ee521a0 Mon Sep 17 00:00:00 2001 From: asarium Date: Thu, 9 Nov 2017 19:07:51 +0100 Subject: [PATCH 10/30] Check package environment on local mod data loading This is needed since both Windows and Linux packages could be installed at the same time when the user uses the same directory on multiple platforms. --- knossos/repo.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/knossos/repo.py b/knossos/repo.py index e54a707d..b780ed08 100644 --- a/knossos/repo.py +++ b/knossos/repo.py @@ -855,7 +855,11 @@ def set(self, values): self.custom_build = values.get('custom_build', None) self.check_notes = values.get('check_notes', '') for pkg in pkgs: - self.packages.append(InstalledPackage(pkg, self)) + installed_pkg = InstalledPackage(pkg, self) + # If the user installed packages on multiple platforms into the same directory then an installed package + # may be present that is not valid for the current environment so we need to check that here + if installed_pkg.check_env(): + self.packages.append(installed_pkg) def get(self): return { From 2a070a209a340f2220aab1f3668bf98af8088512 Mon Sep 17 00:00:00 2001 From: ngld Date: Fri, 10 Nov 2017 00:50:08 +0100 Subject: [PATCH 11/30] Fix the stability filter (#59) --- html/templates/kn-devel-page.vue | 15 ++++++++++++++- knossos/repo.py | 8 +++++++- knossos/windows.py | 22 +++++++++++++++++++++- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/html/templates/kn-devel-page.vue b/html/templates/kn-devel-page.vue index 0f3033ce..9486931c 100644 --- a/html/templates/kn-devel-page.vue +++ b/html/templates/kn-devel-page.vue @@ -139,6 +139,19 @@ export default { } }, + computed: { + engine_builds() { + let builds = []; + for(let mod of this.mods) { + if(mod.type === 'engine') { + builds = builds.concat(mod.versions); + } + } + + return builds; + } + }, + methods: { showRetailPrompt() { vm.showRetailPrompt(); @@ -740,7 +753,7 @@ export default {
+
+
+ +
+
+
@@ -469,9 +519,9 @@ export default {
@@ -511,7 +561,8 @@ export default {
- + +
diff --git a/knossos/repo.py b/knossos/repo.py index 8c154144..2e201f82 100644 --- a/knossos/repo.py +++ b/knossos/repo.py @@ -829,11 +829,6 @@ def load(path): mod.folder = os.path.normpath(os.path.dirname(path)) mod.set(data) return mod - elif path.lower().endswith('.ini'): - mod = IniMod() - mod.folder = os.path.normpath(os.path.dirname(path)) - mod.load(path) - return mod else: return None @@ -1064,7 +1059,7 @@ def __init__(self, values=None): self._pr_list = [] self._sc_list = [] - self.version = semantic_version.Version('1.0.0+ini') + self.version = semantic_version.Version('1.0.0') def load(self, path): with open(path, 'r') as stream: @@ -1081,7 +1076,7 @@ def load(self, path): continue if name == 'modname': - self.title = value + ' (ini)' + self.title = value elif name == 'infotext': self.description = value elif name.startswith('image'): @@ -1091,11 +1086,11 @@ def load(self, path): elif name in ('secondarylist', 'secondrylist'): self._sc_list = value.split(',') - self.folder = os.path.basename(os.path.dirname(path)) + self.folder = os.path.dirname(path) if self.title == '': - self.title = self.folder + ' (ini)' + self.title = os.path.basename(self.folder) - self.mid = '##INI_COMPAT#' + self.folder + self.mid = os.path.basename(self.folder) if self.logo: self.logo_path = os.path.join(path, self.logo) @@ -1103,6 +1098,11 @@ def load(self, path): 'name': 'Content', 'status': 'required' }, self) + + # Set some default values + self.screenshots = [] + self.attachments = [] + self.add_pkg(pkg) def get_mod_flag(self): @@ -1112,6 +1112,12 @@ def get_mod_flag(self): return mods + def get_primary_list(self): + return self._pr_list + + def get_secondary_list(self): + return self._sc_list + class InstalledPackage(Package): check_notes = '' diff --git a/knossos/tasks.py b/knossos/tasks.py index a3e75762..24ba1b04 100644 --- a/knossos/tasks.py +++ b/knossos/tasks.py @@ -622,33 +622,8 @@ def work2(self, archive): os.makedirs(dparent) if dev_mode and archive['pkg'].is_vp: - vp = vplib.VpReader(src_path) - - fc = float(len(vp.files)) - done = 0 progress.start_task(0.98, 0.02, '%s') - for path, meta in vp.files.items(): - progress.update(done / fc, path) - hdl = vp.open_file(path) - - sub_dest = util.ipath(os.path.join(modpath, archive['pkg'].folder, path)) - sub_par = os.path.dirname(sub_dest) - - if not os.path.isdir(sub_par): - os.makedirs(sub_par) - - with open(sub_dest, 'wb') as dest_hdl: - remaining = meta['size'] - bufsize = 16 * 1024 # 16 KiB - while remaining > 0: - buf = hdl.read(min(remaining, bufsize)) - if not buf: - break - - dest_hdl.write(buf) - remaining -= bufsize - - done += 1 + util.extract_vp_file(src_path, os.path.join(modpath, archive['pkg'].folder)) # Avoid confusing CheckTask with a missing VP file. archive['pkg'].filelist = [] @@ -1522,6 +1497,40 @@ def work(self, p): bytes_done += os.stat(src).st_size +class VpExtractionTask(progress.Task): + def __init__(self, installed_mod, ini_mod): + super(VpExtractionTask, self).__init__() + + self.mod = installed_mod + self.ini_mod = ini_mod + + self.title = 'Extracting VP files...' + + self._threads = 1 # VP extraction does not benefit from multiple threads + + for vp_file in os.listdir(ini_mod.folder): + # We only look at vp files + if not vp_file.lower().endswith(".vp"): + continue + + vp_path = os.path.join(ini_mod.folder, vp_file) + + self.add_work((vp_path,)) + + def work(self, vp_file): + base_filename = os.path.basename(vp_file).replace(".vp", "") + + dest_folder = os.path.join(self.mod.folder, base_filename) + + progress.start_task(0.0, 1.0, 'Extracting %s') + + util.extract_vp_file(vp_file, dest_folder) + + progress.finish_task() + # Collect the extracted vp files so we can use that once extraction has finished + self.post(vp_file) + + def run_task(task, cb=None): def wrapper(): cb(task.get_results()) diff --git a/knossos/util.py b/knossos/util.py index 88d4affd..fb724d05 100644 --- a/knossos/util.py +++ b/knossos/util.py @@ -34,6 +34,7 @@ from threading import Condition, Event, Thread from collections import deque +from .vplib import VpReader from . import center, progress from .qt import QtCore @@ -798,6 +799,38 @@ def is_fs2_retail_directory(path): return False +def extract_vp_file(vp_path, dest_path): + if not os.path.isdir(dest_path): + os.makedirs(dest_path) + + vp_reader = VpReader(vp_path) + + fc = float(len(vp_reader.files)) + done = 0 + for path, meta in vp_reader.files.items(): + progress.update(done / fc, path) + hdl = vp_reader.open_file(path) + + sub_dest = ipath(os.path.join(dest_path, path)) + sub_par = os.path.dirname(sub_dest) + + if not os.path.isdir(sub_par): + os.makedirs(sub_par) + + with open(sub_dest, 'wb') as dest_hdl: + remaining = meta['size'] + bufsize = 16 * 1024 # 16 KiB + while remaining > 0: + buf = hdl.read(min(remaining, bufsize)) + if not buf: + break + + dest_hdl.write(buf) + remaining -= bufsize + + done += 1 + + def enable_raven(): try: from raven import Client diff --git a/knossos/web.py b/knossos/web.py index 46e4d8b2..e37a7166 100644 --- a/knossos/web.py +++ b/knossos/web.py @@ -1142,6 +1142,111 @@ def testVoice(self, voice, volume, text): def showDescEditor(self, text): windows.DescriptionEditorWindow(text) + @QtCore.Slot(str, result=str) + def parseIniMod(self, path): + mod = repo.IniMod() + mod.load(path) + return json.dumps(mod.get()) + + @QtCore.Slot(str, str, str, str, str, str, result=bool) + def importIniMod(self, ini_path, name, mid, version, mtype, parent): + if parent != 'FS2': + parent = self._get_mod(parent) + + if parent == -1: + QtWidgets.QMessageBox.critical(None, 'Knossos', self.tr('The selected parent TC is not valid!')) + return False + else: + parent = parent.mid + + mod = repo.InstalledMod({ + 'title': name, + 'id': mid, + 'version': version, + 'type': mtype, + 'parent': parent, + 'dev_mode': True + }) + mod.generate_folder() + + if os.path.isdir(mod.folder): + # TODO: Check online, too? + QtWidgets.QMessageBox.critical(None, 'Knossos', self.tr('There already exists a mod with the chosen ID!')) + return False + + upper_folder = os.path.dirname(mod.folder) + if not os.path.isdir(upper_folder): + logging.error('%s did not exist during mod creation! (parent = %s)' % (mod.folder, mod.parent)) + QtWidgets.QMessageBox.critical(None, 'Knossos', self.tr('The chosen parent does not exist! Something went very wrong here!!')) + return False + + # We need the ini mod for determining where to pull the VPs from + ini_mod = repo.IniMod() + ini_mod.load(ini_path) + + if len(ini_mod.get_primary_list()) > 0: + QtWidgets.QMessageBox.critical(None, 'Knossos', self.tr( + 'Ini mods with a primary list are currently not supported for importing!')) + return False + + # This dict will convert a known secondary list entry to a mod.json style dependency + dependency_mapping = { + "mediavps_2014": { + "id": "MVPS", + "version": "3.7.2", + }, + "mediavps_3612": { + "id": "MVPS", + "version": "3.6.12", + }, + "mediavps": { + "id": "MVPS", + "version": "3.6.10", + }, + } + + package_dependencies = [] + + for dependency in ini_mod.get_secondary_list(): + dependency = dependency.lower() # The mapping only works for lower case + if dependency not in dependency_mapping: + # An unknown dependency is just skipped + QtWidgets.QMessageBox.warning(None, 'Knossos', + self.tr( + 'The mod.ini dependency %s is not known to Knossos and could not be converted to a mod.json dependency.') + % (dependency)) + continue + + package_dependencies.append(dependency_mapping[dependency]) + + task = tasks.VpExtractionTask(mod, ini_mod) + + def finish_import(): + for vp_file in task.get_results(): + base_filename = os.path.basename(vp_file).replace(".vp", "") + + pkg = repo.InstalledPackage({ + 'name': base_filename, + 'status': 'required', + 'folder': base_filename, + 'dependencies': package_dependencies, + 'is_vp': True + }) + mod.add_pkg(pkg) + + center.installed.add_mod(mod) + mod.update_mod_flag() + + mod.save() + + center.main_win.update_mod_list() + + task.done.connect(finish_import) + + tasks.run_task(task) + + return True + if QtWebChannel: BrowserCtrl = WebBridge From 9a7363de7079557b654a87b5cb9e4de3074f3588 Mon Sep 17 00:00:00 2001 From: ngld Date: Sat, 11 Nov 2017 18:07:17 +0100 Subject: [PATCH 21/30] Fixed `process_pkg_selection` (should solve #74) The new code added to fix the stability filter didn't take the version format into account. --- knossos/repo.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/knossos/repo.py b/knossos/repo.py index 2e201f82..e2887b76 100644 --- a/knossos/repo.py +++ b/knossos/repo.py @@ -309,7 +309,14 @@ def process_pkg_selection(self, pkgs, recursive=True): mod = pkg.get_mod() dd = dep_dict.setdefault(mod.mid, {}) dd = dd.setdefault(pkg.name, {}) - dd[mod.version] = pkg + + version = str(mod.version) + if version != '*' and not SpecItem.re_spec.match(version): + # Make a spec out of this version + version = '==' + version + + version = util.Spec(version) + dd[version] = pkg # Resolve the pkgs' dependencies while len(ndeps) > 0: From 34c6362983cab2618a71f2bc665451422c001050 Mon Sep 17 00:00:00 2001 From: ngld Date: Sat, 11 Nov 2017 18:09:55 +0100 Subject: [PATCH 22/30] Disallow removing packages from dev mods (fixes #78) --- knossos/windows.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/knossos/windows.py b/knossos/windows.py index 4422b0f0..7c53a4da 100644 --- a/knossos/windows.py +++ b/knossos/windows.py @@ -426,7 +426,11 @@ def show_packages(self): item.setData(0, QtCore.Qt.UserRole, mod) item.setData(0, QtCore.Qt.UserRole + 2, '') c = 0 - mod_installed = center.installed.is_installed(mod) + + try: + local_mod = center.installed.query(mod) + except repo.ModNotFound: + local_mod = None for pkg in mod.packages: fsize = 0 @@ -445,13 +449,13 @@ def show_packages(self): if is_installed: sub.setText(1, self.tr('Installed')) - if pkg.status == 'required' or pkg in needed_pkgs or is_required: + if pkg.status == 'required' or pkg in needed_pkgs or is_required or (local_mod and local_mod.dev_mode): sub.setCheckState(0, QtCore.Qt.Checked) sub.setDisabled(True) c += 1 elif pkg.status == 'recommended': - if not mod_installed or is_installed: + if not local_mod or is_installed: sub.setCheckState(0, QtCore.Qt.Checked) c += 1 else: From 8279ed7f202828733414876445dfa9e72607e272 Mon Sep 17 00:00:00 2001 From: ngld Date: Sat, 11 Nov 2017 18:14:04 +0100 Subject: [PATCH 23/30] Handle edge-cases related to the stability filter correctly --- knossos/repo.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/knossos/repo.py b/knossos/repo.py index e2887b76..cfe45bd8 100644 --- a/knossos/repo.py +++ b/knossos/repo.py @@ -366,7 +366,7 @@ def process_pkg_selection(self, pkgs, recursive=True): stab_idx = STABILITES.index(stab) candidates = [] - while stab_idx > 0: + while stab_idx > -1: candidates = [m for m in remains if m.get_mod().stability == stab] if len(candidates) == 0: # Nothing found, try the next lower stability @@ -376,7 +376,9 @@ def process_pkg_selection(self, pkgs, recursive=True): # Found at least one result break - remains = candidates + # An empty remains list would trigger an index out of bounds error; avoid that + if len(candidates) > 0: + remains = candidates # Pick the latest remains.sort(key=lambda v: v.get_mod().version) From 108cf42a92ceb64a7e798a8e5f9734e4f9d62178 Mon Sep 17 00:00:00 2001 From: ngld Date: Sat, 11 Nov 2017 18:14:32 +0100 Subject: [PATCH 24/30] Don't change the tab after triggering a mod install Closes #77 --- knossos/windows.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/knossos/windows.py b/knossos/windows.py index 7c53a4da..72a767b7 100644 --- a/knossos/windows.py +++ b/knossos/windows.py @@ -535,8 +535,6 @@ def update_notes(self, item): self.win.notesField.setPlainText(item.data(0, QtCore.Qt.UserRole + 2)) def install(self): - center.main_win.update_mod_buttons('home') - to_install, to_remove = self.get_selected_pkgs() run_task(InstallTask(to_install, self._mod)) From e2dc12707df39536aefb6421de4f03780a8447da Mon Sep 17 00:00:00 2001 From: ngld Date: Sat, 11 Nov 2017 19:05:07 +0100 Subject: [PATCH 25/30] Merge the import ini dialog with the create mod dialog. --- html/templates/kn-devel-page.vue | 21 ---- html/templates/kn-page.vue | 42 ++----- knossos/web.py | 201 +++++++++++++------------------ 3 files changed, 95 insertions(+), 169 deletions(-) diff --git a/html/templates/kn-devel-page.vue b/html/templates/kn-devel-page.vue index ab3aa7ba..9486931c 100644 --- a/html/templates/kn-devel-page.vue +++ b/html/templates/kn-devel-page.vue @@ -181,26 +181,6 @@ export default { vm.popup_visible = true; }, - openImportPopup() { - vm.popup_mode = 'import_ini_mod'; - vm.popup_title = 'Import mod.ini'; - vm.popup_mod_name = ''; - vm.popup_mod_id = ''; - vm.popup_mod_version = '1.0.0'; - vm.popup_mod_type = 'mod'; - vm.popup_mod_tcs = this.mods.filter((mod) => mod.type === 'tc'); - vm.popup_mod_parent = ''; - - for(let tc of vm.popup_mod_tcs) { - if(tc.id === 'FS2') { - vm.popup_mod_parent = 'FS2'; - break; - } - } - - vm.popup_visible = true; - }, - openNewVersionPopup() { vm.popup_mode = 'new_mod_version'; vm.popup_title = 'Create a new mod version'; @@ -510,7 +490,6 @@ export default {
- {{ mod.title }} diff --git a/html/templates/kn-page.vue b/html/templates/kn-page.vue index 91744fb2..c4bbcaf6 100644 --- a/html/templates/kn-page.vue +++ b/html/templates/kn-page.vue @@ -140,35 +140,14 @@ export default { return; } - call(fs2mod.createMod, this.popup_mod_name, this.popup_mod_id, this.popup_mod_version, this.popup_mod_type, this.popup_mod_parent, (result) => { - if(result) { - this.popup_visible = false; - } - }); - }, - - importIniMod() { - if (this.popup_ini_path === '') { - alert('You need to enter the path to the mod.ini file!'); - } - - if(this.popup_mod_id === '') { - alert('You need to enter a mod ID!'); - return; - } - - - if(this.popup_mod_name === '') { - alert('You need to enter a mod name!'); - return; - } - - call(fs2mod.importIniMod, this.popup_ini_path, this.popup_mod_name, this.popup_mod_id, - this.popup_mod_version, this.popup_mod_type, this.popup_mod_parent, (result) => { - if (result) { + call(fs2mod.createMod, this.popup_ini_path, this.popup_mod_name, this.popup_mod_id, this.popup_mod_version, + this.popup_mod_type, this.popup_mod_parent, + (result) => { + if(result) { this.popup_visible = false; } - }); + } + ); }, addPackage() { @@ -475,12 +454,14 @@ export default {

-
+
-
+
+ +

Only use this if you want to convert a legacy mod

@@ -561,8 +542,7 @@ export default {
- - +
diff --git a/knossos/web.py b/knossos/web.py index e37a7166..2d6a9727 100644 --- a/knossos/web.py +++ b/knossos/web.py @@ -524,8 +524,8 @@ def getRunningTasks(self): logging.exception('Failed to encoding running tasks!') return 'null' - @QtCore.Slot(str, str, str, str, str, result=bool) - def createMod(self, name, mid, version, mtype, parent): + @QtCore.Slot(str, str, str, str, str, str, result=bool) + def createMod(self, ini_path, name, mid, version, mtype, parent): if mtype in ('mod', 'ext'): if parent != 'FS2': parent = self._get_mod(parent) @@ -567,27 +567,93 @@ def createMod(self, name, mid, version, mtype, parent): QtWidgets.QMessageBox.critical(None, 'Knossos', self.tr('The chosen parent does not exist! Something went very wrong here!!')) return False - pkg = repo.InstalledPackage({ - 'name': 'Content', - 'status': 'required', - 'folder': 'content' - }) + if ini_path != '': + # We need the ini mod for determining where to pull the VPs from + ini_mod = repo.IniMod() + ini_mod.load(ini_path) + + if len(ini_mod.get_primary_list()) > 0: + QtWidgets.QMessageBox.critical(None, 'Knossos', self.tr( + 'Ini mods with a primary list are currently not supported for importing!')) + return False - if mtype in ('tool', 'engine'): - pkg.folder = '.' + # This dict will convert a known secondary list entry to a mod.json style dependency + dependency_mapping = { + "mediavps_2014": { + "id": "MVPS", + "version": "3.7.2", + }, + "mediavps_3612": { + "id": "MVPS", + "version": "3.6.12", + }, + "mediavps": { + "id": "MVPS", + "version": "3.6.10", + }, + } - os.mkdir(mod.folder) - pkg_folder = os.path.join(mod.folder, pkg.folder) - if not os.path.isdir(pkg_folder): - os.mkdir(pkg_folder) + package_dependencies = [] - mod.add_pkg(pkg) - mod.save() + for dependency in ini_mod.get_secondary_list(): + dependency = dependency.lower() # The mapping only works for lower case + if dependency not in dependency_mapping: + # An unknown dependency is just skipped + QtWidgets.QMessageBox.warning(None, 'Knossos', + self.tr( + 'The mod.ini dependency %s is not known to Knossos and could not be converted to a mod.json dependency.') + % (dependency)) + continue - center.installed.add_mod(mod) - center.main_win.update_mod_list() + package_dependencies.append(dependency_mapping[dependency]) - return True + task = tasks.VpExtractionTask(mod, ini_mod) + + def finish_import(): + for vp_file in task.get_results(): + base_filename = os.path.basename(vp_file).replace(".vp", "") + + pkg = repo.InstalledPackage({ + 'name': base_filename, + 'status': 'required', + 'folder': base_filename, + 'dependencies': package_dependencies, + 'is_vp': True + }) + mod.add_pkg(pkg) + + center.installed.add_mod(mod) + mod.update_mod_flag() + mod.save() + + center.main_win.update_mod_list() + + task.done.connect(finish_import) + tasks.run_task(task) + + return True + else: + pkg = repo.InstalledPackage({ + 'name': 'Content', + 'status': 'required', + 'folder': 'content' + }) + + if mtype in ('tool', 'engine'): + pkg.folder = '.' + + os.mkdir(mod.folder) + pkg_folder = os.path.join(mod.folder, pkg.folder) + if not os.path.isdir(pkg_folder): + os.mkdir(pkg_folder) + + mod.add_pkg(pkg) + mod.save() + + center.installed.add_mod(mod) + center.main_win.update_mod_list() + + return True @QtCore.Slot(str, str, str, str, result=int) def addPackage(self, mid, version, pkg_name, pkg_folder): @@ -1148,105 +1214,6 @@ def parseIniMod(self, path): mod.load(path) return json.dumps(mod.get()) - @QtCore.Slot(str, str, str, str, str, str, result=bool) - def importIniMod(self, ini_path, name, mid, version, mtype, parent): - if parent != 'FS2': - parent = self._get_mod(parent) - - if parent == -1: - QtWidgets.QMessageBox.critical(None, 'Knossos', self.tr('The selected parent TC is not valid!')) - return False - else: - parent = parent.mid - - mod = repo.InstalledMod({ - 'title': name, - 'id': mid, - 'version': version, - 'type': mtype, - 'parent': parent, - 'dev_mode': True - }) - mod.generate_folder() - - if os.path.isdir(mod.folder): - # TODO: Check online, too? - QtWidgets.QMessageBox.critical(None, 'Knossos', self.tr('There already exists a mod with the chosen ID!')) - return False - - upper_folder = os.path.dirname(mod.folder) - if not os.path.isdir(upper_folder): - logging.error('%s did not exist during mod creation! (parent = %s)' % (mod.folder, mod.parent)) - QtWidgets.QMessageBox.critical(None, 'Knossos', self.tr('The chosen parent does not exist! Something went very wrong here!!')) - return False - - # We need the ini mod for determining where to pull the VPs from - ini_mod = repo.IniMod() - ini_mod.load(ini_path) - - if len(ini_mod.get_primary_list()) > 0: - QtWidgets.QMessageBox.critical(None, 'Knossos', self.tr( - 'Ini mods with a primary list are currently not supported for importing!')) - return False - - # This dict will convert a known secondary list entry to a mod.json style dependency - dependency_mapping = { - "mediavps_2014": { - "id": "MVPS", - "version": "3.7.2", - }, - "mediavps_3612": { - "id": "MVPS", - "version": "3.6.12", - }, - "mediavps": { - "id": "MVPS", - "version": "3.6.10", - }, - } - - package_dependencies = [] - - for dependency in ini_mod.get_secondary_list(): - dependency = dependency.lower() # The mapping only works for lower case - if dependency not in dependency_mapping: - # An unknown dependency is just skipped - QtWidgets.QMessageBox.warning(None, 'Knossos', - self.tr( - 'The mod.ini dependency %s is not known to Knossos and could not be converted to a mod.json dependency.') - % (dependency)) - continue - - package_dependencies.append(dependency_mapping[dependency]) - - task = tasks.VpExtractionTask(mod, ini_mod) - - def finish_import(): - for vp_file in task.get_results(): - base_filename = os.path.basename(vp_file).replace(".vp", "") - - pkg = repo.InstalledPackage({ - 'name': base_filename, - 'status': 'required', - 'folder': base_filename, - 'dependencies': package_dependencies, - 'is_vp': True - }) - mod.add_pkg(pkg) - - center.installed.add_mod(mod) - mod.update_mod_flag() - - mod.save() - - center.main_win.update_mod_list() - - task.done.connect(finish_import) - - tasks.run_task(task) - - return True - if QtWebChannel: BrowserCtrl = WebBridge From bd53804cb73b9cc21d3aaa715f6b8bc7073fd4de Mon Sep 17 00:00:00 2001 From: ngld Date: Sat, 11 Nov 2017 19:55:43 +0100 Subject: [PATCH 26/30] Update the Ubuntu Dockerfile --- releng/ubuntu/Dockerfile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/releng/ubuntu/Dockerfile b/releng/ubuntu/Dockerfile index c9342cbd..a370cb4e 100644 --- a/releng/ubuntu/Dockerfile +++ b/releng/ubuntu/Dockerfile @@ -5,10 +5,10 @@ RUN apt-get update && apt-get upgrade -y && \ python3-six python3-requests python3-requests-toolbelt python3-ply \ python3-semantic-version python3-setuptools python3-pyqt5 python3-pyqt5.qtwebkit \ pyqt5-dev-tools qtbase5-dev-tools libsdl2-2.0-0 libopenal1 p7zip-full \ - ninja-build rsync npm twine python3-wheel gnupg-agent gnupg2 pinentry-tty gdb && \ - useradd -mG sudo packager && \ + ninja-build rsync npm twine python3-wheel gnupg-agent gnupg2 pinentry-tty gdb + +RUN useradd -mG sudo packager && \ echo '%sudo ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers && \ - install -do packager /build && \ - ln -s nodejs /usr/bin/node + install -do packager /build CMD ["/bin/bash"] From 6c7d6908a6b8253d51dbe21bd0dc3c70a7eeb434 Mon Sep 17 00:00:00 2001 From: ngld Date: Sat, 11 Nov 2017 20:12:04 +0100 Subject: [PATCH 27/30] Don't use two variables with the same name in the same function. *facepalm* --- knossos/tasks.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/knossos/tasks.py b/knossos/tasks.py index 24ba1b04..3679a97a 100644 --- a/knossos/tasks.py +++ b/knossos/tasks.py @@ -1471,7 +1471,7 @@ def work(self, p): if not os.path.isdir(dest_base): os.makedirs(dest_base) - files = [] + plan = [] total_size = 0.0 for src_prefix, dirs, files in os.walk(src_path): dest_prefix = os.path.join(dest_path, os.path.relpath(src_prefix, src_path)) @@ -1486,11 +1486,11 @@ def work(self, p): for sub in files: sdest = os.path.join(dest_prefix, sub) ssrc = os.path.join(src_prefix, sub) - files.append((ssrc, sdest)) + plan.append((ssrc, sdest)) total_size += os.stat(ssrc).st_size bytes_done = 0 - for src, dest in files: + for src, dest in plan: progress.update(bytes_done / total_size, os.path.relpath(src, src_path)) shutil.copyfile(src, dest) From da9f57f7ae2e893638b03b876d02e0bd7bffd9b6 Mon Sep 17 00:00:00 2001 From: ngld Date: Sat, 11 Nov 2017 22:12:39 +0100 Subject: [PATCH 28/30] Updated package scripts --- releng/arch/Dockerfile | 2 +- releng/arch/PKGBUILD | 39 ++++++++++++++++++++++++++++++++++++ releng/arch/auto-build.sh | 2 +- releng/macos/provision.sh | 2 +- releng/ubuntu/Dockerfile | 6 +++++- releng/ubuntu/debian/control | 2 +- releng/windows/provision.bat | 2 +- 7 files changed, 49 insertions(+), 6 deletions(-) create mode 100644 releng/arch/PKGBUILD diff --git a/releng/arch/Dockerfile b/releng/arch/Dockerfile index c70b7ed2..f5b7e502 100644 --- a/releng/arch/Dockerfile +++ b/releng/arch/Dockerfile @@ -13,7 +13,7 @@ RUN pacman -Sy --noconfirm archlinux-keyring && \ useradd -mG wheel packager && \ echo '%wheel ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers && \ install -do packager /scratch && \ - sudo -u packager aur -sci --noconfirm --noprogress python-semantic-version && \ + sudo -u packager aur -sci --noconfirm --noprogress python-semantic-version python-token-bucket && \ rm -r /scratch/* && \ sudo -u packager git config --global user.name "$AUR_USER" && \ sudo -u packager git config --global user.email "$AUR_EMAIL" diff --git a/releng/arch/PKGBUILD b/releng/arch/PKGBUILD new file mode 100644 index 00000000..8d13fabe --- /dev/null +++ b/releng/arch/PKGBUILD @@ -0,0 +1,39 @@ +# Maintainer: ngld +_name=knossos +pkgname=fs2-knossos +pkgver=0.6.0 +pkgrel=1 +pkgdesc="A simple mod manager for FreeSpace 2 Open" +arch=('any') +url="https://github.com/ngld/knossos" +license=('Apache') +groups=() +depends=( + 'python' 'python-six' 'python-requests' 'python-requests-toolbelt' 'python-ply' 'python-token-bucket' 'python-pyqt5' 'qt5-webengine' + 'qt5-webchannel' 'python-semantic-version' 'python-raven' 'p7zip' 'openal' 'sdl2' +) +makedepends=('python-setuptools' 'ninja' 'npm') +options=(!emptydirs) +source=( + "https://github.com/ngld/knossos/archive/v${pkgver}.tar.gz" + knossos + knossos.desktop) +md5sums=('d238a3a4f6190f0ed0710652a46c4941' + '541dfc75f3aecbe08b843eeec252e4b4' + 'afd34e2bf9b8f74c1fc5785662e1f04a') + +package() { + cd "$srcdir/${_name}-$pkgver" + + npm install + python configure.py + ninja resources + python setup.py install --root="$pkgdir/" --optimize=1 + + install -Dm755 ../knossos "$pkgdir/usr/bin/knossos" + install -Dm644 LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE" + install -Dm644 NOTICE "$pkgdir/usr/share/licenses/$pkgname/NOTICE" + install -Dm644 ../knossos.desktop "$pkgdir/usr/share/applications/knossos.desktop" +} + +# vim:set ts=2 sw=2 et: diff --git a/releng/arch/auto-build.sh b/releng/arch/auto-build.sh index 13075b34..2363bbe8 100644 --- a/releng/arch/auto-build.sh +++ b/releng/arch/auto-build.sh @@ -20,7 +20,7 @@ if [ "$RELEASE" = "y" ]; then git clone aur@aur.archlinux.org:fs2-knossos.git pkg cd pkg - sed -i -e 's#^pkgver=.*#pkgver='"$VERSION"'#' -e 's#^pkrel=.*#pkgrel=1#' PKGBUILD + sed -e 's#^pkgver=.*#pkgver='"$VERSION"'#' -e 's#^pkrel=.*#pkgrel=1#' < ../PKGBUILD > PKGBUILD updpkgsums mksrcinfo diff --git a/releng/macos/provision.sh b/releng/macos/provision.sh index ad29cdfb..3ed6ba5d 100644 --- a/releng/macos/provision.sh +++ b/releng/macos/provision.sh @@ -34,7 +34,7 @@ sudo installer -store -pkg python.pkg -target / echo "==> Installing Python dependencies" pip3 install -U pip -pip3 install six requests requests_toolbelt ply raven semantic_version PyQt5 PyInstaller +pip3 install six requests requests_toolbelt ply raven semantic_version PyQt5 PyInstaller token_bucket echo "==> Installing SDL2" curl -so SDL2.dmg "https://libsdl.org/release/SDL2-2.0.5.dmg" diff --git a/releng/ubuntu/Dockerfile b/releng/ubuntu/Dockerfile index a370cb4e..456b91f4 100644 --- a/releng/ubuntu/Dockerfile +++ b/releng/ubuntu/Dockerfile @@ -5,7 +5,11 @@ RUN apt-get update && apt-get upgrade -y && \ python3-six python3-requests python3-requests-toolbelt python3-ply \ python3-semantic-version python3-setuptools python3-pyqt5 python3-pyqt5.qtwebkit \ pyqt5-dev-tools qtbase5-dev-tools libsdl2-2.0-0 libopenal1 p7zip-full \ - ninja-build rsync npm twine python3-wheel gnupg-agent gnupg2 pinentry-tty gdb + ninja-build rsync npm twine python3-wheel gnupg-agent gnupg2 pinentry-tty gdb \ + python-software-properties software-properties-common && \ + add-apt-repository ppa:ngld/knossos && \ + apt-get update && \ + apt-get install -y python3-token-bucket RUN useradd -mG sudo packager && \ echo '%sudo ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers && \ diff --git a/releng/ubuntu/debian/control b/releng/ubuntu/debian/control index 7fc408e3..cf745d99 100644 --- a/releng/ubuntu/debian/control +++ b/releng/ubuntu/debian/control @@ -9,7 +9,7 @@ Homepage: https://github.com/ngld/knossos Package: knossos Architecture: all -Depends: ${misc:Depends}, ${python3:Depends}, libsdl2-2.0-0, libopenal1, p7zip-full, python3-pyqt5, python3-pyqt5.qtwebengine, python3-pyqt5.qtwebchannel, python3-requests-toolbelt, python3-ply +Depends: ${misc:Depends}, ${python3:Depends}, libsdl2-2.0-0, libopenal1, p7zip-full, python3-pyqt5, python3-pyqt5.qtwebengine, python3-pyqt5.qtwebchannel, python3-requests-toolbelt, python3-token-bucket, python3-ply Description: Simple mod manager for FreeSpace 2 Open The original idea and prototype were created by Hellzed. ngld rewrote the manager in Python and extended it. diff --git a/releng/windows/provision.bat b/releng/windows/provision.bat index d908bce5..986a5467 100644 --- a/releng/windows/provision.bat +++ b/releng/windows/provision.bat @@ -28,7 +28,7 @@ choco install -y --no-progress --x86 vcredist2010 vcredist2015 nsis echo ::: Installing python dependencies... py -3 -mpip install -U pip -py -3 -mpip install PyQt5 six requests requests_toolbelt ply raven semantic_version pypiwin32 comtypes pyinstaller etaprogress +py -3 -mpip install PyQt5 six requests requests_toolbelt ply raven semantic_version pypiwin32 comtypes pyinstaller etaprogress token_bucket echo ::: Downloading remaining dependencies... py -3 tools/common/download_archive.py releng/windows/support/support.json From c5313969eb45b6e2ff82eb03ede9c7e1ac2997e2 Mon Sep 17 00:00:00 2001 From: ngld Date: Sat, 11 Nov 2017 22:59:29 +0100 Subject: [PATCH 29/30] Fix installer scripts --- releng/windows/nsis/installer.nsi | 4 +++- releng/windows/nsis/updater.nsi | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/releng/windows/nsis/installer.nsi b/releng/windows/nsis/installer.nsi index 69f7c379..dec70a21 100644 --- a/releng/windows/nsis/installer.nsi +++ b/releng/windows/nsis/installer.nsi @@ -15,7 +15,6 @@ !include MUI2.nsh Name "Knossos ${KNOSSOS_VERSION}" -SetShellVarContext all # Install for all users RequestExecutionLevel admin # We need admin for the "fso:// Support" section InstallDir "$PROGRAMFILES\Knossos" InstallDirRegKey HKLM "Software\Knossos" "Install Dir" @@ -77,6 +76,7 @@ Section WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Knossos" "NoRepair" 1 !insertmacro MUI_STARTMENU_WRITE_BEGIN Application + SetShellVarContext all # Install for all users CreateDirectory "$SMPROGRAMS\$StartMenuFolder" CreateShortcut "$SMPROGRAMS\$StartMenuFolder\Knossos.lnk" "$INSTDIR\Knossos.exe" @@ -87,6 +87,7 @@ Section SectionEnd Section "Desktop icon" desk_icon + SetShellVarContext all # Install for all users CreateShortcut "$DESKTOP\Knossos.lnk" "$INSTDIR\Knossos.exe" SectionEnd @@ -96,6 +97,7 @@ SectionEnd Section "Uninstall" !insertmacro MUI_STARTMENU_GETFOLDER Application $StartMenuFolder + SetShellVarContext all # Install for all users Delete "$SMPROGRAMS\$StartMenuFolder\Knossos.lnk" Delete "$SMPROGRAMS\$StartMenuFolder\Launch FSO.lnk" diff --git a/releng/windows/nsis/updater.nsi b/releng/windows/nsis/updater.nsi index 53dfcaa0..ef161d1e 100644 --- a/releng/windows/nsis/updater.nsi +++ b/releng/windows/nsis/updater.nsi @@ -19,7 +19,6 @@ !include nsProcess.nsh Name Knossos -SetShellVarContext all # Install for all users RequestExecutionLevel admin InstallDir "$PROGRAMFILES\Knossos" InstallDirRegKey HKLM "Software\Knossos" "Install Dir" From 932ea4f6ce3806b589b10aef1c260c87d48ac623 Mon Sep 17 00:00:00 2001 From: ngld Date: Sat, 11 Nov 2017 23:10:44 +0100 Subject: [PATCH 30/30] Improve the mod create popup --- html/templates/kn-page.vue | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/html/templates/kn-page.vue b/html/templates/kn-page.vue index c4bbcaf6..2463483f 100644 --- a/html/templates/kn-page.vue +++ b/html/templates/kn-page.vue @@ -456,18 +456,6 @@ export default {
-
- -
- - -

Only use this if you want to convert a legacy mod

-
-
- -
-
-
@@ -484,6 +472,20 @@ export default {
+
+ +
+
+ + + + +
+ +

Only use this if you want to convert a legacy mod! Will update Name and ID fields above.

+
+
+