fix: lake: cache clean should succeed w/ no cache dir (#12532)
This PR fixes a bug with `cache clean` where it would fail if the cache directory does not exist. This introduces a `removeDirAllIfExists` utility which is also now used in `lake clean`. While `lake clean` did previously check for a nonexistent build directory, this version should be more robust to racing runs of `lake clean` as well.
This commit is contained in:
parent
61e09dd57e
commit
e2407589ff
4 changed files with 35 additions and 7 deletions
|
|
@ -549,7 +549,7 @@ protected def clean : CliM PUnit := do
|
|||
return cache.dir
|
||||
else
|
||||
error "no cache to delete; no workspace configuration found and no system cache detected"
|
||||
IO.FS.removeDirAll dir
|
||||
removeDirAllIfExists dir
|
||||
|
||||
protected def help : CliM PUnit := do
|
||||
IO.println <| helpCache <| ← takeArgD ""
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ public import Lake.Util.OrdHashSet
|
|||
public import Lake.Util.Name
|
||||
meta import all Lake.Util.OpaqueType
|
||||
import Lake.Util.OpaqueType
|
||||
import Lake.Util.IO
|
||||
|
||||
open System Lean
|
||||
|
||||
|
|
@ -407,5 +408,4 @@ public def isBuildableModule (mod : Name) (self : Package) : Bool :=
|
|||
|
||||
/-- Remove the package's build outputs (i.e., delete its build directory). -/
|
||||
public def clean (self : Package) : IO PUnit := do
|
||||
if (← self.buildDir.pathExists) then
|
||||
IO.FS.removeDirAll self.buildDir
|
||||
removeDirAllIfExists self.buildDir
|
||||
|
|
|
|||
|
|
@ -10,24 +10,48 @@ public import Init.System.IO
|
|||
|
||||
open System
|
||||
|
||||
set_option doc.verso true
|
||||
|
||||
namespace Lake
|
||||
|
||||
/-- Creates any missing parent directories of `path`. -/
|
||||
/-- Creates any missing parent directories of {lean}`path`. -/
|
||||
public def createParentDirs (path : FilePath) : IO Unit := do
|
||||
if let some dir := path.parent then IO.FS.createDirAll dir
|
||||
|
||||
/-- Remove the file at `path` if it exists. -/
|
||||
/-- Remove the file at {lean}`path` if it exists. -/
|
||||
public def removeFileIfExists (path : FilePath) : IO Unit := do
|
||||
try IO.FS.removeFile path catch
|
||||
| .noFileOrDirectory .. => pure ()
|
||||
| e => throw e
|
||||
|
||||
/-- Copy a file from `src` to `dst`. -/
|
||||
/--
|
||||
Remove a directory and all its contents.
|
||||
Like {lean}`IO.FS.removeDirAll`, but does not fail if {lean}`path` does not exist
|
||||
or if a file is first deleted by a racing process.
|
||||
-/
|
||||
public partial def removeDirAllIfExists (path : FilePath) : IO Unit := do
|
||||
let ents ← try path.readDir catch
|
||||
| .noFileOrDirectory .. => return -- path did not exist or something else was faster
|
||||
| e => throw e
|
||||
for ent in ents do
|
||||
-- Do not follow symlinks
|
||||
let mdata ← try ent.path.symlinkMetadata catch
|
||||
| .noFileOrDirectory .. => continue -- something else was faster
|
||||
| e => throw e
|
||||
if mdata.type == .dir then
|
||||
removeDirAllIfExists ent.path
|
||||
else
|
||||
removeFileIfExists ent.path
|
||||
try IO.FS.removeDir path catch
|
||||
| .noFileOrDirectory .. => return -- something else was faster
|
||||
| e => throw e
|
||||
|
||||
/-- Copy a file from {lean}`src` to {lean}`dst`. -/
|
||||
public def copyFile (src dst : FilePath) : IO Unit := do
|
||||
let contents ← IO.FS.readBinFile src
|
||||
IO.FS.writeBinFile dst contents
|
||||
|
||||
/-- Returns the normalized real path of a file if it exists. Otherwise, returns `""`. -/
|
||||
/-- Returns the normalized real path of a file if it exists. Otherwise, returns {lean}`""`. -/
|
||||
public def resolvePath (path : FilePath) : BaseIO FilePath := do
|
||||
match (← (IO.FS.realPath path).toBaseIO) with
|
||||
| .ok path =>
|
||||
|
|
|
|||
4
tests/lake/tests/cache/test.sh
vendored
4
tests/lake/tests/cache/test.sh
vendored
|
|
@ -11,6 +11,10 @@ TEST_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd)"
|
|||
CACHE_DIR="$(norm_path "$TEST_DIR")/.lake/cache"
|
||||
export LAKE_CACHE_DIR="$CACHE_DIR"
|
||||
|
||||
# Verify that `lake cache clean` works without a cache directory
|
||||
test_exp ! -d "$CACHE_DIR"
|
||||
test_run cache clean
|
||||
|
||||
# Verify packages without `enableArtifactCache` do not use the cache by default
|
||||
test_run build -f unset.toml Test:static
|
||||
test_exp ! -d "$CACHE_DIR"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue