diff --git a/src/Spago/Command/Fetch.purs b/src/Spago/Command/Fetch.purs index 768f21e32..3627ea875 100644 --- a/src/Spago/Command/Fetch.purs +++ b/src/Spago/Command/Fetch.purs @@ -217,7 +217,17 @@ run { packages: packagesRequestedToInstall, ensureRanges, isTest, isRepl } = do fetchPackagesToLocalCache :: ∀ a. Map PackageName Package -> Spago (FetchEnv a) Unit fetchPackagesToLocalCache packages = do - { offline } <- ask + { offline, workspace } <- ask + -- Build a map of expected integrities from the lockfile for verification + let + lockfileIntegrities :: Map (Tuple PackageName Version) Sha256 + lockfileIntegrities = case workspace.packageSet.lockfile of + Left _ -> Map.empty + Right lockfile -> Map.fromFoldable $ Array.mapMaybe extractRegistryIntegrity $ Map.toUnfoldable lockfile.packages + where + extractRegistryIntegrity = case _ of + Tuple name (FromRegistry { version, integrity }) -> Just $ Tuple (Tuple name version) integrity + _ -> Nothing -- Before starting to fetch packages we build a Map of AVars to act as locks for each git location. -- This is so we don't have two threads trying to clone the same repo at the same time. gitLocks <- liftAff $ map (Map.fromFoldable <<< List.catMaybes) $ for (Map.values packages) case _ of @@ -246,6 +256,17 @@ fetchPackagesToLocalCache packages = do Left err -> die $ "Couldn't read metadata, reason:\n " <> err Right versionMetadata -> do logDebug $ "Metadata read: " <> printJson Metadata.publishedMetadataCodec versionMetadata + -- Verify that the lockfile integrity matches the registry metadata + case Map.lookup (Tuple name v) lockfileIntegrities of + Just expectedIntegrity | expectedIntegrity /= versionMetadata.hash -> + logWarn $ Array.intercalate "\n" + [ "Package " <> packageVersion <> " has a different hash in the lockfile" + , " (" <> Sha256.print expectedIntegrity <> ")" + , "than in the registry metadata" + , " (" <> Sha256.print versionMetadata.hash <> ")." + , "This shouldn't really happen, so please open an issue at https://github.com/purescript/spago/issues" + ] + _ -> pure unit -- then check if we have a tarball cached. If not, download it let globalCachePackagePath = Paths.globalCachePath "packages" PackageName.print name let archivePath = globalCachePackagePath (versionString <> ".tar.gz")