diff options
39 files changed, 441 insertions, 749 deletions
@@ -7,12 +7,8 @@ build* subprojects/ lang/*.qm -test/plugins.d -publicKey.h +tools/src/crashhandler/defaults.go .config .config.old - -# manpages -smolbote.1 -smolbote.5 +compile_commands.json diff --git a/3rd-party/SingleApplication/SingleApplication.git b/3rd-party/SingleApplication/SingleApplication.git -Subproject c6bc2a3e52701d1a0282bd9e3755a6d01fa629d +Subproject 16ea64b2548b02f59bf49b255466278c3ff0ace diff --git a/3rd-party/breakpad/build.sh b/3rd-party/breakpad/build.sh deleted file mode 100755 index 5e9b1e3..0000000 --- a/3rd-party/breakpad/build.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash - -if [ ! -f breakpad.git/src/third_party/lss/linux_syscall_support.h ]; then - mkdir -p breakpad.git/src/third_party/lss - curl -L https://chromium.googlesource.com/linux-syscall-support/+/master/linux_syscall_support.h?format=TEXT | base64 --decode > breakpad.git/src/third_party/lss/linux_syscall_support.h -fi - -buildpath=$(pwd)/build -if [ ! -d $buildpath ]; then - mkdir $buildpath -fi - -installpath=$(pwd)/install -if [ ! -d $installpath ]; then - mkdir $installpath -fi - -cd $buildpath -../breakpad.git/configure --prefix=$installpath -make -j 2 -make install @@ -205,7 +205,7 @@ menu "Breakpad Integration" config PATH_CRASHHANDLER string "Crash handler location" - default "" + default "poi-crash" endmenu menu "Workarounds" diff --git a/configure b/configure deleted file mode 100755 index fb011b0..0000000 --- a/configure +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/env python3 -import shutil -import os -import subprocess - -def concat_options(default, options=[]): - if not options: - return default - r = '' - for option in options: - if option is default: - r += '*' + option + '* ' - else: - r += option + ' ' - return r.strip() - -def prompt(prompt, default, options=[]): - v = input("{} ({}): ".format(prompt, concat_options(default, options))) - if v is not '': - return v - return default - -if __name__ == "__main__": - # build options - build_dir = prompt('build folder', 'build') - build_type = prompt('build type', 'release', ['plain', 'debug', 'debugoptimized', 'release']) - build_prefix = prompt('prefix', '/usr/local') - - build_pie = prompt('position-independent executable', 'true', ['true', 'false']) - build_lto = prompt('link-time optimization', 'true', ['true', 'false']) - - # feature selection - auto_features = prompt('Feature auto state', 'disabled', ['auto', 'enabled', 'disabled']) - f_breakpad = prompt('Use breakpad', 'disabled', ['enabled', 'disabled']) - f_plasma = prompt('Use plasma', 'disabled', ['enabled', 'disabled']) - f_manpage = prompt('make manpage', 'enabled', ['enabled', 'disabled']) - - # compilers - cc = prompt('C compiler', 'gcc') - cpp = prompt('CPP compiler', 'g++') - ld = prompt('Linker', 'gold') - - # clean build folder - if os.path.isdir(build_dir): - shutil.rmtree(build_dir) - os.mkdir(build_dir, 0o700) - - env = { - **os.environ, - 'CC' : cc, - 'CXX' : cpp - } - # configure build dir - subprocess.run(['meson', '--buildtype={}'.format(build_type), '--prefix={}'.format(build_prefix), '--auto-features={}'.format(auto_features), - '-Db_pie={}'.format(build_pie), '-Db_lto={}'.format(build_lto), '-Dcpp_link_args="-fuse-ld={}"'.format(ld), - '-DBreakpad={}'.format(f_breakpad), '-DPlasma={}'.format(f_plasma), '-Dmanpage={}'.format(f_manpage), - build_dir], env=env, check=True) - - print("\n\n--- Configure step complete ---") - print("For more configuration options run 'meson configure' in the configured build directory.") - print("You can now build with 'ninja -C {}'.".format(build_dir)) - diff --git a/data/poi.cfg b/data/poi.cfg deleted file mode 100644 index f6b2d2c..0000000 --- a/data/poi.cfg +++ /dev/null @@ -1,78 +0,0 @@ -// smolbote default configuration file -// Uses libconfig format, for details refer to: -// https://hyperrealm.github.io/libconfig/libconfig_manual.html#Configuration-Files - -// Browser default settings -browser = { - // default profile name the browser should use; "" is off-the-record - profile = ""; - - // default window size - window = { - height = 720; - width = 1280; - maximized = true; - title = "title — smolbote [profile]"; - }; - - ui = { - navtoolbarMovable = false; - tabtoolbarMovable = false; - }; - - shortcuts = { - // browser menu - newWindow = "Ctrl+N"; - newTab = "Ctrl+T"; - about = "F1"; - quit = "Ctrl+Q"; - - // navigation - back = "Ctrl+Left"; - forward = "Ctrl+Right"; - refresh = "F5"; - reload = "Ctrl+F5"; - //stop = ""; - home = "Ctrl+Home"; - - // tabs - tabClose = "Ctrl+X"; - tabLeft = "Ctrl+O"; - tabRight = "Ctrl+P"; - - // page - toggleSearchBox = "F3"; - focusAddress = "F4"; - fullscreen = "F11"; - }; -}; - -// Filter settings -filter = { - path = "~/.config/smolbote/hosts.d"; -}; - -// Plugin settings -plugins = { - path = "~/.config/smolbote/plugins.d"; -}; - -// Profile settings -profile = { - path = "~/.config/smolbote/profiles.d"; - search = "https://duckduckgo.com/?q=$term&ia=web" - homepage = "about:blank"; - newtab = "about:blank"; -}; - -// Bookmark settings -bookmarks = { - path = "~/.config/smolbote/bookmarks.xbel"; - shortcut = "Ctrl+B"; -}; - -// Downloads settings -downloads = { - path = "~/Downloads" - shortcut = "Ctrl+D"; -}; diff --git a/data/resources.qrc b/data/resources.qrc index 9387efe..b872d19 100644 --- a/data/resources.qrc +++ b/data/resources.qrc @@ -1,5 +1,5 @@ <RCC> <qresource prefix="/"> - <file alias="icon.svg">poi.svg</file> + <file alias="icons/poi.svg">poi.svg</file> </qresource> </RCC> diff --git a/lib/pluginloader/meson.build b/lib/pluginloader/meson.build index b93bf42..cbca725 100644 --- a/lib/pluginloader/meson.build +++ b/lib/pluginloader/meson.build @@ -5,8 +5,9 @@ private_pem = meson.build_root() / get_option('ssl_private_pem') public_pem = meson.build_root() / get_option('ssl_public_pem') publicKey_h = custom_target('publicKey_h', + input: files('ssl-keygen.py'), output: 'publicKey.h', - command: [python3, meson.source_root() / 'tools/ssl-keygen.py', + command: [python3, '@INPUT@', '--private=' + private_pem, '--public=' + public_pem, '--output=@OUTPUT@', '--array-name=publicKey_pem'] ) diff --git a/tools/ssl-keygen.py b/lib/pluginloader/ssl-keygen.py index 555b379..7feaf1a 100755 --- a/tools/ssl-keygen.py +++ b/lib/pluginloader/ssl-keygen.py @@ -13,22 +13,21 @@ def generate_public_key(in_pem='privateKey.pem', out_pem='publicKey.pem'): subprocess.run(['openssl', 'rsa', '-in', in_pem, '-pubout', '-out', out_pem], check=True) def hexdump(array_type, array_name, length_type, in_pem, out_h): - n = 0 + array_len = 0 print("// Autogenerated hex dump of OpenSSL public key, do not edit", file=out_h) print("{} {}[] = {{".format(array_type, array_name), file=out_h) for line in iter(partial(in_pem.read, 16), b''): + array_len += len(line) l = list(line) for n, i in enumerate(l): l[n] = '0x{:02X}'.format(i) print(" {},".format(", ".join(l)), file=out_h) - n += 1 - print("};", file=out_h) - print("{} {}_len = {};".format(length_type, array_name, n), file=out_h) + print("{} {}_len = {};".format(length_type, array_name, array_len), file=out_h) if __name__ == "__main__": parser = argparse.ArgumentParser(description='Generate OpenSSL key and hexdump') diff --git a/linux/.config b/linux/.config deleted file mode 100644 index eea58d5..0000000 --- a/linux/.config +++ /dev/null @@ -1,105 +0,0 @@ -# Generated by Kconfiglib (https://github.com/ulfalizer/Kconfiglib) - -# -# Application -# -CONFIG_POI_NAME="smolbote" -CONFIG_POI_ICON=":/icon.svg" -CONFIG_POI_CFG_PATH="~/.config/smolbote/smolbote.cfg" -# end of Application - -# -# Keyboard shortcuts -# - -# -# Main Window shortcuts -# -CONFIG_shortcuts.session.save="Ctrl+S,S" -CONFIG_shortcuts.session.open="Ctrl+S,O" -CONFIG_shortcuts.window.newgroup="Ctrl+G" -CONFIG_shortcuts.window.newwindow="Ctrl+N" -CONFIG_shortcuts.window.about="Ctrl+H" -CONFIG_shortcuts.window.quit="Ctrl+Q" -CONFIG_shortcuts.window.search="F3" -CONFIG_shortcuts.window.bookmarks.show="Ctrl+B" -CONFIG_shortcuts.window.downloads.show="Ctrl+D" - -# -# Navigation Bar shortcuts -# -CONFIG_shortcuts.navigation.back="Ctrl+Left" -CONFIG_shortcuts.navigation.backmenu="Ctrl+Down" -CONFIG_shortcuts.navigation.forward="Ctrl+Right" -CONFIG_shortcuts.navigation.forwardmenu="Ctrl+Up" -CONFIG_shortcuts.navigation.refresh="F5" -CONFIG_shortcuts.navigation.reload="Ctrl+F5" -CONFIG_shortcuts.navigation.home="Ctrl+Home" - -# -# Address Bar shortcuts -# -CONFIG_shortcuts.address.focus="F4" -CONFIG_shortcuts.address.menu="F2" - -# -# Subwindow shortcuts -# -CONFIG_shortcuts.subwindow.menu="F1" -CONFIG_shortcuts.subwindow.tile="F9" -CONFIG_shortcuts.subwindow.cascade="F10" -CONFIG_shortcuts.subwindow.fullscreen="F11" -CONFIG_shortcuts.subwindow.newtab="Ctrl+T" -CONFIG_shortcuts.subwindow.closetab="Ctrl+X" -CONFIG_shortcuts.subwindow.restoretab="Ctrl+Shift+T" -CONFIG_shortcuts.subwindow.tableft="Ctrl+O" -CONFIG_shortcuts.subwindow.movetableft="Ctrl+Shift+O" -CONFIG_shortcuts.subwindow.tabright="Ctrl+P" -CONFIG_shortcuts.subwindow.movetabright="Ctrl+Shift+P" -# end of Keyboard shortcuts - -# -# Main Window -# -CONFIG_mainwindow.title="smolbote" -CONFIG_mainwindow.width=1280 -CONFIG_mainwindow.height=720 -# end of Main Window - -# -# Profile Settings -# -CONFIG_profile.path="~/.config/smolbote/profiles.d" -CONFIG_profile.default="" -CONFIG_profile.search="https://duckduckgo.com/?q=%1&ia=web" -CONFIG_profile.homepage="about:blank" -CONFIG_profile.newtab="about:blank" -# end of Profile Settings - -CONFIG_USEPLUGINS=y - -# -# Plugin Settings -# -CONFIG_plugins.path="~/.config/smolbote/plugins.d" -# CONFIG_PLUGIN_SIGNATURE_IGNORED is not set -CONFIG_PLUGIN_SIGNATURE_CHECKED=y -# CONFIG_PLUGIN_SIGNATURE_ENFORCED is not set -CONFIG_PLUGIN_SIGNATURE_HASH="SHA256" -# end of Plugin Settings - -# -# Default paths -# -CONFIG_filter.path="~/.config/smolbote/hosts.d" -CONFIG_bookmarks.path="~/.config/smolbote/bookmarks.xbel" -CONFIG_downloads.path="~/Downloads" -CONFIG_session.path="~/.config/smolbote/session.d" -# CONFIG_USEPLASMA is not set -# CONFIG_USEBREAKPAD is not set - -# -# Workarounds -# -CONFIG_QTBUG_65223=y -# end of Workarounds diff --git a/linux/makepkg/PKGBUILD b/linux/makepkg/PKGBUILD index 9243405..debf2f1 100644 --- a/linux/makepkg/PKGBUILD +++ b/linux/makepkg/PKGBUILD @@ -2,8 +2,7 @@ pkgname=smolbote-git pkgdesc='Yet another no-frills browser' - -pkgver=r0 +pkgver=0 pkgrel=1 url="https://neueland.iserlohn-fortress.net/gitea/smolbote" @@ -16,7 +15,7 @@ depends=('qt5-webengine>=5.11.0' 'spdlog') optdepends=('firejail: launch a sandboxed instance') makedepends=('git' 'meson' 'python-kconfiglib' 'openssl' 'qt5-tools' 'scdoc') -# this is the central repository +# use git+file:///path/to/your/repo to build from a local repo source=("git+https://neueland.iserlohn-fortress.net/gitea/aqua/smolbote.git" "git+https://github.com/itay-grudev/SingleApplication.git" "git+https://github.com/Taywee/args") @@ -25,14 +24,9 @@ sha512sums=('SKIP' 'SKIP' 'SKIP') -#validgpgkeys=(# Aqua-sama <aqua@iserlohn-fortress.net> -# BB1C090188E3E32B375C13FD095DE26BC16D2E98) +#validgpgkeys=(BB1C090188E3E32B375C13FD095DE26BC16D2E98) # Aqua-sama <aqua@iserlohn-fortress.net> ## Build Options - -# Run menuconfig -#_menuconfig= - # Enable plugin signing: # meson/ninja will generate the privateKey.pem and publicKey.pem in the $builddir # Because this embeds the public key into the executable, enabling this option will break reproducible builds. @@ -52,9 +46,6 @@ pkgver() { cd smolbote # Without version tag echo r$(git rev-list --count HEAD)-$(git rev-parse --short HEAD) | sed 's/\([^-]*-g\)/r\1/;s/-/./g' - - # With version tag - #git describe --long | sed 's/\([^-]*-g\)/r\1/;s/-/./g' } build() { @@ -72,17 +63,21 @@ build() { # --auto-features=disabled - features should be explicitly enabled # b_pie: Build executables as position independent # b_lto: Use link time optimization - meson --buildtype=plain --prefix=/usr/local --auto-features=disabled \ + meson --buildtype=plain --wrap-mode=nodownload \ + --prefix=/usr/local --auto-features=disabled \ -Db_pie=true -Db_lto=true -Dcpp_link_args="-fuse-ld=gold" \ -Dmanpage=enabled \ $srcdir/build + # uncomment to enable crashhandler + #meson configure -Dcrashhandler=enabled $srcdir/build + #KCONFIG_CONFIG=linux/.config setconfig USEBREAKPAD=y + # Run menuconfig #KCONFIG_CONFIG=linux/.config menuconfig # Build - cd $srcdir/build - ninja + ninja -C $srcdir/build } package() { diff --git a/linux/meson.build b/linux/meson.build new file mode 100644 index 0000000..5b5c79e --- /dev/null +++ b/linux/meson.build @@ -0,0 +1,30 @@ +# application icon +install_data('../data/poi.svg', install_dir: get_option('datadir') / 'icons/hicolor/scalable/apps') + +# firejail profile +install_data('firejail/poi.profile', install_dir: get_option('libdir') / 'smolbote') + +# .desktop files +conf = configuration_data({ + 'exec_poi': get_option('prefix')/get_option('bindir')/get_option('poi'), + 'firejail': get_option('firejail'), + 'firejail_profile': get_option('prefix')/get_option('libdir')/'smolbote/poi.profile' +}) +desktop_files = ['poi.desktop', 'poi_firejail.desktop', 'poi_picksession.desktop'] +desktop_dir = get_option('datadir')/'applications' +foreach f : desktop_files + configure_file(input: f + '.in', output: f, configuration: conf, install_dir: desktop_dir) +endforeach + +# producing debug symbols +if get_option('crashhandler').enabled() +custom_target('poi-sym', + input: poi_exe, + output: 'poi.sym', + capture: true, + command: [ find_program('dump_syms'), '@INPUT@' ], + build_by_default: false, +# install_dir: symbols/poi/$(head -n1 linux/poi.sym | awk '{ print $(NF-1) }') +) +endif + diff --git a/meson.build b/meson.build index 35541c5..6a7518b 100644 --- a/meson.build +++ b/meson.build @@ -1,8 +1,8 @@ -project('smolbote', 'cpp', +project('smolbote', ['cpp'], version: '0.1.0', - default_options: ['cpp_std=c++17', 'strip=true', 'warning_level=3'], + default_options: ['cpp_std=c++17', 'warning_level=3'], license: 'GPL3', - meson_version: '>=0.51.2' + meson_version: '>=0.52.0' ) kconfig = import('unstable-kconfig') @@ -10,21 +10,6 @@ kconf = kconfig.load(host_machine.system() + '/.config') cdata = configuration_data(kconf) -conf_init_list = '\n' -foreach key, value : kconf - n = key.split('_')[1] - if n.contains('.') - if n.endswith('.width') or n.endswith('.height') - conf_init_list += ' { "@0@", @1@ },\n'.format(n.to_lower(), value.to_int()) - else - conf_init_list += ' { "@0@", std::string(@1@) },\n'.format(n.to_lower(), value) - endif - endif -endforeach -cdata.set('conf_init_list', conf_init_list) - -configure_file(input: 'src/conf.hpp.in', output: 'conf.hpp', configuration: cdata) - version_h = vcs_tag( command: [find_program('git').path(), 'describe', '--long', '--abbrev=40'], #fallback: defaults to meson.project_version(), @@ -37,12 +22,13 @@ if not get_option('debug') add_project_arguments('-DQT_NO_DEBUG', language: 'cpp') endif +sourceset = import('sourceset') + cxx = meson.get_compiler('cpp') # add some specific flags add_project_arguments(cxx.get_supported_arguments([ - '-ffunction-sections', # Place each function into its own section - # Leads to better ASLR but larger executables + '-ffunction-sections', # Place each function into its own section, better ASLR but larger executables '-fstack-protector-all', # Emit code to check for buffer overflows on all functions '-fstack-clash-protection', # Emit code to check for stack clash attacks @@ -52,26 +38,22 @@ add_project_arguments(cxx.get_supported_arguments([ '-Wdate-time', # Warn when using __TIME__ and __DATE__ macros '-Wimplicit-fallthrough', ]), language: 'cpp') +add_project_link_arguments(cxx.get_supported_link_arguments([ + '-fuse-ld=gold' +]), language: 'cpp') mod_qt5 = import('qt5') -dep_qt5 = dependency('qt5', modules: ['Core', 'Network', 'Widgets', 'WebEngineWidgets', 'Concurrent']) +dep_qt5 = dependency('qt5', + modules: ['Core', 'Network', 'Widgets', 'WebEngineWidgets', 'Concurrent'], + include_type: 'system' +) dep_spdlog = dependency('spdlog', fallback: ['spdlog', 'spdlog_dep'], version: '>=1.3.1') optional_deps = [] -if get_option('Breakpad').enabled() -optional_deps += declare_dependency(compile_args: '-DBREAKPAD', - dependencies: [dependency('breakpad-client'), dependency('threads')] -) -endif - -if get_option('Plasma').enabled() -optional_deps += declare_dependency(compile_args: '-DPLASMA', - dependencies: [ dependency('KF5WindowSystem', method: 'cmake'), dependency('KF5Wallet', method: 'cmake')] -) -endif - +dep_breakpad = dependency('breakpad-client', include_type: 'system', required: get_option('crashhandler')) +dep_threads = dependency('threads', include_type: 'system', required: get_option('crashhandler')) dep_gtest = dependency('gtest', required: false, disabler: true) # Generate config header @@ -82,6 +64,8 @@ interfaces_moc = mod_qt5.preprocess( dependencies: dep_qt5 ) +poi_sourceset = sourceset.source_set() + subdir('lib/about') subdir('lib/bookmarks') subdir('lib/configuration') @@ -95,9 +79,29 @@ subdir('3rd-party/args') subdir('src') subdir('lang') subdir('doc') +subdir('tools') #subdir('plugins/ConfigurationEditor') subdir('plugins/ProfileEditor') subdir('test/conf') +ssconfig = poi_sourceset.apply(cdata) + +poi_exe = executable(get_option('poi'), + cpp_args: ['-DQAPPLICATION_CLASS=QApplication'], + sources: [ssconfig.sources()], + include_directories: [include, include_directories('src')], + dependencies: [dep_qt5, dep_spdlog, dep_SingleApplication, dep_args, optional_deps, dep_about, dep_bookmarks, dep_configuration, dep_downloads, dep_pluginloader, dep_urlfilter], + install: true, +) + +subdir(host_machine.system()) + +# cppcheck target +cppcheck = find_program('cppcheck', required: false) +if cppcheck.found() +run_target('cppcheck', + command: [cppcheck, '--enable=all', '--project=' + meson.build_root() / 'compile_commands.json'] +) +endif diff --git a/meson_options.txt b/meson_options.txt index 8a3dfea..91f2d0e 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1,18 +1,12 @@ -# Executable options -option('poiName', description: 'Executable name', type: 'string', value: 'poi') -option('firejail', description: 'firejail executable name', type: 'string', value: '/usr/bin/firejail') +option('poi', description: 'Executable name', type: 'string', value: 'poi') +option('firejail', description: 'firejail executable name', type: 'string', value: '/usr/bin/firejail') + +option('manpage', description: 'Generate and install manpage', type: 'feature', value: 'auto') +option('translations', description: 'Generate and install translations', type: 'feature', value: 'auto') +option('crashhandler', description: 'Enable breakpad crash reporting', type: 'feature', value: 'auto') +option('updater', description: 'Build updater component', type: 'feature', value: 'auto') # Build options option('signPlugins', description: 'Generate OpenSSL signing key', type: 'feature', value: 'auto') option('ssl_private_pem', description: 'OpenSSL private key path', type: 'string', value: 'privateKey.pem') option('ssl_public_pem', description: 'OpenSSL public key path', type: 'string', value: 'publicKey.pem') - -# Install options -option('manpage', description: 'Generate and install manpage', type: 'feature', value: 'auto') -option('translations', description: 'Generate and install translations', type: 'feature', value: 'auto') - -# Feature options -option('Breakpad', description: 'Enable breakpad crash reporting', type: 'feature', value: 'auto') -option('Plasma', description: 'Enable KDE plasma integration', type: 'feature', value: 'auto') -option('Python', description: 'Enable Python interpreter', type: 'feature', value: 'auto') - diff --git a/scripts/gen-crashhandler-default-go.py b/scripts/gen-crashhandler-default-go.py new file mode 100755 index 0000000..e080ed9 --- /dev/null +++ b/scripts/gen-crashhandler-default-go.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 + +import sys +import argparse +import kconfiglib +import re + +def findItem(node, name): + while node: + if isinstance(node.item, kconfiglib.Symbol): + if node.item.name == name: + return node.item.str_value + + if node.list: + found = findItem(node.list, name) + if found is not None: + return found + + node = node.next + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("--kconfig", nargs="?", default="Kconfig", help="Top-level Kconfig") + parser.add_argument("--dotconfig", nargs="?", help=".config") + parser.add_argument("--input", type=argparse.FileType('r'), help="default.go.in") + parser.add_argument("--output", type=argparse.FileType('w'), default=sys.stdout, help="Output location") + args = parser.parse_args() + + kconf = kconfiglib.Kconfig(args.kconfig) + if args.dotconfig is not None: + kconf.load_config(args.dotconfig) + + marker = re.compile('.+(@(\w+)@)') + for line in args.input: + found = marker.match(line) + if found: + print(str.replace(line, found.group(1), findItem(kconf.top_node, found.group(2))), end='', file=args.output) + else: + print(line, end='', file=args.output) + diff --git a/scripts/gen-default-cfg.py b/scripts/gen-default-cfg.py new file mode 100755 index 0000000..dc88ceb --- /dev/null +++ b/scripts/gen-default-cfg.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 + +import sys +import argparse +import kconfiglib + +def node_to_str(node): + if(node.item.type == kconfiglib.STRING): + return "std::string(\"" + node.item.str_value + "\")" + elif(node.item.type == kconfiglib.INT): + return "int(" + node.item.str_value + ")" + elif(node.item.type == kconfiglib.BOOL): + tri_val_str = ("false", "unknown", "true")[node.item.tri_value] + return "bool(" + tri_val_str + ")" + + return None + +def writeItem(node, file): + while node: + if isinstance(node.item, kconfiglib.Symbol): + name = node.item.name.lower().replace('_', '.') + print("\t{ \"" + name + "\", " + node_to_str(node) + " },", file=file) + + if node.list: + writeItem(node.list, file) + + node = node.next + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("--kconfig", nargs="?", default="Kconfig", help="Top-level Kconfig") + parser.add_argument("--dotconfig", nargs="?", help=".config") + parser.add_argument("--input", type=argparse.FileType('r'), help="settings.h.in") + parser.add_argument("--output", type=argparse.FileType('w'), default=sys.stdout, help="Output location") + args = parser.parse_args() + + kconf = kconfiglib.Kconfig(args.kconfig) + if args.dotconfig is not None: + kconf.load_config(args.dotconfig) + + print("/* Autogenerated file", file=args.output) + print(" * kconfig: {}".format(args.kconfig), file=args.output) + print(" * dotconfig: {}".format(args.dotconfig), file=args.output) + print(" */", file=args.output) + + for line in args.input: + if "@__DEFAULT_CFG__" in line: + writeItem(kconf.top_node.list, file=args.output) + else: + print(line, end='', file=args.output) diff --git a/tools/list-authors.sh b/scripts/list-authors.sh index 430d4a9..430d4a9 100755 --- a/tools/list-authors.sh +++ b/scripts/list-authors.sh diff --git a/src/browser.cpp b/src/browser.cpp index b3039a5..c3cbd2f 100644 --- a/src/browser.cpp +++ b/src/browser.cpp @@ -9,17 +9,21 @@ #include "browser.h" #include "aboutdialog.h" #include "aboutplugin.h" -#include "mainwindow/addressbar.h" +#include "adblock/adblocklist.h" #include "bookmarkswidget.h" -#include "conf.hpp" #include "configuration.h" #include "downloadswidget.h" +#include "hostlist/hostlist.h" +#include "mainwindow/addressbar.h" #include "mainwindow/mainwindow.h" -#include "webengine/webprofilemanager.h" +#include "mainwindow/menubar.h" #include "subwindow/subwindow.h" +#include "urlfilter.h" #include "util.h" #include "webengine/urlinterceptor.h" #include "webengine/webprofile.h" +#include "webengine/webprofilemanager.h" +#include "webengine/webview.h" #include <QAction> #include <QDir> #include <QFileDialog> @@ -27,30 +31,25 @@ #include <QFileInfoList> #include <QJsonArray> #include <QJsonDocument> +#include <QLibraryInfo> #include <QPluginLoader> #include <QTimer> +#include <QTranslator> #include <QVersionNumber> #include <plugininterface.h> -#include <version.h> -#include "mainwindow/menubar.h" -#include "webengine/webview.h" -#include "urlfilter.h" -#include "adblock/adblocklist.h" -#include "hostlist/hostlist.h" -#include <spdlog/spdlog.h> #include <pluginloader.h> -#include <QLibraryInfo> -#include <QTranslator> +#include <spdlog/spdlog.h> +#include <version.h> Browser::Browser(int &argc, char *argv[], bool allowSecondary) : SingleApplication(argc, argv, allowSecondary, SingleApplication::User | SingleApplication::SecondaryNotification | SingleApplication::ExcludeAppVersion) { - setApplicationName(CONFIG_POI_NAME); - setWindowIcon(QIcon(CONFIG_POI_ICON)); + Configuration conf; + + setApplicationName(conf.value<QString>("poi.name").value()); + setWindowIcon(QIcon(conf.value<QString>("poi.icon").value())); setApplicationVersion(QVersionNumber::fromString(QLatin1String(poi_Version)).toString()); - Configuration conf; - if(const auto _translation = conf.value<QString>("browser.translation")) { auto *translator = new QTranslator(this); if(translator->load(_translation.value())) @@ -70,7 +69,6 @@ Browser::Browser(int &argc, char *argv[], bool allowSecondary) if(auto iconTheme = conf.value<QString>("browser.iconTheme")) { QIcon::setThemeName(iconTheme.value()); } - } Browser::~Browser() @@ -104,7 +102,7 @@ QPair<QString, Profile *> Browser::loadProfile(const QString &id, bool isOffTheR { Configuration conf; - const QString _id = [id](){ + const QString _id = [id]() { // if id contains a separator, it should be a path if(id.contains(QDir::separator())) { return QFileInfo(id).baseName(); @@ -313,7 +311,8 @@ void Browser::addPluginTo(PluginInfo *info, MainWindow *window) }); auto *removeAction = pluginMenu->addAction(tr("Remove")); - connect(removeAction, &QAction::triggered, this, [this, info]() {; + connect(removeAction, &QAction::triggered, this, [this, info]() { + ; m_plugins.removeOne(info); delete info; }); diff --git a/src/conf.hpp.in b/src/conf.hpp.in deleted file mode 100644 index ed97730..0000000 --- a/src/conf.hpp.in +++ /dev/null @@ -1,33 +0,0 @@ -/* - * This file is part of smolbote. It's copyrighted by the contributors recorded - * in the version control history of the file, available from its original - * location: https://neueland.iserlohn-fortress.net/gitea/aqua/smolbote - * - * SPDX-License-Identifier: GPL-3.0 - */ - -#include "configuration.h" -#include <fstream> - -#mesondefine CONFIG_POI_NAME -#mesondefine CONFIG_POI_ICON -#mesondefine CONFIG_POI_CFG_PATH - -#mesondefine CONFIG_QTBUG_65223 - -inline void init_conf(const std::string &path) -{ - auto value_map = std::make_unique<Configuration, std::initializer_list<std::pair<std::string, conf_value_t>>>({ - @conf_init_list@ - }); - - std::fstream fs; - fs.open(path, std::fstream::in); - if(fs.is_open()) { - value_map->read(fs); - fs.close(); - } - - Configuration::move_global(std::move(value_map)); -} - diff --git a/src/main.cpp b/src/main.cpp index 7889c08..f4f2b78 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -8,11 +8,11 @@ #include "browser.h" #include "builtins.h" -#include "conf.hpp" #include "configuration.h" #include "crashhandler.h" #include "session/session.h" #include "session/sessiondialog.h" +#include "settings.h" #include "util.h" #include "version.h" #include <QFile> @@ -91,20 +91,7 @@ int main(int argc, char **argv) return builtins::build(); // create and load configuration - const std::string config_path = [&]() { - std::string path; - if(cmd_config) - path = args::get(cmd_config); - else - path = std::string(CONFIG_POI_CFG_PATH); - - if(path.front() == '~') - path.replace(0, 1, QStandardPaths::writableLocation(QStandardPaths::HomeLocation).toStdString()); - - return path; - }(); - spdlog::debug("Opening config file {}", config_path); - init_conf(config_path); + init_conf(args::get(cmd_config)); if(cmd_args) { const auto front = args::get(cmd_args).front(); diff --git a/src/mainwindow/mainwindow.cpp b/src/mainwindow/mainwindow.cpp index 292d922..558fe49 100644 --- a/src/mainwindow/mainwindow.cpp +++ b/src/mainwindow/mainwindow.cpp @@ -9,15 +9,14 @@ #include "mainwindow.h" #include "addressbar.h" #include "browser.h" -#include "conf.hpp" #include "configuration.h" #include "menubar.h" -#include "webengine/webprofilemanager.h" #include "session/session.h" #include "session/sessiondialog.h" #include "subwindow/subwindow.h" -#include "webengine/webview.h" #include "webengine/webprofile.h" +#include "webengine/webprofilemanager.h" +#include "webengine/webview.h" #include "widgets/dockwidget.h" #include "widgets/navigationbar.h" #include "widgets/searchform.h" @@ -35,9 +34,6 @@ #include <QStatusBar> #include <QToolBar> #include <QUrl> -#ifdef CONFIG_PLASMA_BLUR -#include <KWindowEffects> -#endif MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) @@ -46,11 +42,6 @@ MainWindow::MainWindow(QWidget *parent) m_menuBar = new MenuBar(this); this->setMenuBar(m_menuBar); -#ifdef CONFIG_PLASMA_BLUR - setAttribute(Qt::WA_TranslucentBackground, true); - KWindowEffects::enableBlurBehind(this->winId(), true); -#endif - Configuration config; // create UI diff --git a/src/meson.build b/src/meson.build index 3494112..25f94f0 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,5 +1,13 @@ -# poi -poi_moc = mod_qt5.preprocess( +python = import('python') +python3 = python.find_installation('python3') + +poi_settings_h = custom_target('default_config_value', + input: files('../scripts/gen-default-cfg.py', '../Kconfig', '..'/host_machine.system()/'.config', 'settings.h.in'), + output: 'settings.h', + command: [ python3, '@INPUT0@', '--kconfig=@INPUT1@', '--dotconfig=@INPUT2@', '--input=@INPUT3@', '--output=@OUTPUT@' ] +) + +poi_sourceset.add(mod_qt5.preprocess( moc_headers: ['browser.h', 'mainwindow/mainwindow.h', 'mainwindow/addressbar.h', 'mainwindow/menubar.h', 'mainwindow/widgets/completer.h', 'mainwindow/widgets/urllineedit.h', 'mainwindow/widgets/dockwidget.h', 'mainwindow/widgets/menusearch.h', 'mainwindow/widgets/navigationbar.h', 'mainwindow/widgets/searchform.h', 'session/savesessiondialog.h', 'session/sessiondialog.h', 'session/sessionform.h', @@ -9,14 +17,10 @@ poi_moc = mod_qt5.preprocess( qresources: '../data/resources.qrc', rcc_extra_arguments: ['--format-version=1'], dependencies: dep_qt5 -) +)) -poi = executable(get_option('poiName'), install: true, - cpp_args: ['-DQAPPLICATION_CLASS=QApplication'], - dependencies: [dep_qt5, dep_spdlog, dep_SingleApplication, dep_args, optional_deps, - dep_about, dep_bookmarks, dep_configuration, dep_downloads, dep_pluginloader, dep_urlfilter], - include_directories: [include], - sources: ['main.cpp', 'builtins.cpp', 'crashhandler.cpp', poi_moc, version_h, +poi_sourceset.add(files( + 'main.cpp', 'builtins.cpp', 'crashhandler.cpp', 'browser.cpp', 'util.cpp', 'util.h', @@ -43,29 +47,9 @@ poi = executable(get_option('poiName'), install: true, 'webengine/webview.cpp', 'webengine/webprofile.cpp', 'webengine/webprofilemanager.cpp', - interfaces_moc, - 'wallet/wallet.cpp', 'wallet/wallet.h'] + 'wallet/wallet.cpp', 'wallet/wallet.h' +), + interfaces_moc, version_h, poi_settings_h ) -# install .desktop file and firejail profile for systems in this array -if ['linux'].contains(host_machine.system()) - conf = configuration_data({ - 'exec_poi': get_option('prefix') / get_option('bindir') / get_option('poiName'), - 'firejail': get_option('firejail'), - 'firejail_profile': get_option('prefix') / get_option('libdir') / 'smolbote/poi.profile' - }) - - # application icon - install_data('../data/poi.svg', install_dir: get_option('datadir') / 'icons/hicolor/scalable/apps') - - # firejail profile - install_data('../linux/firejail/poi.profile', install_dir: get_option('libdir') / 'smolbote') - - # Install .desktop to $prefix/share/applications - desktop_install_dir = get_option('datadir') / 'applications' - configure_file(input: '../linux/poi.desktop.in', output: 'poi.desktop', configuration: conf, install_dir: desktop_install_dir ) - configure_file(input: '../linux/poi_firejail.desktop.in', output: 'poi_firejail.desktop', configuration: conf, install_dir: desktop_install_dir ) - configure_file(input: '../linux/poi_picksession.desktop.in', output: 'poi_picksession.desktop', configuration: conf, install_dir: desktop_install_dir ) - -endif diff --git a/src/settings.h.in b/src/settings.h.in new file mode 100644 index 0000000..a4b5159 --- /dev/null +++ b/src/settings.h.in @@ -0,0 +1,29 @@ +#pragma once + +#include <QStandardPaths> +#include <configuration.h> +#include <fstream> + +inline void init_conf(const std::string &path) +{ + + const std::string cfgpath = [&]() { + auto p = path; + if(p.front() == '~') + p.replace(0, 1, QStandardPaths::writableLocation(QStandardPaths::HomeLocation).toStdString()); + return p; + }(); + + auto value_map = std::make_unique<Configuration, std::initializer_list<std::pair<std::string, conf_value_t>>>({ + @__DEFAULT_CFG__ + }); + + std::fstream fs; + fs.open(path, std::fstream::in); + if(fs.is_open()) { + value_map->read(fs); + fs.close(); + } + + Configuration::move_global(std::move(value_map)); +} diff --git a/src/webengine/webview.cpp b/src/webengine/webview.cpp index 930b747..4fa227f 100644 --- a/src/webengine/webview.cpp +++ b/src/webengine/webview.cpp @@ -8,7 +8,6 @@ #include "webview.h" #include "browser.h" -#include "conf.hpp" #include "subwindow/subwindow.h" #include "wallet/wallet.h" #include "webpage.h" @@ -57,13 +56,12 @@ WebView::WebView(WebProfile *profile, QWidget *parent) m_loaded = true; }); -#ifdef CONFIG_QTBUG_65223 + // TODO for Qt 5.15, check for fix on QTBUG 65223 connect(this, &QWebEngineView::loadProgress, this, [this](int progress) { if(progress == 100) { emit loadFinished(true); } }); -#endif } void WebView::setProfile(WebProfile *profile) diff --git a/subprojects/spdlog.wrap b/subprojects/spdlog.wrap index 9dac4d8..b0f760b 100644 --- a/subprojects/spdlog.wrap +++ b/subprojects/spdlog.wrap @@ -1,10 +1,10 @@ [wrap-file] -directory = spdlog-1.3.1 +directory = spdlog-1.4.2 -source_url = https://github.com/gabime/spdlog/archive/v1.3.1.tar.gz -source_filename = v1.3.1.tar.gz -source_hash = 160845266e94db1d4922ef755637f6901266731c4cb3b30b45bf41efa0e6ab70 +source_url = https://github.com/gabime/spdlog/archive/v1.4.2.tar.gz +source_filename = v1.4.2.tar.gz +source_hash = 821c85b120ad15d87ca2bc44185fa9091409777c756029125a02f81354072157 -patch_url = https://wrapdb.mesonbuild.com/v1/projects/spdlog/1.3.1/1/get_zip -patch_filename = spdlog-1.3.1-1-wrap.zip -patch_hash = 715a0229781019b853d409cc0bf891ee4b9d3a17bec0cf87f4ad30b28bbecc87 +patch_url = https://wrapdb.mesonbuild.com/v1/projects/spdlog/1.4.2/1/get_zip +patch_filename = spdlog-1.4.2-1-wrap.zip +patch_hash = e0616f2a956670b0b23daba08f14d4f51a9551e74071269bc218cd05b666b229 diff --git a/tools/check-license.rb b/tools/check-license.rb deleted file mode 100755 index 8eeb6bb..0000000 --- a/tools/check-license.rb +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env ruby - -result = 0 -files = Dir.glob("src/**/*.h") + Dir.glob("src/**/*.cpp") \ - + Dir.glob("lib/**/*.h") + Dir.glob("lib/**/*.cpp") \ - + Dir.glob("plugins/**/*.h") + Dir.glob("plugins/**/*.cpp") - -puts 'Checking licenses...' -files.each { |name| - File.open(name) { |file| - if file.grep(/SPDX-License-Identifier/).empty? then - puts "Missing or incorrect license header: #{name}" - result += 1 - end - } -} - -exit result diff --git a/tools/deploy/get-latest-builds.sh b/tools/deploy/get-latest-builds.sh deleted file mode 100755 index fc3046d..0000000 --- a/tools/deploy/get-latest-builds.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash - -echo Get build information -curl -o project-meta.json -H "Content-Type: application/json" https://ci.appveyor.com/api/projects/XianNox/smolbote-hg - -commit=$(jq -r .build.commitId project-meta.json) -echo Build commit: $commit - -for (( i=0; i<$(jq -r '.build.jobs | length' project-meta.json); i++ )) -do - jobId=$(jq -r .build.jobs[$i].jobId project-meta.json) - osType=$(jq -r .build.jobs[$i].osType project-meta.json) - - echo Downloading $jobId-$osType - curl -o smolbote-nightly-$commit-$osType.7z -L https://ci.appveyor.com/api/buildjobs/$jobId/artifacts/smolbote.7z - - echo Extracting package - 7za x smolbote-nightly-$commit-$osType.7z smolbote-install/bin - mv smolbote-nightly-$commit-$osType.7z serve/ - mv smolbote-install/bin serve/smolbote-$commit-$osType - rm -r smolbote-install -done - diff --git a/tools/format-code.sh b/tools/format-code.sh deleted file mode 100755 index 68be1d8..0000000 --- a/tools/format-code.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -# get names of staged files | filter out the header and cpp files | clang-format them -git diff --staged --name-only | grep --regex="\.h\|\.cpp" | xargs clang-format -i diff --git a/tools/gpgkey.preset b/tools/gpgkey.preset deleted file mode 100644 index c33c12c..0000000 --- a/tools/gpgkey.preset +++ /dev/null @@ -1,18 +0,0 @@ -# https://www.gnupg.org/documentation/manuals/gnupg/Unattended-GPG-key-generation.html -# To generate key: gpg2 --homedir=gpg-fakehome --batch --generate-key --expert gpgkey.preset -# To list key: gpg2 --homedir=gpg-fakehome --list-keys -%echo Generating GPG key (ed25519-sign) - -Key-Type: EdDSA -Key-Curve: ed25519 -Key-Length: 256 -Key-Usage: sign - -Name-Real: smolbote build process -Name-Email: smolbote@localhost - -Passphrase: null - -%commit -%echo Generating key done - diff --git a/tools/meson.build b/tools/meson.build new file mode 100644 index 0000000..fd1547e --- /dev/null +++ b/tools/meson.build @@ -0,0 +1,36 @@ +if get_option('crashhandler').enabled() or get_option('updater').enabled() + go = find_program('go', required: true) + go_args = [ '-buildmode=pie' ] +endif + +if get_option('crashhandler').enabled() + +# normally, you'd use configure_file to create this file, but that would only place it in build, +# and go will refuse to build from files in two different directories +meson.add_postconf_script(meson.source_root()/'scripts/gen-crashhandler-default-go.py', + '--kconfig=' + meson.source_root()/'Kconfig', + '--dotconfig=' + meson.source_root()/host_machine.system()/'.config', + '--input=' + meson.current_source_dir()/'src/crashhandler/defaults.go.in', + '--output=' + meson.current_source_dir()/'src/crashhandler/defaults.go' +) + +custom_target('poi-crash', + input: [ files('src/updater/main.go'), meson.current_source_dir()/'src/crashhandler/defaults.go' ], + output: 'poi-crash', + command: ['env', 'GOPATH='+meson.current_source_dir(), go, 'build', go_args, '-o=@OUTPUT@', 'crashhandler'], + build_by_default: true, + install: true, + install_dir: get_option('bindir'), +) +endif + +if get_option('updater').enabled() +custom_target('poi-update', + input: files('src/updater/main.go'), + output: 'poi-update', + command: ['env', 'GOPATH='+meson.current_source_dir(), go, 'build', go_args, '-o=@OUTPUT@', 'updater'], + build_by_default: true, + install: true, + install_dir: get_option('bindir'), +) +endif diff --git a/tools/report-clang-tidy.sh b/tools/report-clang-tidy.sh deleted file mode 100755 index eddb703..0000000 --- a/tools/report-clang-tidy.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -cp build/compile_commands.json tidy/compile_commands.json - -# https://bugs.llvm.org/show_bug.cgi?id=37315 -sed -i 's/-pipe//g' tidy/compile_commands.json -# do not scan system headers (replace -I with -isystem) -sed -i 's/\-I\/usr\/include/\-isystem\/usr\/include/g' tidy/compile_commands.json - -for folder in $(find src lib -type d) -do - if [[ $folder != *'test' ]]; then - clang-tidy -p tidy $folder/*.cpp $folder/*.h > reports/clangtidy-$(basename $folder).txt - fi -done - diff --git a/tools/report-cppcheck.sh b/tools/report-cppcheck.sh deleted file mode 100755 index 2e42226..0000000 --- a/tools/report-cppcheck.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -cppcheck --enable=all --project=tidy/compile_commands.json 2> report.txt - diff --git a/tools/src/crashhandler/defaults.go.in b/tools/src/crashhandler/defaults.go.in new file mode 100644 index 0000000..2ea5827 --- /dev/null +++ b/tools/src/crashhandler/defaults.go.in @@ -0,0 +1,4 @@ +package main + +var dumpPath = "@PATH_CRASHDUMP@" + diff --git a/tools/src/crashhandler/main.go b/tools/src/crashhandler/main.go new file mode 100644 index 0000000..00ce0cd --- /dev/null +++ b/tools/src/crashhandler/main.go @@ -0,0 +1,79 @@ +package main + +import ( + "flag" + "fmt" + "io/ioutil" + "os" + "strings" +) + +type CrashDump struct { + Name string + DumpPath string + MetadataPath string +} + +func expandHomeDir(path string) (string, error) { + home, err := os.UserHomeDir() + if err != nil { + return path, err + } + + return strings.Replace(path, "~/", home, -1), nil +} + +func dumps(path string) ([]CrashDump, error) { + files, err := ioutil.ReadDir(path) + if err != nil { + return nil, err + } + + var crashes []CrashDump + + for i, file := range files { + if strings.HasSuffix(file.Name(), ".dmp") { + if i+1 < len(files) && files[i+1].Name() == file.Name()+".txt" { + crashes = append(crashes, CrashDump{Name: strings.TrimSuffix(file.Name(), ".dmp"), + DumpPath: file.Name(), MetadataPath: files[i+1].Name()}) + } else { + crashes = append(crashes, CrashDump{Name: strings.TrimSuffix(file.Name(), ".dmp"), DumpPath: file.Name()}) + } + } + } + + return crashes, nil +} + +func main() { + helpFlag := flag.Bool("help", false, "Show help information.") + flag.StringVar(&dumpPath, "crashd", dumpPath, "Crash dump path") + + // create crash report flags + crashedFlag := flag.String("c", "", "Create crash report at specified location and write any specified data into it") + + flag.Parse() + dumpPath, _ = expandHomeDir(dumpPath) + + if *helpFlag { + flag.PrintDefaults() + return + } + + if *crashedFlag != "" { + fmt.Println("Creating crash dump report", *crashedFlag) + contents := []byte("Additional information: " + strings.Join(flag.Args(), "")) + ioutil.WriteFile(*crashedFlag+".txt", contents, 0644) + return + } + + fmt.Printf("[%s]\n", dumpPath) + c, err := dumps(dumpPath) + if err != nil { + panic(err) + } + for _, d := range c { + fmt.Printf("\t- %s\n", d.Name) + } + +} diff --git a/tools/src/updater/main.go b/tools/src/updater/main.go new file mode 100644 index 0000000..e6e1560 --- /dev/null +++ b/tools/src/updater/main.go @@ -0,0 +1,47 @@ +package main + +import ( + "flag" + "fmt" + "net/http" + "encoding/json" + "io/ioutil" +) + +func main() { + helpFlag := flag.Bool("help", false, "Show help information") + //verboseFlag := flag.Bool("verbose", false, "Print more information") + //repoFlag := flag.String("repo", "https://neueland.iserlohn-fortress.net/smolbote/downloads", "Repository path") + //dryRunFlag := flag.Bool("dry-run", false, "Dry run: only check files, do not download") + + flag.Parse() + + branchesRequest := "https://neueland.iserlohn-fortress.net/gitea/api/v1/repos/aqua/smolbote/branches" + + // help flag --> show usage and exit + if *helpFlag { + flag.PrintDefaults() + return + } + + response, err := http.Get(branchesRequest) + if err != nil { + panic(err) + } else if response.StatusCode != 200 { + fmt.Printf("Could not get manifest: %s\n", response.Status) + return + } + defer response.Body.Close() + + body, _ := ioutil.ReadAll(response.Body) + + var branches []BranchResponse + json.Unmarshal(body, &branches) + + + for _,v := range(branches) { + fmt.Printf("%s\t%s %s\n", v.Name, v.Commit.ID, v.Commit.Timestamp) + } + fmt.Println("done") + +} diff --git a/tools/src/updater/manifest.go b/tools/src/updater/manifest.go new file mode 100644 index 0000000..f9d3d86 --- /dev/null +++ b/tools/src/updater/manifest.go @@ -0,0 +1,16 @@ +package main + +import ( + "time" +) + +type CommitResponse struct { + ID string `json:"id"` + Timestamp time.Time `json:"timestamp"` +} + +type BranchResponse struct { + Name string `json:"name"` + Commit CommitResponse `json:"commit"` +} + diff --git a/tools/updater/download.go b/tools/updater/download.go deleted file mode 100644 index 8c9de9a..0000000 --- a/tools/updater/download.go +++ /dev/null @@ -1,88 +0,0 @@ -package main - -import ( - "fmt" - "io" - "net/http" - "os" - "path/filepath" - "strings" -) - -func Min(x, y int64) int64 { - if x < y { - return x - } - return y -} - -func Max(x, y int64) int64 { - if x > y { - return x - } - return y -} - -// WriteCounter counts the number of bytes written to it -type WriteCounter struct { - ContentLength int64 - BytesWritten uint64 - - Step int64 -} - -func NewWriteCounter(contentLength int64) *WriteCounter { - ptr := new(WriteCounter) - ptr.ContentLength = contentLength - ptr.Step = Max(contentLength/20, 1) - - return ptr -} - -func (wc *WriteCounter) Write(p []byte) (int, error) { - n := len(p) - wc.BytesWritten += uint64(n) - wc.PrintProgress() - return n, nil -} - -func (wc *WriteCounter) PrintProgress() { - // clear the line by using a character return to go back to the start of the - // line and remove the remaining characters - fmt.Printf("\r%s", strings.Repeat(" ", 35)) - - // steps can be at most 20 -> get the minimum of (n_steps) and 20 - steps := int(Min(int64(wc.BytesWritten)/wc.Step, 20)) - - fmt.Printf("\r[%s%s] %d/%d bytes complete", strings.Repeat("#", steps), strings.Repeat(" ", 20-steps), wc.BytesWritten, wc.ContentLength) -} - -func downloadFile(path string, url string) error { - // make sure dir exists - os.MkdirAll(filepath.Dir(path), 0755) - - // create .part file - output, err := os.Create(path + ".part") - if err != nil { - return err - } - defer output.Close() - - // get data - response, err := http.Get(url) - if err != nil { - return err - } - defer response.Body.Close() - - // create progress reporter - counter := NewWriteCounter(response.ContentLength) - _, err = io.Copy(output, io.TeeReader(response.Body, counter)) - if err != nil { - return err - } - - fmt.Printf("\n") - output.Close() - return os.Rename(path+".part", path) -} diff --git a/tools/updater/main.go b/tools/updater/main.go deleted file mode 100644 index baef1f1..0000000 --- a/tools/updater/main.go +++ /dev/null @@ -1,77 +0,0 @@ -package main - -import ( - "bufio" - "flag" - "fmt" - "net/http" - "os" - "runtime" - "strings" -) - -func fail(err error) { - fmt.Printf("An error has occurred:\n%s\n", err.Error()) - if runtime.GOOS == "windows" { - fmt.Print("Press 'Enter' to continue...") - fmt.Scanln() - } - os.Exit(-1) -} - -func main() { - helpFlag := flag.Bool("help", false, "Show help information") - verboseFlag := flag.Bool("verbose", false, "Print more information") - repoFlag := flag.String("repo", "https://neueland.iserlohn-fortress.net/smolbote/downloads", "Repository path") - platformFlag := flag.String("platform", runtime.GOOS, "Platform") - dryRunFlag := flag.Bool("dry-run", false, "Dry run: only check files, do not download") - - flag.Parse() - - manifestPath := fmt.Sprintf("%s/%s-sha512.txt", *repoFlag, *platformFlag) - repoPath := fmt.Sprintf("%s/%s/", *repoFlag, *platformFlag) - - // help flag --> show usage and exit - if *helpFlag { - fmt.Println("Usage:") - flag.PrintDefaults() - - fmt.Println("Paths:") - fmt.Println(" manifest ", manifestPath) - fmt.Println(" repository ", repoPath) - return - } - - response, err := http.Get(manifestPath) - if err != nil { - fail(err) - } else if response.StatusCode != 200 { - fmt.Printf("Could not get manifest: %s\n", response.Status) - return - } - defer response.Body.Close() - - // read through manifest - scanner := bufio.NewScanner(response.Body) - for scanner.Scan() { - s := strings.Split(scanner.Text(), " ") - - filepath := s[1] - checksum := s[0] - - if same, err := checkFile(filepath, checksum); err != nil { - fail(err) - } else { - if *verboseFlag { - fmt.Printf("[%s]: %t\n", filepath, same) - } - - if !same && !*dryRunFlag { - if err := downloadFile(filepath, repoPath+filepath); err != nil { - fail(err) - } - } - } - } - -} diff --git a/tools/updater/manifest.go b/tools/updater/manifest.go deleted file mode 100644 index 0d8bfae..0000000 --- a/tools/updater/manifest.go +++ /dev/null @@ -1,41 +0,0 @@ -package main - -import ( - "crypto/sha512" - "fmt" - "io" - "os" -) - -func checkFile(filepath string, checksum string) (bool, error) { - if _, err := os.Stat(filepath); os.IsNotExist(err) { - return false, nil - } - - // file exists, check checksum - lsum, err := hash(filepath) - if err != nil { - return false, err - } - - if checksum != fmt.Sprintf("%x", lsum) { - return false, nil - } - - return true, nil -} - -func hash(filepath string) ([]byte, error) { - file, err := os.Open(filepath) - if err != nil { - return nil, err - } - defer file.Close() - - hasher := sha512.New() - if _, err := io.Copy(hasher, file); err != nil { - return nil, err - } - - return hasher.Sum(nil), nil -} |