From 026bf4f0a6373d4d810213e6b673ab56157cee13 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Sat, 2 Dec 2023 20:13:06 -0600 Subject: [PATCH 01/21] Update node deps as much as possible --- core/spago.yaml | 1 - core/src/Log.purs | 4 +- docs-search/index/spago.yaml | 1 - .../index/src/Docs/Search/IndexBuilder.purs | 2 +- .../index/test/Docs/Search/IndexBuilder.purs | 3 - spago.lock | 276 ++++++++++-------- spago.yaml | 35 ++- src/Spago/Cmd.purs | 115 ++++++-- src/Spago/Command/Build.purs | 8 +- src/Spago/Command/Bundle.purs | 10 +- src/Spago/Command/Docs.purs | 7 +- src/Spago/Command/Ls.purs | 2 +- src/Spago/Command/Run.purs | 26 +- src/Spago/Git.purs | 61 ++-- src/Spago/Psa.purs | 9 +- src/Spago/Purs.purs | 19 +- test/Prelude.purs | 62 ++-- test/Spago.purs | 8 +- test/Spago/Build/Pedantic.purs | 3 +- test/Spago/Build/Polyrepo.purs | 13 +- test/Spago/Publish.purs | 3 +- test/Spago/Registry.purs | 8 +- test/Spago/Test.purs | 5 +- 23 files changed, 394 insertions(+), 287 deletions(-) diff --git a/core/spago.yaml b/core/spago.yaml index 3c488e478..11fd47609 100644 --- a/core/spago.yaml +++ b/core/spago.yaml @@ -22,7 +22,6 @@ package: - newtype - node-buffer - node-fs - - node-fs-aff - node-path - node-process - ordered-collections diff --git a/core/src/Log.purs b/core/src/Log.purs index 38c7a99f0..2d075614d 100644 --- a/core/src/Log.purs +++ b/core/src/Log.purs @@ -152,13 +152,13 @@ logError l = log { level: LogError, content: Ansi.foreground Ansi.Red (toDoc l) die :: forall a b m u. MonadEffect m => MonadAsk (LogEnv b) m => Loggable a => a -> m u die msg = do logFailure msg - Effect.liftEffect $ Process.exit 1 + Effect.liftEffect $ Process.exit' 1 -- | Same as `die`, but with multiple failures die' :: forall a b m u. MonadEffect m => MonadAsk (LogEnv b) m => Loggable a => Array a -> m u die' msgs = do _ <- traverse logFailure msgs - Effect.liftEffect $ Process.exit 1 + Effect.liftEffect $ Process.exit' 1 justOrDieWith :: forall a b m x. MonadEffect m => MonadAsk (LogEnv b) m => Loggable a => Maybe x -> a -> m x justOrDieWith value msg = case value of diff --git a/docs-search/index/spago.yaml b/docs-search/index/spago.yaml index fa9a8c302..79013bfb6 100644 --- a/docs-search/index/spago.yaml +++ b/docs-search/index/spago.yaml @@ -19,7 +19,6 @@ package: - newtype - node-buffer - node-fs - - node-fs-aff - node-process - ordered-collections - prelude diff --git a/docs-search/index/src/Docs/Search/IndexBuilder.purs b/docs-search/index/src/Docs/Search/IndexBuilder.purs index 088ed425e..e5e3f0834 100644 --- a/docs-search/index/src/Docs/Search/IndexBuilder.purs +++ b/docs-search/index/src/Docs/Search/IndexBuilder.purs @@ -447,7 +447,7 @@ withExisting file f = do logAndExit :: forall a. String -> Effect a logAndExit message = do log message - Process.exit 1 + Process.exit' 1 showGlobs :: Array String -> String showGlobs = Array.intercalate ", " diff --git a/docs-search/index/test/Docs/Search/IndexBuilder.purs b/docs-search/index/test/Docs/Search/IndexBuilder.purs index ca1144efa..1a20c63c7 100644 --- a/docs-search/index/test/Docs/Search/IndexBuilder.purs +++ b/docs-search/index/test/Docs/Search/IndexBuilder.purs @@ -5,8 +5,6 @@ import Prelude import Docs.Search.IndexBuilder (patchHtml) import Data.Maybe (Maybe(..)) -import Data.Traversable (traverse) -import Effect.Class (liftEffect) import Test.Spec (Spec, describe, it) import Test.Spec.Assertions (shouldEqual, shouldNotEqual) @@ -20,6 +18,5 @@ tests = do shouldNotEqual patched (Just input) shouldNotEqual patched Nothing it "only patches once" do - let input = "" let patchTwice = patchHtml >=> patchHtml shouldEqual (patchTwice "") Nothing diff --git a/spago.lock b/spago.lock index 2f4214c6a..709d46b26 100644 --- a/spago.lock +++ b/spago.lock @@ -87,7 +87,6 @@ workspace: - newtype - node-buffer - node-fs - - node-fs-aff - node-process - ordered-collections - prelude @@ -189,7 +188,6 @@ workspace: - newtype - node-buffer - node-fs - - node-fs-aff - node-path - node-process - ordered-collections @@ -203,8 +201,32 @@ workspace: - tuples test_dependencies: [] package_set: - registry: 20.0.1 + registry: 46.0.0 extra_packages: + dodo-printer: + dependencies: + - aff + - ansi + - arrays + - avar + - console + - control + - effect + - either + - exceptions + - foldable-traversable + - integers + - lists + - maybe + - newtype + - parallel + - partial + - prelude + - safe-coerce + - strings + - tuples + git: https://github.com/natefaubion/purescript-dodo-printer.git + ref: v2.2.1 html-parser-halogen: dependencies: - halogen @@ -320,7 +342,6 @@ workspace: - lists - maybe - node-fs - - node-fs-aff - node-path - node-process - ordered-collections @@ -331,14 +352,15 @@ workspace: - tuples git: https://github.com/natefaubion/purescript-node-glob-basic.git ref: v1.2.2 + optparse: 5.0.0 ordered-collections: 3.1.1 registry-foreign: git: https://github.com/purescript/registry-dev.git - ref: 6a803c37577af368caa221a2a06d6be2079d32da + ref: d7d35c94cc286528e506a6a7ca78d22c84b251c9 subdir: foreign registry-lib: git: https://github.com/purescript/registry-dev.git - ref: 6a803c37577af368caa221a2a06d6be2079d32da + ref: d7d35c94cc286528e506a6a7ca78d22c84b251c9 subdir: lib search-trie: dependencies: @@ -394,7 +416,7 @@ workspace: - newtype - node-buffer - node-child-process - - node-fs-aff + - node-fs - node-path - node-process - node-streams @@ -502,12 +524,13 @@ packages: dependencies: [] arrays: type: registry - version: 7.2.0 - integrity: sha256-vjd5tY1VFIg3HGBUFqG9+tWXqkV3EHRqZCzE+JC2yR0= + version: 7.3.0 + integrity: sha256-tmcklBlc/muUtUfr9RapdCPwnlQeB3aSrC4dK85gQlc= dependencies: - bifunctors - control - foldable-traversable + - functions - maybe - nonempty - partial @@ -575,8 +598,8 @@ packages: - unfoldable codec: type: registry - version: 6.0.0 - integrity: sha256-VLG7Ii38xmeT5UGH98xBFiWp1YnFZim/iMg+aQz2RB8= + version: 6.1.0 + integrity: sha256-6vMLNlsJxQarVQ9cn1FYfl5x6opfzxAza15SzRdxFxQ= dependencies: - bifunctors - profunctor @@ -604,8 +627,8 @@ packages: - strings console: type: registry - version: 6.0.0 - integrity: sha256-gJpJ53fCDAL8BiCiJXH0HNAJ9K3gJtLo8GDaCK6hA5U= + version: 6.1.0 + integrity: sha256-CxmAzjgyuGDmt9FZW51VhV6rBPwR6o0YeKUzA9rSzcM= dependencies: - effect - prelude @@ -677,6 +700,13 @@ packages: - partial - prelude - tuples + debug: + type: registry + version: 6.0.2 + integrity: sha256-vmkYFuXYuELBzeauvgHG6E6Kf/Hp1dAnxwE9ByHfwSg= + dependencies: + - functions + - prelude distributive: type: registry version: 6.0.0 @@ -688,9 +718,9 @@ packages: - tuples - type-equality dodo-printer: - type: registry - version: 2.2.1 - integrity: sha256-9HgCr5c0TMZCSi/ibCB5LlAL8HTQf/KTRljIXkZeEKM= + type: git + url: https://github.com/natefaubion/purescript-dodo-printer.git + rev: 831c5c963a57ca4bfd62f96335267d7d0785851d dependencies: - aff - ansi @@ -705,25 +735,17 @@ packages: - integers - lists - maybe - - minibench - newtype - - node-buffer - - node-child-process - - node-fs-aff - - node-path - - node-process - - node-streams - parallel - partial - - posix-types - prelude - safe-coerce - strings - tuples dom-indexed: type: registry - version: 11.0.0 - integrity: sha256-asNUditTILJdNGS7xxFFkm6TrxC0hykoZUII3aTi5Q4= + version: 12.0.0 + integrity: sha256-bltgxNRfJrJc73YirgM+8u4AqdJAsuaKr7epwzIayF0= dependencies: - media-types - prelude @@ -793,49 +815,25 @@ packages: - enums fetch: type: registry - version: 1.1.4 - integrity: sha256-Tmt60rjS4PNtKMVGpo8O6W1Fdhcu3a3CvyN/x+SwXEs= + version: 4.0.0 + integrity: sha256-Ita74WPIvzCsSIkUQQbBDKgIrsnuBWIRzEJ8Q5P7iQU= dependencies: - aff - - aff-promise - arraybuffer-types + - bifunctors - effect - - fetch-core - - foreign - - http-methods - - newtype - - prelude - - record - - typelevel-prelude - - unsafe-coerce - - web-file - - web-promise - - web-streams - fetch-core: - type: registry - version: 4.0.4 - integrity: sha256-lS4yhvznII/vg37LewU/Ubeoj6OpxED2kb5/yn58YQQ= - dependencies: - - arraybuffer-types - - arrays - - console - - effect - - foldable-traversable - foreign - - foreign-object - - functions - http-methods + - js-fetch + - js-promise-aff - maybe - newtype - - nullable + - ordered-collections - prelude - record - - tuples + - strings - typelevel-prelude - - unfoldable - - unsafe-coerce - web-file - - web-promise - web-streams filterable: type: registry @@ -936,8 +934,8 @@ packages: - transformers free: type: registry - version: 7.0.0 - integrity: sha256-72auTIZAG6fhz4F94rxyDwgfnHwp+/89rujZpZWrV0w= + version: 7.1.0 + integrity: sha256-JAumgEsGSzJCNLD8AaFvuX7CpqS5yruCngi6yI7+V5k= dependencies: - catenable-lists - control @@ -1119,6 +1117,29 @@ packages: - foreign - integers - now + js-fetch: + type: registry + version: 0.2.1 + integrity: sha256-zQaVi9wFWku1SsWmdR11kRpOb+wxkNWR49cn928ucjw= + dependencies: + - arraybuffer-types + - arrays + - effect + - foldable-traversable + - foreign + - foreign-object + - functions + - http-methods + - js-promise + - maybe + - newtype + - prelude + - record + - tuples + - typelevel-prelude + - unfoldable + - web-file + - web-streams js-promise: type: registry version: 1.0.0 @@ -1130,6 +1151,14 @@ packages: - functions - maybe - prelude + js-promise-aff: + type: registry + version: 1.0.0 + integrity: sha256-s9kml9Ei74hKlMMg41yyZp4GkbmYUwaH+gBWWrdhwec= + dependencies: + - aff + - foreign + - js-promise js-timers: type: registry version: 6.1.0 @@ -1304,18 +1333,6 @@ packages: dependencies: - newtype - prelude - minibench: - type: registry - version: 4.0.1 - integrity: sha256-7jyxcklZI49q/otYvMV4f9YnJwEqQ3Me5buhDwAOydw= - dependencies: - - console - - effect - - integers - - numbers - - partial - - prelude - - refs mmorph: type: registry version: 7.0.0 @@ -1333,42 +1350,47 @@ packages: - safe-coerce node-buffer: type: registry - version: 8.0.0 - integrity: sha256-RwOTB8yTS4Jjqc55JqxRcVaMXP+cYJ5aww0XH1Z/I8A= + version: 9.0.0 + integrity: sha256-PWE2DJ5ruBLCmeA/fUiuySEFmUJ/VuRfyrnCuVZBlu4= dependencies: - arraybuffer-types - effect - maybe + - nullable - st - unsafe-coerce node-child-process: type: registry - version: 9.0.0 - integrity: sha256-bi7hXHcrgqw6UQzD4p0kr2flPxdqyRHv3bLcffZYpm0= + version: 11.1.0 + integrity: sha256-vioMNgk8p+CGwlb6T3I3TIir27el85Yg4satLE/I89w= dependencies: - exceptions - foreign - foreign-object - functions + - node-event-emitter - node-fs + - node-os - node-streams - nullable - posix-types - unsafe-coerce node-event-emitter: type: registry - version: 1.0.1 - integrity: sha256-OwJNgvg20g4g5Alp5Zka3C5KMLH8hwTz9KW4DYr82ls= + version: 3.0.0 + integrity: sha256-Qw0MjsT4xRH2j2i4K8JmRjcMKnH5z1Cw39t00q4LE4w= dependencies: - effect + - either - functions + - maybe + - nullable - prelude - - safe-coerce - unsafe-coerce node-execa: type: registry - version: 1.3.2 - integrity: sha256-kKVeJC+s5Pfye9aJ2V55NUfSyETZ2DZxPP02+zpNS/M= + version: 5.0.0 + integrity: sha256-yNcgbCs4guwoTApyV6LRoYCYnU5loWgQiqMtsbloZqk= dependencies: - aff - arrays @@ -1384,9 +1406,11 @@ packages: - js-timers - maybe - node-buffer + - node-child-process - node-event-emitter - node-fs - node-human-signals + - node-os - node-path - node-process - node-streams @@ -1398,20 +1422,18 @@ packages: - partial - posix-types - prelude - - profunctor-lenses - record - refs - safe-coerce - strings - tailrec - - transformers - tuples - unsafe-coerce - unsafe-reference node-fs: type: registry - version: 8.2.0 - integrity: sha256-6X/8KFH5qAF15UDrMadoyAMZxd08bs9IF2XrVgvpH2I= + version: 9.1.0 + integrity: sha256-TzhvGdrwcM0bazDvrWSqh+M/H8GKYf1Na6aGm2Qg4+c= dependencies: - datetime - effect @@ -1430,15 +1452,6 @@ packages: - prelude - strings - unsafe-coerce - node-fs-aff: - type: registry - version: 9.2.0 - integrity: sha256-usKEFrLY9zh8o3IP3bwc+jX7Zd4OOmhHvwLFZlxdN8U= - dependencies: - - aff - - either - - node-fs - - node-path node-human-signals: type: registry version: 1.0.0 @@ -1450,6 +1463,30 @@ packages: - maybe - ordered-collections - prelude + node-os: + type: registry + version: 5.1.0 + integrity: sha256-K3gcu9AXanN1+qtk1900+Fi+CuO0s3/H/RMNRNgIzso= + dependencies: + - arrays + - bifunctors + - console + - control + - datetime + - effect + - either + - exceptions + - foldable-traversable + - foreign + - foreign-object + - functions + - maybe + - node-buffer + - nullable + - partial + - posix-types + - prelude + - unsafe-coerce node-path: type: registry version: 5.0.0 @@ -1458,25 +1495,29 @@ packages: - effect node-process: type: registry - version: 10.0.0 - integrity: sha256-YzUqf7HWkGEQVRmkxUpL1x2GzKqKLyEyR7mkP68xcZs= + version: 11.2.0 + integrity: sha256-+2MQDYChjGbVbapCyJtuWYwD41jk+BntF/kcOTKBMVs= dependencies: - effect + - foreign - foreign-object - maybe + - node-event-emitter - node-streams - posix-types - prelude - unsafe-coerce node-streams: type: registry - version: 7.0.0 - integrity: sha256-EGCA+hp6chlxDlQ8UG3RIaIIL1R0OckKnqP+KPAX1y4= + version: 9.0.0 + integrity: sha256-2n6dq7YWleTDmD1Kur/ul7Cn08IvWrScgPf+0PgX2TQ= dependencies: + - aff - effect - either - exceptions - node-buffer + - node-event-emitter - nullable - prelude nonempty: @@ -1600,8 +1641,8 @@ packages: - prelude parallel: type: registry - version: 6.0.0 - integrity: sha256-VJbkGD0rAKX+NUEeBJbYJ78bEKaZbgow+QwQEfPB6ko= + version: 7.0.0 + integrity: sha256-gUC9i4Txnx9K9RcMLsjujbwZz6BB1bnE2MLvw4GIw5o= dependencies: - control - effect @@ -1783,7 +1824,7 @@ packages: registry-foreign: type: git url: https://github.com/purescript/registry-dev.git - rev: 6a803c37577af368caa221a2a06d6be2079d32da + rev: d7d35c94cc286528e506a6a7ca78d22c84b251c9 subdir: foreign dependencies: - aff @@ -1821,7 +1862,7 @@ packages: registry-lib: type: git url: https://github.com/purescript/registry-dev.git - rev: 6a803c37577af368caa221a2a06d6be2079d32da + rev: d7d35c94cc286528e506a6a7ca78d22c84b251c9 subdir: lib dependencies: - aff @@ -1847,7 +1888,6 @@ packages: - newtype - node-buffer - node-fs - - node-fs-aff - node-path - nullable - ordered-collections @@ -1902,17 +1942,17 @@ packages: - prelude spec: type: registry - version: 7.3.0 - integrity: sha256-YmmRmlHmSHyAM8j5/QVHLgkMhtAkt2FXytVb5j/Zu0s= + version: 7.5.5 + integrity: sha256-HdyBH7Ys1/m2SdTq3u2u9LdQ4cGeaohWeEMYay2mHdU= dependencies: - aff - ansi - arrays - avar - bifunctors - - console - control - datetime + - debug - effect - either - exceptions @@ -1928,6 +1968,7 @@ packages: - parallel - pipes - prelude + - refs - strings - tailrec - transformers @@ -2150,25 +2191,14 @@ packages: - web-storage web-pointerevents: type: registry - version: 1.0.0 - integrity: sha256-I3OGc4gVslh2QsH8QUTeihKCIpFwv4t3RoycZB9ITOs= + version: 2.0.0 + integrity: sha256-uy1cI/Tck8Cf/MP0psvm2MLNxdijqfLZGLRq5FmuRh0= dependencies: - effect - maybe - prelude - web-dom - web-uievents - web-promise: - type: registry - version: 3.1.0 - integrity: sha256-YfqJyEC3bHH6D8QgTi0ME5oJmGYOuZ2TlcyOdpG8dIE= - dependencies: - - effect - - exceptions - - foldable-traversable - - functions - - maybe - - prelude web-storage: type: registry version: 5.0.0 @@ -2178,16 +2208,16 @@ packages: - web-events web-streams: type: registry - version: 3.0.0 - integrity: sha256-+QELAR7lb08Ebr4lCntxeGk5Z1i+NInDJwzEzz3Pigc= + version: 4.0.0 + integrity: sha256-02HgXIk6R+pU9fWOX42krukAI1QkCbLKcCv3b4Jq6WI= dependencies: - arraybuffer-types - effect - exceptions + - js-promise - nullable - prelude - tuples - - web-promise web-touchevents: type: registry version: 4.0.0 @@ -2196,8 +2226,8 @@ packages: - web-uievents web-uievents: type: registry - version: 4.0.0 - integrity: sha256-Vtp5m/8IWP3flDXpnVn3Mxq8lCFDlBFp5eBnB+uO/CM= + version: 5.0.0 + integrity: sha256-5I+ut9JYno3wowti3vJGs1afKCm1ucppKuy+zhuSyss= dependencies: - web-html web-xhr: diff --git a/spago.yaml b/spago.yaml index 7f7385100..7fbcdf80c 100644 --- a/spago.yaml +++ b/spago.yaml @@ -60,15 +60,15 @@ workspace: - ImplicitQualifiedImport lock: true package_set: - registry: 20.0.1 + registry: 46.0.0 extra_packages: registry-lib: git: https://github.com/purescript/registry-dev.git - ref: 6a803c37577af368caa221a2a06d6be2079d32da + ref: d7d35c94cc286528e506a6a7ca78d22c84b251c9 subdir: lib registry-foreign: git: https://github.com/purescript/registry-dev.git - ref: 6a803c37577af368caa221a2a06d6be2079d32da + ref: d7d35c94cc286528e506a6a7ca78d22c84b251c9 subdir: foreign html-parser-halogen: dependencies: @@ -212,7 +212,7 @@ workspace: - newtype - node-buffer - node-child-process - - node-fs-aff + - node-fs - node-path - node-process - node-streams @@ -261,7 +261,7 @@ workspace: - lists - maybe - node-fs - - node-fs-aff + - node-fs - node-path - node-process - ordered-collections @@ -271,3 +271,28 @@ workspace: - strings - tuples ordered-collections: "3.1.1" + dodo-printer: + git: "https://github.com/natefaubion/purescript-dodo-printer.git" + ref: "v2.2.1" + dependencies: + - aff + - ansi + - arrays + - avar + - console + - control + - effect + - either + - exceptions + - foldable-traversable + - integers + - lists + - maybe + - newtype + - parallel + - partial + - prelude + - safe-coerce + - strings + - tuples + optparse: 5.0.0 diff --git a/src/Spago/Cmd.purs b/src/Spago/Cmd.purs index 17c0487e1..e41456ad1 100644 --- a/src/Spago/Cmd.purs +++ b/src/Spago/Cmd.purs @@ -3,9 +3,12 @@ module Spago.Cmd where import Spago.Prelude import Data.Array as Array +import Data.Foldable (traverse_) +import Data.Posix (Pid) import Data.String (Pattern(..)) import Data.String as String import Data.Time.Duration (Milliseconds(..)) +import Node.ChildProcess.Types (Exit(..), KillSignal, inherit, pipe) import Node.Library.Execa as Execa import Node.Platform as Platform import Node.Process as Process @@ -16,6 +19,61 @@ data StdinConfig | StdinNewPipe | StdinWrite String +type ExecResult = + { canceled :: Boolean + , escapedCommand :: String + , exit :: Exit + , exitCode :: Maybe Int + , killed :: Boolean + , message :: String + , originalMessage :: Maybe String + , pid :: Maybe Pid + , shortMessage :: String + , signal :: Maybe KillSignal + , signalDescription :: Maybe String + , stderr :: String + , stderrError :: Maybe Error + , stdinError :: Maybe Error + , stdout :: String + , stdoutError :: Maybe Error + , timedOut :: Boolean + } + +printExecResult :: ExecResult -> String +printExecResult r = Array.intercalate "\n" + [ "escapedCommand: " <> show r.escapedCommand + , "canceled: " <> show r.canceled + , "exit: " <> show r.exit + , "exitCode: " <> show r.exitCode + , "signal: " <> show r.signal + , "signalDescription: " <> show r.signalDescription + , "pid: " <> show r.pid + , "killed: " <> show r.killed + , "timedOut: " <> show r.timedOut + , "shortMessage: " <> show r.shortMessage + , "message: " <> show r.message + , "originalMessage: " <> show r.originalMessage + , "stdinError: " <> show r.stdinError + , "stdoutError: " <> show r.stdoutError + , "stderrError: " <> show r.stderrError + , "stderr:" + , r.stderr + , "" + , "stdout:" + , r.stdout + , "" + ] + +-- | True if the process exited normally with exit code 0 +isSuccess :: ExecResult -> Boolean +isSuccess r = case r.exit of + Normally 0 -> true + _ -> false + +-- | True if the process exited with a non-zero exit code or was terminated by a signal +isFailure :: ExecResult -> Boolean +isFailure = not <<< isSuccess + type ExecOptions = { pipeStdin :: StdinConfig , pipeStdout :: Boolean @@ -23,10 +81,6 @@ type ExecOptions = , cwd :: Maybe FilePath } -type ExecResult = Execa.ExecaSuccess - -type ExecError = Execa.ExecaError - defaultExecOptions :: ExecOptions defaultExecOptions = { pipeStdin: StdinNewPipe @@ -37,33 +91,38 @@ defaultExecOptions = spawn :: forall m. MonadAff m => String -> Array String -> ExecOptions -> m Execa.ExecaProcess spawn cmd args opts = liftAff do - subprocess <- Execa.execa cmd args (_ { cwd = opts.cwd }) + let + stdinOpt = case opts.pipeStdin of + StdinPipeParent -> Just inherit + StdinWrite _ -> Just pipe + StdinNewPipe -> Just pipe + subprocess <- Execa.execa cmd args (_ { cwd = opts.cwd, stdin = stdinOpt, stdout = Just pipe, stderr = Just pipe }) case opts.pipeStdin of - StdinPipeParent -> subprocess.stdin.shareParentProcessStdin - StdinWrite s -> subprocess.stdin.writeUtf8End s + StdinWrite s | Just { writeUtf8End } <- subprocess.stdin -> writeUtf8End s _ -> pure unit + when (opts.pipeStderr) do - subprocess.stderr.pipeToParentStderr + traverse_ _.pipeToParentStderr subprocess.stderr when (opts.pipeStdout) do - subprocess.stdout.pipeToParentStdout + traverse_ _.pipeToParentStdout subprocess.stdout pure subprocess -joinProcess :: forall m. MonadAff m => Execa.ExecaProcess -> m (Either ExecError ExecResult) -joinProcess cp = liftAff $ cp.result +joinProcess :: forall m. MonadAff m => Execa.ExecaProcess -> m ExecResult +joinProcess cp = liftAff $ cp.getResult -exec :: forall m. MonadAff m => String -> Array String -> ExecOptions -> m (Either ExecError ExecResult) +exec :: forall m. MonadAff m => String -> Array String -> ExecOptions -> m ExecResult exec cmd args opts = liftAff do subprocess <- spawn cmd args opts - subprocess.result + subprocess.getResult -kill :: Execa.ExecaProcess -> Aff ExecError +kill :: Execa.ExecaProcess -> Aff ExecResult kill cp = liftAff do void $ cp.killForced $ Milliseconds 2_000.0 - cp.result >>= case _ of - Left e -> pure e - Right res -> unsafeCrashWith ("Tried to kill the process, failed. Result: " <> show res) + cp.getResult >>= \r -> case isSuccess r of + false -> pure r + true -> unsafeCrashWith ("Tried to kill the process, failed. Result:\n" <> printExecResult r) -- | Try to find one of the flags in a list of Purs args -- | For example, trying to find the `output` arg @@ -114,25 +173,25 @@ getExecutable command = Just Platform.Win32 -> do -- On Windows, we often need to call the `.cmd` version let cmd1 = mkCmd command (Just "cmd") - askVersion cmd1 >>= case _ of - Right r -> pure { cmd: cmd1, output: r.stdout } - Left err' -> do + askVersion cmd1 >>= \r -> case isSuccess r of + true -> pure { cmd: cmd1, output: r.stdout } + false -> do let cmd2 = mkCmd command Nothing - logDebug [ "Failed to find purs.cmd. Trying with just purs...", show err' ] - askVersion cmd2 >>= case _ of - Right r -> pure { cmd: cmd2, output: r.stdout } - Left err -> complain err + logDebug [ "Failed to find purs.cmd. Trying with just purs...", show r.message ] + askVersion cmd2 >>= \r' -> case isSuccess r' of + true -> pure { cmd: cmd2, output: r'.stdout } + false -> complain r _ -> do -- On other platforms, we just call `purs` let cmd1 = mkCmd command Nothing - askVersion cmd1 >>= case _ of - Right r -> pure { cmd: cmd1, output: r.stdout } - Left err -> complain err + askVersion cmd1 >>= \r -> case isSuccess r of + true -> pure { cmd: cmd1, output: r.stdout } + false -> complain r where askVersion cmd = exec cmd [ "--version" ] defaultExecOptions { pipeStdout = false, pipeStderr = false } mkCmd cmd maybeExtension = cmd <> maybe "" (append ".") maybeExtension complain err = do - logDebug $ show err + logDebug $ printExecResult err die [ "Failed to find " <> command <> ". Have you installed it, and is it in your PATH?" ] diff --git a/src/Spago/Command/Build.purs b/src/Spago/Command/Build.purs index 22755f09f..d129b7238 100644 --- a/src/Spago/Command/Build.purs +++ b/src/Spago/Command/Build.purs @@ -132,11 +132,11 @@ run opts = do moreBackendArgs = case backend.args of Just as | Array.length as > 0 -> as _ -> [] - Cmd.exec backend.cmd (addOutputArgs moreBackendArgs) Cmd.defaultExecOptions >>= case _ of - Left err -> do - logDebug $ show err + Cmd.exec backend.cmd (addOutputArgs moreBackendArgs) Cmd.defaultExecOptions >>= \r -> case Cmd.isSuccess r of + false -> do + logDebug $ Cmd.printExecResult r die [ "Failed to build with backend " <> backend.cmd ] - Right _r -> + true -> logSuccess "Backend build succeeded." let diff --git a/src/Spago/Command/Bundle.purs b/src/Spago/Command/Bundle.purs index de9179c09..187d97113 100644 --- a/src/Spago/Command/Bundle.purs +++ b/src/Spago/Command/Bundle.purs @@ -4,8 +4,8 @@ import Spago.Prelude import Node.Path as Path import Spago.Cmd as Cmd -import Spago.Esbuild (Esbuild) import Spago.Config (BundlePlatform(..), BundleType(..), Workspace, WorkspacePackage) +import Spago.Esbuild (Esbuild) type BundleEnv a = { esbuild :: Esbuild @@ -77,8 +77,8 @@ run = do ] <> opts.extraArgs <> minify <> sourceMap <> entrypoint <> nodePatch logInfo "Bundling..." logDebug $ "Running esbuild: " <> show args - Cmd.exec esbuild.cmd args execOptions >>= case _ of - Right _r -> logSuccess "Bundle succeeded." - Left err -> do - logDebug $ show err + Cmd.exec esbuild.cmd args execOptions >>= \r -> case Cmd.isSuccess r of + true -> logSuccess "Bundle succeeded." + false -> do + logDebug $ Cmd.printExecResult r die [ "Failed to bundle." ] diff --git a/src/Spago/Command/Docs.purs b/src/Spago/Command/Docs.purs index c20fd1956..bb9ca1447 100644 --- a/src/Spago/Command/Docs.purs +++ b/src/Spago/Command/Docs.purs @@ -7,10 +7,11 @@ import Spago.Prelude import Control.Promise (Promise) import Control.Promise as Promise -import Docs.Search.IndexBuilder as IndexBuilder import Docs.Search.Config as DocConfig +import Docs.Search.IndexBuilder as IndexBuilder import Effect.Uncurried (EffectFn1, runEffectFn1) import Node.Process as Process +import Spago.Cmd as Cmd import Spago.Command.Build as Build import Spago.Command.Fetch as Fetch import Spago.Config (Workspace) @@ -42,9 +43,7 @@ run = do } result <- Purs.docs globs docsFormat - case result of - Left err -> die err.message - Right _ -> pure unit + unless (Cmd.isSuccess result) $ die result.message when (docsFormat == Html) $ do liftAff $ IndexBuilder.run' diff --git a/src/Spago/Command/Ls.purs b/src/Spago/Command/Ls.purs index 3439b053f..f872cbc0d 100644 --- a/src/Spago/Command/Ls.purs +++ b/src/Spago/Command/Ls.purs @@ -13,7 +13,7 @@ import Spago.Prelude import Data.Codec.Argonaut as CA import Data.Codec.Argonaut.Common as CAC import Data.Codec.Argonaut.Record as CAR -import Data.Foldable (elem, traverse_) +import Data.Foldable (elem) import Data.Map (filterKeys) import Data.Map as Map import Data.Tuple.Nested (type (/\)) diff --git a/src/Spago/Command/Run.purs b/src/Spago/Command/Run.purs index 6193fe05f..500ef2b66 100644 --- a/src/Spago/Command/Run.purs +++ b/src/Spago/Command/Run.purs @@ -47,11 +47,11 @@ type Node = { cmd :: String, version :: Version } nodeVersion :: forall a. Spago (LogEnv a) Version nodeVersion = - Cmd.exec "node" [ "--version" ] Cmd.defaultExecOptions { pipeStdout = false, pipeStderr = false } >>= case _ of - Left err -> do - logDebug $ show err + Cmd.exec "node" [ "--version" ] Cmd.defaultExecOptions { pipeStdout = false, pipeStderr = false } >>= \r -> case Cmd.isSuccess r of + false -> do + logDebug $ Cmd.printExecResult r die [ "Failed to find node. Have you installed it, and is it in your PATH?" ] - Right r -> case parseLenientVersion r.stdout of + true -> case parseLenientVersion r.stdout of Left _err -> die $ "Failed to parse NodeJS version. Was: " <> r.stdout Right v -> if Version.major v >= 13 then @@ -116,20 +116,20 @@ run = do FS.writeTextFile packageJsonPath packageJsonContents logDebug $ "Executing from: " <> show opts.executeDir logDebug $ "Running node command with args: `" <> show nodeArgs <> "`" - Cmd.exec node.cmd nodeArgs (execOptions { cwd = Just opts.executeDir }) >>= case _ of - Right _r -> case opts.successMessage of + Cmd.exec node.cmd nodeArgs (execOptions { cwd = Just opts.executeDir }) >>= \r -> case Cmd.isSuccess r of + true -> case opts.successMessage of Just m -> logSuccess m Nothing -> pure unit - Left err -> do - logDebug $ show err + false -> do + logDebug $ Cmd.printExecResult r die opts.failureMessage Just backend -> do let args = [ "--run", opts.moduleName <> ".main" ] <> opts.execArgs logDebug $ "Running command `" <> backend.cmd <> " " <> show args <> "`" - Cmd.exec backend.cmd args execOptions >>= case _ of - Right _r -> case opts.successMessage of + Cmd.exec backend.cmd args execOptions >>= \r -> case Cmd.isSuccess r of + true -> case opts.successMessage of Just m -> logSuccess m Nothing -> pure unit - Left err -> do - logDebug $ show err - die [ opts.failureMessage, "Backend " <> show backend <> " exited with error:" <> err.shortMessage ] + false -> do + logDebug $ Cmd.printExecResult r + die [ opts.failureMessage, "Backend " <> show backend <> " exited with error:" <> r.shortMessage ] diff --git a/src/Spago/Git.purs b/src/Spago/Git.purs index 8f2afc2f6..9ed66d33f 100644 --- a/src/Spago/Git.purs +++ b/src/Spago/Git.purs @@ -18,6 +18,7 @@ import Control.Monad.Except as Except import Data.Array as Array import Data.String (Pattern(..)) import Data.String as String +import Node.ChildProcess.Types (Exit(..)) import Node.Path as Path import Node.Process as Process import Registry.Version as Version @@ -35,7 +36,9 @@ runGit :: forall a. Array String -> Maybe FilePath -> ExceptT String (Spago (Git runGit args cwd = ExceptT do { git } <- ask result <- Cmd.exec git.cmd args (Cmd.defaultExecOptions { pipeStdout = false, pipeStderr = false, cwd = cwd }) - pure $ bimap _.stderr _.stdout result + pure case Cmd.isSuccess result of + true -> Right result.stdout + false -> Left result.stderr fetchRepo :: forall a b. { git :: String, ref :: String | a } -> FilePath -> Spago (GitEnv b) (Either (Array String) Unit) fetchRepo { git, ref } path = do @@ -79,38 +82,38 @@ listTags :: forall a. Maybe FilePath -> Spago (GitEnv a) (Either Docc (Array Str listTags cwd = do let opts = Cmd.defaultExecOptions { pipeStdout = false, pipeStderr = false, cwd = cwd } { git } <- ask - Cmd.exec git.cmd [ "tag" ] opts >>= case _ of - Left err -> do - pure $ Left $ toDoc [ "Could not run `git tag`. Error:", err.message ] - Right res -> pure $ Right $ String.split (Pattern "\n") res.stdout + Cmd.exec git.cmd [ "tag" ] opts >>= \r -> case Cmd.isSuccess r of + false -> do + pure $ Left $ toDoc [ "Could not run `git tag`. Error:", r.message ] + true -> pure $ Right $ String.split (Pattern "\n") r.stdout getStatus :: forall a. Maybe FilePath -> Spago (GitEnv a) (Either Docc String) getStatus cwd = do let opts = Cmd.defaultExecOptions { pipeStdout = false, pipeStderr = false, cwd = cwd } { git } <- ask - Cmd.exec git.cmd [ "status", "--porcelain" ] opts >>= case _ of - Left err -> do - pure $ Left $ toDoc [ "Could not run `git status`. Error:", err.message ] - Right res -> pure $ Right res.stdout + Cmd.exec git.cmd [ "status", "--porcelain" ] opts >>= \r -> case Cmd.isSuccess r of + false -> do + pure $ Left $ toDoc [ "Could not run `git status`. Error:", r.message ] + true -> pure $ Right r.stdout getRef :: forall a. Maybe FilePath -> Spago (GitEnv a) (Either Docc String) getRef cwd = do let opts = Cmd.defaultExecOptions { pipeStdout = false, pipeStderr = false, cwd = cwd } { git } <- ask - Cmd.exec git.cmd [ "rev-parse", "HEAD" ] opts >>= case _ of - Left err -> pure $ Left $ toDoc + Cmd.exec git.cmd [ "rev-parse", "HEAD" ] opts >>= \r -> case Cmd.isSuccess r of + false -> pure $ Left $ toDoc [ "Could not run `git rev-parse HEAD` to determine the current ref. Error:" - , err.shortMessage + , r.shortMessage ] - Right res' -> pure $ Right res'.stdout + true -> pure $ Right r.stdout tagCheckedOut :: forall a. Maybe FilePath -> Spago (GitEnv a) (Either Docc String) tagCheckedOut cwd = do let opts = Cmd.defaultExecOptions { pipeStdout = false, pipeStderr = false, cwd = cwd } { git } <- ask - Cmd.exec git.cmd [ "describe", "--tags", "--exact-match" ] opts >>= case _ of - Left _ -> pure $ Left $ toDoc "The git ref currently checked out is not a tag." - Right res' -> pure $ Right res'.stdout + Cmd.exec git.cmd [ "describe", "--tags", "--exact-match" ] opts >>= \r -> case Cmd.isSuccess r of + false -> pure $ Left $ toDoc "The git ref currently checked out is not a tag." + true -> pure $ Right r.stdout pushTag :: forall a. Maybe FilePath -> Version -> Spago (GitEnv a) (Either Docc Unit) pushTag cwd version = do @@ -122,13 +125,13 @@ pushTag cwd version = do pure $ Right unit Online -> do logInfo $ "Pushing tag 'v" <> Version.print version <> "' to the remote" - Cmd.exec git.cmd [ "push", "origin", "v" <> Version.print version ] opts >>= case _ of - Left err -> pure $ Left $ toDoc + Cmd.exec git.cmd [ "push", "origin", "v" <> Version.print version ] opts >>= \r -> case Cmd.isSuccess r of + false -> pure $ Left $ toDoc [ "Could not push the tag 'v" <> Version.print version <> "' to the remote." , "Error:" - , err.shortMessage + , r.shortMessage ] - Right _ -> pure $ Right unit + true -> pure $ Right unit -- | Check if the path is ignored by git -- @@ -138,12 +141,12 @@ isIgnored :: forall a. FilePath -> Spago (GitEnv a) Boolean isIgnored path = do { git } <- ask result <- Cmd.exec git.cmd [ "check-ignore", "--quiet", path ] (Cmd.defaultExecOptions { pipeStdout = false, pipeStderr = false }) - case result of + case result.exit of -- Git is successful if it's an ignored file - Right { exitCode: 0 } -> pure true + Normally 0 -> pure true -- Git will fail with exitCode 128 if this is not a git repo or if it's dealing with a link. -- We ignore links - I mean, do we really want to deal with recursive links?!? - Left { exitCode: Just 128 } -> do + Normally 128 -> do -- Sigh. Even if something is behind a link Node will not tell us that, -- so we need to check all the paths between the cwd and the provided path -- Just beautiful @@ -153,17 +156,17 @@ isIgnored path = do FS.getInBetweenPaths cwd absolutePath Array.any identity <$> traverse FS.isLink paths -- Git will fail with 1 when a file is just, like, normally ignored - Left { exitCode: Just 1 } -> pure false + Normally 1 -> pure false _ -> do logDebug "IsIgnored encountered an interesting exitCode" - logDebug $ show result + logDebug $ Cmd.printExecResult result -- We still do not ignore it, just in case pure false getGit :: forall a. Spago (LogEnv a) Git getGit = do - Cmd.exec "git" [ "--version" ] Cmd.defaultExecOptions { pipeStdout = false, pipeStderr = false } >>= case _ of - Right r -> pure { cmd: "git", version: r.stdout } - Left err -> do - logDebug $ show err + Cmd.exec "git" [ "--version" ] Cmd.defaultExecOptions { pipeStdout = false, pipeStderr = false } >>= \r -> case Cmd.isSuccess r of + true -> pure { cmd: "git", version: r.stdout } + false -> do + logDebug $ Cmd.printExecResult r die [ "Failed to find git. Have you installed it, and is it in your PATH?" ] diff --git a/src/Spago/Psa.purs b/src/Spago/Psa.purs index 9d5b91961..b25070ba7 100644 --- a/src/Spago/Psa.purs +++ b/src/Spago/Psa.purs @@ -23,6 +23,7 @@ import Foreign.Object as FO import Node.Encoding as Encoding import Node.FS.Aff as FSA import Node.Path as Path +import Spago.Cmd as Cmd import Spago.Config (Package(..), PackageMap, WorkspacePackage) import Spago.Config as Config import Spago.Core.Config (CensorBuildWarnings(..), WarningCensorTest(..)) @@ -38,11 +39,7 @@ defaultStatVerbosity = Core.CompactStats psaCompile :: forall a. Set.Set FilePath -> Array String -> PsaArgs -> Spago (Purs.PursEnv a) Unit psaCompile globs pursArgs psaArgs = do result <- Purs.compile globs (Array.snoc pursArgs "--json-errors") - let - result' = case result of - Left err -> { output: err.stdout, exitCode: err.exitCode, err: Just err } - Right success -> { output: success.stdout, exitCode: Just success.exitCode, err: Nothing } - arrErrorsIsEmpty <- forWithIndex (Str.split (Str.Pattern "\n") result'.output) \idx err -> + arrErrorsIsEmpty <- forWithIndex (Str.split (Str.Pattern "\n") result.stdout) \idx err -> case jsonParser err >>= CA.decode psaResultCodec >>> lmap CA.printJsonDecodeError of Left decodeErrMsg -> do logWarn $ Array.intercalate "\n" @@ -63,7 +60,7 @@ psaCompile globs pursArgs psaArgs = do if Array.all identity arrErrorsIsEmpty then do logSuccess "Build succeeded." else do - for_ result'.err $ logDebug <<< show + unless (Cmd.isSuccess result) $ logDebug $ Cmd.printExecResult result die [ "Failed to build." ] where diff --git a/src/Spago/Purs.purs b/src/Spago/Purs.purs index bb7df255e..cb09ee1f0 100644 --- a/src/Spago/Purs.purs +++ b/src/Spago/Purs.purs @@ -8,6 +8,7 @@ import Data.Codec.Argonaut.Record as CAR import Data.Profunctor as Profunctor import Data.Set as Set import Data.String as String +import Node.Library.Execa (ExecaResult) import Registry.Internal.Codec as Internal.Codec import Registry.Version as Version import Spago.Cmd as Cmd @@ -40,7 +41,7 @@ parseVersionOutput { cmd, output: stdout } = case parseLenientVersion (dropStuff where dropStuff pattern = fromMaybe "" <<< Array.head <<< String.split (String.Pattern pattern) -compile :: forall a. Set FilePath -> Array String -> Spago (PursEnv a) (Either Cmd.ExecError Cmd.ExecResult) +compile :: forall a. Set FilePath -> Array String -> Spago (PursEnv a) ExecaResult compile globs pursArgs = do { purs } <- ask let args = [ "compile" ] <> pursArgs <> Set.toUnfoldable globs @@ -53,7 +54,7 @@ compile globs pursArgs = do Cmd.exec purs.cmd args $ Cmd.defaultExecOptions { pipeStdout = false } -repl :: forall a. Set FilePath -> Array String -> Spago (PursEnv a) (Either Cmd.ExecError Cmd.ExecResult) +repl :: forall a. Set FilePath -> Array String -> Spago (PursEnv a) ExecaResult repl globs pursArgs = do { purs } <- ask @@ -87,7 +88,7 @@ printDocsFormat = case _ of Ctags -> "ctags" Etags -> "etags" -docs :: forall a. Set FilePath -> DocsFormat -> Spago (PursEnv a) (Either Cmd.ExecError Cmd.ExecResult) +docs :: forall a. Set FilePath -> DocsFormat -> Spago (PursEnv a) ExecaResult docs globs format = do { purs } <- ask let args = [ "docs", "--format", printDocsFormat format ] <> Set.toUnfoldable globs @@ -126,10 +127,10 @@ graph globs pursArgs = do let args = [ "graph" ] <> pursArgs <> Set.toUnfoldable globs logDebug [ "Running command:", "purs " <> String.joinWith " " args ] let execOpts = Cmd.defaultExecOptions { pipeStdout = false, pipeStderr = false } - Cmd.exec purs.cmd args execOpts >>= case _ of - Right { stdout } -> do + Cmd.exec purs.cmd args execOpts >>= \r -> case Cmd.isSuccess r of + true -> do logDebug "Called `purs graph`, decoding.." - pure $ parseJson moduleGraphCodec stdout - Left err -> do - logDebug $ show err - die [ "Failed to call `purs graph`, error: " <> err.shortMessage ] + pure $ parseJson moduleGraphCodec r.stdout + false -> do + logDebug $ Cmd.printExecResult r + die [ "Failed to call `purs graph`, error: " <> r.shortMessage ] diff --git a/test/Prelude.purs b/test/Prelude.purs index e5baf0305..035e0f7f1 100644 --- a/test/Prelude.purs +++ b/test/Prelude.purs @@ -16,8 +16,8 @@ import Node.Path as Path import Node.Process as Process import Registry.PackageName as PackageName import Registry.Version as Version -import Spago.Cmd (ExecError, ExecResult) as X -import Spago.Cmd (ExecError, ExecResult, StdinConfig(..)) +import Spago.Cmd (ExecResult, StdinConfig(..)) as X +import Spago.Cmd (ExecResult, StdinConfig(..)) import Spago.Cmd as Cmd import Spago.Command.Init as Init import Spago.Core.Config (Dependencies(..), Config) @@ -28,8 +28,8 @@ import Test.Spec.Assertions (fail) import Test.Spec.Assertions as Assert type TestDirs = - { spago :: Array String -> Aff (Either ExecError ExecResult) - , spago' :: StdinConfig -> Array String -> Aff (Either ExecError ExecResult) + { spago :: Array String -> Aff ExecResult + , spago' :: StdinConfig -> Array String -> Aff ExecResult , fixture :: FilePath -> FilePath , oldCwd :: FilePath , testCwd :: FilePath @@ -51,7 +51,7 @@ withTempDir = Aff.bracket createTempDir cleanupTempDir fixture path = Path.concat [ fixturesPath, path ] - spago' :: StdinConfig -> Array String -> Aff (Either ExecError ExecResult) + spago' :: StdinConfig -> Array String -> Aff ExecResult spago' stdin args = Cmd.exec "node" @@ -109,18 +109,14 @@ plusDependencies deps config = config check :: { stdout :: String -> Aff Unit , stderr :: String -> Aff Unit - , result :: Either ExecError ExecResult -> Boolean + , result :: ExecResult -> Boolean } - -> Either ExecError ExecResult + -> ExecResult -> Aff Unit check checkers execResult = do let - stdout = String.trim $ case execResult of - Left err -> err.stdout - Right res -> res.stdout - stderr = String.trim $ case execResult of - Left err -> err.stderr - Right res -> res.stderr + stdout = String.trim $ execResult.stdout + stderr = String.trim $ execResult.stderr printStdoutStderr <- liftEffect $ map isJust $ Process.lookupEnv "SPAGO_TEST_DEBUG" @@ -138,9 +134,9 @@ check checkers execResult = do checkOutputsStr :: { stdoutStr :: Maybe String , stderrStr :: Maybe String - , result :: Either ExecError ExecResult -> Boolean + , result :: ExecResult -> Boolean } - -> Either ExecError ExecResult + -> ExecResult -> Aff Unit checkOutputsStr checkers = check @@ -152,9 +148,9 @@ checkOutputsStr checkers = checkOutputs :: { stdoutFile :: Maybe FilePath , stderrFile :: Maybe FilePath - , result :: Either ExecError ExecResult -> Boolean + , result :: ExecResult -> Boolean } - -> Either ExecError ExecResult + -> ExecResult -> Aff Unit checkOutputs checkers execResult = do let @@ -175,29 +171,29 @@ checkOutputs checkers execResult = do } execResult -shouldBeSuccess :: Either ExecError ExecResult -> Aff Unit -shouldBeSuccess = checkOutputs { stdoutFile: Nothing, stderrFile: Nothing, result: isRight } +shouldBeSuccess :: ExecResult -> Aff Unit +shouldBeSuccess = checkOutputs { stdoutFile: Nothing, stderrFile: Nothing, result: Cmd.isSuccess } -shouldBeSuccessOutput :: FilePath -> Either ExecError ExecResult -> Aff Unit -shouldBeSuccessOutput outFixture = checkOutputs { stdoutFile: Just outFixture, stderrFile: Nothing, result: isRight } +shouldBeSuccessOutput :: FilePath -> ExecResult -> Aff Unit +shouldBeSuccessOutput outFixture = checkOutputs { stdoutFile: Just outFixture, stderrFile: Nothing, result: Cmd.isSuccess } -shouldBeSuccessErr :: FilePath -> Either ExecError ExecResult -> Aff Unit -shouldBeSuccessErr errFixture = checkOutputs { stdoutFile: Nothing, stderrFile: Just errFixture, result: isRight } +shouldBeSuccessErr :: FilePath -> ExecResult -> Aff Unit +shouldBeSuccessErr errFixture = checkOutputs { stdoutFile: Nothing, stderrFile: Just errFixture, result: Cmd.isSuccess } -shouldBeSuccessOutputWithErr :: FilePath -> FilePath -> Either ExecError ExecResult -> Aff Unit -shouldBeSuccessOutputWithErr outFixture errFixture = checkOutputs { stdoutFile: Just outFixture, stderrFile: Just errFixture, result: isRight } +shouldBeSuccessOutputWithErr :: FilePath -> FilePath -> ExecResult -> Aff Unit +shouldBeSuccessOutputWithErr outFixture errFixture = checkOutputs { stdoutFile: Just outFixture, stderrFile: Just errFixture, result: Cmd.isSuccess } -shouldBeFailure :: Either ExecError ExecResult -> Aff Unit -shouldBeFailure = checkOutputs { stdoutFile: Nothing, stderrFile: Nothing, result: isLeft } +shouldBeFailure :: ExecResult -> Aff Unit +shouldBeFailure = checkOutputs { stdoutFile: Nothing, stderrFile: Nothing, result: Cmd.isFailure } -shouldBeFailureOutput :: FilePath -> Either ExecError ExecResult -> Aff Unit -shouldBeFailureOutput outFixture = checkOutputs { stdoutFile: Just outFixture, stderrFile: Nothing, result: isLeft } +shouldBeFailureOutput :: FilePath -> ExecResult -> Aff Unit +shouldBeFailureOutput outFixture = checkOutputs { stdoutFile: Just outFixture, stderrFile: Nothing, result: Cmd.isFailure } -shouldBeFailureErr :: FilePath -> Either ExecError ExecResult -> Aff Unit -shouldBeFailureErr errFixture = checkOutputs { stdoutFile: Nothing, stderrFile: Just errFixture, result: isLeft } +shouldBeFailureErr :: FilePath -> ExecResult -> Aff Unit +shouldBeFailureErr errFixture = checkOutputs { stdoutFile: Nothing, stderrFile: Just errFixture, result: Cmd.isFailure } -shouldBeFailureOutputWithErr :: FilePath -> FilePath -> Either ExecError ExecResult -> Aff Unit -shouldBeFailureOutputWithErr outFixture errFixture = checkOutputs { stdoutFile: Just outFixture, stderrFile: Just errFixture, result: isLeft } +shouldBeFailureOutputWithErr :: FilePath -> FilePath -> ExecResult -> Aff Unit +shouldBeFailureOutputWithErr outFixture errFixture = checkOutputs { stdoutFile: Just outFixture, stderrFile: Just errFixture, result: Cmd.isFailure } mkPackageName :: String -> PackageName mkPackageName = unsafeFromRight <<< PackageName.parse diff --git a/test/Spago.purs b/test/Spago.purs index 0fe4f4ea3..262b43b4c 100644 --- a/test/Spago.purs +++ b/test/Spago.purs @@ -29,10 +29,10 @@ import Test.Spec.Reporter as Spec.Reporter import Test.Spec.Runner as Spec.Runner testConfig :: Spec.Runner.Config -testConfig = - { slow: Milliseconds 10_000.0 - , timeout: Just (Milliseconds 90_000.0) - , exit: true +testConfig = Spec.Runner.defaultConfig + { slow = Milliseconds 10_000.0 + , timeout = Just (Milliseconds 90_000.0) + , exit = true } main :: Effect Unit diff --git a/test/Spago/Build/Pedantic.purs b/test/Spago/Build/Pedantic.purs index f838092a7..6221e332f 100644 --- a/test/Spago/Build/Pedantic.purs +++ b/test/Spago/Build/Pedantic.purs @@ -5,6 +5,7 @@ import Test.Prelude import Data.Array as Array import Data.Map as Map import Node.Path as Path +import Spago.Cmd (ExecResult) import Spago.Core.Config (Dependencies(..), Config) import Spago.FS as FS import Test.Spec (SpecT) @@ -227,7 +228,7 @@ defaultSetupConfig = , testMain: Nothing } -setup :: (Array String -> Aff (Either ExecError ExecResult)) -> SetupConfig -> Aff Unit +setup :: (Array String -> Aff ExecResult) -> SetupConfig -> Aff Unit setup spago config = do spago [ "init", "--name", "pedantic" ] >>= shouldBeSuccess unless (Array.null config.installSourcePackages) do diff --git a/test/Spago/Build/Polyrepo.purs b/test/Spago/Build/Polyrepo.purs index fd74561f1..c9952681a 100644 --- a/test/Spago/Build/Polyrepo.purs +++ b/test/Spago/Build/Polyrepo.purs @@ -14,6 +14,7 @@ import Node.Path as Path import Node.Platform as Platform import Node.Process as Process import Registry.Version as Version +import Spago.Cmd as Cmd import Spago.Command.Init (DefaultConfigOptions(..)) import Spago.Command.Init as Init import Spago.Core.Config as Config @@ -215,7 +216,7 @@ spec = Spec.describe "polyrepo" do unless (String.contains (Pattern exp) stdErr) do Assert.fail $ "STDERR did not contain text:\n" <> exp <> "\n\nStderr was:\n" <> stdErr - spago [ "build" ] >>= check { stdout: mempty, stderr: hasExpectedModules, result: isLeft } + spago [ "build" ] >>= check { stdout: mempty, stderr: hasExpectedModules, result: Cmd.isFailure } Spec.describe "warning censoring and error-promotion" do let @@ -266,7 +267,7 @@ spec = Spec.describe "polyrepo" do shouldNotHaveWarning stdErr = do when (Array.any (\exp -> String.contains (Pattern exp) stdErr) paths) do Assert.fail $ "STDERR contained one or more texts:\n" <> show paths <> "\n\nStderr was:\n" <> stdErr - spago [ "build" ] >>= check { stdout: mempty, stderr: shouldNotHaveWarning, result: isRight } + spago [ "build" ] >>= check { stdout: mempty, stderr: shouldNotHaveWarning, result: Cmd.isSuccess } Spec.it "build fails when 'strict: true' and warnings were not censored" \{ spago } -> do writeWorkspaceOnlySpagoYamlFile @@ -283,7 +284,7 @@ spec = Spec.describe "polyrepo" do hasUnusedWarningError stdErr = do unless (Array.any (\exp -> String.contains (Pattern exp) stdErr) errs) do Assert.fail $ "STDERR did not contain texts:\n" <> show errs <> "\n\nStderr was:\n" <> stdErr - spago [ "build" ] >>= check { stdout: mempty, stderr: hasUnusedWarningError, result: isLeft } + spago [ "build" ] >>= check { stdout: mempty, stderr: hasUnusedWarningError, result: Cmd.isFailure } Spec.describe "passing --ensure-ranges flag..." do let @@ -326,7 +327,7 @@ spec = Spec.describe "polyrepo" do ] unless (String.contains (Pattern msg) stdErr) do Assert.fail $ "STDERR did not contain text:\n" <> msg <> "\n\nStderr was:\n" <> stdErr - spago [ "build", "--ensure-ranges" ] >>= check { stdout: mempty, stderr: hasNoRootPackageError, result: isLeft } + spago [ "build", "--ensure-ranges" ] >>= check { stdout: mempty, stderr: hasNoRootPackageError, result: Cmd.isFailure } Spec.describe "pedantic packages" do let @@ -420,7 +421,7 @@ spec = Spec.describe "polyrepo" do let unfoundTexts = Array.filter (\exp -> not $ String.contains (Pattern exp) stdErr) errs unless (Array.null unfoundTexts) do Assert.fail $ "STDERR did not contain expected texts:\n" <> (Array.intercalate "\n\n" unfoundTexts) <> "\n\nStderr was:\n" <> stdErr - spago [ "build" ] >>= check { stdout: mempty, stderr: hasExpectedErrors, result: isLeft } + spago [ "build" ] >>= check { stdout: mempty, stderr: hasExpectedErrors, result: Cmd.isFailure } Spec.it "passing --pedantic-packages overrides package and test configs" \{ spago } -> do writeWorkspaceOnlySpagoYamlFile @@ -438,4 +439,4 @@ spec = Spec.describe "polyrepo" do let unfoundTexts = Array.filter (\exp -> not $ String.contains (Pattern exp) stdErr) errs unless (Array.null unfoundTexts) do Assert.fail $ "STDERR did not contain expected texts:\n" <> (Array.intercalate "\n\n" unfoundTexts) <> "\n\nStderr was:\n" <> stdErr - spago [ "build", "--pedantic-packages" ] >>= check { stdout: mempty, stderr: hasExpectedErrors, result: isLeft } + spago [ "build", "--pedantic-packages" ] >>= check { stdout: mempty, stderr: hasExpectedErrors, result: Cmd.isFailure } diff --git a/test/Spago/Publish.purs b/test/Spago/Publish.purs index f5c47c4e8..0c59ec6ce 100644 --- a/test/Spago/Publish.purs +++ b/test/Spago/Publish.purs @@ -5,7 +5,6 @@ import Test.Prelude import Node.FS.Aff as FSA import Node.Platform as Platform import Node.Process as Process -import Spago.Cmd (StdinConfig(..)) import Spago.Cmd as Cmd import Spago.FS as FS import Test.Spec (Spec) @@ -64,6 +63,6 @@ doTheGitThing = do git [ "commit", "-m", "first" ] >>= shouldBeSuccess git [ "tag", "v0.0.1" ] >>= shouldBeSuccess where - git :: Array String -> Aff (Either ExecError ExecResult) + git :: Array String -> Aff ExecResult git args = Cmd.exec "git" args $ Cmd.defaultExecOptions { pipeStdout = false, pipeStderr = false, pipeStdin = StdinNewPipe } diff --git a/test/Spago/Registry.purs b/test/Spago/Registry.purs index 019750892..84c81fded 100644 --- a/test/Spago/Registry.purs +++ b/test/Spago/Registry.purs @@ -15,8 +15,8 @@ spec = Spec.around withTempDir do Spec.it "list package sets" \{ spago, fixture } -> do result <- spago [ "registry", "package-sets" ] let - result' = result # map \success@{ stdout } -> success - { stdout = stdout + result' = result + { stdout = result.stdout -- Take the oldest lines of output - the list of package sets will grow all the time # String.split (Pattern "\n") # Array.take 200 @@ -27,8 +27,8 @@ spec = Spec.around withTempDir do Spec.it "list only latest package sets for compiler" \{ spago, fixture } -> do result <- spago [ "registry", "package-sets", "--latest" ] let - result' = result # map \success@{ stdout } -> success - { stdout = stdout + result' = result + { stdout = result.stdout -- Take the oldest lines of output - the list of package sets will grow all the time # String.split (Pattern "\n") # Array.take 7 diff --git a/test/Spago/Test.purs b/test/Spago/Test.purs index 98f9ef312..75cb1adda 100644 --- a/test/Spago/Test.purs +++ b/test/Spago/Test.purs @@ -8,6 +8,7 @@ import Node.Path as Path import Node.Platform as Platform import Node.Process as Process import Registry.Version as Version +import Spago.Cmd as Cmd import Spago.Command.Init (DefaultConfigOptions(..)) import Spago.Command.Init as Init import Spago.Core.Config as Config @@ -78,7 +79,7 @@ spec = Spec.around withTempDir do } ) # plusDependencies [ "aff", "node-buffer", "node-fs" ] ) - spago [ "test", "-p", "subpackage" ] >>= checkOutputsStr { stdoutStr: Just fileContent, stderrStr: Nothing, result: isRight } + spago [ "test", "-p", "subpackage" ] >>= checkOutputsStr { stdoutStr: Just fileContent, stderrStr: Nothing, result: Cmd.isSuccess } Spec.it "fails when running tests from a sub-package, where the module does not exist" \{ spago } -> do spago [ "init" ] >>= shouldBeSuccess @@ -136,5 +137,5 @@ spec = Spec.around withTempDir do unless (String.contains (String.Pattern exp) stdErr) do Assert.fail $ "STDERR did not contain text:\n" <> exp <> "\n\nStderr was:\n" <> stdErr - spago [ "test" ] >>= check { stdout: mempty, stderr: hasUnusedNameWarningError, result: isRight } + spago [ "test" ] >>= check { stdout: mempty, stderr: hasUnusedNameWarningError, result: Cmd.isSuccess } From b71a7d25f6f52467579de3c811e1824b9b2b38e6 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 4 Dec 2023 10:10:49 -0600 Subject: [PATCH 02/21] Update thought2 fork of optparse --- spago.lock | 42 +++++++++++++++++++++++++++++++++++++----- spago.yaml | 36 +++++++++++++++++++++++++++++++++++- 2 files changed, 72 insertions(+), 6 deletions(-) diff --git a/spago.lock b/spago.lock index 709d46b26..0a5cb5703 100644 --- a/spago.lock +++ b/spago.lock @@ -352,7 +352,40 @@ workspace: - tuples git: https://github.com/natefaubion/purescript-node-glob-basic.git ref: v1.2.2 - optparse: 5.0.0 + optparse: + dependencies: + - aff + - arrays + - bifunctors + - console + - control + - effect + - either + - enums + - exists + - exitcodes + - foldable-traversable + - free + - gen + - integers + - lazy + - lists + - maybe + - newtype + - node-buffer + - node-process + - node-streams + - nonempty + - numbers + - open-memoize + - partial + - prelude + - strings + - tailrec + - transformers + - tuples + git: https://github.com/thought2/purescript-optparse.git + ref: a9b227110c34ae4f8c1b2fcb07de6f1327ce5826 ordered-collections: 3.1.1 registry-foreign: git: https://github.com/purescript/registry-dev.git @@ -1581,9 +1614,9 @@ packages: - maybe - tuples optparse: - type: registry - version: 5.0.0 - integrity: sha256-Y1xqUrnOB5934wKssPyWVdF4kqA6ITXwSasdEOkxZT8= + type: git + url: https://github.com/thought2/purescript-optparse.git + rev: a9b227110c34ae4f8c1b2fcb07de6f1327ce5826 dependencies: - aff - arrays @@ -1611,7 +1644,6 @@ packages: - open-memoize - partial - prelude - - quickcheck - strings - tailrec - transformers diff --git a/spago.yaml b/spago.yaml index 7fbcdf80c..cb43a90c7 100644 --- a/spago.yaml +++ b/spago.yaml @@ -295,4 +295,38 @@ workspace: - safe-coerce - strings - tuples - optparse: 5.0.0 + optparse: + git: "https://github.com/thought2/purescript-optparse.git" + ref: "a9b227110c34ae4f8c1b2fcb07de6f1327ce5826" + dependencies: + - aff + - arrays + - bifunctors + - console + - control + - effect + - either + - enums + - exists + - exitcodes + - foldable-traversable + - free + - gen + - integers + - lazy + - lists + - maybe + - newtype + - node-buffer + - node-process + - node-streams + - nonempty + - numbers + - open-memoize + - partial + - prelude + - strings + - tailrec + - transformers + - tuples + From 7a103d0dc6c25980186dc01ea1faab243412845a Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 4 Dec 2023 10:18:43 -0600 Subject: [PATCH 03/21] Update latest test to use newer execa handling --- test/Spago/Build/BuildInfo.purs | 13 +++++++------ test/Spago/Run.purs | 1 - 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/test/Spago/Build/BuildInfo.purs b/test/Spago/Build/BuildInfo.purs index db55f52c9..951cbbccd 100644 --- a/test/Spago/Build/BuildInfo.purs +++ b/test/Spago/Build/BuildInfo.purs @@ -8,6 +8,7 @@ import Data.DateTime.Instant as Instant import Effect.Exception as Exception import Node.Path as Path import Registry.Version as Version +import Spago.Cmd as Cmd import Spago.Command.Init (DefaultConfigOptions(..)) import Spago.Command.Init as Init import Spago.Core.Config as Config @@ -26,9 +27,9 @@ spec = let logOptions = { logOptions: { color: false, verbosity: LogQuiet, startingTime: Instant.fromDateTime bottom } } purs <- runSpago logOptions getPurs spagoResult <- spago [ "--version" ] - sVersion <- case spagoResult of - Left e -> MonadError.throwError $ Exception.error e.message - Right a -> pure a.stderr + sVersion <- case Cmd.isSuccess spagoResult of + false -> MonadError.throwError $ Exception.error spagoResult.message + true -> pure spagoResult.stderr pure $ Array.intercalate "\n" $ @@ -86,7 +87,7 @@ spec = Spec.it ("'spago " <> Array.intercalate " " command <> " works") \{ spago } -> do setupSinglePackage spago expected <- mkExpectedStdout { spago, rest: [ "foo: 0.0.0" ] } - spago command >>= checkOutputsStr { stderrStr: Nothing, stdoutStr: Just expected, result: isRight } + spago command >>= checkOutputsStr { stderrStr: Nothing, stdoutStr: Just expected, result: Cmd.isSuccess } Spec.describe "using generated 'BuildInfo.purs' file in multi-package context" do @@ -133,9 +134,9 @@ spec = Spec.it ("'spago run -p " <> package <> " --main " <> srcMain <> "' works") \{ spago } -> do expected <- mkExpectedStdout { spago, rest: packagesWithVersion } - spago [ "run", "-p", package, "--main", srcMain ] >>= checkOutputsStr { stderrStr: Nothing, stdoutStr: Just expected, result: isRight } + spago [ "run", "-p", package, "--main", srcMain ] >>= checkOutputsStr { stderrStr: Nothing, stdoutStr: Just expected, result: Cmd.isSuccess } Spec.it ("'spago test -p " <> package <> "' works") \{ spago } -> do expected <- mkExpectedStdout { spago, rest: packagesWithVersion } - spago [ "test", "-p", package ] >>= checkOutputsStr { stderrStr: Nothing, stdoutStr: Just expected, result: isRight } + spago [ "test", "-p", package ] >>= checkOutputsStr { stderrStr: Nothing, stdoutStr: Just expected, result: Cmd.isSuccess } diff --git a/test/Spago/Run.purs b/test/Spago/Run.purs index e991929a0..6c86a4381 100644 --- a/test/Spago/Run.purs +++ b/test/Spago/Run.purs @@ -2,7 +2,6 @@ module Test.Spago.Run where import Test.Prelude -import Spago.Cmd (StdinConfig(..)) import Spago.FS as FS import Test.Spec (Spec) import Test.Spec as Spec From 2e213e79bc65310c30f395d5abd4f41e8aa9ef4d Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 4 Dec 2023 10:19:11 -0600 Subject: [PATCH 04/21] Fix import warning --- test/Spago/Build/Pedantic.purs | 1 - 1 file changed, 1 deletion(-) diff --git a/test/Spago/Build/Pedantic.purs b/test/Spago/Build/Pedantic.purs index c8d89fc62..cb4137740 100644 --- a/test/Spago/Build/Pedantic.purs +++ b/test/Spago/Build/Pedantic.purs @@ -5,7 +5,6 @@ import Test.Prelude import Data.Array as Array import Data.Map as Map import Node.Path as Path -import Spago.Cmd (ExecResult) import Spago.Core.Config (Dependencies(..), Config) import Spago.FS as FS import Test.Spec (SpecT) From 46c45bd29053a74965f2dd992781344b59a3d0a2 Mon Sep 17 00:00:00 2001 From: Fabrizio Ferrai Date: Mon, 4 Dec 2023 19:16:13 +0200 Subject: [PATCH 05/21] Try using powershell in windows ci --- .github/workflows/build.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 137dabf73..189a93bfe 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -78,8 +78,14 @@ jobs: - name: Bundle docs-search client run: node ./bin/bundle.js bundle -p docs-search-client-halogen - - name: Run tests - run: node ./bin/bundle.js test + - name: Run tests (windows) + if: matrix.os == 'windows-latest' + shell: pwsh + run: node bin/bundle.js test + + - name: Run tests (linux and macos) + if: matrix.os != 'windows-latest' + run: node ./bin/index.dev.js test - name: Check formatting (Linux only) if: matrix.os == 'ubuntu-latest' From 44172b3e22efaaf914c77a131930033f7ded0e24 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 4 Dec 2023 11:34:46 -0600 Subject: [PATCH 06/21] Add verbose flag --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 189a93bfe..b08b136cf 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -81,7 +81,7 @@ jobs: - name: Run tests (windows) if: matrix.os == 'windows-latest' shell: pwsh - run: node bin/bundle.js test + run: node bin/bundle.js test --verbose - name: Run tests (linux and macos) if: matrix.os != 'windows-latest' From a6cdd899e612324a0879e8dcfccbc4645c2d290b Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 4 Dec 2023 14:32:12 -0600 Subject: [PATCH 07/21] Check chars --- .github/workflows/build.yml | 5 +++++ check-chars.mjs | 27 +++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 check-chars.mjs diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b08b136cf..3c7dc0984 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -40,6 +40,11 @@ jobs: with: node-version: 18 + - name: How many args on Windows? + if: matrix.os == 'windows-latest' + run: | + node check-chars.mjs + - name: Cache NPM dependencies uses: actions/cache@v2 env: diff --git a/check-chars.mjs b/check-chars.mjs new file mode 100644 index 000000000..e096fe55e --- /dev/null +++ b/check-chars.mjs @@ -0,0 +1,27 @@ +import cp from "node:child_process"; + +const echo = "echo"; +const space = " "; +const maxCharLimit = 8191 - echo.length - space.length - 1 +let initialArgs = ""; +for (let index = 0; index < maxCharLimit; index++) { + initialArgs = initialArgs + "0"; +} + +const go = (args) => { + console.log(`Attempting to spawn 'echo X' where 'X' is ${args.length} chars`); + const result = cp.spawn(echo, [ args ], { stdio: [null, null, null]}); + result.on("close", (code, sig) => { + if (code === 1 || sig) { + go(args.slice(0, -1)); + } else if (code === 0) { + console.log(`Successfully spawned with ${args.length} chars`); + } else { + console.log("Something else happened."); + console.log(exit); + console.log(sig); + } + }); +}; + +go(initialArgs); From 2c643053c0bf19ab586367c22cd2c73553f6f3a6 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 4 Dec 2023 14:35:41 -0600 Subject: [PATCH 08/21] Sanity check parameters --- check-chars.mjs | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/check-chars.mjs b/check-chars.mjs index e096fe55e..1680b5392 100644 --- a/check-chars.mjs +++ b/check-chars.mjs @@ -1,14 +1,15 @@ import cp from "node:child_process"; const echo = "echo"; -const space = " "; -const maxCharLimit = 8191 - echo.length - space.length - 1 +const maxCharLimit = 8191 let initialArgs = ""; +let initialParams = []; for (let index = 0; index < maxCharLimit; index++) { initialArgs = initialArgs + "0"; + initialParams.push("0"); } -const go = (args) => { +const checkCharCount = (args) => { console.log(`Attempting to spawn 'echo X' where 'X' is ${args.length} chars`); const result = cp.spawn(echo, [ args ], { stdio: [null, null, null]}); result.on("close", (code, sig) => { @@ -24,4 +25,24 @@ const go = (args) => { }); }; -go(initialArgs); +checkCharCount(initialArgs); + + +const checkParamCount = (params) => { + console.log(`Attempting to spawn 'echo X...' where 'X' is ${params.length} parameters`); + const result = cp.spawn(echo, params, { stdio: [null, null, null]}); + result.on("close", (code, sig) => { + if (code === 1 || sig) { + go(params.slice(0, -1)); + } else if (code === 0) { + console.log(`Successfully spawned with ${params.length} parameters`); + } else { + console.log("Something else happened."); + console.log(exit); + console.log(sig); + } + }); +}; + +checkParamCount(initialParams); + From 38b6cde7756caa17c5e0a077956184bad4d10d12 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Tue, 26 Dec 2023 17:07:12 -0800 Subject: [PATCH 09/21] Merge remote-tracking branch 'origin/master' into jam/update-node-deps --- bin/spago.yaml | 8 +- bin/src/Flags.purs | 7 + bin/src/Main.purs | 171 +-- core/spago.yaml | 2 + core/src/Config.purs | 6 +- core/src/Prelude.purs | 5 +- docs-search/client-halogen/spago.yaml | 2 + .../src/Docs/Search/App/SearchField.purs | 4 +- .../src/Docs/Search/App/SearchResults.purs | 26 +- .../src/Docs/Search/App/Sidebar.purs | 4 +- docs-search/common/spago.yaml | 5 + .../common/src/Docs/Search/Config.purs | 4 +- .../common/src/Docs/Search/Declarations.purs | 10 +- .../common/src/Docs/Search/Engine.purs | 7 +- .../common/src/Docs/Search/JsonCodec.purs | 13 +- docs-search/common/src/Docs/Search/Meta.purs | 11 +- docs-search/common/src/Docs/Search/Score.purs | 6 +- .../common/src/Docs/Search/SearchResult.purs | 21 +- .../common/src/Docs/Search/TypeDecoder.purs | 18 +- .../common/src/Docs/Search/TypeQuery.purs | 32 +- .../common/src/Docs/Search/TypeShape.purs | 13 +- docs-search/common/src/Docs/Search/Types.purs | 14 +- docs-search/index/spago.yaml | 2 + .../index/src/Docs/Search/ModuleParser.purs | 4 +- flake.lock | 35 +- package-lock.json | 4 +- package.json | 2 +- spago.lock | 1059 ++++++++++++++++- spago.yaml | 18 +- src/Spago/Command/Build.purs | 2 +- src/Spago/Command/Docs.purs | 5 +- src/Spago/Command/Fetch.purs | 507 ++++---- src/Spago/Command/Init.purs | 3 +- src/Spago/Command/Ls.purs | 10 +- src/Spago/Command/Publish.purs | 73 +- src/Spago/Command/Registry.purs | 18 +- src/Spago/Command/Repl.purs | 6 +- src/Spago/Command/Script.purs | 2 - src/Spago/Command/Sources.purs | 8 +- src/Spago/Command/Uninstall.purs | 183 +-- src/Spago/Config.js | 8 +- src/Spago/Config.purs | 231 ++-- src/Spago/Db.purs | 9 + src/Spago/Git.purs | 13 +- src/Spago/Lock.purs | 52 +- src/Spago/Purs.purs | 1 - src/Spago/Registry.purs | 259 +++- src/Spago/Repl.purs | 14 +- test-fixtures/alternate-backend-output.txt | 1 - test-fixtures/circular-dependencies.txt | 1 - test-fixtures/codegen-opt.txt | 1 - test-fixtures/list-packages-registry.txt | 2 + test-fixtures/missing-dependencies.txt | 1 - test-fixtures/offline.txt | 1 - ...rect-import-transitive-dependency-both.txt | 3 +- ...rect-import-transitive-dependency-test.txt | 3 +- ...ck-direct-import-transitive-dependency.txt | 3 +- .../pedantic/check-pedantic-packages.txt | 3 +- .../check-unused-dependency-in-source.txt | 3 +- .../pedantic/check-unused-dependency.txt | 3 +- ...heck-unused-source-and-test-dependency.txt | 3 +- .../pedantic/check-unused-test-dependency.txt | 3 +- .../pedantic-instructions-initial-failure.txt | 3 +- ...antic-instructions-installation-result.txt | 7 +- test-fixtures/polyrepo.lock | 427 +++++++ test-fixtures/publish-main-win.txt | 1 - test-fixtures/publish-main.txt | 3 +- test-fixtures/publish-no-bounds.txt | 3 +- test-fixtures/publish-no-config.txt | 5 +- test-fixtures/publish-no-git.txt | 3 +- test-fixtures/publish.txt | 5 +- .../spago-install-existing-dep-stderr.txt | 2 - test-fixtures/spago-with-hash.yaml | 14 - test-fixtures/spago-with-maybe.lock | 562 +++++++++ test-fixtures/spago.lock | 514 ++++++++ test-fixtures/test-missing-module.txt | 1 - test-fixtures/test-output-stderr.txt | 1 - .../uninstall-deps-undeclared-src-deps.txt | 7 +- .../uninstall-deps-undeclared-test-deps.txt | 7 +- .../uninstall-no-package-selection.txt | 1 - test-fixtures/uninstall-no-test-config.txt | 1 - test-fixtures/uninstall-remove-src-deps.txt | 6 +- test-fixtures/uninstall-remove-test-deps.txt | 6 +- test/Prelude.purs | 4 +- test/Spago/Build.purs | 33 +- test/Spago/Build/Polyrepo.purs | 3 +- test/Spago/Install.purs | 40 +- test/Spago/Lock.purs | 71 +- test/Spago/Publish.purs | 2 +- 89 files changed, 3720 insertions(+), 960 deletions(-) create mode 100644 test-fixtures/polyrepo.lock delete mode 100644 test-fixtures/spago-with-hash.yaml create mode 100644 test-fixtures/spago-with-maybe.lock create mode 100644 test-fixtures/spago.lock diff --git a/bin/spago.yaml b/bin/spago.yaml index 287b882f7..15b611e0d 100644 --- a/bin/spago.yaml +++ b/bin/spago.yaml @@ -1,11 +1,14 @@ package: name: spago-bin publish: - version: 0.93.19 + version: 0.93.22 license: BSD-3-Clause + build: + strict: true + censor_project_warnings: + - WildcardInferredType dependencies: - aff - - optparse - arrays - codec-argonaut - console @@ -14,6 +17,7 @@ package: - node-fs - node-path - node-process + - optparse - ordered-collections - record - refs diff --git a/bin/src/Flags.purs b/bin/src/Flags.purs index 077f77006..1fad6f760 100644 --- a/bin/src/Flags.purs +++ b/bin/src/Flags.purs @@ -164,6 +164,13 @@ transitive = <> O.help "Include transitive dependencies" ) +pure :: Parser Boolean +pure = + O.switch + ( O.long "pure" + <> O.help "Use the package information from the current lockfile, even if it is out of date" + ) + pedanticPackages :: Parser Boolean pedanticPackages = O.switch diff --git a/bin/src/Main.purs b/bin/src/Main.purs index dcefd18f7..be4989e3d 100644 --- a/bin/src/Main.purs +++ b/bin/src/Main.purs @@ -10,11 +10,11 @@ import Data.Array.NonEmpty as NonEmptyArray import Data.Codec.Argonaut.Common as CA.Common import Data.Foldable as Foldable import Data.List as List -import Data.Map as Map 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 @@ -22,16 +22,11 @@ import Options.Applicative (CommandFields, Mod, Parser, ParserPrefs(..)) import Options.Applicative as O import Optparse as Optparse import Record as Record -import Registry.Constants as Registry.Constants -import Registry.ManifestIndex as ManifestIndex -import Registry.Metadata as Metadata import Registry.PackageName as PackageName -import Registry.Version as Version import Spago.Bin.Flags as Flags import Spago.Command.Build as Build import Spago.Command.Bundle as Bundle import Spago.Command.Docs as Docs -import Spago.Command.Uninstall as Uninstall import Spago.Command.Fetch as Fetch import Spago.Command.Graph (GraphModulesArgs, GraphPackagesArgs) import Spago.Command.Graph as Graph @@ -45,6 +40,7 @@ import Spago.Command.Repl as Repl import Spago.Command.Run as Run import Spago.Command.Sources as Sources import Spago.Command.Test as Test +import Spago.Command.Uninstall as Uninstall import Spago.Command.Upgrade as Upgrade import Spago.Config (BundleConfig, BundlePlatform(..), BundleType(..), PackageMap, RunConfig, TestConfig) import Spago.Config as Config @@ -75,12 +71,16 @@ type InitArgs = , useSolver :: Boolean } -type FetchArgs = - { packages :: List String +type FetchArgsRow a = + ( packages :: List String , selectedPackage :: Maybe String , ensureRanges :: Boolean , testDeps :: Boolean - } + , pure :: Boolean + | a + ) + +type FetchArgs a = Record (FetchArgsRow a) type InstallArgs = { packages :: List String @@ -91,6 +91,7 @@ type InstallArgs = , pedanticPackages :: Boolean , ensureRanges :: Boolean , testDeps :: Boolean + , pure :: Boolean } type UninstallArgs = @@ -109,6 +110,7 @@ type BuildArgs a = , jsonErrors :: Boolean , strict :: Maybe Boolean , statVerbosity :: Maybe Core.StatVerbosity + , pure :: Boolean | a } @@ -136,6 +138,7 @@ type RunArgs = , ensureRanges :: Boolean , strict :: Maybe Boolean , statVerbosity :: Maybe Core.StatVerbosity + , pure :: Boolean } type TestArgs = @@ -147,6 +150,7 @@ type TestArgs = , execArgs :: Maybe (Array String) , strict :: Maybe Boolean , statVerbosity :: Maybe Core.StatVerbosity + , pure :: Boolean } type SourcesArgs = @@ -170,6 +174,7 @@ type BundleArgs = , ensureRanges :: Boolean , strict :: Maybe Boolean , statVerbosity :: Maybe Core.StatVerbosity + , pure :: Boolean } type PublishArgs = @@ -184,7 +189,7 @@ data Command a = Build (BuildArgs a) | Bundle BundleArgs | Docs DocsArgs - | Fetch FetchArgs + | Fetch (FetchArgs a) | Init InitArgs | Install InstallArgs | Uninstall UninstallArgs @@ -287,13 +292,14 @@ initArgsParser = , useSolver: Flags.useSolver } -fetchArgsParser :: Parser FetchArgs +fetchArgsParser :: Parser (FetchArgs ()) fetchArgsParser = Optparse.fromRecord { packages: Flags.packages , selectedPackage: Flags.selectedPackage , ensureRanges: Flags.ensureRanges , testDeps: Flags.testDeps + , pure: Flags.pure } sourcesArgsParser :: Parser SourcesArgs @@ -314,6 +320,7 @@ installArgsParser = , pedanticPackages: Flags.pedanticPackages , ensureRanges: Flags.ensureRanges , testDeps: Flags.testDeps + , pure: Flags.pure } uninstallArgsParser :: Parser UninstallArgs @@ -335,6 +342,7 @@ buildArgsParser = Optparse.fromRecord , jsonErrors: Flags.jsonErrors , strict: Flags.strict , statVerbosity: Flags.statVerbosity + , pure: Flags.pure } replArgsParser :: Parser ReplArgs @@ -356,6 +364,7 @@ runArgsParser = Optparse.fromRecord , ensureRanges: Flags.ensureRanges , strict: Flags.strict , statVerbosity: Flags.statVerbosity + , pure: Flags.pure } testArgsParser :: Parser TestArgs @@ -368,6 +377,7 @@ testArgsParser = Optparse.fromRecord , pedanticPackages: Flags.pedanticPackages , strict: Flags.strict , statVerbosity: Flags.statVerbosity + , pure: Flags.pure } bundleArgsParser :: Parser BundleArgs @@ -388,6 +398,7 @@ bundleArgsParser = , ensureRanges: Flags.ensureRanges , strict: Flags.strict , statVerbosity: Flags.statVerbosity + , pure: Flags.pure } publishArgsParser :: Parser PublishArgs @@ -463,6 +474,7 @@ lsPathsArgsParser = Optparse.fromRecord lsPackagesArgsParser :: Parser LsPackagesArgs lsPackagesArgsParser = Optparse.fromRecord { json: Flags.json + , pure: Flags.pure } lsDepsArgsParser :: Parser LsDepsArgs @@ -470,6 +482,7 @@ lsDepsArgsParser = Optparse.fromRecord { json: Flags.json , transitive: Flags.transitive , selectedPackage: Flags.selectedPackage + , pure: Flags.pure } data Cmd a = Cmd'SpagoCmd (SpagoCmd a) | Cmd'VersionCmd Boolean @@ -487,7 +500,10 @@ parseArgs = do ( O.info ( O.helper <*> ( (Cmd'SpagoCmd <$> argParser) <|> - (Cmd'VersionCmd <$> (O.switch (O.long "version" <> O.short 'v' <> O.help "Show the current version"))) + ( Cmd'VersionCmd <$> + ( O.flag' true (O.long "version" <> O.short 'v' <> O.help "Show the current version") + ) + ) ) ) (O.progDesc "PureScript package manager and build tool") @@ -508,6 +524,8 @@ main = do , selectedPackage: args.selectedPackage , ensureRanges: false , testDeps: false + , isRepl: false + , pure: false } void $ runSpago env (Sources.run { json: args.json }) Init args@{ useSolver } -> do @@ -528,7 +546,7 @@ main = do logInfo "Set up a new Spago project." logInfo "Try running `spago run`" Fetch args -> do - { env, fetchOpts } <- mkFetchEnv offline args + { env, fetchOpts } <- mkFetchEnv offline (Record.merge { isRepl: false } args) void $ runSpago env (Fetch.run fetchOpts) RegistrySearch args -> do env <- mkRegistryEnv offline @@ -539,8 +557,8 @@ main = do RegistryPackageSets args -> do env <- mkRegistryEnv offline void $ runSpago env (RegistryCmd.packageSets args) - Install args@{ packages, selectedPackage, ensureRanges, testDeps } -> do - { env, fetchOpts } <- mkFetchEnv offline { packages, selectedPackage, ensureRanges, testDeps } + Install args -> do + { env, fetchOpts } <- mkFetchEnv offline (Record.merge args { isRepl: false }) dependencies <- runSpago env (Fetch.run fetchOpts) let buildArgs = Record.merge @@ -552,17 +570,17 @@ main = do let options = { depsOnly: true, pursArgs: List.toUnfoldable args.pursArgs, jsonErrors: false } runSpago env' (Build.run options) Uninstall { packagesToRemove, selectedPackage, testDeps } -> do - { env, fetchOpts } <- mkFetchEnv offline { packages: packagesToRemove, selectedPackage, ensureRanges: false, testDeps: false } + { env, fetchOpts } <- mkFetchEnv offline { packages: packagesToRemove, selectedPackage, ensureRanges: false, testDeps: false, isRepl: false, pure: false } let options = { testDeps, dependenciesToRemove: Set.fromFoldable fetchOpts.packages } - runSpago { workspace: env.workspace, logOptions: env.logOptions } (Uninstall.run options) - Build args@{ selectedPackage, ensureRanges, jsonErrors } -> do - { env, fetchOpts } <- mkFetchEnv offline { packages: mempty, selectedPackage, ensureRanges, testDeps: false } + runSpago env (Uninstall.run options) + Build args@{ selectedPackage, ensureRanges, jsonErrors, pure } -> do + { env, fetchOpts } <- mkFetchEnv offline { packages: mempty, selectedPackage, ensureRanges, pure, testDeps: false, isRepl: false } dependencies <- runSpago env (Fetch.run fetchOpts) buildEnv <- runSpago env (mkBuildEnv args dependencies) let options = { depsOnly: false, pursArgs: List.toUnfoldable args.pursArgs, jsonErrors } runSpago buildEnv (Build.run options) Publish { selectedPackage } -> do - { env, fetchOpts } <- mkFetchEnv offline { packages: mempty, selectedPackage, ensureRanges: false, testDeps: false } + { env, fetchOpts } <- mkFetchEnv offline { packages: mempty, selectedPackage, ensureRanges: false, testDeps: false, isRepl: false, pure: false } dependencies <- runSpago env (Fetch.run fetchOpts) publishEnv <- runSpago env (mkPublishEnv dependencies) void $ runSpago publishEnv (Publish.publish {}) @@ -592,30 +610,32 @@ main = do , selectedPackage , ensureRanges: false , testDeps: false + , isRepl: true + , pure: false } dependencies <- runSpago env (Fetch.run fetchOpts) supportPackages <- runSpago env (SpagoRepl.supportPackage env.workspace.packageSet) replEnv <- runSpago env (mkReplEnv args dependencies supportPackages) void $ runSpago replEnv Repl.run - Bundle args@{ selectedPackage, ensureRanges } -> do - { env, fetchOpts } <- mkFetchEnv offline { packages: mempty, selectedPackage, ensureRanges, testDeps: false } + Bundle args@{ selectedPackage, ensureRanges, pure } -> do + { env, fetchOpts } <- mkFetchEnv offline { packages: mempty, selectedPackage, ensureRanges, pure, testDeps: false, isRepl: false } dependencies <- runSpago env (Fetch.run fetchOpts) buildEnv <- runSpago env (mkBuildEnv args dependencies) let options = { depsOnly: false, pursArgs: List.toUnfoldable args.pursArgs, jsonErrors: false } runSpago buildEnv (Build.run options) bundleEnv <- runSpago env (mkBundleEnv args) runSpago bundleEnv Bundle.run - Run args@{ selectedPackage, ensureRanges } -> do - { env, fetchOpts } <- mkFetchEnv offline { packages: mempty, selectedPackage, ensureRanges, testDeps: false } + Run args@{ selectedPackage, ensureRanges, pure } -> do + { env, fetchOpts } <- mkFetchEnv offline { packages: mempty, selectedPackage, ensureRanges, pure, testDeps: false, isRepl: false } dependencies <- runSpago env (Fetch.run fetchOpts) buildEnv <- runSpago env (mkBuildEnv args dependencies) let options = { depsOnly: false, pursArgs: List.toUnfoldable args.pursArgs, jsonErrors: false } runSpago buildEnv (Build.run options) runEnv <- runSpago env (mkRunEnv args buildEnv) runSpago runEnv Run.run - Test args@{ selectedPackage } -> do - { env, fetchOpts } <- mkFetchEnv offline { packages: mempty, selectedPackage, ensureRanges: false, testDeps: false } + Test args@{ selectedPackage, pure } -> do + { env, fetchOpts } <- mkFetchEnv offline { packages: mempty, selectedPackage, pure, ensureRanges: false, testDeps: false, isRepl: false } dependencies <- runSpago env (Fetch.run fetchOpts) buildEnv <- runSpago env (mkBuildEnv (Record.union args { ensureRanges: false }) dependencies) let options = { depsOnly: false, pursArgs: List.toUnfoldable args.pursArgs, jsonErrors: false } @@ -624,34 +644,34 @@ main = do runSpago testEnv Test.run LsPaths args -> do runSpago { logOptions } $ Ls.listPaths args - LsPackages args -> do - let fetchArgs = { packages: mempty, selectedPackage: Nothing, ensureRanges: false, testDeps: false } + LsPackages args@{ pure } -> do + let fetchArgs = { packages: mempty, selectedPackage: Nothing, pure, ensureRanges: false, testDeps: false, isRepl: false } { env: env@{ workspace }, fetchOpts } <- mkFetchEnv offline fetchArgs dependencies <- runSpago env (Fetch.run fetchOpts) let lsEnv = { workspace, dependencies, logOptions } runSpago lsEnv (Ls.listPackageSet args) - LsDeps { selectedPackage, json, transitive } -> do - let fetchArgs = { packages: mempty, selectedPackage, ensureRanges: false, testDeps: false } + LsDeps { selectedPackage, json, transitive, pure } -> do + let fetchArgs = { packages: mempty, selectedPackage, pure, ensureRanges: false, testDeps: false, isRepl: false } { env, fetchOpts } <- mkFetchEnv offline fetchArgs dependencies <- runSpago env (Fetch.run fetchOpts) lsEnv <- runSpago env (mkLsEnv dependencies) runSpago lsEnv (Ls.listPackages { json, transitive }) Docs args -> do - { env, fetchOpts } <- mkFetchEnv offline { packages: mempty, selectedPackage: Nothing, ensureRanges: false, testDeps: true } + { env, fetchOpts } <- mkFetchEnv offline { packages: mempty, pure: false, selectedPackage: Nothing, ensureRanges: false, testDeps: true, isRepl: false } dependencies <- runSpago env (Fetch.run fetchOpts) docsEnv <- runSpago env (mkDocsEnv args dependencies) runSpago docsEnv Docs.run Upgrade _args -> do - { env } <- mkFetchEnv offline { packages: mempty, selectedPackage: Nothing, ensureRanges: false, testDeps: false } + { env } <- mkFetchEnv offline { packages: mempty, selectedPackage: Nothing, pure: false, ensureRanges: false, testDeps: false, isRepl: false } runSpago env Upgrade.run -- TODO: add selected to graph commands GraphModules args -> do - { env, fetchOpts } <- mkFetchEnv offline { packages: mempty, selectedPackage: Nothing, ensureRanges: false, testDeps: false } + { env, fetchOpts } <- mkFetchEnv offline { packages: mempty, selectedPackage: Nothing, pure: false, ensureRanges: false, testDeps: false, isRepl: false } dependencies <- runSpago env (Fetch.run fetchOpts) purs <- Purs.getPurs runSpago { dependencies, logOptions, purs, workspace: env.workspace } (Graph.graphModules args) GraphPackages args -> do - { env, fetchOpts } <- mkFetchEnv offline { packages: mempty, selectedPackage: Nothing, ensureRanges: false, testDeps: false } + { env, fetchOpts } <- mkFetchEnv offline { packages: mempty, selectedPackage: Nothing, pure: false, ensureRanges: false, testDeps: false, isRepl: false } dependencies <- runSpago env (Fetch.run fetchOpts) purs <- Purs.getPurs runSpago { dependencies, logOptions, purs, workspace: env.workspace } (Graph.graphPackages args) @@ -891,7 +911,7 @@ mkReplEnv replArgs dependencies supportPackage = do , selected } -mkFetchEnv :: forall a. OnlineStatus -> FetchArgs -> Spago (LogEnv a) { env :: Fetch.FetchEnv (), fetchOpts :: Fetch.FetchOpts } +mkFetchEnv :: forall a b. OnlineStatus -> { isRepl :: Boolean | FetchArgsRow b } -> Spago (LogEnv a) { env :: Fetch.FetchEnv (), fetchOpts :: Fetch.FetchOpts } mkFetchEnv offline args = do let parsePackageName p = case PackageName.parse p of @@ -906,8 +926,8 @@ mkFetchEnv offline args = do Left _err -> die $ "Failed to parse selected package name, was: " <> show args.selectedPackage env <- mkRegistryEnv offline - workspace <- runSpago env (Config.readWorkspace maybeSelectedPackage) - let fetchOpts = { packages: packageNames, ensureRanges: args.ensureRanges, isTest: args.testDeps } + workspace <- runSpago env (Config.readWorkspace { maybeSelectedPackage, pureBuild: args.pure }) + let fetchOpts = { packages: packageNames, ensureRanges: args.ensureRanges, isTest: args.testDeps, isRepl: args.isRepl } pure { fetchOpts, env: Record.union { workspace } env } mkRegistryEnv :: forall a. OnlineStatus -> Spago (LogEnv a) (Registry.RegistryEnv ()) @@ -925,84 +945,15 @@ mkRegistryEnv offline = do git <- Git.getGit purs <- Purs.getPurs { logOptions } <- ask - - -- Connect to the database - we need it to keep track of when to pull the Registry, - -- so we don't do it too often db <- liftEffect $ Db.connect { database: Paths.databasePath , logger: \str -> Reader.runReaderT (logDebug $ "DB: " <> str) { logOptions } } - - -- we keep track of how old the latest pull was - if the last pull was recent enough - -- we just move on, otherwise run the fibers - fetchingFreshRegistry <- Registry.shouldFetchRegistryRepos db - when fetchingFreshRegistry do - -- clone the registry and index repo, or update them - logInfo "Refreshing the Registry Index..." - runSpago { logOptions, git, offline } $ parallelise - [ Git.fetchRepo { git: "https://github.com/purescript/registry-index.git", ref: "main" } Paths.registryIndexPath >>= case _ of - Right _ -> pure unit - Left _err -> logWarn "Couldn't refresh the registry-index, will proceed anyways" - , Git.fetchRepo { git: "https://github.com/purescript/registry.git", ref: "main" } Paths.registryPath >>= case _ of - Right _ -> pure unit - Left _err -> logWarn "Couldn't refresh the registry, will proceed anyways" - ] - - -- Now that we are up to date with the Registry we init/refresh the database - Registry.updatePackageSetsDb db - - -- Prepare the functions to read the manifests and metadata - here we memoize as much - -- as we can in the DB, so we don't have to read the files every time - let - -- Manifests are immutable so we can just lookup in the DB or read from file if not there - getManifestFromIndex :: PackageName -> Version -> Spago (LogEnv ()) (Maybe Manifest) - getManifestFromIndex name version = do - liftEffect (Db.getManifest db name version) >>= case _ of - Just manifest -> pure (Just manifest) - Nothing -> do - -- if we don't have it we need to read it from file - -- (note that we have all the versions of a package in the same file) - logDebug $ "Reading package from Index: " <> PackageName.print name - maybeManifests <- liftAff $ ManifestIndex.readEntryFile Paths.registryIndexPath name - manifests <- map (map (\m@(Manifest m') -> Tuple m'.version m)) case maybeManifests of - Right ms -> pure $ NonEmptyArray.toUnfoldable ms - Left err -> do - logWarn $ "Could not read package manifests from index, proceeding anyways. Error: " <> err - pure [] - let versions = Map.fromFoldable manifests - -- and memoize it - for_ manifests \(Tuple _ manifest@(Manifest m)) -> do - logDebug $ "Inserting manifest in DB: " <> PackageName.print name <> " v" <> Version.print m.version - liftEffect $ Db.insertManifest db name m.version manifest - pure (Map.lookup version versions) - - -- Metadata can change over time (unpublished packages, and new packages), so we need - -- to read it from file every time we have a fresh Registry - let - metadataFromFile name = do - let metadataFilePath = Path.concat [ Paths.registryPath, Registry.Constants.metadataDirectory, PackageName.print name <> ".json" ] - logDebug $ "Reading metadata from file: " <> metadataFilePath - liftAff (FS.readJsonFile Metadata.codec metadataFilePath) - - getMetadata :: PackageName -> Spago (LogEnv ()) (Either String Metadata) - getMetadata name = do - -- we first try reading it from the DB - liftEffect (Db.getMetadata db name) >>= case _ of - Just metadata | not fetchingFreshRegistry -> do - logDebug $ "Got metadata from DB: " <> PackageName.print name - pure (Right metadata) - _ -> do - -- if we don't have it we try reading it from file - metadataFromFile name >>= case _ of - Left e -> pure (Left e) - Right m -> do - -- and memoize it - liftEffect (Db.insertMetadata db name m) - pure (Right m) + registryBox <- liftAff $ AVar.empty + registryLock <- liftAff $ AVar.new unit pure - { getManifestFromIndex - , getMetadata + { getRegistry: Registry.getRegistryFns registryBox registryLock , logOptions , offline , purs @@ -1030,7 +981,7 @@ mkLsEnv dependencies = do ] pure { logOptions, workspace, dependencies, selected } -mkDocsEnv :: forall a. DocsArgs -> Fetch.PackageTransitiveDeps -> Spago (Fetch.FetchEnv a) Docs.DocsEnv +mkDocsEnv :: DocsArgs -> Fetch.PackageTransitiveDeps -> Spago (Fetch.FetchEnv _) (Docs.DocsEnv _) mkDocsEnv args dependencies = do { logOptions, workspace } <- ask purs <- Purs.getPurs diff --git a/core/spago.yaml b/core/spago.yaml index 11fd47609..b1e85e2e2 100644 --- a/core/spago.yaml +++ b/core/spago.yaml @@ -1,5 +1,7 @@ package: name: spago-core + build: + strict: true dependencies: - aff - argonaut-core diff --git a/core/src/Config.purs b/core/src/Config.purs index 3229998cb..dc00bb37a 100644 --- a/core/src/Config.purs +++ b/core/src/Config.purs @@ -288,12 +288,10 @@ type WorkspaceConfig = , extra_packages :: Maybe (Map PackageName ExtraPackage) , backend :: Maybe BackendConfig , build_opts :: Maybe WorkspaceBuildOptionsInput - , lock :: Maybe Boolean } workspaceConfigCodec :: JsonCodec WorkspaceConfig workspaceConfigCodec = CA.object "WorkspaceConfig" - $ CA.recordPropOptional (Proxy :: _ "lock") CA.boolean $ CA.recordPropOptional (Proxy :: _ "package_set") setAddressCodec $ CA.recordPropOptional (Proxy :: _ "backend") backendConfigCodec $ CA.recordPropOptional (Proxy :: _ "build_opts") buildOptionsCodec @@ -483,5 +481,7 @@ readConfig :: forall a. FilePath -> Spago (LogEnv a) (Either String { doc :: Yam readConfig path = do logDebug $ "Reading config from " <> path FS.exists path >>= case _ of - false -> pure (Left $ "Did not find " <> path <> " file.") + false -> pure $ Left $ case path of + "spago.yaml" -> "Did not find " <> path <> " Run `spago init` to initialise a new project." + _ -> "Did not find " <> path true -> liftAff $ FS.readYamlDocFile configCodec path diff --git a/core/src/Prelude.purs b/core/src/Prelude.purs index 2ed332564..b3d365b96 100644 --- a/core/src/Prelude.purs +++ b/core/src/Prelude.purs @@ -10,8 +10,8 @@ import Prelude import Control.Alt ((<|>)) as Extra import Control.Monad.Error.Class (class MonadError, class MonadThrow, try, catchError) as Extra -import Control.Monad.Reader (ask, asks) as Extra -import Control.Monad.Reader (class MonadAsk, ReaderT, runReaderT) +import Control.Monad.Reader (ask, asks, local) as Extra +import Control.Monad.Reader (class MonadAsk, class MonadReader, ReaderT, runReaderT) import Control.Monad.State (StateT) as Extra import Data.Array ((..)) as Extra import Data.Array.NonEmpty (NonEmptyArray) as Extra @@ -65,6 +65,7 @@ derive newtype instance Extra.MonadAff (Spago env) derive newtype instance Extra.MonadThrow Extra.Error (Spago env) derive newtype instance Extra.MonadError Extra.Error (Spago env) derive newtype instance MonadAsk env (Spago env) +derive newtype instance MonadReader env (Spago env) runSpago' :: forall a env. env -> Spago env a -> Extra.Aff a runSpago' env (Spago m) = runReaderT m env diff --git a/docs-search/client-halogen/spago.yaml b/docs-search/client-halogen/spago.yaml index ca3c71648..86649abab 100644 --- a/docs-search/client-halogen/spago.yaml +++ b/docs-search/client-halogen/spago.yaml @@ -33,6 +33,8 @@ package: - web-html - web-storage - web-uievents + build: + strict: true bundle: type: "app" minify: true diff --git a/docs-search/client-halogen/src/Docs/Search/App/SearchField.purs b/docs-search/client-halogen/src/Docs/Search/App/SearchField.purs index a418873ae..b2f53e5c1 100644 --- a/docs-search/client-halogen/src/Docs/Search/App/SearchField.purs +++ b/docs-search/client-halogen/src/Docs/Search/App/SearchField.purs @@ -62,7 +62,7 @@ handleQuery :: forall a . Query a -> H.HalogenM State Action () SearchFieldMessage Aff (Maybe a) -handleQuery (ReadURIHash next) = do +handleQuery (ReadURIHash _next) = do oldInput <- H.get <#> _.input newInput <- H.liftEffect URIHash.getInput when (oldInput /= newInput) do @@ -85,7 +85,7 @@ handleAction = case _ of (HTMLDocument.toEventTarget document) (map (HandleKey sid) <<< KE.fromEvent) - HandleKey sid ev -> do + HandleKey _sid ev -> do when (KE.code ev == "KeyS") do state <- H.get diff --git a/docs-search/client-halogen/src/Docs/Search/App/SearchResults.purs b/docs-search/client-halogen/src/Docs/Search/App/SearchResults.purs index 2fdfae958..9ddff5c28 100644 --- a/docs-search/client-halogen/src/Docs/Search/App/SearchResults.purs +++ b/docs-search/client-halogen/src/Docs/Search/App/SearchResults.purs @@ -15,7 +15,7 @@ import Docs.Search.SearchResult (ResultInfo(..), SearchResult(..)) import Docs.Search.TypeDecoder (Constraint(..), Constraint', Type', Qualified(..), QualifiedBy(..), ProperName(..), Type(..), TypeArgument, ClassName, FunDeps) import Docs.Search.TypeQuery as TypeQuery import Docs.Search.TypeIndex (TypeIndex) -import Docs.Search.Types (Identifier(..), ModuleName(..), PackageName) +import Docs.Search.Types (Identifier, ModuleName(..), PackageName) import Docs.Search.Meta (Meta) import Prelude @@ -95,15 +95,15 @@ handleQuery :: forall o a . Query a -> H.HalogenM State Action () o Aff (Maybe a) -handleQuery (MessageFromSearchField Focused next) = do +handleQuery (MessageFromSearchField Focused _next) = do pure Nothing -handleQuery (MessageFromSearchField LostFocus next) = do +handleQuery (MessageFromSearchField LostFocus _next) = do pure Nothing -handleQuery (MessageFromSearchField InputCleared next) = do +handleQuery (MessageFromSearchField InputCleared _next) = do H.modify_ (_ { results = [], input = "", mode = Off }) showPageContents pure Nothing -handleQuery (MessageFromSearchField (InputUpdated input_) next) = do +handleQuery (MessageFromSearchField (InputUpdated input_) _next) = do let input = String.trim input_ state <- H.modify (_ { input = input }) @@ -233,9 +233,9 @@ renderResult state (DeclResult r) = renderSearchResult state r renderResult state (TypeResult r) = renderSearchResult state r -renderResult state (PackResult r) = +renderResult _state (PackResult r) = renderPackageResult r -renderResult state (MdlResult r) = +renderResult _state (MdlResult r) = renderModuleResult r renderPackageResult @@ -272,7 +272,7 @@ renderModuleResult :: forall a . ModuleResult -> Array (HH.HTML a Action) -renderModuleResult { name, package } = +renderModuleResult { name, package: _ } = [ HH.div [ HP.class_ (wrap "result") ] [ HH.h3 [ HP.class_ (wrap "result__title") ] [ HH.span @@ -457,7 +457,7 @@ renderTypeClassMemberSignature } -> { name :: Identifier | rest } -> Array (HH.HTML a Action) -renderTypeClassMemberSignature { type: ty, typeClass, typeClassArguments } result = +renderTypeClassMemberSignature { type: ty, typeClass: _, typeClassArguments: _ } result = [ HH.text $ unwrap result.name , HH.text " :: " , renderType ty @@ -507,8 +507,8 @@ renderTypeSynonymSignature { type: ty, arguments } { name } = ] renderTypeArgument :: forall a. TypeArgument -> Array (HH.HTML a Action) -renderTypeArgument ({ name, kind }) = - case kind of +renderTypeArgument ({ name, kind: maybeKind }) = + case maybeKind of Nothing -> [ HH.text $ name ] Just kind -> @@ -614,8 +614,8 @@ renderForAll ty = [ keyword "forall" ] <> ( Array.fromFoldable foralls.binders <#> - \{ name, kind } -> - case kind of + \{ name, kind: maybeKind } -> + case maybeKind of Nothing -> HH.text (" " <> name) Just kind -> HH.span_ diff --git a/docs-search/client-halogen/src/Docs/Search/App/Sidebar.purs b/docs-search/client-halogen/src/Docs/Search/App/Sidebar.purs index 6351c5379..1f8d6d442 100644 --- a/docs-search/client-halogen/src/Docs/Search/App/Sidebar.purs +++ b/docs-search/client-halogen/src/Docs/Search/App/Sidebar.purs @@ -107,7 +107,7 @@ handleQuery :: forall a i . Query a -> H.HalogenM State i () Action Aff (Maybe a) -handleQuery (UpdateModuleGrouping next) = do +handleQuery (UpdateModuleGrouping _next) = do oldGroupingMode <- H.get <#> _.groupingMode newGroupingMode <- H.liftEffect loadGroupingModeFromLocalStorage when (oldGroupingMode /= newGroupingMode) do @@ -201,7 +201,7 @@ getCurrentModuleName = do getCurrentPackage :: ModuleIndex -> Maybe ModuleName -> PackageInfo getCurrentPackage { modulePackages } (Just moduleName) = fromMaybe UnknownPackage $ Map.lookup moduleName modulePackages -getCurrentPackage { modulePackages } Nothing = UnknownPackage +getCurrentPackage { modulePackages: _ } Nothing = UnknownPackage -- | Convert checkbox status to sidebar mode isCheckedToGroupingMode :: Boolean -> GroupingMode diff --git a/docs-search/common/spago.yaml b/docs-search/common/spago.yaml index 3a2de0ca9..572d7f113 100644 --- a/docs-search/common/spago.yaml +++ b/docs-search/common/spago.yaml @@ -1,5 +1,10 @@ package: name: docs-search-common + build: + strict: true + censor_project_warnings: + - ImplicitQualifiedImport + - ImplicitQualifiedImportReExport dependencies: - aff - aff-promise diff --git a/docs-search/common/src/Docs/Search/Config.purs b/docs-search/common/src/Docs/Search/Config.purs index a3a8f02d8..553dfa569 100644 --- a/docs-search/common/src/Docs/Search/Config.purs +++ b/docs-search/common/src/Docs/Search/Config.purs @@ -1,13 +1,11 @@ module Docs.Search.Config where -import Docs.Search.Types (GlobalIdentifier, PackageName, PartId(..), URL, FilePath) - import Prelude import Data.Char as Char import Data.List (List, (:)) -import Data.List as List import Data.Newtype (wrap) +import Docs.Search.Types (GlobalIdentifier, PackageName, PartId(..), URL, FilePath) version :: String version = "0.0.12" diff --git a/docs-search/common/src/Docs/Search/Declarations.purs b/docs-search/common/src/Docs/Search/Declarations.purs index 09650b5f5..1e7bff57c 100644 --- a/docs-search/common/src/Docs/Search/Declarations.purs +++ b/docs-search/common/src/Docs/Search/Declarations.purs @@ -46,7 +46,7 @@ mkDeclarations scores = Declarations <<< foldr (insertDocModule scores) mempty -> Trie Char (List SearchResult) -> Trie Char (List SearchResult) - insertDocModule scores (DocModule { name, declarations }) trie = + insertDocModule _scores (DocModule { name, declarations }) trie = foldr (insertDeclaration scores name) trie declarations insertDeclaration @@ -55,7 +55,7 @@ insertDeclaration -> Declaration -> Trie Char (List SearchResult) -> Trie Char (List SearchResult) -insertDeclaration scores moduleName entry@(Declaration { title }) trie = foldr insertSearchResult trie (resultsForDeclaration scores moduleName entry) +insertDeclaration scores moduleName entry@(Declaration { title: _ }) trie = foldr insertSearchResult trie (resultsForDeclaration scores moduleName entry) insertSearchResult :: { path :: String @@ -120,7 +120,7 @@ resultsForDeclaration scores moduleName indexEntry@(Declaration entry) = _ -> Nothing mkInfo :: DeclLevel -> Declaration -> Maybe ResultInfo -mkInfo declLevel (Declaration { info, title }) = +mkInfo declLevel (Declaration { info, title: _ }) = case info of ValueDeclaration ty -> Just $ ValueResult { type: ty } @@ -195,7 +195,7 @@ getLevelAndName (Declaration { info, title }) = ) title ) - ExternDataDeclaration _ kind -> + ExternDataDeclaration _ _kind -> { name: title, declLevel: TypeLevel } -- | Extract package name from `sourceSpan.name`, which contains path to @@ -228,7 +228,7 @@ resultsForChildDeclaration packageInfo moduleName parentResult - child@(ChildDeclaration { title, info, comments, sourceSpan }) + child@(ChildDeclaration { title, info: _, comments, sourceSpan }) | Just resultInfo <- mkChildInfo parentResult child = { path: title , result: SearchResult diff --git a/docs-search/common/src/Docs/Search/Engine.purs b/docs-search/common/src/Docs/Search/Engine.purs index 4809719c0..25ffc415e 100644 --- a/docs-search/common/src/Docs/Search/Engine.purs +++ b/docs-search/common/src/Docs/Search/Engine.purs @@ -70,7 +70,7 @@ getResultPackageInfo (MdlResult r) = r.package getResultModuleName :: Result -> ModuleName getResultModuleName (DeclResult r) = (unwrap r).moduleName getResultModuleName (TypeResult r) = (unwrap r).moduleName -getResultModuleName (PackResult r) = ModuleName "" +getResultModuleName (PackResult _r) = ModuleName "" getResultModuleName (MdlResult r) = r.name getResultName :: Result -> String @@ -79,10 +79,7 @@ getResultName (TypeResult r) = unwrap (unwrap r).name getResultName (PackResult r) = unwrap r.name getResultName (MdlResult r) = unwrap r.name -sortByPopularity - :: forall index typeIndex - . Array Result - -> Array Result +sortByPopularity :: Array Result -> Array Result sortByPopularity = Array.sortBy ( compare `on` (getResultScore >>> negate) diff --git a/docs-search/common/src/Docs/Search/JsonCodec.purs b/docs-search/common/src/Docs/Search/JsonCodec.purs index dd42a3210..d547262e5 100644 --- a/docs-search/common/src/Docs/Search/JsonCodec.purs +++ b/docs-search/common/src/Docs/Search/JsonCodec.purs @@ -5,18 +5,15 @@ module Docs.Search.JsonCodec ) where import Prelude -import Prim.Row (class Cons) +import Prim.Row (class Cons) import Codec.Json.Unidirectional.Value (DecodeError, printDecodeError) -import Data.Argonaut.Core (Json, fromString, stringify) -import Data.Codec.Argonaut (JsonCodec, JsonDecodeError(..)) -import Data.Codec.Argonaut.Common as CA -import Data.Codec.Argonaut.Sum as CAS -import Data.Codec.Argonaut.Record as CAR -import Data.Either (Either(..)) +import Data.Argonaut.Core (Json) +import Data.Codec.Argonaut (JsonDecodeError(..)) +import Data.Either (Either) import Data.Profunctor.Choice (left) import Data.Symbol (class IsSymbol) -import Data.Variant +import Data.Variant (Variant, inj) import Type.Proxy (Proxy(..)) -- | Equivalent to `Data.Variant.inj`, just uses a Visible Type Application instead of Proxy diff --git a/docs-search/common/src/Docs/Search/Meta.purs b/docs-search/common/src/Docs/Search/Meta.purs index 7a90ee837..b737dfb7d 100644 --- a/docs-search/common/src/Docs/Search/Meta.purs +++ b/docs-search/common/src/Docs/Search/Meta.purs @@ -1,16 +1,13 @@ module Docs.Search.Meta where +import Prelude + +import Data.Codec.Argonaut (JsonCodec) +import Data.Codec.Argonaut.Record as CAR import Docs.Search.Config as Config import Docs.Search.Loader as Loader import Docs.Search.Types (PackageName) import Docs.Search.Types as Package - -import Data.Codec.Argonaut (JsonCodec, JsonDecodeError) -import Data.Codec.Argonaut.Common as CA -import Data.Codec.Argonaut.Record as CAR - -import Prelude - import Effect.Aff (Aff, catchError) type Meta = diff --git a/docs-search/common/src/Docs/Search/Score.purs b/docs-search/common/src/Docs/Search/Score.purs index 5de0e078e..f8745c005 100644 --- a/docs-search/common/src/Docs/Search/Score.purs +++ b/docs-search/common/src/Docs/Search/Score.purs @@ -1,17 +1,13 @@ module Docs.Search.Score where -import Docs.Search.Types (PackageName(..), PackageInfo(..), PackageScore(..)) - import Prelude import Data.Array as Array import Data.Map (Map) import Data.Map as Map import Data.Maybe (fromMaybe) -import Data.Newtype (unwrap, wrap) -import Data.String.CodeUnits as String import Data.Tuple (Tuple(..)) -import Data.Tuple as Tuple +import Docs.Search.Types (PackageInfo(..), PackageName, PackageScore(..)) import Safe.Coerce (coerce) import Web.Bower.PackageMeta as Bower diff --git a/docs-search/common/src/Docs/Search/SearchResult.purs b/docs-search/common/src/Docs/Search/SearchResult.purs index 605b48635..3418fe4a4 100644 --- a/docs-search/common/src/Docs/Search/SearchResult.purs +++ b/docs-search/common/src/Docs/Search/SearchResult.purs @@ -1,19 +1,8 @@ module Docs.Search.SearchResult where -import Docs.Search.JsonCodec (inject) -import Docs.Search.DocsJson as Docs -import Docs.Search.TypeDecoder (Constraint, FunDeps, QualifiedName, Type, TypeArgument) -import Docs.Search.Types (Identifier(..), ModuleName, PackageInfo, PackageScore) -import Docs.Search.Types as Package -import Docs.Search.TypeDecoder (Constraint', Qualified, Type, TypeArgument, FunDeps, Type', ProperName(..), ClassName(..)) -import Docs.Search.TypeDecoder as TypeDecoder -import Docs.Search.JsonCodec as JsonCodec -import Docs.Search.DocTypes (DataDeclType, SourceSpan) -import Docs.Search.Types (ModuleName, PackageInfo, Identifier, PackageScore) - import Prelude -import Data.Codec.Argonaut (JsonCodec, JsonDecodeError) +import Data.Codec.Argonaut (JsonCodec) import Data.Codec.Argonaut.Common as CA import Data.Codec.Argonaut.Record as CAR import Data.Codec.Argonaut.Variant as CAV @@ -21,8 +10,14 @@ import Data.Either (Either(..)) import Data.Maybe (Maybe(..)) import Data.Newtype (class Newtype, un) import Data.Profunctor (wrapIso, dimap) -import Data.Tuple (Tuple) import Data.Variant as Variant +import Docs.Search.DocTypes (DataDeclType, SourceSpan) +import Docs.Search.DocsJson as Docs +import Docs.Search.JsonCodec (inject) +import Docs.Search.TypeDecoder (ClassName, Constraint', FunDeps, ProperName, Qualified, Type', TypeArgument) +import Docs.Search.TypeDecoder as TypeDecoder +import Docs.Search.Types (Identifier(..), ModuleName, PackageInfo, PackageScore) +import Docs.Search.Types as Package -- | Metadata that makes sense only for certain types of search results. data ResultInfo diff --git a/docs-search/common/src/Docs/Search/TypeDecoder.purs b/docs-search/common/src/Docs/Search/TypeDecoder.purs index 849c3f7a4..a1ddb69f0 100644 --- a/docs-search/common/src/Docs/Search/TypeDecoder.purs +++ b/docs-search/common/src/Docs/Search/TypeDecoder.purs @@ -12,25 +12,19 @@ module Docs.Search.TypeDecoder , constraintCodec ) where -import Docs.Search.DocTypes as ReExport - -import Docs.Search.Types (Identifier) -import Docs.Search.DocTypes (Type', Type(..), Constraint(..), Label(..), DataDeclType, ProperName(..), Qualified(..)) -import Docs.Search.DocTypes as DocTypes -import Docs.Search.JsonCodec as JsonCodec - import Prelude +import Prim hiding (Constraint) import Codec.Json.Unidirectional.Value as Json import Data.Argonaut.Core as Argonaut -import Data.Codec.Argonaut (JsonCodec) import Data.Codec.Argonaut.Common as CA import Data.Codec.Argonaut.Record as CAR -import Data.List (List(..), (:)) -import Data.List as List -import Data.Maybe (Maybe(..)) -import Data.Newtype (wrap) +import Data.Maybe (Maybe) import Data.Tuple (Tuple) +import Docs.Search.DocTypes (AnyOpName, ChildDeclaration(..), ChildDeclarationInfo(..), ClassName, Constraint(..), Constraint', ConstraintData(..), ConstructorName, DataDeclType(..), Declaration(..), DeclarationInfo(..), DocLink(..), DocModule(..), GithubRepo(..), GithubUser(..), Ident(..), InPackage(..), InternalIdentData(..), KindInfo(..), Label(..), LinkLocation(..), LinksContext(..), ManifestError(..), ModuleName(..), Name(..), Namespace, NotYetKnown(..), OpName(..), OpNameType, Package(..), PackageError(..), ProperName(..), ProperNameType, Qualified(..), QualifiedBy(..), RowListItem(..), SkolemScope(..), SourceAnn(..), SourceConstraint, SourcePos(..), SourceSpan(..), SourceType, Type(..), Type', TypeName, TypeOpName, TypeVarVisibility(..), UploadedPackage, ValueOpName, VerifiedPackage, WildcardData(..), _ss, _sss, byNullSourcePos, compareConstraint, compareMaybeType, compareType, eqConstraint, eqMaybeType, eqType, fromChildDeclaration, fromChildDeclarationInfo, fromConstraint, fromConstraintData, fromDataDeclType, fromDeclaration, fromDeclarationInfo, fromDocModule, fromGithubRepo, fromGithubUser, fromISO8601, fromIdent, fromInPackage, fromInternalIdentData, fromKindInfo, fromLabel, fromModuleName, fromNotYetKnown, fromOpName, fromPackage, fromProperName, fromQualified, fromQualifiedBy, fromSkolemScope, fromSourceAnn, fromSourcePos, fromSourceSpan, fromType, fromTypeVarVisibility, fromVersion, fromWildcardData, hh_mm, kindType, nullSourceAnn, nullSourcePos, nullSourceSpan, showDataDeclType, srcTypeConstructor, toAsConstrantUnit, toChildDeclaration, toChildDeclarationInfo, toConstraint', toConstraintData, toConstraintUnit, toDataDeclType, toDeclaration, toDeclarationInfo, toDocModule, toFunDeps, toGithubRepo, toGithubUser, toISO8601, toIdent, toInPackage, toInternalIdentData, toKindInfo, toLabel, toModuleName, toNotYetKnown, toOpName, toPackage, toProperName, toQualified, toQualifiedBy, toSkolemScope, toSourceAnn, toSourceConstraint, toSourcePos, toSourceSpan, toSourceType, toType', toTypeArguments, toTypeUnit, toTypeVarVisibility, toUploadedPackage, toVersion, toWildcardData, yyyy_mm_dd) as ReExport +import Docs.Search.DocTypes (Constraint, DataDeclType, ProperName, Qualified, Type') +import Docs.Search.DocTypes as DocTypes +import Docs.Search.JsonCodec as JsonCodec type QualifiedName tag = Qualified (ProperName tag) diff --git a/docs-search/common/src/Docs/Search/TypeQuery.purs b/docs-search/common/src/Docs/Search/TypeQuery.purs index b997664d8..1ade92a43 100644 --- a/docs-search/common/src/Docs/Search/TypeQuery.purs +++ b/docs-search/common/src/Docs/Search/TypeQuery.purs @@ -12,17 +12,13 @@ module Docs.Search.TypeQuery , joinRows ) where -import Docs.Search.Config as Config -import Docs.Search.Extra (foldl1, foldr1) -import Docs.Search.TypeDecoder (Type(..), Type', Qualified(..), QualifiedBy(..), ModuleName(..), ProperName(..), Label(..), Constraint(..), TypeArgument) -import Docs.Search.Types (Identifier(..)) - import Prelude +import Prim hiding (Row) + import Control.Alt ((<|>)) import Data.Array as Array import Data.Either (Either) import Data.Generic.Rep (class Generic) -import Data.Show.Generic (genericShow) import Data.List (List(..), many, some, (:)) import Data.List as List import Data.List.NonEmpty (NonEmptyList) @@ -34,14 +30,19 @@ import Data.Newtype (wrap) import Data.Ord (abs) import Data.Set (Set) import Data.Set as Set +import Data.Show.Generic (genericShow) import Data.String.CodeUnits (fromCharArray) import Data.String.Common (trim) as String import Data.Tuple (Tuple(..), fst, snd) +import Docs.Search.Config as Config +import Docs.Search.Extra (foldl1, foldr1) +import Docs.Search.TypeDecoder (Type(..), Type', Qualified(..), QualifiedBy(..), ModuleName(..), ProperName(..), Label(..), Constraint(..), TypeArgument) +import Docs.Search.Types (Identifier(..)) import Language.PureScript.PSString as PSString +import Safe.Coerce (coerce) import StringParser (ParseError, Parser, runParser, try) import StringParser.CodePoints (alphaNum, anyLetter, char, eof, lowerCaseChar, skipSpaces, string, upperCaseChar) import StringParser.Combinators (fix, sepBy, sepBy1, sepEndBy, sepEndBy1) -import Safe.Coerce (coerce) -- | We need type queries because we don't have a full-featured type parser -- | available. @@ -152,14 +153,14 @@ getFreeVariables query = go Set.empty Set.empty (List.singleton $ Next query) if Set.member var bound then free else Set.insert var free - go bound free Nil = free + go _bound free Nil = free go bound free (Unbind vars : rest) = go (Set.difference bound vars) free rest go bound free (Next (QVar var) : rest) = go bound (insertIfUnbound bound var free) rest - go bound free (Next (QConst str) : rest) = + go bound free (Next (QConst _str) : rest) = go bound free rest go bound free (Next (QFun q1 q2) : rest) = go bound free (Next q1 : Next q2 : rest) @@ -336,9 +337,6 @@ unify query type_ = go Nil (List.singleton { q: query, t: type_ }) go acc ({ q, t: TypeLevelInt _ _ } : rest) = go (QueryMismatch q : acc) rest - go acc ({ q, t: TypeLevelString _ _ } : rest) = - go (QueryMismatch q : acc) rest - go acc ({ q, t: TypeWildcard _ _ } : rest) = go (QueryMismatch q : acc) rest @@ -417,7 +415,7 @@ namesPenalty = go 0 Set.size (Set.intersection qcs tcs) in go (p + Config.penalties.matchConstraint * p') rest - go p (RowsMismatch n m : rest) = go (Config.penalties.rowsMismatch * abs (n - m)) rest + go _p (RowsMismatch n m : rest) = go (Config.penalties.rowsMismatch * abs (n - m)) rest go p (_ : rest) = go p rest -- | Penalty for generalization and instantiation. @@ -425,12 +423,12 @@ mismatchPenalty :: List Substitution -> Int mismatchPenalty = go 0 where go n Nil = n - go n (Instantiate q t : rest) = go + go n (Instantiate _q t : rest) = go ( n + typeSize t * Config.penalties.instantiate ) rest - go n (Generalize q t : rest) = go + go n (Generalize q _t : rest) = go ( n + typeQuerySize q * Config.penalties.generalize ) @@ -497,7 +495,7 @@ typeSize = go 0 <<< List.singleton ( TypeConstructor _ ( Qualified (ByModuleName (ModuleName "Prim")) - name + _name ) ) t1 @@ -517,7 +515,7 @@ typeSize = go 0 <<< List.singleton go (n + 1) rest go n (KindedType _ t1 t2 : rest) = go n (t1 : t2 : rest) - go n (BinaryNoParensType _ op t1 t2 : rest) = + go n (BinaryNoParensType _ _op t1 t2 : rest) = go (n + 1) (t1 : t2 : rest) go n (ParensInType _ t : rest) = go n (t : rest) diff --git a/docs-search/common/src/Docs/Search/TypeShape.purs b/docs-search/common/src/Docs/Search/TypeShape.purs index 3f54ce85b..625e9c8b3 100644 --- a/docs-search/common/src/Docs/Search/TypeShape.purs +++ b/docs-search/common/src/Docs/Search/TypeShape.purs @@ -8,12 +8,8 @@ module Docs.Search.TypeShape , ShapeChunk(..) ) where -import Docs.Search.TypeDecoder (ModuleName(..), ProperName(..), Qualified(..), QualifiedBy(..), Type(..), Type') -import Docs.Search.TypeQuery (TypeQuery(..)) -import Docs.Search.TypeQuery as TypeQuery -import Docs.Search.Types (Identifier(..)) - import Prelude + import Data.Generic.Rep (class Generic) import Data.Show.Generic (genericShow) import Data.List (List(..), (:)) @@ -22,6 +18,9 @@ import Data.List.NonEmpty as NonEmptyList import Data.Set as Set import Data.Tuple (Tuple(..), snd) import Data.Ord (abs) +import Docs.Search.TypeDecoder (ModuleName(..), ProperName(..), Qualified(..), QualifiedBy(..), Type(..), Type') +import Docs.Search.TypeQuery (TypeQuery(..)) +import Docs.Search.TypeQuery as TypeQuery type TypeShape = List ShapeChunk @@ -71,7 +70,7 @@ shapeOfTypeQuery query = case this of QVar _ -> go rest (PVar : acc) - QConst v -> + QConst _v -> go rest (PVar : acc) QFun q1 q2 -> go (q1 : q2 : rest) (PFun : acc) @@ -79,7 +78,7 @@ shapeOfTypeQuery query = go (q1 : q2 : rest) (PApp : acc) QForAll lst q -> go (q : rest) (PForAll (NonEmptyList.length lst) : acc) - QConstraint str lst q -> + QConstraint _str _lst q -> go (q : rest) acc QRow lst -> let diff --git a/docs-search/common/src/Docs/Search/Types.purs b/docs-search/common/src/Docs/Search/Types.purs index e10c5a59b..76af6015c 100644 --- a/docs-search/common/src/Docs/Search/Types.purs +++ b/docs-search/common/src/Docs/Search/Types.purs @@ -13,28 +13,22 @@ module Docs.Search.Types , FilePath(..) ) where -import Web.Bower.PackageMeta (PackageName(..)) as ReExport -import Language.PureScript.Names (ModuleName(..)) as ReExport - -import Docs.Search.JsonCodec (inject) - import Prelude -import Data.Argonaut.Core (Json) -import Data.Codec.Argonaut (JsonCodec, JsonDecodeError) +import Data.Codec.Argonaut (JsonCodec) import Data.Codec.Argonaut.Common as CA -import Data.Codec.Argonaut.Sum as CAS import Data.Codec.Argonaut.Variant as CAV import Data.Either (Either(..)) import Data.Generic.Rep (class Generic) import Data.Newtype (class Newtype) -import Data.Maybe (Maybe(..)) import Data.Profunctor (wrapIso, dimap) import Data.Show.Generic (genericShow) -import Data.Tuple (Tuple(..)) import Data.Variant as Variant +import Docs.Search.JsonCodec (inject) import Language.PureScript.Names (ModuleName(..)) +import Language.PureScript.Names (ModuleName(..)) as ReExport import Web.Bower.PackageMeta (PackageName(..)) +import Web.Bower.PackageMeta (PackageName(..)) as ReExport newtype Identifier = Identifier String diff --git a/docs-search/index/spago.yaml b/docs-search/index/spago.yaml index 79013bfb6..23be5c1d2 100644 --- a/docs-search/index/spago.yaml +++ b/docs-search/index/spago.yaml @@ -1,5 +1,7 @@ package: name: docs-search-index + build: + strict: true dependencies: - aff - argonaut-core diff --git a/docs-search/index/src/Docs/Search/ModuleParser.purs b/docs-search/index/src/Docs/Search/ModuleParser.purs index 17527b775..b468e3b11 100644 --- a/docs-search/index/src/Docs/Search/ModuleParser.purs +++ b/docs-search/index/src/Docs/Search/ModuleParser.purs @@ -2,14 +2,12 @@ module Docs.Search.ModuleParser where import Prelude -import Control.Alt ((<|>)) import Data.Either (hush) import Data.Foldable (intercalate) import Data.Maybe (Maybe) import Data.Newtype (wrap) import Docs.Search.Types (ModuleName) -import Effect (Effect) -import StringParser (Parser, char, choice, fix, many, manyTill, noneOf, regex, runParser, sepBy, sepBy1, string, try, whiteSpace) +import StringParser (Parser, char, choice, many, manyTill, noneOf, regex, runParser, sepBy1, string, try, whiteSpace) parseModuleName :: String -> Maybe ModuleName parseModuleName = map wrap <<< hush <<< runParser do diff --git a/flake.lock b/flake.lock index d312da095..2f668c47e 100644 --- a/flake.lock +++ b/flake.lock @@ -1,15 +1,31 @@ { "nodes": { + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, "flake-utils": { "inputs": { "systems": "systems" }, "locked": { - "lastModified": 1694529238, - "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", + "lastModified": 1701680307, + "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=", "owner": "numtide", "repo": "flake-utils", - "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", + "rev": "4022d587cbbfd70fe950c1e2083a02621806a725", "type": "github" }, "original": { @@ -20,11 +36,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1697851979, - "narHash": "sha256-lJ8k4qkkwdvi+t/Xc6Fn74kUuobpu9ynPGxNZR6OwoA=", + "lastModified": 1702759837, + "narHash": "sha256-u3XeJVRe/Q975nwFE+6ALEwypMKJEELMJKDAhSKyq3M=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "5550a85a087c04ddcace7f892b0bdc9d8bb080c8", + "rev": "b2566f4f897ac6224e094b167d9488d03e157f28", "type": "github" }, "original": { @@ -36,17 +52,18 @@ }, "purescript-overlay": { "inputs": { + "flake-compat": "flake-compat", "nixpkgs": [ "nixpkgs" ], "slimlock": "slimlock" }, "locked": { - "lastModified": 1697766752, - "narHash": "sha256-jTGJhKuv/KPsMOnfIUSqoTckf4jo3e+9e0XY2cvXbD4=", + "lastModified": 1703097182, + "narHash": "sha256-L7UeQMdZWKEOUpRveXhvq2aF18yF5KgyCUYZYxvCZPI=", "owner": "thomashoneyman", "repo": "purescript-overlay", - "rev": "1a6676b94f064113980b142454e3eefeecce5dcc", + "rev": "aa82efe06d9d32cee5bda7a44d9cf6cdc4c6fb60", "type": "github" }, "original": { diff --git a/package-lock.json b/package-lock.json index 618865546..726ac6c62 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "spago", - "version": "0.93.19", + "version": "0.93.22", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "spago", - "version": "0.93.19", + "version": "0.93.22", "license": "BSD-3-Clause", "dependencies": { "better-sqlite3": "^8.6.0", diff --git a/package.json b/package.json index a40227943..e4bf9552d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "spago", - "version": "0.93.19", + "version": "0.93.22", "license": "BSD-3-Clause", "description": "🍝 PureScript package manager and build tool", "keywords": [ diff --git a/spago.lock b/spago.lock index 03546dd08..f9801b0a0 100644 --- a/spago.lock +++ b/spago.lock @@ -36,6 +36,107 @@ workspace: - web-storage - web-uievents test_dependencies: [] + build_plan: + - aff + - aff-promise + - argonaut-core + - arrays + - avar + - bifunctors + - catenable-lists + - codec + - codec-argonaut + - colors + - console + - const + - contravariant + - control + - css + - datetime + - distributive + - docs-search-common + - dom-indexed + - effect + - either + - enums + - exceptions + - exists + - fixed-points + - foldable-traversable + - foreign + - foreign-object + - fork + - formatters + - free + - freeap + - functions + - functors + - gen + - halogen + - halogen-css + - halogen-subscriptions + - halogen-vdom + - html-parser-halogen + - identity + - integers + - invariant + - js-date + - js-promise + - js-uri + - json-codecs + - language-purescript + - lazy + - lcg + - lists + - markdown-it + - markdown-it-halogen + - maybe + - media-types + - newtype + - nonempty + - now + - nullable + - numbers + - options + - ordered-collections + - orders + - parallel + - parsing + - partial + - prelude + - profunctor + - profunctor-lenses + - quickcheck + - quickcheck-laws + - random + - record + - refs + - safe-coerce + - search-trie + - st + - string-parsers + - strings + - tailrec + - these + - transformers + - tuples + - type-equality + - typelevel-prelude + - unfoldable + - unicode + - unsafe-coerce + - unsafe-reference + - variant + - versions + - web-clipboard + - web-dom + - web-events + - web-file + - web-html + - web-pointerevents + - web-storage + - web-touchevents + - web-uievents docs-search-common: path: docs-search/common dependencies: @@ -66,6 +167,75 @@ workspace: - tuples - variant test_dependencies: [] + build_plan: + - aff + - aff-promise + - argonaut-core + - arrays + - bifunctors + - codec + - codec-argonaut + - console + - const + - contravariant + - control + - datetime + - distributive + - effect + - either + - enums + - exceptions + - exists + - fixed-points + - foldable-traversable + - foreign + - foreign-object + - formatters + - functions + - functors + - gen + - identity + - integers + - invariant + - json-codecs + - language-purescript + - lazy + - lcg + - lists + - maybe + - newtype + - nonempty + - nullable + - numbers + - ordered-collections + - orders + - parallel + - parsing + - partial + - prelude + - profunctor + - profunctor-lenses + - quickcheck + - quickcheck-laws + - random + - record + - refs + - safe-coerce + - search-trie + - st + - string-parsers + - strings + - tailrec + - these + - transformers + - tuples + - type-equality + - typelevel-prelude + - unfoldable + - unicode + - unsafe-coerce + - variant + - versions docs-search-index: path: docs-search/index dependencies: @@ -98,6 +268,95 @@ workspace: test_dependencies: - exceptions - spec + build_plan: + - aff + - aff-promise + - ansi + - argonaut-core + - arraybuffer-types + - arrays + - avar + - bifunctors + - catenable-lists + - codec + - codec-argonaut + - console + - const + - contravariant + - control + - datetime + - debug + - distributive + - docs-search-common + - effect + - either + - enums + - exceptions + - exists + - fixed-points + - foldable-traversable + - foreign + - foreign-object + - fork + - formatters + - free + - functions + - functors + - gen + - identity + - integers + - invariant + - js-date + - json-codecs + - language-purescript + - lazy + - lcg + - lists + - maybe + - mmorph + - newtype + - node-buffer + - node-event-emitter + - node-fs + - node-path + - node-process + - node-streams + - nonempty + - now + - nullable + - numbers + - ordered-collections + - orders + - parallel + - parsing + - partial + - pipes + - posix-types + - prelude + - profunctor + - profunctor-lenses + - quickcheck + - quickcheck-laws + - random + - record + - refs + - safe-coerce + - search-trie + - spec + - st + - string-parsers + - strings + - tailrec + - these + - transformers + - tuples + - type-equality + - typelevel-prelude + - unfoldable + - unicode + - unsafe-coerce + - variant + - versions spago: path: ./ dependencies: @@ -143,6 +402,132 @@ workspace: - unsafe-coerce test_dependencies: - spec + build_plan: + - aff + - aff-promise + - affjax + - affjax-node + - ansi + - argonaut-core + - arraybuffer-types + - arrays + - assert + - avar + - b64 + - bifunctors + - catenable-lists + - codec + - codec-argonaut + - console + - const + - contravariant + - control + - convertable-options + - datetime + - debug + - distributive + - docs-search-common + - docs-search-index + - dodo-printer + - effect + - either + - encoding + - enums + - exceptions + - exists + - fetch + - filterable + - fixed-points + - foldable-traversable + - foreign + - foreign-object + - fork + - form-urlencoded + - formatters + - free + - functions + - functors + - gen + - graphs + - http-methods + - identity + - integers + - invariant + - js-date + - js-fetch + - js-promise + - js-promise-aff + - js-timers + - js-uri + - json-codecs + - language-cst-parser + - language-purescript + - lazy + - lcg + - lists + - maybe + - media-types + - mmorph + - newtype + - node-buffer + - node-child-process + - node-event-emitter + - node-execa + - node-fs + - node-human-signals + - node-os + - node-path + - node-process + - node-streams + - nonempty + - now + - nullable + - numbers + - ordered-collections + - orders + - parallel + - parsing + - partial + - pipes + - posix-types + - prelude + - profunctor + - profunctor-lenses + - quickcheck + - quickcheck-laws + - random + - record + - refs + - registry-foreign + - registry-lib + - routing-duplex + - safe-coerce + - search-trie + - spago-core + - spec + - st + - string-parsers + - strings + - stringutils + - tailrec + - these + - transformers + - tuples + - type-equality + - typelevel-prelude + - unfoldable + - unicode + - unsafe-coerce + - unsafe-reference + - variant + - versions + - web-dom + - web-events + - web-file + - web-html + - web-storage + - web-streams + - web-xhr spago-bin: path: bin dependencies: @@ -164,6 +549,137 @@ workspace: - spago-core - unsafe-coerce test_dependencies: [] + build_plan: + - aff + - aff-promise + - affjax + - affjax-node + - ansi + - argonaut-core + - arraybuffer-types + - arrays + - assert + - avar + - b64 + - bifunctors + - catenable-lists + - codec + - codec-argonaut + - console + - const + - contravariant + - control + - convertable-options + - datetime + - debug + - distributive + - docs-search-common + - docs-search-index + - dodo-printer + - effect + - either + - encoding + - enums + - exceptions + - exists + - exitcodes + - fetch + - filterable + - fixed-points + - foldable-traversable + - foreign + - foreign-object + - fork + - form-urlencoded + - formatters + - free + - functions + - functors + - gen + - graphs + - http-methods + - identity + - integers + - invariant + - js-date + - js-fetch + - js-promise + - js-promise-aff + - js-timers + - js-uri + - json-codecs + - language-cst-parser + - language-purescript + - lazy + - lcg + - lists + - maybe + - media-types + - mmorph + - newtype + - node-buffer + - node-child-process + - node-event-emitter + - node-execa + - node-fs + - node-human-signals + - node-os + - node-path + - node-process + - node-streams + - nonempty + - now + - nullable + - numbers + - open-memoize + - optparse + - ordered-collections + - orders + - parallel + - parsing + - partial + - pipes + - posix-types + - prelude + - profunctor + - profunctor-lenses + - psci-support + - quickcheck + - quickcheck-laws + - random + - record + - refs + - registry-foreign + - registry-lib + - routing-duplex + - safe-coerce + - search-trie + - spago + - spago-core + - spec + - st + - string-parsers + - strings + - stringutils + - tailrec + - these + - transformers + - tuples + - type-equality + - typelevel-prelude + - unfoldable + - unicode + - unsafe-coerce + - unsafe-reference + - variant + - versions + - web-dom + - web-events + - web-file + - web-html + - web-storage + - web-streams + - web-xhr spago-core: path: core dependencies: @@ -200,8 +716,548 @@ workspace: - transformers - tuples test_dependencies: [] + build_plan: + - aff + - ansi + - argonaut-core + - arraybuffer-types + - arrays + - assert + - avar + - bifunctors + - catenable-lists + - codec + - codec-argonaut + - console + - const + - contravariant + - control + - datetime + - distributive + - dodo-printer + - effect + - either + - enums + - exceptions + - exists + - filterable + - fixed-points + - foldable-traversable + - foreign + - foreign-object + - formatters + - free + - functions + - functors + - gen + - graphs + - identity + - integers + - invariant + - js-date + - js-uri + - language-cst-parser + - lazy + - lcg + - lists + - maybe + - newtype + - node-buffer + - node-event-emitter + - node-fs + - node-path + - node-process + - node-streams + - nonempty + - now + - nullable + - numbers + - ordered-collections + - orders + - parallel + - parsing + - partial + - posix-types + - prelude + - profunctor + - profunctor-lenses + - quickcheck + - random + - record + - refs + - registry-lib + - routing-duplex + - safe-coerce + - st + - strings + - tailrec + - transformers + - tuples + - type-equality + - typelevel-prelude + - unfoldable + - unicode + - unsafe-coerce + - variant package_set: - registry: 46.0.0 + address: + registry: 46.0.0 + compiler: ">=0.15.12 <0.16.0" + content: + abc-parser: 2.0.1 + ace: 9.1.0 + aff: 7.1.0 + aff-bus: 6.0.0 + aff-coroutines: 9.0.0 + aff-promise: 4.0.0 + aff-retry: 2.0.0 + affjax: 13.0.0 + affjax-node: 1.0.0 + affjax-web: 1.0.0 + ansi: 7.0.0 + applicative-phases: 1.0.0 + argonaut: 9.0.0 + argonaut-aeson-generic: 0.4.1 + argonaut-codecs: 9.1.0 + argonaut-core: 7.0.0 + argonaut-generic: 8.0.0 + argonaut-traversals: 10.0.0 + argparse-basic: 2.0.0 + array-builder: 0.1.2 + array-search: 0.5.6 + arraybuffer: 13.2.0 + arraybuffer-builder: 3.1.0 + arraybuffer-types: 3.0.2 + arrays: 7.3.0 + arrays-extra: 0.4.2 + arrays-zipper: 2.0.1 + ask: 1.0.0 + assert: 6.0.0 + assert-multiple: 0.3.4 + avar: 5.0.0 + b64: 0.0.8 + barbies: 1.0.1 + barlow-lens: 0.9.0 + bifunctors: 6.0.0 + bigints: 7.0.1 + bolson: 0.3.9 + bookhound: 0.1.5 + bower-json: 3.0.0 + call-by-name: 4.0.1 + canvas: 6.0.0 + canvas-action: 9.0.0 + cartesian: 1.0.6 + catenable-lists: 7.0.0 + chameleon: 1.0.0 + chameleon-halogen: 1.0.3 + chameleon-react-basic: 1.1.0 + chameleon-styled: 2.5.0 + chameleon-transformers: 1.0.0 + channel: 1.0.0 + checked-exceptions: 3.1.1 + classless: 0.1.1 + classless-arbitrary: 0.1.1 + classless-decode-json: 0.1.1 + classless-encode-json: 0.1.3 + classnames: 2.0.0 + codec: 6.1.0 + codec-argonaut: 10.0.0 + codec-json: 1.1.0 + colors: 7.0.1 + concur-core: 0.5.0 + concur-react: 0.5.0 + concurrent-queues: 3.0.0 + console: 6.1.0 + const: 6.0.0 + contravariant: 6.0.0 + control: 6.0.0 + convertable-options: 1.0.0 + coroutines: 7.0.0 + css: 6.0.0 + css-frameworks: 1.0.1 + data-mvc: 0.0.2 + datetime: 6.1.0 + datetime-parsing: 0.2.0 + debug: 6.0.2 + decimals: 7.1.0 + default-values: 1.0.1 + deku: 0.9.23 + deno: 0.0.5 + dissect: 1.0.0 + distributive: 6.0.0 + dom-filereader: 7.0.0 + dom-indexed: 12.0.0 + dotenv: 4.0.3 + droplet: 0.6.0 + dts: 0.2.0 + dual-numbers: 1.0.2 + dynamic-buffer: 3.0.1 + echarts-simple: 0.0.1 + effect: 4.0.0 + either: 6.1.0 + elmish: 0.10.0 + elmish-enzyme: 0.1.1 + elmish-hooks: 0.10.0 + elmish-html: 0.8.1 + elmish-testing-library: 0.3.1 + email-validate: 7.0.0 + encoding: 0.0.8 + enums: 6.0.1 + env-names: 0.3.4 + error: 2.0.0 + exceptions: 6.0.0 + exists: 6.0.0 + exitcodes: 4.0.0 + expect-inferred: 3.0.0 + fahrtwind: 2.0.0 + fallback: 0.1.0 + fast-vect: 1.1.0 + fetch: 4.0.0 + fetch-argonaut: 1.0.1 + fetch-core: 5.1.0 + fetch-yoga-json: 1.1.0 + filterable: 5.0.0 + fix-functor: 0.1.0 + fixed-points: 7.0.0 + fixed-precision: 5.0.0 + flame: 1.3.0 + float32: 2.0.0 + fmt: 0.2.1 + foldable-traversable: 6.0.0 + foreign: 7.0.0 + foreign-object: 4.1.0 + foreign-readwrite: 3.4.0 + forgetmenot: 0.1.0 + fork: 6.0.0 + form-urlencoded: 7.0.0 + formatters: 7.0.0 + framer-motion: 1.0.1 + free: 7.1.0 + freeap: 7.0.0 + freer-free: 0.0.1 + freet: 7.0.0 + functions: 6.0.0 + functor1: 3.0.0 + functors: 5.0.0 + fuzzy: 0.4.0 + gen: 4.0.0 + generate-values: 1.0.1 + generic-router: 0.0.1 + geojson: 0.0.5 + geometry-plane: 1.0.3 + grain: 3.0.0 + grain-router: 3.0.0 + grain-virtualized: 3.0.0 + graphs: 8.1.0 + group: 4.1.1 + halogen: 7.0.0 + halogen-bootstrap5: 2.2.0 + halogen-css: 10.0.0 + halogen-echarts-simple: 0.0.4 + halogen-formless: 4.0.3 + halogen-helix: 1.0.0 + halogen-hooks: 0.6.3 + halogen-hooks-extra: 0.9.0 + halogen-store: 0.5.4 + halogen-storybook: 2.0.0 + halogen-subscriptions: 2.0.0 + halogen-svg-elems: 8.0.0 + halogen-typewriter: 1.0.2 + halogen-vdom: 8.0.0 + halogen-vdom-string-renderer: 0.5.0 + heckin: 2.0.1 + heterogeneous: 0.6.0 + homogeneous: 0.4.0 + http-methods: 6.0.0 + httpurple: 4.0.0 + humdrum: 0.0.1 + hyrule: 2.3.8 + identity: 6.0.0 + identy: 4.0.1 + indexed-db: 1.0.0 + indexed-monad: 3.0.0 + int64: 3.0.0 + integers: 6.0.0 + interpolate: 5.0.2 + invariant: 6.0.0 + jarilo: 1.0.1 + jelly: 0.10.0 + jelly-router: 0.3.0 + jelly-signal: 0.4.0 + jest: 1.0.0 + js-abort-controller: 1.0.0 + js-bigints: 2.2.1 + js-date: 8.0.0 + js-fetch: 0.2.1 + js-fileio: 3.0.0 + js-intl: 1.0.4 + js-iterators: 0.1.1 + js-maps: 0.1.2 + js-promise: 1.0.0 + js-promise-aff: 1.0.0 + js-timers: 6.1.0 + js-uri: 3.1.0 + json: 1.0.0 + json-codecs: 5.0.0 + justifill: 0.5.0 + jwt: 0.0.9 + labeled-data: 0.2.0 + lazy: 6.0.0 + lazy-joe: 1.0.0 + lcg: 4.0.0 + leibniz: 5.0.0 + liminal: 1.0.1 + linalg: 6.0.0 + lists: 7.0.0 + literals: 1.0.2 + logging: 3.0.0 + logging-journald: 0.4.0 + lumi-components: 18.0.0 + machines: 7.0.0 + maps-eager: 0.4.1 + marionette: 1.0.0 + marionette-react-basic-hooks: 0.1.1 + matrices: 5.0.1 + matryoshka: 1.0.0 + maybe: 6.0.0 + media-types: 6.0.0 + midi: 4.0.0 + milkis: 9.0.0 + minibench: 4.0.1 + mmorph: 7.0.0 + monad-control: 5.0.0 + monad-logger: 1.3.1 + monad-loops: 0.5.0 + monad-unlift: 1.0.1 + monoid-extras: 0.0.1 + monoidal: 0.16.0 + morello: 0.4.0 + mote: 3.0.0 + motsunabe: 2.0.0 + mvc: 0.0.1 + mysql: 6.0.1 + n3: 0.1.0 + nano-id: 1.1.0 + nanoid: 0.1.0 + naturals: 3.0.0 + nested-functor: 0.2.1 + newtype: 5.0.0 + nextjs: 0.1.1 + nextui: 0.2.0 + node-buffer: 9.0.0 + node-child-process: 11.1.0 + node-event-emitter: 3.0.0 + node-execa: 5.0.0 + node-fs: 9.1.0 + node-http: 9.1.0 + node-http2: 1.1.1 + node-human-signals: 1.0.0 + node-net: 5.1.0 + node-os: 5.1.0 + node-path: 5.0.0 + node-process: 11.2.0 + node-readline: 8.1.0 + node-sqlite3: 8.0.0 + node-streams: 9.0.0 + node-tls: 0.3.1 + node-url: 7.0.1 + node-zlib: 0.4.0 + nonempty: 7.0.0 + now: 6.0.0 + npm-package-json: 2.0.0 + nullable: 6.0.0 + numberfield: 0.1.0 + numbers: 9.0.1 + oak: 3.1.1 + oak-debug: 1.2.2 + object-maps: 0.3.0 + ocarina: 1.5.4 + open-folds: 6.3.0 + open-memoize: 6.1.0 + open-pairing: 6.1.0 + options: 7.0.0 + ordered-collections: 3.1.1 + ordered-set: 0.4.0 + orders: 6.0.0 + pairs: 9.0.1 + parallel: 7.0.0 + parsing: 10.2.0 + parsing-dataview: 3.2.4 + partial: 4.0.0 + pathy: 9.0.0 + pha: 0.13.0 + phaser: 0.7.0 + phylio: 1.1.2 + pipes: 8.0.0 + pirates-charm: 0.0.1 + pmock: 0.6.0 + point-free: 1.0.0 + pointed-list: 0.5.1 + polymorphic-vectors: 4.0.0 + posix-types: 6.0.0 + precise: 6.0.0 + precise-datetime: 7.0.0 + prelude: 6.0.1 + prettier-printer: 3.0.0 + profunctor: 6.0.0 + profunctor-lenses: 8.0.0 + protobuf: 4.3.0 + psa-utils: 8.0.0 + psci-support: 6.0.0 + qualified-do: 2.2.0 + quantities: 12.2.0 + quickcheck: 8.0.1 + quickcheck-combinators: 0.1.3 + quickcheck-laws: 7.0.0 + quickcheck-utf8: 0.0.0 + random: 6.0.0 + rationals: 6.0.0 + rdf: 0.1.0 + react: 11.0.0 + react-aria: 0.2.0 + react-basic: 17.0.0 + react-basic-classic: 3.0.0 + react-basic-dnd: 10.1.0 + react-basic-dom: 6.1.0 + react-basic-emotion: 7.1.0 + react-basic-hooks: 8.2.0 + react-basic-storybook: 2.0.0 + react-dom: 8.0.0 + react-halo: 3.0.0 + react-icons: 1.1.2 + react-markdown: 0.1.0 + react-testing-library: 4.0.1 + react-virtuoso: 1.0.0 + read: 1.0.1 + recharts: 1.1.0 + record: 4.0.0 + record-extra: 5.0.1 + record-studio: 1.0.4 + refs: 6.0.0 + remotedata: 5.0.0 + resource: 2.0.1 + resourcet: 1.0.0 + result: 1.0.3 + return: 0.2.0 + ring-modules: 5.0.1 + rito: 0.3.4 + routing: 11.0.0 + routing-duplex: 0.7.0 + run: 5.0.0 + safe-coerce: 2.0.0 + safely: 4.0.1 + school-of-music: 1.3.0 + selection-foldable: 0.2.0 + selective-functors: 1.0.1 + semirings: 7.0.0 + signal: 13.0.0 + simple-emitter: 3.0.1 + simple-i18n: 2.0.1 + simple-json: 9.0.0 + simple-ulid: 3.0.0 + sized-matrices: 1.0.0 + sized-vectors: 5.0.2 + slug: 3.0.8 + small-ffi: 4.0.1 + soundfonts: 4.1.0 + sparse-matrices: 1.3.0 + sparse-polynomials: 2.0.5 + spec: 7.5.5 + spec-mocha: 5.0.0 + spec-quickcheck: 5.0.0 + splitmix: 2.1.0 + ssrs: 1.0.0 + st: 6.2.0 + statistics: 0.3.2 + strictlypositiveint: 1.0.1 + string-parsers: 8.0.0 + strings: 6.0.1 + strings-extra: 4.0.0 + stringutils: 0.0.12 + substitute: 0.2.3 + supply: 0.2.0 + svg-parser: 3.0.0 + systemd-journald: 0.3.0 + tagged: 4.0.2 + tailrec: 6.1.0 + tecton: 0.2.1 + tecton-halogen: 0.2.0 + test-unit: 17.0.0 + thermite: 6.3.1 + thermite-dom: 0.3.1 + these: 6.0.0 + transformation-matrix: 1.0.1 + transformers: 6.0.0 + tree-rose: 4.0.2 + ts-bridge: 2.2.0 + tuples: 7.0.0 + two-or-more: 1.0.0 + type-equality: 4.0.1 + typedenv: 2.0.1 + typelevel: 6.0.0 + typelevel-lists: 2.1.0 + typelevel-peano: 1.0.1 + typelevel-prelude: 7.0.0 + typelevel-regex: 0.0.3 + typelevel-rows: 0.1.0 + uint: 7.0.0 + ulid: 3.0.1 + uncurried-transformers: 1.1.0 + undefined: 2.0.0 + undefined-is-not-a-problem: 1.1.0 + unfoldable: 6.0.0 + unicode: 6.0.0 + unique: 0.6.1 + unlift: 1.0.1 + unordered-collections: 3.0.1 + unsafe-coerce: 6.0.0 + unsafe-reference: 5.0.0 + untagged-to-tagged: 0.1.4 + untagged-union: 1.0.0 + uri: 9.0.0 + uuid: 9.0.0 + uuidv4: 1.0.0 + validation: 6.0.0 + variant: 8.0.0 + variant-encodings: 2.0.0 + vectorfield: 1.0.1 + vectors: 2.1.0 + versions: 7.0.0 + visx: 0.0.2 + web-clipboard: 5.0.0 + web-cssom: 2.0.0 + web-cssom-view: 0.1.0 + web-dom: 6.0.0 + web-dom-parser: 8.0.0 + web-dom-xpath: 3.0.0 + web-encoding: 3.0.0 + web-events: 4.0.0 + web-fetch: 4.0.1 + web-file: 4.0.0 + web-geometry: 0.1.0 + web-html: 4.1.0 + web-pointerevents: 2.0.0 + web-proletarian: 1.0.0 + web-promise: 3.2.0 + web-resize-observer: 2.0.0 + web-router: 1.0.0 + web-socket: 4.0.0 + web-storage: 5.0.0 + web-streams: 4.0.0 + web-touchevents: 4.0.0 + web-uievents: 5.0.0 + web-url: 2.0.0 + web-workers: 1.1.0 + web-xhr: 5.0.1 + webextension-polyfill: 0.1.0 + webgpu: 0.0.1 + which: 2.0.0 + yoga-fetch: 1.0.1 + yoga-json: 5.1.0 + yoga-om: 0.1.0 + yoga-postgres: 6.0.0 + yoga-tree: 1.0.0 + z3: 0.0.2 extra_packages: dodo-printer: git: https://github.com/natefaubion/purescript-dodo-printer.git @@ -242,7 +1298,6 @@ workspace: - effect - foldable-traversable - prelude - - psci-support json-codecs: 4.0.0 language-cst-parser: git: https://github.com/natefaubion/purescript-language-cst-parser.git diff --git a/spago.yaml b/spago.yaml index d214a3c48..7e7af4890 100644 --- a/spago.yaml +++ b/spago.yaml @@ -1,11 +1,16 @@ package: name: spago publish: - version: 0.93.19 + version: 0.93.22 license: BSD-3-Clause location: githubOwner: purescript githubRepo: spago + build: + strict: true + censor_project_warnings: + - WildcardInferredType + - ImplicitQualifiedImportReExport dependencies: - aff - affjax @@ -49,16 +54,12 @@ package: - unsafe-coerce test: main: Test.Spago + censor_test_warnings: + - ImplicitQualifiedImportReExport + - ImplicitQualifiedImport dependencies: - spec workspace: - build_opts: - strict: false - censor_warnings: project - censor_codes: - - ImplicitQualifiedImportReExport - - ImplicitQualifiedImport - lock: true package_set: registry: 46.0.0 extra_packages: @@ -83,7 +84,6 @@ workspace: - effect - foldable-traversable - prelude - - psci-support git: https://github.com/nonbili/purescript-jest.git ref: caf2032f2e5828337e897a99f5359c00e91cb0ee language-purescript: diff --git a/src/Spago/Command/Build.purs b/src/Spago/Command/Build.purs index f10f51350..bde0cb327 100644 --- a/src/Spago/Command/Build.purs +++ b/src/Spago/Command/Build.purs @@ -42,7 +42,7 @@ type BuildOptions = , jsonErrors :: Boolean } -run :: forall a. BuildOptions -> Spago (BuildEnv a) Unit +run :: BuildOptions -> Spago (BuildEnv _) Unit run opts = do logInfo "Building..." { dependencies diff --git a/src/Spago/Command/Docs.purs b/src/Spago/Command/Docs.purs index bb9ca1447..8c6063bd7 100644 --- a/src/Spago/Command/Docs.purs +++ b/src/Spago/Command/Docs.purs @@ -19,7 +19,7 @@ import Spago.Config as Config import Spago.Purs (Purs, DocsFormat(..)) import Spago.Purs as Purs -type DocsEnv = +type DocsEnv a = { purs :: Purs , workspace :: Workspace , dependencies :: Fetch.PackageTransitiveDeps @@ -27,9 +27,10 @@ type DocsEnv = , docsFormat :: DocsFormat , depsOnly :: Boolean , open :: Boolean + | a } -run :: Spago DocsEnv Unit +run :: Spago (DocsEnv _) Unit run = do logDebug "Running `spago docs`" logInfo "Generating documentation for the project. This might take a while..." diff --git a/src/Spago/Command/Fetch.purs b/src/Spago/Command/Fetch.purs index 5dec62b3b..b9e064483 100644 --- a/src/Spago/Command/Fetch.purs +++ b/src/Spago/Command/Fetch.purs @@ -8,6 +8,7 @@ module Spago.Command.Fetch , getTransitiveDeps , getTransitiveDepsFromRegistry , run + , writeNewLockfile ) where import Spago.Prelude @@ -17,12 +18,16 @@ import Affjax.ResponseFormat as Response import Affjax.StatusCode (StatusCode(..)) import Control.Monad.State as State import Data.Array as Array +import Data.Array.NonEmpty as NEA import Data.Codec.Argonaut as CA +import Data.Codec.Argonaut.Common as CA.Common import Data.Either as Either import Data.HTTP.Method as Method import Data.Int as Int import Data.Map as Map +import Data.Newtype (wrap) import Data.Set as Set +import Data.Traversable (sequence) import Effect.Ref as Ref import Node.Buffer as Buffer import Node.Encoding as Encoding @@ -35,7 +40,7 @@ import Registry.Sha256 as Sha256 import Registry.Solver as Registry.Solver import Registry.Version as Registry.Version import Registry.Version as Version -import Spago.Config (Dependencies(..), GitPackage, LockfileSettings(..), Package(..), PackageMap, PackageSet(..), Workspace, WorkspacePackage) +import Spago.Config (BuildType(..), Dependencies(..), GitPackage, Package(..), PackageMap, Workspace, WorkspacePackage) import Spago.Config as Config import Spago.Db as Db import Spago.FS as FS @@ -44,14 +49,14 @@ import Spago.Lock (LockEntry(..)) import Spago.Lock as Lock import Spago.Paths as Paths import Spago.Purs as Purs +import Spago.Registry as Registry import Spago.Repl as Repl import Spago.Tar as Tar type PackageTransitiveDeps = Map PackageName PackageMap type FetchEnvRow a = - ( getManifestFromIndex :: PackageName -> Version -> Spago (LogEnv ()) (Maybe Manifest) - , getMetadata :: PackageName -> Spago (LogEnv ()) (Either String Metadata) + ( getRegistry :: Spago (Registry.PreRegistryEnv ()) Registry.RegistryFunctions , workspace :: Workspace , logOptions :: LogOptions , offline :: OnlineStatus @@ -67,216 +72,265 @@ type FetchOpts = { packages :: Array PackageName , ensureRanges :: Boolean , isTest :: Boolean + , isRepl :: Boolean } -run - :: forall a - . FetchOpts - -> Spago (FetchEnv a) PackageTransitiveDeps -run { packages: packagesToInstall, ensureRanges, isTest } = do - logDebug $ "Requested to install these packages: " <> printJson (CA.array PackageName.codec) packagesToInstall +run :: forall a. FetchOpts -> Spago (FetchEnv a) PackageTransitiveDeps +run { packages: packagesRequestedToInstall, ensureRanges, isTest, isRepl } = do + logDebug $ "Requested to install these packages: " <> printJson (CA.array PackageName.codec) packagesRequestedToInstall - { getMetadata, logOptions, workspace, offline } <- ask - - let - installingPackages = not $ Array.null packagesToInstall - - getSelectedPackageTransitiveDeps :: WorkspacePackage -> Spago (FetchEnv a) PackageMap - getSelectedPackageTransitiveDeps selected = - getTransitiveDeps $ getWorkspacePackageDeps selected <> Dependencies (Map.fromFoldable $ map (_ /\ Nothing) packagesToInstall) - - -- lookup the dependencies in the package set, so we get their version numbers. - { dependencies, transitiveDeps } <- case workspace.selected of - Just (selected :: WorkspacePackage) -> do - transitiveDeps <- getSelectedPackageTransitiveDeps selected - pure - { dependencies: Map.singleton selected.package.name transitiveDeps - , transitiveDeps - } - Nothing -> do - dependencies <- traverse getTransitiveDeps - $ Map.fromFoldable - $ map (\p -> Tuple p.package.name (getWorkspacePackageDeps p)) - $ Config.getWorkspacePackages workspace.packageSet - pure - { dependencies - , transitiveDeps: toAllDependencies dependencies - } + { workspace: currentWorkspace, offline } <- ask let getPackageConfigPath errorMessageEnd = do - case workspace.selected of + case currentWorkspace.selected of Just { path, doc, package } -> pure { configPath: Path.concat [ path, "spago.yaml" ], yamlDoc: doc, package } - Nothing -> case workspace.rootPackage of - Just rootPackage -> do pure { configPath: "spago.yaml", yamlDoc: workspace.doc, package: rootPackage } + Nothing -> case currentWorkspace.rootPackage of + Just rootPackage -> do pure { configPath: "spago.yaml", yamlDoc: currentWorkspace.doc, package: rootPackage } Nothing -> die [ "No package found in the root configuration." , "Please use the `-p` flag to select a package " <> errorMessageEnd ] - -- write to the config file if we are adding new packages - when installingPackages do - { configPath, package, yamlDoc } <- getPackageConfigPath "to install your packages in." - let packageDependencies = Map.keys $ unwrap package.dependencies - -- Prevent users from installing a circular dependency - let packages = Array.filter (\p -> p /= package.name) packagesToInstall - let overlappingPackages = Set.intersection packageDependencies (Set.fromFoldable packages) - unless (Set.isEmpty overlappingPackages) do - logWarn - $ [ toDoc "You tried to install some packages that are already present in the configuration, proceeding anyways:" ] - <> map (indent <<< toDoc <<< append "- " <<< PackageName.print) (Array.fromFoldable overlappingPackages) - logInfo $ "Adding " <> show (Array.length packages) <> " packages to the config in " <> configPath - liftEffect $ Config.addPackagesToConfig yamlDoc isTest packages - liftAff $ FS.writeYamlDocFile configPath yamlDoc - - -- if the flag is selected, we kick off the process of adding ranges to the config - when ensureRanges do - { configPath, package, yamlDoc } <- getPackageConfigPath "in which to add ranges." - logInfo $ "Adding ranges to dependencies to the config in " <> configPath - packageDeps <- (Map.lookup package.name dependencies) `justOrDieWith` - "Impossible: package dependencies must be in dependencies map" - let rangeMap = map getRangeFromPackage packageDeps - liftEffect $ Config.addRangesToConfig yamlDoc rangeMap - liftAff $ FS.writeYamlDocFile configPath yamlDoc - - -- TODO: need to be careful about what happens when we select a single package vs the whole workspace - -- because otherwise the lockfile will be partial. - -- Most likely we'll want to first figure out if we want a new lockfile at all, - -- then possibly resolve all the packages anyways, then resolve the ones for a single package - -- (which comes for free at that point since the cache is already populated) - lockfile <- do - let - fromWorkspacePackage :: WorkspacePackage -> Tuple PackageName Lock.WorkspaceLockPackage - fromWorkspacePackage { path, package } = Tuple package.name - { path - , dependencies: package.dependencies - , test_dependencies: foldMap _.dependencies package.test - } + installingPackagesData <- do + case Array.null packagesRequestedToInstall of + true -> pure Nothing + false -> do + { configPath, package, yamlDoc } <- getPackageConfigPath "to install your packages in." + currentWorkspacePackage <- NEA.find (\p -> p.package.name == package.name) (Config.getWorkspacePackages currentWorkspace.packageSet) `justOrDieWith` "Impossible: package must be in workspace packages" + let + packageDependencies = Map.keys $ case isTest of + false -> unwrap package.dependencies + true -> unwrap $ maybe mempty _.dependencies package.test + -- Prevent users from installing a circular dependency + packages = Array.filter (\p -> p /= package.name) packagesRequestedToInstall + overlappingPackages = Set.intersection packageDependencies (Set.fromFoldable packages) + actualPackagesToInstall = Array.filter (\p -> not $ Set.member p overlappingPackages) packages + newPackageDependencies = wrap $ Map.fromFoldable $ map (\p -> Tuple p Nothing) actualPackagesToInstall + newWorkspacePackage = case isTest of + false -> currentWorkspacePackage { package { dependencies = package.dependencies <> newPackageDependencies } } + true -> currentWorkspacePackage { package { test = package.test # map (\t -> t { dependencies = t.dependencies <> newPackageDependencies }) } } + logDebug $ "Overlapping packages: " <> printJson (CA.Common.set PackageName.codec) overlappingPackages + logDebug $ "Actual packages to install: " <> printJson (CA.array PackageName.codec) actualPackagesToInstall + -- If we are installing new packages, we need to add them to the config + -- We also warn the user if they are already present in the config + unless (Set.isEmpty overlappingPackages) do + logWarn + $ [ toDoc "You tried to install some packages that are already present in the configuration, proceeding anyways:" ] + <> map (indent <<< toDoc <<< append "- " <<< PackageName.print) (Array.fromFoldable overlappingPackages) + case Array.null actualPackagesToInstall of + true -> pure Nothing + false -> do + logDebug $ "Packages to install: " <> printJson (CA.array PackageName.codec) actualPackagesToInstall + pure $ Just { configPath, yamlDoc, actualPackagesToInstall, newWorkspacePackage } - lockfileWorkspace :: Lock.WorkspaceLock - lockfileWorkspace = - { package_set: workspace.workspaceConfig.package_set - , packages: Map.fromFoldable - $ map fromWorkspacePackage (Config.getWorkspacePackages workspace.packageSet) - , extra_packages: fromMaybe Map.empty workspace.workspaceConfig.extra_packages + let + -- If we need to install new packages then we need to zero the current lockfile, we're going to need a new one + workspace = case installingPackagesData of + Nothing -> currentWorkspace + Just { newWorkspacePackage } -> currentWorkspace + { packageSet = currentWorkspace.packageSet + { lockfile = Left "Lockfile is out of date (installing new packages)" + -- If we are installing packages, we need to add the new deps to the selected package + , buildType = case currentWorkspace.packageSet.buildType of + RegistrySolverBuild packageMap -> RegistrySolverBuild $ Map.insert newWorkspacePackage.package.name (WorkspacePackage newWorkspacePackage) packageMap + PackageSetBuild info packageMap -> PackageSetBuild info $ Map.insert newWorkspacePackage.package.name (WorkspacePackage newWorkspacePackage) packageMap + } + , selected = Just newWorkspacePackage } - (lockfilePackages :: Map PackageName Lock.LockEntry) <- Map.catMaybes <$> - forWithIndex transitiveDeps \packageName package -> do - (packageDependencies :: Array PackageName) <- (Array.fromFoldable <<< Map.keys <<< fromMaybe Map.empty) - <$> getPackageDependencies packageName package - case package of - GitPackage gitPackage -> do - let packageLocation = Config.getPackageLocation packageName package - Git.getRef (Just packageLocation) >>= case _ of - Left err -> die err - Right rev -> pure $ Just $ FromGit { rev, dependencies: packageDependencies, url: gitPackage.git, subdir: gitPackage.subdir } - RegistryVersion version -> do - metadata <- runSpago { logOptions } $ getMetadata packageName - registryVersion <- case (metadata >>= (\(Metadata meta) -> Either.note "Didn't find version in the metadata file" $ Map.lookup version meta.published)) of - Left err -> die $ "Couldn't read metadata, reason:\n " <> err - Right { hash: integrity } -> - pure { version, integrity, dependencies: packageDependencies } - pure $ Just $ FromRegistry registryVersion - LocalPackage { path } -> pure $ Just (FromPath { path, dependencies: packageDependencies }) - WorkspacePackage _ -> pure $ Nothing - - pure { workspace: lockfileWorkspace, packages: lockfilePackages } + local (_ { workspace = workspace }) do + -- We compute the transitive deps for all the packages in the workspace, but keep them + -- split by package - we need all of them so we can stash them in the lockfile, but we + -- are going to only download the ones that we need to, if e.g. there's a package selected + dependencies <- traverse getTransitiveDeps + $ Map.fromFoldable + $ map (\p -> Tuple p.package.name p) + $ Config.getWorkspacePackages workspace.packageSet + + case installingPackagesData of + Nothing -> pure unit + Just { configPath, yamlDoc, actualPackagesToInstall } -> do + let + countString = case Array.length actualPackagesToInstall of + 1 -> "1 package" + n -> show n <> " packages" + logInfo $ "Adding " <> countString <> " to the config in " <> configPath + liftAff $ Config.addPackagesToConfig configPath yamlDoc isTest actualPackagesToInstall + + -- if the flag is selected, we kick off the process of adding ranges to the config + when ensureRanges do + { configPath, package, yamlDoc } <- getPackageConfigPath "in which to add ranges." + logInfo $ "Adding ranges to dependencies to the config in " <> configPath + packageDeps <- (Map.lookup package.name dependencies) `justOrDieWith` + "Impossible: package dependencies must be in dependencies map" + let rangeMap = map getRangeFromPackage packageDeps + liftEffect $ Config.addRangesToConfig yamlDoc rangeMap + liftAff $ FS.writeYamlDocFile configPath yamlDoc + + -- the repl needs a support package, so we add it here as a sidecar + supportPackage <- Repl.supportPackage workspace.packageSet + let + allTransitiveDeps = case isRepl of + false -> dependencies + true -> map (\packageMap -> Map.union packageMap supportPackage) dependencies + depsToFetch <- case workspace.selected of + Nothing -> pure (toAllDependencies allTransitiveDeps) + -- If there's a package selected, we only fetch the transitive deps for that one + Just p -> case Map.lookup p.package.name dependencies of + Nothing -> die "Impossible: package dependencies must be in dependencies map" + Just deps -> pure $ Map.union deps if isRepl then supportPackage else Map.empty + + case workspace.packageSet.lockfile of + Right _lockfile -> pure unit + Left reason -> writeNewLockfile reason allTransitiveDeps + + -- then for every package we have we try to download it, and copy it in the local cache + logInfo "Downloading dependencies..." + + parallelise $ (flip map) (Map.toUnfoldable depsToFetch :: Array (Tuple PackageName Package)) \(Tuple name package) -> do + let localPackageLocation = Config.getPackageLocation name package + -- first of all, we check if we have the package in the local cache. If so, we don't even do the work + unlessM (FS.exists localPackageLocation) case package of + GitPackage gitPackage -> getGitPackageInLocalCache name gitPackage + RegistryVersion v -> do + -- if the version comes from the registry then we have a longer list of things to do + let versionString = Registry.Version.print v + let packageVersion = PackageName.print name <> "@" <> versionString + -- get the metadata for the package, so we have access to the hash and other info + metadata <- Registry.getMetadata name + case (metadata >>= (\(Metadata meta) -> Either.note "Didn't find version in the metadata file" $ Map.lookup v meta.published)) of + Left err -> die $ "Couldn't read metadata, reason:\n " <> err + Right versionMetadata -> do + logDebug $ "Metadata read: " <> printJson Metadata.publishedMetadataCodec versionMetadata + -- then check if we have a tarball cached. If not, download it + let globalCachePackagePath = Path.concat [ Paths.globalCachePath, "packages", PackageName.print name ] + let archivePath = Path.concat [ globalCachePackagePath, versionString <> ".tar.gz" ] + FS.mkdirp globalCachePackagePath + -- We need to see if the tarball is there, and if we can decompress it. + -- This is because if Spago is killed while it's writing the tar, then it might leave it corrupted. + -- By checking that it's broken we can try to redownload it here. + tarExists <- FS.exists archivePath + -- unpack the tars in a temp folder, then move to local cache + let tarInnerFolder = PackageName.print name <> "-" <> Version.print v + tempDir <- mkTemp + FS.mkdirp tempDir + tarIsGood <- + if tarExists then do + logDebug $ "Trying to unpack archive to temp folder: " <> tempDir + map (either (const false) (const true)) $ liftEffect $ Tar.extract { filename: archivePath, cwd: tempDir } + else + pure false + case tarExists, tarIsGood, offline of + true, true, _ -> pure unit -- Tar exists and is good, and we already unpacked it. Happy days! + _, _, Offline -> die $ "Package " <> packageVersion <> " is not in the local cache, and Spago is running in offline mode - can't make progress." + _, _, Online -> do + let packageUrl = "https://packages.registry.purescript.org/" <> PackageName.print name <> "/" <> versionString <> ".tar.gz" + logInfo $ "Fetching package " <> packageVersion + response <- liftAff $ withBackoff' $ Http.request + ( Http.defaultRequest + { method = Left Method.GET + , responseFormat = Response.arrayBuffer + , url = packageUrl + } + ) + case response of + Nothing -> die $ "Couldn't reach the registry at " <> packageUrl + Just (Left err) -> die $ "Couldn't fetch package " <> packageVersion <> ":\n " <> Http.printError err + Just (Right { status, body }) | status /= StatusCode 200 -> do + (buf :: Buffer) <- liftEffect $ Buffer.fromArrayBuffer body + bodyString <- liftEffect $ Buffer.toString Encoding.UTF8 buf + die $ "Couldn't fetch package " <> packageVersion <> ", status was not ok " <> show status <> ", got answer:\n " <> bodyString + Just (Right r@{ body: archiveArrayBuffer }) -> do + logDebug $ "Got status: " <> show r.status + -- check the size and hash of the tar against the metadata + archiveBuffer <- liftEffect $ Buffer.fromArrayBuffer archiveArrayBuffer + archiveSize <- liftEffect $ Buffer.size archiveBuffer + archiveSha <- liftEffect $ Sha256.hashBuffer archiveBuffer + unless (Int.toNumber archiveSize == versionMetadata.bytes) do + die $ "Archive fetched for " <> packageVersion <> " has a different size (" <> show archiveSize <> ") than expected (" <> show versionMetadata.bytes <> ")" + unless (archiveSha == versionMetadata.hash) do + die $ "Archive fetched for " <> packageVersion <> " has a different hash (" <> Sha256.print archiveSha <> ") than expected (" <> Sha256.print versionMetadata.hash <> ")" + -- if everything's alright we stash the tar in the global cache + logDebug $ "Fetched archive for " <> packageVersion <> ", saving it in the global cache: " <> archivePath + FS.writeFile archivePath archiveBuffer + logDebug $ "Unpacking archive to temp folder: " <> tempDir + (liftEffect $ Tar.extract { filename: archivePath, cwd: tempDir }) >>= case _ of + Right _ -> pure unit + Left err -> die [ "Failed to decode downloaded package " <> packageVersion <> ", error:", show err ] + logDebug $ "Moving extracted file to local cache:" <> localPackageLocation + FS.moveSync { src: (Path.concat [ tempDir, tarInnerFolder ]), dst: localPackageLocation } + -- Local package, no work to be done + LocalPackage _ -> pure unit + WorkspacePackage _ -> pure unit + + pure dependencies + +type LockfileBuilderResult = + { workspacePackages :: Map PackageName Lock.WorkspaceLockPackage + , packages :: Map PackageName Lock.LockEntry + } + +writeNewLockfile :: forall a. String -> PackageTransitiveDeps -> Spago (FetchEnv a) Unit +writeNewLockfile reason allTransitiveDeps = do + logInfo $ reason <> ", generating it..." + { workspace } <- ask + let + processPackage :: LockfileBuilderResult -> Tuple PackageName (Tuple PackageName Package) -> Spago (FetchEnv a) LockfileBuilderResult + processPackage result (Tuple workspacePackageName (Tuple dependencyName dependencyPackage)) = do + (packageDependencies :: Array PackageName) <- (Array.fromFoldable <<< Map.keys <<< fromMaybe Map.empty) + <$> getPackageDependencies dependencyName dependencyPackage + let + updatePackage r package = (updateWorkspacePackage r) + { packages = Map.insert dependencyName package r.packages } + updateWorkspacePackage r = r + { workspacePackages = Map.alter + ( case _ of + Nothing -> Nothing + Just pkg -> Just $ pkg { build_plan = Set.insert dependencyName (pkg.build_plan) } + ) + workspacePackageName + r.workspacePackages + } + + case dependencyPackage of + WorkspacePackage _pkg -> pure $ updateWorkspacePackage result + GitPackage gitPackage -> do + let packageLocation = Config.getPackageLocation dependencyName dependencyPackage + Git.getRef (Just packageLocation) >>= case _ of + Left err -> die err -- TODO maybe not die here? + Right rev -> pure $ updatePackage result $ FromGit { rev, dependencies: packageDependencies, url: gitPackage.git, subdir: gitPackage.subdir } + RegistryVersion version -> do + metadata <- Registry.getMetadata dependencyName + registryVersion <- case (metadata >>= (\(Metadata meta) -> Either.note "Didn't find version in the metadata file" $ Map.lookup version meta.published)) of + Left err -> die $ "Couldn't read metadata, reason:\n " <> err + Right { hash: integrity } -> + pure { version, integrity, dependencies: packageDependencies } + pure $ updatePackage result $ FromRegistry registryVersion + LocalPackage { path } -> do + pure $ updatePackage result $ FromPath { path, dependencies: packageDependencies } let - shouldWriteLockFile = case workspace.selected, workspace.lockfile of - Nothing, GenerateLockfile -> true - Nothing, (UseLockfile _) -> true - _, _ -> false - - when shouldWriteLockFile do - logInfo "Writing a new lockfile" - liftAff $ FS.writeYamlFile Lock.lockfileCodec "spago.lock" lockfile - - -- then for every package we have we try to download it, and copy it in the local cache - logInfo "Downloading dependencies..." - - -- the repl needs a support package, so we fetch it here as a sidecar - supportPackage <- Repl.supportPackage workspace.packageSet - let transitiveDeps' = Map.union transitiveDeps supportPackage - - parallelise $ (flip map) (Map.toUnfoldable transitiveDeps' :: Array (Tuple PackageName Package)) \(Tuple name package) -> do - let localPackageLocation = Config.getPackageLocation name package - -- first of all, we check if we have the package in the local cache. If so, we don't even do the work - unlessM (FS.exists localPackageLocation) case package of - GitPackage gitPackage -> getGitPackageInLocalCache name gitPackage - RegistryVersion v -> do - -- if the version comes from the registry then we have a longer list of things to do - let versionString = Registry.Version.print v - let packageVersion = PackageName.print name <> "@" <> versionString - -- get the metadata for the package, so we have access to the hash and other info - metadata <- runSpago { logOptions } $ getMetadata name - case (metadata >>= (\(Metadata meta) -> Either.note "Didn't find version in the metadata file" $ Map.lookup v meta.published)) of - Left err -> die $ "Couldn't read metadata, reason:\n " <> err - Right versionMetadata -> do - logDebug $ "Metadata read: " <> printJson Metadata.publishedMetadataCodec versionMetadata - -- then check if we have a tarball cached. If not, download it - let globalCachePackagePath = Path.concat [ Paths.globalCachePath, "packages", PackageName.print name ] - let archivePath = Path.concat [ globalCachePackagePath, versionString <> ".tar.gz" ] - FS.mkdirp globalCachePackagePath - -- We need to see if the tarball is there, and if we can decompress it. - -- This is because if Spago is killed while it's writing the tar, then it might leave it corrupted. - -- By checking that it's broken we can try to redownload it here. - tarExists <- FS.exists archivePath - -- unpack the tars in a temp folder, then move to local cache - let tarInnerFolder = PackageName.print name <> "-" <> Version.print v - tempDir <- mkTemp - FS.mkdirp tempDir - tarIsGood <- - if tarExists then do - logDebug $ "Trying to unpack archive to temp folder: " <> tempDir - map (either (const false) (const true)) $ liftEffect $ Tar.extract { filename: archivePath, cwd: tempDir } - else - pure false - case tarExists, tarIsGood, offline of - true, true, _ -> pure unit -- Tar exists and is good, and we already unpacked it. Happy days! - _, _, Offline -> die $ "Package " <> packageVersion <> " is not in the local cache, and Spago is running in offline mode - can't make progress." - _, _, Online -> do - let packageUrl = "https://packages.registry.purescript.org/" <> PackageName.print name <> "/" <> versionString <> ".tar.gz" - logInfo $ "Fetching package " <> packageVersion - response <- liftAff $ withBackoff' $ Http.request - ( Http.defaultRequest - { method = Left Method.GET - , responseFormat = Response.arrayBuffer - , url = packageUrl - } - ) - case response of - Nothing -> die $ "Couldn't reach the registry at " <> packageUrl - Just (Left err) -> die $ "Couldn't fetch package " <> packageVersion <> ":\n " <> Http.printError err - Just (Right { status, body }) | status /= StatusCode 200 -> do - (buf :: Buffer) <- liftEffect $ Buffer.fromArrayBuffer body - bodyString <- liftEffect $ Buffer.toString Encoding.UTF8 buf - die $ "Couldn't fetch package " <> packageVersion <> ", status was not ok " <> show status <> ", got answer:\n " <> bodyString - Just (Right r@{ body: archiveArrayBuffer }) -> do - logDebug $ "Got status: " <> show r.status - -- check the size and hash of the tar against the metadata - archiveBuffer <- liftEffect $ Buffer.fromArrayBuffer archiveArrayBuffer - archiveSize <- liftEffect $ Buffer.size archiveBuffer - archiveSha <- liftEffect $ Sha256.hashBuffer archiveBuffer - unless (Int.toNumber archiveSize == versionMetadata.bytes) do - die $ "Archive fetched for " <> packageVersion <> " has a different size (" <> show archiveSize <> ") than expected (" <> show versionMetadata.bytes <> ")" - unless (archiveSha == versionMetadata.hash) do - die $ "Archive fetched for " <> packageVersion <> " has a different hash (" <> Sha256.print archiveSha <> ") than expected (" <> Sha256.print versionMetadata.hash <> ")" - -- if everything's alright we stash the tar in the global cache - logDebug $ "Fetched archive for " <> packageVersion <> ", saving it in the global cache: " <> archivePath - FS.writeFile archivePath archiveBuffer - logDebug $ "Unpacking archive to temp folder: " <> tempDir - (liftEffect $ Tar.extract { filename: archivePath, cwd: tempDir }) >>= case _ of - Right _ -> pure unit - Left err -> die [ "Failed to decode downloaded package " <> packageVersion <> ", error:", show err ] - logDebug $ "Moving extracted file to local cache:" <> localPackageLocation - FS.moveSync { src: (Path.concat [ tempDir, tarInnerFolder ]), dst: localPackageLocation } - -- Local package, no work to be done - LocalPackage _ -> pure unit - WorkspacePackage _ -> pure unit - - pure dependencies + toArray :: forall k v. Map k v -> Array (Tuple k v) + toArray = Map.toUnfoldable + ({ packages, workspacePackages } :: LockfileBuilderResult) <- + Array.foldM processPackage + { workspacePackages: Map.fromFoldable $ map Config.workspacePackageToLockfilePackage (Config.getWorkspacePackages workspace.packageSet), packages: Map.empty } + (foldMap sequence $ toArray $ map toArray allTransitiveDeps) + + let + lockfile = + { packages + , workspace: + { package_set: case workspace.packageSet.buildType of + RegistrySolverBuild _ -> Nothing + PackageSetBuild info _ -> Just info + , packages: workspacePackages + , extra_packages: fromMaybe Map.empty workspace.workspaceConfig.extra_packages + } + } + liftAff $ FS.writeYamlFile Lock.lockfileCodec "spago.lock" lockfile + logInfo "Lockfile written to spago.lock. Please commit this file." toAllDependencies :: PackageTransitiveDeps -> PackageMap toAllDependencies = foldl (Map.unionWith (\l _ -> l)) Map.empty @@ -296,8 +350,7 @@ getGitPackageInLocalCache name package = do getPackageDependencies :: forall a. PackageName -> Package -> Spago (FetchEnv a) (Maybe (Map PackageName Range)) getPackageDependencies packageName package = case package of RegistryVersion v -> do - { getManifestFromIndex, logOptions } <- ask - maybeManifest <- runSpago { logOptions } $ getManifestFromIndex packageName v + maybeManifest <- Registry.getManifestFromIndex packageName v pure $ map (_.dependencies <<< unwrap) maybeManifest GitPackage p -> do -- Note: we get the package in local cache nonetheless, @@ -341,20 +394,53 @@ type TransitiveDepsResult = } } -getTransitiveDeps :: forall a. Dependencies -> Spago (FetchEnv a) PackageMap -getTransitiveDeps (Dependencies deps) = do - let depsRanges = map (fromMaybe Config.widestRange) deps +getTransitiveDeps :: forall a. Config.WorkspacePackage -> Spago (FetchEnv a) PackageMap +getTransitiveDeps workspacePackage = do + let depsRanges = map (fromMaybe Config.widestRange) (unwrap $ getWorkspacePackageDeps workspacePackage) { workspace } <- ask - case workspace.packageSet of - Registry extraPackages -> do - plan <- getTransitiveDepsFromRegistry depsRanges extraPackages - logDebug $ "Got a plan from the Solver: " <> printJson (Internal.Codec.packageMap Version.codec) plan - pure (map RegistryVersion plan) - PackageSet set -> getTransitiveDepsFromPackageSet set (Array.fromFoldable $ Map.keys depsRanges) + case workspace.packageSet.lockfile of + -- If we have a lockfile we can just use that - we don't need build a plan, since we store it for every workspace + -- package, so we can just filter out the packages we need. + Right lockfile -> do + case Map.lookup workspacePackage.package.name lockfile.workspace.packages of + Nothing -> die $ "Package " <> PackageName.print workspacePackage.package.name <> " not found in lockfile" + Just { build_plan } -> do + let + allWorkspacePackages = Map.fromFoldable $ map (\p -> Tuple p.package.name (WorkspacePackage p)) (Config.getWorkspacePackages workspace.packageSet) + + isInBuildPlan :: forall v. PackageName -> v -> Boolean + isInBuildPlan name _package = Set.member name build_plan + + workspacePackagesWeNeed = Map.filterWithKey isInBuildPlan allWorkspacePackages + otherPackages = map fromLockEntry $ Map.filterWithKey isInBuildPlan lockfile.packages + + pure $ Map.union otherPackages workspacePackagesWeNeed + + -- No lockfile, we need to build a plan from scratch, and hit the Registry and so on + Left _ -> case workspace.packageSet.buildType of + RegistrySolverBuild extraPackages -> do + plan <- getTransitiveDepsFromRegistry depsRanges extraPackages + logDebug $ "Got a plan from the Solver: " <> printJson (Internal.Codec.packageMap Version.codec) plan + pure (map RegistryVersion plan) + PackageSetBuild _info set -> getTransitiveDepsFromPackageSet set (Array.fromFoldable $ Map.keys depsRanges) + + where + -- Note: here we can safely discard the dependencies because we don't need to bother about building a build plan, + -- we already built it when the lockfile was put together in the first place. All the dependency info is there so + -- that other things can use it (e.g. Nix), but Spago is not going to need it at this point. + fromLockEntry :: LockEntry -> Package + fromLockEntry = case _ of + FromPath { path } -> LocalPackage { path } + FromRegistry { version } -> RegistryVersion version + FromGit { rev, dependencies, url, subdir } -> GitPackage + { ref: rev + , dependencies: Just $ wrap $ Map.fromFoldable $ map (\p -> Tuple p Nothing) dependencies + , git: url + , subdir + } getTransitiveDepsFromRegistry :: forall a. Map PackageName Range -> PackageMap -> Spago (FetchEnv a) (Map PackageName Version) getTransitiveDepsFromRegistry depsRanges extraPackages = do - { logOptions, getMetadata, getManifestFromIndex } <- ask let loader :: PackageName -> Spago (FetchEnv a) (Map Version (Map PackageName Range)) loader packageName = do @@ -362,13 +448,13 @@ getTransitiveDepsFromRegistry depsRanges extraPackages = do case Map.lookup packageName extraPackages of Just p -> map (Map.singleton (getVersionFromPackage p) <<< fromMaybe Map.empty) $ getPackageDependencies packageName p Nothing -> do - maybeMetadata <- runSpago { logOptions } (getMetadata packageName) + maybeMetadata <- Registry.getMetadata packageName let versions = case maybeMetadata of Right (Metadata metadata) -> Array.fromFoldable $ Map.keys metadata.published Left _err -> [] map (Map.fromFoldable :: Array _ -> Map _ _) $ for versions \v -> do - maybeManifest <- runSpago { logOptions } $ getManifestFromIndex packageName v + maybeManifest <- Registry.getManifestFromIndex packageName v let deps = fromMaybe Map.empty $ map (_.dependencies <<< unwrap) maybeManifest pure (Tuple v deps) maybePlan <- Registry.Solver.loadAndSolve loader depsRanges @@ -384,7 +470,6 @@ getTransitiveDepsFromRegistry depsRanges extraPackages = do getTransitiveDepsFromPackageSet :: forall a. PackageMap -> Array PackageName -> Spago (FetchEnv a) PackageMap getTransitiveDepsFromPackageSet packageSet deps = do logDebug "Getting transitive deps" - -- { workspace } <- ask packageDependenciesCache <- liftEffect $ Ref.new Map.empty let memoisedGetPackageDependencies :: PackageName -> Package -> Spago (FetchEnv a) (Maybe (Map PackageName Range)) diff --git a/src/Spago/Command/Init.purs b/src/Spago/Command/Init.purs index 5cc2adeb1..0743af4d8 100644 --- a/src/Spago/Command/Init.purs +++ b/src/Spago/Command/Init.purs @@ -31,7 +31,7 @@ type InitOptions = -- TODO run git init? Is that desirable? -run :: forall a. InitOptions -> Spago (RegistryEnv a) Config +run :: InitOptions -> Spago (RegistryEnv _) Config run opts = do logInfo "Initializing a new project..." @@ -175,7 +175,6 @@ defaultConfig' opts = , package_set: setVersion # map \set -> SetFromRegistry { registry: set } , build_opts: Nothing , backend: Nothing - , lock: Nothing } } where diff --git a/src/Spago/Command/Ls.purs b/src/Spago/Command/Ls.purs index f872cbc0d..10893ed1b 100644 --- a/src/Spago/Command/Ls.purs +++ b/src/Spago/Command/Ls.purs @@ -22,19 +22,21 @@ import Registry.Internal.Codec (packageMap) import Registry.PackageName as PackageName import Registry.Version as Version import Spago.Command.Fetch as Fetch -import Spago.Config (Package(..), PackageSet(..), Workspace, WorkspacePackage) +import Spago.Config (BuildType(..), Package(..), Workspace, WorkspacePackage) import Spago.Config as Config import Spago.Paths as Paths import Type.Proxy (Proxy(..)) type LsPackagesArgs = { json :: Boolean + , pure :: Boolean } type LsDepsArgs = { json :: Boolean , transitive :: Boolean , selectedPackage :: Maybe String + , pure :: Boolean } type LsDepsOpts = @@ -87,9 +89,9 @@ listPackageSet :: LsPackagesArgs -> Spago LsSetEnv Unit listPackageSet { json } = do logDebug "Running `listPackageSet`" { workspace } <- ask - case workspace.packageSet of - Registry _extraPackages -> die "Cannot list the packages in the package set, as none is configured for the project." - PackageSet packageSet -> do + case workspace.packageSet.buildType of + RegistrySolverBuild _extraPackages -> die "Cannot list the packages in the package set, as none is configured for the project." + PackageSetBuild _info packageSet -> do let packages = Map.toUnfoldable packageSet case json of true -> formatPackagesJson packages diff --git a/src/Spago/Command/Publish.purs b/src/Spago/Command/Publish.purs index 5fda39365..15ab7a09d 100644 --- a/src/Spago/Command/Publish.purs +++ b/src/Spago/Command/Publish.purs @@ -29,6 +29,7 @@ import Registry.Operation.Validation as Operation.Validation import Registry.PackageName as PackageName import Registry.Version as Version import Routing.Duplex as Duplex +import Spago.Command.Build (BuildEnv) import Spago.Command.Build as Build import Spago.Command.Fetch as Fetch import Spago.Config (Package(..), Workspace, WorkspacePackage) @@ -42,6 +43,8 @@ import Spago.Log (LogVerbosity(..)) import Spago.Log as Log import Spago.Purs (Purs) import Spago.Purs.Graph as Graph +import Spago.Registry (PreRegistryEnv) +import Spago.Registry as Registry type PublishData = { name :: PackageName @@ -52,8 +55,7 @@ type PublishData = } type PublishEnv a = - { getManifestFromIndex :: PackageName -> Version -> Spago (LogEnv ()) (Maybe Manifest) - , getMetadata :: PackageName -> Spago (LogEnv ()) (Either String Metadata) + { getRegistry :: Spago (PreRegistryEnv ()) Registry.RegistryFunctions , workspace :: Workspace , logOptions :: LogOptions , offline :: OnlineStatus @@ -89,13 +91,7 @@ publish _args = do ) resultRef - env@ - { selected: selected' - , purs - , dependencies - , logOptions - , getMetadata - } <- ask + env@{ selected: selected', purs, dependencies } <- ask let (selected :: WorkspacePackage) = selected' { hasTests = false } let name = selected.package.name let strName = PackageName.print name @@ -103,22 +99,7 @@ publish _args = do logDebug $ "Publishing package " <> strName -- As first thing we run a build to make sure the package compiles at all - runSpago - -- We explicitly list the env fields because `Record.merge` didn't compile. - { getManifestFromIndex: env.getManifestFromIndex - , getMetadata: env.getMetadata - , workspace: env.workspace { selected = Just selected } - , logOptions: env.logOptions - , git: env.git - , purs: env.purs - , selected - , dependencies: env.dependencies - , psaCliFlags: - { statVerbosity: (Nothing :: Maybe Core.StatVerbosity) - , strict: (Nothing :: Maybe Boolean) - } - , pedanticPackages: false - } + runBuild { selected, dependencies: env.dependencies } ( Build.run { depsOnly: false , pursArgs: [] @@ -169,7 +150,7 @@ publish _args = do -- Get the metadata file for this package. -- It will exist if the package has been published at some point, it will not if the package is new. -- We make a new one if that's the case. - metadata <- runSpago { logOptions } (getMetadata name) >>= case _ of + metadata <- Registry.getMetadata name >>= case _ of Right (Metadata metadata) -> pure metadata Left err -> do logDebug $ "Got error while reading metadata file: " <> err @@ -341,8 +322,8 @@ publish _args = do <> Log.break die' $ Array.fromFoldable errors Right { expectedVersion, publishingData: publishingData@{ resolutions } } -> do - logInfo "Passed preliminary checks. " - -- This requires login credentials. + logInfo "Passed preliminary checks." + -- This requires login credentials. Git.pushTag Nothing expectedVersion >>= case _ of Left err -> die $ toDoc [ err @@ -356,22 +337,7 @@ publish _args = do -- from the solver (this is because the build might terminate the process, and we shall output the errors first) logInfo "Building again with the build plan from the solver..." let buildPlanDependencies = map Config.RegistryVersion resolutions - runSpago - -- We explicitly list the env fields because `Record.merge` didn't compile. - { getManifestFromIndex: env.getManifestFromIndex - , getMetadata: env.getMetadata - , workspace: env.workspace { selected = Just selected } - , logOptions: env.logOptions - , git: env.git - , purs: env.purs - , selected: env.selected - , dependencies: Map.singleton selected.package.name buildPlanDependencies - , psaCliFlags: - { statVerbosity: (Nothing :: Maybe Core.StatVerbosity) - , strict: (Nothing :: Maybe Boolean) - } - , pedanticPackages: false - } + runBuild { selected, dependencies: Map.singleton selected.package.name buildPlanDependencies } ( Build.run { depsOnly: false , pursArgs: [] @@ -391,6 +357,25 @@ publish _args = do waitForJobFinish jobId pure newPublishingData + where + -- If you are reading this and think that you can make it look nicer with + -- a `Record.merge` then please, be my guest + runBuild :: _ -> Spago (BuildEnv _) _ -> Spago (PublishEnv _) _ + runBuild { selected, dependencies } action = do + env <- ask + runSpago + { purs: env.purs + , git: env.git + , dependencies: dependencies + , logOptions: env.logOptions + , workspace: env.workspace { selected = Just selected } + , psaCliFlags: + { statVerbosity: (Nothing :: Maybe Core.StatVerbosity) + , strict: (Nothing :: Maybe Boolean) + } + , pedanticPackages: false + } + action callRegistry :: forall env a b. String -> JsonCodec b -> Maybe { codec :: JsonCodec a, data :: a } -> Spago (PublishEnv env) b callRegistry url outputCodec maybeInput = handleError do diff --git a/src/Spago/Command/Registry.purs b/src/Spago/Command/Registry.purs index 1694ec1a4..81caba8c8 100644 --- a/src/Spago/Command/Registry.purs +++ b/src/Spago/Command/Registry.purs @@ -10,7 +10,6 @@ import Data.Formatter.DateTime as DateTime import Data.Map as Map import Data.String (Pattern(..)) import Data.String as String -import Node.Path as Path import Registry.Internal.Codec as Internal import Registry.Internal.Codec as Internal.Codec import Registry.Internal.Format as Internal.Format @@ -18,9 +17,8 @@ import Registry.Metadata as Metadata import Registry.PackageName as PackageName import Registry.Version as Version import Spago.Db as Db -import Spago.FS as FS -import Spago.Paths as Paths import Spago.Registry (RegistryEnv) +import Spago.Registry as Registry type RegistrySearchArgs = { package :: String @@ -28,10 +26,10 @@ type RegistrySearchArgs = } -- TODO: I guess we could also search in (1) the tags and (2) the description -search :: forall a. RegistrySearchArgs -> Spago (RegistryEnv a) Unit +search :: RegistrySearchArgs -> Spago (RegistryEnv _) Unit search { package: searchString, json } = do logInfo $ "Searching for " <> show searchString <> " in the Registry package names..." - metadataFiles <- FS.ls $ Path.concat [ Paths.registryPath, "metadata" ] + metadataFiles <- Registry.listMetadataFiles let matches = Array.filter (String.contains (Pattern searchString)) (Array.mapMaybe (String.stripSuffix (Pattern ".json")) metadataFiles) @@ -39,12 +37,11 @@ search { package: searchString, json } = do logError "Did not find any packages matching the search string." else do -- We have only the match names, at least we get the time of the last release to be even a little useful - { getMetadata, logOptions } <- ask infos <- map (Map.fromFoldable <<< Array.catMaybes) $ for matches \match -> case PackageName.parse match of Left err -> do logWarn $ "Couldn't parse package name: " <> err pure Nothing - Right packageName -> runSpago { logOptions } (getMetadata packageName) >>= case _ of + Right packageName -> Registry.getMetadata packageName >>= case _ of Left err -> do logWarn $ "Couldn't read metadata for pacakge " <> PackageName.print packageName <> ", error: " <> err pure Nothing @@ -77,14 +74,13 @@ type RegistryInfoArgs = , json :: Boolean } -info :: forall a. RegistryInfoArgs -> Spago (RegistryEnv a) Unit +info :: RegistryInfoArgs -> Spago (RegistryEnv _) Unit info { package, json } = do packageName <- case PackageName.parse package of Left err -> die [ toDoc "Could not parse package name, error:", indent (toDoc $ show err) ] Right name -> pure name - { getMetadata, logOptions } <- ask - runSpago { logOptions } (getMetadata packageName) >>= case _ of + Registry.getMetadata packageName >>= case _ of Left err -> do logDebug err die $ "Could not find package " <> PackageName.print packageName @@ -99,7 +95,7 @@ type RegistryPackageSetsArgs = , json :: Boolean } -packageSets :: forall a. RegistryPackageSetsArgs -> Spago (RegistryEnv a) Unit +packageSets :: RegistryPackageSetsArgs -> Spago (RegistryEnv _) Unit packageSets { latest, json } = do { db } <- ask availableSets <- liftEffect $ Db.selectPackageSets db diff --git a/src/Spago/Command/Repl.purs b/src/Spago/Command/Repl.purs index d3ab77bce..8d5553300 100644 --- a/src/Spago/Command/Repl.purs +++ b/src/Spago/Command/Repl.purs @@ -23,9 +23,9 @@ type ReplEnv a = | a } -run :: forall a. Spago (ReplEnv a) Unit +run :: Spago (ReplEnv _) Unit run = do - { dependencies, purs, logOptions, pursArgs, selected, depsOnly, supportPackage } <- ask + { dependencies, pursArgs, selected, depsOnly, supportPackage } <- ask let allDependencies = Map.unionWith (\l _ -> l) supportPackage $ Fetch.toAllDependencies dependencies @@ -35,4 +35,4 @@ run = do , depsOnly , withTests: true } - void $ runSpago { purs, logOptions } $ Purs.repl globs pursArgs + void $ Purs.repl globs pursArgs diff --git a/src/Spago/Command/Script.purs b/src/Spago/Command/Script.purs index 84fb9babd..9d579a2b4 100644 --- a/src/Spago/Command/Script.purs +++ b/src/Spago/Command/Script.purs @@ -1,3 +1 @@ module Spago.Command.Script where - -import Prelude diff --git a/src/Spago/Command/Sources.purs b/src/Spago/Command/Sources.purs index 240e84cb4..d3ee23a90 100644 --- a/src/Spago/Command/Sources.purs +++ b/src/Spago/Command/Sources.purs @@ -22,11 +22,11 @@ run { json } = do Just selected -> NEA.singleton selected Nothing -> Config.getWorkspacePackages workspace.packageSet - deps = foldMap Fetch.getWorkspacePackageDeps selectedPackages + transitiveDeps <- traverse Fetch.getTransitiveDeps + $ Map.fromFoldable + $ map (\p -> Tuple p.package.name p) selectedPackages - transitiveDeps <- Fetch.getTransitiveDeps deps - - let transitivePackages = Map.union (Map.fromFoldable (map (\p -> Tuple (p.package.name) (WorkspacePackage p)) selectedPackages)) transitiveDeps + let transitivePackages = Map.union (Map.fromFoldable (map (\p -> Tuple (p.package.name) (WorkspacePackage p)) selectedPackages)) (Fetch.toAllDependencies transitiveDeps) let globs = Array.foldMap diff --git a/src/Spago/Command/Uninstall.purs b/src/Spago/Command/Uninstall.purs index 4abae7023..643de4b94 100644 --- a/src/Spago/Command/Uninstall.purs +++ b/src/Spago/Command/Uninstall.purs @@ -1,6 +1,5 @@ module Spago.Command.Uninstall ( run - , UninstallEnv , UninstallArgs ) where @@ -8,12 +7,17 @@ import Spago.Prelude import Data.Array as Array import Data.Array.NonEmpty as NEA -import Data.FoldableWithIndex (foldlWithIndex) import Data.Map as Map +import Data.Newtype (wrap) +import Data.Set as Set import Data.Set.NonEmpty as NonEmptySet +import Data.String as String import Node.Path as Path +import Node.Process as Process import Registry.PackageName as PackageName -import Spago.Config (Dependencies, PackageConfig, Workspace) +import Spago.Command.Fetch (FetchEnv) +import Spago.Command.Fetch as Fetch +import Spago.Config (BuildType(..), Dependencies, Package(..), PackageConfig) import Spago.Config as Config import Spago.Config as Core import Spago.FS as FS @@ -23,98 +27,101 @@ type UninstallArgs = , testDeps :: Boolean } -type UninstallEnv = - { workspace :: Workspace - , logOptions :: LogOptions - } - -run :: UninstallArgs -> Spago UninstallEnv Unit +run :: UninstallArgs -> Spago (FetchEnv _) Unit run args = do logDebug "Running `spago uninstall`" { workspace } <- ask + + { sourceOrTestString, deps, configPath, yamlDoc, name } <- case workspace.selected, workspace.rootPackage of + Just p, _ -> toContext (Path.concat [ p.path, "spago.yaml" ]) p.doc p.package + Nothing, Just rootPackage -> toContext "spago.yaml" workspace.doc rootPackage + Nothing, Nothing -> die "No package was selected. Please select a package." let - modifyConfig - :: FilePath - -> YamlDoc Core.Config - -> String - -> NonEmptyArray PackageName - -> Spago UninstallEnv Unit - modifyConfig configPath yamlDoc sourceOrTestString = \removedPackages -> do - logInfo - [ "Removing the following " <> sourceOrTestString <> " dependencies:" - , " " <> intercalateMap ", " PackageName.print removedPackages - ] - logDebug $ "Editing config file at path: " <> configPath - liftEffect $ Config.removePackagesFromConfig yamlDoc args.testDeps $ NonEmptySet.fromFoldable1 removedPackages - liftAff $ FS.writeYamlDocFile configPath yamlDoc - where - intercalateMap sep f = _.val <<< foldl go { init: true, val: "" } - where - go acc next = { init: false, val: if acc.init then f next else acc.val <> sep <> f next } + { warn, removed: removedSet } = separate deps + warnAbout = NEA.fromFoldable warn + removed = NEA.fromFoldable removedSet + newDeps = wrap $ Map.filterKeys (not <<< flip Set.member removedSet) $ unwrap deps + modifyDoc = modifyConfig configPath yamlDoc sourceOrTestString - toContext - :: FilePath - -> YamlDoc Core.Config - -> PackageConfig - -> Either - PackageName - { name :: PackageName - , deps :: Dependencies - , sourceOrTestString :: String - , modifyDoc :: NonEmptyArray PackageName -> Spago UninstallEnv Unit - } - toContext configPath yamlDoc pkgConfig - | args.testDeps = case pkgConfig.test of - Nothing -> - Left pkgConfig.name - Just { dependencies } -> do - let sourceOrTestString = "test" - Right - { name: pkgConfig.name - , deps: dependencies - , sourceOrTestString - , modifyDoc: modifyConfig configPath yamlDoc sourceOrTestString - } - | otherwise = do - let sourceOrTestString = "source" - Right - { name: pkgConfig.name - , deps: pkgConfig.dependencies - , sourceOrTestString - , modifyDoc: modifyConfig configPath yamlDoc sourceOrTestString - } - missingTestConfigOrContext <- case workspace.selected of - Just p -> - pure $ toContext (Path.concat [ p.path, "spago.yaml" ]) p.doc p.package + logDebug $ "Existing " <> sourceOrTestString <> " dependencies are: " <> (String.joinWith ", " $ map PackageName.print $ Array.fromFoldable $ Map.keys $ unwrap deps) + for_ warnAbout \undeclaredPkgs -> + logWarn + [ toDoc $ "The following packages cannot be uninstalled because they are not declared in the package's " <> sourceOrTestString <> " dependencies:" + , indent2 $ toDoc $ String.joinWith ", " $ Array.fromFoldable $ map PackageName.print undeclaredPkgs + ] + + case removed of Nothing -> do - case workspace.rootPackage of - Nothing -> - die "No package was selected. Please select a package." - Just p -> - pure $ toContext "spago.yaml" workspace.doc p - case missingTestConfigOrContext of - Left pkgName -> - logWarn $ "Could not uninstall test dependencies for " <> PackageName.print pkgName <> " because it does not have a test configuration." - Right context -> do - logDebug $ "Existing " <> context.sourceOrTestString <> " dependencies are: " <> (Array.intercalate ", " $ foldlWithIndex (\k a _ -> Array.snoc a $ PackageName.print k) [] $ unwrap context.deps) + logWarn $ "The package config for " <> PackageName.print name <> " was not updated." + -- We might be in a place where the config file is untouched, but we still need to update the lockfile + case workspace.packageSet.lockfile of + Right _ -> pure unit + Left reason -> writeNewLockfile reason + Just removed' -> do + modifyDoc removed' + + currentWorkspacePackage <- NEA.find (\p -> p.package.name == name) (Config.getWorkspacePackages workspace.packageSet) `justOrDieWith` "Impossible: package must be in workspace packages" let - { warn, removed } = foldl separate init args.dependenciesToRemove - where - init = { warn: [], removed: [] } + newWorkspacePackage = case args.testDeps of + false -> currentWorkspacePackage { package { dependencies = newDeps } } + true -> currentWorkspacePackage { package { test = currentWorkspacePackage.package.test # map (\t -> t { dependencies = newDeps }) } } + + newWorkspace = workspace + { packageSet = workspace.packageSet + { lockfile = Left "Lockfile is out of date (installing new packages)" + -- If we are installing packages, we need to add the new deps to the selected package + , buildType = case workspace.packageSet.buildType of + RegistrySolverBuild packageMap -> RegistrySolverBuild $ Map.insert newWorkspacePackage.package.name (WorkspacePackage newWorkspacePackage) packageMap + PackageSetBuild info packageMap -> PackageSetBuild info $ Map.insert newWorkspacePackage.package.name (WorkspacePackage newWorkspacePackage) packageMap + } + , selected = Just newWorkspacePackage + } + + local (_ { workspace = newWorkspace }) do + writeNewLockfile "Lockfile is out of date (uninstalled packages)" + + where + writeNewLockfile reason = do + { workspace } <- ask + dependencies <- traverse Fetch.getTransitiveDeps + $ Map.fromFoldable + $ map (\p -> Tuple p.package.name p) + $ Config.getWorkspacePackages workspace.packageSet + Fetch.writeNewLockfile reason dependencies - separate :: _ -> PackageName -> _ - separate acc next - | Map.member next $ unwrap context.deps = acc { removed = Array.snoc acc.removed next } - | otherwise = acc { warn = Array.snoc acc.warn next } - for_ (NEA.fromArray warn) \undeclaredPkgs -> - logWarn - [ "The following packages cannot be uninstalled because they are not declared in the package's " <> context.sourceOrTestString <> " dependencies:" - , " " <> NEA.intercalate ", " (map PackageName.print undeclaredPkgs) - ] + toContext :: FilePath -> YamlDoc Core.Config -> PackageConfig -> Spago _ (_ _) + toContext configPath yamlDoc pkgConfig = case args.testDeps of + true -> case pkgConfig.test of + Nothing -> do + logWarn $ "Could not uninstall test dependencies for " <> PackageName.print pkgConfig.name <> " because it does not have a test configuration." + liftEffect $ Process.exit' 0 + Just { dependencies } -> pure + { name: pkgConfig.name + , deps: dependencies + , sourceOrTestString: "test" + , yamlDoc + , configPath + } + false -> pure + { name: pkgConfig.name + , deps: pkgConfig.dependencies + , sourceOrTestString: "source" + , yamlDoc + , configPath + } - case NEA.fromArray removed of - Nothing -> - logInfo $ "The package config for " <> PackageName.print context.name <> " was not updated." - Just removed' -> - context.modifyDoc removed' + separate :: Dependencies -> { warn :: Set PackageName, removed :: Set PackageName } + separate deps = foldl f { warn: mempty, removed: mempty } args.dependenciesToRemove + where + f :: _ -> PackageName -> _ + f acc next = case Map.member next (unwrap deps) of + true -> acc { removed = Set.insert next acc.removed } + false -> acc { warn = Set.insert next acc.warn } + modifyConfig :: FilePath -> YamlDoc Core.Config -> String -> NonEmptyArray PackageName -> Spago (FetchEnv _) Unit + modifyConfig configPath yamlDoc sourceOrTestString = \removedPackages -> do + logInfo $ "Removing the following " <> sourceOrTestString <> " dependencies: " + <> (String.joinWith ", " $ map PackageName.print $ Array.fromFoldable removedPackages) + logDebug $ "Editing config file at path: " <> configPath + liftEffect $ Config.removePackagesFromConfig yamlDoc args.testDeps $ NonEmptySet.fromFoldable1 removedPackages + liftAff $ FS.writeYamlDocFile configPath yamlDoc diff --git a/src/Spago/Config.js b/src/Spago/Config.js index 408f5210a..b9cd9122a 100644 --- a/src/Spago/Config.js +++ b/src/Spago/Config.js @@ -63,8 +63,8 @@ export function removePackagesFromConfigImpl(doc, isTest, shouldRemove) { let newItems = []; for (const el of deps.items) { if ( - (Yaml.isScalar(el) && shouldRemove(el.value)) || - (Yaml.isMap(el) && shouldRemove(el.items[0].key)) + (Yaml.isScalar(el) && shouldRemove(el.value)) || + (Yaml.isMap(el) && shouldRemove(el.items[0].key)) ) { continue; } @@ -99,7 +99,3 @@ export function addRangesToConfigImpl(doc, rangesMap) { export function setPackageSetVersionInConfigImpl(doc, version) { doc.setIn(["workspace", "package_set", "registry"], version); } - -export function updatePackageSetHashInConfigImpl(doc, sha) { - doc.setIn(["workspace", "package_set", "hash"], sha); -} diff --git a/src/Spago/Config.purs b/src/Spago/Config.purs index 817c81355..60fa58005 100644 --- a/src/Spago/Config.purs +++ b/src/Spago/Config.purs @@ -1,6 +1,6 @@ module Spago.Config ( BuildOptions - , LockfileSettings(..) + , BuildType(..) , Package(..) , PackageSet(..) , PackageMap @@ -19,6 +19,7 @@ module Spago.Config , readWorkspace , sourceGlob , setPackageSetVersionInConfig + , workspacePackageToLockfilePackage ) where import Spago.Prelude @@ -49,15 +50,16 @@ import Record as Record import Registry.Foreign.FastGlob as Glob import Registry.Internal.Codec as Internal.Codec import Registry.PackageName as PackageName +import Registry.PackageSet as Registry.PackageSet import Registry.Range as Range -import Registry.Sha256 as Sha256 import Registry.Version as Version import Spago.Core.Config as Core import Spago.FS as FS import Spago.Git as Git -import Spago.Lock (Lockfile) +import Spago.Lock (Lockfile, PackageSetInfo) import Spago.Lock as Lock import Spago.Paths as Paths +import Spago.Registry as Registry import Type.Proxy (Proxy(..)) type Workspace = @@ -69,7 +71,6 @@ type Workspace = , doc :: YamlDoc Core.Config , workspaceConfig :: Core.WorkspaceConfig , rootPackage :: Maybe Core.PackageConfig - , lockfile :: LockfileSettings } type BuildOptions = @@ -78,13 +79,6 @@ type BuildOptions = , statVerbosity :: Maybe Core.StatVerbosity } -data LockfileSettings - = UseLockfile Lockfile - | GenerateLockfile - | SkipLockfile - -derive instance Eq LockfileSettings - fromExtraPackage :: Core.ExtraPackage -> Package fromExtraPackage = case _ of Core.ExtraLocalPackage lp -> LocalPackage lp @@ -130,9 +124,14 @@ derive newtype instance Eq RemotePackageSet type PackageMap = Map PackageName Package -data PackageSet - = PackageSet PackageMap - | Registry PackageMap +data BuildType + = RegistrySolverBuild PackageMap + | PackageSetBuild PackageSetInfo PackageMap + +type PackageSet = + { buildType :: BuildType + , lockfile :: Either String Lockfile + } type WorkspacePackage = { path :: FilePath @@ -149,41 +148,20 @@ data Package -- | Reads all the configurations in the tree and builds up the Map of local -- | packages to be integrated in the package set -readWorkspace :: forall a. Maybe PackageName -> Spago (Git.GitEnv a) Workspace -readWorkspace maybeSelectedPackage = do +readWorkspace :: { maybeSelectedPackage :: Maybe PackageName, pureBuild :: Boolean } -> Spago (Registry.RegistryEnv _) Workspace +readWorkspace { maybeSelectedPackage, pureBuild } = do logInfo "Reading Spago workspace configuration..." -- First try to read the config in the root. It _has_ to contain a workspace -- configuration, or we fail early. { workspace, package: maybePackage, workspaceDoc } <- Core.readConfig "spago.yaml" >>= case _ of - Left err -> die [ "Couldn't parse Spago config, error:\n " <> err, "Run `spago init` to initialise a new project." ] + Left err -> die [ "Couldn't parse Spago config, error:\n " <> err, "The configuration file help can be found here https://github.com/purescript/spago#the-configuration-file" ] Right { yaml: { workspace: Nothing } } -> die [ "Your spago.yaml doesn't contain a workspace section." , "See the relevant documentation here: https://github.com/purescript/spago#the-workspace" ] Right { yaml: { workspace: Just workspace, package }, doc } -> pure { workspace, package, workspaceDoc: doc } - lockfile <- FS.exists "spago.lock" >>= case _ of - true -> liftAff (FS.readYamlFile Lock.lockfileCodec "spago.lock") >>= case _ of - Left error -> die $ "Your project contains a spago.lock file, but it cannot be decoded:\n" <> error - Right contents - | workspace.lock == Just false -> die "Your workspace specifies 'lock: false', but there is a spago.lock file in the workspace." - | otherwise -> do - -- TODO: here figure out if the lockfile is still valid by checking if: - -- - the package set section of the workspace is the same - -- - the dependencies of each package are the same - pure (UseLockfile contents) - false - -- If the user specifies lock: true then we always create a lockfile. - | workspace.lock == Just true -> pure GenerateLockfile - -- If the user specifies lock: false then we always skip the lockfile. - | workspace.lock == Just false -> pure SkipLockfile - -- If the user does not set the 'lock' field then we defer to whether or - -- not they are using a package set. - | otherwise -> case workspace.package_set of - Nothing -> pure GenerateLockfile - Just _ -> pure SkipLockfile - -- Then gather all the spago other configs in the tree. { succeeded: otherConfigPaths, failed, ignored } <- do result <- liftAff $ Glob.match' Paths.cwd [ "**/spago.yaml" ] { ignore: [ ".spago", "spago.yaml" ] } @@ -261,40 +239,66 @@ readWorkspace maybeSelectedPackage = do pkgs -> [ toDoc "Available packages:", indent (toDoc pkgs) ] Just p -> pure (Just p) + maybeLockfileContents <- FS.exists "spago.lock" >>= case _ of + false -> pure (Left "No lockfile found") + true -> liftAff (FS.readYamlFile Lock.lockfileCodec "spago.lock") >>= case _ of + Left error -> do + logWarn + [ "Your project contains a spago.lock file, but it cannot be decoded. Spago will generate a new one." + , "Error was: " <> error + ] + pure (Left "Could not decode lockfile") + -- Here we figure out if the lockfile is still up to date by having a quick look at the configurations: + -- if they changed since the last write, then we need to regenerate the lockfile + -- Unless! the user is passing the --pure flag, in which case we just use the lockfile + Right contents -> case pureBuild, shouldComputeNewLockfile { workspace, workspacePackages } contents.workspace of + true, _ -> do + logDebug "Using lockfile because of --pure flag" + pure (Right contents) + false, true -> pure (Left "Lockfile is out of date") + false, false -> do + logDebug "Lockfile is up to date, using it" + pure (Right contents) + -- Read in the package database { offline } <- ask - { compatibleCompiler, remotePackageSet } <- case workspace.package_set of - Nothing -> do + packageSetInfo <- case maybeLockfileContents, workspace.package_set of + _, Nothing -> do logDebug "Did not find a package set in your config, using Registry solver" - pure - { compatibleCompiler: Core.widestRange - , remotePackageSet: Nothing - } - Just (Core.SetFromRegistry { registry: v }) -> do + pure Nothing + + -- If there's a lockfile we don't attempt to fetch the package set from the registry + -- repo nor from the internet, since we already have the whole set right there + Right lockfile, _ -> do + logDebug "Found lockfile, using the package set from there" + pure lockfile.workspace.package_set + + Left _, Just address@(Core.SetFromRegistry { registry: v }) -> do logDebug "Reading the package set from the Registry repo..." - let packageSetPath = Path.concat [ Paths.registryPath, "package-sets", Version.print v <> ".json" ] - liftAff (FS.readJsonFile remotePackageSetCodec packageSetPath) >>= case _ of - Left err -> die $ "Couldn't read the package set: " <> err - Right (RemotePackageSet registryPackageSet) -> do - logInfo "Read the package set from the registry" - pure - { compatibleCompiler: Range.caret registryPackageSet.compiler - , remotePackageSet: Just registryPackageSet.packages - } - Just (Core.SetFromPath { path }) -> do + (Registry.PackageSet.PackageSet registryPackageSet) <- Registry.readPackageSet v + logDebug "Read the package set from the Registry repo" + pure $ Just + { content: map Core.RemoteRegistryVersion registryPackageSet.packages + , address + , compiler: Range.caret registryPackageSet.compiler + } + + Left _, Just address@(Core.SetFromPath { path }) -> do logDebug $ "Reading the package set from local path: " <> path liftAff (FS.readJsonFile remotePackageSetCodec path) >>= case _ of Left err -> die $ "Couldn't read the package set: " <> err Right (RemotePackageSet localPackageSet) -> do logInfo "Read the package set from local path" - pure - { compatibleCompiler: Range.caret localPackageSet.compiler - , remotePackageSet: Just localPackageSet.packages + pure $ Just + { content: localPackageSet.packages + , address + , compiler: Range.caret localPackageSet.compiler } - Just (Core.SetFromUrl { url: rawUrl, hash: maybeHash }) -> do - -- If there is a hash then we look up in the CAS, if not we fetch stuff, compute a hash and store it there - let - fetchPackageSet' = do + + Left _, Just address@(Core.SetFromUrl { url: rawUrl }) -> do + result <- case offline of + Offline -> die "You are offline, but the package set is not cached locally. Please connect to the internet and try again." + Online -> do logDebug $ "Reading the package set from URL: " <> rawUrl url <- case parseUrl rawUrl of Left err -> die $ "Could not parse URL for the package set, error: " <> show err @@ -320,24 +324,10 @@ readWorkspace maybeSelectedPackage = do Just { version } -> pure (unsafeFromRight (parseLenientVersion version)) Nothing -> die $ "Couldn't find 'metadata' package in legacy package set." pure { compiler: version, remotePackageSet: map Core.RemoteLegacyPackage set } - fetchPackageSet = case offline of - Online -> fetchPackageSet' - Offline -> die "You are offline, but the package set is not cached locally. Please connect to the internet and try again." - result <- case maybeHash of - Just hash -> readPackageSetFromHash hash >>= case _ of - Left err -> do - logDebug $ show err - fetchPackageSet - Right r -> pure r - Nothing -> do - logWarn $ "Did not find a hash for your package set import, adding it to your config..." - fetchPackageSet - newHash <- writePackageSetToHash result - logDebug $ "Package set hash: " <> Sha256.print newHash - updatePackageSetHashInConfig workspaceDoc newHash - pure - { compatibleCompiler: Range.caret result.compiler - , remotePackageSet: Just result.remotePackageSet + pure $ Just + { content: result.remotePackageSet + , compiler: Range.caret result.compiler + , address } -- Mix in the package set (a) the workspace packages, and (b) the extra_packages @@ -351,13 +341,14 @@ readWorkspace maybeSelectedPackage = do let extraPackages = map fromExtraPackage (fromMaybe Map.empty workspace.extra_packages) localPackagesOverlap = Set.intersection (Map.keys workspacePackages) (Map.keys extraPackages) - packageSet = + buildType = let localPackages = Map.union (map WorkspacePackage workspacePackages) extraPackages in - case remotePackageSet of - Nothing -> Registry localPackages - Just set -> PackageSet $ Map.union localPackages (map fromRemotePackage set) + case packageSetInfo of + Nothing -> RegistrySolverBuild localPackages + Just info -> PackageSetBuild info $ Map.union localPackages (map fromRemotePackage info.content) + packageSet = { buildType, lockfile: maybeLockfileContents } -- Note again: we only try to prevent collisions between workspace packages and local overrides. -- We otherwise want local packages to override _remote_ ones, e.g. in the case where you are @@ -392,13 +383,12 @@ readWorkspace maybeSelectedPackage = do pure { selected: maybeSelected , packageSet - , compatibleCompiler + , compatibleCompiler: fromMaybe Core.widestRange $ map _.compiler packageSetInfo , backend: workspace.backend , buildOptions , doc: workspaceDoc , workspaceConfig: workspace , rootPackage: maybePackage - , lockfile } rootPackageToWorkspacePackage @@ -410,6 +400,23 @@ rootPackageToWorkspacePackage { rootPackage, workspaceDoc } = do hasTests <- liftEffect $ FS.exists "test" pure { path: "./", doc: workspaceDoc, package: rootPackage, hasTests } +workspacePackageToLockfilePackage :: WorkspacePackage -> Tuple PackageName Lock.WorkspaceLockPackage +workspacePackageToLockfilePackage { path, package } = Tuple package.name + { path + , dependencies: package.dependencies + , test_dependencies: foldMap _.dependencies package.test + , build_plan: mempty -- Note: this is filled in later + } + +shouldComputeNewLockfile :: { workspace :: Core.WorkspaceConfig, workspacePackages :: Map PackageName WorkspacePackage } -> Lock.WorkspaceLock -> Boolean +shouldComputeNewLockfile { workspace, workspacePackages } workspaceLock = + -- the workspace packages should exactly match, except for the needed_by field, which is filled in during build plan construction + (map (workspacePackageToLockfilePackage >>> snd) workspacePackages /= (map (_ { build_plan = mempty }) workspaceLock.packages)) + -- and the extra packages should exactly match + || (fromMaybe Map.empty workspace.extra_packages /= workspaceLock.extra_packages) + -- and the package set address needs to match - we have no way to match the package set contents at this point, so we let it be + || (workspace.package_set /= map _.address workspaceLock.package_set) + getPackageLocation :: PackageName -> Package -> FilePath getPackageLocation name = Paths.mkRelative <<< case _ of RegistryVersion v -> Path.concat [ Paths.localCachePackagesPath, PackageName.print name <> "-" <> Version.print v ] @@ -464,10 +471,11 @@ testGlob = "test/**/*.purs" -- We can afford an unsafe here, if it's empty we have bigger problems getWorkspacePackages :: PackageSet -> NonEmptyArray WorkspacePackage -getWorkspacePackages = unsafeFromJust <<< NEA.fromFoldable <<< Array.mapMaybe extractWorkspacePackage <<< Map.toUnfoldable <<< case _ of - PackageSet m -> m - Registry m -> m +getWorkspacePackages = unsafeFromJust <<< NEA.fromFoldable <<< Array.mapMaybe extractWorkspacePackage <<< Map.toUnfoldable <<< extractSet <<< _.buildType where + extractSet = case _ of + PackageSetBuild _info m -> m + RegistrySolverBuild m -> m extractWorkspacePackage = case _ of Tuple _ (WorkspacePackage p) -> Just p _ -> Nothing @@ -487,45 +495,6 @@ getTopologicallySortedWorkspacePackages packageSet = do type PackageSetResult = { compiler :: Version, remotePackageSet :: Map PackageName Core.RemotePackage } -packageSetResultCodec :: JsonCodec PackageSetResult -packageSetResultCodec = CAR.object "PackageSetResult" - { compiler: Version.codec - , remotePackageSet: Internal.Codec.packageMap Core.remotePackageCodec - } - -readPackageSetFromHash :: forall a. Sha256 -> Spago (LogEnv a) (Either String PackageSetResult) -readPackageSetFromHash hash = do - hex <- liftEffect (shaToHex hash) - let path = packageSetCachePath hex - logDebug $ "Reading cached package set entry from " <> path - FS.exists path >>= case _ of - false -> pure $ Left $ "Did not find a package set cached with hash " <> Sha256.print hash - true -> (liftAff $ FS.readJsonFile packageSetResultCodec path) >>= case _ of - Left err -> pure $ Left $ "Error while reading cached package set " <> Sha256.print hash <> ": " <> err - Right res -> pure $ Right res - -writePackageSetToHash :: forall a. PackageSetResult -> Spago (LogEnv a) Sha256 -writePackageSetToHash result = do - let serialised = printJson packageSetResultCodec result - hash <- liftEffect $ Sha256.hashString serialised - hex <- liftEffect (shaToHex hash) - FS.mkdirp packageSetsCachePath - FS.writeTextFile (packageSetCachePath hex) serialised - pure hash - -packageSetsCachePath :: FilePath -packageSetsCachePath = Path.concat [ Paths.globalCachePath, "setsCAS" ] - -packageSetCachePath :: HexString → String -packageSetCachePath (HexString hash) = Path.concat [ packageSetsCachePath, hash ] - -foreign import updatePackageSetHashInConfigImpl :: EffectFn2 (YamlDoc Core.Config) String Unit - -updatePackageSetHashInConfig :: forall m. MonadAff m => MonadEffect m => YamlDoc Core.Config -> Sha256 -> m Unit -updatePackageSetHashInConfig doc sha = do - liftEffect $ runEffectFn2 updatePackageSetHashInConfigImpl doc (Sha256.print sha) - liftAff $ FS.writeYamlDocFile "spago.yaml" doc - foreign import setPackageSetVersionInConfigImpl :: EffectFn2 (YamlDoc Core.Config) String Unit setPackageSetVersionInConfig :: forall m. MonadAff m => MonadEffect m => YamlDoc Core.Config -> Version -> m Unit @@ -535,8 +504,10 @@ setPackageSetVersionInConfig doc version = do foreign import addPackagesToConfigImpl :: EffectFn3 (YamlDoc Core.Config) Boolean (Array String) Unit -addPackagesToConfig :: YamlDoc Core.Config -> Boolean -> Array PackageName -> Effect Unit -addPackagesToConfig doc isTest pkgs = runEffectFn3 addPackagesToConfigImpl doc isTest (map PackageName.print pkgs) +addPackagesToConfig :: forall m. MonadAff m => FilePath -> YamlDoc Core.Config -> Boolean -> Array PackageName -> m Unit +addPackagesToConfig configPath doc isTest pkgs = do + liftEffect $ runEffectFn3 addPackagesToConfigImpl doc isTest (map PackageName.print pkgs) + liftAff $ FS.writeYamlDocFile configPath doc foreign import removePackagesFromConfigImpl :: EffectFn3 (YamlDoc Core.Config) Boolean (PackageName -> Boolean) Unit diff --git a/src/Spago/Db.purs b/src/Spago/Db.purs index ba6bfaaab..82276e271 100644 --- a/src/Spago/Db.purs +++ b/src/Spago/Db.purs @@ -65,6 +65,10 @@ selectLatestPackageSetByCompiler db compiler = do maybePackageSet <- Nullable.toMaybe <$> Uncurried.runEffectFn2 selectLatestPackageSetByCompilerImpl db (Version.print compiler) pure $ packageSetFromJs =<< maybePackageSet +{- + +We'll need these when implementing a command for "show me what's in this package set" + selectPackageSetEntriesBySet :: Db -> Version -> Effect (Array PackageSetEntry) selectPackageSetEntriesBySet db packageSetVersion = do packageSetEntries <- Uncurried.runEffectFn2 selectPackageSetEntriesBySetImpl db (Version.print packageSetVersion) @@ -74,6 +78,7 @@ selectPackageSetEntriesByPackage :: Db -> PackageName -> Version -> Effect (Arra selectPackageSetEntriesByPackage db packageName version = do packageSetEntries <- Uncurried.runEffectFn3 selectPackageSetEntriesByPackageImpl db (PackageName.print packageName) (Version.print version) pure $ Array.mapMaybe packageSetEntryFromJs packageSetEntries +-} getLastPull :: Db -> String -> Effect (Maybe DateTime) getLastPull db key = do @@ -172,6 +177,8 @@ packageSetEntryToJs { packageSetVersion, packageName, packageVersion } = , packageVersion: Version.print packageVersion } +{- + packageSetEntryFromJs :: PackageSetEntryJs -> Maybe PackageSetEntry packageSetEntryFromJs p = hush do packageSetVersion <- Version.parse p.packageSetVersion @@ -179,6 +186,8 @@ packageSetEntryFromJs p = hush do packageVersion <- Version.parse p.packageVersion pure $ { packageSetVersion, packageName, packageVersion } +-} + -------------------------------------------------------------------------------- -- Codecs diff --git a/src/Spago/Git.purs b/src/Spago/Git.purs index 9ed66d33f..b133275cb 100644 --- a/src/Spago/Git.purs +++ b/src/Spago/Git.purs @@ -61,22 +61,27 @@ fetchRepo { git, ref } path = do Except.runExceptT $ runGit_ [ "clone", "--filter=tree:0", git, path ] Nothing result <- Except.runExceptT do Except.ExceptT $ pure cloneOrFetchResult + logDebug $ "Checking out the requested ref for " <> git <> " : " <> ref _ <- runGit [ "checkout", ref ] (Just path) -- if we are on a branch and not on a detached head, then we need to pull -- the following command will fail if on a detached head, and succeed if on a branch Except.mapExceptT ( \a -> a >>= case _ of Left _err -> pure (Right unit) - Right _ -> Except.runExceptT $ runGit_ [ "pull", "--rebase", "--autostash" ] (Just path) + Right _ -> do + logDebug "Pulling the latest changes" + Except.runExceptT $ runGit_ [ "pull", "--rebase", "--autostash" ] (Just path) ) (runGit_ [ "symbolic-ref", "-q", "HEAD" ] (Just path)) - pure case result of - Left err -> Left + case result of + Left err -> pure $ Left [ "Error while fetching the repo '" <> git <> "' at ref '" <> ref <> "':" , " " <> err ] - Right _ -> Right unit + Right _ -> do + logDebug $ "Successfully fetched the repo '" <> git <> "' at ref '" <> ref <> "'" + pure $ Right unit listTags :: forall a. Maybe FilePath -> Spago (GitEnv a) (Either Docc (Array String)) listTags cwd = do diff --git a/src/Spago/Lock.purs b/src/Spago/Lock.purs index 6920eca89..3edca3a17 100644 --- a/src/Spago/Lock.purs +++ b/src/Spago/Lock.purs @@ -5,6 +5,7 @@ module Spago.Lock , lockEntryCodec , PathLock , GitLock + , PackageSetInfo , RegistryLock , WorkspaceLock , WorkspaceLockPackage @@ -13,31 +14,47 @@ module Spago.Lock import Spago.Prelude import Data.Codec.Argonaut as CA +import Data.Codec.Argonaut.Common as CA.Common import Data.Profunctor as Profunctor import Record as Record import Registry.Internal.Codec as Registry.Codec import Registry.PackageName as PackageName +import Registry.Range as Range import Registry.Sha256 as Sha256 import Registry.Version as Version -import Spago.Core.Config (Dependencies, ExtraPackage, SetAddress) import Spago.Core.Config as Config +import Spago.Core.Config as Core import Type.Proxy (Proxy(..)) +type Lockfile = + { workspace :: WorkspaceLock + , packages :: Map PackageName LockEntry + } + +data LockEntry + = FromPath PathLock + | FromGit GitLock + | FromRegistry RegistryLock + +derive instance Eq LockEntry + type WorkspaceLock = - { package_set :: Maybe SetAddress + { package_set :: Maybe PackageSetInfo , packages :: Map PackageName WorkspaceLockPackage - , extra_packages :: Map PackageName ExtraPackage + , extra_packages :: Map PackageName Core.ExtraPackage } -type WorkspaceLockPackage = - { dependencies :: Dependencies - , test_dependencies :: Dependencies - , path :: FilePath +type PackageSetInfo = + { address :: Core.SetAddress + , content :: Map PackageName Core.RemotePackage + , compiler :: Range } -type Lockfile = - { workspace :: WorkspaceLock - , packages :: Map PackageName LockEntry +type WorkspaceLockPackage = + { dependencies :: Core.Dependencies + , test_dependencies :: Core.Dependencies + , path :: FilePath + , build_plan :: Set PackageName } lockfileCodec :: JsonCodec Lockfile @@ -49,7 +66,7 @@ lockfileCodec = CA.object "Lockfile" workspaceLockCodec :: JsonCodec WorkspaceLock workspaceLockCodec = CA.object "WorkspaceLock" $ CA.recordProp (Proxy :: _ "packages") (Registry.Codec.packageMap dependenciesCodec) - $ CA.recordPropOptional (Proxy :: _ "package_set") Config.setAddressCodec + $ CA.recordPropOptional (Proxy :: _ "package_set") packageSetCodec $ CA.recordProp (Proxy :: _ "extra_packages") (Registry.Codec.packageMap Config.extraPackageCodec) $ CA.record where @@ -57,14 +74,15 @@ workspaceLockCodec = CA.object "WorkspaceLock" $ CA.recordProp (Proxy :: _ "path") CA.string $ CA.recordProp (Proxy :: _ "dependencies") Config.dependenciesCodec $ CA.recordProp (Proxy :: _ "test_dependencies") Config.dependenciesCodec + $ CA.recordProp (Proxy :: _ "build_plan") (CA.Common.set PackageName.codec) $ CA.record -data LockEntry - = FromPath PathLock - | FromGit GitLock - | FromRegistry RegistryLock - -derive instance Eq LockEntry +packageSetCodec :: JsonCodec PackageSetInfo +packageSetCodec = CA.object "PackageSetInfo" + $ CA.recordProp (Proxy :: _ "address") Config.setAddressCodec + $ CA.recordProp (Proxy :: _ "compiler") Range.codec + $ CA.recordProp (Proxy :: _ "content") (Registry.Codec.packageMap Core.remotePackageCodec) + $ CA.record lockEntryCodec :: JsonCodec LockEntry lockEntryCodec = CA.codec' decode encode diff --git a/src/Spago/Purs.purs b/src/Spago/Purs.purs index cb09ee1f0..8167dd5cd 100644 --- a/src/Spago/Purs.purs +++ b/src/Spago/Purs.purs @@ -55,7 +55,6 @@ compile globs pursArgs = do { pipeStdout = false } repl :: forall a. Set FilePath -> Array String -> Spago (PursEnv a) ExecaResult - repl globs pursArgs = do { purs } <- ask let args = [ "repl" ] <> pursArgs <> Set.toUnfoldable globs diff --git a/src/Spago/Registry.purs b/src/Spago/Registry.purs index d723baf19..0da4c4a87 100644 --- a/src/Spago/Registry.purs +++ b/src/Spago/Registry.purs @@ -1,16 +1,35 @@ -module Spago.Registry where +module Spago.Registry + ( PreRegistryEnv + , PreRegistryEnvRow + , RegistryEnv + , RegistryEnvRow + , RegistryFunctions + , findPackageSet + , getManifestFromIndex + , getMetadata + , getRegistryFns + , listMetadataFiles + , readPackageSet + ) where import Spago.Prelude import Data.Array as Array +import Data.Array.NonEmpty as NonEmptyArray import Data.DateTime as DateTime import Data.Map as Map import Data.Set as Set import Data.String (Pattern(..)) import Data.String as String import Data.Time.Duration (Minutes(..)) +import Effect.AVar (AVar) +import Effect.Aff.AVar as AVar import Effect.Now as Now import Node.Path as Path +import Registry.Constants as Registry.Constants +import Registry.ManifestIndex as ManifestIndex +import Registry.Metadata as Metadata +import Registry.PackageName as PackageName import Registry.PackageSet (PackageSet(..)) import Registry.PackageSet as PackageSet import Registry.Version as Version @@ -21,60 +40,201 @@ import Spago.Git as Git import Spago.Paths as Paths import Spago.Purs as Purs -type RegistryEnv a = - { getManifestFromIndex :: PackageName -> Version -> Spago (LogEnv ()) (Maybe Manifest) - , getMetadata :: PackageName -> Spago (LogEnv ()) (Either String Metadata) - , offline :: OnlineStatus +type PreRegistryEnvRow a = + ( offline :: OnlineStatus , logOptions :: LogOptions , purs :: Purs.Purs , git :: Git.Git , db :: Db.Db | a + ) + +type PreRegistryEnv a = Record (PreRegistryEnvRow a) + +type RegistryEnvRow a = PreRegistryEnvRow + ( getRegistry :: Spago (PreRegistryEnv ()) RegistryFunctions + | a + ) + +type RegistryEnv a = Record (RegistryEnvRow a) + +type RegistryFunctions = + { getManifestFromIndex :: PackageName -> Version -> Spago (LogEnv ()) (Maybe Manifest) + , getMetadata :: PackageName -> Spago (LogEnv ()) (Either String Metadata) + , findPackageSet :: Maybe Version -> Spago (PreRegistryEnv ()) Version + , listMetadataFiles :: Spago (LogEnv ()) (Array String) + , readPackageSet :: Version -> Spago (LogEnv ()) PackageSet } --- | Update the database with the latest package sets -updatePackageSetsDb :: forall a. Db -> Spago (LogEnv a) Unit -updatePackageSetsDb db = do - setsAvailable <- map Set.fromFoldable getAvailablePackageSets - setsInDb <- map (Set.fromFoldable <<< map _.version) (liftEffect $ Db.selectPackageSets db) - let setsToInsert = Set.difference setsAvailable setsInDb - - unless (Set.isEmpty setsToInsert) do - for_ (Set.toUnfoldable setsToInsert :: Array _) \setVersion -> do - PackageSet set <- readPackageSet setVersion - -- First insert the package set - logDebug $ "Inserting package set in DB: " <> Version.print setVersion - liftEffect $ Db.insertPackageSet db { compiler: set.compiler, date: set.published, version: set.version } - -- Then we insert every entry separately - for_ (Map.toUnfoldable set.packages :: Array _) \(Tuple name version) -> do - liftEffect $ Db.insertPackageSetEntry db { packageName: name, packageVersion: version, packageSetVersion: set.version } - --- | List all the package sets versions available in the Registry repo -getAvailablePackageSets :: forall a. Spago (LogEnv a) (Array Version) -getAvailablePackageSets = do - { success: setVersions, fail: parseFailures } <- map (partitionEithers <<< map parseSetVersion) $ FS.ls Paths.packageSetsPath - - unless (Array.null parseFailures) do - logDebug $ [ toDoc "Failed to parse some package-sets versions:" ] <> map (indent <<< toDoc <<< show) parseFailures - - pure setVersions +getMetadata :: PackageName -> Spago (RegistryEnv _) _ +getMetadata packageName = do + { getRegistry, logOptions, db, git, purs, offline } <- ask + { getMetadata: fn } <- runSpago { logOptions, db, git, purs, offline } getRegistry + runSpago { logOptions } (fn packageName) + +getManifestFromIndex :: PackageName -> Version -> Spago (RegistryEnv _) _ +getManifestFromIndex packageName version = do + { getRegistry, logOptions, db, git, purs, offline } <- ask + { getManifestFromIndex: fn } <- runSpago { logOptions, db, git, purs, offline } getRegistry + runSpago { logOptions } (fn packageName version) + +findPackageSet :: Maybe Version -> Spago (RegistryEnv _) _ +findPackageSet version = do + { getRegistry, logOptions, db, git, purs, offline } <- ask + { findPackageSet: fn } <- runSpago { logOptions, db, git, purs, offline } getRegistry + runSpago { logOptions, db, git, purs, offline } (fn version) + +listMetadataFiles :: Spago (RegistryEnv _) _ +listMetadataFiles = do + { getRegistry, logOptions, db, git, purs, offline } <- ask + { listMetadataFiles: fn } <- runSpago { logOptions, db, git, purs, offline } getRegistry + runSpago { logOptions } fn + +readPackageSet :: Version -> Spago (RegistryEnv _) _ +readPackageSet version = do + { getRegistry, logOptions, db, git, purs, offline } <- ask + { readPackageSet: fn } <- runSpago { logOptions, db, git, purs, offline } getRegistry + runSpago { logOptions } (fn version) + +getRegistryFns :: AVar RegistryFunctions -> AVar Unit -> Spago (PreRegistryEnv _) RegistryFunctions +getRegistryFns registryBox registryLock = do + -- The Box AVar will be empty until the first time we fetch the Registry, then + -- we can just use the value that is cached. + -- The Lock AVar is used to make sure + -- that only one fiber is fetching the Registry at a time, and that all the other + -- fibers will wait for it to finish and then use the cached value. + { db } <- ask + liftAff $ AVar.take registryLock + liftAff (AVar.tryRead registryBox) >>= case _ of + Just registry -> do + liftAff $ AVar.put unit registryLock + pure registry + Nothing -> do + fetchingFreshRegistry <- fetchRegistry + let + registryFns = + { getManifestFromIndex: getManifestFromIndexImpl db + , getMetadata: getMetadataImpl db fetchingFreshRegistry + , listMetadataFiles: FS.ls (Path.concat [ Paths.registryPath, Registry.Constants.metadataDirectory ]) + , findPackageSet: findPackageSetImpl + , readPackageSet: readPackageSetImpl + } + liftAff $ AVar.put registryFns registryBox + liftAff $ AVar.put unit registryLock + pure registryFns + + where + fetchRegistry :: Spago (PreRegistryEnv _) Boolean + fetchRegistry = do + -- we keep track of how old the latest pull was - if the last pull was recent enough + -- we just move on, otherwise run the fibers + { db } <- ask + fetchingFreshRegistry <- shouldFetchRegistryRepos db + when fetchingFreshRegistry do + -- clone the registry and index repo, or update them + logInfo "Refreshing the Registry Index..." + parallelise + [ Git.fetchRepo { git: "https://github.com/purescript/registry-index.git", ref: "main" } Paths.registryIndexPath >>= case _ of + Right _ -> pure unit + Left _err -> logWarn "Couldn't refresh the registry-index, will proceed anyways" + , Git.fetchRepo { git: "https://github.com/purescript/registry.git", ref: "main" } Paths.registryPath >>= case _ of + Right _ -> pure unit + Left _err -> logWarn "Couldn't refresh the registry, will proceed anyways" + ] + + -- Now that we are up to date with the Registry we init/refresh the database + updatePackageSetsDb db + pure fetchingFreshRegistry + + -- | Update the database with the latest package sets + updatePackageSetsDb :: Db -> Spago (LogEnv _) Unit + updatePackageSetsDb db = do + { logOptions } <- ask + setsAvailable <- map Set.fromFoldable getAvailablePackageSets + setsInDb <- map (Set.fromFoldable <<< map _.version) (liftEffect $ Db.selectPackageSets db) + let setsToInsert = Set.difference setsAvailable setsInDb + + unless (Set.isEmpty setsToInsert) do + for_ (Set.toUnfoldable setsToInsert :: Array _) \setVersion -> do + PackageSet set <- runSpago { logOptions } (readPackageSetImpl setVersion) + -- First insert the package set + logDebug $ "Inserting package set in DB: " <> Version.print setVersion + liftEffect $ Db.insertPackageSet db { compiler: set.compiler, date: set.published, version: set.version } + -- Then we insert every entry separately + for_ (Map.toUnfoldable set.packages :: Array _) \(Tuple name version) -> do + liftEffect $ Db.insertPackageSetEntry db { packageName: name, packageVersion: version, packageSetVersion: set.version } + + -- | List all the package sets versions available in the Registry repo + getAvailablePackageSets :: Spago (LogEnv _) (Array Version) + getAvailablePackageSets = do + { success: setVersions, fail: parseFailures } <- map (partitionEithers <<< map parseSetVersion) $ FS.ls Paths.packageSetsPath + + unless (Array.null parseFailures) do + logDebug $ [ toDoc "Failed to parse some package-sets versions:" ] <> map (indent <<< toDoc <<< show) parseFailures + + pure setVersions + where + parseSetVersion str = Version.parse case String.stripSuffix (Pattern ".json") str of + Nothing -> str + Just v -> v + + readPackageSetImpl :: Version -> Spago (LogEnv ()) PackageSet + readPackageSetImpl setVersion = do + logDebug "Reading the package set from the Registry repo..." + let packageSetPath = Path.concat [ Paths.packageSetsPath, Version.print setVersion <> ".json" ] + liftAff (FS.readJsonFile PackageSet.codec packageSetPath) >>= case _ of + Left err -> die $ "Couldn't read the package set: " <> err + Right registryPackageSet -> do + logDebug $ "Read the package set " <> Version.print setVersion <> " from the registry" + pure registryPackageSet + +-- Metadata can change over time (unpublished packages, and new packages), so we need +-- to read it from file every time we have a fresh Registry +getMetadataImpl :: Db -> Boolean -> PackageName -> Spago (LogEnv ()) (Either String Metadata) +getMetadataImpl db fetchingFreshRegistry name = do + -- we first try reading it from the DB + liftEffect (Db.getMetadata db name) >>= case _ of + Just metadata | not fetchingFreshRegistry -> do + logDebug $ "Got metadata from DB: " <> PackageName.print name + pure (Right metadata) + _ -> do + -- if we don't have it we try reading it from file + metadataFromFile name >>= case _ of + Left e -> pure (Left e) + Right m -> do + -- and memoize it + liftEffect (Db.insertMetadata db name m) + pure (Right m) where - parseSetVersion str = Version.parse case String.stripSuffix (Pattern ".json") str of - Nothing -> str - Just v -> v - -readPackageSet :: forall a. Version -> Spago (LogEnv a) PackageSet -readPackageSet setVersion = do - logDebug "Reading the package set from the Registry repo..." - let packageSetPath = Path.concat [ Paths.packageSetsPath, Version.print setVersion <> ".json" ] - liftAff (FS.readJsonFile PackageSet.codec packageSetPath) >>= case _ of - Left err -> die $ "Couldn't read the package set: " <> err - Right registryPackageSet -> do - logDebug $ "Read the package set " <> Version.print setVersion <> " from the registry" - pure registryPackageSet - -findPackageSet :: forall a. Maybe Version -> Spago (RegistryEnv a) Version -findPackageSet maybeSet = do + metadataFromFile pkgName = do + let metadataFilePath = Path.concat [ Paths.registryPath, Registry.Constants.metadataDirectory, PackageName.print pkgName <> ".json" ] + logDebug $ "Reading metadata from file: " <> metadataFilePath + liftAff (FS.readJsonFile Metadata.codec metadataFilePath) + +-- Manifests are immutable so we can just lookup in the DB or read from file if not there +getManifestFromIndexImpl :: Db -> PackageName -> Version -> Spago (LogEnv ()) (Maybe Manifest) +getManifestFromIndexImpl db name version = do + liftEffect (Db.getManifest db name version) >>= case _ of + Just manifest -> pure (Just manifest) + Nothing -> do + -- if we don't have it we need to read it from file + -- (note that we have all the versions of a package in the same file) + logDebug $ "Reading package from Index: " <> PackageName.print name + maybeManifests <- liftAff $ ManifestIndex.readEntryFile Paths.registryIndexPath name + manifests <- map (map (\m@(Manifest m') -> Tuple m'.version m)) case maybeManifests of + Right ms -> pure $ NonEmptyArray.toUnfoldable ms + Left err -> do + logWarn $ "Could not read package manifests from index, proceeding anyways. Error: " <> err + pure [] + let versions = Map.fromFoldable manifests + -- and memoize it + for_ manifests \(Tuple _ manifest@(Manifest m)) -> do + logDebug $ "Inserting manifest in DB: " <> PackageName.print name <> " v" <> Version.print m.version + liftEffect $ Db.insertManifest db name m.version manifest + pure (Map.lookup version versions) + +findPackageSetImpl :: forall a. Maybe Version -> Spago (PreRegistryEnv a) Version +findPackageSetImpl maybeSet = do { db, purs } <- ask availableSets <- liftEffect $ Db.selectPackageSets db let availableVersions = map _.version availableSets @@ -139,10 +299,11 @@ shouldFetchRegistryRepos db = do let staleAfter = Minutes 15.0 let (timeDiff :: Minutes) = DateTime.diff now lastRegistryFetch let isOldEnough = timeDiff > staleAfter - if isOldEnough then do + -- We check if it's old, but also if we have it at all + registryExists <- FS.exists Paths.registryPath + if isOldEnough || not registryExists then do logDebug "Registry is old, refreshing" liftEffect $ Db.updateLastPull db registryKey now pure true else do - logDebug "Registry is fresh enough, moving on..." pure false diff --git a/src/Spago/Repl.purs b/src/Spago/Repl.purs index e95fc4694..ae2c0a233 100644 --- a/src/Spago/Repl.purs +++ b/src/Spago/Repl.purs @@ -6,21 +6,21 @@ import Spago.Prelude import Data.Map as Map import Registry.PackageName as PackageName +import Spago.Config (BuildType(..), Package(..), PackageMap, PackageSet) import Spago.Registry (RegistryEnv) -import Spago.Config (Package(..), PackageMap, PackageSet(..)) +import Spago.Registry as Registry -- TODO I guess this should be configurable supportPackageName :: PackageName supportPackageName = unsafeFromRight $ PackageName.parse "psci-support" -supportPackage :: forall a. PackageSet -> Spago (RegistryEnv a) PackageMap +supportPackage :: PackageSet -> Spago (RegistryEnv _) PackageMap supportPackage packageSet = do - { getMetadata, logOptions } <- ask - case packageSet of - PackageSet packages -> pure $ Map.filterWithKey (\k _v -> k == supportPackageName) packages + case packageSet.buildType of + PackageSetBuild _info packages -> pure $ Map.filterWithKey (\k _v -> k == supportPackageName) packages -- TODO: we should look in the "other" packages first - Registry _other -> do - maybeMetadata <- runSpago { logOptions } (getMetadata supportPackageName) + RegistrySolverBuild _other -> do + maybeMetadata <- Registry.getMetadata supportPackageName pure case maybeMetadata of Right (Metadata metadata) -> case Map.findMax metadata.published of Nothing -> Map.empty diff --git a/test-fixtures/alternate-backend-output.txt b/test-fixtures/alternate-backend-output.txt index 964766865..a9b0aaa6e 100644 --- a/test-fixtures/alternate-backend-output.txt +++ b/test-fixtures/alternate-backend-output.txt @@ -1,5 +1,4 @@ Reading Spago workspace configuration... -Read the package set from the registry ✅ Selecting package to build: subpackage diff --git a/test-fixtures/circular-dependencies.txt b/test-fixtures/circular-dependencies.txt index 3e504c114..ce0ed29ec 100644 --- a/test-fixtures/circular-dependencies.txt +++ b/test-fixtures/circular-dependencies.txt @@ -1,5 +1,4 @@ Reading Spago workspace configuration... -Read the package set from the registry ✅ Selecting package to build: bbb diff --git a/test-fixtures/codegen-opt.txt b/test-fixtures/codegen-opt.txt index 2617921c4..7bc602b11 100644 --- a/test-fixtures/codegen-opt.txt +++ b/test-fixtures/codegen-opt.txt @@ -1,5 +1,4 @@ Reading Spago workspace configuration... -Read the package set from the registry ✅ Selecting package to build: 7368613235362d68766258694c614d517a3667747a58725778 diff --git a/test-fixtures/list-packages-registry.txt b/test-fixtures/list-packages-registry.txt index 7e5d1f6f7..b5084c682 100644 --- a/test-fixtures/list-packages-registry.txt +++ b/test-fixtures/list-packages-registry.txt @@ -2,6 +2,8 @@ Reading Spago workspace configuration... ✅ Selecting package to build: aaa +No lockfile found, generating it... +Lockfile written to spago.lock. Please commit this file. Downloading dependencies... ❌ Cannot list the packages in the package set, as none is configured for the project. diff --git a/test-fixtures/missing-dependencies.txt b/test-fixtures/missing-dependencies.txt index 14e9b30c8..9f39f39bb 100644 --- a/test-fixtures/missing-dependencies.txt +++ b/test-fixtures/missing-dependencies.txt @@ -1,5 +1,4 @@ Reading Spago workspace configuration... -Read the package set from the registry ✅ Selecting package to build: aaaa diff --git a/test-fixtures/offline.txt b/test-fixtures/offline.txt index 7e627ecfd..f8483c153 100644 --- a/test-fixtures/offline.txt +++ b/test-fixtures/offline.txt @@ -1,5 +1,4 @@ Reading Spago workspace configuration... -Read the package set from the registry ✅ Selecting package to build: eee diff --git a/test-fixtures/pedantic/check-direct-import-transitive-dependency-both.txt b/test-fixtures/pedantic/check-direct-import-transitive-dependency-both.txt index 1cd258a4d..df914fbf7 100644 --- a/test-fixtures/pedantic/check-direct-import-transitive-dependency-both.txt +++ b/test-fixtures/pedantic/check-direct-import-transitive-dependency-both.txt @@ -1,5 +1,4 @@ Reading Spago workspace configuration... -Read the package set from the registry ✅ Selecting package to build: pedantic @@ -27,4 +26,4 @@ Tests for package 'pedantic' import the following transitive dependencies - plea These errors can be fixed by running the below command(s): spago install -p pedantic maybe -spago install -p pedantic --test-deps control \ No newline at end of file +spago install -p pedantic --test-deps control diff --git a/test-fixtures/pedantic/check-direct-import-transitive-dependency-test.txt b/test-fixtures/pedantic/check-direct-import-transitive-dependency-test.txt index c8c545d74..85109de44 100644 --- a/test-fixtures/pedantic/check-direct-import-transitive-dependency-test.txt +++ b/test-fixtures/pedantic/check-direct-import-transitive-dependency-test.txt @@ -1,5 +1,4 @@ Reading Spago workspace configuration... -Read the package set from the registry ✅ Selecting package to build: pedantic @@ -21,4 +20,4 @@ Tests for package 'pedantic' import the following transitive dependencies - plea Control.Alt These errors can be fixed by running the below command(s): -spago install -p pedantic --test-deps control \ No newline at end of file +spago install -p pedantic --test-deps control diff --git a/test-fixtures/pedantic/check-direct-import-transitive-dependency.txt b/test-fixtures/pedantic/check-direct-import-transitive-dependency.txt index c894aa26c..728284054 100644 --- a/test-fixtures/pedantic/check-direct-import-transitive-dependency.txt +++ b/test-fixtures/pedantic/check-direct-import-transitive-dependency.txt @@ -1,5 +1,4 @@ Reading Spago workspace configuration... -Read the package set from the registry ✅ Selecting package to build: pedantic @@ -21,4 +20,4 @@ Sources for package 'pedantic' import the following transitive dependencies - pl Control.Alt These errors can be fixed by running the below command(s): -spago install -p pedantic control \ No newline at end of file +spago install -p pedantic control diff --git a/test-fixtures/pedantic/check-pedantic-packages.txt b/test-fixtures/pedantic/check-pedantic-packages.txt index d1c73545f..3748bc6b5 100644 --- a/test-fixtures/pedantic/check-pedantic-packages.txt +++ b/test-fixtures/pedantic/check-pedantic-packages.txt @@ -1,5 +1,4 @@ Reading Spago workspace configuration... -Read the package set from the registry ✅ Selecting package to build: pedantic @@ -37,4 +36,4 @@ These errors can be fixed by running the below command(s): spago uninstall -p pedantic console effect either spago install -p pedantic newtype spago uninstall -p pedantic --test-deps tuples -spago install -p pedantic --test-deps either \ No newline at end of file +spago install -p pedantic --test-deps either diff --git a/test-fixtures/pedantic/check-unused-dependency-in-source.txt b/test-fixtures/pedantic/check-unused-dependency-in-source.txt index 085e1d343..7316f743e 100644 --- a/test-fixtures/pedantic/check-unused-dependency-in-source.txt +++ b/test-fixtures/pedantic/check-unused-dependency-in-source.txt @@ -1,5 +1,4 @@ Reading Spago workspace configuration... -Read the package set from the registry ✅ Selecting package to build: pedantic @@ -29,4 +28,4 @@ Tests for package 'pedantic' import the following transitive dependencies - plea These errors can be fixed by running the below command(s): spago uninstall -p pedantic console effect -spago install -p pedantic --test-deps console effect \ No newline at end of file +spago install -p pedantic --test-deps console effect diff --git a/test-fixtures/pedantic/check-unused-dependency.txt b/test-fixtures/pedantic/check-unused-dependency.txt index df9ff5275..a74358caf 100644 --- a/test-fixtures/pedantic/check-unused-dependency.txt +++ b/test-fixtures/pedantic/check-unused-dependency.txt @@ -1,5 +1,4 @@ Reading Spago workspace configuration... -Read the package set from the registry ✅ Selecting package to build: pedantic @@ -20,4 +19,4 @@ Sources for package 'pedantic' declares unused dependencies - please remove them - effect These errors can be fixed by running the below command(s): -spago uninstall -p pedantic console effect \ No newline at end of file +spago uninstall -p pedantic console effect diff --git a/test-fixtures/pedantic/check-unused-source-and-test-dependency.txt b/test-fixtures/pedantic/check-unused-source-and-test-dependency.txt index 3ea9f4603..387b4b2f2 100644 --- a/test-fixtures/pedantic/check-unused-source-and-test-dependency.txt +++ b/test-fixtures/pedantic/check-unused-source-and-test-dependency.txt @@ -1,5 +1,4 @@ Reading Spago workspace configuration... -Read the package set from the registry ✅ Selecting package to build: pedantic @@ -25,4 +24,4 @@ Tests for package 'pedantic' declares unused dependencies - please remove them f These errors can be fixed by running the below command(s): spago uninstall -p pedantic console effect -spago uninstall -p pedantic --test-deps console effect \ No newline at end of file +spago uninstall -p pedantic --test-deps console effect diff --git a/test-fixtures/pedantic/check-unused-test-dependency.txt b/test-fixtures/pedantic/check-unused-test-dependency.txt index 302d8e2b5..2cd0d7efe 100644 --- a/test-fixtures/pedantic/check-unused-test-dependency.txt +++ b/test-fixtures/pedantic/check-unused-test-dependency.txt @@ -1,5 +1,4 @@ Reading Spago workspace configuration... -Read the package set from the registry ✅ Selecting package to build: pedantic @@ -19,4 +18,4 @@ Tests for package 'pedantic' declares unused dependencies - please remove them f - newtype These errors can be fixed by running the below command(s): -spago uninstall -p pedantic --test-deps newtype \ No newline at end of file +spago uninstall -p pedantic --test-deps newtype diff --git a/test-fixtures/pedantic/pedantic-instructions-initial-failure.txt b/test-fixtures/pedantic/pedantic-instructions-initial-failure.txt index 318771bda..b68c36af6 100644 --- a/test-fixtures/pedantic/pedantic-instructions-initial-failure.txt +++ b/test-fixtures/pedantic/pedantic-instructions-initial-failure.txt @@ -1,5 +1,4 @@ Reading Spago workspace configuration... -Read the package set from the registry ✅ Selecting package to build: pedantic @@ -21,4 +20,4 @@ Sources for package 'pedantic' import the following transitive dependencies - pl Effect These errors can be fixed by running the below command(s): -spago install -p pedantic effect \ No newline at end of file +spago install -p pedantic effect diff --git a/test-fixtures/pedantic/pedantic-instructions-installation-result.txt b/test-fixtures/pedantic/pedantic-instructions-installation-result.txt index 9953c0d53..6ac115bef 100644 --- a/test-fixtures/pedantic/pedantic-instructions-installation-result.txt +++ b/test-fixtures/pedantic/pedantic-instructions-installation-result.txt @@ -1,13 +1,14 @@ Reading Spago workspace configuration... -Read the package set from the registry ✅ Selecting package to build: pedantic -Adding 1 packages to the config in spago.yaml +Adding 1 package to the config in spago.yaml +Lockfile is out of date (installing new packages), generating it... +Lockfile written to spago.lock. Please commit this file. Downloading dependencies... Building... Src Lib All Warnings 0 0 0 Errors 0 0 0 -✅ Build succeeded. \ No newline at end of file +✅ Build succeeded. diff --git a/test-fixtures/polyrepo.lock b/test-fixtures/polyrepo.lock new file mode 100644 index 000000000..5fd05e893 --- /dev/null +++ b/test-fixtures/polyrepo.lock @@ -0,0 +1,427 @@ +workspace: + packages: + package-a: + path: package-a + dependencies: + - package-b + - package-c + - prelude + test_dependencies: + - console + - effect + - prelude + build_plan: + - console + - effect + - package-b + - package-c + - prelude + package-b: + path: package-b + dependencies: + - package-c + - prelude + test_dependencies: + - console + - effect + - prelude + build_plan: + - console + - effect + - package-c + - prelude + package-c: + path: package-c + dependencies: + - prelude + test_dependencies: + - console + - effect + - prelude + build_plan: + - console + - effect + - prelude + package_set: + address: + registry: 0.0.1 + compiler: ">=0.15.4 <0.16.0" + content: + ace: 9.0.0 + aff: 7.1.0 + aff-bus: 6.0.0 + aff-coroutines: 9.0.0 + aff-promise: 4.0.0 + aff-retry: 2.0.0 + affjax: 13.0.0 + affjax-node: 1.0.0 + affjax-web: 1.0.0 + ansi: 7.0.0 + argonaut: 9.0.0 + argonaut-codecs: 9.1.0 + argonaut-core: 7.0.0 + argonaut-generic: 8.0.0 + argonaut-traversals: 10.0.0 + argparse-basic: 2.0.0 + array-builder: 0.1.2 + arraybuffer: 13.0.0 + arraybuffer-builder: 3.0.1 + arraybuffer-types: 3.0.2 + arrays: 7.1.0 + arrays-zipper: 2.0.1 + ask: 1.0.0 + assert: 6.0.0 + avar: 5.0.0 + b64: 0.0.8 + barbies: 1.0.1 + barlow-lens: 0.9.0 + bifunctors: 6.0.0 + bigints: 7.0.1 + bolson: 0.1.1 + bower-json: 3.0.0 + call-by-name: 4.0.1 + canvas: 6.0.0 + canvas-action: 9.0.0 + cartesian: 1.0.6 + catenable-lists: 7.0.0 + channel: 1.0.0 + checked-exceptions: 3.1.1 + classnames: 2.0.0 + codec: 5.0.0 + codec-argonaut: 9.0.0 + colors: 7.0.1 + concur-core: 0.5.0 + concur-react: 0.5.0 + concurrent-queues: 3.0.0 + console: 6.0.0 + const: 6.0.0 + contravariant: 6.0.0 + control: 6.0.0 + convertable-options: 1.0.0 + coroutines: 7.0.0 + css: 6.0.0 + datetime: 6.1.0 + datetime-parsing: 0.2.0 + debug: 6.0.2 + decimals: 7.1.0 + deku: 0.6.1 + deno: 0.0.5 + dissect: 1.0.0 + distributive: 6.0.0 + dodo-printer: 2.2.1 + dom-filereader: 7.0.0 + dom-indexed: 11.0.0 + dotenv: 3.0.0 + droplet: 0.5.0 + dynamic-buffer: 3.0.1 + effect: 4.0.0 + either: 6.1.0 + elmish: 0.8.3 + elmish-enzyme: 0.1.1 + elmish-hooks: 0.8.2 + elmish-html: 0.7.2 + elmish-testing-library: 0.2.0 + email-validate: 7.0.0 + encoding: 0.0.8 + enums: 6.0.1 + error: 2.0.0 + exceptions: 6.0.0 + exists: 6.0.0 + exitcodes: 4.0.0 + expect-inferred: 3.0.0 + fallback: 0.1.0 + fast-vect: 0.7.0 + fetch: 1.1.4 + fetch-argonaut: 1.0.0 + fetch-core: 4.0.4 + fetch-yoga-json: 1.1.0 + filterable: 5.0.0 + fixed-points: 7.0.0 + fixed-precision: 5.0.0 + flame: 1.2.0 + float32: 2.0.0 + foldable-traversable: 6.0.0 + foreign: 7.0.0 + foreign-object: 4.0.0 + foreign-readwrite: 3.0.0 + fork: 6.0.0 + form-urlencoded: 7.0.0 + formatters: 7.0.0 + free: 7.0.0 + freeap: 7.0.0 + freer-free: 0.0.1 + freet: 7.0.0 + functions: 6.0.0 + functor1: 3.0.0 + functors: 5.0.0 + fuzzy: 0.4.0 + gen: 4.0.0 + generate-values: 1.0.1 + generic-router: 0.0.1 + geometry-plane: 1.0.3 + github-actions-toolkit: 0.5.0 + graphql-client: 9.2.2 + graphs: 8.1.0 + group: 4.1.1 + halogen: 7.0.0 + halogen-css: 10.0.0 + halogen-formless: 4.0.2 + halogen-hooks: 0.6.1 + halogen-hooks-extra: 0.9.0 + halogen-store: 0.5.4 + halogen-storybook: 2.0.0 + halogen-subscriptions: 2.0.0 + halogen-svg-elems: 6.0.0 + halogen-vdom: 8.0.0 + halogen-vdom-string-renderer: 0.5.0 + heckin: 2.0.1 + heterogeneous: 0.6.0 + heterogeneous-extrablatt: 0.2.1 + homogeneous: 0.4.0 + http-methods: 6.0.0 + httpure: 0.15.0 + httpurple: 3.0.0 + httpurple-argonaut: 1.0.1 + httpurple-yoga-json: 1.0.0 + hyrule: 2.1.0 + identity: 6.0.0 + indexed-monad: 2.1.0 + int64: 2.0.0 + integers: 6.0.0 + interpolate: 5.0.0 + invariant: 6.0.0 + jarilo: 1.0.1 + jelly: 0.4.1 + jest: 1.0.0 + js-date: 8.0.0 + js-fileio: 3.0.0 + js-promise: 1.0.0 + js-timers: 6.1.0 + js-uri: 3.1.0 + justifill: 0.5.0 + jwt: 0.0.9 + language-cst-parser: 0.12.1 + lazy: 6.0.0 + lazy-joe: 1.0.0 + lcg: 4.0.0 + leibniz: 5.0.0 + linalg: 5.1.0 + lists: 7.0.0 + literals: 1.0.2 + logging: 3.0.0 + logging-journald: 0.4.0 + machines: 7.0.0 + matrices: 5.0.1 + matryoshka: 1.0.0 + maybe: 6.0.0 + mdast-util-from-markdown: 0.2.1 + media-types: 6.0.0 + midi: 4.0.0 + milkis: 9.0.0 + minibench: 4.0.0 + mmorph: 7.0.0 + monad-control: 5.0.0 + monad-logger: 1.3.1 + monad-loops: 0.5.0 + monad-unlift: 1.0.1 + monoid-extras: 0.0.1 + monoidal: 0.16.0 + morello: 0.3.2 + mote: 3.0.0 + motsunabe: 2.0.0 + nano-id: 1.1.0 + naturals: 3.0.0 + nested-functor: 0.2.1 + newtype: 5.0.0 + node-buffer: 8.0.0 + node-buffer-blob: 1.0.0 + node-child-process: 9.0.0 + node-fs: 8.1.0 + node-fs-aff: 9.1.0 + node-http: 8.0.0 + node-net: 4.0.0 + node-path: 5.0.0 + node-process: 10.0.0 + node-readline: 7.0.0 + node-sqlite3: 8.0.0 + node-streams: 7.0.0 + node-streams-aff: 4.0.0 + node-url: 6.0.0 + nonempty: 7.0.0 + now: 6.0.0 + npm-package-json: 2.0.0 + nullable: 6.0.0 + numbers: 9.0.0 + ocarina: 1.3.0 + open-folds: 6.3.0 + open-memoize: 6.1.0 + open-pairing: 6.1.0 + options: 7.0.0 + optparse: 5.0.0 + ordered-collections: 3.0.0 + ordered-set: 0.4.0 + orders: 6.0.0 + pairs: 9.0.0 + parallel: 6.0.0 + parsing: 10.0.0 + parsing-dataview: 3.1.0 + partial: 4.0.0 + pathy: 9.0.0 + pha: 0.9.0 + phaser: 0.6.0 + pipes: 8.0.0 + point-free: 1.0.0 + pointed-list: 0.5.1 + polymorphic-vectors: 4.0.0 + posix-types: 6.0.0 + precise: 6.0.0 + precise-datetime: 7.0.0 + prelude: 6.0.1 + prettier-printer: 3.0.0 + profunctor: 6.0.0 + profunctor-lenses: 8.0.0 + protobuf: 4.0.0 + ps-cst: 1.2.0 + psa-utils: 8.0.0 + psc-ide: 19.0.0 + psci-support: 6.0.0 + qualified-do: 2.2.0 + quantities: 12.1.0 + quickcheck: 8.0.1 + quickcheck-combinators: 0.1.3 + quickcheck-laws: 7.0.0 + quickcheck-utf8: 0.0.0 + random: 6.0.0 + rationals: 5.0.0 + react: 10.0.1 + react-basic: 17.0.0 + react-basic-classic: 3.0.0 + react-basic-dnd: 10.1.0 + react-basic-dom: 6.0.0 + react-basic-emotion: 7.0.0 + react-basic-hooks: 8.0.0 + react-dom: 8.0.0 + react-halo: 3.0.0 + react-icons: 1.0.8 + react-testing-library: 4.0.1 + read: 1.0.1 + record: 4.0.0 + refs: 6.0.0 + remotedata: 5.0.0 + resource: 2.0.1 + resourcet: 1.0.0 + result: 1.0.3 + return: 0.2.0 + ring-modules: 5.0.1 + rito: 0.1.0 + routing: 11.0.0 + routing-duplex: 0.6.0 + run: 5.0.0 + safe-coerce: 2.0.0 + safely: 4.0.1 + selection-foldable: 0.2.0 + semirings: 7.0.0 + signal: 13.0.0 + simple-emitter: 2.0.0 + simple-json: 9.0.0 + sized-matrices: 1.0.0 + sized-vectors: 5.0.2 + slug: 3.0.8 + soundfonts: 4.1.0 + sparse-matrices: 1.2.1 + sparse-polynomials: 1.0.5 + spec: 7.0.0 + spec-discovery: 8.0.1 + spec-quickcheck: 5.0.0 + splitmix: 2.1.0 + ssrs: 1.0.0 + st: 6.0.0 + strictlypositiveint: 1.0.1 + string-parsers: 8.0.0 + strings: 6.0.1 + strings-extra: 4.0.0 + stringutils: 0.0.12 + substitute: 0.2.3 + sunde: 3.0.0 + supply: 0.2.0 + svg-parser: 3.0.0 + systemd-journald: 0.3.0 + tailrec: 6.1.0 + test-unit: 17.0.0 + thermite: 6.3.1 + thermite-dom: 0.3.1 + these: 6.0.0 + toppokki: 4.0.0 + transformers: 6.0.0 + tree-rose: 4.0.2 + tuples: 7.0.0 + two-or-more: 1.0.0 + type-equality: 4.0.1 + typelevel: 6.0.0 + typelevel-lists: 2.1.0 + typelevel-peano: 1.0.1 + typelevel-prelude: 7.0.0 + typelevel-rows: 0.1.0 + uint: 7.0.0 + ulid: 3.0.1 + uncurried-transformers: 1.1.0 + undefined: 2.0.0 + undefined-is-not-a-problem: 1.1.0 + unfoldable: 6.0.0 + unicode: 6.0.0 + unlift: 1.0.1 + unordered-collections: 3.0.1 + unsafe-coerce: 6.0.0 + unsafe-reference: 5.0.0 + untagged-union: 1.0.0 + uri: 9.0.0 + uuid: 9.0.0 + validation: 6.0.0 + variant: 8.0.0 + vectorfield: 1.0.1 + versions: 7.0.0 + web-clipboard: 4.1.0 + web-cssom: 2.0.0 + web-dom: 6.0.0 + web-dom-parser: 8.0.0 + web-dom-xpath: 3.0.0 + web-encoding: 3.0.0 + web-events: 4.0.0 + web-fetch: 3.0.0 + web-file: 4.0.0 + web-html: 4.1.0 + web-pointerevents: 1.0.0 + web-promise: 3.1.0 + web-router: 1.0.0 + web-socket: 4.0.0 + web-storage: 5.0.0 + web-streams: 3.0.0 + web-touchevents: 4.0.0 + web-uievents: 4.0.0 + web-url: 2.0.0 + web-workers: 1.1.0 + web-xhr: 5.0.0 + which: 2.0.0 + yoga-fetch: 1.0.1 + yoga-json: 3.0.2 + yoga-postgres: 6.0.0 + extra_packages: {} +packages: + console: + type: registry + version: 6.0.0 + integrity: sha256-gJpJ53fCDAL8BiCiJXH0HNAJ9K3gJtLo8GDaCK6hA5U= + dependencies: + - effect + - prelude + effect: + type: registry + version: 4.0.0 + integrity: sha256-eBtZu+HZcMa5HilvI6kaDyVX3ji8p0W9MGKy2K4T6+M= + dependencies: + - prelude + prelude: + type: registry + version: 6.0.1 + integrity: sha256-o8p6SLYmVPqzXZhQFd2hGAWEwBoXl1swxLG/scpJ0V0= + dependencies: [] diff --git a/test-fixtures/publish-main-win.txt b/test-fixtures/publish-main-win.txt index bf80c6f98..55aa1f248 100644 --- a/test-fixtures/publish-main-win.txt +++ b/test-fixtures/publish-main-win.txt @@ -1,5 +1,4 @@ Reading Spago workspace configuration... -Read the package set from the registry ✅ Selecting package to build: aaa diff --git a/test-fixtures/publish-main.txt b/test-fixtures/publish-main.txt index ddb7fde8c..8461f8e94 100644 --- a/test-fixtures/publish-main.txt +++ b/test-fixtures/publish-main.txt @@ -1,5 +1,4 @@ Reading Spago workspace configuration... -Read the package set from the registry ✅ Selecting package to build: aaa @@ -18,4 +17,4 @@ Your package "aaa" is not ready for publishing yet, encountered 1 error: in its `src` directory. All package sources must be in the `src` directory, with any additional sources indicated by the `files` key in your manifest. - - src/Main.purs: Module name is Main but PureScript libraries cannot publish modules named: Main, Test.Main \ No newline at end of file + - src/Main.purs: Module name is Main but PureScript libraries cannot publish modules named: Main, Test.Main diff --git a/test-fixtures/publish-no-bounds.txt b/test-fixtures/publish-no-bounds.txt index 24389ce3b..6452f6e72 100644 --- a/test-fixtures/publish-no-bounds.txt +++ b/test-fixtures/publish-no-bounds.txt @@ -1,5 +1,4 @@ Reading Spago workspace configuration... -Read the package set from the registry ✅ Selecting package to build: aaaa @@ -21,4 +20,4 @@ See the configuration file's documentation: https://github.com/purescript/spago# ❌ The configuration is missing version bounds for some packages. Run `spago fetch --ensure-ranges` to add them: - console - effect - - prelude \ No newline at end of file + - prelude diff --git a/test-fixtures/publish-no-config.txt b/test-fixtures/publish-no-config.txt index 02f20fc98..bb509b943 100644 --- a/test-fixtures/publish-no-config.txt +++ b/test-fixtures/publish-no-config.txt @@ -1,8 +1,9 @@ Reading Spago workspace configuration... -Read the package set from the registry ✅ Selecting package to build: aaaa +Lockfile is out of date, generating it... +Lockfile written to spago.lock. Please commit this file. Downloading dependencies... Building... Src Lib All @@ -15,4 +16,4 @@ Your package "aaaa" is not ready for publishing yet, encountered 1 error: ❌ Did not find publishing config: add a valid one in `package.publish`. -See the configuration file's documentation: https://github.com/purescript/spago#the-configuration-file \ No newline at end of file +See the configuration file's documentation: https://github.com/purescript/spago#the-configuration-file diff --git a/test-fixtures/publish-no-git.txt b/test-fixtures/publish-no-git.txt index 24eda5666..b5636ca1d 100644 --- a/test-fixtures/publish-no-git.txt +++ b/test-fixtures/publish-no-git.txt @@ -1,5 +1,4 @@ Reading Spago workspace configuration... -Read the package set from the registry ✅ Selecting package to build: aaa @@ -15,4 +14,4 @@ Errors 0 0 0 ❌ Could not verify whether the git tree is clean due to the below error: Could not run `git status`. Error: Command failed with exit code 128: git status --porcelain -fatal: not a git repository (or any of the parent directories): .git \ No newline at end of file +fatal: not a git repository (or any of the parent directories): .git diff --git a/test-fixtures/publish.txt b/test-fixtures/publish.txt index 540a1cc6a..00e3e6d0b 100644 --- a/test-fixtures/publish.txt +++ b/test-fixtures/publish.txt @@ -1,5 +1,4 @@ Reading Spago workspace configuration... -Read the package set from the registry ✅ Selecting package to build: aaa @@ -11,7 +10,7 @@ Errors 0 0 0 ✅ Build succeeded. -Passed preliminary checks. +Passed preliminary checks. ⚠️ Spago is in offline mode - not pushing the git tag v0.0.1 Building again with the build plan from the solver... Building... @@ -25,4 +24,4 @@ Errors 0 0 0 ✅ Ready for publishing. Calling the registry.. -❌ Spago is offline - not able to call the Registry. \ No newline at end of file +❌ Spago is offline - not able to call the Registry. diff --git a/test-fixtures/spago-install-existing-dep-stderr.txt b/test-fixtures/spago-install-existing-dep-stderr.txt index ecb78e248..d1feb9487 100644 --- a/test-fixtures/spago-install-existing-dep-stderr.txt +++ b/test-fixtures/spago-install-existing-dep-stderr.txt @@ -1,9 +1,7 @@ Reading Spago workspace configuration... -Read the package set from the registry ✅ Selecting package to build: 7368613235362d50744f44764f717435586c685938735a5154 ⚠️ You tried to install some packages that are already present in the configuration, proceeding anyways: - effect -Adding 1 packages to the config in spago.yaml Downloading dependencies... diff --git a/test-fixtures/spago-with-hash.yaml b/test-fixtures/spago-with-hash.yaml deleted file mode 100644 index 99cc7d074..000000000 --- a/test-fixtures/spago-with-hash.yaml +++ /dev/null @@ -1,14 +0,0 @@ -package: - name: aaa - dependencies: - - console - - effect - - prelude - test: - main: Test.Main - dependencies: [] -workspace: - package_set: - url: https://raw.githubusercontent.com/purescript/registry/main/package-sets/29.3.0.json - hash: sha256-LJoXQjRcY0IkP1YJMwvhKAtb4NpxoJW5A6DxapTI+as= - extra_packages: {} diff --git a/test-fixtures/spago-with-maybe.lock b/test-fixtures/spago-with-maybe.lock new file mode 100644 index 000000000..fb7085d92 --- /dev/null +++ b/test-fixtures/spago-with-maybe.lock @@ -0,0 +1,562 @@ +workspace: + packages: + aaa: + path: ./ + dependencies: + - console + - effect + - maybe + - prelude + test_dependencies: [] + build_plan: + - console + - control + - effect + - invariant + - maybe + - newtype + - prelude + - safe-coerce + - unsafe-coerce + package_set: + address: + registry: 33.0.0 + compiler: ">=0.15.10 <0.16.0" + content: + ace: 9.1.0 + aff: 7.1.0 + aff-bus: 6.0.0 + aff-coroutines: 9.0.0 + aff-promise: 4.0.0 + aff-retry: 2.0.0 + affjax: 13.0.0 + affjax-node: 1.0.0 + affjax-web: 1.0.0 + ansi: 7.0.0 + argonaut: 9.0.0 + argonaut-aeson-generic: 0.4.1 + argonaut-codecs: 9.1.0 + argonaut-core: 7.0.0 + argonaut-generic: 8.0.0 + argonaut-traversals: 10.0.0 + argparse-basic: 2.0.0 + array-builder: 0.1.2 + array-search: 0.5.6 + arraybuffer: 13.2.0 + arraybuffer-builder: 3.1.0 + arraybuffer-types: 3.0.2 + arrays: 7.2.1 + arrays-zipper: 2.0.1 + ask: 1.0.0 + assert: 6.0.0 + assert-multiple: 0.3.4 + avar: 5.0.0 + b64: 0.0.8 + barbies: 1.0.1 + barlow-lens: 0.9.0 + basic-auth: 3.0.1 + bifunctors: 6.0.0 + bigints: 7.0.1 + bolson: 0.3.9 + bookhound: 0.1.3 + bower-json: 3.0.0 + bucketchain: 1.0.1 + bucketchain-basic-auth: 1.0.1 + bucketchain-conditional: 1.0.1 + bucketchain-cors: 1.0.1 + bucketchain-csrf: 1.0.1 + bucketchain-header-utils: 1.0.1 + bucketchain-health: 1.0.1 + bucketchain-history-api-fallback: 1.0.1 + bucketchain-logger: 1.0.1 + bucketchain-secure: 1.0.1 + bucketchain-simple-api: 5.0.1 + bucketchain-sslify: 1.0.1 + bucketchain-static: 1.0.1 + call-by-name: 4.0.1 + canvas: 6.0.0 + canvas-action: 9.0.0 + cartesian: 1.0.6 + catenable-lists: 7.0.0 + chameleon: 0.0.5 + chameleon-halogen: 0.0.5 + chameleon-react-basic: 0.1.0 + chameleon-styled: 0.1.0 + chameleon-transformers: 0.1.0 + channel: 1.0.0 + checked-exceptions: 3.1.1 + classless: 0.1.1 + classless-arbitrary: 0.1.1 + classless-decode-json: 0.1.1 + classless-encode-json: 0.1.3 + classnames: 2.0.0 + codec: 6.0.0 + codec-argonaut: 10.0.0 + colors: 7.0.1 + concur-core: 0.5.0 + concur-react: 0.5.0 + concurrent-queues: 3.0.0 + console: 6.0.0 + const: 6.0.0 + contravariant: 6.0.0 + control: 6.0.0 + convertable-options: 1.0.0 + coroutines: 7.0.0 + crypto: 5.0.1 + css: 6.0.0 + css-frameworks: 1.0.1 + data-mvc: 0.0.2 + datetime: 6.1.0 + datetime-parsing: 0.2.0 + debug: 6.0.2 + decimals: 7.1.0 + default-values: 1.0.1 + deku: 0.9.23 + deno: 0.0.5 + dissect: 1.0.0 + distributive: 6.0.0 + dodo-printer: 2.2.1 + dom-filereader: 7.0.0 + dom-indexed: 11.0.0 + dotenv: 4.0.0 + droplet: 0.6.0 + dts: 0.2.0 + dynamic-buffer: 3.0.1 + echarts-simple: 0.0.1 + effect: 4.0.0 + either: 6.1.0 + elmish: 0.10.0 + elmish-enzyme: 0.1.1 + elmish-hooks: 0.9.1 + elmish-html: 0.8.1 + elmish-testing-library: 0.3.1 + email-validate: 7.0.0 + encoding: 0.0.8 + enums: 6.0.1 + env-names: 0.3.4 + error: 2.0.0 + exceptions: 6.0.0 + exists: 6.0.0 + exitcodes: 4.0.0 + expect-inferred: 3.0.0 + fahrtwind: 2.0.0 + fallback: 0.1.0 + fast-vect: 1.1.0 + fetch-argonaut: 1.0.1 + fetch-yoga-json: 1.1.0 + filterable: 5.0.0 + fixed-points: 7.0.0 + fixed-precision: 5.0.0 + flame: 1.3.0 + float32: 2.0.0 + foldable-traversable: 6.0.0 + foreign: 7.0.0 + foreign-object: 4.1.0 + foreign-readwrite: 3.4.0 + forgetmenot: 0.1.0 + fork: 6.0.0 + form-urlencoded: 7.0.0 + formatters: 7.0.0 + framer-motion: 1.0.1 + free: 7.0.0 + freeap: 7.0.0 + freer-free: 0.0.1 + freet: 7.0.0 + functions: 6.0.0 + functor1: 3.0.0 + functors: 5.0.0 + fuzzy: 0.4.0 + gen: 4.0.0 + generate-values: 1.0.1 + generic-router: 0.0.1 + geojson: 0.0.3 + geometry-plane: 1.0.3 + github-actions-toolkit: 0.5.0 + grain: 3.0.0 + grain-router: 3.0.0 + grain-virtualized: 3.0.0 + graphql-client: 9.3.2 + graphs: 8.1.0 + group: 4.1.1 + halogen: 7.0.0 + halogen-bootstrap5: 2.2.0 + halogen-css: 10.0.0 + halogen-echarts-simple: 0.0.4 + halogen-formless: 4.0.3 + halogen-helix: 1.0.0 + halogen-hooks: 0.6.3 + halogen-hooks-extra: 0.9.0 + halogen-store: 0.5.4 + halogen-storybook: 2.0.0 + halogen-subscriptions: 2.0.0 + halogen-svg-elems: 8.0.0 + halogen-typewriter: 1.0.2 + halogen-vdom: 8.0.0 + halogen-vdom-string-renderer: 0.5.0 + heckin: 2.0.1 + heterogeneous: 0.6.0 + homogeneous: 0.4.0 + http-methods: 6.0.0 + httpure: 0.16.0 + httpurple: 3.0.1 + httpurple-argonaut: 1.0.1 + httpurple-yoga-json: 1.0.0 + humdrum: 0.0.1 + hyrule: 2.3.8 + identity: 6.0.0 + identy: 4.0.1 + indexed-db: 1.0.0 + indexed-monad: 3.0.0 + int64: 3.0.0 + integers: 6.0.0 + interactive-data: 0.3.0 + interpolate: 5.0.2 + invariant: 6.0.0 + jarilo: 1.0.1 + jelly: 0.10.0 + jelly-router: 0.3.0 + jelly-signal: 0.4.0 + jest: 1.0.0 + js-abort-controller: 1.0.0 + js-bigints: 2.1.0 + js-date: 8.0.0 + js-fileio: 3.0.0 + js-iterators: 0.1.1 + js-maps: 0.1.2 + js-promise: 1.0.0 + js-promise-aff: 1.0.0 + js-timers: 6.1.0 + js-uri: 3.1.0 + json-codecs: 3.0.0 + justifill: 0.5.0 + jwt: 0.0.9 + labeled-data: 0.2.0 + language-cst-parser: 0.13.0 + lazy: 6.0.0 + lazy-joe: 1.0.0 + lcg: 4.0.0 + leibniz: 5.0.0 + liminal: 1.0.1 + linalg: 6.0.0 + lists: 7.0.0 + literals: 1.0.2 + logging: 3.0.0 + logging-journald: 0.4.0 + machines: 7.0.0 + maps-eager: 0.4.1 + marionette: 1.0.0 + marionette-commander: 0.1.1 + marionette-react-basic-hooks: 0.1.1 + matrices: 5.0.1 + matryoshka: 1.0.0 + maybe: 6.0.0 + mdast-util-from-markdown: 0.2.1 + media-types: 6.0.0 + midi: 4.0.0 + milkis: 9.0.0 + minibench: 4.0.1 + mmorph: 7.0.0 + monad-control: 5.0.0 + monad-logger: 1.3.1 + monad-loops: 0.5.0 + monad-unlift: 1.0.1 + monoid-extras: 0.0.1 + monoidal: 0.16.0 + morello: 0.4.0 + mote: 3.0.0 + motsunabe: 2.0.0 + mvc: 0.0.1 + mysql: 6.0.1 + n3: 0.1.0 + nano-id: 1.1.0 + nanoid: 0.1.0 + naturals: 3.0.0 + nested-functor: 0.2.1 + newtype: 5.0.0 + nextjs: 0.1.1 + nextui: 0.2.0 + node-buffer: 8.0.0 + node-buffer-blob: 1.0.0 + node-child-process: 9.0.0 + node-env-paths: 1.0.0 + node-event-emitter: 3.0.0 + node-execa: 3.0.0 + node-fs: 8.2.0 + node-fs-aff: 9.2.0 + node-http: 8.0.0 + node-human-signals: 1.0.0 + node-net: 4.0.0 + node-os: 5.1.0 + node-path: 5.0.0 + node-process: 10.0.0 + node-readline: 7.0.0 + node-sqlite3: 8.0.0 + node-streams: 7.0.0 + node-streams-aff: 5.0.0 + node-url: 6.0.0 + node-zlib: 0.4.0 + nodemailer: 4.0.1 + nonempty: 7.0.0 + now: 6.0.0 + npm-package-json: 2.0.0 + nullable: 6.0.0 + numberfield: 0.1.0 + numbers: 9.0.1 + oak: 3.1.1 + oak-debug: 1.2.2 + object-maps: 0.3.0 + ocarina: 1.5.4 + open-folds: 6.3.0 + open-memoize: 6.1.0 + open-pairing: 6.1.0 + options: 7.0.0 + optparse: 5.0.0 + ordered-collections: 3.0.0 + ordered-set: 0.4.0 + orders: 6.0.0 + pairs: 9.0.1 + parallel: 6.0.0 + parsing: 10.2.0 + parsing-dataview: 3.2.4 + partial: 4.0.0 + pathy: 9.0.0 + pha: 0.11.0 + phaser: 0.7.0 + phylio: 1.1.2 + pipes: 8.0.0 + pirates-charm: 0.0.1 + pmock: 0.4.0 + point-free: 1.0.0 + pointed-list: 0.5.1 + polymorphic-vectors: 4.0.0 + posix-types: 6.0.0 + precise: 6.0.0 + precise-datetime: 7.0.0 + prelude: 6.0.1 + prettier-printer: 3.0.0 + profunctor: 6.0.0 + profunctor-lenses: 8.0.0 + protobuf: 4.3.0 + ps-cst: 1.2.0 + psa-utils: 8.0.0 + psc-ide: 19.0.0 + psci-support: 6.0.0 + qualified-do: 2.2.0 + quantities: 12.2.0 + quickcheck: 8.0.1 + quickcheck-combinators: 0.1.3 + quickcheck-laws: 7.0.0 + quickcheck-utf8: 0.0.0 + random: 6.0.0 + rationals: 6.0.0 + rdf: 0.1.0 + react: 11.0.0 + react-aria: 0.2.0 + react-basic: 17.0.0 + react-basic-classic: 3.0.0 + react-basic-dnd: 10.1.0 + react-basic-dom: 6.1.0 + react-basic-emotion: 7.1.0 + react-basic-hooks: 8.2.0 + react-basic-storybook: 2.0.0 + react-dom: 8.0.0 + react-halo: 3.0.0 + react-icons: 1.1.1 + react-markdown: 0.1.0 + react-testing-library: 4.0.1 + react-virtuoso: 1.0.0 + read: 1.0.1 + recharts: 1.1.0 + record: 4.0.0 + record-extra: 5.0.1 + record-studio: 1.0.4 + refs: 6.0.0 + remotedata: 5.0.0 + resource: 2.0.1 + resourcet: 1.0.0 + result: 1.0.3 + return: 0.2.0 + ring-modules: 5.0.1 + rito: 0.3.4 + routing: 11.0.0 + routing-duplex: 0.7.0 + run: 5.0.0 + safe-coerce: 2.0.0 + safely: 4.0.1 + school-of-music: 1.3.0 + selection-foldable: 0.2.0 + semirings: 7.0.0 + signal: 13.0.0 + simple-emitter: 3.0.1 + simple-i18n: 2.0.1 + simple-json: 9.0.0 + simple-jwt: 4.0.1 + simple-ulid: 3.0.0 + sized-matrices: 1.0.0 + sized-vectors: 5.0.2 + slug: 3.0.8 + small-ffi: 4.0.1 + soundfonts: 4.1.0 + sparse-matrices: 1.3.0 + sparse-polynomials: 2.0.5 + spec: 7.5.4 + spec-discovery: 8.0.1 + spec-golden: 1.0.0 + spec-mocha: 5.0.0 + spec-quickcheck: 5.0.0 + spec-reporter-xunit: 0.6.1 + splitmix: 2.1.0 + ssrs: 1.0.0 + st: 6.2.0 + statistics: 0.3.2 + strictlypositiveint: 1.0.1 + string-parsers: 8.0.0 + strings: 6.0.1 + strings-extra: 4.0.0 + stringutils: 0.0.12 + substitute: 0.2.3 + sunde: 3.0.0 + supply: 0.2.0 + svg-parser: 3.0.0 + systemd-journald: 0.3.0 + tagged: 4.0.2 + tailrec: 6.1.0 + tecton: 0.2.1 + tecton-halogen: 0.2.0 + test-unit: 17.0.0 + thermite: 6.3.1 + thermite-dom: 0.3.1 + these: 6.0.0 + toppokki: 4.0.0 + transformation-matrix: 1.0.1 + transformers: 6.0.0 + tree-rose: 4.0.2 + ts-bridge: 2.1.2 + tuples: 7.0.0 + two-or-more: 1.0.0 + type-equality: 4.0.1 + typedenv: 2.0.1 + typelevel: 6.0.0 + typelevel-lists: 2.1.0 + typelevel-peano: 1.0.1 + typelevel-prelude: 7.0.0 + typelevel-rows: 0.1.0 + uint: 7.0.0 + ulid: 3.0.1 + uncurried-transformers: 1.1.0 + undefined: 2.0.0 + undefined-is-not-a-problem: 1.1.0 + unfoldable: 6.0.0 + unicode: 6.0.0 + unique: 0.6.1 + unlift: 1.0.1 + unordered-collections: 3.0.1 + unsafe-coerce: 6.0.0 + unsafe-reference: 5.0.0 + untagged-to-tagged: 0.1.4 + untagged-union: 1.0.0 + uri: 9.0.0 + uuid: 9.0.0 + uuidv4: 1.0.0 + validation: 6.0.0 + variant: 8.0.0 + variant-encodings: 2.0.0 + vectorfield: 1.0.1 + vectors: 2.1.0 + versions: 7.0.0 + visx: 0.0.2 + web-clipboard: 5.0.0 + web-cssom: 2.0.0 + web-cssom-view: 0.1.0 + web-dom: 6.0.0 + web-dom-parser: 8.0.0 + web-dom-xpath: 3.0.0 + web-encoding: 3.0.0 + web-events: 4.0.0 + web-fetch: 4.0.1 + web-file: 4.0.0 + web-geometry: 0.1.0 + web-html: 4.1.0 + web-intl: 0.4.0 + web-pointerevents: 1.0.0 + web-proletarian: 1.0.0 + web-resize-observer: 2.0.0 + web-router: 1.0.0 + web-socket: 4.0.0 + web-storage: 5.0.0 + web-streams: 4.0.0 + web-touchevents: 4.0.0 + web-uievents: 4.0.0 + web-url: 2.0.0 + web-workers: 1.1.0 + web-xhr: 5.0.1 + webextension-polyfill: 0.1.0 + webgpu: 0.0.1 + which: 2.0.0 + yoga-fetch: 1.0.1 + yoga-json: 5.1.0 + yoga-om: 0.1.0 + yoga-postgres: 6.0.0 + yoga-tree: 1.0.0 + z3: 0.0.2 + extra_packages: {} +packages: + console: + type: registry + version: 6.0.0 + integrity: sha256-gJpJ53fCDAL8BiCiJXH0HNAJ9K3gJtLo8GDaCK6hA5U= + dependencies: + - effect + - prelude + control: + type: registry + version: 6.0.0 + integrity: sha256-sH7Pg9E96JCPF9PIA6oQ8+BjTyO/BH1ZuE/bOcyj4Jk= + dependencies: + - newtype + - prelude + effect: + type: registry + version: 4.0.0 + integrity: sha256-eBtZu+HZcMa5HilvI6kaDyVX3ji8p0W9MGKy2K4T6+M= + dependencies: + - prelude + invariant: + type: registry + version: 6.0.0 + integrity: sha256-RGWWyYrz0Hs1KjPDA+87Kia67ZFBhfJ5lMGOMCEFoLo= + dependencies: + - control + - prelude + maybe: + type: registry + version: 6.0.0 + integrity: sha256-5cCIb0wPwbat2PRkQhUeZO0jcAmf8jCt2qE0wbC3v2Q= + dependencies: + - control + - invariant + - newtype + - prelude + newtype: + type: registry + version: 5.0.0 + integrity: sha256-gdrQu8oGe9eZE6L3wOI8ql/igOg+zEGB5ITh2g+uttw= + dependencies: + - prelude + - safe-coerce + prelude: + type: registry + version: 6.0.1 + integrity: sha256-o8p6SLYmVPqzXZhQFd2hGAWEwBoXl1swxLG/scpJ0V0= + dependencies: [] + safe-coerce: + type: registry + version: 2.0.0 + integrity: sha256-a1ibQkiUcbODbLE/WAq7Ttbbh9ex+x33VCQ7GngKudU= + dependencies: + - unsafe-coerce + unsafe-coerce: + type: registry + version: 6.0.0 + integrity: sha256-IqIYW4Vkevn8sI+6aUwRGvd87tVL36BBeOr0cGAE7t0= + dependencies: [] diff --git a/test-fixtures/spago.lock b/test-fixtures/spago.lock new file mode 100644 index 000000000..ec80c9f3d --- /dev/null +++ b/test-fixtures/spago.lock @@ -0,0 +1,514 @@ +workspace: + packages: + aaa: + path: ./ + dependencies: + - console + - effect + - prelude + test_dependencies: [] + build_plan: + - console + - effect + - prelude + package_set: + address: + registry: 33.0.0 + compiler: ">=0.15.10 <0.16.0" + content: + ace: 9.1.0 + aff: 7.1.0 + aff-bus: 6.0.0 + aff-coroutines: 9.0.0 + aff-promise: 4.0.0 + aff-retry: 2.0.0 + affjax: 13.0.0 + affjax-node: 1.0.0 + affjax-web: 1.0.0 + ansi: 7.0.0 + argonaut: 9.0.0 + argonaut-aeson-generic: 0.4.1 + argonaut-codecs: 9.1.0 + argonaut-core: 7.0.0 + argonaut-generic: 8.0.0 + argonaut-traversals: 10.0.0 + argparse-basic: 2.0.0 + array-builder: 0.1.2 + array-search: 0.5.6 + arraybuffer: 13.2.0 + arraybuffer-builder: 3.1.0 + arraybuffer-types: 3.0.2 + arrays: 7.2.1 + arrays-zipper: 2.0.1 + ask: 1.0.0 + assert: 6.0.0 + assert-multiple: 0.3.4 + avar: 5.0.0 + b64: 0.0.8 + barbies: 1.0.1 + barlow-lens: 0.9.0 + basic-auth: 3.0.1 + bifunctors: 6.0.0 + bigints: 7.0.1 + bolson: 0.3.9 + bookhound: 0.1.3 + bower-json: 3.0.0 + bucketchain: 1.0.1 + bucketchain-basic-auth: 1.0.1 + bucketchain-conditional: 1.0.1 + bucketchain-cors: 1.0.1 + bucketchain-csrf: 1.0.1 + bucketchain-header-utils: 1.0.1 + bucketchain-health: 1.0.1 + bucketchain-history-api-fallback: 1.0.1 + bucketchain-logger: 1.0.1 + bucketchain-secure: 1.0.1 + bucketchain-simple-api: 5.0.1 + bucketchain-sslify: 1.0.1 + bucketchain-static: 1.0.1 + call-by-name: 4.0.1 + canvas: 6.0.0 + canvas-action: 9.0.0 + cartesian: 1.0.6 + catenable-lists: 7.0.0 + chameleon: 0.0.5 + chameleon-halogen: 0.0.5 + chameleon-react-basic: 0.1.0 + chameleon-styled: 0.1.0 + chameleon-transformers: 0.1.0 + channel: 1.0.0 + checked-exceptions: 3.1.1 + classless: 0.1.1 + classless-arbitrary: 0.1.1 + classless-decode-json: 0.1.1 + classless-encode-json: 0.1.3 + classnames: 2.0.0 + codec: 6.0.0 + codec-argonaut: 10.0.0 + colors: 7.0.1 + concur-core: 0.5.0 + concur-react: 0.5.0 + concurrent-queues: 3.0.0 + console: 6.0.0 + const: 6.0.0 + contravariant: 6.0.0 + control: 6.0.0 + convertable-options: 1.0.0 + coroutines: 7.0.0 + crypto: 5.0.1 + css: 6.0.0 + css-frameworks: 1.0.1 + data-mvc: 0.0.2 + datetime: 6.1.0 + datetime-parsing: 0.2.0 + debug: 6.0.2 + decimals: 7.1.0 + default-values: 1.0.1 + deku: 0.9.23 + deno: 0.0.5 + dissect: 1.0.0 + distributive: 6.0.0 + dodo-printer: 2.2.1 + dom-filereader: 7.0.0 + dom-indexed: 11.0.0 + dotenv: 4.0.0 + droplet: 0.6.0 + dts: 0.2.0 + dynamic-buffer: 3.0.1 + echarts-simple: 0.0.1 + effect: 4.0.0 + either: 6.1.0 + elmish: 0.10.0 + elmish-enzyme: 0.1.1 + elmish-hooks: 0.9.1 + elmish-html: 0.8.1 + elmish-testing-library: 0.3.1 + email-validate: 7.0.0 + encoding: 0.0.8 + enums: 6.0.1 + env-names: 0.3.4 + error: 2.0.0 + exceptions: 6.0.0 + exists: 6.0.0 + exitcodes: 4.0.0 + expect-inferred: 3.0.0 + fahrtwind: 2.0.0 + fallback: 0.1.0 + fast-vect: 1.1.0 + fetch-argonaut: 1.0.1 + fetch-yoga-json: 1.1.0 + filterable: 5.0.0 + fixed-points: 7.0.0 + fixed-precision: 5.0.0 + flame: 1.3.0 + float32: 2.0.0 + foldable-traversable: 6.0.0 + foreign: 7.0.0 + foreign-object: 4.1.0 + foreign-readwrite: 3.4.0 + forgetmenot: 0.1.0 + fork: 6.0.0 + form-urlencoded: 7.0.0 + formatters: 7.0.0 + framer-motion: 1.0.1 + free: 7.0.0 + freeap: 7.0.0 + freer-free: 0.0.1 + freet: 7.0.0 + functions: 6.0.0 + functor1: 3.0.0 + functors: 5.0.0 + fuzzy: 0.4.0 + gen: 4.0.0 + generate-values: 1.0.1 + generic-router: 0.0.1 + geojson: 0.0.3 + geometry-plane: 1.0.3 + github-actions-toolkit: 0.5.0 + grain: 3.0.0 + grain-router: 3.0.0 + grain-virtualized: 3.0.0 + graphql-client: 9.3.2 + graphs: 8.1.0 + group: 4.1.1 + halogen: 7.0.0 + halogen-bootstrap5: 2.2.0 + halogen-css: 10.0.0 + halogen-echarts-simple: 0.0.4 + halogen-formless: 4.0.3 + halogen-helix: 1.0.0 + halogen-hooks: 0.6.3 + halogen-hooks-extra: 0.9.0 + halogen-store: 0.5.4 + halogen-storybook: 2.0.0 + halogen-subscriptions: 2.0.0 + halogen-svg-elems: 8.0.0 + halogen-typewriter: 1.0.2 + halogen-vdom: 8.0.0 + halogen-vdom-string-renderer: 0.5.0 + heckin: 2.0.1 + heterogeneous: 0.6.0 + homogeneous: 0.4.0 + http-methods: 6.0.0 + httpure: 0.16.0 + httpurple: 3.0.1 + httpurple-argonaut: 1.0.1 + httpurple-yoga-json: 1.0.0 + humdrum: 0.0.1 + hyrule: 2.3.8 + identity: 6.0.0 + identy: 4.0.1 + indexed-db: 1.0.0 + indexed-monad: 3.0.0 + int64: 3.0.0 + integers: 6.0.0 + interactive-data: 0.3.0 + interpolate: 5.0.2 + invariant: 6.0.0 + jarilo: 1.0.1 + jelly: 0.10.0 + jelly-router: 0.3.0 + jelly-signal: 0.4.0 + jest: 1.0.0 + js-abort-controller: 1.0.0 + js-bigints: 2.1.0 + js-date: 8.0.0 + js-fileio: 3.0.0 + js-iterators: 0.1.1 + js-maps: 0.1.2 + js-promise: 1.0.0 + js-promise-aff: 1.0.0 + js-timers: 6.1.0 + js-uri: 3.1.0 + json-codecs: 3.0.0 + justifill: 0.5.0 + jwt: 0.0.9 + labeled-data: 0.2.0 + language-cst-parser: 0.13.0 + lazy: 6.0.0 + lazy-joe: 1.0.0 + lcg: 4.0.0 + leibniz: 5.0.0 + liminal: 1.0.1 + linalg: 6.0.0 + lists: 7.0.0 + literals: 1.0.2 + logging: 3.0.0 + logging-journald: 0.4.0 + machines: 7.0.0 + maps-eager: 0.4.1 + marionette: 1.0.0 + marionette-commander: 0.1.1 + marionette-react-basic-hooks: 0.1.1 + matrices: 5.0.1 + matryoshka: 1.0.0 + maybe: 6.0.0 + mdast-util-from-markdown: 0.2.1 + media-types: 6.0.0 + midi: 4.0.0 + milkis: 9.0.0 + minibench: 4.0.1 + mmorph: 7.0.0 + monad-control: 5.0.0 + monad-logger: 1.3.1 + monad-loops: 0.5.0 + monad-unlift: 1.0.1 + monoid-extras: 0.0.1 + monoidal: 0.16.0 + morello: 0.4.0 + mote: 3.0.0 + motsunabe: 2.0.0 + mvc: 0.0.1 + mysql: 6.0.1 + n3: 0.1.0 + nano-id: 1.1.0 + nanoid: 0.1.0 + naturals: 3.0.0 + nested-functor: 0.2.1 + newtype: 5.0.0 + nextjs: 0.1.1 + nextui: 0.2.0 + node-buffer: 8.0.0 + node-buffer-blob: 1.0.0 + node-child-process: 9.0.0 + node-env-paths: 1.0.0 + node-event-emitter: 3.0.0 + node-execa: 3.0.0 + node-fs: 8.2.0 + node-fs-aff: 9.2.0 + node-http: 8.0.0 + node-human-signals: 1.0.0 + node-net: 4.0.0 + node-os: 5.1.0 + node-path: 5.0.0 + node-process: 10.0.0 + node-readline: 7.0.0 + node-sqlite3: 8.0.0 + node-streams: 7.0.0 + node-streams-aff: 5.0.0 + node-url: 6.0.0 + node-zlib: 0.4.0 + nodemailer: 4.0.1 + nonempty: 7.0.0 + now: 6.0.0 + npm-package-json: 2.0.0 + nullable: 6.0.0 + numberfield: 0.1.0 + numbers: 9.0.1 + oak: 3.1.1 + oak-debug: 1.2.2 + object-maps: 0.3.0 + ocarina: 1.5.4 + open-folds: 6.3.0 + open-memoize: 6.1.0 + open-pairing: 6.1.0 + options: 7.0.0 + optparse: 5.0.0 + ordered-collections: 3.0.0 + ordered-set: 0.4.0 + orders: 6.0.0 + pairs: 9.0.1 + parallel: 6.0.0 + parsing: 10.2.0 + parsing-dataview: 3.2.4 + partial: 4.0.0 + pathy: 9.0.0 + pha: 0.11.0 + phaser: 0.7.0 + phylio: 1.1.2 + pipes: 8.0.0 + pirates-charm: 0.0.1 + pmock: 0.4.0 + point-free: 1.0.0 + pointed-list: 0.5.1 + polymorphic-vectors: 4.0.0 + posix-types: 6.0.0 + precise: 6.0.0 + precise-datetime: 7.0.0 + prelude: 6.0.1 + prettier-printer: 3.0.0 + profunctor: 6.0.0 + profunctor-lenses: 8.0.0 + protobuf: 4.3.0 + ps-cst: 1.2.0 + psa-utils: 8.0.0 + psc-ide: 19.0.0 + psci-support: 6.0.0 + qualified-do: 2.2.0 + quantities: 12.2.0 + quickcheck: 8.0.1 + quickcheck-combinators: 0.1.3 + quickcheck-laws: 7.0.0 + quickcheck-utf8: 0.0.0 + random: 6.0.0 + rationals: 6.0.0 + rdf: 0.1.0 + react: 11.0.0 + react-aria: 0.2.0 + react-basic: 17.0.0 + react-basic-classic: 3.0.0 + react-basic-dnd: 10.1.0 + react-basic-dom: 6.1.0 + react-basic-emotion: 7.1.0 + react-basic-hooks: 8.2.0 + react-basic-storybook: 2.0.0 + react-dom: 8.0.0 + react-halo: 3.0.0 + react-icons: 1.1.1 + react-markdown: 0.1.0 + react-testing-library: 4.0.1 + react-virtuoso: 1.0.0 + read: 1.0.1 + recharts: 1.1.0 + record: 4.0.0 + record-extra: 5.0.1 + record-studio: 1.0.4 + refs: 6.0.0 + remotedata: 5.0.0 + resource: 2.0.1 + resourcet: 1.0.0 + result: 1.0.3 + return: 0.2.0 + ring-modules: 5.0.1 + rito: 0.3.4 + routing: 11.0.0 + routing-duplex: 0.7.0 + run: 5.0.0 + safe-coerce: 2.0.0 + safely: 4.0.1 + school-of-music: 1.3.0 + selection-foldable: 0.2.0 + semirings: 7.0.0 + signal: 13.0.0 + simple-emitter: 3.0.1 + simple-i18n: 2.0.1 + simple-json: 9.0.0 + simple-jwt: 4.0.1 + simple-ulid: 3.0.0 + sized-matrices: 1.0.0 + sized-vectors: 5.0.2 + slug: 3.0.8 + small-ffi: 4.0.1 + soundfonts: 4.1.0 + sparse-matrices: 1.3.0 + sparse-polynomials: 2.0.5 + spec: 7.5.4 + spec-discovery: 8.0.1 + spec-golden: 1.0.0 + spec-mocha: 5.0.0 + spec-quickcheck: 5.0.0 + spec-reporter-xunit: 0.6.1 + splitmix: 2.1.0 + ssrs: 1.0.0 + st: 6.2.0 + statistics: 0.3.2 + strictlypositiveint: 1.0.1 + string-parsers: 8.0.0 + strings: 6.0.1 + strings-extra: 4.0.0 + stringutils: 0.0.12 + substitute: 0.2.3 + sunde: 3.0.0 + supply: 0.2.0 + svg-parser: 3.0.0 + systemd-journald: 0.3.0 + tagged: 4.0.2 + tailrec: 6.1.0 + tecton: 0.2.1 + tecton-halogen: 0.2.0 + test-unit: 17.0.0 + thermite: 6.3.1 + thermite-dom: 0.3.1 + these: 6.0.0 + toppokki: 4.0.0 + transformation-matrix: 1.0.1 + transformers: 6.0.0 + tree-rose: 4.0.2 + ts-bridge: 2.1.2 + tuples: 7.0.0 + two-or-more: 1.0.0 + type-equality: 4.0.1 + typedenv: 2.0.1 + typelevel: 6.0.0 + typelevel-lists: 2.1.0 + typelevel-peano: 1.0.1 + typelevel-prelude: 7.0.0 + typelevel-rows: 0.1.0 + uint: 7.0.0 + ulid: 3.0.1 + uncurried-transformers: 1.1.0 + undefined: 2.0.0 + undefined-is-not-a-problem: 1.1.0 + unfoldable: 6.0.0 + unicode: 6.0.0 + unique: 0.6.1 + unlift: 1.0.1 + unordered-collections: 3.0.1 + unsafe-coerce: 6.0.0 + unsafe-reference: 5.0.0 + untagged-to-tagged: 0.1.4 + untagged-union: 1.0.0 + uri: 9.0.0 + uuid: 9.0.0 + uuidv4: 1.0.0 + validation: 6.0.0 + variant: 8.0.0 + variant-encodings: 2.0.0 + vectorfield: 1.0.1 + vectors: 2.1.0 + versions: 7.0.0 + visx: 0.0.2 + web-clipboard: 5.0.0 + web-cssom: 2.0.0 + web-cssom-view: 0.1.0 + web-dom: 6.0.0 + web-dom-parser: 8.0.0 + web-dom-xpath: 3.0.0 + web-encoding: 3.0.0 + web-events: 4.0.0 + web-fetch: 4.0.1 + web-file: 4.0.0 + web-geometry: 0.1.0 + web-html: 4.1.0 + web-intl: 0.4.0 + web-pointerevents: 1.0.0 + web-proletarian: 1.0.0 + web-resize-observer: 2.0.0 + web-router: 1.0.0 + web-socket: 4.0.0 + web-storage: 5.0.0 + web-streams: 4.0.0 + web-touchevents: 4.0.0 + web-uievents: 4.0.0 + web-url: 2.0.0 + web-workers: 1.1.0 + web-xhr: 5.0.1 + webextension-polyfill: 0.1.0 + webgpu: 0.0.1 + which: 2.0.0 + yoga-fetch: 1.0.1 + yoga-json: 5.1.0 + yoga-om: 0.1.0 + yoga-postgres: 6.0.0 + yoga-tree: 1.0.0 + z3: 0.0.2 + extra_packages: {} +packages: + console: + type: registry + version: 6.0.0 + integrity: sha256-gJpJ53fCDAL8BiCiJXH0HNAJ9K3gJtLo8GDaCK6hA5U= + dependencies: + - effect + - prelude + effect: + type: registry + version: 4.0.0 + integrity: sha256-eBtZu+HZcMa5HilvI6kaDyVX3ji8p0W9MGKy2K4T6+M= + dependencies: + - prelude + prelude: + type: registry + version: 6.0.1 + integrity: sha256-o8p6SLYmVPqzXZhQFd2hGAWEwBoXl1swxLG/scpJ0V0= + dependencies: [] diff --git a/test-fixtures/test-missing-module.txt b/test-fixtures/test-missing-module.txt index 41ac0250f..48118579c 100644 --- a/test-fixtures/test-missing-module.txt +++ b/test-fixtures/test-missing-module.txt @@ -1,5 +1,4 @@ Reading Spago workspace configuration... -Read the package set from the registry ✅ Selecting package to build: 7368613235362d6a336156536c675a7033334e7659556c6d38 diff --git a/test-fixtures/test-output-stderr.txt b/test-fixtures/test-output-stderr.txt index f2da8ecc5..6c8684e9f 100644 --- a/test-fixtures/test-output-stderr.txt +++ b/test-fixtures/test-output-stderr.txt @@ -1,5 +1,4 @@ Reading Spago workspace configuration... -Read the package set from the registry ✅ Selecting package to build: 7368613235362d6a336156536c675a7033334e7659556c6d38 diff --git a/test-fixtures/uninstall-deps-undeclared-src-deps.txt b/test-fixtures/uninstall-deps-undeclared-src-deps.txt index 7c5846b9e..adc618e10 100644 --- a/test-fixtures/uninstall-deps-undeclared-src-deps.txt +++ b/test-fixtures/uninstall-deps-undeclared-src-deps.txt @@ -1,8 +1,9 @@ Reading Spago workspace configuration... -Read the package set from the registry ✅ Selecting package to build: uninstall-tests ⚠️ The following packages cannot be uninstalled because they are not declared in the package's source dependencies: - either -The package config for uninstall-tests was not updated. + either +⚠️ The package config for uninstall-tests was not updated. +No lockfile found, generating it... +Lockfile written to spago.lock. Please commit this file. diff --git a/test-fixtures/uninstall-deps-undeclared-test-deps.txt b/test-fixtures/uninstall-deps-undeclared-test-deps.txt index a98c42f1a..f7b3d8654 100644 --- a/test-fixtures/uninstall-deps-undeclared-test-deps.txt +++ b/test-fixtures/uninstall-deps-undeclared-test-deps.txt @@ -1,8 +1,9 @@ Reading Spago workspace configuration... -Read the package set from the registry ✅ Selecting package to build: uninstall-tests ⚠️ The following packages cannot be uninstalled because they are not declared in the package's test dependencies: - either -The package config for uninstall-tests was not updated. + either +⚠️ The package config for uninstall-tests was not updated. +No lockfile found, generating it... +Lockfile written to spago.lock. Please commit this file. diff --git a/test-fixtures/uninstall-no-package-selection.txt b/test-fixtures/uninstall-no-package-selection.txt index e1f326301..cfa2801c2 100644 --- a/test-fixtures/uninstall-no-package-selection.txt +++ b/test-fixtures/uninstall-no-package-selection.txt @@ -1,5 +1,4 @@ Reading Spago workspace configuration... -Read the package set from the registry ✅ Selecting 2 packages to build: bar diff --git a/test-fixtures/uninstall-no-test-config.txt b/test-fixtures/uninstall-no-test-config.txt index db33dfcc4..28eb91468 100644 --- a/test-fixtures/uninstall-no-test-config.txt +++ b/test-fixtures/uninstall-no-test-config.txt @@ -1,5 +1,4 @@ Reading Spago workspace configuration... -Read the package set from the registry ✅ Selecting package to build: uninstall-tests diff --git a/test-fixtures/uninstall-remove-src-deps.txt b/test-fixtures/uninstall-remove-src-deps.txt index 23d474152..891850a33 100644 --- a/test-fixtures/uninstall-remove-src-deps.txt +++ b/test-fixtures/uninstall-remove-src-deps.txt @@ -1,7 +1,7 @@ Reading Spago workspace configuration... -Read the package set from the registry ✅ Selecting package to build: uninstall-tests -Removing the following source dependencies: - either +Removing the following source dependencies: either +Lockfile is out of date (uninstalled packages), generating it... +Lockfile written to spago.lock. Please commit this file. diff --git a/test-fixtures/uninstall-remove-test-deps.txt b/test-fixtures/uninstall-remove-test-deps.txt index 70b7e7271..525d292dc 100644 --- a/test-fixtures/uninstall-remove-test-deps.txt +++ b/test-fixtures/uninstall-remove-test-deps.txt @@ -1,7 +1,7 @@ Reading Spago workspace configuration... -Read the package set from the registry ✅ Selecting package to build: uninstall-tests -Removing the following test dependencies: - either +Removing the following test dependencies: either +Lockfile is out of date (uninstalled packages), generating it... +Lockfile written to spago.lock. Please commit this file. diff --git a/test/Prelude.purs b/test/Prelude.purs index e71b3dd5c..d9d4f00ac 100644 --- a/test/Prelude.purs +++ b/test/Prelude.purs @@ -173,10 +173,10 @@ checkOutputs checkers execResult = do Console.log $ "Overwriting fixture at path: " <> fixtureFileExpected let parentDir = dirname fixtureFileExpected unlessM (FS.exists parentDir) $ FS.mkdirp parentDir - FS.writeTextFile fixtureFileExpected actual + FS.writeTextFile fixtureFileExpected (actual <> "\n") else do expected <- String.trim <$> FS.readTextFile fixtureFileExpected - actual `Assert.shouldEqual` expected + actual `shouldEqualStr` expected check { stdout: checkOrOverwrite checkers.stdoutFile , stderr: checkOrOverwrite checkers.stderrFile diff --git a/test/Spago/Build.purs b/test/Spago/Build.purs index b1e411a01..33a23aa0a 100644 --- a/test/Spago/Build.purs +++ b/test/Spago/Build.purs @@ -8,9 +8,10 @@ import Node.Process as Process import Spago.Command.Init as Init import Spago.Core.Config as Config import Spago.FS as FS +import Spago.Paths as Paths +import Test.Spago.Build.BuildInfo as BuildInfo import Test.Spago.Build.Pedantic as Pedantic import Test.Spago.Build.Polyrepo as BuildPolyrepo -import Test.Spago.Build.BuildInfo as BuildInfo import Test.Spec (Spec) import Test.Spec as Spec import Test.Spec.Assertions as Assert @@ -106,6 +107,36 @@ spec = Spec.around withTempDir do } spago [ "build" ] >>= shouldBeFailure + Spec.it "building with a lockfile doesn't need the Registry repo" \{ spago, fixture } -> do + spago [ "init", "--name", "aaa", "--package-set", "33.0.0" ] >>= shouldBeSuccess + spago [ "build" ] >>= shouldBeSuccess + -- Check that we have written the lockfile + checkFixture "spago.lock" (fixture "spago.lock") + -- Then remove the registry repo + FSA.rm' Paths.registryPath { force: true, recursive: true, retryDelay: 0, maxRetries: 0 } + -- And check that we can still build + spago [ "build" ] >>= shouldBeSuccess + -- And that we still don't have the registry + FS.exists Paths.registryPath `Assert.shouldReturn` false + + Spec.it "using the --pure flag does not refresh the lockfile" \{ spago, fixture } -> do + spago [ "init", "--name", "aaa", "--package-set", "33.0.0" ] >>= shouldBeSuccess + spago [ "build" ] >>= shouldBeSuccess + -- Check that we have written the lockfile + checkFixture "spago.lock" (fixture "spago.lock") + -- Update the config + let + conf = Init.defaultConfig + { name: mkPackageName "aaa" + , testModuleName: "Test.Main" + , withWorkspace: Just { setVersion: Just $ mkVersion "33.0.0" } + } + FS.writeYamlFile Config.configCodec "spago.yaml" + (conf { package = conf.package # map (\pkg -> pkg { dependencies = pkg.dependencies <> mkDependencies [ "maybe" ] }) }) + -- Check that building with --pure does not refresh the lockfile + spago [ "build", "--pure" ] >>= shouldBeSuccess + checkFixture "spago.lock" (fixture "spago.lock") + Spec.it "compiles with the specified backend" \{ spago, fixture } -> do spago [ "init" ] >>= shouldBeSuccess let diff --git a/test/Spago/Build/Polyrepo.purs b/test/Spago/Build/Polyrepo.purs index c9952681a..0013eaa41 100644 --- a/test/Spago/Build/Polyrepo.purs +++ b/test/Spago/Build/Polyrepo.purs @@ -171,12 +171,13 @@ spec = Spec.describe "polyrepo" do end ``` -} - Spec.it "Case 3 (dependencies: A&B -> C; A -> B) builds" \{ spago } -> do + Spec.it "Case 3 (dependencies: A&B -> C; A -> B) builds" \{ spago, fixture } -> do writeWorkspaceOnlySpagoYamlFile pkgC <- setupPackageWithDeps { packageName: "package-c", hasTest: false, deps: [] } pkgB <- setupPackageWithDeps { packageName: "package-b", hasTest: true, deps: [ pkgC ] } void $ setupPackageWithDeps { packageName: "package-a", hasTest: true, deps: [ pkgC, pkgB ] } spago [ "build" ] >>= shouldBeSuccess + checkFixture "spago.lock" (fixture "polyrepo.lock") {- ```mermaid diff --git a/test/Spago/Install.purs b/test/Spago/Install.purs index 529e86104..f902c9807 100644 --- a/test/Spago/Install.purs +++ b/test/Spago/Install.purs @@ -22,7 +22,7 @@ spec :: Spec Unit spec = Spec.around withTempDir do Spec.describe "install" do - Spec.it "warns that config was not changed when trying to install a package already present in project dependencies" \{ spago, fixture } -> do + Spec.it "warns that the config was not changed when trying to install a package already present in project dependencies" \{ spago, fixture } -> do spago [ "init", "--name", "7368613235362d50744f44764f717435586c685938735a5154" ] >>= shouldBeSuccess spago [ "install" ] >>= shouldBeSuccess spago [ "fetch", "effect" ] >>= shouldBeSuccessErr (fixture "spago-install-existing-dep-stderr.txt") @@ -211,32 +211,6 @@ spec = Spec.around withTempDir do spago [ "install", "-p", "subpackage", "either" ] >>= shouldBeSuccess checkFixture "subpackage/spago.yaml" (fixture "spago-subpackage-install-success.yaml") - Spec.it "adds a hash to the package set when importing it from a URL" \{ spago, fixture } -> do - spago [ "init" ] >>= shouldBeSuccess - let - conf = Init.defaultConfig - { name: mkPackageName "aaa" - , withWorkspace: Just - { setVersion: Just $ unsafeFromRight $ Version.parse "0.0.1" } - , testModuleName: "Test.Main" - } - FS.writeYamlFile Config.configCodec "spago.yaml" - ( conf - { workspace = conf.workspace # map - ( _ - { package_set = Just - ( Config.SetFromUrl - { hash: Nothing - , url: "https://raw.githubusercontent.com/purescript/registry/main/package-sets/29.3.0.json" - } - ) - } - ) - } - ) - spago [ "install" ] >>= shouldBeSuccess - checkFixture "spago.yaml" (fixture "spago-with-hash.yaml") - Spec.it "can build with a newer (but still compatible) compiler than the one in the package set" \{ spago } -> do spago [ "init", "--package-set", "10.0.0" ] >>= shouldBeSuccess startingTime <- liftEffect $ Now.now @@ -247,6 +221,18 @@ spec = Spec.around withTempDir do false -> Assert.fail $ "Expected purs version to be newer than 0.15.4, but it was " <> Version.print purs.version spago [ "install" ] >>= shouldBeSuccess + Spec.it "can refresh the lockfile, and uninstall restores it" \{ spago, fixture } -> do + spago [ "init", "--name", "aaa", "--package-set", "33.0.0" ] >>= shouldBeSuccess + spago [ "build" ] >>= shouldBeSuccess + -- Check that we have written the lockfile + checkFixture "spago.lock" (fixture "spago.lock") + spago [ "install", "maybe" ] >>= shouldBeSuccess + -- Check that the new lockfile includes maybe + checkFixture "spago.lock" (fixture "spago-with-maybe.lock") + spago [ "uninstall", "maybe" ] >>= shouldBeSuccess + -- Check that the lockfile is back to the original + checkFixture "spago.lock" (fixture "spago.lock") + writeConfigWithEither :: Aff Unit writeConfigWithEither = do -- The commit for `either` is for the `v6.1.0` release diff --git a/test/Spago/Lock.purs b/test/Spago/Lock.purs index c184b1819..31cd15be3 100644 --- a/test/Spago/Lock.purs +++ b/test/Spago/Lock.purs @@ -4,11 +4,13 @@ import Test.Prelude import Data.Codec.Argonaut as CA import Data.Map as Map +import Data.Set as Set import Registry.Range as Range import Registry.Sha256 as Sha256 import Registry.Version as Version import Spago.Core.Config (Dependencies(..), ExtraPackage(..), RemotePackage(..), SetAddress(..)) import Spago.Core.Config as Config +import Spago.Core.Config as Core import Spago.Lock (LockEntry(..), Lockfile) import Spago.Lock as Lock import Test.Spec (Spec) @@ -37,14 +39,29 @@ validLockfile = ] , test_dependencies: Dependencies Map.empty , path: "my-app" + , build_plan: Set.fromFoldable + [ mkPackageName "my-library" + , mkPackageName "effect" + , mkPackageName "prelude" + ] } , packageTuple "my-library" { dependencies: Dependencies $ Map.fromFoldable [ packageTuple "prelude" Nothing ] , test_dependencies: Dependencies $ Map.fromFoldable [ packageTuple "console" (Just Config.widestRange) ] , path: "my-library" + , build_plan: Set.fromFoldable [ mkPackageName "prelude" ] } ] - , package_set: Just $ SetFromRegistry { registry: unsafeFromRight (Version.parse "22.1.1") } + , package_set: Just + { address: SetFromRegistry { registry: unsafeFromRight (Version.parse "22.1.1") } + , compiler: unsafeFromRight (Range.parse ">=0.13.8 <0.14.0") + -- This is not actually the content of the package set, but you get the idea + , content: Map.fromFoldable + [ Tuple (mkPackageName "effect") (Core.RemoteRegistryVersion $ mkVersion "4.0.0") + , Tuple (mkPackageName "prelude") (Core.RemoteRegistryVersion $ mkVersion "4.0.0") + , Tuple (mkPackageName "console") (Core.RemoteRegistryVersion $ mkVersion "4.0.0") + ] + } , extra_packages: Map.fromFoldable [ packageTuple "console" $ ExtraRemotePackage $ RemoteGitPackage { git: "https://github.com/purescript/purescript-console.git" @@ -62,23 +79,26 @@ validLockfile = } , packages: Map.fromFoldable - [ packageTuple "console" $ FromGit - { url: "https://github.com/purescript/purescript-console.git" - , rev: "3b83d7b792d03872afeea5e62b4f686ab0f09842" - , subdir: Nothing - , dependencies: [ prelude ] - } - , packageTuple "effect" $ FromRegistry - { version: unsafeFromRight (Version.parse "4.0.0") - , integrity: unsafeFromRight (Sha256.parse "sha256-eBtZu+HZcMa5HilvI6kaDyVX3ji8p0W9MGKy2K4T6+M=") - , dependencies: [ prelude ] - } - , packageTuple "prelude" $ FromGit - { url: "https://github.com/purescript/purescript-libraries.git" - , rev: "3b83d7b792d03872afeea5e62b4f686ab0f09842" - , subdir: Just "prelude" - , dependencies: [] - } + [ packageTuple "console" $ + FromGit + { url: "https://github.com/purescript/purescript-console.git" + , rev: "3b83d7b792d03872afeea5e62b4f686ab0f09842" + , subdir: Nothing + , dependencies: [ prelude ] + } + , packageTuple "effect" $ + FromRegistry + { version: unsafeFromRight (Version.parse "4.0.0") + , integrity: unsafeFromRight (Sha256.parse "sha256-eBtZu+HZcMa5HilvI6kaDyVX3ji8p0W9MGKy2K4T6+M=") + , dependencies: [ prelude ] + } + , packageTuple "prelude" $ + FromGit + { url: "https://github.com/purescript/purescript-libraries.git" + , rev: "3b83d7b792d03872afeea5e62b4f686ab0f09842" + , subdir: Just "prelude" + , dependencies: [] + } ] } where @@ -95,6 +115,10 @@ workspace: packages: my-app: path: my-app + build_plan: + - effect + - my-library + - prelude dependencies: - effect: ">=1.0.0 <5.0.0" - my-library @@ -102,14 +126,21 @@ workspace: my-library: path: my-library + build_plan: + - prelude dependencies: - prelude test_dependencies: - console: "*" package_set: - registry: 22.1.1 - + address: + registry: 22.1.1 + compiler: ">=0.13.8 <0.14.0" + content: + console: 4.0.0 + effect: 4.0.0 + prelude: 4.0.0 extra_packages: console: git: https://github.com/purescript/purescript-console.git diff --git a/test/Spago/Publish.purs b/test/Spago/Publish.purs index 0c59ec6ce..a82093b48 100644 --- a/test/Spago/Publish.purs +++ b/test/Spago/Publish.purs @@ -32,7 +32,7 @@ spec = Spec.around withTempDir do spago [ "build" ] >>= shouldBeSuccess spago [ "publish", "--offline" ] >>= shouldBeFailureErr (fixture "publish-no-git.txt") - Spec.it "fails the module is called Main" \{ spago, fixture } -> do + Spec.it "fails if the module is called Main" \{ spago, fixture } -> do spago [ "init", "--name", "aaaa" ] >>= shouldBeSuccess FSA.unlink "spago.yaml" FS.copyFile { src: fixture "spago-publish.yaml", dst: "spago.yaml" } From 595e45f34f0f7117c262944d4b8581b6343ba2b3 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Tue, 26 Dec 2023 17:30:01 -0800 Subject: [PATCH 10/21] Update package set; drop unneeded mods --- spago.lock | 78 ++++++++++++++++++------------------------------------ spago.yaml | 38 +------------------------- 2 files changed, 27 insertions(+), 89 deletions(-) diff --git a/spago.lock b/spago.lock index f9801b0a0..befc4589f 100644 --- a/spago.lock +++ b/spago.lock @@ -801,8 +801,8 @@ workspace: - variant package_set: address: - registry: 46.0.0 - compiler: ">=0.15.12 <0.16.0" + registry: 47.9.1 + compiler: ">=0.15.13 <0.16.0" content: abc-parser: 2.0.1 ace: 9.1.0 @@ -829,7 +829,7 @@ workspace: arraybuffer-builder: 3.1.0 arraybuffer-types: 3.0.2 arrays: 7.3.0 - arrays-extra: 0.4.2 + arrays-extra: 0.4.4 arrays-zipper: 2.0.1 ask: 1.0.0 assert: 6.0.0 @@ -841,7 +841,7 @@ workspace: bifunctors: 6.0.0 bigints: 7.0.1 bolson: 0.3.9 - bookhound: 0.1.5 + bookhound: 0.1.7 bower-json: 3.0.0 call-by-name: 4.0.1 canvas: 6.0.0 @@ -889,7 +889,7 @@ workspace: dom-indexed: 12.0.0 dotenv: 4.0.3 droplet: 0.6.0 - dts: 0.2.0 + dts: 1.0.0 dual-numbers: 1.0.2 dynamic-buffer: 3.0.1 echarts-simple: 0.0.1 @@ -905,14 +905,15 @@ workspace: enums: 6.0.1 env-names: 0.3.4 error: 2.0.0 + eta-conversion: 0.3.2 exceptions: 6.0.0 exists: 6.0.0 exitcodes: 4.0.0 expect-inferred: 3.0.0 fahrtwind: 2.0.0 fallback: 0.1.0 - fast-vect: 1.1.0 - fetch: 4.0.0 + fast-vect: 1.2.0 + fetch: 4.1.0 fetch-argonaut: 1.0.1 fetch-core: 5.1.0 fetch-yoga-json: 1.1.0 @@ -951,7 +952,7 @@ workspace: graphs: 8.1.0 group: 4.1.1 halogen: 7.0.0 - halogen-bootstrap5: 2.2.0 + halogen-bootstrap5: 2.3.1 halogen-css: 10.0.0 halogen-echarts-simple: 0.0.4 halogen-formless: 4.0.3 @@ -962,7 +963,7 @@ workspace: halogen-storybook: 2.0.0 halogen-subscriptions: 2.0.0 halogen-svg-elems: 8.0.0 - halogen-typewriter: 1.0.2 + halogen-typewriter: 1.0.4 halogen-vdom: 8.0.0 halogen-vdom-string-renderer: 0.5.0 heckin: 2.0.1 @@ -1017,10 +1018,12 @@ workspace: maps-eager: 0.4.1 marionette: 1.0.0 marionette-react-basic-hooks: 0.1.1 + marked: 0.1.0 matrices: 5.0.1 matryoshka: 1.0.0 maybe: 6.0.0 media-types: 6.0.0 + meowclient: 1.0.0 midi: 4.0.0 milkis: 9.0.0 minibench: 4.0.1 @@ -1049,6 +1052,7 @@ workspace: node-event-emitter: 3.0.0 node-execa: 5.0.0 node-fs: 9.1.0 + node-glob-basic: 1.3.0 node-http: 9.1.0 node-http2: 1.1.1 node-human-signals: 1.0.0 @@ -1076,9 +1080,11 @@ workspace: open-memoize: 6.1.0 open-pairing: 6.1.0 options: 7.0.0 + optparse: 5.0.1 ordered-collections: 3.1.1 ordered-set: 0.4.0 orders: 6.0.0 + owoify: 1.2.0 pairs: 9.0.1 parallel: 7.0.0 parsing: 10.2.0 @@ -1090,7 +1096,7 @@ workspace: phylio: 1.1.2 pipes: 8.0.0 pirates-charm: 0.0.1 - pmock: 0.6.0 + pmock: 0.9.0 point-free: 1.0.0 pointed-list: 0.5.1 polymorphic-vectors: 4.0.0 @@ -1132,6 +1138,7 @@ workspace: recharts: 1.1.0 record: 4.0.0 record-extra: 5.0.1 + record-ptional-fields: 0.1.2 record-studio: 1.0.4 refs: 6.0.0 remotedata: 5.0.0 @@ -1189,7 +1196,7 @@ workspace: transformation-matrix: 1.0.1 transformers: 6.0.0 tree-rose: 4.0.2 - ts-bridge: 2.2.0 + ts-bridge: 4.0.0 tuples: 7.0.0 two-or-more: 1.0.0 type-equality: 4.0.1 @@ -1239,7 +1246,7 @@ workspace: web-pointerevents: 2.0.0 web-proletarian: 1.0.0 web-promise: 3.2.0 - web-resize-observer: 2.0.0 + web-resize-observer: 2.1.0 web-router: 1.0.0 web-socket: 4.0.0 web-storage: 5.0.0 @@ -1407,41 +1414,6 @@ workspace: - refs - strings - tuples - optparse: - git: https://github.com/thought2/purescript-optparse.git - ref: a9b227110c34ae4f8c1b2fcb07de6f1327ce5826 - dependencies: - - aff - - arrays - - bifunctors - - console - - control - - effect - - either - - enums - - exists - - exitcodes - - foldable-traversable - - free - - gen - - integers - - lazy - - lists - - maybe - - newtype - - node-buffer - - node-process - - node-streams - - nonempty - - numbers - - open-memoize - - partial - - prelude - - strings - - tailrec - - transformers - - tuples - ordered-collections: 3.1.1 registry-foreign: git: https://github.com/purescript/registry-dev.git ref: d7d35c94cc286528e506a6a7ca78d22c84b251c9 @@ -1903,16 +1875,18 @@ packages: - enums fetch: type: registry - version: 4.0.0 - integrity: sha256-Ita74WPIvzCsSIkUQQbBDKgIrsnuBWIRzEJ8Q5P7iQU= + version: 4.1.0 + integrity: sha256-zCwBUkRL9n6nUhK1+7UqqsuxswPFATsZfGSBOA3NYYY= dependencies: - aff - arraybuffer-types - bifunctors - effect + - either - foreign - http-methods - js-fetch + - js-promise - js-promise-aff - maybe - newtype @@ -2669,9 +2643,9 @@ packages: - maybe - tuples optparse: - type: git - url: https://github.com/thought2/purescript-optparse.git - rev: a9b227110c34ae4f8c1b2fcb07de6f1327ce5826 + type: registry + version: 5.0.1 + integrity: sha256-cEzEkNW4q0gZlXl4z0zn+H2vs6l2UAp7NPHCsois73k= dependencies: - aff - arrays diff --git a/spago.yaml b/spago.yaml index 7e7af4890..41ddc480f 100644 --- a/spago.yaml +++ b/spago.yaml @@ -61,7 +61,7 @@ package: - spec workspace: package_set: - registry: 46.0.0 + registry: 47.9.1 extra_packages: registry-lib: git: https://github.com/purescript/registry-dev.git @@ -270,7 +270,6 @@ workspace: - refs - strings - tuples - ordered-collections: "3.1.1" dodo-printer: git: "https://github.com/natefaubion/purescript-dodo-printer.git" ref: "v2.2.1" @@ -295,38 +294,3 @@ workspace: - safe-coerce - strings - tuples - optparse: - git: "https://github.com/thought2/purescript-optparse.git" - ref: "a9b227110c34ae4f8c1b2fcb07de6f1327ce5826" - dependencies: - - aff - - arrays - - bifunctors - - console - - control - - effect - - either - - enums - - exists - - exitcodes - - foldable-traversable - - free - - gen - - integers - - lazy - - lists - - maybe - - newtype - - node-buffer - - node-process - - node-streams - - nonempty - - numbers - - open-memoize - - partial - - prelude - - strings - - tailrec - - transformers - - tuples - From fa97e890744e549c6af8d952fcee74c5ef37377c Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Wed, 10 Jan 2024 13:58:35 -0600 Subject: [PATCH 11/21] Update `packages` dir to `p` --- src/Spago/Paths.purs | 10 +- test-fixtures/graph-modules.json | 112 ++++++++++---------- test-fixtures/sources-output.txt | 6 +- test-fixtures/sources-subproject-output.txt | 6 +- test/Spago/Install.purs | 2 +- 5 files changed, 71 insertions(+), 65 deletions(-) diff --git a/src/Spago/Paths.purs b/src/Spago/Paths.purs index 348e7efd6..11e09489f 100644 --- a/src/Spago/Paths.purs +++ b/src/Spago/Paths.purs @@ -27,10 +27,16 @@ globalCachePath :: FilePath globalCachePath = paths.cache localCachePath :: FilePath -localCachePath = Path.concat [ cwd, ".spago" ] +localCachePath = toLocalCachePath cwd localCachePackagesPath :: FilePath -localCachePackagesPath = Path.concat [ localCachePath, "packages" ] +localCachePackagesPath = toLocalCachePackagesPath cwd + +toLocalCachePath :: FilePath -> FilePath +toLocalCachePath rootDir = Path.concat [ rootDir, ".spago" ] + +toLocalCachePackagesPath :: FilePath -> FilePath +toLocalCachePackagesPath rootDir = Path.concat [ toLocalCachePath rootDir, "p" ] registryPath ∷ FilePath registryPath = Path.concat [ globalCachePath, "registry" ] diff --git a/test-fixtures/graph-modules.json b/test-fixtures/graph-modules.json index 771326b17..a7e487dfa 100644 --- a/test-fixtures/graph-modules.json +++ b/test-fixtures/graph-modules.json @@ -7,7 +7,7 @@ "Type.Proxy" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Control/Applicative.purs" + "path": ".spago/p/prelude-6.0.1/src/Control/Applicative.purs" }, "Control.Apply": { "depends": [ @@ -17,7 +17,7 @@ "Type.Proxy" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Control/Apply.purs" + "path": ".spago/p/prelude-6.0.1/src/Control/Apply.purs" }, "Control.Bind": { "depends": [ @@ -30,14 +30,14 @@ "Type.Proxy" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Control/Bind.purs" + "path": ".spago/p/prelude-6.0.1/src/Control/Bind.purs" }, "Control.Category": { "depends": [ "Control.Semigroupoid" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Control/Category.purs" + "path": ".spago/p/prelude-6.0.1/src/Control/Category.purs" }, "Control.Monad": { "depends": [ @@ -49,17 +49,17 @@ "Type.Proxy" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Control/Monad.purs" + "path": ".spago/p/prelude-6.0.1/src/Control/Monad.purs" }, "Control.Semigroupoid": { "depends": [], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Control/Semigroupoid.purs" + "path": ".spago/p/prelude-6.0.1/src/Control/Semigroupoid.purs" }, "Data.Boolean": { "depends": [], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/Boolean.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/Boolean.purs" }, "Data.BooleanAlgebra": { "depends": [ @@ -69,7 +69,7 @@ "Type.Proxy" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/BooleanAlgebra.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/BooleanAlgebra.purs" }, "Data.Bounded": { "depends": [ @@ -80,7 +80,7 @@ "Type.Proxy" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/Bounded.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/Bounded.purs" }, "Data.Bounded.Generic": { "depends": [ @@ -88,7 +88,7 @@ "Data.Bounded" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/Bounded/Generic.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/Bounded/Generic.purs" }, "Data.CommutativeRing": { "depends": [ @@ -99,7 +99,7 @@ "Type.Proxy" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/CommutativeRing.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/CommutativeRing.purs" }, "Data.DivisionRing": { "depends": [ @@ -108,7 +108,7 @@ "Data.Semiring" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/DivisionRing.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/DivisionRing.purs" }, "Data.Eq": { "depends": [ @@ -120,7 +120,7 @@ "Type.Proxy" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/Eq.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/Eq.purs" }, "Data.Eq.Generic": { "depends": [ @@ -128,7 +128,7 @@ "Data.Generic.Rep" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/Eq/Generic.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/Eq/Generic.purs" }, "Data.EuclideanRing": { "depends": [ @@ -139,7 +139,7 @@ "Data.Semiring" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/EuclideanRing.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/EuclideanRing.purs" }, "Data.Field": { "depends": [ @@ -150,7 +150,7 @@ "Data.Semiring" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/Field.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/Field.purs" }, "Data.Function": { "depends": [ @@ -160,7 +160,7 @@ "Data.Ring" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/Function.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/Function.purs" }, "Data.Functor": { "depends": [ @@ -169,7 +169,7 @@ "Type.Proxy" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/Functor.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/Functor.purs" }, "Data.Generic.Rep": { "depends": [ @@ -180,7 +180,7 @@ "Type.Proxy" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/Generic/Rep.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/Generic/Rep.purs" }, "Data.HeytingAlgebra": { "depends": [ @@ -190,7 +190,7 @@ "Type.Proxy" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/HeytingAlgebra.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/HeytingAlgebra.purs" }, "Data.HeytingAlgebra.Generic": { "depends": [ @@ -199,7 +199,7 @@ "Data.HeytingAlgebra" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/HeytingAlgebra/Generic.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/HeytingAlgebra/Generic.purs" }, "Data.Monoid": { "depends": [ @@ -215,7 +215,7 @@ "Type.Proxy" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/Monoid.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/Monoid.purs" }, "Data.Monoid.Additive": { "depends": [ @@ -224,7 +224,7 @@ "Data.Ord" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/Monoid/Additive.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/Monoid/Additive.purs" }, "Data.Monoid.Conj": { "depends": [ @@ -234,7 +234,7 @@ "Data.Ord" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/Monoid/Conj.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/Monoid/Conj.purs" }, "Data.Monoid.Disj": { "depends": [ @@ -244,7 +244,7 @@ "Data.Ord" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/Monoid/Disj.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/Monoid/Disj.purs" }, "Data.Monoid.Dual": { "depends": [ @@ -253,14 +253,14 @@ "Data.Ord" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/Monoid/Dual.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/Monoid/Dual.purs" }, "Data.Monoid.Endo": { "depends": [ "Prelude" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/Monoid/Endo.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/Monoid/Endo.purs" }, "Data.Monoid.Generic": { "depends": [ @@ -268,7 +268,7 @@ "Data.Generic.Rep" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/Monoid/Generic.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/Monoid/Generic.purs" }, "Data.Monoid.Multiplicative": { "depends": [ @@ -277,12 +277,12 @@ "Data.Ord" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/Monoid/Multiplicative.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/Monoid/Multiplicative.purs" }, "Data.NaturalTransformation": { "depends": [], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/NaturalTransformation.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/NaturalTransformation.purs" }, "Data.Ord": { "depends": [ @@ -296,7 +296,7 @@ "Type.Proxy" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/Ord.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/Ord.purs" }, "Data.Ord.Generic": { "depends": [ @@ -304,7 +304,7 @@ "Data.Generic.Rep" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/Ord/Generic.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/Ord/Generic.purs" }, "Data.Ordering": { "depends": [ @@ -313,7 +313,7 @@ "Data.Show" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/Ordering.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/Ordering.purs" }, "Data.Reflectable": { "depends": [ @@ -321,7 +321,7 @@ "Type.Proxy" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/Reflectable.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/Reflectable.purs" }, "Data.Ring": { "depends": [ @@ -332,7 +332,7 @@ "Type.Proxy" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/Ring.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/Ring.purs" }, "Data.Ring.Generic": { "depends": [ @@ -340,7 +340,7 @@ "Data.Generic.Rep" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/Ring/Generic.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/Ring/Generic.purs" }, "Data.Semigroup": { "depends": [ @@ -351,7 +351,7 @@ "Type.Proxy" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/Semigroup.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/Semigroup.purs" }, "Data.Semigroup.First": { "depends": [ @@ -360,7 +360,7 @@ "Data.Ord" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/Semigroup/First.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/Semigroup/First.purs" }, "Data.Semigroup.Generic": { "depends": [ @@ -368,7 +368,7 @@ "Data.Generic.Rep" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/Semigroup/Generic.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/Semigroup/Generic.purs" }, "Data.Semigroup.Last": { "depends": [ @@ -377,7 +377,7 @@ "Data.Ord" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/Semigroup/Last.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/Semigroup/Last.purs" }, "Data.Semiring": { "depends": [ @@ -387,7 +387,7 @@ "Type.Proxy" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/Semiring.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/Semiring.purs" }, "Data.Semiring.Generic": { "depends": [ @@ -395,7 +395,7 @@ "Data.Generic.Rep" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/Semiring/Generic.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/Semiring/Generic.purs" }, "Data.Show": { "depends": [ @@ -407,7 +407,7 @@ "Type.Proxy" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/Show.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/Show.purs" }, "Data.Show.Generic": { "depends": [ @@ -417,24 +417,24 @@ "Type.Proxy" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/Show/Generic.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/Show/Generic.purs" }, "Data.Symbol": { "depends": [ "Type.Proxy" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/Symbol.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/Symbol.purs" }, "Data.Unit": { "depends": [], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/Unit.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/Unit.purs" }, "Data.Void": { "depends": [], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Data/Void.purs" + "path": ".spago/p/prelude-6.0.1/src/Data/Void.purs" }, "Effect": { "depends": [ @@ -442,7 +442,7 @@ "Control.Apply" ], "package": "effect", - "path": ".spago/packages/effect-4.0.0/src/Effect.purs" + "path": ".spago/p/effect-4.0.0/src/Effect.purs" }, "Effect.Class": { "depends": [ @@ -451,7 +451,7 @@ "Effect" ], "package": "effect", - "path": ".spago/packages/effect-4.0.0/src/Effect/Class.purs" + "path": ".spago/p/effect-4.0.0/src/Effect/Class.purs" }, "Effect.Class.Console": { "depends": [ @@ -462,7 +462,7 @@ "Effect.Console" ], "package": "console", - "path": ".spago/packages/console-6.0.0/src/Effect/Class/Console.purs" + "path": ".spago/p/console-6.0.0/src/Effect/Class/Console.purs" }, "Effect.Console": { "depends": [ @@ -471,7 +471,7 @@ "Data.Unit" ], "package": "console", - "path": ".spago/packages/console-6.0.0/src/Effect/Console.purs" + "path": ".spago/p/console-6.0.0/src/Effect/Console.purs" }, "Effect.Uncurried": { "depends": [ @@ -479,14 +479,14 @@ "Effect" ], "package": "effect", - "path": ".spago/packages/effect-4.0.0/src/Effect/Uncurried.purs" + "path": ".spago/p/effect-4.0.0/src/Effect/Uncurried.purs" }, "Effect.Unsafe": { "depends": [ "Effect" ], "package": "effect", - "path": ".spago/packages/effect-4.0.0/src/Effect/Unsafe.purs" + "path": ".spago/p/effect-4.0.0/src/Effect/Unsafe.purs" }, "Main": { "depends": [ @@ -528,16 +528,16 @@ "Data.Void" ], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Prelude.purs" + "path": ".spago/p/prelude-6.0.1/src/Prelude.purs" }, "Record.Unsafe": { "depends": [], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Record/Unsafe.purs" + "path": ".spago/p/prelude-6.0.1/src/Record/Unsafe.purs" }, "Type.Proxy": { "depends": [], "package": "prelude", - "path": ".spago/packages/prelude-6.0.1/src/Type/Proxy.purs" + "path": ".spago/p/prelude-6.0.1/src/Type/Proxy.purs" } } diff --git a/test-fixtures/sources-output.txt b/test-fixtures/sources-output.txt index 89d1e6873..200dc4fe8 100644 --- a/test-fixtures/sources-output.txt +++ b/test-fixtures/sources-output.txt @@ -1,5 +1,5 @@ src/**/*.purs test/**/*.purs -.spago/packages/console-6.1.0/src/**/*.purs -.spago/packages/effect-4.0.0/src/**/*.purs -.spago/packages/prelude-6.0.1/src/**/*.purs +.spago/p/console-6.1.0/src/**/*.purs +.spago/p/effect-4.0.0/src/**/*.purs +.spago/p/prelude-6.0.1/src/**/*.purs diff --git a/test-fixtures/sources-subproject-output.txt b/test-fixtures/sources-subproject-output.txt index c5e382f04..2d0d8859d 100644 --- a/test-fixtures/sources-subproject-output.txt +++ b/test-fixtures/sources-subproject-output.txt @@ -1,5 +1,5 @@ -.spago/packages/console-6.1.0/src/**/*.purs -.spago/packages/effect-4.0.0/src/**/*.purs -.spago/packages/prelude-6.0.1/src/**/*.purs +.spago/p/console-6.1.0/src/**/*.purs +.spago/p/effect-4.0.0/src/**/*.purs +.spago/p/prelude-6.0.1/src/**/*.purs subpackage/src/**/*.purs subpackage/test/**/*.purs diff --git a/test/Spago/Install.purs b/test/Spago/Install.purs index f902c9807..a807d0323 100644 --- a/test/Spago/Install.purs +++ b/test/Spago/Install.purs @@ -132,7 +132,7 @@ spec = Spec.around withTempDir do } ) spago [ "install", "nonexistent-package" ] >>= shouldBeSuccess - let slashyPath = Path.concat [ testCwd, ".spago", "packages", "nonexistent-package", "spago-test%2fbranch-with-slash" ] + let slashyPath = Path.concat [ toLocalCachePackagesPath testCwd, "nonexistent-package", "spago-test%2fbranch-with-slash" ] unlessM (FS.exists slashyPath) do Assertions.fail $ "Expected path to exist: " <> slashyPath kids <- FSA.readdir slashyPath From ce2531cc1b2953dd5978a4c69a3fb6020fa50671 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Wed, 10 Jan 2024 14:01:35 -0600 Subject: [PATCH 12/21] Fix import --- test/Spago/Install.purs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/Spago/Install.purs b/test/Spago/Install.purs index a807d0323..033ea73c7 100644 --- a/test/Spago/Install.purs +++ b/test/Spago/Install.purs @@ -12,6 +12,7 @@ import Spago.Command.Init as Init import Spago.Core.Config as Config import Spago.FS as FS import Spago.Log (LogVerbosity(..)) +import Spago.Paths as Paths import Spago.Purs as Purs import Test.Spec (Spec) import Test.Spec as Spec @@ -132,7 +133,7 @@ spec = Spec.around withTempDir do } ) spago [ "install", "nonexistent-package" ] >>= shouldBeSuccess - let slashyPath = Path.concat [ toLocalCachePackagesPath testCwd, "nonexistent-package", "spago-test%2fbranch-with-slash" ] + let slashyPath = Path.concat [ Paths.toLocalCachePackagesPath testCwd, "nonexistent-package", "spago-test%2fbranch-with-slash" ] unlessM (FS.exists slashyPath) do Assertions.fail $ "Expected path to exist: " <> slashyPath kids <- FSA.readdir slashyPath From e2bafaa3f76922c2b1fd07be8dbe5242544a6610 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Wed, 10 Jan 2024 16:54:05 -0600 Subject: [PATCH 13/21] Increase docs tests' timeout to 5s --- docs-search/index/test/Docs/Search/Main.purs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/docs-search/index/test/Docs/Search/Main.purs b/docs-search/index/test/Docs/Search/Main.purs index ccbbc2e63..3418f7230 100644 --- a/docs-search/index/test/Docs/Search/Main.purs +++ b/docs-search/index/test/Docs/Search/Main.purs @@ -2,19 +2,29 @@ module Test.Docs.Search.Main where import Prelude +import Data.Identity (Identity(..)) +import Data.Maybe (Maybe(..)) +import Data.Newtype (un) import Effect (Effect) -import Effect.Aff (launchAff_) +import Effect.Aff (Milliseconds(..), launchAff_) import Test.Declarations as Declarations import Test.IndexBuilder as IndexBuilder import Test.ModuleIndex as ModuleIndex import Test.ModuleParser as ModuleParser -import Test.TypeQuery as TypeQuery import Test.Spec (Spec) import Test.Spec.Reporter.Console (consoleReporter) -import Test.Spec.Runner (runSpec) +import Test.Spec.Runner (Config, defaultConfig, runSpecT) +import Test.TypeQuery as TypeQuery + + +testConfig :: Config +testConfig = defaultConfig + { slow = Milliseconds 2_000.0 + , timeout = Just (Milliseconds 5_000.0) + } main :: Effect Unit -main = launchAff_ $ runSpec [ consoleReporter ] mainTest +main = launchAff_ $ void $ un Identity $ runSpecT testConfig [ consoleReporter ] mainTest mainTest :: Spec Unit mainTest = do From 46727276d2e6a135cf12fa58a814d302028246bc Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Wed, 10 Jan 2024 17:04:44 -0600 Subject: [PATCH 14/21] Update windows' sources golden output --- test-fixtures/sources-output.win.txt | 6 +++--- test-fixtures/sources-subproject-output.win.txt | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/test-fixtures/sources-output.win.txt b/test-fixtures/sources-output.win.txt index f6b63d150..1858391f8 100644 --- a/test-fixtures/sources-output.win.txt +++ b/test-fixtures/sources-output.win.txt @@ -1,5 +1,5 @@ src\**\*.purs test\**\*.purs -.spago\packages\console-6.1.0\src\**\*.purs -.spago\packages\effect-4.0.0\src\**\*.purs -.spago\packages\prelude-6.0.1\src\**\*.purs +.spago\p\console-6.1.0\src\**\*.purs +.spago\p\effect-4.0.0\src\**\*.purs +.spago\p\prelude-6.0.1\src\**\*.purs diff --git a/test-fixtures/sources-subproject-output.win.txt b/test-fixtures/sources-subproject-output.win.txt index 50fe243fe..60fa168cb 100644 --- a/test-fixtures/sources-subproject-output.win.txt +++ b/test-fixtures/sources-subproject-output.win.txt @@ -1,5 +1,5 @@ -.spago\packages\console-6.1.0\src\**\*.purs -.spago\packages\effect-4.0.0\src\**\*.purs -.spago\packages\prelude-6.0.1\src\**\*.purs +.spago\p\console-6.1.0\src\**\*.purs +.spago\p\effect-4.0.0\src\**\*.purs +.spago\p\prelude-6.0.1\src\**\*.purs subpackage\src\**\*.purs subpackage\test\**\*.purs From e5121e8ab7bf539287f627eadc5a5fbdb7e43c75 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Wed, 10 Jan 2024 17:07:06 -0600 Subject: [PATCH 15/21] Use spago version's stdout, not stderr --- test/Spago/Build/BuildInfo.purs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Spago/Build/BuildInfo.purs b/test/Spago/Build/BuildInfo.purs index 5fc2bbdca..db7505547 100644 --- a/test/Spago/Build/BuildInfo.purs +++ b/test/Spago/Build/BuildInfo.purs @@ -20,7 +20,7 @@ import Test.Spec as Spec spec :: SpecT Aff TestDirs Identity Unit spec = - Spec.describe "BuildInfo.purs" do + Spec.describeOnly "BuildInfo.purs" do let mkExpectedStdout { spago, rest } = do @@ -29,7 +29,7 @@ spec = spagoResult <- spago [ "--version" ] sVersion <- case Cmd.isSuccess spagoResult of false -> MonadError.throwError $ Exception.error spagoResult.message - true -> pure spagoResult.stderr + true -> pure spagoResult.stdout pure $ Array.intercalate "\n" $ From 0822d3a685f874a247e02c73ea145a2d21552813 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Wed, 10 Jan 2024 18:10:39 -0600 Subject: [PATCH 16/21] Fix formatting --- docs-search/index/test/Docs/Search/Main.purs | 1 - 1 file changed, 1 deletion(-) diff --git a/docs-search/index/test/Docs/Search/Main.purs b/docs-search/index/test/Docs/Search/Main.purs index 3418f7230..82c45143c 100644 --- a/docs-search/index/test/Docs/Search/Main.purs +++ b/docs-search/index/test/Docs/Search/Main.purs @@ -16,7 +16,6 @@ import Test.Spec.Reporter.Console (consoleReporter) import Test.Spec.Runner (Config, defaultConfig, runSpecT) import Test.TypeQuery as TypeQuery - testConfig :: Config testConfig = defaultConfig { slow = Milliseconds 2_000.0 From 583c90b01d14719f5c44091c56c93805b85f1091 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Wed, 10 Jan 2024 18:12:06 -0600 Subject: [PATCH 17/21] Cleanup ci files --- .github/workflows/build.yml | 15 ++---------- check-chars.mjs | 48 ------------------------------------- 2 files changed, 2 insertions(+), 61 deletions(-) delete mode 100644 check-chars.mjs diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3c7dc0984..137dabf73 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -40,11 +40,6 @@ jobs: with: node-version: 18 - - name: How many args on Windows? - if: matrix.os == 'windows-latest' - run: | - node check-chars.mjs - - name: Cache NPM dependencies uses: actions/cache@v2 env: @@ -83,14 +78,8 @@ jobs: - name: Bundle docs-search client run: node ./bin/bundle.js bundle -p docs-search-client-halogen - - name: Run tests (windows) - if: matrix.os == 'windows-latest' - shell: pwsh - run: node bin/bundle.js test --verbose - - - name: Run tests (linux and macos) - if: matrix.os != 'windows-latest' - run: node ./bin/index.dev.js test + - name: Run tests + run: node ./bin/bundle.js test - name: Check formatting (Linux only) if: matrix.os == 'ubuntu-latest' diff --git a/check-chars.mjs b/check-chars.mjs deleted file mode 100644 index 1680b5392..000000000 --- a/check-chars.mjs +++ /dev/null @@ -1,48 +0,0 @@ -import cp from "node:child_process"; - -const echo = "echo"; -const maxCharLimit = 8191 -let initialArgs = ""; -let initialParams = []; -for (let index = 0; index < maxCharLimit; index++) { - initialArgs = initialArgs + "0"; - initialParams.push("0"); -} - -const checkCharCount = (args) => { - console.log(`Attempting to spawn 'echo X' where 'X' is ${args.length} chars`); - const result = cp.spawn(echo, [ args ], { stdio: [null, null, null]}); - result.on("close", (code, sig) => { - if (code === 1 || sig) { - go(args.slice(0, -1)); - } else if (code === 0) { - console.log(`Successfully spawned with ${args.length} chars`); - } else { - console.log("Something else happened."); - console.log(exit); - console.log(sig); - } - }); -}; - -checkCharCount(initialArgs); - - -const checkParamCount = (params) => { - console.log(`Attempting to spawn 'echo X...' where 'X' is ${params.length} parameters`); - const result = cp.spawn(echo, params, { stdio: [null, null, null]}); - result.on("close", (code, sig) => { - if (code === 1 || sig) { - go(params.slice(0, -1)); - } else if (code === 0) { - console.log(`Successfully spawned with ${params.length} parameters`); - } else { - console.log("Something else happened."); - console.log(exit); - console.log(sig); - } - }); -}; - -checkParamCount(initialParams); - From 7b4b45dd2097897ae7c5a4ebe7c8b940d3fb802d Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Fri, 12 Jan 2024 09:43:16 -0600 Subject: [PATCH 18/21] Wrap ExecaResult in Either --- src/Spago/Cmd.purs | 48 ++++++++++++-------- src/Spago/Command/Build.purs | 6 +-- src/Spago/Command/Bundle.purs | 6 +-- src/Spago/Command/Docs.purs | 5 ++- src/Spago/Command/Run.purs | 18 ++++---- src/Spago/Git.purs | 80 +++++++++++++++++---------------- src/Spago/Psa.purs | 7 ++- src/Spago/Purs.purs | 12 ++--- test/Prelude.purs | 57 +++++++++++------------ test/Spago/Build/BuildInfo.purs | 15 +++---- test/Spago/Build/Pedantic.purs | 2 +- test/Spago/Build/Polyrepo.purs | 13 +++--- test/Spago/Publish.purs | 2 +- test/Spago/Registry.purs | 12 ++--- test/Spago/Test.purs | 5 +-- 15 files changed, 152 insertions(+), 136 deletions(-) diff --git a/src/Spago/Cmd.purs b/src/Spago/Cmd.purs index e41456ad1..09af864b9 100644 --- a/src/Spago/Cmd.purs +++ b/src/Spago/Cmd.purs @@ -109,20 +109,32 @@ spawn cmd args opts = liftAff do pure subprocess -joinProcess :: forall m. MonadAff m => Execa.ExecaProcess -> m ExecResult -joinProcess cp = liftAff $ cp.getResult - -exec :: forall m. MonadAff m => String -> Array String -> ExecOptions -> m ExecResult +joinProcess :: forall m. MonadAff m => Execa.ExecaProcess -> m (Either ExecResult ExecResult) +joinProcess cp = do + result <- liftAff $ cp.getResult + case result.exit of + Normally 0 -> pure $ Right result + _ -> pure $ Left result + +exec :: forall m. MonadAff m => String -> Array String -> ExecOptions -> m (Either ExecResult ExecResult) exec cmd args opts = liftAff do - subprocess <- spawn cmd args opts - subprocess.getResult + result <- _.getResult =<< spawn cmd args opts + case result.exit of + Normally 0 -> pure $ Right result + _ -> pure $ Left result kill :: Execa.ExecaProcess -> Aff ExecResult kill cp = liftAff do void $ cp.killForced $ Milliseconds 2_000.0 - cp.getResult >>= \r -> case isSuccess r of - false -> pure r - true -> unsafeCrashWith ("Tried to kill the process, failed. Result:\n" <> printExecResult r) + cp.getResult >>= \r -> case r.exit of + Normally 0 -> pure r + _ -> unsafeCrashWith ("Tried to kill the process, failed. Result:\n" <> printExecResult r) + +getStdout :: Either ExecResult ExecResult -> String +getStdout = either _.stdout _.stdout + +getStderr :: Either ExecResult ExecResult -> String +getStderr = either _.stderr _.stderr -- | Try to find one of the flags in a list of Purs args -- | For example, trying to find the `output` arg @@ -173,20 +185,20 @@ getExecutable command = Just Platform.Win32 -> do -- On Windows, we often need to call the `.cmd` version let cmd1 = mkCmd command (Just "cmd") - askVersion cmd1 >>= \r -> case isSuccess r of - true -> pure { cmd: cmd1, output: r.stdout } - false -> do + askVersion cmd1 >>= case _ of + Right r -> pure { cmd: cmd1, output: r.stdout } + Left r -> do let cmd2 = mkCmd command Nothing logDebug [ "Failed to find purs.cmd. Trying with just purs...", show r.message ] - askVersion cmd2 >>= \r' -> case isSuccess r' of - true -> pure { cmd: cmd2, output: r'.stdout } - false -> complain r + askVersion cmd2 >>= case _ of + Right r' -> pure { cmd: cmd2, output: r'.stdout } + Left r' -> complain r' _ -> do -- On other platforms, we just call `purs` let cmd1 = mkCmd command Nothing - askVersion cmd1 >>= \r -> case isSuccess r of - true -> pure { cmd: cmd1, output: r.stdout } - false -> complain r + askVersion cmd1 >>= case _ of + Right r -> pure { cmd: cmd1, output: r.stdout } + Left r -> complain r where askVersion cmd = exec cmd [ "--version" ] defaultExecOptions { pipeStdout = false, pipeStderr = false } diff --git a/src/Spago/Command/Build.purs b/src/Spago/Command/Build.purs index bde0cb327..8c16ef7fe 100644 --- a/src/Spago/Command/Build.purs +++ b/src/Spago/Command/Build.purs @@ -132,11 +132,11 @@ run opts = do moreBackendArgs = case backend.args of Just as | Array.length as > 0 -> as _ -> [] - Cmd.exec backend.cmd (addOutputArgs moreBackendArgs) Cmd.defaultExecOptions >>= \r -> case Cmd.isSuccess r of - false -> do + Cmd.exec backend.cmd (addOutputArgs moreBackendArgs) Cmd.defaultExecOptions >>= case _ of + Left r -> do logDebug $ Cmd.printExecResult r die [ "Failed to build with backend " <> backend.cmd ] - true -> + Right _ -> logSuccess "Backend build succeeded." let diff --git a/src/Spago/Command/Bundle.purs b/src/Spago/Command/Bundle.purs index 187d97113..1b6418cd1 100644 --- a/src/Spago/Command/Bundle.purs +++ b/src/Spago/Command/Bundle.purs @@ -77,8 +77,8 @@ run = do ] <> opts.extraArgs <> minify <> sourceMap <> entrypoint <> nodePatch logInfo "Bundling..." logDebug $ "Running esbuild: " <> show args - Cmd.exec esbuild.cmd args execOptions >>= \r -> case Cmd.isSuccess r of - true -> logSuccess "Bundle succeeded." - false -> do + Cmd.exec esbuild.cmd args execOptions >>= case _ of + Right _ -> logSuccess "Bundle succeeded." + Left r -> do logDebug $ Cmd.printExecResult r die [ "Failed to bundle." ] diff --git a/src/Spago/Command/Docs.purs b/src/Spago/Command/Docs.purs index 8c6063bd7..0ea06a5b3 100644 --- a/src/Spago/Command/Docs.purs +++ b/src/Spago/Command/Docs.purs @@ -11,7 +11,6 @@ import Docs.Search.Config as DocConfig import Docs.Search.IndexBuilder as IndexBuilder import Effect.Uncurried (EffectFn1, runEffectFn1) import Node.Process as Process -import Spago.Cmd as Cmd import Spago.Command.Build as Build import Spago.Command.Fetch as Fetch import Spago.Config (Workspace) @@ -44,7 +43,9 @@ run = do } result <- Purs.docs globs docsFormat - unless (Cmd.isSuccess result) $ die result.message + case result of + Left r -> die r.message + _ -> pure unit when (docsFormat == Html) $ do liftAff $ IndexBuilder.run' diff --git a/src/Spago/Command/Run.purs b/src/Spago/Command/Run.purs index 500ef2b66..382efb3ab 100644 --- a/src/Spago/Command/Run.purs +++ b/src/Spago/Command/Run.purs @@ -47,11 +47,11 @@ type Node = { cmd :: String, version :: Version } nodeVersion :: forall a. Spago (LogEnv a) Version nodeVersion = - Cmd.exec "node" [ "--version" ] Cmd.defaultExecOptions { pipeStdout = false, pipeStderr = false } >>= \r -> case Cmd.isSuccess r of - false -> do + Cmd.exec "node" [ "--version" ] Cmd.defaultExecOptions { pipeStdout = false, pipeStderr = false } >>= case _ of + Left r -> do logDebug $ Cmd.printExecResult r die [ "Failed to find node. Have you installed it, and is it in your PATH?" ] - true -> case parseLenientVersion r.stdout of + Right r -> case parseLenientVersion r.stdout of Left _err -> die $ "Failed to parse NodeJS version. Was: " <> r.stdout Right v -> if Version.major v >= 13 then @@ -116,20 +116,20 @@ run = do FS.writeTextFile packageJsonPath packageJsonContents logDebug $ "Executing from: " <> show opts.executeDir logDebug $ "Running node command with args: `" <> show nodeArgs <> "`" - Cmd.exec node.cmd nodeArgs (execOptions { cwd = Just opts.executeDir }) >>= \r -> case Cmd.isSuccess r of - true -> case opts.successMessage of + Cmd.exec node.cmd nodeArgs (execOptions { cwd = Just opts.executeDir }) >>= case _ of + Right _ -> case opts.successMessage of Just m -> logSuccess m Nothing -> pure unit - false -> do + Left r -> do logDebug $ Cmd.printExecResult r die opts.failureMessage Just backend -> do let args = [ "--run", opts.moduleName <> ".main" ] <> opts.execArgs logDebug $ "Running command `" <> backend.cmd <> " " <> show args <> "`" - Cmd.exec backend.cmd args execOptions >>= \r -> case Cmd.isSuccess r of - true -> case opts.successMessage of + Cmd.exec backend.cmd args execOptions >>= case _ of + Right _ -> case opts.successMessage of Just m -> logSuccess m Nothing -> pure unit - false -> do + Left r -> do logDebug $ Cmd.printExecResult r die [ opts.failureMessage, "Backend " <> show backend <> " exited with error:" <> r.shortMessage ] diff --git a/src/Spago/Git.purs b/src/Spago/Git.purs index b133275cb..c5bf227e9 100644 --- a/src/Spago/Git.purs +++ b/src/Spago/Git.purs @@ -36,9 +36,9 @@ runGit :: forall a. Array String -> Maybe FilePath -> ExceptT String (Spago (Git runGit args cwd = ExceptT do { git } <- ask result <- Cmd.exec git.cmd args (Cmd.defaultExecOptions { pipeStdout = false, pipeStderr = false, cwd = cwd }) - pure case Cmd.isSuccess result of - true -> Right result.stdout - false -> Left result.stderr + pure case result of + Right r -> Right r.stdout + Left r -> Left r.stderr fetchRepo :: forall a b. { git :: String, ref :: String | a } -> FilePath -> Spago (GitEnv b) (Either (Array String) Unit) fetchRepo { git, ref } path = do @@ -87,38 +87,38 @@ listTags :: forall a. Maybe FilePath -> Spago (GitEnv a) (Either Docc (Array Str listTags cwd = do let opts = Cmd.defaultExecOptions { pipeStdout = false, pipeStderr = false, cwd = cwd } { git } <- ask - Cmd.exec git.cmd [ "tag" ] opts >>= \r -> case Cmd.isSuccess r of - false -> do + Cmd.exec git.cmd [ "tag" ] opts >>= case _ of + Left r -> do pure $ Left $ toDoc [ "Could not run `git tag`. Error:", r.message ] - true -> pure $ Right $ String.split (Pattern "\n") r.stdout + Right r -> pure $ Right $ String.split (Pattern "\n") r.stdout getStatus :: forall a. Maybe FilePath -> Spago (GitEnv a) (Either Docc String) getStatus cwd = do let opts = Cmd.defaultExecOptions { pipeStdout = false, pipeStderr = false, cwd = cwd } { git } <- ask - Cmd.exec git.cmd [ "status", "--porcelain" ] opts >>= \r -> case Cmd.isSuccess r of - false -> do + Cmd.exec git.cmd [ "status", "--porcelain" ] opts >>= case _ of + Left r -> do pure $ Left $ toDoc [ "Could not run `git status`. Error:", r.message ] - true -> pure $ Right r.stdout + Right r -> pure $ Right r.stdout getRef :: forall a. Maybe FilePath -> Spago (GitEnv a) (Either Docc String) getRef cwd = do let opts = Cmd.defaultExecOptions { pipeStdout = false, pipeStderr = false, cwd = cwd } { git } <- ask - Cmd.exec git.cmd [ "rev-parse", "HEAD" ] opts >>= \r -> case Cmd.isSuccess r of - false -> pure $ Left $ toDoc + Cmd.exec git.cmd [ "rev-parse", "HEAD" ] opts >>= case _ of + Left r -> pure $ Left $ toDoc [ "Could not run `git rev-parse HEAD` to determine the current ref. Error:" , r.shortMessage ] - true -> pure $ Right r.stdout + Right r -> pure $ Right r.stdout tagCheckedOut :: forall a. Maybe FilePath -> Spago (GitEnv a) (Either Docc String) tagCheckedOut cwd = do let opts = Cmd.defaultExecOptions { pipeStdout = false, pipeStderr = false, cwd = cwd } { git } <- ask - Cmd.exec git.cmd [ "describe", "--tags", "--exact-match" ] opts >>= \r -> case Cmd.isSuccess r of - false -> pure $ Left $ toDoc "The git ref currently checked out is not a tag." - true -> pure $ Right r.stdout + Cmd.exec git.cmd [ "describe", "--tags", "--exact-match" ] opts >>= case _ of + Left _ -> pure $ Left $ toDoc "The git ref currently checked out is not a tag." + Right r -> pure $ Right r.stdout pushTag :: forall a. Maybe FilePath -> Version -> Spago (GitEnv a) (Either Docc Unit) pushTag cwd version = do @@ -130,13 +130,13 @@ pushTag cwd version = do pure $ Right unit Online -> do logInfo $ "Pushing tag 'v" <> Version.print version <> "' to the remote" - Cmd.exec git.cmd [ "push", "origin", "v" <> Version.print version ] opts >>= \r -> case Cmd.isSuccess r of - false -> pure $ Left $ toDoc + Cmd.exec git.cmd [ "push", "origin", "v" <> Version.print version ] opts >>= case _ of + Left r -> pure $ Left $ toDoc [ "Could not push the tag 'v" <> Version.print version <> "' to the remote." , "Error:" , r.shortMessage ] - true -> pure $ Right unit + Right _ -> pure $ Right unit -- | Check if the path is ignored by git -- @@ -146,32 +146,34 @@ isIgnored :: forall a. FilePath -> Spago (GitEnv a) Boolean isIgnored path = do { git } <- ask result <- Cmd.exec git.cmd [ "check-ignore", "--quiet", path ] (Cmd.defaultExecOptions { pipeStdout = false, pipeStderr = false }) - case result.exit of + case result of -- Git is successful if it's an ignored file - Normally 0 -> pure true + Right _ -> pure true -- Git will fail with exitCode 128 if this is not a git repo or if it's dealing with a link. -- We ignore links - I mean, do we really want to deal with recursive links?!? - Normally 128 -> do - -- Sigh. Even if something is behind a link Node will not tell us that, - -- so we need to check all the paths between the cwd and the provided path - -- Just beautiful - paths <- liftEffect do - cwd <- Process.cwd - absolutePath <- Path.resolve [] path - FS.getInBetweenPaths cwd absolutePath - Array.any identity <$> traverse FS.isLink paths - -- Git will fail with 1 when a file is just, like, normally ignored - Normally 1 -> pure false - _ -> do - logDebug "IsIgnored encountered an interesting exitCode" - logDebug $ Cmd.printExecResult result - -- We still do not ignore it, just in case - pure false + Left r + | Normally 128 <- r.exit -> do + -- Sigh. Even if something is behind a link Node will not tell us that, + -- so we need to check all the paths between the cwd and the provided path + -- Just beautiful + paths <- liftEffect do + cwd <- Process.cwd + absolutePath <- Path.resolve [] path + FS.getInBetweenPaths cwd absolutePath + Array.any identity <$> traverse FS.isLink paths + -- Git will fail with 1 when a file is just, like, normally ignored + | Normally 1 <- r.exit -> + pure false + | otherwise -> do + logDebug "IsIgnored encountered an interesting exitCode" + logDebug $ Cmd.printExecResult r + -- We still do not ignore it, just in case + pure false getGit :: forall a. Spago (LogEnv a) Git getGit = do - Cmd.exec "git" [ "--version" ] Cmd.defaultExecOptions { pipeStdout = false, pipeStderr = false } >>= \r -> case Cmd.isSuccess r of - true -> pure { cmd: "git", version: r.stdout } - false -> do + Cmd.exec "git" [ "--version" ] Cmd.defaultExecOptions { pipeStdout = false, pipeStderr = false } >>= case _ of + Right r -> pure { cmd: "git", version: r.stdout } + Left r -> do logDebug $ Cmd.printExecResult r die [ "Failed to find git. Have you installed it, and is it in your PATH?" ] diff --git a/src/Spago/Psa.purs b/src/Spago/Psa.purs index b25070ba7..d173ed9b6 100644 --- a/src/Spago/Psa.purs +++ b/src/Spago/Psa.purs @@ -39,7 +39,8 @@ defaultStatVerbosity = Core.CompactStats psaCompile :: forall a. Set.Set FilePath -> Array String -> PsaArgs -> Spago (Purs.PursEnv a) Unit psaCompile globs pursArgs psaArgs = do result <- Purs.compile globs (Array.snoc pursArgs "--json-errors") - arrErrorsIsEmpty <- forWithIndex (Str.split (Str.Pattern "\n") result.stdout) \idx err -> + let resultStdout = Cmd.getStdout result + arrErrorsIsEmpty <- forWithIndex (Str.split (Str.Pattern "\n") resultStdout) \idx err -> case jsonParser err >>= CA.decode psaResultCodec >>> lmap CA.printJsonDecodeError of Left decodeErrMsg -> do logWarn $ Array.intercalate "\n" @@ -60,7 +61,9 @@ psaCompile globs pursArgs psaArgs = do if Array.all identity arrErrorsIsEmpty then do logSuccess "Build succeeded." else do - unless (Cmd.isSuccess result) $ logDebug $ Cmd.printExecResult result + case result of + Left r -> logDebug $ Cmd.printExecResult r + _ -> pure unit die [ "Failed to build." ] where diff --git a/src/Spago/Purs.purs b/src/Spago/Purs.purs index 8167dd5cd..c6efb4ae0 100644 --- a/src/Spago/Purs.purs +++ b/src/Spago/Purs.purs @@ -41,7 +41,7 @@ parseVersionOutput { cmd, output: stdout } = case parseLenientVersion (dropStuff where dropStuff pattern = fromMaybe "" <<< Array.head <<< String.split (String.Pattern pattern) -compile :: forall a. Set FilePath -> Array String -> Spago (PursEnv a) ExecaResult +compile :: forall a. Set FilePath -> Array String -> Spago (PursEnv a) (Either ExecaResult ExecaResult) compile globs pursArgs = do { purs } <- ask let args = [ "compile" ] <> pursArgs <> Set.toUnfoldable globs @@ -54,7 +54,7 @@ compile globs pursArgs = do Cmd.exec purs.cmd args $ Cmd.defaultExecOptions { pipeStdout = false } -repl :: forall a. Set FilePath -> Array String -> Spago (PursEnv a) ExecaResult +repl :: forall a. Set FilePath -> Array String -> Spago (PursEnv a) (Either ExecaResult ExecaResult) repl globs pursArgs = do { purs } <- ask let args = [ "repl" ] <> pursArgs <> Set.toUnfoldable globs @@ -87,7 +87,7 @@ printDocsFormat = case _ of Ctags -> "ctags" Etags -> "etags" -docs :: forall a. Set FilePath -> DocsFormat -> Spago (PursEnv a) ExecaResult +docs :: forall a. Set FilePath -> DocsFormat -> Spago (PursEnv a) (Either ExecaResult ExecaResult) docs globs format = do { purs } <- ask let args = [ "docs", "--format", printDocsFormat format ] <> Set.toUnfoldable globs @@ -126,10 +126,10 @@ graph globs pursArgs = do let args = [ "graph" ] <> pursArgs <> Set.toUnfoldable globs logDebug [ "Running command:", "purs " <> String.joinWith " " args ] let execOpts = Cmd.defaultExecOptions { pipeStdout = false, pipeStderr = false } - Cmd.exec purs.cmd args execOpts >>= \r -> case Cmd.isSuccess r of - true -> do + Cmd.exec purs.cmd args execOpts >>= case _ of + Right r -> do logDebug "Called `purs graph`, decoding.." pure $ parseJson moduleGraphCodec r.stdout - false -> do + Left r -> do logDebug $ Cmd.printExecResult r die [ "Failed to call `purs graph`, error: " <> r.shortMessage ] diff --git a/test/Prelude.purs b/test/Prelude.purs index d9d4f00ac..ff7e8eda7 100644 --- a/test/Prelude.purs +++ b/test/Prelude.purs @@ -12,13 +12,14 @@ import Data.String as String import Effect.Aff as Aff import Effect.Class.Console (log) import Effect.Class.Console as Console +import Node.Library.Execa (ExecaResult) import Node.Path (dirname) import Node.Path as Path import Node.Process as Process import Registry.PackageName as PackageName import Registry.Version as Version -import Spago.Cmd (ExecResult, StdinConfig(..)) as X import Spago.Cmd (ExecResult, StdinConfig(..)) +import Spago.Cmd (ExecResult, StdinConfig(..)) as X import Spago.Cmd as Cmd import Spago.Command.Init as Init import Spago.Core.Config (Dependencies(..), Config) @@ -29,8 +30,8 @@ import Test.Spec.Assertions (fail) import Test.Spec.Assertions as Assert type TestDirs = - { spago :: Array String -> Aff ExecResult - , spago' :: StdinConfig -> Array String -> Aff ExecResult + { spago :: Array String -> Aff (Either ExecResult ExecResult) + , spago' :: StdinConfig -> Array String -> Aff (Either ExecResult ExecResult) , fixture :: FilePath -> FilePath , oldCwd :: FilePath , testCwd :: FilePath @@ -52,7 +53,7 @@ withTempDir = Aff.bracket createTempDir cleanupTempDir fixture path = Path.concat [ fixturesPath, path ] - spago' :: StdinConfig -> Array String -> Aff ExecResult + spago' :: StdinConfig -> Array String -> Aff (Either ExecResult ExecResult) spago' stdin args = Cmd.exec "node" @@ -120,14 +121,14 @@ plusDependencies deps config = config check :: { stdout :: String -> Aff Unit , stderr :: String -> Aff Unit - , result :: ExecResult -> Boolean + , result :: Either ExecResult ExecResult -> Boolean } - -> ExecResult + -> Either ExecResult ExecResult -> Aff Unit check checkers execResult = do let - stdout = String.trim $ execResult.stdout - stderr = String.trim $ execResult.stderr + stdout = String.trim $ Cmd.getStdout execResult + stderr = String.trim $ Cmd.getStderr execResult printStdoutStderr <- liftEffect $ map isJust $ Process.lookupEnv "SPAGO_TEST_DEBUG" @@ -145,9 +146,9 @@ check checkers execResult = do checkOutputsStr :: { stdoutStr :: Maybe String , stderrStr :: Maybe String - , result :: ExecResult -> Boolean + , result :: Either ExecResult ExecResult -> Boolean } - -> ExecResult + -> Either ExecResult ExecResult -> Aff Unit checkOutputsStr checkers = check @@ -159,9 +160,9 @@ checkOutputsStr checkers = checkOutputs :: { stdoutFile :: Maybe FilePath , stderrFile :: Maybe FilePath - , result :: ExecResult -> Boolean + , result :: (Either ExecResult ExecResult) -> Boolean } - -> ExecResult + -> Either ExecResult ExecResult -> Aff Unit checkOutputs checkers execResult = do let @@ -184,29 +185,29 @@ checkOutputs checkers execResult = do } execResult -shouldBeSuccess :: ExecResult -> Aff Unit -shouldBeSuccess = checkOutputs { stdoutFile: Nothing, stderrFile: Nothing, result: Cmd.isSuccess } +shouldBeSuccess :: Either ExecaResult ExecaResult -> Aff Unit +shouldBeSuccess = checkOutputs { stdoutFile: Nothing, stderrFile: Nothing, result: isRight } -shouldBeSuccessOutput :: FilePath -> ExecResult -> Aff Unit -shouldBeSuccessOutput outFixture = checkOutputs { stdoutFile: Just outFixture, stderrFile: Nothing, result: Cmd.isSuccess } +shouldBeSuccessOutput :: FilePath -> Either ExecaResult ExecaResult -> Aff Unit +shouldBeSuccessOutput outFixture = checkOutputs { stdoutFile: Just outFixture, stderrFile: Nothing, result: isRight } -shouldBeSuccessErr :: FilePath -> ExecResult -> Aff Unit -shouldBeSuccessErr errFixture = checkOutputs { stdoutFile: Nothing, stderrFile: Just errFixture, result: Cmd.isSuccess } +shouldBeSuccessErr :: FilePath -> Either ExecaResult ExecaResult -> Aff Unit +shouldBeSuccessErr errFixture = checkOutputs { stdoutFile: Nothing, stderrFile: Just errFixture, result: isRight } -shouldBeSuccessOutputWithErr :: FilePath -> FilePath -> ExecResult -> Aff Unit -shouldBeSuccessOutputWithErr outFixture errFixture = checkOutputs { stdoutFile: Just outFixture, stderrFile: Just errFixture, result: Cmd.isSuccess } +shouldBeSuccessOutputWithErr :: FilePath -> FilePath -> Either ExecaResult ExecaResult -> Aff Unit +shouldBeSuccessOutputWithErr outFixture errFixture = checkOutputs { stdoutFile: Just outFixture, stderrFile: Just errFixture, result: isRight } -shouldBeFailure :: ExecResult -> Aff Unit -shouldBeFailure = checkOutputs { stdoutFile: Nothing, stderrFile: Nothing, result: Cmd.isFailure } +shouldBeFailure :: Either ExecaResult ExecaResult -> Aff Unit +shouldBeFailure = checkOutputs { stdoutFile: Nothing, stderrFile: Nothing, result: isLeft } -shouldBeFailureOutput :: FilePath -> ExecResult -> Aff Unit -shouldBeFailureOutput outFixture = checkOutputs { stdoutFile: Just outFixture, stderrFile: Nothing, result: Cmd.isFailure } +shouldBeFailureOutput :: FilePath -> Either ExecaResult ExecaResult -> Aff Unit +shouldBeFailureOutput outFixture = checkOutputs { stdoutFile: Just outFixture, stderrFile: Nothing, result: isLeft } -shouldBeFailureErr :: FilePath -> ExecResult -> Aff Unit -shouldBeFailureErr errFixture = checkOutputs { stdoutFile: Nothing, stderrFile: Just errFixture, result: Cmd.isFailure } +shouldBeFailureErr :: FilePath -> Either ExecaResult ExecaResult -> Aff Unit +shouldBeFailureErr errFixture = checkOutputs { stdoutFile: Nothing, stderrFile: Just errFixture, result: isLeft } -shouldBeFailureOutputWithErr :: FilePath -> FilePath -> ExecResult -> Aff Unit -shouldBeFailureOutputWithErr outFixture errFixture = checkOutputs { stdoutFile: Just outFixture, stderrFile: Just errFixture, result: Cmd.isFailure } +shouldBeFailureOutputWithErr :: FilePath -> FilePath -> Either ExecaResult ExecaResult -> Aff Unit +shouldBeFailureOutputWithErr outFixture errFixture = checkOutputs { stdoutFile: Just outFixture, stderrFile: Just errFixture, result: isLeft } mkPackageName :: String -> PackageName mkPackageName = unsafeFromRight <<< PackageName.parse diff --git a/test/Spago/Build/BuildInfo.purs b/test/Spago/Build/BuildInfo.purs index db7505547..4fa0eb863 100644 --- a/test/Spago/Build/BuildInfo.purs +++ b/test/Spago/Build/BuildInfo.purs @@ -8,7 +8,6 @@ import Data.DateTime.Instant as Instant import Effect.Exception as Exception import Node.Path as Path import Registry.Version as Version -import Spago.Cmd as Cmd import Spago.Command.Init (DefaultConfigOptions(..)) import Spago.Command.Init as Init import Spago.Core.Config as Config @@ -20,16 +19,16 @@ import Test.Spec as Spec spec :: SpecT Aff TestDirs Identity Unit spec = - Spec.describeOnly "BuildInfo.purs" do + Spec.describe "BuildInfo.purs" do let mkExpectedStdout { spago, rest } = do let logOptions = { logOptions: { color: false, verbosity: LogQuiet, startingTime: Instant.fromDateTime bottom } } purs <- runSpago logOptions getPurs spagoResult <- spago [ "--version" ] - sVersion <- case Cmd.isSuccess spagoResult of - false -> MonadError.throwError $ Exception.error spagoResult.message - true -> pure spagoResult.stdout + sVersion <- case spagoResult of + Left r -> MonadError.throwError $ Exception.error r.message + Right r -> pure r.stdout pure $ Array.intercalate "\n" $ @@ -87,7 +86,7 @@ spec = Spec.it ("'spago " <> Array.intercalate " " command <> " works") \{ spago } -> do setupSinglePackage spago expected <- mkExpectedStdout { spago, rest: [ "foo: 0.0.0" ] } - spago command >>= checkOutputsStr { stderrStr: Nothing, stdoutStr: Just expected, result: Cmd.isSuccess } + spago command >>= checkOutputsStr { stderrStr: Nothing, stdoutStr: Just expected, result: isRight } Spec.describe "using generated 'BuildInfo.purs' file in multi-package context" do @@ -134,9 +133,9 @@ spec = Spec.it ("'spago run -p " <> package <> " --main " <> srcMain <> "' works") \{ spago } -> do expected <- mkExpectedStdout { spago, rest: packagesWithVersion } - spago [ "run", "-p", package, "--main", srcMain ] >>= checkOutputsStr { stderrStr: Nothing, stdoutStr: Just expected, result: Cmd.isSuccess } + spago [ "run", "-p", package, "--main", srcMain ] >>= checkOutputsStr { stderrStr: Nothing, stdoutStr: Just expected, result: isRight } Spec.it ("'spago test -p " <> package <> "' works") \{ spago } -> do expected <- mkExpectedStdout { spago, rest: packagesWithVersion } - spago [ "test", "-p", package ] >>= checkOutputsStr { stderrStr: Nothing, stdoutStr: Just expected, result: Cmd.isSuccess } + spago [ "test", "-p", package ] >>= checkOutputsStr { stderrStr: Nothing, stdoutStr: Just expected, result: isRight } diff --git a/test/Spago/Build/Pedantic.purs b/test/Spago/Build/Pedantic.purs index cb4137740..25e716982 100644 --- a/test/Spago/Build/Pedantic.purs +++ b/test/Spago/Build/Pedantic.purs @@ -255,7 +255,7 @@ defaultSetupConfig = , testMain: Nothing } -setup :: (Array String -> Aff ExecResult) -> SetupConfig -> Aff Unit +setup :: (Array String -> Aff (Either ExecResult ExecResult)) -> SetupConfig -> Aff Unit setup spago config = do spago [ "init", "--name", "pedantic" ] >>= shouldBeSuccess unless (Array.null config.installSourcePackages) do diff --git a/test/Spago/Build/Polyrepo.purs b/test/Spago/Build/Polyrepo.purs index 0013eaa41..cae181797 100644 --- a/test/Spago/Build/Polyrepo.purs +++ b/test/Spago/Build/Polyrepo.purs @@ -14,7 +14,6 @@ import Node.Path as Path import Node.Platform as Platform import Node.Process as Process import Registry.Version as Version -import Spago.Cmd as Cmd import Spago.Command.Init (DefaultConfigOptions(..)) import Spago.Command.Init as Init import Spago.Core.Config as Config @@ -217,7 +216,7 @@ spec = Spec.describe "polyrepo" do unless (String.contains (Pattern exp) stdErr) do Assert.fail $ "STDERR did not contain text:\n" <> exp <> "\n\nStderr was:\n" <> stdErr - spago [ "build" ] >>= check { stdout: mempty, stderr: hasExpectedModules, result: Cmd.isFailure } + spago [ "build" ] >>= check { stdout: mempty, stderr: hasExpectedModules, result: isLeft } Spec.describe "warning censoring and error-promotion" do let @@ -268,7 +267,7 @@ spec = Spec.describe "polyrepo" do shouldNotHaveWarning stdErr = do when (Array.any (\exp -> String.contains (Pattern exp) stdErr) paths) do Assert.fail $ "STDERR contained one or more texts:\n" <> show paths <> "\n\nStderr was:\n" <> stdErr - spago [ "build" ] >>= check { stdout: mempty, stderr: shouldNotHaveWarning, result: Cmd.isSuccess } + spago [ "build" ] >>= check { stdout: mempty, stderr: shouldNotHaveWarning, result: isRight } Spec.it "build fails when 'strict: true' and warnings were not censored" \{ spago } -> do writeWorkspaceOnlySpagoYamlFile @@ -285,7 +284,7 @@ spec = Spec.describe "polyrepo" do hasUnusedWarningError stdErr = do unless (Array.any (\exp -> String.contains (Pattern exp) stdErr) errs) do Assert.fail $ "STDERR did not contain texts:\n" <> show errs <> "\n\nStderr was:\n" <> stdErr - spago [ "build" ] >>= check { stdout: mempty, stderr: hasUnusedWarningError, result: Cmd.isFailure } + spago [ "build" ] >>= check { stdout: mempty, stderr: hasUnusedWarningError, result: isLeft } Spec.describe "passing --ensure-ranges flag..." do let @@ -328,7 +327,7 @@ spec = Spec.describe "polyrepo" do ] unless (String.contains (Pattern msg) stdErr) do Assert.fail $ "STDERR did not contain text:\n" <> msg <> "\n\nStderr was:\n" <> stdErr - spago [ "build", "--ensure-ranges" ] >>= check { stdout: mempty, stderr: hasNoRootPackageError, result: Cmd.isFailure } + spago [ "build", "--ensure-ranges" ] >>= check { stdout: mempty, stderr: hasNoRootPackageError, result: isLeft } Spec.describe "pedantic packages" do let @@ -422,7 +421,7 @@ spec = Spec.describe "polyrepo" do let unfoundTexts = Array.filter (\exp -> not $ String.contains (Pattern exp) stdErr) errs unless (Array.null unfoundTexts) do Assert.fail $ "STDERR did not contain expected texts:\n" <> (Array.intercalate "\n\n" unfoundTexts) <> "\n\nStderr was:\n" <> stdErr - spago [ "build" ] >>= check { stdout: mempty, stderr: hasExpectedErrors, result: Cmd.isFailure } + spago [ "build" ] >>= check { stdout: mempty, stderr: hasExpectedErrors, result: isLeft } Spec.it "passing --pedantic-packages overrides package and test configs" \{ spago } -> do writeWorkspaceOnlySpagoYamlFile @@ -440,4 +439,4 @@ spec = Spec.describe "polyrepo" do let unfoundTexts = Array.filter (\exp -> not $ String.contains (Pattern exp) stdErr) errs unless (Array.null unfoundTexts) do Assert.fail $ "STDERR did not contain expected texts:\n" <> (Array.intercalate "\n\n" unfoundTexts) <> "\n\nStderr was:\n" <> stdErr - spago [ "build", "--pedantic-packages" ] >>= check { stdout: mempty, stderr: hasExpectedErrors, result: Cmd.isFailure } + spago [ "build", "--pedantic-packages" ] >>= check { stdout: mempty, stderr: hasExpectedErrors, result: isLeft } diff --git a/test/Spago/Publish.purs b/test/Spago/Publish.purs index a82093b48..b880cd9af 100644 --- a/test/Spago/Publish.purs +++ b/test/Spago/Publish.purs @@ -63,6 +63,6 @@ doTheGitThing = do git [ "commit", "-m", "first" ] >>= shouldBeSuccess git [ "tag", "v0.0.1" ] >>= shouldBeSuccess where - git :: Array String -> Aff ExecResult + git :: Array String -> Aff (Either ExecResult ExecResult) git args = Cmd.exec "git" args $ Cmd.defaultExecOptions { pipeStdout = false, pipeStderr = false, pipeStdin = StdinNewPipe } diff --git a/test/Spago/Registry.purs b/test/Spago/Registry.purs index 84c81fded..1ade397f7 100644 --- a/test/Spago/Registry.purs +++ b/test/Spago/Registry.purs @@ -15,23 +15,23 @@ spec = Spec.around withTempDir do Spec.it "list package sets" \{ spago, fixture } -> do result <- spago [ "registry", "package-sets" ] let - result' = result - { stdout = result.stdout + updateStdout r = r + { stdout = r.stdout -- Take the oldest lines of output - the list of package sets will grow all the time # String.split (Pattern "\n") # Array.take 200 # String.joinWith "\n" } - shouldBeSuccessOutput (fixture "registry-list-package-sets.txt") result' + shouldBeSuccessOutput (fixture "registry-list-package-sets.txt") $ bimap updateStdout updateStdout result Spec.it "list only latest package sets for compiler" \{ spago, fixture } -> do result <- spago [ "registry", "package-sets", "--latest" ] let - result' = result - { stdout = result.stdout + updateStdout r = r + { stdout = r.stdout -- Take the oldest lines of output - the list of package sets will grow all the time # String.split (Pattern "\n") # Array.take 7 # String.joinWith "\n" } - shouldBeSuccessOutput (fixture "registry-list-package-sets-latest.txt") result' + shouldBeSuccessOutput (fixture "registry-list-package-sets-latest.txt") $ bimap updateStdout updateStdout result diff --git a/test/Spago/Test.purs b/test/Spago/Test.purs index 75cb1adda..98f9ef312 100644 --- a/test/Spago/Test.purs +++ b/test/Spago/Test.purs @@ -8,7 +8,6 @@ import Node.Path as Path import Node.Platform as Platform import Node.Process as Process import Registry.Version as Version -import Spago.Cmd as Cmd import Spago.Command.Init (DefaultConfigOptions(..)) import Spago.Command.Init as Init import Spago.Core.Config as Config @@ -79,7 +78,7 @@ spec = Spec.around withTempDir do } ) # plusDependencies [ "aff", "node-buffer", "node-fs" ] ) - spago [ "test", "-p", "subpackage" ] >>= checkOutputsStr { stdoutStr: Just fileContent, stderrStr: Nothing, result: Cmd.isSuccess } + spago [ "test", "-p", "subpackage" ] >>= checkOutputsStr { stdoutStr: Just fileContent, stderrStr: Nothing, result: isRight } Spec.it "fails when running tests from a sub-package, where the module does not exist" \{ spago } -> do spago [ "init" ] >>= shouldBeSuccess @@ -137,5 +136,5 @@ spec = Spec.around withTempDir do unless (String.contains (String.Pattern exp) stdErr) do Assert.fail $ "STDERR did not contain text:\n" <> exp <> "\n\nStderr was:\n" <> stdErr - spago [ "test" ] >>= check { stdout: mempty, stderr: hasUnusedNameWarningError, result: Cmd.isSuccess } + spago [ "test" ] >>= check { stdout: mempty, stderr: hasUnusedNameWarningError, result: isRight } From 3f11ced30be18aa73864a01fa3883a199ba87e3d Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Fri, 12 Jan 2024 09:44:41 -0600 Subject: [PATCH 19/21] Swap code paths --- src/Spago/Cmd.purs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Spago/Cmd.purs b/src/Spago/Cmd.purs index 09af864b9..7d5875c58 100644 --- a/src/Spago/Cmd.purs +++ b/src/Spago/Cmd.purs @@ -127,8 +127,8 @@ kill :: Execa.ExecaProcess -> Aff ExecResult kill cp = liftAff do void $ cp.killForced $ Milliseconds 2_000.0 cp.getResult >>= \r -> case r.exit of - Normally 0 -> pure r - _ -> unsafeCrashWith ("Tried to kill the process, failed. Result:\n" <> printExecResult r) + Normally 0 -> unsafeCrashWith ("Tried to kill the process, failed. Result:\n" <> printExecResult r) + _ -> pure r getStdout :: Either ExecResult ExecResult -> String getStdout = either _.stdout _.stdout From 386989700898fc114ebecdbf309058445fd3befa Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Fri, 12 Jan 2024 09:47:47 -0600 Subject: [PATCH 20/21] Drop dead code --- src/Spago/Cmd.purs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/Spago/Cmd.purs b/src/Spago/Cmd.purs index 7d5875c58..0479ad9c5 100644 --- a/src/Spago/Cmd.purs +++ b/src/Spago/Cmd.purs @@ -64,16 +64,6 @@ printExecResult r = Array.intercalate "\n" , "" ] --- | True if the process exited normally with exit code 0 -isSuccess :: ExecResult -> Boolean -isSuccess r = case r.exit of - Normally 0 -> true - _ -> false - --- | True if the process exited with a non-zero exit code or was terminated by a signal -isFailure :: ExecResult -> Boolean -isFailure = not <<< isSuccess - type ExecOptions = { pipeStdin :: StdinConfig , pipeStdout :: Boolean From 4da3b27869c5bd5a3c00e331616fec519776734a Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Fri, 12 Jan 2024 09:58:58 -0600 Subject: [PATCH 21/21] Format --- src/Spago/Git.purs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Spago/Git.purs b/src/Spago/Git.purs index c5bf227e9..d3d98eef3 100644 --- a/src/Spago/Git.purs +++ b/src/Spago/Git.purs @@ -153,16 +153,16 @@ isIgnored path = do -- We ignore links - I mean, do we really want to deal with recursive links?!? Left r | Normally 128 <- r.exit -> do - -- Sigh. Even if something is behind a link Node will not tell us that, - -- so we need to check all the paths between the cwd and the provided path - -- Just beautiful - paths <- liftEffect do - cwd <- Process.cwd - absolutePath <- Path.resolve [] path - FS.getInBetweenPaths cwd absolutePath - Array.any identity <$> traverse FS.isLink paths + -- Sigh. Even if something is behind a link Node will not tell us that, + -- so we need to check all the paths between the cwd and the provided path + -- Just beautiful + paths <- liftEffect do + cwd <- Process.cwd + absolutePath <- Path.resolve [] path + FS.getInBetweenPaths cwd absolutePath + Array.any identity <$> traverse FS.isLink paths -- Git will fail with 1 when a file is just, like, normally ignored - | Normally 1 <- r.exit -> + | Normally 1 <- r.exit -> pure false | otherwise -> do logDebug "IsIgnored encountered an interesting exitCode"