From 1a8c6aaa939fb97591944b04c6ecea48d46f5a72 Mon Sep 17 00:00:00 2001 From: caryoscelus Date: Wed, 27 Dec 2023 11:27:15 +0000 Subject: [PATCH 1/3] Fetch version info from git or Build file --- requirements.txt | 1 + src/Config.py | 18 ++++++++++++-- src/buildinfo.py | 47 ++++++++++++++++++++++++++++++++++++ src/util/Git.py | 62 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 126 insertions(+), 2 deletions(-) create mode 100755 src/buildinfo.py create mode 100644 src/util/Git.py diff --git a/requirements.txt b/requirements.txt index b9eb9fc9..c5ecfae2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -16,3 +16,4 @@ defusedxml>=0.7 pyaes requests ipython>=8 +GitPython diff --git a/src/Config.py b/src/Config.py index fee378d0..768443e5 100644 --- a/src/Config.py +++ b/src/Config.py @@ -1,6 +1,7 @@ import argparse import sys import os +import platform import locale import re import configparser @@ -9,9 +10,21 @@ import logging.handlers import stat import time -class Config(object): +class Config: def __init__(self, argv): + try: + from . import Build + except ImportError: + print('cannot find build') + from .util import Git + self.build_type = 'source' + self.branch = Git.branch() or 'unknown' + self.commit = Git.commit() or 'unknown' + else: + self.build_type = Build.build_type + self.branch = Build.branch + self.commit = Build.commit self.version = "0.7.10+" self.user_agent = "conservancy" # DEPRECATED ; replace with git-generated commit @@ -306,7 +319,8 @@ class Config(object): self.parser.add_argument('--tor-hs-port', help='Hidden service port in Tor always mode', metavar='limit', type=int, default=15441) self.parser.add_argument('--repl', help='Instead of printing logs in console, drop into REPL after initialization', action='store_true') - self.parser.add_argument('--version', action='version', version=f'zeronet-conservancy {self.version} r{self.rev}') + self.parser.add_argument('--version', action='version', + version=f'zeronet-conservancy {self.version} ({self.build_type} from {self.branch}-{self.commit})') self.parser.add_argument('--end', help='Stop multi value argument parsing', action='store_true') return self.parser diff --git a/src/buildinfo.py b/src/buildinfo.py new file mode 100755 index 00000000..38de4cae --- /dev/null +++ b/src/buildinfo.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 + +## Copyright (c) 2023 caryoscelus +## +## zeronet-conservancy is free software: you can redistribute it and/or modify it under the +## terms of the GNU General Public License as published by the Free Software +## Foundation, either version 3 of the License, or (at your option) any later version. +## +## zeronet-conservancy is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## zeronet-conservancy. If not, see . +## + +"""A small script to generate build info""" + +from util import Git + +import sys + +def main(argv): + if len(argv) < 2: + print(f'Useage: {argv[0]} ') + print('Known build types:') + sys.exit(1) + else: + writeBuildInfo(argv[1]) + +def writeBuildInfo(build_type): + bvars = { + 'build_type': build_type, + 'branch': Git.branch(), + 'commit': Git.commit(), + } + code = '\n'.join(f'{var} = {repr(val)}' for var, val in bvars.items()) + content = \ + '# auto-generated by buildinfo.py\n' \ + '# This file should not persist in git tree\n' + code + '\n' + with open('src/Build.py', 'w') as f: + f.write(content) + +if __name__ == '__main__': + from sys import argv + main(argv) diff --git a/src/util/Git.py b/src/util/Git.py new file mode 100644 index 00000000..7b60d396 --- /dev/null +++ b/src/util/Git.py @@ -0,0 +1,62 @@ +## Copyright (c) 2023 caryoscelus +## +## zeronet-conservancy is free software: you can redistribute it and/or modify it under the +## terms of the GNU General Public License as published by the Free Software +## Foundation, either version 3 of the License, or (at your option) any later version. +## +## zeronet-conservancy is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## zeronet-conservancy. If not, see . +## + +"""Git-related operations + +Currently this is only to retrieve git revision for debug purposes, but later on we might +also want to use it for updates. +""" + +import os + +from typing import Optional + +global git + +try: + import git +except ImportError: + git = None +else: + try: + global _repo + up = os.path.dirname + root = up(up(up(__file__))) + print(root) + _repo = git.Repo(root) + except Exception as exc: + print("Caught exception while trying to detect git repo.") + traceback.print_exc() + git = None + +def _gitted(f): + if git: + return f + else: + return lambda *args, **kwargs: None + +@_gitted +def commit() -> str: + """Returns git revision, possibly suffixed with -dirty""" + dirty = '-dirty' if _repo.is_dirty() else '' + return f'{_repo.head.commit}{dirty}' + +@_gitted +def branch() -> Optional[str]: + """Returns current git branch if any""" + try: + return str(_repo.active_branch) + except TypeError: + return None From 15dddc27c6164c83663235b2b98e0ecbc455e06d Mon Sep 17 00:00:00 2001 From: caryoscelus Date: Wed, 27 Dec 2023 13:17:59 +0000 Subject: [PATCH 2/3] Get rid of using old-style revision everywhere --- plugins/AnnounceLocal/AnnounceLocalPlugin.py | 2 +- plugins/Stats/StatsPlugin.py | 4 ++-- src/Config.py | 7 +++---- src/Plugin/PluginManager.py | 3 --- src/Site/Site.py | 1 - src/Ui/UiRequest.py | 4 ++-- src/Ui/UiWebsocket.py | 6 ++++-- src/main.py | 2 +- 8 files changed, 13 insertions(+), 16 deletions(-) diff --git a/plugins/AnnounceLocal/AnnounceLocalPlugin.py b/plugins/AnnounceLocal/AnnounceLocalPlugin.py index b9225966..2034a436 100644 --- a/plugins/AnnounceLocal/AnnounceLocalPlugin.py +++ b/plugins/AnnounceLocal/AnnounceLocalPlugin.py @@ -31,7 +31,7 @@ class LocalAnnouncer(BroadcastServer.BroadcastServer): self.sender_info["peer_id"] = self.server.peer_id self.sender_info["port"] = self.server.port self.sender_info["broadcast_port"] = listen_port - self.sender_info["rev"] = config.rev + self.sender_info["rev"] = config.user_agent_rev self.known_peers = {} self.last_discover = 0 diff --git a/plugins/Stats/StatsPlugin.py b/plugins/Stats/StatsPlugin.py index 32fd06c5..be692ecf 100644 --- a/plugins/Stats/StatsPlugin.py +++ b/plugins/Stats/StatsPlugin.py @@ -41,7 +41,7 @@ class UiRequestPlugin(object): from Crypt import CryptConnection # Memory - yield "rev%s | " % config.rev + yield f'{config.version_full} | ' yield "%s | " % main.file_server.ip_external_list yield "Port: %s | " % main.file_server.port yield "Network: %s | " % main.file_server.supported_ip_types @@ -579,7 +579,7 @@ class ActionsPlugin: yield "\n" yield from self.formatTable( - ["ZeroNet version:", "%s rev%s" % (config.version, config.rev)], + ["zeronet-conservancy version:", config.version_full], ["Python:", "%s" % sys.version], ["Platform:", "%s" % sys.platform], ["Crypt verify lib:", "%s" % CryptBitcoin.lib_verify_best], diff --git a/src/Config.py b/src/Config.py index 768443e5..8a847bf3 100644 --- a/src/Config.py +++ b/src/Config.py @@ -26,9 +26,9 @@ class Config: self.branch = Build.branch self.commit = Build.commit self.version = "0.7.10+" + self.version_full = f'{self.version} ({self.build_type} from {self.branch}-{self.commit})' self.user_agent = "conservancy" - # DEPRECATED ; replace with git-generated commit - self.rev = 5140 + # for compatibility self.user_agent_rev = 8192 self.argv = argv self.action = None @@ -319,8 +319,7 @@ class Config: self.parser.add_argument('--tor-hs-port', help='Hidden service port in Tor always mode', metavar='limit', type=int, default=15441) self.parser.add_argument('--repl', help='Instead of printing logs in console, drop into REPL after initialization', action='store_true') - self.parser.add_argument('--version', action='version', - version=f'zeronet-conservancy {self.version} ({self.build_type} from {self.branch}-{self.commit})') + self.parser.add_argument('--version', action='version', version=f'zeronet-conservancy {self.version_full}') self.parser.add_argument('--end', help='Stop multi value argument parsing', action='store_true') return self.parser diff --git a/src/Plugin/PluginManager.py b/src/Plugin/PluginManager.py index 5855c842..ab0940e8 100644 --- a/src/Plugin/PluginManager.py +++ b/src/Plugin/PluginManager.py @@ -22,7 +22,6 @@ class PluginManager: self.pluggable = {} self.plugin_names = [] # Loaded plugin names self.plugins_updated = {} # List of updated plugins since restart - self.plugins_rev = {} # Installed plugins revision numbers self.after_load = [] # Execute functions after loaded plugins self.function_flags = {} # Flag function for permissions self.reloading = False @@ -88,7 +87,6 @@ class PluginManager: plugin["dir_path"] = dir_path plugin["inner_path"] = plugin_name plugin["enabled"] = is_enabled - plugin["rev"] = config.rev plugin["loaded"] = plugin_name in self.plugin_names plugins.append(plugin) @@ -101,7 +99,6 @@ class PluginManager: for plugin in self.listPlugins(): self.log.debug("Loading plugin: %s (%s)" % (plugin["name"], plugin["source"])) if plugin["source"] != "builtin": - self.plugins_rev[plugin["name"]] = plugin["rev"] site_plugin_dir = os.path.dirname(plugin["dir_path"]) if site_plugin_dir not in sys.path: sys.path.append(site_plugin_dir) diff --git a/src/Site/Site.py b/src/Site/Site.py index ae2be36a..ad0e3ca2 100644 --- a/src/Site/Site.py +++ b/src/Site/Site.py @@ -600,7 +600,6 @@ class Site(object): num_connected_peers = len(peers) random.shuffle(peers) - peers = sorted(peers, key=lambda peer: peer.connection.handshake.get("rev", 0) < config.rev - 100) # Prefer newer clients if len(peers) < limit * 2 and len(self.peers) > len(peers): # Add more, non-connected peers if necessary peers += self.getRecentPeers(limit * 2) diff --git a/src/Ui/UiRequest.py b/src/Ui/UiRequest.py index 17e63c9b..2b06661d 100644 --- a/src/Ui/UiRequest.py +++ b/src/Ui/UiRequest.py @@ -660,7 +660,7 @@ class UiRequest: permissions=json.dumps(site.settings["permissions"]), show_loadingscreen=json.dumps(show_loadingscreen), sandbox_permissions=sandbox_permissions, - rev=config.rev, + rev=config.commit, lang=config.language, homepage=homepage, themeclass=themeclass, @@ -1038,7 +1038,7 @@ class UiRequest: if details and config.debug: details = {key: val for key, val in list(self.env.items()) if hasattr(val, "endswith") and "COOKIE" not in key} - details["version_zeronet"] = "%s r%s" % (config.version, config.rev) + details["version_zeronet"] = config.version_full details["version_python"] = sys.version details["version_gevent"] = gevent.__version__ details["plugins"] = PluginManager.plugin_manager.plugin_names diff --git a/src/Ui/UiWebsocket.py b/src/Ui/UiWebsocket.py index e6f2f405..a21c9885 100644 --- a/src/Ui/UiWebsocket.py +++ b/src/Ui/UiWebsocket.py @@ -328,13 +328,15 @@ class UiWebsocket(object): 'ui_ip' : config.ui_ip, 'ui_port' : config.ui_port, 'version' : config.version, - 'rev' : config.rev, + # The only place this is used is in dashboard so we shorten it for now + 'rev' : config.commit[:8], 'timecorrection' : file_server.timecorrection, 'language' : config.language, 'debug' : config.debug, 'offline' : config.offline, 'plugins' : PluginManager.plugin_manager.plugin_names, - 'plugins_rev' : PluginManager.plugin_manager.plugins_rev, + # For compat only + 'plugins_rev' : {}, 'user_settings' : self.user.settings, 'lib_verify_best' : CryptBitcoin.lib_verify_best } diff --git a/src/main.py b/src/main.py index 3c526b85..b7fd6e8b 100644 --- a/src/main.py +++ b/src/main.py @@ -196,7 +196,7 @@ elif config.bind: @PluginManager.acceptPlugins class Actions: def call(self, function_name, kwargs): - logging.info("Version: %s r%s, Python %s, Gevent: %s" % (config.version, config.rev, sys.version, gevent.__version__)) + logging.info(f'zeronet-conservancy {config.version_full} on Python {sys.version} Gevent {gevent.__version__}') func = getattr(self, function_name, None) back = func(**kwargs) From 25bfc0341ca3f0d8a1bba0f89d77f1724f2ebca8 Mon Sep 17 00:00:00 2001 From: caryoscelus Date: Wed, 27 Dec 2023 14:24:03 +0000 Subject: [PATCH 3/3] Use integer rev in UiWebSocket for dashboard compatibility --- src/Ui/UiWebsocket.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ui/UiWebsocket.py b/src/Ui/UiWebsocket.py index a21c9885..086e4444 100644 --- a/src/Ui/UiWebsocket.py +++ b/src/Ui/UiWebsocket.py @@ -328,8 +328,8 @@ class UiWebsocket(object): 'ui_ip' : config.ui_ip, 'ui_port' : config.ui_port, 'version' : config.version, - # The only place this is used is in dashboard so we shorten it for now - 'rev' : config.commit[:8], + # Some legacy code relies on this being an integer, so lets return dummy one + 'rev' : config.user_agent_rev, 'timecorrection' : file_server.timecorrection, 'language' : config.language, 'debug' : config.debug,