diff --git a/common/git.py b/common/git.py new file mode 100644 index 0000000000..e15a5051d2 --- /dev/null +++ b/common/git.py @@ -0,0 +1,42 @@ +import subprocess +from openpilot.common.utils import cache +from openpilot.common.run import run_cmd, run_cmd_default + + +@cache +def get_commit(branch: str = "HEAD") -> str: + return run_cmd_default(["git", "rev-parse", branch]) + + +@cache +def get_commit_date(commit: str = "HEAD") -> str: + return run_cmd_default(["git", "show", "--no-patch", "--format='%ct %ci'", commit]) + + +@cache +def get_short_branch() -> str: + return run_cmd_default(["git", "rev-parse", "--abbrev-ref", "HEAD"]) + + +@cache +def get_branch() -> str: + return run_cmd_default(["git", "rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}"]) + + +@cache +def get_origin() -> str: + try: + local_branch = run_cmd(["git", "name-rev", "--name-only", "HEAD"]) + tracking_remote = run_cmd(["git", "config", "branch." + local_branch + ".remote"]) + return run_cmd(["git", "config", "remote." + tracking_remote + ".url"]) + except subprocess.CalledProcessError: # Not on a branch, fallback + return run_cmd_default(["git", "config", "--get", "remote.origin.url"]) + + +@cache +def get_normalized_origin() -> str: + return get_origin() \ + .replace("git@", "", 1) \ + .replace(".git", "", 1) \ + .replace("https://", "", 1) \ + .replace(":", "/", 1) diff --git a/common/run.py b/common/run.py new file mode 100644 index 0000000000..25abe98c41 --- /dev/null +++ b/common/run.py @@ -0,0 +1,13 @@ +import subprocess + + +def run_cmd(cmd: list[str]) -> str: + return subprocess.check_output(cmd, encoding='utf8').strip() + + +def run_cmd_default(cmd: list[str], default: str = "") -> str: + try: + return run_cmd(cmd) + except subprocess.CalledProcessError: + return default + diff --git a/common/utils.py b/common/utils.py index b9de020ee6..e37f2448c5 100644 --- a/common/utils.py +++ b/common/utils.py @@ -1,3 +1,11 @@ +from collections.abc import Callable +from functools import lru_cache +from typing import TypeVar + + +_RT = TypeVar("_RT") + + class Freezable: _frozen: bool = False @@ -9,3 +17,7 @@ class Freezable: if self._frozen: raise Exception("cannot modify frozen object") super().__setattr__(*args, **kwargs) + + +def cache(user_function: Callable[..., _RT], /) -> Callable[..., _RT]: + return lru_cache(maxsize=None)(user_function) diff --git a/selfdrive/athena/athenad.py b/selfdrive/athena/athenad.py index 9f901498b7..d228af572c 100755 --- a/selfdrive/athena/athenad.py +++ b/selfdrive/athena/athenad.py @@ -32,12 +32,13 @@ from cereal import log from cereal.services import SERVICE_LIST from openpilot.common.api import Api from openpilot.common.file_helpers import CallbackReader +from openpilot.common.git import get_commit, get_normalized_origin, get_short_branch from openpilot.common.params import Params from openpilot.common.realtime import set_core_affinity from openpilot.system.hardware import HARDWARE, PC from openpilot.system.loggerd.xattr_cache import getxattr, setxattr from openpilot.common.swaglog import cloudlog -from openpilot.system.version import get_commit, get_normalized_origin, get_short_branch, get_version +from openpilot.system.version import get_version from openpilot.system.hardware.hw import Paths diff --git a/selfdrive/athena/manage_athenad.py b/selfdrive/athena/manage_athenad.py index 486e426911..3065bed5c7 100755 --- a/selfdrive/athena/manage_athenad.py +++ b/selfdrive/athena/manage_athenad.py @@ -7,7 +7,8 @@ from openpilot.common.params import Params from openpilot.selfdrive.manager.process import launcher from openpilot.common.swaglog import cloudlog from openpilot.system.hardware import HARDWARE -from openpilot.system.version import get_version, get_normalized_origin, get_short_branch, get_commit, is_dirty +from openpilot.common.git import get_commit, get_normalized_origin, get_short_branch +from openpilot.system.version import get_version, is_dirty ATHENA_MGR_PID_PARAM = "AthenadPid" diff --git a/selfdrive/controls/controlsd.py b/selfdrive/controls/controlsd.py index 77bc787078..e6f91130b9 100755 --- a/selfdrive/controls/controlsd.py +++ b/selfdrive/controls/controlsd.py @@ -12,6 +12,7 @@ from cereal.visionipc import VisionIpcClient, VisionStreamType from openpilot.common.conversions import Conversions as CV +from openpilot.common.git import get_short_branch from openpilot.common.numpy_fast import clip from openpilot.common.params import Params from openpilot.common.realtime import config_realtime_process, Priority, Ratekeeper, DT_CTRL @@ -30,7 +31,6 @@ from openpilot.selfdrive.controls.lib.longcontrol import LongControl from openpilot.selfdrive.controls.lib.vehicle_model import VehicleModel from openpilot.system.hardware import HARDWARE -from openpilot.system.version import get_short_branch SOFT_DISABLE_TIME = 3 # seconds LDW_MIN_SPEED = 31 * CV.MPH_TO_MS diff --git a/selfdrive/controls/lib/events.py b/selfdrive/controls/lib/events.py index c5228ef7f2..c6e9504f35 100755 --- a/selfdrive/controls/lib/events.py +++ b/selfdrive/controls/lib/events.py @@ -7,9 +7,9 @@ from collections.abc import Callable from cereal import log, car import cereal.messaging as messaging from openpilot.common.conversions import Conversions as CV +from openpilot.common.git import get_short_branch from openpilot.common.realtime import DT_CTRL from openpilot.selfdrive.locationd.calibrationd import MIN_SPEED_FILTER -from openpilot.system.version import get_short_branch AlertSize = log.ControlsState.AlertSize AlertStatus = log.ControlsState.AlertStatus diff --git a/selfdrive/manager/manager.py b/selfdrive/manager/manager.py index 24dceaaf08..f30b81861a 100755 --- a/selfdrive/manager/manager.py +++ b/selfdrive/manager/manager.py @@ -16,9 +16,10 @@ from openpilot.selfdrive.manager.process import ensure_running from openpilot.selfdrive.manager.process_config import managed_processes from openpilot.selfdrive.athena.registration import register, UNREGISTERED_DONGLE_ID from openpilot.common.swaglog import cloudlog, add_file_handler -from openpilot.system.version import is_dirty, get_commit, get_version, get_origin, get_short_branch, \ +from openpilot.common.git import get_commit, get_origin, get_short_branch, get_commit_date +from openpilot.system.version import is_dirty, get_version, \ get_normalized_origin, terms_version, training_version, \ - is_tested_branch, is_release_branch, get_commit_date + is_tested_branch, is_release_branch diff --git a/selfdrive/sentry.py b/selfdrive/sentry.py index 5b63a9fe2d..889178610f 100644 --- a/selfdrive/sentry.py +++ b/selfdrive/sentry.py @@ -6,9 +6,9 @@ from sentry_sdk.integrations.threading import ThreadingIntegration from openpilot.common.params import Params from openpilot.selfdrive.athena.registration import is_registered_device from openpilot.system.hardware import HARDWARE, PC +from openpilot.common.git import get_commit, get_branch, get_origin from openpilot.common.swaglog import cloudlog -from openpilot.system.version import get_branch, get_commit, get_origin, get_version, \ - is_comma_remote, is_dirty, is_tested_branch +from openpilot.system.version import get_version, is_comma_remote, is_dirty, is_tested_branch class SentryProject(Enum): diff --git a/selfdrive/test/process_replay/model_replay.py b/selfdrive/test/process_replay/model_replay.py index 94895285df..9db05cfc82 100755 --- a/selfdrive/test/process_replay/model_replay.py +++ b/selfdrive/test/process_replay/model_replay.py @@ -6,13 +6,13 @@ from collections import defaultdict from typing import Any import cereal.messaging as messaging +from openpilot.common.git import get_commit from openpilot.common.params import Params from openpilot.system.hardware import PC from openpilot.selfdrive.manager.process_config import managed_processes from openpilot.tools.lib.openpilotci import BASE_URL, get_url from openpilot.selfdrive.test.process_replay.compare_logs import compare_logs, format_diff from openpilot.selfdrive.test.process_replay.process_replay import get_process_config, replay_process -from openpilot.system.version import get_commit from openpilot.tools.lib.framereader import FrameReader from openpilot.tools.lib.logreader import LogReader from openpilot.tools.lib.helpers import save_log diff --git a/selfdrive/test/process_replay/test_debayer.py b/selfdrive/test/process_replay/test_debayer.py index edf2cbd469..805d73db88 100755 --- a/selfdrive/test/process_replay/test_debayer.py +++ b/selfdrive/test/process_replay/test_debayer.py @@ -9,7 +9,7 @@ import pyopencl as cl # install with `PYOPENCL_CL_PRETEND_VERSION=2.0 pip insta from openpilot.system.hardware import PC, TICI from openpilot.common.basedir import BASEDIR from openpilot.tools.lib.openpilotci import BASE_URL -from openpilot.system.version import get_commit +from openpilot.common.git import get_commit from openpilot.system.camerad.snapshot.snapshot import yuv_to_rgb from openpilot.tools.lib.logreader import LogReader from openpilot.tools.lib.filereader import FileReader diff --git a/selfdrive/test/process_replay/test_processes.py b/selfdrive/test/process_replay/test_processes.py index 99f04600a5..ce1daddf42 100755 --- a/selfdrive/test/process_replay/test_processes.py +++ b/selfdrive/test/process_replay/test_processes.py @@ -7,11 +7,11 @@ from collections import defaultdict from tqdm import tqdm from typing import Any +from openpilot.common.git import get_commit from openpilot.selfdrive.car.car_helpers import interface_names from openpilot.tools.lib.openpilotci import get_url, upload_file from openpilot.selfdrive.test.process_replay.compare_logs import compare_logs, format_diff from openpilot.selfdrive.test.process_replay.process_replay import CONFIGS, PROC_REPLAY_DIR, FAKEDATA, check_openpilot_enabled, replay_process -from openpilot.system.version import get_commit from openpilot.tools.lib.filereader import FileReader from openpilot.tools.lib.logreader import LogReader from openpilot.tools.lib.helpers import save_log diff --git a/selfdrive/tombstoned.py b/selfdrive/tombstoned.py index ba3582d130..f1b8c88083 100755 --- a/selfdrive/tombstoned.py +++ b/selfdrive/tombstoned.py @@ -11,8 +11,8 @@ from typing import NoReturn import openpilot.selfdrive.sentry as sentry from openpilot.system.hardware.hw import Paths +from openpilot.common.git import get_commit from openpilot.common.swaglog import cloudlog -from openpilot.system.version import get_commit MAX_SIZE = 1_000_000 * 100 # allow up to 100M MAX_TOMBSTONE_FN_LEN = 62 # 85 - 23 ("/crash/") diff --git a/system/version.py b/system/version.py index 4319ef2140..7452506846 100755 --- a/system/version.py +++ b/system/version.py @@ -1,12 +1,13 @@ #!/usr/bin/env python3 import os import subprocess -from typing import TypeVar -from collections.abc import Callable -from functools import lru_cache + from openpilot.common.basedir import BASEDIR from openpilot.common.swaglog import cloudlog +from openpilot.common.utils import cache +from openpilot.common.git import get_origin, get_branch, get_short_branch, get_normalized_origin, get_commit_date + RELEASE_BRANCHES = ['release3-staging', 'release3', 'nightly'] TESTED_BRANCHES = RELEASE_BRANCHES + ['devel', 'devel-staging'] @@ -14,60 +15,6 @@ TESTED_BRANCHES = RELEASE_BRANCHES + ['devel', 'devel-staging'] training_version: bytes = b"0.2.0" terms_version: bytes = b"2" -_RT = TypeVar("_RT") -def cache(user_function: Callable[..., _RT], /) -> Callable[..., _RT]: - return lru_cache(maxsize=None)(user_function) - - -def run_cmd(cmd: list[str]) -> str: - return subprocess.check_output(cmd, encoding='utf8').strip() - - -def run_cmd_default(cmd: list[str], default: str = "") -> str: - try: - return run_cmd(cmd) - except subprocess.CalledProcessError: - return default - - -@cache -def get_commit(branch: str = "HEAD") -> str: - return run_cmd_default(["git", "rev-parse", branch]) - - -@cache -def get_commit_date(commit: str = "HEAD") -> str: - return run_cmd_default(["git", "show", "--no-patch", "--format='%ct %ci'", commit]) - - -@cache -def get_short_branch() -> str: - return run_cmd_default(["git", "rev-parse", "--abbrev-ref", "HEAD"]) - - -@cache -def get_branch() -> str: - return run_cmd_default(["git", "rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}"]) - - -@cache -def get_origin() -> str: - try: - local_branch = run_cmd(["git", "name-rev", "--name-only", "HEAD"]) - tracking_remote = run_cmd(["git", "config", "branch." + local_branch + ".remote"]) - return run_cmd(["git", "config", "remote." + tracking_remote + ".url"]) - except subprocess.CalledProcessError: # Not on a branch, fallback - return run_cmd_default(["git", "config", "--get", "remote.origin.url"]) - - -@cache -def get_normalized_origin() -> str: - return get_origin() \ - .replace("git@", "", 1) \ - .replace(".git", "", 1) \ - .replace("https://", "", 1) \ - .replace(":", "/", 1) - @cache def get_version() -> str: