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/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..8a847bf3 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,13 +10,25 @@ 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.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
@@ -306,7 +319,7 @@ 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_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..086e4444 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,
+ # 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,
'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/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/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)
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