Stop tracking workspace/; bundled-demos/ is the canonical demo source
`workspace/` is runtime state (per-user folders, no-auth dev's `code/`) and shouldn't be in git. The same files were previously committed under both `workspace/code/` and `src/static/bundled-demos/`, which forced a Docker `diff -q` sync check and leaked user-scoped paths into version control. - /workspace/ added to .gitignore; all previously tracked files removed via `git rm --cached`. - src/static/bundled-demos/ becomes the single source of truth: panel16 demos, led_tutorial, led_patterns, neopixel demos, and main.py move here alongside the existing canonical demos. - New BUNDLED_DEMOS_DIR config; user_workspace seeders read from it. - main.py lifespan seeds WORKSPACE_ROOT/code/ on startup so a fresh clone running `pipenv run dev` still gets the full sample set (existing files never overwritten — user edits survive restarts). - Dockerfile drops `COPY workspace` and the diff sanity check. - README/LED_TUTORIAL repointed at the new canonical paths. - test_led_patterns loads led_patterns.py from bundled-demos. - test_api uses mkdir(exist_ok=True) for `code/` (startup pre-creates). Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -34,7 +34,13 @@ def user_workspace_root(user_id: int, username: str, workspace_root: Path | None
|
||||
|
||||
|
||||
def _seed_canonical_demos_into_code(code_dir: Path) -> None:
|
||||
src_root = config.PROJECT_ROOT.resolve() / "workspace" / "code"
|
||||
"""Copy bundled demos into a user's `code/` if missing.
|
||||
|
||||
Reads from `BUNDLED_DEMOS_DIR` (single source of truth, ships under
|
||||
`src/static/bundled-demos/`), never from `workspace/`, so this works
|
||||
even when `workspace/` is empty (gitignored runtime directory).
|
||||
"""
|
||||
src_root = config.BUNDLED_DEMOS_DIR.resolve()
|
||||
for filename in _CANONICAL_DEMO_FILENAMES:
|
||||
dst = code_dir / filename
|
||||
if dst.exists():
|
||||
@@ -45,7 +51,12 @@ def _seed_canonical_demos_into_code(code_dir: Path) -> None:
|
||||
|
||||
|
||||
def ensure_default_code_main(user_root: Path) -> None:
|
||||
"""Ensure code/ has main.py and self-contained NeoPixel demos (copied from repo workspace/code/)."""
|
||||
"""Ensure code/ has main.py and the canonical NeoPixel demos.
|
||||
|
||||
Demos are sourced from `BUNDLED_DEMOS_DIR` (the single committed home
|
||||
for sample scripts). Only files listed in `_CANONICAL_DEMO_FILENAMES`
|
||||
get auto-seeded — the rest are available via the editor's "Reset
|
||||
demos" button or a manual copy."""
|
||||
code_dir = user_root / "code"
|
||||
code_dir.mkdir(parents=True, exist_ok=True)
|
||||
main_py = code_dir / "main.py"
|
||||
@@ -54,6 +65,34 @@ def ensure_default_code_main(user_root: Path) -> None:
|
||||
_seed_canonical_demos_into_code(code_dir)
|
||||
|
||||
|
||||
def seed_all_bundled_demos(user_root: Path) -> None:
|
||||
"""Copy *every* file in `BUNDLED_DEMOS_DIR` into `<user_root>/code/`.
|
||||
|
||||
Used at app startup to populate a fresh `workspace/code/` with the
|
||||
full sample set so a no-auth dev install (`pipenv run dev` after
|
||||
`git clone`) has something to play with. Existing files are not
|
||||
overwritten — user edits are preserved.
|
||||
"""
|
||||
code_dir = user_root / "code"
|
||||
code_dir.mkdir(parents=True, exist_ok=True)
|
||||
main_py = code_dir / "main.py"
|
||||
if not main_py.exists():
|
||||
main_py.write_text(DEFAULT_MAIN_PY, encoding="utf-8")
|
||||
src_root = config.BUNDLED_DEMOS_DIR.resolve()
|
||||
if not src_root.is_dir():
|
||||
return
|
||||
for src in sorted(src_root.iterdir()):
|
||||
if not src.is_file() or not src.name.endswith(".py"):
|
||||
continue
|
||||
dst = code_dir / src.name
|
||||
if dst.exists():
|
||||
continue
|
||||
try:
|
||||
dst.write_text(src.read_text(encoding="utf-8"), encoding="utf-8")
|
||||
except (UnicodeDecodeError, OSError):
|
||||
continue
|
||||
|
||||
|
||||
def rename_user_workspace_leaf(
|
||||
user_id: int, old_username: str, new_username: str, workspace_root: Path | None = None
|
||||
) -> None:
|
||||
|
||||
Reference in New Issue
Block a user