forgexa-cli 1.22.3__tar.gz → 1.22.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/PKG-INFO +1 -1
- {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/forgexa_cli/__init__.py +1 -1
- {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/forgexa_cli/daemon.py +48 -7
- {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/forgexa_cli.egg-info/PKG-INFO +1 -1
- {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/pyproject.toml +1 -1
- {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/README.md +0 -0
- {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/forgexa_cli/_build_config.py +0 -0
- {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/forgexa_cli/autoupgrade.py +0 -0
- {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/forgexa_cli/main.py +0 -0
- {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/forgexa_cli/py.typed +0 -0
- {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/forgexa_cli.egg-info/SOURCES.txt +0 -0
- {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/forgexa_cli.egg-info/dependency_links.txt +0 -0
- {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/forgexa_cli.egg-info/entry_points.txt +0 -0
- {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/forgexa_cli.egg-info/requires.txt +0 -0
- {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/forgexa_cli.egg-info/top_level.txt +0 -0
- {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/setup.cfg +0 -0
- {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/tests/test_auth_and_runtime_commands.py +0 -0
- {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/tests/test_autoupgrade.py +0 -0
- {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/tests/test_check_command.py +0 -0
- {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/tests/test_silent_install.py +0 -0
- {forgexa_cli-1.22.3 → forgexa_cli-1.22.4}/tests/test_upgrade_observability.py +0 -0
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"""forgexa-cli — Forgexa command-line client."""
|
|
2
|
-
__version__ = "1.22.
|
|
2
|
+
__version__ = "1.22.4"
|
|
@@ -555,7 +555,7 @@ except (ImportError, ModuleNotFoundError):
|
|
|
555
555
|
# DAEMON_VERSION is the protocol/logic version of the daemon code.
|
|
556
556
|
# Kept in sync with pyproject.toml version via bump-version.sh.
|
|
557
557
|
# CLIENT_TYPE identifies which packaging/distribution this daemon runs in.
|
|
558
|
-
DAEMON_VERSION = "1.22.
|
|
558
|
+
DAEMON_VERSION = "1.22.4"
|
|
559
559
|
|
|
560
560
|
|
|
561
561
|
def _detect_client_type() -> str:
|
|
@@ -2617,7 +2617,10 @@ class WorkspaceManager:
|
|
|
2617
2617
|
|
|
2618
2618
|
async def _remove_broken_worktree(self, main_repo: Path, ws_path: Path, workspace_key: str):
|
|
2619
2619
|
"""Remove a broken worktree directory and clean up stale worktree refs."""
|
|
2620
|
-
#
|
|
2620
|
+
# `git worktree prune` keeps an entry while its directory exists, even
|
|
2621
|
+
# when that directory's .git pointer is corrupt.
|
|
2622
|
+
self._safe_rmtree(ws_path)
|
|
2623
|
+
|
|
2621
2624
|
if main_repo.exists():
|
|
2622
2625
|
try:
|
|
2623
2626
|
await self._git("worktree", "prune", cwd=main_repo)
|
|
@@ -2627,9 +2630,6 @@ class WorkspaceManager:
|
|
|
2627
2630
|
wt_ref = main_repo / ".git" / "worktrees" / workspace_key
|
|
2628
2631
|
if wt_ref.exists():
|
|
2629
2632
|
self._safe_rmtree(wt_ref)
|
|
2630
|
-
# Remove the broken worktree directory using _safe_rmtree so that
|
|
2631
|
-
# read-only git objects on Windows are properly handled.
|
|
2632
|
-
self._safe_rmtree(ws_path)
|
|
2633
2633
|
|
|
2634
2634
|
async def _safe_rmtree_main(self, main_repo: Path) -> None:
|
|
2635
2635
|
"""Remove _main repo, first evicting all linked worktrees to prevent orphans.
|
|
@@ -2677,8 +2677,10 @@ class WorkspaceManager:
|
|
|
2677
2677
|
self,
|
|
2678
2678
|
main_repo: Path,
|
|
2679
2679
|
branch_name: str,
|
|
2680
|
+
*,
|
|
2681
|
+
healthy_only: bool = True,
|
|
2680
2682
|
) -> Path | None:
|
|
2681
|
-
"""Return
|
|
2683
|
+
"""Return a linked worktree already on branch_name."""
|
|
2682
2684
|
try:
|
|
2683
2685
|
raw = await self._git("worktree", "list", "--porcelain", cwd=main_repo)
|
|
2684
2686
|
except RuntimeError:
|
|
@@ -2704,7 +2706,9 @@ class WorkspaceManager:
|
|
|
2704
2706
|
for candidate_path, candidate_branch in entries:
|
|
2705
2707
|
if candidate_path == main_repo or candidate_branch != target_ref:
|
|
2706
2708
|
continue
|
|
2707
|
-
if candidate_path.exists()
|
|
2709
|
+
if not candidate_path.exists():
|
|
2710
|
+
continue
|
|
2711
|
+
if not healthy_only or await self._is_healthy_worktree(candidate_path, main_repo=main_repo):
|
|
2708
2712
|
return candidate_path
|
|
2709
2713
|
|
|
2710
2714
|
return None
|
|
@@ -3827,6 +3831,43 @@ class WorkspaceManager:
|
|
|
3827
3831
|
cwd=main_repo,
|
|
3828
3832
|
)
|
|
3829
3833
|
except Exception as exc:
|
|
3834
|
+
existing_branch_worktree = await self._find_existing_worktree_for_branch(
|
|
3835
|
+
main_repo, branch_name,
|
|
3836
|
+
)
|
|
3837
|
+
if existing_branch_worktree is not None:
|
|
3838
|
+
logger.info(
|
|
3839
|
+
"Fresh start reusing worktree %s after resetting %s to origin/%s",
|
|
3840
|
+
existing_branch_worktree, branch_name, default_branch,
|
|
3841
|
+
)
|
|
3842
|
+
await self._git(
|
|
3843
|
+
"checkout", "-B", branch_name, f"origin/{default_branch}",
|
|
3844
|
+
cwd=existing_branch_worktree,
|
|
3845
|
+
)
|
|
3846
|
+
return existing_branch_worktree
|
|
3847
|
+
|
|
3848
|
+
stale_branch_worktree = await self._find_existing_worktree_for_branch(
|
|
3849
|
+
main_repo, branch_name, healthy_only=False,
|
|
3850
|
+
)
|
|
3851
|
+
if stale_branch_worktree is not None:
|
|
3852
|
+
logger.warning(
|
|
3853
|
+
"Fresh start found broken worktree %s holding branch %s; removing it before retrying",
|
|
3854
|
+
stale_branch_worktree, branch_name,
|
|
3855
|
+
)
|
|
3856
|
+
try:
|
|
3857
|
+
await self._remove_broken_worktree(
|
|
3858
|
+
main_repo, stale_branch_worktree, stale_branch_worktree.name,
|
|
3859
|
+
)
|
|
3860
|
+
await self._git(
|
|
3861
|
+
"branch", "-f", branch_name, f"origin/{default_branch}",
|
|
3862
|
+
cwd=main_repo,
|
|
3863
|
+
)
|
|
3864
|
+
await self._git(
|
|
3865
|
+
"worktree", "add", str(ws_path), branch_name,
|
|
3866
|
+
cwd=main_repo,
|
|
3867
|
+
)
|
|
3868
|
+
return ws_path
|
|
3869
|
+
except Exception as recovery_exc:
|
|
3870
|
+
exc = recovery_exc
|
|
3830
3871
|
self._safe_rmtree(ws_path)
|
|
3831
3872
|
raise RuntimeError(
|
|
3832
3873
|
f"Failed to create clean fresh worktree for branch '{branch_name}'. "
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|