luv-cli 0.0.19__tar.gz → 0.0.20__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: luv-cli
3
- Version: 0.0.19
3
+ Version: 0.0.20
4
4
  Summary: Launch Claude Code agents on GitHub repos with isolated workspaces and optional Docker dev environments
5
5
  Project-URL: Homepage, https://github.com/exospherehost/luv
6
6
  Project-URL: Repository, https://github.com/exospherehost/luv
@@ -411,10 +411,36 @@ def _on_rm_error(func, path, _exc):
411
411
  func(path)
412
412
 
413
413
 
414
+ def _docker_wipe(path: Path) -> bool:
415
+ """rm -rf `path` from inside a busybox container so the container's root can
416
+ delete files that a previous container bind-mounted in as root (e.g. Rust
417
+ target dirs built inside the workspace's dev-environment). Returns True on
418
+ success. No-op if docker isn't available."""
419
+ if shutil.which("docker") is None:
420
+ return False
421
+ parent = path.resolve().parent
422
+ name = path.name
423
+ r = subprocess.run(
424
+ ["docker", "run", "--rm",
425
+ "-v", f"{parent}:/p",
426
+ "busybox", "rm", "-rf", f"/p/{name}"],
427
+ capture_output=True, text=True,
428
+ )
429
+ if r.returncode != 0:
430
+ sys.stderr.write(f"luv: docker rm fallback failed for {path}: {r.stderr.strip()}\n")
431
+ return False
432
+ return not path.exists()
433
+
434
+
414
435
  def _force_rmtree(path: Path) -> None:
415
- """rmtree that chmods read-only files (e.g. uv's CACHEDIR.TAG) instead of crashing."""
436
+ """rmtree that survives read-only files (chmod-and-retry) and root-owned
437
+ files left behind by Docker bind-mounts (containerized rm -rf fallback)."""
416
438
  kwargs = {"onexc": _on_rm_error} if sys.version_info >= (3, 12) else {"onerror": _on_rm_error}
417
- shutil.rmtree(path, **kwargs)
439
+ try:
440
+ shutil.rmtree(path, **kwargs)
441
+ except PermissionError:
442
+ if not _docker_wipe(path):
443
+ raise
418
444
 
419
445
 
420
446
  def cmd_clean(force: bool = False, safe: bool = False) -> None:
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "luv-cli"
7
- version = "0.0.19"
7
+ version = "0.0.20"
8
8
  description = "Launch Claude Code agents on GitHub repos with isolated workspaces and optional Docker dev environments"
9
9
  requires-python = ">=3.10"
10
10
  license = "MIT"
File without changes
File without changes
File without changes
File without changes