|
4 | 4 | import re
|
5 | 5 | import sys
|
6 | 6 |
|
7 |
| -PACKAGE_FILE = pathlib.Path("socketsecurity/__init__.py") |
| 7 | +INIT_FILE = pathlib.Path("socketsecurity/__init__.py") |
| 8 | +PYPROJECT_FILE = pathlib.Path("pyproject.toml") |
| 9 | + |
8 | 10 | VERSION_PATTERN = re.compile(r"__version__\s*=\s*['\"]([^'\"]+)['\"]")
|
| 11 | +PYPROJECT_PATTERN = re.compile(r'^version\s*=\s*".*"$', re.MULTILINE) |
9 | 12 |
|
10 |
| -def get_hatch_version(full=False, strip_local=False): |
11 |
| - version = subprocess.check_output(["hatch", "version"], text=True).strip() |
12 |
| - if not full or strip_local: |
13 |
| - version = version.split("+")[0] # strip local metadata |
14 |
| - return version |
| 13 | +def get_git_tag(): |
| 14 | + try: |
| 15 | + tag = subprocess.check_output(["git", "describe", "--tags", "--exact-match"], stderr=subprocess.DEVNULL, text=True).strip() |
| 16 | + return tag.lstrip("v") # Remove 'v' prefix |
| 17 | + except subprocess.CalledProcessError: |
| 18 | + return None |
15 | 19 |
|
16 |
| -def get_current_version(): |
17 |
| - content = PACKAGE_FILE.read_text() |
18 |
| - match = VERSION_PATTERN.search(content) |
19 |
| - return match.group(1) if match else None |
| 20 | +def get_latest_tag(): |
| 21 | + try: |
| 22 | + tag = subprocess.check_output(["git", "describe", "--tags", "--abbrev=0"], text=True).strip() |
| 23 | + return tag.lstrip("v") |
| 24 | + except subprocess.CalledProcessError: |
| 25 | + return "0.0.0" |
20 | 26 |
|
21 |
| -def update_version(new_version): |
22 |
| - content = PACKAGE_FILE.read_text() |
23 |
| - new_content = VERSION_PATTERN.sub(f"__version__ = '{new_version}'", content) |
24 |
| - PACKAGE_FILE.write_text(new_content) |
| 27 | +def get_commit_count_since(tag): |
| 28 | + try: |
| 29 | + output = subprocess.check_output(["git", "rev-list", f"{tag}..HEAD", "--count"], text=True).strip() |
| 30 | + return int(output) |
| 31 | + except subprocess.CalledProcessError: |
| 32 | + return 0 |
25 | 33 |
|
26 |
| -def main(): |
27 |
| - full_mode = "--dev" in sys.argv |
28 |
| - hatch_version = get_hatch_version(full=full_mode, strip_local=full_mode) |
29 |
| - current_version = get_current_version() |
| 34 | +def inject_version(version: str): |
| 35 | + print(f"🔁 Injecting version: {version}") |
| 36 | + |
| 37 | + # Update __init__.py |
| 38 | + init_content = INIT_FILE.read_text() |
| 39 | + new_init_content = VERSION_PATTERN.sub(f"__version__ = '{version}'", init_content) |
| 40 | + INIT_FILE.write_text(new_init_content) |
30 | 41 |
|
31 |
| - if not current_version: |
32 |
| - print(f"❌ Couldn't find __version__ in {PACKAGE_FILE}") |
33 |
| - return 1 |
| 42 | + # Update pyproject.toml |
| 43 | + pyproject = PYPROJECT_FILE.read_text() |
| 44 | + if PYPROJECT_PATTERN.search(pyproject): |
| 45 | + new_pyproject = PYPROJECT_PATTERN.sub(f'version = "{version}"', pyproject) |
| 46 | + else: |
| 47 | + new_pyproject = re.sub(r"(\[project\])", rf"\1\nversion = \"{version}\"", pyproject) |
| 48 | + PYPROJECT_FILE.write_text(new_pyproject) |
| 49 | + |
| 50 | +def main(): |
| 51 | + mode = "--dev" if "--dev" in sys.argv else "release" |
34 | 52 |
|
35 |
| - if hatch_version != current_version: |
36 |
| - print(f"🔁 Updating version: {current_version} → {hatch_version}") |
37 |
| - update_version(hatch_version) |
38 |
| - return 0 if full_mode else 1 |
| 53 | + if mode == "release": |
| 54 | + version = get_git_tag() |
| 55 | + if not version: |
| 56 | + print("❌ Error: No exact tag found for release.") |
| 57 | + sys.exit(1) |
| 58 | + else: |
| 59 | + base = get_latest_tag() |
| 60 | + commits = get_commit_count_since(f"v{base}") |
| 61 | + version = f"{base}.dev{commits}" |
39 | 62 |
|
40 |
| - print(f"✅ Version is in sync: {hatch_version}") |
41 |
| - return 0 |
| 63 | + inject_version(version) |
| 64 | + print(f"✅ Injected {mode} version: {version}") |
42 | 65 |
|
43 | 66 | if __name__ == "__main__":
|
44 |
| - sys.exit(main()) |
| 67 | + main() |
0 commit comments