Skip to content

Commit e5f22c3

Browse files
mnriemCopilot
andcommitted
fix: implicitly add --force when only engine-owned dirs exist
When the workflow engine creates .specify/workflows/runs/ before steps execute, the directory is technically non-empty. Previously, specify init would prompt for confirmation (hanging in unattended mode) unless the user explicitly set force: true. Now the step detects that only engine-owned directories (.specify/) are present and implicitly adds --force so init proceeds without user interaction. Also fixes the test to exercise the implicit-force path rather than passing force: True explicitly (which bypassed the check entirely). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent adff325 commit e5f22c3

2 files changed

Lines changed: 14 additions & 5 deletions

File tree

src/specify_cli/workflows/steps/init/__init__.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,18 +107,21 @@ def execute(self, config: dict[str, Any], context: StepContext) -> StepResult:
107107
# ``specify init`` prompts for confirmation if the directory is not
108108
# empty. Workflows run unattended (no stdin), so the prompt would
109109
# abort with a confusing error. Fail fast with an actionable message.
110+
# Exception: if the only pre-existing content is engine-owned (e.g.
111+
# .specify/workflows/runs/), treat it as implicitly empty and auto-add
112+
# --force so init can proceed unattended.
110113
targets_current_dir = here or not project or str(project) == "."
111114
if targets_current_dir and not force:
112115
base = context.project_root or os.getcwd()
113116
try:
114117
with os.scandir(base) as it:
115-
not_empty = any(
118+
non_engine_entries = [
116119
entry for entry in it
117120
if entry.name not in _ENGINE_OWNED_DIRS
118-
)
121+
]
119122
except OSError:
120-
not_empty = False
121-
if not_empty:
123+
non_engine_entries = []
124+
if non_engine_entries:
122125
error_message = (
123126
f"Target directory {base!r} is not empty. Set "
124127
"'force: true' to merge into a non-empty directory."
@@ -138,6 +141,10 @@ def execute(self, config: dict[str, Any], context: StepContext) -> StepResult:
138141
},
139142
error=error_message,
140143
)
144+
else:
145+
# Only engine-owned dirs exist — implicitly force so specify
146+
# init doesn't prompt about the non-empty directory.
147+
force = True
141148

142149
if integration:
143150
argv.extend(["--integration", str(integration)])

tests/test_workflows.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1086,10 +1086,12 @@ def test_engine_owned_dirs_do_not_trigger_non_empty_check(self, tmp_path):
10861086
project_root=str(tmp_path), default_integration="copilot"
10871087
)
10881088
result = step.execute(
1089-
{"id": "bootstrap", "here": True, "script": "sh", "force": True},
1089+
{"id": "bootstrap", "here": True, "script": "sh"},
10901090
ctx,
10911091
)
10921092
assert result.status == StepStatus.COMPLETED
1093+
# Verify --force was implicitly added
1094+
assert "--force" in result.output["argv"]
10931095

10941096
def test_default_integration_when_none_provided(self, tmp_path):
10951097
from specify_cli.workflows.steps.init import InitStep

0 commit comments

Comments
 (0)