Skip to content

Commit 9b5bebf

Browse files
committed
Reinstate standalone script command
Signed-off-by: ahmad <ahmadalgaidy@hotmail.com>
1 parent e508f4f commit 9b5bebf

8 files changed

Lines changed: 133 additions & 5 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
Features:
11+
* Reinstate `spago script` for running standalone PureScript files with package-set and dependency options
12+
1013
Bugfixes:
1114
* Fix flaky `SQLITE_IOERR_TRUNCATE` on Windows when multiple spago processes connect concurrently to the cache DB, by skipping `PRAGMA journal_mode = WAL` when it's already enabled (WAL mode is persistent in the DB file header) and tolerating the race on the initial set
1215
* Retry transient network failures (connection errors and 5xx responses) when fetching package tarballs and calling the registry API, instead of failing immediately

‎bin/src/Flags.purs‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,23 @@ packages =
278278
<> O.help "Package name to add as dependency"
279279
)
280280

281+
scriptSource :: Parser String
282+
scriptSource =
283+
O.strArgument
284+
( O.metavar "SOURCE"
285+
<> O.help "PureScript source file to run"
286+
)
287+
288+
scriptDependencies :: Parser (List String)
289+
scriptDependencies =
290+
O.many $
291+
O.strOption
292+
( O.long "dependency"
293+
<> O.short 'd'
294+
<> O.metavar "PACKAGE"
295+
<> O.help "Package dependency to make available to the script"
296+
)
297+
281298
packagesToRemove :: Parser (List String)
282299
packagesToRemove =
283300
O.many $

‎bin/src/Main.purs‎

Lines changed: 79 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import Spago.Command.Registry (RegistryInfoArgs, RegistryPackageSetsArgs, Regist
3939
import Spago.Command.Registry as RegistryCmd
4040
import Spago.Command.Repl as Repl
4141
import Spago.Command.Run as Run
42+
import Spago.Command.Script as Script
4243
import Spago.Command.Sources as Sources
4344
import Spago.Command.Test as Test
4445
import Spago.Command.Uninstall as Uninstall
@@ -145,6 +146,12 @@ type RunArgs =
145146
, pure :: Boolean
146147
}
147148

149+
type ScriptArgs =
150+
{ source :: String
151+
, dependencies :: List String
152+
, packageSet :: Maybe String
153+
}
154+
148155
type TestArgs =
149156
{ selectedPackage :: Maybe String
150157
, output :: Maybe String
@@ -212,6 +219,7 @@ data Command a
212219
| RegistryTransfer RegistryTransferArgs
213220
| Repl ReplArgs
214221
| Run RunArgs
222+
| Script ScriptArgs
215223
| Sources SourcesArgs
216224
| Test TestArgs
217225
| Upgrade UpgradeArgs
@@ -270,6 +278,7 @@ argParser =
270278
)
271279
, commandParser "repl" (Repl <$> replArgsParser) "Start a REPL"
272280
, commandParser "run" (Run <$> runArgsParser) "Run the project"
281+
, commandParser "script" (Script <$> scriptArgsParser) "Run a standalone PureScript source file"
273282
, commandParser "sources" (Sources <$> sourcesArgsParser) "List all the source paths (globs) for the dependencies of the project"
274283
, commandParser "test" (Test <$> testArgsParser) "Test the project"
275284
, commandParser "uninstall" (Uninstall <$> uninstallArgsParser) "Remove dependencies from a package"
@@ -414,6 +423,14 @@ bundleArgsParser =
414423
, pure: Flags.pureLockfile
415424
}
416425

426+
scriptArgsParser :: Parser ScriptArgs
427+
scriptArgsParser =
428+
Optparse.fromRecord
429+
{ source: Flags.scriptSource
430+
, dependencies: Flags.scriptDependencies
431+
, packageSet: Flags.maybeSetVersion
432+
}
433+
417434
publishArgsParser :: Parser PublishArgs
418435
publishArgsParser =
419436
Optparse.fromRecord
@@ -657,8 +674,66 @@ main = do
657674
let options = { depsOnly: false, pursArgs: List.toUnfoldable args.pursArgs, jsonErrors: false }
658675
built <- runSpago buildEnv (Build.run options)
659676
when built do
660-
runEnv <- runSpago env (mkRunEnv args buildEnv)
677+
runEnv <- runSpago env (mkRunEnv args buildEnv Nothing)
678+
runSpago runEnv Run.run
679+
Script args -> do
680+
originalCwd <- Paths.cwd
681+
sourcePath <- Path.toAbsolute (Path.global args.source)
682+
tmpDir <- mkTemp
683+
FS.mkdirp tmpDir
684+
Paths.chdir tmpDir
685+
tmpRootPath <- Path.mkRoot tmpDir
686+
registryEnv <- mkRegistryEnv offline <#> Record.union { rootPath: tmpRootPath }
687+
setVersion <- parseSetVersion args.packageSet
688+
void $ runSpago registryEnv $ Init.run
689+
{ setVersion
690+
, mode: Init.InitWorkspace { packageName: Just "script" }
691+
, useSolver: false
692+
}
693+
FS.copyTree
694+
{ src: sourcePath
695+
, dst: tmpRootPath </> "src" </> (Script.moduleName <> ".purs")
696+
}
697+
{ env, fetchOpts } <- mkFetchEnv
698+
{ packages: args.dependencies
699+
, selectedPackage: Nothing
700+
, ensureRanges: false
701+
, testDeps: false
702+
, isRepl: false
703+
, pure: false
704+
, migrateConfig: false
705+
, offline
706+
}
707+
dependencies <- runSpago env (Fetch.run fetchOpts)
708+
buildEnv <- runSpago env
709+
( mkBuildEnv
710+
{ backendArgs: mempty
711+
, output: Nothing
712+
, pedanticPackages: false
713+
, statVerbosity: Nothing
714+
, strict: Nothing
715+
}
716+
dependencies
717+
)
718+
built <- runSpago buildEnv (Build.run { depsOnly: false, pursArgs: mempty, jsonErrors: false })
719+
when built do
720+
let
721+
runArgs =
722+
{ selectedPackage: Nothing
723+
, output: Nothing
724+
, pedanticPackages: false
725+
, pursArgs: mempty
726+
, backendArgs: mempty
727+
, execArgs: Nothing
728+
, main: Just Script.moduleName
729+
, ensureRanges: false
730+
, strict: Nothing
731+
, statVerbosity: Nothing
732+
, pure: false
733+
}
734+
runEnv <- runSpago env (mkRunEnv runArgs buildEnv (Just $ Path.toGlobal originalCwd))
661735
runSpago runEnv Run.run
736+
Paths.chdir originalCwd
662737
Test args@{ selectedPackage, pure } -> do
663738
{ env, fetchOpts } <- mkFetchEnv { packages: mempty, selectedPackage, pure, ensureRanges: false, testDeps: false, isRepl: false, migrateConfig, offline }
664739
dependencies <- runSpago env (Fetch.run fetchOpts)
@@ -787,8 +862,8 @@ mkBundleEnv bundleArgs { dependencies, purs } = do
787862
let bundleEnv = { esbuild, logOptions, rootPath, workspace: newWorkspace, selected, bundleOptions, purs, dependencies }
788863
pure bundleEnv
789864

790-
mkRunEnv :: forall a b. RunArgs -> Build.BuildEnv b -> Spago (Fetch.FetchEnv a) (Run.RunEnv ())
791-
mkRunEnv runArgs { dependencies, purs } = do
865+
mkRunEnv :: forall a b. RunArgs -> Build.BuildEnv b -> Maybe GlobalPath -> Spago (Fetch.FetchEnv a) (Run.RunEnv ())
866+
mkRunEnv runArgs { dependencies, purs } executeDir = do
792867
{ workspace, logOptions, rootPath } <- ask
793868
logDebug $ "Run args: " <> show runArgs
794869

@@ -824,7 +899,7 @@ mkRunEnv runArgs { dependencies, purs } = do
824899
runOptions =
825900
{ moduleName
826901
, execArgs
827-
, executeDir: Path.toGlobal rootPath
902+
, executeDir: fromMaybe (Path.toGlobal rootPath) executeDir
828903
, successMessage: Nothing
829904
, failureMessage: "Running failed."
830905
}

‎src/Spago/Command/Script.purs‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,6 @@
1-
module Spago.Command.Script where
1+
module Spago.Command.Script
2+
( moduleName
3+
) where
4+
5+
moduleName :: String
6+
moduleName = "Main"
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
module Main where
2+
3+
import Prelude
4+
import Effect (Effect)
5+
import Node.FS.Sync (writeTextFile)
6+
import Node.Encoding as Encoding
7+
8+
main :: Effect Unit
9+
main = do
10+
writeTextFile Encoding.UTF8 "spago-script-result.txt" "HELLO\n"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
HELLO

‎test/Spago.purs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import Test.Spago.Publish as Publish
2525
import Test.Spago.Registry as Registry
2626
import Test.Spago.Repl as Repl
2727
import Test.Spago.Run as Run
28+
import Test.Spago.Script as Script
2829
import Test.Spago.Sources as Sources
2930
import Test.Spago.Test as Test
3031
import Test.Spago.Transfer as Transfer
@@ -69,6 +70,7 @@ main = do
6970
Ls.spec cmdLocks
7071
Repl.spec
7172
Run.spec cmdLocks
73+
Script.spec cmdLocks
7274
Test.spec cmdLocks
7375
Bundle.spec cmdLocks
7476
Registry.spec

‎test/Spago/Script.purs‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
module Test.Spago.Script where
2+
3+
import Test.Prelude
4+
5+
import Spago.Path as Path
6+
import Test.Spec (Spec)
7+
import Test.Spec as Spec
8+
9+
spec :: CommandLocks -> Spec Unit
10+
spec locks = Spec.parallel $ Spec.around (withBuildLock locks) do
11+
Spec.describe "script" do
12+
Spec.it "runs a standalone source file from the caller's directory" \{ spago, fixture, testCwd } -> do
13+
let source = fixture "spago-script-make-file.purs"
14+
spago [ "script", "-d", "node-fs", Path.toRaw source ] >>= shouldBeSuccess
15+
checkFixture (testCwd </> "spago-script-result.txt") (fixture "spago-script-result.txt")

0 commit comments

Comments
 (0)