Refresh default-sensitive shared templates without touching scripts.
(
project_path: Path,
*,
version: str,
core_pack: Path | None,
repo_root: Path,
console: Any,
invoke_separator: str,
force: bool = False,
)
| 298 | |
| 299 | |
| 300 | def refresh_shared_templates( |
| 301 | project_path: Path, |
| 302 | *, |
| 303 | version: str, |
| 304 | core_pack: Path | None, |
| 305 | repo_root: Path, |
| 306 | console: Any, |
| 307 | invoke_separator: str, |
| 308 | force: bool = False, |
| 309 | ) -> None: |
| 310 | """Refresh default-sensitive shared templates without touching scripts.""" |
| 311 | templates_src = shared_templates_source(core_pack=core_pack, repo_root=repo_root) |
| 312 | if not templates_src.is_dir(): |
| 313 | return |
| 314 | |
| 315 | manifest = load_speckit_manifest(project_path, version=version, console=console) |
| 316 | tracked_files = manifest.files |
| 317 | modified = set(manifest.check_modified()) |
| 318 | skipped_files: list[str] = [] |
| 319 | planned_updates: list[tuple[Path, str, str]] = [] |
| 320 | |
| 321 | dest_templates = project_path / ".specify" / "templates" |
| 322 | _ensure_safe_shared_directory(project_path, dest_templates) |
| 323 | for src in templates_src.iterdir(): |
| 324 | if not src.is_file() or src.name == "vscode-settings.json" or src.name.startswith("."): |
| 325 | continue |
| 326 | |
| 327 | dst = dest_templates / src.name |
| 328 | _ensure_safe_shared_destination(project_path, dst) |
| 329 | rel = dst.relative_to(project_path).as_posix() |
| 330 | if dst.exists() and not force: |
| 331 | if rel not in tracked_files or rel in modified: |
| 332 | skipped_files.append(rel) |
| 333 | continue |
| 334 | |
| 335 | content = src.read_text(encoding="utf-8") |
| 336 | content = IntegrationBase.resolve_command_refs(content, invoke_separator) |
| 337 | planned_updates.append((dst, rel, content)) |
| 338 | |
| 339 | for dst, rel, content in planned_updates: |
| 340 | _write_shared_text(project_path, dst, content) |
| 341 | manifest.record_existing(rel) |
| 342 | |
| 343 | manifest.save() |
| 344 | |
| 345 | if skipped_files: |
| 346 | console.print( |
| 347 | f"[yellow]⚠[/yellow] {len(skipped_files)} modified or untracked shared template file(s) were not updated:" |
| 348 | ) |
| 349 | for rel in skipped_files: |
| 350 | console.print(f" {rel}") |
| 351 | |
| 352 | |
| 353 | def install_shared_infra( |