diff --git a/mitmproxy/utils/debug.py b/mitmproxy/utils/debug.py index de01b12cd..e8eca9063 100644 --- a/mitmproxy/utils/debug.py +++ b/mitmproxy/utils/debug.py @@ -1,43 +1,24 @@ import gc import os +import platform +import re +import signal import sys import threading -import signal -import platform import traceback -import subprocess - -from mitmproxy import version from OpenSSL import SSL +from mitmproxy import version + def dump_system_info(): - mitmproxy_version = version.VERSION - here = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) - try: - git_describe = subprocess.check_output( - ['git', 'describe', '--tags', '--long'], - stderr=subprocess.STDOUT, - cwd=here, - ) - except: - pass - else: - last_tag, tag_dist, commit = git_describe.decode().strip().rsplit("-", 2) - - commit = commit.lstrip("g") # remove the 'g' prefix added by recent git versions - tag_dist = int(tag_dist) - - if tag_dist > 0: - tag_dist = "dev{:04}".format(tag_dist) - else: - tag_dist = "" - - mitmproxy_version += "{tag_dist} ({commit})".format( - tag_dist=tag_dist, - commit=commit, - ) + mitmproxy_version = version.get_version(True, True) + mitmproxy_version = re.sub( + r"-0x([0-9a-f]+)", + r" (commit \1)", + mitmproxy_version + ) # PyInstaller builds indicator, if using precompiled binary if getattr(sys, 'frozen', False): diff --git a/mitmproxy/version.py b/mitmproxy/version.py index c901cb67f..3073c3d3f 100644 --- a/mitmproxy/version.py +++ b/mitmproxy/version.py @@ -1,3 +1,8 @@ +import os +import subprocess + +# The actual version string. For precompiled binaries, this will be changed to include the build +# tag, e.g. "3.0.0.dev0042-0xcafeabc" VERSION = "3.0.0" PATHOD = "pathod " + VERSION MITMPROXY = "mitmproxy " + VERSION @@ -6,5 +11,54 @@ MITMPROXY = "mitmproxy " + VERSION # for each change in the file format. FLOW_FORMAT_VERSION = 5 + +def get_version(dev: bool = False, build: bool = False, refresh: bool = False) -> str: + """ + Return a detailed version string, sourced either from a hardcoded VERSION constant + or obtained dynamically using git. + + Args: + dev: If True, non-tagged releases will include a ".devXXXX" suffix, where XXXX is the number + of commits since the last tagged release. + build: If True, non-tagged releases will include a "-0xXXXXXXX" suffix, where XXXXXXX are + the first seven digits of the commit hash. + refresh: If True, always try to use git instead of a potentially hardcoded constant. + """ + + mitmproxy_version = VERSION + + if "dev" in VERSION and not refresh: + pass # There is a hardcoded build tag, so we just use what's there. + elif dev or build: + here = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) + try: + git_describe = subprocess.check_output( + ['git', 'describe', '--tags', '--long'], + stderr=subprocess.STDOUT, + cwd=here, + ) + last_tag, tag_dist, commit = git_describe.decode().strip().rsplit("-", 2) + commit = commit.lstrip("g")[:7] + tag_dist = int(tag_dist) + except Exception: + pass + else: + # Remove current suffix + mitmproxy_version = mitmproxy_version.split(".dev")[0] + + # Add suffix for non-tagged releases + if tag_dist > 0: + mitmproxy_version += ".dev{tag_dist:04}".format(tag_dist=tag_dist) + # The wheel build tag (we use the commit) must start with a digit, so we include "0x" + mitmproxy_version += "-0x{commit}".format(commit=commit) + + if not dev: + mitmproxy_version = mitmproxy_version.split(".dev")[0] + elif not build: + mitmproxy_version = mitmproxy_version.split("-0x")[0] + + return mitmproxy_version + + if __name__ == "__main__": print(VERSION) diff --git a/release/rtool.py b/release/rtool.py index 14a0a0784..4a07885cb 100755 --- a/release/rtool.py +++ b/release/rtool.py @@ -81,35 +81,18 @@ def git(args: str) -> str: def get_version(dev: bool = False, build: bool = False) -> str: - version = runpy.run_path(VERSION_FILE)["VERSION"] - version = re.sub(r"\.dev.+?$", "", version) # replace dev suffix if present. - - last_tag, tag_dist, commit = git("describe --tags --long").strip().rsplit("-", 2) - commit = commit.lstrip("g")[:7] - tag_dist = int(tag_dist) - - if tag_dist > 0 and dev: - dev_tag = ".dev{tag_dist:04}".format(tag_dist=tag_dist) - else: - dev_tag = "" - - if tag_dist > 0 and build: - # The wheel build tag (we use the commit) must start with a digit, so we include "0x" - build_tag = "-0x{commit}".format(commit=commit) - else: - build_tag = "" - - return version + dev_tag + build_tag + x = runpy.run_path(VERSION_FILE) + return x["get_version"](dev, build, True) def set_version(dev: bool) -> None: """ - Update version information in mitmproxy's version.py to either include the dev version or not. + Update version information in mitmproxy's version.py to either include hardcoded information or not. """ - v = get_version(dev) - with open(VERSION_FILE) as f: + version = get_version(dev, dev) + with open(VERSION_FILE, "r") as f: content = f.read() - content = re.sub(r'^VERSION = ".+?"', 'VERSION = "{}"'.format(v), content) + content = re.sub(r'^VERSION = ".+?"', 'VERSION = "{}"'.format(version), content, flags=re.M) with open(VERSION_FILE, "w") as f: f.write(content) diff --git a/setup.py b/setup.py index cfda3071c..cd1355970 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ here = os.path.abspath(os.path.dirname(__file__)) with open(os.path.join(here, 'README.rst'), encoding='utf-8') as f: long_description = f.read() -VERSION = runpy.run_path(os.path.join(here, "mitmproxy", "version.py"))["VERSION"] +VERSION = runpy.run_path(os.path.join(here, "mitmproxy", "version.py"))["VERSION"].split("-0x")[0] setup( name="mitmproxy", diff --git a/test/mitmproxy/test_version.py b/test/mitmproxy/test_version.py index f87b08517..f8d646dc3 100644 --- a/test/mitmproxy/test_version.py +++ b/test/mitmproxy/test_version.py @@ -1,4 +1,6 @@ import runpy +import subprocess +from unittest import mock from mitmproxy import version @@ -8,3 +10,24 @@ def test_version(capsys): stdout, stderr = capsys.readouterr() assert len(stdout) > 0 assert stdout.strip() == version.VERSION + + +def test_get_version_hardcoded(): + version.VERSION = "3.0.0.dev123-0xcafebabe" + assert version.get_version() == "3.0.0" + assert version.get_version(True) == "3.0.0.dev123" + assert version.get_version(True, True) == "3.0.0.dev123-0xcafebabe" + + +def test_get_version(): + version.VERSION = "3.0.0" + + with mock.patch('subprocess.check_output') as m: + m.return_value = b"tag-0-cafecafe" + assert version.get_version(True, True) == "3.0.0" + + m.return_value = b"tag-2-cafecafe" + assert version.get_version(True, True) == "3.0.0.dev0002-0xcafecaf" + + m.side_effect = subprocess.CalledProcessError(-1, 'git describe --tags --long') + assert version.get_version(True, True) == "3.0.0" diff --git a/test/mitmproxy/utils/test_debug.py b/test/mitmproxy/utils/test_debug.py index a8e1054da..0ca6ead0f 100644 --- a/test/mitmproxy/utils/test_debug.py +++ b/test/mitmproxy/utils/test_debug.py @@ -1,5 +1,4 @@ import io -import subprocess import sys from unittest import mock import pytest @@ -14,18 +13,6 @@ def test_dump_system_info_precompiled(precompiled): assert ("binary" in debug.dump_system_info()) == precompiled -def test_dump_system_info_version(): - with mock.patch('subprocess.check_output') as m: - m.return_value = b"v2.0.0-0-cafecafe" - x = debug.dump_system_info() - assert 'dev' not in x - assert 'cafecafe' in x - - with mock.patch('subprocess.check_output') as m: - m.side_effect = subprocess.CalledProcessError(-1, 'git describe --tags --long') - assert 'dev' not in debug.dump_system_info() - - def test_dump_info(): cs = io.StringIO() debug.dump_info(None, None, file=cs, testing=True)