1
1
mirror of https://github.com/anoma/juvix.git synced 2024-10-26 17:52:17 +03:00

Update the Juvix lock file when the Package file changes (#2522)

Adds a new version of the lock file that stores the hash (sha256 digest)
of the package file (Package.juvix, juvix.yaml) it was generated from as
a field:

```
# This file was autogenerated by Juvix version 0.5.4.
# Do not edit this file manually.

version: 2
checksum: d05940a4d3dc0e15451d02e1294819c875ba486ee54e26865ba8d190ac7c27c3
dependencies:
- git:
    name: stdlib
    ref: f68b0614ad695eaa13ead42f3466e0a78219f826
    url: https://github.com/anoma/juvix-stdlib.git
  dependencies: []
```

The lock file is regenerated when the hash of the package file doesn't
match the value of the `checksum` field, i.e when the user updates the
package file.

Existing lock files are automatically migrated to version 2.

* Closes https://github.com/anoma/juvix/issues/2464
This commit is contained in:
Paul Cadman 2023-11-22 22:21:29 +00:00 committed by GitHub
parent c6586a960d
commit 1c1a5b7117
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 282 additions and 224 deletions

View File

@ -198,6 +198,14 @@ jobs:
run: | run: |
sed --version sed --version
- name: Install coreutils
run: |
brew install coreutils
- name: Test sha256sum (used by smoke)
run: |
sha256sum --version
- name: Download and extract wasi-sysroot - name: Download and extract wasi-sysroot
run: > run: >
curl curl

View File

@ -240,10 +240,12 @@ fast-test-skip-slow:
@${STACK} test --fast ${STACKFLAGS} ${STACKTESTFLAGS} --ta '-p "! /slow tests/"' @${STACK} test --fast ${STACKFLAGS} ${STACKTESTFLAGS} --ta '-p "! /slow tests/"'
SMOKE := $(shell command -v smoke 2> /dev/null) SMOKE := $(shell command -v smoke 2> /dev/null)
SHA256SUM := $(shell command -v sha256sum 2> /dev/null)
.PHONY : smoke-only .PHONY : smoke-only
smoke-only: smoke-only:
@$(if $(SMOKE),, $(error "Smoke not found, please install it from https://github.com/jonaprieto/smoke")) @$(if $(SMOKE),, $(error "Smoke not found, please install it from https://github.com/jonaprieto/smoke"))
@$(if $(SHA256SUM),, $(error "sha256sum not found, please install the GNU coreutils package (e.g {apt, brew} install coreutils)"))
@smoke $(shell find tests -name '*.smoke.yaml') @smoke $(shell find tests -name '*.smoke.yaml')
.PHONY : smoke .PHONY : smoke

View File

@ -45,9 +45,11 @@ dependencies:
- aeson == 2.1.* - aeson == 2.1.*
- ansi-terminal == 0.11.* - ansi-terminal == 0.11.*
- base == 4.17.* - base == 4.17.*
- base16-bytestring == 1.0.*
- blaze-html == 0.9.* - blaze-html == 0.9.*
- bytestring == 0.11.* - bytestring == 0.11.*
- containers == 0.6.* - containers == 0.6.*
- cryptohash-sha256 == 0.11.*
- directory == 1.3.* - directory == 1.3.*
- dlist == 1.0.* - dlist == 1.0.*
- edit-distance == 0.2.* - edit-distance == 0.2.*

View File

@ -26,6 +26,7 @@ import Juvix.Compiler.Pipeline.Package
import Juvix.Compiler.Pipeline.Package.Loader.EvalEff import Juvix.Compiler.Pipeline.Package.Loader.EvalEff
import Juvix.Data.Effect.Git import Juvix.Data.Effect.Git
import Juvix.Data.Effect.TaggedLock import Juvix.Data.Effect.TaggedLock
import Juvix.Data.SHA256 qualified as SHA256
import Juvix.Extra.Paths import Juvix.Extra.Paths
import Juvix.Extra.Stdlib (ensureStdlib) import Juvix.Extra.Stdlib (ensureStdlib)
import Juvix.Prelude import Juvix.Prelude
@ -175,15 +176,26 @@ registerDependencies' conf = do
void (addRootDependency conf e glob) void (addRootDependency conf e glob)
| otherwise -> do | otherwise -> do
lockfile <- addRootDependency conf e (e ^. entryPointRoot) lockfile <- addRootDependency conf e (e ^. entryPointRoot)
root <- asks (^. envRoot) whenM shouldWriteLockfile $ do
whenM shouldWriteLockfile (writeLockfile root lockfile) packageFileChecksum <- SHA256.digestFile (e ^. entryPointPackage . packageFile)
lockfilePath' <- lockfilePath
writeLockfile lockfilePath' packageFileChecksum lockfile
where where
shouldWriteLockfile :: Sem r Bool shouldWriteLockfile :: Sem r Bool
shouldWriteLockfile = do shouldWriteLockfile = do
lockfileExists <- lockfilePath >>= fileExists'
hasRemoteDependencies <- gets (^. resolverHasRemoteDependencies)
shouldUpdateLockfile' <- gets (^. resolverShouldUpdateLockfile)
let shouldForce = conf ^. dependenciesConfigForceUpdateLockfile
shouldWriteInitialLockfile = not lockfileExists && hasRemoteDependencies
shouldUpdateLockfile = lockfileExists && shouldUpdateLockfile'
return (shouldForce || shouldWriteInitialLockfile || shouldUpdateLockfile)
lockfilePath :: Sem r (Path Abs File)
lockfilePath = do
root <- asks (^. envRoot) root <- asks (^. envRoot)
lockfileExists <- fileExists' (mkPackageLockfilePath root) return (mkPackageLockfilePath root)
depsShouldWriteLockfile <- gets (^. resolverShouldWriteLockfile)
return (conf ^. dependenciesConfigForceUpdateLockfile || not lockfileExists && depsShouldWriteLockfile)
addRootDependency :: addRootDependency ::
forall r. forall r.
@ -196,15 +208,23 @@ addRootDependency conf e root = do
let pf = mkPackageFilePath root let pf = mkPackageFilePath root
d = mkPackageDependencyInfo pf (mkPathDependency (toFilePath root)) d = mkPackageDependencyInfo pf (mkPathDependency (toFilePath root))
resolvedDependency <- resolveDependency d resolvedDependency <- resolveDependency d
checkShouldWriteLockfile resolvedDependency checkRemoteDependency resolvedDependency
let p = resolvedDependency ^. resolvedDependencyPath let p = resolvedDependency ^. resolvedDependencyPath
withEnvRoot p $ do withEnvRoot p $ do
pkg <- mkPackage (Just e) p pkg <- mkPackage (Just e) p
shouldUpdateLockfile' <- shouldUpdateLockfile pkg
when shouldUpdateLockfile' setShouldUpdateLockfile
let resolvedPkg :: Package let resolvedPkg :: Package
| conf ^. dependenciesConfigForceUpdateLockfile = unsetPackageLockfile pkg | shouldUpdateLockfile' = unsetPackageLockfile pkg
| otherwise = pkg | otherwise = pkg
deps <- addDependency' resolvedPkg (Just e) resolvedDependency deps <- addDependency' resolvedPkg (Just e) resolvedDependency
return Lockfile {_lockfileDependencies = deps ^. lockfileDependencyDependencies} return Lockfile {_lockfileDependencies = deps ^. lockfileDependencyDependencies}
where
shouldUpdateLockfile :: Package -> Sem r Bool
shouldUpdateLockfile pkg = do
let checksumMay :: Maybe Text = pkg ^? packageLockfile . _Just . lockfileInfoChecksum . _Just
packageFileChecksum <- SHA256.digestFile (pkg ^. packageFile)
return (conf ^. dependenciesConfigForceUpdateLockfile || Just packageFileChecksum /= checksumMay)
addDependency :: addDependency ::
forall r. forall r.
@ -214,7 +234,7 @@ addDependency ::
Sem r LockfileDependency Sem r LockfileDependency
addDependency me d = do addDependency me d = do
resolvedDependency <- resolveDependency d resolvedDependency <- resolveDependency d
checkShouldWriteLockfile resolvedDependency checkRemoteDependency resolvedDependency
let p = resolvedDependency ^. resolvedDependencyPath let p = resolvedDependency ^. resolvedDependencyPath
cached <- lookupCachedDependency p cached <- lookupCachedDependency p
case cached of case cached of

View File

@ -23,7 +23,8 @@ data ResolverState = ResolverState
_resolverFiles :: HashMap (Path Rel File) (NonEmpty PackageInfo), _resolverFiles :: HashMap (Path Rel File) (NonEmpty PackageInfo),
-- | PackageInfos indexed by root -- | PackageInfos indexed by root
_resolverCache :: HashMap (Path Abs Dir) ResolverCacheItem, _resolverCache :: HashMap (Path Abs Dir) ResolverCacheItem,
_resolverShouldWriteLockfile :: Bool _resolverHasRemoteDependencies :: Bool,
_resolverShouldUpdateLockfile :: Bool
} }
deriving stock (Show) deriving stock (Show)
@ -42,12 +43,19 @@ iniResolverState =
ResolverState ResolverState
{ _resolverCache = mempty, { _resolverCache = mempty,
_resolverFiles = mempty, _resolverFiles = mempty,
_resolverShouldWriteLockfile = False _resolverHasRemoteDependencies = False,
_resolverShouldUpdateLockfile = False
} }
checkShouldWriteLockfile :: (Member (State ResolverState) r) => ResolvedDependency -> Sem r () setHasRemoteDependencies :: (Member (State ResolverState) r) => Sem r ()
checkShouldWriteLockfile d = case d ^. resolvedDependencyDependency of setHasRemoteDependencies = modify' (set resolverHasRemoteDependencies True)
DependencyGit {} -> modify' (set resolverShouldWriteLockfile True)
setShouldUpdateLockfile :: (Member (State ResolverState) r) => Sem r ()
setShouldUpdateLockfile = modify' (set resolverShouldUpdateLockfile True)
checkRemoteDependency :: (Member (State ResolverState) r) => ResolvedDependency -> Sem r ()
checkRemoteDependency d = case d ^. resolvedDependencyDependency of
DependencyGit {} -> setHasRemoteDependencies
DependencyPath {} -> return () DependencyPath {} -> return ()
withEnvRoot :: (Members '[Reader ResolverEnv] r) => Path Abs Dir -> Sem r a -> Sem r a withEnvRoot :: (Members '[Reader ResolverEnv] r) => Path Abs Dir -> Sem r a -> Sem r a

View File

@ -7,6 +7,7 @@ import Data.Aeson.BetterErrors qualified as Aeson
import Data.Aeson.Encoding (pair) import Data.Aeson.Encoding (pair)
import Data.Aeson.TH import Data.Aeson.TH
import Data.String.Interpolate (i) import Data.String.Interpolate (i)
import Data.Text qualified as T
import Data.Yaml import Data.Yaml
import Data.Yaml.Pretty import Data.Yaml.Pretty
import Juvix.Compiler.Pipeline.Package.Dependency import Juvix.Compiler.Pipeline.Package.Dependency
@ -29,16 +30,59 @@ newtype Lockfile = Lockfile
} }
deriving stock (Generic, Show, Eq) deriving stock (Generic, Show, Eq)
type LockfileV1 = Lockfile
data LockfileV2 = LockfileV2
{ _lockfileV2Version :: Int,
_lockfileV2Checksum :: Text,
_lockfileV2Dependencies :: [LockfileDependency]
}
deriving stock (Generic, Show, Eq)
data VersionedLockfile
= V1Lockfile LockfileV1
| V2Lockfile LockfileV2
deriving stock (Show, Eq)
data LockfileVersionTag
= LockfileV1Tag
| LockfileV2Tag
deriving stock (Show, Eq)
allVersionedLockfiles :: [LockfileVersionTag]
allVersionedLockfiles = [LockfileV1Tag, LockfileV2Tag]
lockfileVersionNumber :: LockfileVersionTag -> Int
lockfileVersionNumber = \case
LockfileV1Tag -> 1
LockfileV2Tag -> 2
data LockfileInfo = LockfileInfo data LockfileInfo = LockfileInfo
{ _lockfileInfoPath :: Path Abs File, { _lockfileInfoPath :: Path Abs File,
_lockfileInfoChecksum :: Maybe Text,
_lockfileInfoLockfile :: Lockfile _lockfileInfoLockfile :: Lockfile
} }
deriving stock (Eq, Show) deriving stock (Eq, Show)
makeLenses ''LockfileDependency makeLenses ''LockfileDependency
makeLenses ''Lockfile makeLenses ''Lockfile
makeLenses ''LockfileV2
makeLenses ''LockfileInfo makeLenses ''LockfileInfo
mkLockfileV2 :: Text -> [LockfileDependency] -> LockfileV2
mkLockfileV2 _lockfileV2Checksum _lockfileV2Dependencies =
LockfileV2 {_lockfileV2Version = lockfileVersionNumber LockfileV2Tag, ..}
lockfile' :: SimpleGetter VersionedLockfile Lockfile
lockfile' = to $ \case
V1Lockfile l -> l
V2Lockfile l -> Lockfile {_lockfileDependencies = l ^. lockfileV2Dependencies}
checksum :: SimpleGetter VersionedLockfile (Maybe Text)
checksum = to $ \case
V1Lockfile {} -> Nothing
V2Lockfile l -> Just (l ^. lockfileV2Checksum)
instance ToJSON LockfileDependency where instance ToJSON LockfileDependency where
toJSON d = object [dep, Str.dependencies .= toJSON (d ^. lockfileDependencyDependencies)] toJSON d = object [dep, Str.dependencies .= toJSON (d ^. lockfileDependencyDependencies)]
where where
@ -65,20 +109,50 @@ instance FromJSON LockfileDependency where
p' :: Parse' Dependency p' :: Parse' Dependency
p' = DependencyPath <$> (key Str.path_ fromAesonParser) Aeson.<|> DependencyGit <$> (key Str.git fromAesonParser) p' = DependencyPath <$> (key Str.path_ fromAesonParser) Aeson.<|> DependencyGit <$> (key Str.git fromAesonParser)
lockfileOptions :: Options lockfileV2Options :: Options
lockfileOptions = lockfileV2Options =
defaultOptions defaultOptions
{ fieldLabelModifier = over Lens._head toLower . dropPrefix "_lockfile", { fieldLabelModifier = over Lens._head toLower . dropPrefix "_lockfileV2",
rejectUnknownFields = True, rejectUnknownFields = True,
omitNothingFields = True omitNothingFields = True
} }
instance ToJSON Lockfile where instance ToJSON LockfileV2 where
toJSON = genericToJSON lockfileOptions toJSON = genericToJSON lockfileV2Options
toEncoding = genericToEncoding lockfileOptions toEncoding = genericToEncoding lockfileV2Options
instance FromJSON Lockfile where data LockfileParseErr = LockfileUnsupportedVersion
parseJSON = toAesonParser' (Lockfile <$> (key Str.dependencies fromAesonParser))
instance FromJSON VersionedLockfile where
parseJSON = toAesonParser displayErr $ do
v <- parseVersion
case v of
LockfileV1Tag -> V1Lockfile <$> parseV1
LockfileV2Tag -> V2Lockfile <$> parseV2
where
parseV1 :: Parse LockfileParseErr Lockfile
parseV1 = Lockfile <$> key Str.dependencies fromAesonParser
parseV2 :: Parse LockfileParseErr LockfileV2
parseV2 = do
checksum' <- key "checksum" asText
deps <- key Str.dependencies fromAesonParser
return (mkLockfileV2 checksum' deps)
parseVersion :: Parse LockfileParseErr LockfileVersionTag
parseVersion = fromMaybeM (return LockfileV1Tag) (keyMay Str.version parseVersion')
where
parseVersion' :: Parse LockfileParseErr LockfileVersionTag
parseVersion' = do
n <- asIntegral
if
| lockfileVersionNumber LockfileV1Tag == n -> return LockfileV1Tag
| lockfileVersionNumber LockfileV2Tag == n -> return LockfileV2Tag
| otherwise -> throwCustomError LockfileUnsupportedVersion
displayErr :: LockfileParseErr -> Text
displayErr = \case
LockfileUnsupportedVersion -> "lockfile error: unsupported version. Supported versions: " <> T.intercalate ", " (show . lockfileVersionNumber <$> allVersionedLockfiles)
mkPackageLockfilePath :: Path Abs Dir -> Path Abs File mkPackageLockfilePath :: Path Abs Dir -> Path Abs File
mkPackageLockfilePath = (<//> juvixLockfile) mkPackageLockfilePath = (<//> juvixLockfile)
@ -93,11 +167,16 @@ mayReadLockfile root = do
if if
| lockfileExists -> do | lockfileExists -> do
bs <- readFileBS' lockfilePath bs <- readFileBS' lockfilePath
either (throwErr . pack . prettyPrintParseException) ((return . Just) . mkLockfileInfo lockfilePath) (decodeEither' @Lockfile bs) either (throwErr . pack . prettyPrintParseException) ((return . Just) . mkLockfileInfo lockfilePath) (decodeEither' @VersionedLockfile bs)
| otherwise -> return Nothing | otherwise -> return Nothing
where where
mkLockfileInfo :: Path Abs File -> Lockfile -> LockfileInfo mkLockfileInfo :: Path Abs File -> VersionedLockfile -> LockfileInfo
mkLockfileInfo _lockfileInfoPath _lockfileInfoLockfile = LockfileInfo {..} mkLockfileInfo _lockfileInfoPath vl =
LockfileInfo
{ _lockfileInfoChecksum = vl ^. checksum,
_lockfileInfoLockfile = vl ^. lockfile',
..
}
lockfilePath :: Path Abs File lockfilePath :: Path Abs File
lockfilePath = mkPackageLockfilePath root lockfilePath = mkPackageLockfilePath root
@ -115,21 +194,23 @@ mayReadLockfile root = do
lockfileEncodeConfig :: Config lockfileEncodeConfig :: Config
lockfileEncodeConfig = setConfCompare keyCompare defConfig lockfileEncodeConfig = setConfCompare keyCompare defConfig
where where
-- serialize the dependencies after all other keys -- serialize the dependencies field after all other keys and the version
-- field before all other keys
keyCompare :: Text -> Text -> Ordering keyCompare :: Text -> Text -> Ordering
keyCompare x y = keyCompare x y =
if if
| y == Str.dependencies || x == Str.dependencies -> GT | y == Str.dependencies -> LT
| x == Str.dependencies -> GT
| x == Str.version -> LT
| y == Str.version -> GT
| otherwise -> compare x y | otherwise -> compare x y
writeLockfile :: (Members '[Files] r) => Path Abs Dir -> Lockfile -> Sem r () writeLockfile :: (Members '[Files] r) => Path Abs File -> Text -> Lockfile -> Sem r ()
writeLockfile root lf = do writeLockfile lockfilePath checksum' lf = do
ensureDir' (parent lockfilePath) ensureDir' (parent lockfilePath)
writeFileBS lockfilePath (header <> encodePretty lockfileEncodeConfig lf) let v2lf = mkLockfileV2 checksum' (lf ^. lockfileDependencies)
writeFileBS lockfilePath (header <> encodePretty lockfileEncodeConfig v2lf)
where where
lockfilePath :: Path Abs File
lockfilePath = mkPackageLockfilePath root
header :: ByteString header :: ByteString
header = [i|\# This file was autogenerated by Juvix version #{versionDoc}.\n\# Do not edit this file manually.\n\n|] header = [i|\# This file was autogenerated by Juvix version #{versionDoc}.\n\# Do not edit this file manually.\n\n|]

View File

@ -27,7 +27,7 @@ data LoaderResource = LoaderResource
makeLenses ''LoaderResource makeLenses ''LoaderResource
runEvalFileEffIO :: forall r a. (Members '[TaggedLock, Embed IO, Error PackageLoaderError] r) => Sem (EvalFileEff ': r) a -> Sem r a runEvalFileEffIO :: forall r a. (Members '[TaggedLock, Files, Embed IO, Error PackageLoaderError] r) => Sem (EvalFileEff ': r) a -> Sem r a
runEvalFileEffIO = interpretScopedAs allocator handler runEvalFileEffIO = interpretScopedAs allocator handler
where where
allocator :: Path Abs File -> Sem r LoaderResource allocator :: Path Abs File -> Sem r LoaderResource
@ -115,7 +115,7 @@ runEvalFileEffIO = interpretScopedAs allocator handler
Just l -> l ^. intervalFile == f Just l -> l ^. intervalFile == f
Nothing -> False Nothing -> False
loadPackage' :: (Members '[TaggedLock, Embed IO, Error PackageLoaderError] r) => Path Abs File -> Sem r CoreResult loadPackage' :: (Members '[TaggedLock, Files, Embed IO, Error PackageLoaderError] r) => Path Abs File -> Sem r CoreResult
loadPackage' packagePath = do loadPackage' packagePath = do
( mapError ( mapError
( \e -> ( \e ->
@ -127,7 +127,6 @@ loadPackage' packagePath = do
. evalInternetOffline . evalInternetOffline
. ignoreHighlightBuilder . ignoreHighlightBuilder
. runProcessIO . runProcessIO
. runFilesIO
. evalTopBuiltins . evalTopBuiltins
. evalTopNameIdGen . evalTopNameIdGen
. evalTopBuiltins . evalTopBuiltins

9
src/Juvix/Data/SHA256.hs Normal file
View File

@ -0,0 +1,9 @@
module Juvix.Data.SHA256 where
import Crypto.Hash.SHA256 qualified as SHA256
import Data.ByteString.Base16 qualified as Base16
import Juvix.Prelude
-- | Create a HEX encoded, SHA256 digest of the contents of a file.
digestFile :: (Member Files r) => Path Abs File -> Sem r Text
digestFile = fmap (decodeUtf8Lenient . Base16.encode . SHA256.hash) . readFileBS'

View File

@ -802,3 +802,6 @@ path_ = "path"
package :: (IsString s) => s package :: (IsString s) => s
package = "package" package = "package"
version :: (IsString s) => s
version = "version"

View File

@ -6,9 +6,15 @@ module Juvix.Prelude.Aeson
where where
import Data.Aeson import Data.Aeson
import Data.Aeson.KeyMap qualified as KeyMap
import Data.Aeson.Text import Data.Aeson.Text
import Data.Text.Lazy qualified as Lazy import Data.Text.Lazy qualified as Lazy
import Juvix.Prelude.Base import Juvix.Prelude.Base
encodeToText :: (ToJSON a) => a -> Text encodeToText :: (ToJSON a) => a -> Text
encodeToText = Lazy.toStrict . encodeToLazyText encodeToText = Lazy.toStrict . encodeToLazyText
appendFields :: [(Key, Value)] -> Value -> Value
appendFields keyValues = \case
Object obj -> Object (KeyMap.fromList keyValues <> obj)
a -> a

View File

@ -10,6 +10,7 @@ import Juvix.Compiler.Concrete.Print qualified as P
import Juvix.Compiler.Concrete.Translation.FromParsed.Analysis.PathResolver import Juvix.Compiler.Concrete.Translation.FromParsed.Analysis.PathResolver
import Juvix.Compiler.Concrete.Translation.FromParsed.Analysis.Scoping qualified as Scoper import Juvix.Compiler.Concrete.Translation.FromParsed.Analysis.Scoping qualified as Scoper
import Juvix.Compiler.Concrete.Translation.FromSource qualified as Parser import Juvix.Compiler.Concrete.Translation.FromSource qualified as Parser
import Juvix.Compiler.Pipeline.Package.Loader
import Juvix.Compiler.Pipeline.Package.Loader.Error import Juvix.Compiler.Pipeline.Package.Loader.Error
import Juvix.Compiler.Pipeline.Package.Loader.EvalEff.IO import Juvix.Compiler.Pipeline.Package.Loader.EvalEff.IO
import Juvix.Compiler.Pipeline.Package.Loader.PathResolver import Juvix.Compiler.Pipeline.Package.Loader.PathResolver
@ -17,7 +18,6 @@ import Juvix.Compiler.Pipeline.Setup
import Juvix.Data.Effect.Git import Juvix.Data.Effect.Git
import Juvix.Data.Effect.Process import Juvix.Data.Effect.Process
import Juvix.Data.Effect.TaggedLock import Juvix.Data.Effect.TaggedLock
import Juvix.Prelude.Aeson
import Juvix.Prelude.Pretty import Juvix.Prelude.Pretty
data PathResolverMode data PathResolverMode
@ -94,9 +94,9 @@ testDescr PosTest {..} = helper renderCodeNew
Concrete.fromParsed p Concrete.fromParsed p
) )
let yamlFiles :: [(Path Abs File, Text)] let packageFiles' :: [(Path Abs File, Text)]
yamlFiles = packageFiles' =
[ (pkgi ^. packageRoot <//> juvixYamlFile, encodeToText (rawPackage (pkgi ^. packagePackage))) [ (pkgi ^. packagePackage . packageFile, renderPackageVersion PackageVersion1 (pkgi ^. packagePackage))
| pkgi <- (^. resolverCacheItemPackage) <$> toList (resolverState ^. resolverCache) | pkgi <- (^. resolverCacheItemPackage) <$> toList (resolverState ^. resolverCache)
] ]
fsScoped :: HashMap (Path Abs File) Text fsScoped :: HashMap (Path Abs File) Text
@ -105,14 +105,14 @@ testDescr PosTest {..} = helper renderCodeNew
[ (getModuleFilePath m, renderer m) [ (getModuleFilePath m, renderer m)
| m <- toList (s ^. Scoper.resultScoperTable . Scoper.infoModules) | m <- toList (s ^. Scoper.resultScoperTable . Scoper.infoModules)
] ]
<> yamlFiles <> packageFiles'
fsParsed :: HashMap (Path Abs File) Text fsParsed :: HashMap (Path Abs File) Text
fsParsed = fsParsed =
HashMap.fromList $ HashMap.fromList $
[ (getModuleFilePath m, renderCodeNew m) [ (getModuleFilePath m, renderCodeNew m)
| m <- toList (p ^. Parser.resultTable . Parser.infoParsedModules) | m <- toList (p ^. Parser.resultTable . Parser.infoParsedModules)
] ]
<> yamlFiles <> packageFiles'
step "Parsing pretty scoped" step "Parsing pretty scoped"
p' :: Parser.ParserResult <- evalHelper fsScoped upToParsing p' :: Parser.ParserResult <- evalHelper fsScoped upToParsing

View File

@ -1,9 +1,5 @@
module Package; module Package;
import PackageDescription.V1 open; import PackageDescription.Basic open;
package : Package := package : Package := basicPackage;
defaultPackage
{name := "base";
version := mkVersion 1 0 0;
dependencies := []};

View File

@ -8,5 +8,5 @@ package : Package :=
version := mkVersion 0 0 1; version := mkVersion 0 0 1;
dependencies := [ path ".libs/Extra" dependencies := [ path ".libs/Extra"
; path ".libs/Base" ; path ".libs/Base"
; path ".juvix-build/stdlib" ; defaultStdlib
]}; ]};

View File

@ -317,7 +317,11 @@ tests:
main := just "HelloWorld.juvix"}; main := just "HelloWorld.juvix"};
EOF EOF
checksum=$(sha256sum Package.juvix | cut -d " " -f 1)
cat <<-EOF > juvix.lock.yaml cat <<-EOF > juvix.lock.yaml
version: 2
checksum: $checksum
dependencies: dependencies:
- path: .juvix-build/stdlib/ - path: .juvix-build/stdlib/
dependencies: [] dependencies: []
@ -353,6 +357,7 @@ tests:
cat <<-EOF > HelloDep.juvix cat <<-EOF > HelloDep.juvix
module HelloDep; module HelloDep;
import HelloDep2 open; import HelloDep2 open;
import Stdlib.Prelude open;
main : IO := printStringLn "This is from the second commit" >> printStringLn hello; main : IO := printStringLn "This is from the second commit" >> printStringLn hello;
EOF EOF
@ -372,7 +377,7 @@ tests:
git add -A git add -A
git commit -m "commit2" git commit -m "commit2"
# rebuild the project (should use the first commit # rebuild the project (should use the first commit)
cd $temp/base cd $temp/base
# compile with the new hash # compile with the new hash
@ -388,8 +393,7 @@ tests:
- bash - bash
script: | script: |
temp=$(mktemp -d) temp=$(mktemp -d)
echo $temp trap 'rm -rf -- "$temp"' EXIT
# trap 'rm -rf -- "$temp"' EXIT
# create dependency # create dependency
mkdir $temp/dep mkdir $temp/dep
@ -425,7 +429,7 @@ tests:
version := mkVersion 0 0 1; version := mkVersion 0 0 1;
dependencies := dependencies :=
[path ".juvix-build/stdlib"; [path ".juvix-build/stdlib";
git "dep1" "$temp/dep" "$dep1hash"]; git "dep1" "$temp/dep" "main"];
main := just "HelloWorld.juvix"}; main := just "HelloWorld.juvix"};
EOF EOF
@ -457,23 +461,7 @@ tests:
# compile project with new ref - should use lockfile ref # compile project with new ref - should use lockfile ref
cd $temp/base cd $temp/base
juvix clean
cat <<-EOF > Package.juvix
-- juvix-package-version:1
module Package;
import Stdlib.Prelude open;
import PackageDescription.V1 open;
package : Package :=
defaultPackage
{name := "HelloWorld";
version := mkVersion 0 0 1;
dependencies :=
[path ".juvix-build/stdlib";
git "dep1" "$temp/dep" "$dep1hash"];
main := just "HelloWorld.juvix"};
EOF
juvix compile HelloWorld.juvix juvix compile HelloWorld.juvix
./HelloWorld ./HelloWorld
@ -703,78 +691,6 @@ tests:
contains: "Hello from dep1\nHello from dep2" contains: "Hello from dep1\nHello from dep2"
exit-status: 0 exit-status: 0
- name: git-dependencies-lockfile-missing-dependency
command:
shell:
- bash
script: |
temp=$(mktemp -d)
trap 'rm -rf -- "$temp"' EXIT
# create dependency
mkdir $temp/dep1
cd $temp/dep1
git init
cat <<-EOF > HelloDep.juvix
module HelloDep;
import Stdlib.Prelude open;
main : IO := printStringLn "Hello from dep";
EOF
touch juvix.yaml
git add -A
git commit -m "commit1"
dep1hash=$(git rev-parse HEAD)
# create project that uses dependency
mkdir $temp/base
cd $temp/base
cat <<-EOF > Package.juvix
-- juvix-package-version:1
module Package;
import Stdlib.Prelude open;
import PackageDescription.V1 open;
package : Package :=
defaultPackage
{name := "HelloWorld";
version := mkVersion 0 0 1;
dependencies :=
[path ".juvix-build/stdlib/";
git "dep1" "$temp/dep1" "$dep1hash"];
main := just "HelloWorld.juvix"};
EOF
cat <<-EOF > juvix.lock.yaml
dependencies:
- path: .juvix-build/stdlib/
dependencies: []
EOF
cat <<-EOF > HelloWorld.juvix
-- HelloWorld.juvix
module HelloWorld;
import Stdlib.Prelude open;
import HelloDep;
main : IO := HelloDep.main;
EOF
# compile and run the project
juvix compile HelloWorld.juvix
stderr:
contains: "dep1"
stdout:
matches:
regex: ".*"
exit-status: 1
- name: git-dependencies-update-ref-offline - name: git-dependencies-update-ref-offline
command: command:
shell: shell:

View File

@ -287,7 +287,11 @@ tests:
version: 0.1.0 version: 0.1.0
EOF EOF
checksum=$(sha256sum juvix.yaml | cut -d " " -f 1)
cat <<-EOF > juvix.lock.yaml cat <<-EOF > juvix.lock.yaml
version: 2
checksum: $checksum
dependencies: dependencies:
- path: .juvix-build/stdlib/ - path: .juvix-build/stdlib/
dependencies: [] dependencies: []
@ -323,6 +327,7 @@ tests:
cat <<-EOF > HelloDep.juvix cat <<-EOF > HelloDep.juvix
module HelloDep; module HelloDep;
import HelloDep2 open; import HelloDep2 open;
import Stdlib.Prelude open;
main : IO := printStringLn "This is from the second commit" >> printStringLn hello; main : IO := printStringLn "This is from the second commit" >> printStringLn hello;
EOF EOF
@ -342,7 +347,7 @@ tests:
git add -A git add -A
git commit -m "commit2" git commit -m "commit2"
# rebuild the project (should use the first commit # rebuild the project (should use the first commit)
cd $temp/base cd $temp/base
# compile with the new hash # compile with the new hash
@ -358,8 +363,7 @@ tests:
- bash - bash
script: | script: |
temp=$(mktemp -d) temp=$(mktemp -d)
echo $temp trap 'rm -rf -- "$temp"' EXIT
# trap 'rm -rf -- "$temp"' EXIT
# create dependency # create dependency
mkdir $temp/dep mkdir $temp/dep
@ -390,7 +394,7 @@ tests:
- git: - git:
url: $temp/dep url: $temp/dep
name: dep1 name: dep1
ref: $dep1hash ref: main
version: 0.1.0 version: 0.1.0
EOF EOF
@ -423,18 +427,7 @@ tests:
# compile project with new ref - should use lockfile ref # compile project with new ref - should use lockfile ref
cd $temp/base cd $temp/base
cat <<-EOF > juvix.yaml juvix clean
name: HelloWorld
main: HelloWorld.juvix
dependencies:
- .juvix-build/stdlib
- git:
url: $temp/dep
name: dep1
ref: $dep1hash
version: 0.1.0
EOF
juvix compile HelloWorld.juvix juvix compile HelloWorld.juvix
./HelloWorld ./HelloWorld
stdout: stdout:
@ -643,73 +636,6 @@ tests:
contains: "Hello from dep1\nHello from dep2" contains: "Hello from dep1\nHello from dep2"
exit-status: 0 exit-status: 0
- name: git-dependencies-lockfile-missing-dependency
command:
shell:
- bash
script: |
temp=$(mktemp -d)
trap 'rm -rf -- "$temp"' EXIT
# create dependency
mkdir $temp/dep1
cd $temp/dep1
git init
cat <<-EOF > HelloDep.juvix
module HelloDep;
import Stdlib.Prelude open;
main : IO := printStringLn "Hello from dep";
EOF
touch juvix.yaml
git add -A
git commit -m "commit1"
dep1hash=$(git rev-parse HEAD)
# create project that uses dependency
mkdir $temp/base
cd $temp/base
cat <<-EOF > juvix.yaml
name: HelloWorld
main: HelloWorld.juvix
dependencies:
- .juvix-build/stdlib/
- git:
url: $temp/dep1
name: dep1
ref: $dep1hash
version: 0.1.0
EOF
cat <<-EOF > juvix.lock.yaml
dependencies:
- path: .juvix-build/stdlib/
dependencies: []
EOF
cat <<-EOF > HelloWorld.juvix
-- HelloWorld.juvix
module HelloWorld;
import Stdlib.Prelude open;
import HelloDep;
main : IO := HelloDep.main;
EOF
# compile and run the project
juvix compile HelloWorld.juvix
stderr:
contains: "dep1"
stdout:
matches:
regex: ".*"
exit-status: 1
- name: git-dependencies-update-ref-offline - name: git-dependencies-update-ref-offline
command: command:
shell: shell:
@ -1061,6 +987,88 @@ tests:
contains: duplicate contains: duplicate
exit-status: 1 exit-status: 1
- name: lockfile-update-when-package-file-is-updated
command:
shell:
- bash
script: |
temp=$(mktemp -d)
# trap 'rm -rf -- "$temp"' EXIT
echo $temp
# create dependency
mkdir $temp/dep
cd $temp/dep
git init
cat <<-EOF > HelloDep.juvix
module HelloDep;
import Stdlib.Prelude open;
main : IO := printStringLn "Hello from dep";
EOF
cat <<-EOF > Package.juvix
module Package;
import PackageDescription.Basic open;
package : Package := basicPackage;
EOF
git add -A
git commit -m "commit1"
# create project that uses dependency
mkdir $temp/base
cd $temp/base
cat <<-EOF > Package.juvix
module Package;
import PackageDescription.V1 open;
package : Package := defaultPackage {dependencies := [defaultStdlib ; git "dep1" "$temp/dep" "main"]}
EOF
cat <<-EOF > HelloWorld.juvix
-- HelloWorld.juvix
module HelloWorld;
import Stdlib.Prelude open;
import HelloDep;
main : IO := HelloDep.main;
EOF
# compile project to create lock file
juvix compile HelloWorld.juvix
cd $temp/dep
cat <<-EOF > HelloDep.juvix
module HelloDep;
import Stdlib.Prelude open;
main : IO := printStringLn "Hello from commit2";
EOF
git add -A
git commit -m "commit2"
cd $temp/base
juvix clean
juvix compile HelloWorld.juvix
./HelloWorld
# Update the Package file and recompile
# it should use the latest commit
echo "-- comment" >> Package.juvix
juvix clean
juvix compile HelloWorld.juvix
./HelloWorld
stderr: ""
stdout:
matches:
regex: "Hello from dep\n(.*?)Hello from commit2"
options:
- dot-all
exit-status: 0
- name: git-dependencies-no-fetch-if-ref-exists-in-clone - name: git-dependencies-no-fetch-if-ref-exists-in-clone
command: command:
shell: shell: