A fork of https://github.com/crosspoint-reader/crosspoint-reader
1"""
2PlatformIO pre-build script: inject git branch into CROSSPOINT_VERSION for
3the default (dev) environment.
4
5Results in a version string like: 1.1.0-dev+feat-koysnc-xpath
6Release environments are unaffected; they set CROSSPOINT_VERSION in the ini.
7"""
8
9import configparser
10import os
11import subprocess
12import sys
13
14
15def warn(msg):
16 print(f'WARNING [git_branch.py]: {msg}', file=sys.stderr)
17
18
19def get_git_branch(project_dir):
20 try:
21 branch = subprocess.check_output(
22 ['git', 'rev-parse', '--abbrev-ref', 'HEAD'],
23 text=True, stderr=subprocess.PIPE, cwd=project_dir
24 ).strip()
25 # Detached HEAD — show the short SHA instead
26 if branch == 'HEAD':
27 branch = subprocess.check_output(
28 ['git', 'rev-parse', '--short', 'HEAD'],
29 text=True, stderr=subprocess.PIPE, cwd=project_dir
30 ).strip()
31 # Strip characters that would break a C string literal
32 return ''.join(c for c in branch if c not in '"\\')
33 except FileNotFoundError:
34 warn('git not found on PATH; branch suffix will be "unknown"')
35 return 'unknown'
36 except subprocess.CalledProcessError as e:
37 warn(f'git command failed (exit {e.returncode}): {e.stderr.strip()}; branch suffix will be "unknown"')
38 return 'unknown'
39 except Exception as e:
40 warn(f'Unexpected error reading git branch: {e}; branch suffix will be "unknown"')
41 return 'unknown'
42
43
44def get_base_version(project_dir):
45 ini_path = os.path.join(project_dir, 'platformio.ini')
46 if not os.path.isfile(ini_path):
47 warn(f'platformio.ini not found at {ini_path}; base version will be "0.0.0"')
48 return '0.0.0'
49 config = configparser.ConfigParser()
50 config.read(ini_path)
51 if not config.has_option('crosspoint', 'version'):
52 warn('No [crosspoint] version in platformio.ini; base version will be "0.0.0"')
53 return '0.0.0'
54 return config.get('crosspoint', 'version')
55
56
57def inject_version(env):
58 # Only applies to the dev (default) environment; release envs set the
59 # version via build_flags in platformio.ini and are unaffected.
60 if env['PIOENV'] != 'default':
61 return
62
63 project_dir = env['PROJECT_DIR']
64 base_version = get_base_version(project_dir)
65 branch = get_git_branch(project_dir)
66 version_string = f'{base_version}-dev+{branch}'
67
68 env.Append(CPPDEFINES=[('CROSSPOINT_VERSION', f'\\"{version_string}\\"')])
69 print(f'CrossPoint build version: {version_string}')
70
71
72# PlatformIO/SCons entry point — Import and env are SCons builtins injected at runtime.
73# When run directly with Python (e.g. for validation), a lightweight fake env is used
74# so the git/version logic can be exercised without a full build.
75try:
76 Import('env') # noqa: F821 # type: ignore[name-defined]
77 inject_version(env) # noqa: F821 # type: ignore[name-defined]
78except NameError:
79 class _Env(dict):
80 def Append(self, **_): pass
81
82 _project_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
83 inject_version(_Env({'PIOENV': 'default', 'PROJECT_DIR': _project_dir}))