From 188e61d9eeb278bf526389875baaa2f412398fd0 Mon Sep 17 00:00:00 2001 From: Fyodor Soikin Date: Tue, 3 Sep 2024 17:23:37 -0400 Subject: [PATCH] New 'spago init --subpackage foo' option to initialize a sub-project within current workspace (#1279) --- CHANGELOG.md | 2 + bin/src/Flags.purs | 18 ++- bin/src/Main.purs | 44 +++----- src/Spago/Command/Init.purs | 105 +++++++++++++----- .../init/subpackage/conflicting-flags.txt | 21 ++++ .../init/subpackage/existing-src-file.txt | 5 + ...kage-set-solver-warning-existing-files.txt | 8 ++ .../subpackage/package-set-solver-warning.txt | 5 + .../init/subpackage/subdir-spago.yaml | 9 ++ .../init/subpackage/subdir2-spago.yaml | 9 ++ test/Spago/Cli.purs | 13 ++- test/Spago/Init.purs | 3 + test/Spago/InitSubpackage.purs | 63 +++++++++++ 13 files changed, 242 insertions(+), 63 deletions(-) create mode 100644 test-fixtures/init/subpackage/conflicting-flags.txt create mode 100644 test-fixtures/init/subpackage/existing-src-file.txt create mode 100644 test-fixtures/init/subpackage/package-set-solver-warning-existing-files.txt create mode 100644 test-fixtures/init/subpackage/package-set-solver-warning.txt create mode 100644 test-fixtures/init/subpackage/subdir-spago.yaml create mode 100644 test-fixtures/init/subpackage/subdir2-spago.yaml create mode 100644 test/Spago/InitSubpackage.purs diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d025a7d1..a8f54d105 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,8 @@ Other improvements: Spago on different platforms. - when encountering a mistyped option for a command, Spago will show help for that command, not root help. +- a new `spago init --subpackage foo` option to initialize a sub-project in the + current workspace. ## [0.21.0] - 2023-05-04 diff --git a/bin/src/Flags.purs b/bin/src/Flags.purs index f0894de5a..eb11f95c8 100644 --- a/bin/src/Flags.purs +++ b/bin/src/Flags.purs @@ -7,6 +7,7 @@ import Data.List as List import Options.Applicative (FlagFields, Mod, Parser) import Options.Applicative as O import Options.Applicative.Types as OT +import Spago.Command.Init as Init import Spago.Core.Config as Core flagMaybe ∷ ∀ (a ∷ Type). a -> Mod FlagFields (Maybe a) -> Parser (Maybe a) @@ -178,8 +179,8 @@ transitive = <> O.help "Include transitive dependencies" ) -pure :: Parser Boolean -pure = +pureLockfile :: Parser Boolean +pureLockfile = O.switch ( O.long "pure" <> O.help "Use the package information from the current lockfile, even if it is out of date" @@ -301,6 +302,19 @@ maybePackageName = <> O.help "Optional package name to be used for the new project" ) +subpackageName :: Parser String +subpackageName = + O.strOption + ( O.long "subpackage" + <> O.help "Name of a subpackage to initialize within the current workspace" + ) + +initMode :: Parser Init.InitMode +initMode = + (Init.InitSubpackage <$> { packageName: _ } <$> subpackageName) + <|> (Init.InitWorkspace <$> { packageName: _ } <$> maybePackageName) + <|> pure (Init.InitWorkspace { packageName: Nothing }) + ensureRanges :: Parser Boolean ensureRanges = O.switch diff --git a/bin/src/Main.purs b/bin/src/Main.purs index 18b0e53ae..74009d649 100644 --- a/bin/src/Main.purs +++ b/bin/src/Main.purs @@ -12,11 +12,9 @@ import Data.Foldable as Foldable import Data.List as List import Data.Maybe as Maybe import Data.Set as Set -import Data.String as String import Effect.Aff as Aff import Effect.Aff.AVar as AVar import Effect.Now as Now -import Node.Path as Path import Node.Process as Process import Options.Applicative (CommandFields, Mod, Parser, ParserPrefs(..)) import Options.Applicative as O @@ -53,12 +51,10 @@ import Spago.Generated.BuildInfo as BuildInfo import Spago.Git as Git import Spago.Json as Json import Spago.Log (LogVerbosity(..)) -import Spago.Log as Log import Spago.Paths as Paths import Spago.Purs as Purs import Spago.Registry as Registry import Spago.Repl as SpagoRepl -import Unsafe.Coerce as UnsafeCoerce type GlobalArgs = { noColor :: Boolean @@ -70,7 +66,7 @@ type GlobalArgs = type InitArgs = { setVersion :: Maybe String - , name :: Maybe String + , mode :: Init.InitMode , useSolver :: Boolean } @@ -296,7 +292,7 @@ initArgsParser :: Parser InitArgs initArgsParser = Optparse.fromRecord { setVersion: Flags.maybeSetVersion - , name: Flags.maybePackageName + , mode: Flags.initMode , useSolver: Flags.useSolver } @@ -307,7 +303,7 @@ fetchArgsParser = , selectedPackage: Flags.selectedPackage , ensureRanges: Flags.ensureRanges , testDeps: Flags.testDeps - , pure: Flags.pure + , pure: Flags.pureLockfile } sourcesArgsParser :: Parser SourcesArgs @@ -328,7 +324,7 @@ installArgsParser = , pedanticPackages: Flags.pedanticPackages , ensureRanges: Flags.ensureRanges , testDeps: Flags.testDeps - , pure: Flags.pure + , pure: Flags.pureLockfile } uninstallArgsParser :: Parser UninstallArgs @@ -350,7 +346,7 @@ buildArgsParser = Optparse.fromRecord , jsonErrors: Flags.jsonErrors , strict: Flags.strict , statVerbosity: Flags.statVerbosity - , pure: Flags.pure + , pure: Flags.pureLockfile } replArgsParser :: Parser ReplArgs @@ -372,7 +368,7 @@ runArgsParser = Optparse.fromRecord , ensureRanges: Flags.ensureRanges , strict: Flags.strict , statVerbosity: Flags.statVerbosity - , pure: Flags.pure + , pure: Flags.pureLockfile } upgradeArgsParser :: Parser UpgradeArgs @@ -391,7 +387,7 @@ testArgsParser = Optparse.fromRecord , pedanticPackages: Flags.pedanticPackages , strict: Flags.strict , statVerbosity: Flags.statVerbosity - , pure: Flags.pure + , pure: Flags.pureLockfile } bundleArgsParser :: Parser BundleArgs @@ -413,7 +409,7 @@ bundleArgsParser = , ensureRanges: Flags.ensureRanges , strict: Flags.strict , statVerbosity: Flags.statVerbosity - , pure: Flags.pure + , pure: Flags.pureLockfile } publishArgsParser :: Parser PublishArgs @@ -489,7 +485,7 @@ lsPathsArgsParser = Optparse.fromRecord lsPackagesArgsParser :: Parser LsPackagesArgs lsPackagesArgsParser = Optparse.fromRecord { json: Flags.json - , pure: Flags.pure + , pure: Flags.pureLockfile } lsDepsArgsParser :: Parser LsDepsArgs @@ -497,7 +493,7 @@ lsDepsArgsParser = Optparse.fromRecord { json: Flags.json , transitive: Flags.transitive , selectedPackage: Flags.selectedPackage - , pure: Flags.pure + , pure: Flags.pureLockfile } data Cmd a = Cmd'SpagoCmd (SpagoCmd a) | Cmd'VersionCmd Boolean @@ -547,24 +543,10 @@ main = do } void $ runSpago env (Sources.run { json: args.json }) Init args@{ useSolver } -> do - -- Figure out the package name from the current dir - let candidateName = fromMaybe (String.take 150 $ Path.basename Paths.cwd) args.name - logDebug [ show Paths.cwd, show candidateName ] - packageName <- case PackageName.parse (PackageName.stripPureScriptPrefix candidateName) of - Left err -> die - [ toDoc "Could not figure out a name for the new package. Error:" - , Log.break - , Log.indent2 $ toDoc err - ] - Right p -> pure p - setVersion <- parseSetVersion args.setVersion - logDebug [ "Got packageName and setVersion:", PackageName.print packageName, unsafeStringify setVersion ] - let initOpts = { packageName, setVersion, useSolver } -- Fetch the registry here so we can select the right package set later env <- mkRegistryEnv offline - void $ runSpago env $ Init.run initOpts - logInfo "Set up a new Spago project." - logInfo "Try running `spago run`" + setVersion <- parseSetVersion args.setVersion + void $ runSpago env $ Init.run { mode: args.mode, setVersion, useSolver } Fetch args -> do { env, fetchOpts } <- mkFetchEnv (Record.merge { isRepl: false, migrateConfig, offline } args) void $ runSpago env (Fetch.run fetchOpts) @@ -620,7 +602,7 @@ main = do env <- mkRegistryEnv offline void $ runSpago env $ Init.run { setVersion: Nothing - , packageName: UnsafeCoerce.unsafeCoerce "repl" + , mode: Init.InitWorkspace { packageName: Just "repl" } , useSolver: true } pure $ List.fromFoldable [ "effect", "console" ] -- TODO newPackages diff --git a/src/Spago/Command/Init.purs b/src/Spago/Command/Init.purs index a0e309f17..886281386 100644 --- a/src/Spago/Command/Init.purs +++ b/src/Spago/Command/Init.purs @@ -2,6 +2,7 @@ module Spago.Command.Init ( DefaultConfigOptions(..) , DefaultConfigPackageOptions , DefaultConfigWorkspaceOptions + , InitMode(..) , InitOptions , defaultConfig , defaultConfig' @@ -14,19 +15,26 @@ module Spago.Command.Init import Spago.Prelude import Data.Map as Map +import Data.String as String import Node.Path as Path import Registry.PackageName as PackageName import Registry.Version as Version import Spago.Config (Dependencies(..), SetAddress(..), Config) import Spago.Config as Config import Spago.FS as FS +import Spago.Log as Log +import Spago.Paths as Paths import Spago.Registry (RegistryEnv) import Spago.Registry as Registry +data InitMode + = InitWorkspace { packageName :: Maybe String } + | InitSubpackage { packageName :: String } + type InitOptions = -- TODO: we should allow the `--package-set` flag to alternatively pass in a URL { setVersion :: Maybe Version - , packageName :: PackageName + , mode :: InitMode , useSolver :: Boolean } @@ -34,27 +42,27 @@ type InitOptions = run :: ∀ a. InitOptions -> Spago (RegistryEnv a) Config run opts = do - logInfo "Initializing a new project..." - -- Use the specified version of the package set (if specified). -- Otherwise, get the latest version of the package set for the given compiler packageSetVersion <- Registry.findPackageSet opts.setVersion + packageName <- getPackageName + withWorkspace <- getWithWorkspace packageSetVersion + projectDir <- getProjectDir packageName + { purs } <- ask + logInfo "Initializing a new project..." logInfo $ "Found PureScript " <> Version.print purs.version <> ", will use package set " <> Version.print packageSetVersion - -- Write config let - config = defaultConfig - { name: opts.packageName - , withWorkspace: Just - { setVersion: case opts.useSolver of - true -> Nothing - false -> Just packageSetVersion - } - , testModuleName: "Test.Main" - } - let configPath = "spago.yaml" + mainModuleName = "Main" + testModuleName = "Test.Main" + srcDir = Path.concat [ projectDir, "src" ] + testDir = Path.concat [ projectDir, "test" ] + configPath = Path.concat [ projectDir, "spago.yaml" ] + config = defaultConfig { name: packageName, withWorkspace, testModuleName } + + -- Write config (FS.exists configPath) >>= case _ of true -> logInfo $ foundExistingProject configPath false -> liftAff $ FS.writeYamlFile Config.configCodec configPath config @@ -62,17 +70,24 @@ run opts = do -- If these directories (or files) exist, we skip copying "sample sources" -- Because you might want to just init a project with your own source files, -- or just migrate a psc-package project - let mainModuleName = "Main" - whenDirNotExists "src" do - copyIfNotExists ("src" <> Path.sep <> mainModuleName <> ".purs") (srcMainTemplate mainModuleName) + whenDirNotExists srcDir do + copyIfNotExists (Path.concat [ srcDir, mainModuleName <> ".purs" ]) (srcMainTemplate mainModuleName) - whenDirNotExists "test" $ do - FS.mkdirp (Path.concat [ "test", "Test" ]) - copyIfNotExists (Path.concat [ "test", "Test", "Main.purs" ]) (testMainTemplate "Test.Main") + whenDirNotExists testDir $ do + FS.mkdirp (Path.concat [ testDir, "Test" ]) + copyIfNotExists (Path.concat [ testDir, "Test", "Main.purs" ]) (testMainTemplate testModuleName) - copyIfNotExists ".gitignore" gitignoreTemplate + case opts.mode of + InitWorkspace _ -> do + copyIfNotExists ".gitignore" gitignoreTemplate + copyIfNotExists pursReplFile.name pursReplFile.content + InitSubpackage _ -> + pure unit - copyIfNotExists pursReplFile.name pursReplFile.content + logInfo "Set up a new Spago project." + case opts.mode of + InitWorkspace _ -> logInfo "Try running `spago run`" + InitSubpackage _ -> logInfo $ "Try running `spago run -p " <> PackageName.print packageName <> "`" pure config @@ -87,6 +102,46 @@ run opts = do true -> logInfo $ foundExistingFile dest false -> FS.writeTextFile dest srcTemplate + getPackageName :: Spago (RegistryEnv a) PackageName + getPackageName = do + let + candidateName = case opts.mode of + InitWorkspace { packageName: Nothing } -> String.take 150 $ Path.basename Paths.cwd + InitWorkspace { packageName: Just n } -> n + InitSubpackage { packageName: n } -> n + logDebug [ show Paths.cwd, show candidateName ] + pname <- case PackageName.parse (PackageName.stripPureScriptPrefix candidateName) of + Left err -> die + [ toDoc "Could not figure out a name for the new package. Error:" + , Log.break + , Log.indent2 $ toDoc err + ] + Right p -> pure p + logDebug [ "Got packageName and setVersion:", PackageName.print pname, unsafeStringify opts.setVersion ] + pure pname + + getWithWorkspace :: Version -> Spago (RegistryEnv a) (Maybe { setVersion :: Maybe Version }) + getWithWorkspace setVersion = case opts.mode of + InitWorkspace _ -> + pure $ Just + { setVersion: case opts.useSolver of + true -> Nothing + false -> Just setVersion + } + InitSubpackage _ -> do + when (isJust opts.setVersion || opts.useSolver) do + logWarn "The --package-set and --use-solver flags are ignored when initializing a subpackage" + pure Nothing + + getProjectDir :: PackageName -> Spago (RegistryEnv a) FilePath + getProjectDir packageName = case opts.mode of + InitWorkspace _ -> + pure "." + InitSubpackage _ -> do + let dirPath = PackageName.print packageName + unlessM (FS.exists dirPath) $ FS.mkdirp dirPath + pure dirPath + -- TEMPLATES ------------------------------------------------------------------- type TemplateConfig = @@ -234,10 +289,10 @@ pursReplFile = { name: ".purs-repl", content: "import Prelude\n" } -- ERROR TEXTS ----------------------------------------------------------------- foundExistingProject :: FilePath -> String -foundExistingProject path = "Found a " <> show path <> " file, skipping copy." +foundExistingProject path = "Found a \"" <> path <> "\" file, skipping copy." foundExistingDirectory :: FilePath -> String -foundExistingDirectory dir = "Found existing directory " <> show dir <> ", skipping copy of sample sources" +foundExistingDirectory dir = "Found existing directory \"" <> dir <> "\", skipping copy of sample sources" foundExistingFile :: FilePath -> String -foundExistingFile file = "Found existing file " <> show file <> ", not overwriting it" +foundExistingFile file = "Found existing file \"" <> file <> "\", not overwriting it" diff --git a/test-fixtures/init/subpackage/conflicting-flags.txt b/test-fixtures/init/subpackage/conflicting-flags.txt new file mode 100644 index 000000000..47c382272 --- /dev/null +++ b/test-fixtures/init/subpackage/conflicting-flags.txt @@ -0,0 +1,21 @@ +Invalid option `--subpackage' + +Usage: index.dev.js init [--migrate] [--monochrome|--no-color] [--offline] [-q|--quiet] [-v|--verbose] ([--subpackage ARG] | [--name ARG]) [--package-set ARG] [--use-solver] + Initialise a new project + +Available options: + --migrate Migrate the spago.yaml file to the latest format + --monochrome,--no-color Force logging without ANSI color escape sequences + --offline Do not attempt to use the network. Warning: this will + fail if you don't have the necessary dependencies + already cached + -q,--quiet Suppress all spago logging + -v,--verbose Enable additional debug logging, e.g. printing `purs` + commands + --subpackage ARG Name of a subpackage to initialize within the current + workspace + --name ARG Optional package name to be used for the new project + --package-set ARG Optional package set version to be used instead of + the latest one + --use-solver Use the solver instead of package sets + -h,--help Show this help text diff --git a/test-fixtures/init/subpackage/existing-src-file.txt b/test-fixtures/init/subpackage/existing-src-file.txt new file mode 100644 index 000000000..5af82c544 --- /dev/null +++ b/test-fixtures/init/subpackage/existing-src-file.txt @@ -0,0 +1,5 @@ +Initializing a new project... +Found PureScript a.b.c, will use package set x.y.z +Found existing directory "subdir/src", skipping copy of sample sources +Set up a new Spago project. +Try running `spago run -p subdir` diff --git a/test-fixtures/init/subpackage/package-set-solver-warning-existing-files.txt b/test-fixtures/init/subpackage/package-set-solver-warning-existing-files.txt new file mode 100644 index 000000000..579381729 --- /dev/null +++ b/test-fixtures/init/subpackage/package-set-solver-warning-existing-files.txt @@ -0,0 +1,8 @@ +‼ The --package-set and --use-solver flags are ignored when initializing a subpackage +Initializing a new project... +Found PureScript a.b.c, will use package set x.y.z +Found a "subdir/spago.yaml" file, skipping copy. +Found existing directory "subdir/src", skipping copy of sample sources +Found existing directory "subdir/test", skipping copy of sample sources +Set up a new Spago project. +Try running `spago run -p subdir` diff --git a/test-fixtures/init/subpackage/package-set-solver-warning.txt b/test-fixtures/init/subpackage/package-set-solver-warning.txt new file mode 100644 index 000000000..71a619b22 --- /dev/null +++ b/test-fixtures/init/subpackage/package-set-solver-warning.txt @@ -0,0 +1,5 @@ +‼ The --package-set and --use-solver flags are ignored when initializing a subpackage +Initializing a new project... +Found PureScript a.b.c, will use package set x.y.z +Set up a new Spago project. +Try running `spago run -p subdir` diff --git a/test-fixtures/init/subpackage/subdir-spago.yaml b/test-fixtures/init/subpackage/subdir-spago.yaml new file mode 100644 index 000000000..d18305ac3 --- /dev/null +++ b/test-fixtures/init/subpackage/subdir-spago.yaml @@ -0,0 +1,9 @@ +package: + name: subdir + dependencies: + - console + - effect + - prelude + test: + main: Test.Main + dependencies: [] diff --git a/test-fixtures/init/subpackage/subdir2-spago.yaml b/test-fixtures/init/subpackage/subdir2-spago.yaml new file mode 100644 index 000000000..0eb48d03b --- /dev/null +++ b/test-fixtures/init/subpackage/subdir2-spago.yaml @@ -0,0 +1,9 @@ +package: + name: subdir2 + dependencies: + - console + - effect + - prelude + test: + main: Test.Main + dependencies: [] diff --git a/test/Spago/Cli.purs b/test/Spago/Cli.purs index 9570e7440..9592da8e5 100644 --- a/test/Spago/Cli.purs +++ b/test/Spago/Cli.purs @@ -32,12 +32,15 @@ spec = Spec.around withTempDir do { stdoutFile: stdout , stderrFile: stderr , result - , sanitize: - String.trim - >>> Regex.replace progNameRegex "Usage: index.dev.js" - >>> Regex.replace optionsLineRegex " $1" + , sanitize: sanitizeCliHelpOutput } +sanitizeCliHelpOutput :: String -> String +sanitizeCliHelpOutput = + String.trim + >>> Regex.replace progNameRegex "Usage: index.dev.js" + >>> Regex.replace optionsLineRegex " $1" + where -- On Windows progname has the full path like -- "Usage: C:\whatever\index.dev.js", but on Unix -- it's just "Usage: index.dev.js" @@ -61,4 +64,4 @@ spec = Spec.around withTempDir do -- -- Usage: index.dev.js build [--option] [--another-option] [--third-option] [--foo] [-f|--force] [--help] -- - optionsLineRegex = unsafeFromRight $ Regex.regex "\\n\\s+(\\(\\[-|\\[-|PACKAGE)" RF.global + optionsLineRegex = unsafeFromRight $ Regex.regex "\\n\\s+(\\| \\[-|\\(\\[-|\\[-|PACKAGE)" RF.global diff --git a/test/Spago/Init.purs b/test/Spago/Init.purs index a1ca3c130..977ff68a1 100644 --- a/test/Spago/Init.purs +++ b/test/Spago/Init.purs @@ -4,6 +4,7 @@ import Test.Prelude import Node.Path as Path import Spago.FS as FS +import Test.Spago.InitSubpackage as Subpackage import Test.Spec (Spec) import Test.Spec as Spec import Test.Spec.Assertions as Assert @@ -25,3 +26,5 @@ spec = Spec.around withTempDir do Spec.it "should use user-specified tag if it exists instead of latest release" \({ spago, fixture } :: TestDirs) -> do spago [ "init", "--package-set", "9.0.0", "--name", "7368613235362d47665357393342584955783641314b70674c" ] >>= shouldBeSuccess checkFixture "spago.yaml" (fixture "older-package-set-tag.yaml") + + Subpackage.spec diff --git a/test/Spago/InitSubpackage.purs b/test/Spago/InitSubpackage.purs new file mode 100644 index 000000000..567b4dae1 --- /dev/null +++ b/test/Spago/InitSubpackage.purs @@ -0,0 +1,63 @@ +module Test.Spago.InitSubpackage where + +import Test.Prelude + +import Data.String.Regex as Regex +import Data.String.Regex.Flags as RF +import Node.Path as Path +import Spago.FS as FS +import Test.Spago.Cli (sanitizeCliHelpOutput) +import Test.Spec (SpecT) +import Test.Spec as Spec + +spec :: SpecT Aff TestDirs Identity Unit +spec = + Spec.describe "subpackage" do + Spec.it "sets up a sub-project in a subdirectory" \{ spago, fixture } -> do + spago [ "init" ] >>= shouldBeSuccess + spago [ "init", "--subpackage", "subdir" ] >>= shouldBeSuccess + checkFixture "subdir/spago.yaml" (fixture "init/subpackage/subdir-spago.yaml") + spago [ "init", "--subpackage", "subdir2" ] >>= shouldBeSuccess + checkFixture "subdir2/spago.yaml" (fixture "init/subpackage/subdir2-spago.yaml") + + Spec.it "does not overwrite existing files" \{ spago, fixture } -> do + spago [ "init" ] >>= shouldBeSuccess + FS.mkdirp "subdir/src" + FS.writeTextFile (Path.concat [ "subdir", "src", "Main.purs" ]) "Something" + spago [ "init", "--subpackage", "subdir" ] + >>= shouldBeSuccessErr' (fixture "init/subpackage/existing-src-file.txt") + fileContent <- FS.readTextFile (Path.concat [ "subdir", "src", "Main.purs" ]) + fileContent `shouldEqualStr` "Something" + + Spec.it "warns when --package-set or --use-solver flags are used" \{ spago, fixture } -> do + spago [ "init" ] >>= shouldBeSuccess + + spago [ "init", "--package-set", "9.0.0", "--subpackage", "subdir" ] + >>= shouldBeSuccessErr' (fixture "init/subpackage/package-set-solver-warning.txt") + checkFixture "subdir/spago.yaml" (fixture "init/subpackage/subdir-spago.yaml") + + spago [ "init", "--use-solver", "--subpackage", "subdir" ] + >>= shouldBeSuccessErr' (fixture "init/subpackage/package-set-solver-warning-existing-files.txt") + checkFixture "subdir/spago.yaml" (fixture "init/subpackage/subdir-spago.yaml") + + Spec.it "does not allow both --name and --subpackage flags" \{ spago, fixture } -> do + spago [ "init", "--name", "foo", "--subpackage", "bar" ] + >>= shouldBeFailureErr' (fixture "init/subpackage/conflicting-flags.txt") + + where + shouldBeSuccessErr' = checkOutputsWithPatch isRight + shouldBeFailureErr' = checkOutputsWithPatch isLeft + + checkOutputsWithPatch result fixture = + checkOutputs' + { stdoutFile: Nothing + , stderrFile: Just fixture + , result + , sanitize: + sanitizeCliHelpOutput + >>> withForwardSlashes + >>> Regex.replace versionsRegex "Found PureScript a.b.c, will use package set x.y.z" + } + + versionsRegex = unsafeFromRight $ + Regex.regex "Found PureScript \\d+\\.\\d+\\.\\d+, will use package set \\d+\\.\\d+\\.\\d+" RF.noFlags