@@ -91,13 +91,26 @@ handle env = case _ of
9191 UpgradeAtomic oldSet@(PackageSet { packages }) compiler changes reply -> reply <$> Except .runExcept do
9292 Log .info $ " Performing atomic upgrade of package set " <> Version .print (un PackageSet oldSet).version
9393
94- -- It is possible to reuse a workdir when processing package set batches, so
95- -- we need to clean up before doing work .
96- for_ [ packagesWorkDir, outputWorkDir, backupWorkDir ] \dir -> do
97- exists <- Run .liftEffect $ FS.Sync .exists dir
94+ -- Always clean up the backup directory, which is transient and may be
95+ -- left over from a previous crashed job .
96+ do
97+ exists <- Run .liftEffect $ FS.Sync .exists backupWorkDir
9898 when exists do
99- Log .debug $ " Removing existing working directory " <> dir
100- FS.Extra .remove dir
99+ Log .debug $ " Removing leftover backup directory " <> backupWorkDir
100+ FS.Extra .remove backupWorkDir
101+
102+ -- Wipe the compiler output if the compiler version has changed, because
103+ -- output from a different compiler version is not safe to reuse.
104+ when (compiler /= (un PackageSet oldSet).compiler) do
105+ outputExists <- Run .liftEffect $ FS.Sync .exists outputWorkDir
106+ when outputExists do
107+ Log .info $ " Compiler version changed, wiping output directory"
108+ FS.Extra .remove outputWorkDir
109+
110+ -- Sync the packages directory: remove any extraneous packages left from
111+ -- a previous job, then install missing ones. This lets the compiler do
112+ -- incremental compilation when resubmitting the same or similar jobs.
113+ syncPackages packages
101114
102115 installPackages packages
103116 compileInstalledPackages compiler >>= case _ of
@@ -183,6 +196,19 @@ handle env = case _ of
183196 backupWorkDir :: FilePath
184197 backupWorkDir = Path .concat [ env.workdir, " output-backup" ]
185198
199+ -- | Remove directories in packages/ that don't correspond to a package
200+ -- | in the target set. This prevents stale packages from being compiled.
201+ syncPackages :: Map PackageName Version -> Run _ Unit
202+ syncPackages targetPackages = do
203+ packagesExist <- Run .liftEffect $ FS.Sync .exists packagesWorkDir
204+ when packagesExist do
205+ existingDirs <- Run .liftAff $ FS.Aff .readdir packagesWorkDir
206+ let extraneous = extraneousPackageDirs targetPackages existingDirs
207+ unless (Array .null extraneous) do
208+ Log .info $ " Removing " <> show (Array .length extraneous) <> " extraneous packages from previous job: " <> String .joinWith " , " extraneous
209+ for_ extraneous \dir ->
210+ FS.Extra .remove (Path .concat [ packagesWorkDir, dir ])
211+
186212 printMissingCompiler version = " Compilation failed because compiler " <> Version .print version <> " is missing."
187213 printUnknownError error = " Compilation failed because of an unknown error: " <> error
188214 printCompilationError errors = " Compilation failed with errors:\n " <> Purs .printCompilerErrors errors
@@ -345,6 +371,13 @@ commitMessage (PackageSet set) accepted newVersion = String.joinWith "\n" $ fold
345371 Tuple packageName version <- removed
346372 pure $ Array .fold [ " - " , formatPackageVersion packageName version ]
347373
374+ -- | Compute directory names in packages/ that don't correspond to any package
375+ -- | in the target set and should be removed before compilation.
376+ extraneousPackageDirs :: Map PackageName Version -> Array String -> Array String
377+ extraneousPackageDirs targetPackages existingDirs = do
378+ let expectedDirs = Set .fromFoldable $ map (\(Tuple name version) -> formatPackageVersion name version) (Map .toUnfoldable targetPackages :: Array _ )
379+ Array .filter (\dir -> not (Set .member dir expectedDirs)) existingDirs
380+
348381-- | Computes new package set version from old package set and version information of successfully added/updated packages.
349382-- | Note: this must be called with the old `PackageSet` that has not had updates applied.
350383computeNewVersion :: Version -> PackageSet -> ChangeSet -> Version
0 commit comments