mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-11-04 19:43:49 +08:00
Update from the live installed Git revision
This commit is contained in:
@@ -271,7 +271,8 @@ class SoftwareOperations:
|
||||
status["updater"]["lastSuccessAt"] != self._baseline[0]:
|
||||
if request["action"] in SOURCE_ACTIONS:
|
||||
if status["updater"]["lastFetchAt"] != self._baseline[1]:
|
||||
restarting = self._flag("DoReboot") is True or status["installed"]["commit"] != self._fast_commit
|
||||
installed = self.git_identity(self.installed)
|
||||
restarting = self._flag("DoReboot") is True or installed is not None and installed[1] != self._fast_commit
|
||||
if request['action'] == 'versions':
|
||||
request.update(state='complete', error=None)
|
||||
else:
|
||||
@@ -453,12 +454,11 @@ class SoftwareOperations:
|
||||
(branch != view["selectedTarget"] or not view["canDownload"])):
|
||||
raise SoftwareOperationError("Selected updater target changed", 409)
|
||||
if action in SOURCE_ACTIONS:
|
||||
installed = self.status.snapshot()["installed"]
|
||||
identity = self.git_identity(self.installed)
|
||||
if (not view["canFastUpdate"] or identity is None or identity != (installed["branch"], installed["commit"]) or
|
||||
(action in ("update", "fast", "versions", "version") and branch != installed["branch"] and branch not in view["availableBranches"]) or
|
||||
(action == "rollback" and (branch != installed["branch"] or not view["canRollback"]))):
|
||||
raise SoftwareOperationError("Installed branch changed; refresh before updating", 409)
|
||||
if (identity is None or not self._valid_branch(identity[0]) or
|
||||
(action in ("update", "fast", "versions", "version") and branch != identity[0] and branch not in view["availableBranches"]) or
|
||||
(action == "rollback" and (branch != identity[0] or not view["canRollback"]))):
|
||||
raise SoftwareOperationError("Installed checkout or update target is unavailable", 409)
|
||||
if action == 'version':
|
||||
target = payload['selectedCommit']
|
||||
recent = view['history']['recent']
|
||||
@@ -472,8 +472,7 @@ class SoftwareOperations:
|
||||
current = self.status.snapshot()
|
||||
if (current["updater"]["state"] != "idle" or self._flag("DisableUpdates") is not False or
|
||||
self._flag("DoReboot") is not False or not self.process.available() or
|
||||
(action not in SOURCE_ACTIONS and branch is not None and branch not in self._branches()) or
|
||||
(action == "rollback" and current["installed"]["branch"] != branch)):
|
||||
(action not in SOURCE_ACTIONS and branch is not None and branch not in self._branches())):
|
||||
raise SoftwareOperationError("Updater state changed", 409)
|
||||
if action == "select":
|
||||
self.params.put("UpdaterTargetBranch", branch, block=True)
|
||||
@@ -494,12 +493,12 @@ class SoftwareOperations:
|
||||
if not authorized() or not self._parked():
|
||||
raise SoftwareOperationError("Session or parked state changed", 403)
|
||||
if action in SOURCE_ACTIONS:
|
||||
identity = self.git_identity(self.installed)
|
||||
if identity is None or identity != (status["installed"]["branch"], status["installed"]["commit"]):
|
||||
raise SoftwareOperationError("Installed branch changed; refresh before updating", 409)
|
||||
latest_identity = self.git_identity(self.installed)
|
||||
if latest_identity is None or latest_identity != identity:
|
||||
raise SoftwareOperationError("Installed checkout changed while preparing the update; retry when it finishes", 409)
|
||||
if action == 'version' and identity[1] != payload['expectedCommit']:
|
||||
raise SoftwareOperationError('Installed revision changed before version request; refresh and try again', 409)
|
||||
self._fast_commit = status["installed"]["commit"]
|
||||
self._fast_commit = identity[1]
|
||||
if action in SOURCE_ACTIONS:
|
||||
if action == 'version':
|
||||
accepted_owner = self.process.send(action, branch=branch, commit=identity[1], selected_commit=payload['selectedCommit'])
|
||||
|
||||
@@ -481,14 +481,60 @@ class SoftwareOperationsTest(unittest.TestCase):
|
||||
self.act("fast", "main")
|
||||
self.assertEqual(self.process.sent, ["fast"])
|
||||
|
||||
def test_fast_rejects_stale_installed_identity(self):
|
||||
def test_fast_refreshes_stale_cached_identity_without_rewriting_running_metadata(self):
|
||||
self.git[self.installed] = ("main", "b" * 40)
|
||||
self.denied("fast", 409, "main")
|
||||
self.git[self.installed] = ("release", "a" * 40)
|
||||
self.denied("fast", 409, "main")
|
||||
self.assertEqual(self.process.sent, [])
|
||||
self.act("fast", "main")
|
||||
self.assertEqual(self.process.fast_requests, [{"branch": "main", "commit": "b" * 40}])
|
||||
self.assertEqual(self.params.get("GitCommit"), "a" * 40)
|
||||
self.assertEqual(self.owner._fast_commit, "b" * 40)
|
||||
self.params.put("LastUpdateTime", datetime(2026, 10, 30, 12), block=True)
|
||||
self.params.put("UpdaterLastFetchTime", datetime(2026, 10, 30, 12), block=True)
|
||||
self.assertEqual(self.owner.snapshot()["request"]["outcome"], "up_to_date")
|
||||
self.assertFalse(self.params.get_bool("DoReboot"))
|
||||
|
||||
def test_changed_cached_branch_does_not_block_requested_live_branch(self):
|
||||
self.git[self.installed] = ("release", "b" * 40)
|
||||
self.params.remove("UpdaterAvailableBranches")
|
||||
self.act("update", "release")
|
||||
self.assertEqual(self.process.fast_requests, [{"branch": "release", "commit": "b" * 40}])
|
||||
self.assertEqual(self.params.get("GitBranch"), "main")
|
||||
|
||||
def test_real_git_commit_after_manager_start_can_update(self):
|
||||
import subprocess
|
||||
from openpilot.starpilot.galaxy.software_operations import _git_identity
|
||||
def git(*args):
|
||||
return subprocess.check_output(["git", "-c", "user.name=Updater Test", "-c", "user.email=test@example.invalid",
|
||||
"-c", "core.hooksPath=/dev/null", "-C", str(self.installed), *args], text=True).strip()
|
||||
git("init", "-b", "main")
|
||||
git("commit", "--allow-empty", "-m", "First")
|
||||
previous = git("rev-parse", "HEAD")
|
||||
self.params.put("GitCommit", previous, block=True)
|
||||
git("commit", "--allow-empty", "-m", "Hotfix")
|
||||
current = git("rev-parse", "HEAD")
|
||||
self.owner.git_identity = _git_identity
|
||||
self.act("fast", "main")
|
||||
self.assertEqual(self.process.fast_requests, [{"branch": "main", "commit": current}])
|
||||
self.assertEqual(self.params.get("GitCommit"), previous)
|
||||
|
||||
def test_actual_checkout_race_still_prevents_dispatch(self):
|
||||
calls = 0
|
||||
def authorized():
|
||||
nonlocal calls
|
||||
calls += 1
|
||||
if calls == 3:
|
||||
self.git[self.installed] = ("main", "b" * 40)
|
||||
return True
|
||||
with self.assertRaises(SoftwareOperationError):
|
||||
self.owner.action("fast", {"action": "fast", "branch": "main"}, authorized=authorized)
|
||||
self.assertEqual(self.process.sent, [])
|
||||
|
||||
def test_missing_live_checkout_and_unknown_target_still_reject(self):
|
||||
self.git[self.installed] = None
|
||||
self.denied("fast", 409, "main")
|
||||
self.git[self.installed] = ("main", "b" * 40)
|
||||
self.denied("fast", 409, "unknown-branch")
|
||||
self.assertEqual(self.process.sent, [])
|
||||
|
||||
def test_fast_keeps_existing_admission_and_observes_failure(self):
|
||||
for key in ("DisableUpdates", "DoReboot"):
|
||||
self.params.put_bool(key, True, block=True)
|
||||
|
||||
Reference in New Issue
Block a user