Skip to content

Commit 81110a6

Browse files
authored
Fix watch flag in commands other than 'build' (#153)
With the recent changes we added more "build" actions inside other commands, which implies also accepting --watch in these other commands (expected behaviour: on file change rerun the command that is being watched). However, the watch was only piped to the build command, so only the build part would be rerun on change. This fixes that by running the whole action on file change instead.
1 parent 9d04d36 commit 81110a6

3 files changed

Lines changed: 83 additions & 69 deletions

File tree

app/Main.hs

Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ import qualified Paths_spago as Pcli
88
import qualified System.Environment as Env
99
import qualified Turtle as T
1010

11-
import Spago.Build (ExtraArg (..), ModuleName (..), SourcePath (..),
12-
TargetPath (..), WithMain (..), Watch (..), NoBuild (..))
11+
import Spago.Build (BuildOptions (..), ExtraArg (..), ModuleName (..),
12+
NoBuild (..), SourcePath (..), TargetPath (..), Watch (..),
13+
WithMain (..))
1314
import qualified Spago.Build
1415
import Spago.Packages (PackageName (..), PackagesFilter (..))
1516
import qualified Spago.Packages
@@ -36,9 +37,8 @@ data Command
3637
-- | Generate documentation for the project and its dependencies
3738
| Docs [SourcePath]
3839

39-
-- | Build the project paths src/ and test/
40-
-- plus the specified source paths
41-
| Build (Maybe Int) Watch [SourcePath] [ExtraArg]
40+
-- | Build the project paths src/ and test/ plus the specified source paths
41+
| Build BuildOptions
4242

4343
-- | List available packages
4444
| ListPackages (Maybe PackagesFilter)
@@ -50,18 +50,18 @@ data Command
5050
| VerifySet (Maybe Int)
5151

5252
-- | Test the project with some module, default Test.Main
53-
| Test (Maybe ModuleName) (Maybe Int) Watch [SourcePath] [ExtraArg]
53+
| Test (Maybe ModuleName) BuildOptions
5454

5555
-- | Run the project with some module, default Main
56-
| Run (Maybe ModuleName) (Maybe Int) Watch [SourcePath] [ExtraArg]
56+
| Run (Maybe ModuleName) BuildOptions
5757

5858
-- | Bundle the project, with optional main and target path arguments
5959
-- Builds the project before bundling
60-
| Bundle (Maybe ModuleName) (Maybe TargetPath) NoBuild [SourcePath] [ExtraArg]
60+
| Bundle (Maybe ModuleName) (Maybe TargetPath) NoBuild BuildOptions
6161

6262
-- | Bundle a module into a CommonJS module
6363
-- Builds the project before bundling
64-
| MakeModule (Maybe ModuleName) (Maybe TargetPath) NoBuild [SourcePath] [ExtraArg]
64+
| MakeModule (Maybe ModuleName) (Maybe TargetPath) NoBuild BuildOptions
6565

6666
-- | Upgrade the package-set to the latest release
6767
| PackageSetUpgrade
@@ -106,12 +106,12 @@ parser = projectCommands
106106
watch = do
107107
res <- watchBool
108108
pure $ case res of
109-
True -> Watch
109+
True -> Watch
110110
False -> BuildOnce
111111
noBuild = do
112112
res <- noBuildBool
113113
pure $ case res of
114-
True -> NoBuild
114+
True -> NoBuild
115115
False -> DoBuild
116116
mainModule = T.optional (T.opt (Just . ModuleName) "main" 'm' "The main module to bundle")
117117
toTarget = T.optional (T.opt (Just . TargetPath) "to" 't' "The target file path")
@@ -120,6 +120,7 @@ parser = projectCommands
120120
packageName = T.arg (Just . PackageName) "package" "Specify a package name. You can list them with `list-packages`"
121121
packageNames = T.many $ T.arg (Just . PackageName) "package" "Package name to add as dependency"
122122
passthroughArgs = T.many $ T.arg (Just . ExtraArg) " ..any `purs compile` option" "Options passed through to `purs compile`; use -- to separate"
123+
buildOptions = BuildOptions <$> limitJobs <*> watch <*> sourcePaths <*> passthroughArgs
123124
packagesFilter =
124125
let wrap = \case
125126
"direct" -> Just DirectDeps
@@ -147,7 +148,7 @@ parser = projectCommands
147148
build =
148149
( "build"
149150
, "Install the dependencies and compile the current package"
150-
, Build <$> limitJobs <*> watch <*> sourcePaths <*> passthroughArgs
151+
, Build <$> buildOptions
151152
)
152153

153154
repl =
@@ -159,25 +160,25 @@ parser = projectCommands
159160
test =
160161
( "test"
161162
, "Test the project with some module, default Test.Main"
162-
, Test <$> mainModule <*> limitJobs <*> watch <*> sourcePaths <*> passthroughArgs
163+
, Test <$> mainModule <*> buildOptions
163164
)
164-
165+
165166
run =
166167
( "run"
167168
, "Runs the project with some module, default Main"
168-
, Run <$> mainModule <*> limitJobs <*> watch <*> sourcePaths <*> passthroughArgs
169+
, Run <$> mainModule <*> buildOptions
169170
)
170171

171172
bundle =
172173
( "bundle"
173174
, "Bundle the project, with optional main and target path arguments"
174-
, Bundle <$> mainModule <*> toTarget <*> noBuild <*> sourcePaths <*> passthroughArgs
175+
, Bundle <$> mainModule <*> toTarget <*> noBuild <*> buildOptions
175176
)
176177

177178
makeModule =
178179
( "make-module"
179180
, "Bundle a module into a CommonJS module"
180-
, MakeModule <$> mainModule <*> toTarget <*> noBuild <*> sourcePaths <*> passthroughArgs
181+
, MakeModule <$> mainModule <*> toTarget <*> noBuild <*> buildOptions
181182
)
182183

183184
docs =
@@ -298,16 +299,14 @@ main = do
298299
VerifySet limitJobs -> Spago.Packages.verify limitJobs Nothing
299300
PackageSetUpgrade -> Spago.Packages.upgradePackageSet
300301
Freeze -> Spago.Packages.freeze
301-
Build limitJobs watch paths pursArgs -> Spago.Build.build limitJobs watch paths pursArgs
302-
Test modName limitJobs watch paths pursArgs
303-
-> Spago.Build.test modName limitJobs watch paths pursArgs
304-
Run modName limitJobs watch paths pursArgs
305-
-> Spago.Build.run modName limitJobs watch paths pursArgs
302+
Build buildOptions -> Spago.Build.build buildOptions Nothing
303+
Test modName buildOptions -> Spago.Build.test modName buildOptions
304+
Run modName buildOptions -> Spago.Build.run modName buildOptions
306305
Repl paths pursArgs -> Spago.Build.repl paths pursArgs
307-
Bundle modName tPath build paths pursArgs
308-
-> Spago.Build.bundle WithMain modName tPath build paths pursArgs
309-
MakeModule modName tPath build paths pursArgs
310-
-> Spago.Build.makeModule modName tPath build paths pursArgs
306+
Bundle modName tPath shouldBuild buildOptions
307+
-> Spago.Build.bundle WithMain modName tPath shouldBuild buildOptions
308+
MakeModule modName tPath shouldBuild buildOptions
309+
-> Spago.Build.makeModule modName tPath shouldBuild buildOptions
311310
Docs sourcePaths -> Spago.Build.docs sourcePaths
312311
Version -> printVersion
313312
PscPackageLocalSetup force -> PscPackage.localSetup force

app/Spago/Build.hs

Lines changed: 53 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ module Spago.Build
88
, docs
99
, Watch (..)
1010
, NoBuild (..)
11+
, BuildOptions (..)
1112
, Purs.ExtraArg (..)
1213
, Purs.ModuleName (..)
1314
, Purs.SourcePath (..)
@@ -37,6 +38,13 @@ data Watch = Watch | BuildOnce
3738
-- or skip it, in the case of 'bundle' and 'makeModule'.
3839
data NoBuild = NoBuild | DoBuild
3940

41+
data BuildOptions = BuildOptions
42+
{ maybeLimit :: Maybe Int
43+
, shouldWatch :: Watch
44+
, sourcePaths :: [Purs.SourcePath]
45+
, passthroughArgs :: [Purs.ExtraArg]
46+
}
47+
4048
defaultSourcePaths :: [Purs.SourcePath]
4149
defaultSourcePaths =
4250
[ Purs.SourcePath "src/**/*.purs"
@@ -53,16 +61,20 @@ prepareBundleDefaults maybeModuleName maybeTargetPath = (moduleName, targetPath)
5361
targetPath = fromMaybe (Purs.TargetPath "index.js") maybeTargetPath
5462

5563

56-
-- | Build the project with purs, passing through
57-
-- the additional args in the list
58-
build :: Maybe Int -> Watch -> [Purs.SourcePath] -> [Purs.ExtraArg] -> IO ()
59-
build maybeLimit shouldWatch sourcePaths passthroughArgs = do
64+
-- | Build the project with purs, passing through additional args and
65+
-- eventually running some other action after the build
66+
build :: BuildOptions -> Maybe (IO ()) -> IO ()
67+
build BuildOptions{..} maybePostBuild = do
6068
config <- Config.ensureConfig
6169
deps <- Packages.getProjectDeps config
6270
Packages.fetchPackages maybeLimit deps
6371
let projectGlobs = defaultSourcePaths <> sourcePaths
6472
allGlobs = Packages.getGlobs deps <> projectGlobs
65-
buildAction = Purs.compile allGlobs passthroughArgs
73+
buildAction = do
74+
Purs.compile allGlobs passthroughArgs
75+
case maybePostBuild of
76+
Just action -> action
77+
Nothing -> pure ()
6678
absoluteProjectGlobs <- traverse makeAbsolute $ Text.unpack . Purs.unSourcePath <$> projectGlobs
6779
case shouldWatch of
6880
BuildOnce -> buildAction
@@ -78,59 +90,60 @@ repl sourcePaths passthroughArgs = do
7890

7991
-- | Test the project: compile and run "Test.Main"
8092
-- (or the provided module name) with node
81-
test :: Maybe Purs.ModuleName -> Maybe Int -> Watch -> [Purs.SourcePath] -> [Purs.ExtraArg] -> IO ()
93+
test :: Maybe Purs.ModuleName -> BuildOptions -> IO ()
8294
test = runWithNode (Purs.ModuleName "Test.Main") (Just "Tests succeeded.") "Tests failed: "
8395

8496
-- | Run the project: compile and run "Main"
8597
-- (or the provided module name) with node
86-
run :: Maybe Purs.ModuleName -> Maybe Int -> Watch -> [Purs.SourcePath] -> [Purs.ExtraArg] -> IO ()
98+
run :: Maybe Purs.ModuleName -> BuildOptions -> IO ()
8799
run = runWithNode (Purs.ModuleName "Main") Nothing "Running failed, exit code: "
88100

89101
-- | Run the project with node: compile and run with the provided ModuleName
90102
-- (or the default one if that's missing)
91-
runWithNode :: Purs.ModuleName
92-
-> Maybe T.Text
93-
-> T.Text
94-
-> Maybe Purs.ModuleName
95-
-> Maybe Int
96-
-> Watch
97-
-> [Purs.SourcePath]
98-
-> [Purs.ExtraArg]
99-
-> IO ()
100-
runWithNode defaultModuleName maybeSuccessMessage failureMessage maybeModuleName
101-
maybeLimit shouldWatch paths passthroughArgs = do
102-
build maybeLimit shouldWatch paths passthroughArgs
103-
T.shell cmd T.empty >>= \case
104-
T.ExitSuccess -> fromMaybe (pure ()) (echo <$> maybeSuccessMessage)
105-
T.ExitFailure n -> die $ failureMessage <> T.repr n
103+
runWithNode
104+
:: Purs.ModuleName
105+
-> Maybe T.Text
106+
-> T.Text
107+
-> Maybe Purs.ModuleName
108+
-> BuildOptions
109+
-> IO ()
110+
runWithNode defaultModuleName maybeSuccessMessage failureMessage maybeModuleName buildOpts = do
111+
build buildOpts (Just nodeAction)
106112
where
107113
moduleName = fromMaybe defaultModuleName maybeModuleName
108114
cmd = "node -e \"require('./output/" <> Purs.unModuleName moduleName <> "').main()\""
115+
nodeAction = do
116+
T.shell cmd T.empty >>= \case
117+
T.ExitSuccess -> fromMaybe (pure ()) (echo <$> maybeSuccessMessage)
118+
T.ExitFailure n -> die $ failureMessage <> T.repr n
109119

110120
-- | Bundle the project to a js file
111-
bundle :: Purs.WithMain -> Maybe Purs.ModuleName -> Maybe Purs.TargetPath -> NoBuild -> [Purs.SourcePath] -> [Purs.ExtraArg] -> IO ()
112-
bundle withMain maybeModuleName maybeTargetPath noBuild paths passthroughArgs =
121+
bundle :: Purs.WithMain -> Maybe Purs.ModuleName -> Maybe Purs.TargetPath -> NoBuild -> BuildOptions -> IO ()
122+
bundle withMain maybeModuleName maybeTargetPath noBuild buildOpts =
113123
let (moduleName, targetPath) = prepareBundleDefaults maybeModuleName maybeTargetPath
114-
in do
115-
case noBuild of
116-
DoBuild -> build Nothing BuildOnce paths passthroughArgs
117-
NoBuild -> pure ()
118-
Purs.bundle withMain moduleName targetPath
124+
bundleAction = Purs.bundle withMain moduleName targetPath
125+
in case noBuild of
126+
DoBuild -> build buildOpts (Just bundleAction)
127+
NoBuild -> bundleAction
119128

120129
-- | Bundle into a CommonJS module
121-
makeModule :: Maybe Purs.ModuleName -> Maybe Purs.TargetPath -> NoBuild -> [Purs.SourcePath] -> [Purs.ExtraArg] -> IO ()
122-
makeModule maybeModuleName maybeTargetPath noBuild paths passthroughArgs = do
130+
makeModule :: Maybe Purs.ModuleName -> Maybe Purs.TargetPath -> NoBuild -> BuildOptions -> IO ()
131+
makeModule maybeModuleName maybeTargetPath noBuild buildOpts =
123132
let (moduleName, targetPath) = prepareBundleDefaults maybeModuleName maybeTargetPath
124133
jsExport = Text.unpack $ "\nmodule.exports = PS[\""<> Purs.unModuleName moduleName <> "\"];"
125-
echo "Bundling first..."
126-
bundle Purs.WithoutMain (Just moduleName) (Just targetPath) noBuild paths passthroughArgs
127-
-- Here we append the CommonJS export line at the end of the bundle
128-
try (T.with
129-
(T.appendonly $ T.fromText $ Purs.unTargetPath targetPath)
130-
((flip hPutStrLn) jsExport))
131-
>>= \case
132-
Right _ -> echo $ "Make module succeeded and output file to " <> Purs.unTargetPath targetPath
133-
Left (n :: SomeException) -> die $ "Make module failed: " <> T.repr n
134+
bundleAction = do
135+
echo "Bundling first..."
136+
Purs.bundle Purs.WithoutMain moduleName targetPath
137+
-- Here we append the CommonJS export line at the end of the bundle
138+
try (T.with
139+
(T.appendonly $ T.fromText $ Purs.unTargetPath targetPath)
140+
((flip hPutStrLn) jsExport))
141+
>>= \case
142+
Right _ -> echo $ "Make module succeeded and output file to " <> Purs.unTargetPath targetPath
143+
Left (n :: SomeException) -> die $ "Make module failed: " <> T.repr n
144+
in case noBuild of
145+
DoBuild -> build buildOpts (Just bundleAction)
146+
NoBuild -> bundleAction
134147

135148
-- | Generate docs for the `sourcePaths`
136149
docs :: [Purs.SourcePath] -> IO ()

test/spago-test.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,8 @@
150150

151151

152152
## spago bundle
153-
shutil.rmtree("./output") ## Remove output to ensure bundle builds as well as bundles
154153

154+
shutil.rmtree("./output") ## Remove output to ensure bundle builds as well as bundles
155155
expect_success(
156156
['spago', 'bundle', '--to', 'bundle.js'],
157157
"Spago should bundle successfully"
@@ -163,10 +163,12 @@
163163

164164

165165
## spago make-module
166-
shutil.rmtree("./output") ## Remove output to ensure bundle builds as well as bundles
167166

167+
# Now we don't remove the output folder, but we pass the `--no-build`
168+
# flag to skip rebuilding (i.e. we are counting on the previous command to
169+
# have built stuff for us)
168170
expect_success(
169-
['spago', 'make-module', '--to', 'module.js'],
171+
['spago', 'make-module', '--to', 'module.js', '--no-build'],
170172
"Spago should successfully make a module"
171173
)
172174

0 commit comments

Comments
 (0)