From 5fd8ae208699f6d8dab636611f56ac55cf0397e1 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Sat, 18 Nov 2023 12:05:05 +0100 Subject: [PATCH 01/10] Move fallback version to VERSION file Previously, if not installed and no git version could be deduced, a hardcoded 3.0.2 version was used. Now, this fallback version is moved into an external VERSION file and is changed to "unreleased" instead of "3.0.2", to ensure that a proper version is only returned when it is really correct. This also makes it easier to update the version number for releases, and prepares for having a single place in the code to store the release version. --- src/hamster/VERSION | 1 + src/hamster/__init__.py | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 src/hamster/VERSION diff --git a/src/hamster/VERSION b/src/hamster/VERSION new file mode 100644 index 000000000..54ae09e0c --- /dev/null +++ b/src/hamster/VERSION @@ -0,0 +1 @@ +unreleased diff --git a/src/hamster/__init__.py b/src/hamster/__init__.py index 533e1c2bb..2ef37022f 100644 --- a/src/hamster/__init__.py +++ b/src/hamster/__init__.py @@ -18,7 +18,17 @@ # if defs is not there, we are running from sources from subprocess import getstatusoutput rc, output = getstatusoutput("git describe --tags --always --dirty=+") - __version__ = "3.0.2" if rc else "{} (uninstalled)".format(output) + if rc == 0: + # If available, prefer the git version, otherwise fall back to + # the VERSION file (which is meaningful only in released + # versions) + __version__ = "{} (uninstalled)".format(output) + else: + from pathlib import Path + with open(Path(__file__).parent / 'VERSION', 'r') as f: + __version__ = f.read() + del Path + installed = False del getstatusoutput, rc, output From 5dc10748540766156e284c93414afe85de7a8f22 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Sat, 18 Nov 2023 12:13:33 +0100 Subject: [PATCH 02/10] Move version detection into its own file This prepares for using this code from waf, since it can now be imported without additional (gtk) dependencies. --- src/hamster/__init__.py | 25 +++---------------------- src/hamster/version.py | 31 +++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 22 deletions(-) create mode 100644 src/hamster/version.py diff --git a/src/hamster/__init__.py b/src/hamster/__init__.py index 2ef37022f..4970a59f3 100644 --- a/src/hamster/__init__.py +++ b/src/hamster/__init__.py @@ -5,33 +5,14 @@ from gi.repository import Gtk as gtk from hamster.lib import default_logger +from hamster.version import get_version logger = default_logger(__name__) -try: - # defs.py is created by waf from defs.py.in - from hamster import defs - __version__ = defs.VERSION - installed = True -except ImportError: - # if defs is not there, we are running from sources - from subprocess import getstatusoutput - rc, output = getstatusoutput("git describe --tags --always --dirty=+") - if rc == 0: - # If available, prefer the git version, otherwise fall back to - # the VERSION file (which is meaningful only in released - # versions) - __version__ = "{} (uninstalled)".format(output) - else: - from pathlib import Path - with open(Path(__file__).parent / 'VERSION', 'r') as f: - __version__ = f.read() - del Path - - installed = False - del getstatusoutput, rc, output +(__version__, installed) = get_version() # cleanup namespace +del get_version del default_logger del gtk # performance is retained diff --git a/src/hamster/version.py b/src/hamster/version.py new file mode 100644 index 000000000..f10a73240 --- /dev/null +++ b/src/hamster/version.py @@ -0,0 +1,31 @@ +# Should not normally be used directly, use hamster.__version__ and +# hamster.installed instead + +def get_version(): + """ + Figure out the hamster version. + + Returns a tuple with the version string and wether we are installed or not. + """ + + try: + # defs.py is created by waf from defs.py.in + from hamster import defs + version = defs.VERSION + installed = True + except ImportError: + # if defs is not there, we are running from sources + installed = False + + # If available, prefer the git version, otherwise fall back to + # the VERSION file (which is meaningful only in released + # versions) + from subprocess import getstatusoutput + rc, output = getstatusoutput("git describe --tags --always --dirty=+") + if rc == 0: + version = "{} (uninstalled)".format(output) + else: + from pathlib import Path + with open(Path(__file__).parent / 'VERSION', 'r') as f: + version = f.read() + return (version, installed) From 99cef0564a5bdf9cd80a4f3f1688d633714db407 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Sat, 18 Nov 2023 12:33:49 +0100 Subject: [PATCH 03/10] Remove duplicated version detection code from waf/wscript This allows running the src/hamster/version.py file as a standalone script that just outputs the version number and lets wscript call that. This ensures that the exact same version number is used between installed and non-installed versions, and removes the second place where the release version was previously hardcoded. To do this, the version.py code is split into a part that decides the version when installed, and a bit that decides the version when running from the source tree. This is needed since when running the script from waf, sys.path is not set up to allow importing hamster.defs, and trying this might result in importing hamster.defs from a system-wide installed hamster instead of the current source dir. So just skip the installed-version detection entirely when running from waf, it is not relevant anyway. --- src/hamster/version.py | 56 ++++++++++++++++++++++++++---------------- wscript | 10 +++----- 2 files changed, 39 insertions(+), 27 deletions(-) diff --git a/src/hamster/version.py b/src/hamster/version.py index f10a73240..b7ae5c01a 100644 --- a/src/hamster/version.py +++ b/src/hamster/version.py @@ -1,6 +1,28 @@ # Should not normally be used directly, use hamster.__version__ and # hamster.installed instead +def get_installed_version(): + try: + # defs.py is created by waf from defs.py.in + from hamster import defs + return defs.VERSION + except ImportError: + # if defs is not there, we are running from sources + return None + +def get_uninstalled_version(): + # If available, prefer the git version, otherwise fall back to + # the VERSION file (which is meaningful only in released + # versions) + from subprocess import getstatusoutput + rc, output = getstatusoutput("git describe --tags --always --dirty=+") + if rc == 0: + return output + else: + from pathlib import Path + with open(Path(__file__).parent / 'VERSION', 'r') as f: + return f.read() + def get_version(): """ Figure out the hamster version. @@ -8,24 +30,16 @@ def get_version(): Returns a tuple with the version string and wether we are installed or not. """ - try: - # defs.py is created by waf from defs.py.in - from hamster import defs - version = defs.VERSION - installed = True - except ImportError: - # if defs is not there, we are running from sources - installed = False - - # If available, prefer the git version, otherwise fall back to - # the VERSION file (which is meaningful only in released - # versions) - from subprocess import getstatusoutput - rc, output = getstatusoutput("git describe --tags --always --dirty=+") - if rc == 0: - version = "{} (uninstalled)".format(output) - else: - from pathlib import Path - with open(Path(__file__).parent / 'VERSION', 'r') as f: - version = f.read() - return (version, installed) + version = get_installed_version() + if version is not None: + return (version, True) + + version = get_uninstalled_version() + return ("{} (uninstalled)".format(version), False) + + +if __name__ == '__main__': + import sys + # Intended to be called by waf when installing, so only return + # uninstalled version + sys.stdout.write(get_uninstalled_version()) diff --git a/wscript b/wscript index 292408d72..cf89a7889 100644 --- a/wscript +++ b/wscript @@ -1,15 +1,13 @@ # -*- python -*- -from subprocess import getstatusoutput +import subprocess from waflib import Utils - -# slight code duplication with hamster/__init__.py, but this is finally cleaner. -rc, output = getstatusoutput("git describe --tags --always --dirty=+") -VERSION = "3.0.2" if rc else output - +# Reuse code from hamster to figure out the version number to use +process = subprocess.run(["python3", "src/hamster/version.py"], check=True, stdout=subprocess.PIPE, text=True) +VERSION = process.stdout APPNAME = 'hamster' top = '.' From e9a6a357aff855236633a7b5722fae770127e428 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Sat, 18 Nov 2023 13:36:44 +0100 Subject: [PATCH 04/10] Strip v prefix when using git tag as version number Released versions omitted the v prefix (to make proper semantic versions), but version numbers autodetected from git would not, leading to discrepancies. This fixes that. --- src/hamster/version.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/hamster/version.py b/src/hamster/version.py index b7ae5c01a..1a3d8189b 100644 --- a/src/hamster/version.py +++ b/src/hamster/version.py @@ -17,7 +17,9 @@ def get_uninstalled_version(): from subprocess import getstatusoutput rc, output = getstatusoutput("git describe --tags --always --dirty=+") if rc == 0: - return output + import re + # Strip "v" prefix that is used in git tags + return re.sub(r'^v', '', output) else: from pathlib import Path with open(Path(__file__).parent / 'VERSION', 'r') as f: From 9ac904b7fb1ef8517824b9d50b2b7ebc1460bf7b Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Sat, 18 Nov 2023 13:10:38 +0100 Subject: [PATCH 05/10] Drop .GUI from metainfo.xml file This file is mostly used by packaging tools, such as flatpak, to get info about the application. Since flatpak uses org.gnome.Hamster as the main package id, the metainfo.xml must be named the same for it to be used. Possibly more things need to be renamed for all application ids to be consistent, but it is non-obvious what the best approach is there (see also #725 for details). For now, this pragmatically renames metainfo.xml to ensure it is found by flatpak. --- ....Hamster.GUI.metainfo.xml => org.gnome.Hamster.metainfo.xml} | 2 +- data/wscript | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename data/{org.gnome.Hamster.GUI.metainfo.xml => org.gnome.Hamster.metainfo.xml} (98%) diff --git a/data/org.gnome.Hamster.GUI.metainfo.xml b/data/org.gnome.Hamster.metainfo.xml similarity index 98% rename from data/org.gnome.Hamster.GUI.metainfo.xml rename to data/org.gnome.Hamster.metainfo.xml index 9e19087b5..2d6747094 100644 --- a/data/org.gnome.Hamster.GUI.metainfo.xml +++ b/data/org.gnome.Hamster.metainfo.xml @@ -1,6 +1,6 @@ - org.gnome.Hamster.GUI + org.gnome.Hamster CC0-1.0 GPL-3.0+ and CC-BY-SA-3.0 Hamster diff --git a/data/wscript b/data/wscript index db9ac210a..90b9c87de 100644 --- a/data/wscript +++ b/data/wscript @@ -15,7 +15,7 @@ def build(ctx): ctx(features='glib2', settings_schema_files=['org.gnome.hamster.gschema.xml']) - ctx.install_files('${DATADIR}/metainfo', 'org.gnome.Hamster.GUI.metainfo.xml') + ctx.install_files('${DATADIR}/metainfo', 'org.gnome.Hamster.metainfo.xml') filename = "org.gnome.Hamster.GUI.desktop" ctx(features = "subst", From 8a82dc3a31633e261ea9fe491f7a9859b28daa2e Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Sat, 18 Nov 2023 13:16:50 +0100 Subject: [PATCH 06/10] Add version number to metainfo.xml file This is now done by waf at install time and ensures that flatpak knows the hamster version of the build. --- ...ter.metainfo.xml => org.gnome.Hamster.metainfo.xml.in} | 3 +++ data/wscript | 8 +++++++- 2 files changed, 10 insertions(+), 1 deletion(-) rename data/{org.gnome.Hamster.metainfo.xml => org.gnome.Hamster.metainfo.xml.in} (96%) diff --git a/data/org.gnome.Hamster.metainfo.xml b/data/org.gnome.Hamster.metainfo.xml.in similarity index 96% rename from data/org.gnome.Hamster.metainfo.xml rename to data/org.gnome.Hamster.metainfo.xml.in index 2d6747094..613dadb53 100644 --- a/data/org.gnome.Hamster.metainfo.xml +++ b/data/org.gnome.Hamster.metainfo.xml.in @@ -44,6 +44,9 @@ ​hamster https://github.com/projecthamster/hamster/wiki + + + hamster diff --git a/data/wscript b/data/wscript index 90b9c87de..e5a54fa5b 100644 --- a/data/wscript +++ b/data/wscript @@ -15,7 +15,13 @@ def build(ctx): ctx(features='glib2', settings_schema_files=['org.gnome.hamster.gschema.xml']) - ctx.install_files('${DATADIR}/metainfo', 'org.gnome.Hamster.metainfo.xml') + filename = "org.gnome.Hamster.metainfo.xml" + ctx(features = "subst", + source= "%s.in" % filename, + target= "%s" % filename, + dict = ctx.env, + install_path = "${DATADIR}/metainfo" + ) filename = "org.gnome.Hamster.GUI.desktop" ctx(features = "subst", From 5bdd4238815e2a0aeff44acc66b8cad52fc8e981 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Sat, 18 Nov 2023 13:20:43 +0100 Subject: [PATCH 07/10] Hardcode fake release date in metainfo.xml Without a release date, flatpak ignores the version number, but autodetecting the release date (and carrying it into tarballs) might be too much work, so just hardcode an obviously fake date for now. --- data/org.gnome.Hamster.metainfo.xml.in | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/data/org.gnome.Hamster.metainfo.xml.in b/data/org.gnome.Hamster.metainfo.xml.in index 613dadb53..81e3000c9 100644 --- a/data/org.gnome.Hamster.metainfo.xml.in +++ b/data/org.gnome.Hamster.metainfo.xml.in @@ -45,7 +45,8 @@ ​hamster https://github.com/projecthamster/hamster/wiki - + + hamster From 7b51320c56b25a7a11694bd3b7e437f4ce2184e1 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Sun, 19 Nov 2023 12:02:12 +0100 Subject: [PATCH 08/10] Remove .bumpversion.cfg This was not actually used in practice and no longer matches the recent changes to the version handling, so remove it. --- .bumpversion.cfg | 21 --------------------- 1 file changed, 21 deletions(-) delete mode 100644 .bumpversion.cfg diff --git a/.bumpversion.cfg b/.bumpversion.cfg deleted file mode 100644 index 908c1cbaf..000000000 --- a/.bumpversion.cfg +++ /dev/null @@ -1,21 +0,0 @@ -[bumpversion] -current_version = 3.0.2 -parse = (?P\d+)\.(?P\d+)(\.(?P\d+))? -serialize = - {major}.{minor}.{patch} - {major}.{minor} - -[bumpversion:file:src/hamster/__init__.py] -search = __version__ = "{current_version}" -replace = __version__ = "{new_version}" - -[bumpversion:file:wscript] -search = VERSION = "{current_version}" -replace = VERSION = "{new_version}" - -[bumpversion:file:NEWS] -search = Changes since {current_version} -replace = Changes since {new_version} - - - Changes in {new_version} From 38756238bef2ddf72f10226acf1386fe96eba8ef Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Sun, 19 Nov 2023 12:03:20 +0100 Subject: [PATCH 09/10] Remove setup.py This was added a long time ago only for the database backend, but seems to be outdated. In general, hamster cannot be installed using setup.py anyway, since it requires dbus service files, gsettings schemas, etc. so waf is used for all that. Remove setup.py which is no longer used anyway. This fixes #581. --- setup.py | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 setup.py diff --git a/setup.py b/setup.py deleted file mode 100644 index 589ed7178..000000000 --- a/setup.py +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env python2 -import distutils -import os -from distutils.core import setup -from distutils import sysconfig - -data_dir = os.path.join(sysconfig.get_python_lib(), "hamster", "data") - -setup(name='hamster-sqlite', - version='0.3', - description='Minimal dependency nicely abstracted sqlite backend of hamster time tracker - lets you connect to your hamster db and do stuff in python', - author='Toms Baugis', - author_email='toms.baugis@gmail.com', - url='https://github.com/projecthamster/hamster', - package_dir = {'': 'src'}, - py_modules = ['hamster.storage', 'hamster.db', 'hamster.lib.__init__'], - data_files=[(data_dir, ['data/hamster.db'])], - ) From c062980072b8323bca263f28c7e318573704f256 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Sun, 19 Nov 2023 12:22:09 +0100 Subject: [PATCH 10/10] CI: Let github workflow use version number in the flatpak filename Note: For pull requests, the version that is tested is an autogenerated temporary merge commit (which is good, since it tests whether things work *after* merging), but that commit id is also included in the filename which might be bit suprising. To be considered later. --- .github/workflows/testing.yml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 434a9dc99..7eac188e6 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -82,6 +82,10 @@ jobs: steps: - name: Prepare repo uses: actions/checkout@v2 + # Fetch history, so we also fetch the previous tag for deriving + # the version number + with: + fetch-depth: 0 - name: Install system packages # It would be good to cache the GNOME Sdk, as it # is rather big to download each time. @@ -105,10 +109,14 @@ jobs: - name: Export bundle and try to install it run: | mkdir -p dist - flatpak build-bundle --runtime-repo=https://flathub.org/repo/flathub.flatpakrepo build/flatpak/repo dist/Hamster.flatpak org.gnome.Hamster - flatpak --user -y install dist/Hamster.flatpak + # Note: For pull requests, this version includes the git hash + # of the autogenerated *merge* commit, not the original + # to-be-merged commit (because that's also what is tested). + VERSION=$(python src/hamster/version.py) + flatpak build-bundle --runtime-repo=https://flathub.org/repo/flathub.flatpakrepo build/flatpak/repo "dist/Hamster-$VERSION.flatpak" org.gnome.Hamster + flatpak --user -y install "dist/Hamster-$VERSION.flatpak" - name: Upload built artifact uses: actions/upload-artifact@v2 with: name: Flatpak application - path: dist/Hamster.flatpak + path: dist/*.flatpak