From 554c5c95b699608e759890e344a4befb43020275 Mon Sep 17 00:00:00 2001 From: Matthew Leon Date: Thu, 10 Aug 2017 11:21:00 +0100 Subject: [PATCH 01/22] update stack resolver to lts 9.0 --- stack.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stack.yaml b/stack.yaml index fc491c7..4c7e5e1 100644 --- a/stack.yaml +++ b/stack.yaml @@ -1,4 +1,4 @@ -resolver: lts-8.15 +resolver: lts-9.0 packages: - '.' extra-deps: [] From de8db14301f8117368509a544b7706ee9f5c2efb Mon Sep 17 00:00:00 2001 From: Matthew Leon Date: Thu, 10 Aug 2017 12:14:59 +0100 Subject: [PATCH 02/22] move Types to separate library --- app/Main.hs | 3 ++- psc-package.cabal | 12 ++++++++++-- {app => src/Language/PureScript/Package}/Types.hs | 2 +- 3 files changed, 13 insertions(+), 4 deletions(-) rename {app => src/Language/PureScript/Package}/Types.hs (98%) diff --git a/app/Main.hs b/app/Main.hs index 968e369..5f25d00 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -36,7 +36,8 @@ import qualified System.Process as Process import qualified Text.ParserCombinators.ReadP as Read import Turtle hiding (echo, fold, s, x) import qualified Turtle -import Types (PackageName, mkPackageName, runPackageName, untitledPackageName, preludePackageName) + +import Language.PureScript.Package.Types (PackageName, mkPackageName, runPackageName, untitledPackageName, preludePackageName) echoT :: Text -> IO () echoT = Turtle.printf (Turtle.s % "\n") diff --git a/psc-package.cabal b/psc-package.cabal index e3533bb..48fd2ce 100644 --- a/psc-package.cabal +++ b/psc-package.cabal @@ -13,8 +13,17 @@ build-type: Simple extra-source-files: README.md cabal-version: >=1.10 +library + hs-source-dirs: src + exposed-modules: Language.PureScript.Package.Types + build-depends: base >= 4.7 && < 5, + aeson -any, + text + default-language: Haskell2010 + executable psc-package - build-depends: base >=4 && <5, + build-depends: psc-package, + base >=4 && <5, aeson -any, aeson-pretty -any, async -any, @@ -28,7 +37,6 @@ executable psc-package turtle ==1.3.* main-is: Main.hs other-modules: Paths_psc_package - Types buildable: True hs-source-dirs: app ghc-options: -Wall -O2 -threaded -rtsopts -with-rtsopts=-N diff --git a/app/Types.hs b/src/Language/PureScript/Package/Types.hs similarity index 98% rename from app/Types.hs rename to src/Language/PureScript/Package/Types.hs index 2d5e4e5..02ef738 100644 --- a/app/Types.hs +++ b/src/Language/PureScript/Package/Types.hs @@ -1,6 +1,6 @@ {-# LANGUAGE OverloadedStrings #-} -module Types +module Language.PureScript.Package.Types ( PackageName , mkPackageName , runPackageName From db67ddcf506b45a1cb4658f62e326878228dad18 Mon Sep 17 00:00:00 2001 From: Matthew Leon Date: Thu, 10 Aug 2017 12:24:25 +0100 Subject: [PATCH 03/22] move PackageConfig into Types --- app/Main.hs | 9 +-------- src/Language/PureScript/Package/Types.hs | 13 ++++++++++++- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/app/Main.hs b/app/Main.hs index 5f25d00..43016f5 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -37,7 +37,7 @@ import qualified Text.ParserCombinators.ReadP as Read import Turtle hiding (echo, fold, s, x) import qualified Turtle -import Language.PureScript.Package.Types (PackageName, mkPackageName, runPackageName, untitledPackageName, preludePackageName) +import Language.PureScript.Package.Types (PackageConfig(..), name, depends, set, source, PackageName, mkPackageName, runPackageName, untitledPackageName, preludePackageName) echoT :: Text -> IO () echoT = Turtle.printf (Turtle.s % "\n") @@ -49,13 +49,6 @@ exitWithErr errText = errT errText >> exit (ExitFailure 1) packageFile :: Path.FilePath packageFile = "psc-package.json" -data PackageConfig = PackageConfig - { name :: PackageName - , depends :: [PackageName] - , set :: Text - , source :: Text - } deriving (Show, Generic, Aeson.FromJSON, Aeson.ToJSON) - pathToTextUnsafe :: Turtle.FilePath -> Text pathToTextUnsafe = either (error "Path.toText failed") id . Path.toText diff --git a/src/Language/PureScript/Package/Types.hs b/src/Language/PureScript/Package/Types.hs index 02ef738..7838c36 100644 --- a/src/Language/PureScript/Package/Types.hs +++ b/src/Language/PureScript/Package/Types.hs @@ -1,7 +1,10 @@ {-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE DeriveAnyClass #-} +{-# LANGUAGE DeriveGeneric #-} module Language.PureScript.Package.Types - ( PackageName + ( PackageConfig(..) + , PackageName , mkPackageName , runPackageName , preludePackageName @@ -15,6 +18,14 @@ import Data.Char (isAscii, isLower, isDigit) import Data.Monoid ((<>)) import Data.Text (Text) import qualified Data.Text as T +import GHC.Generics (Generic) + +data PackageConfig = PackageConfig + { name :: PackageName + , depends :: [PackageName] + , set :: Text + , source :: Text + } deriving (Show, Generic, FromJSON, ToJSON) newtype PackageName = PackageName Text From a164521c5ded39955ea4eac4c8934b1c38be18c9 Mon Sep 17 00:00:00 2001 From: Matthew Leon Date: Thu, 10 Aug 2017 12:30:05 +0100 Subject: [PATCH 04/22] move PackageInfo to Types --- app/Main.hs | 11 +---------- src/Language/PureScript/Package/Types.hs | 7 +++++++ 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/app/Main.hs b/app/Main.hs index 43016f5..2317296 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -1,5 +1,3 @@ -{-# LANGUAGE DeriveAnyClass #-} -{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} @@ -27,7 +25,6 @@ import qualified Data.Text.Read as TR import Data.Traversable (for) import Data.Version (Version(..), parseVersion, showVersion) import qualified Filesystem.Path.CurrentOS as Path -import GHC.Generics (Generic) import qualified Options.Applicative as Opts import qualified Paths_psc_package as Paths import System.Environment (getArgs) @@ -37,7 +34,7 @@ import qualified Text.ParserCombinators.ReadP as Read import Turtle hiding (echo, fold, s, x) import qualified Turtle -import Language.PureScript.Package.Types (PackageConfig(..), name, depends, set, source, PackageName, mkPackageName, runPackageName, untitledPackageName, preludePackageName) +import Language.PureScript.Package.Types (PackageConfig(..), name, depends, set, source, PackageInfo(..), repo, version, dependencies, PackageName, mkPackageName, runPackageName, untitledPackageName, preludePackageName) echoT :: Text -> IO () echoT = Turtle.printf (Turtle.s % "\n") @@ -89,12 +86,6 @@ writePackageFile = writeTextFile packageFile . packageConfigToJSON -data PackageInfo = PackageInfo - { repo :: Text - , version :: Text - , dependencies :: [PackageName] - } deriving (Show, Eq, Generic, Aeson.FromJSON, Aeson.ToJSON) - type PackageSet = Map.Map PackageName PackageInfo cloneShallow diff --git a/src/Language/PureScript/Package/Types.hs b/src/Language/PureScript/Package/Types.hs index 7838c36..1bd44fb 100644 --- a/src/Language/PureScript/Package/Types.hs +++ b/src/Language/PureScript/Package/Types.hs @@ -4,6 +4,7 @@ module Language.PureScript.Package.Types ( PackageConfig(..) + , PackageInfo(..) , PackageName , mkPackageName , runPackageName @@ -27,6 +28,12 @@ data PackageConfig = PackageConfig , source :: Text } deriving (Show, Generic, FromJSON, ToJSON) +data PackageInfo = PackageInfo + { repo :: Text + , version :: Text + , dependencies :: [PackageName] + } deriving (Show, Eq, Generic, FromJSON, ToJSON) + newtype PackageName = PackageName Text deriving (Show, Eq, Ord) From a04b9361af96cab20c74a527b3e1498dc83dd243 Mon Sep 17 00:00:00 2001 From: Matthew Leon Date: Thu, 10 Aug 2017 12:39:45 +0100 Subject: [PATCH 05/22] turn on ghc warnings --- psc-package.cabal | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/psc-package.cabal b/psc-package.cabal index 48fd2ce..b451dfe 100644 --- a/psc-package.cabal +++ b/psc-package.cabal @@ -15,6 +15,7 @@ cabal-version: >=1.10 library hs-source-dirs: src + ghc-options: -Wall -fwarn-tabs -fwarn-incomplete-uni-patterns -fwarn-incomplete-record-updates -fwarn-identities exposed-modules: Language.PureScript.Package.Types build-depends: base >= 4.7 && < 5, aeson -any, @@ -39,5 +40,5 @@ executable psc-package other-modules: Paths_psc_package buildable: True hs-source-dirs: app - ghc-options: -Wall -O2 -threaded -rtsopts -with-rtsopts=-N + ghc-options: -Wall -fwarn-tabs -fwarn-incomplete-uni-patterns -fwarn-incomplete-record-updates -O2 -threaded -rtsopts -with-rtsopts=-N default-language: Haskell2010 From 176d90e1814a9c8b40d2b7b4e580d4e649ed9108 Mon Sep 17 00:00:00 2001 From: Matthew Leon Date: Thu, 10 Aug 2017 13:55:54 +0100 Subject: [PATCH 06/22] move PackageName to separate module --- app/Main.hs | 3 +- psc-package.cabal | 3 +- src/Language/PureScript/Package/Types.hs | 82 +----------------- .../PureScript/Package/Types/PackageName.hs | 85 +++++++++++++++++++ 4 files changed, 92 insertions(+), 81 deletions(-) create mode 100644 src/Language/PureScript/Package/Types/PackageName.hs diff --git a/app/Main.hs b/app/Main.hs index 2317296..a19953e 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -34,7 +34,8 @@ import qualified Text.ParserCombinators.ReadP as Read import Turtle hiding (echo, fold, s, x) import qualified Turtle -import Language.PureScript.Package.Types (PackageConfig(..), name, depends, set, source, PackageInfo(..), repo, version, dependencies, PackageName, mkPackageName, runPackageName, untitledPackageName, preludePackageName) +import Language.PureScript.Package.Types (PackageConfig(..), name, depends, set, source, PackageInfo(..), repo, version, dependencies) +import Language.PureScript.Package.Types.PackageName (PackageName, mkPackageName, runPackageName, untitledPackageName, preludePackageName) echoT :: Text -> IO () echoT = Turtle.printf (Turtle.s % "\n") diff --git a/psc-package.cabal b/psc-package.cabal index b451dfe..52a71dc 100644 --- a/psc-package.cabal +++ b/psc-package.cabal @@ -16,7 +16,8 @@ cabal-version: >=1.10 library hs-source-dirs: src ghc-options: -Wall -fwarn-tabs -fwarn-incomplete-uni-patterns -fwarn-incomplete-record-updates -fwarn-identities - exposed-modules: Language.PureScript.Package.Types + exposed-modules: Language.PureScript.Package.Types, + Language.PureScript.Package.Types.PackageName build-depends: base >= 4.7 && < 5, aeson -any, text diff --git a/src/Language/PureScript/Package/Types.hs b/src/Language/PureScript/Package/Types.hs index 1bd44fb..fcf3e2f 100644 --- a/src/Language/PureScript/Package/Types.hs +++ b/src/Language/PureScript/Package/Types.hs @@ -5,22 +5,14 @@ module Language.PureScript.Package.Types ( PackageConfig(..) , PackageInfo(..) - , PackageName - , mkPackageName - , runPackageName - , preludePackageName - , untitledPackageName ) where -import Control.Category ((>>>)) -import Data.Aeson (FromJSON, ToJSON, FromJSONKey(..), ToJSONKey(..), ToJSONKeyFunction(..), FromJSONKeyFunction(..), parseJSON, toJSON, withText) -import qualified Data.Aeson.Encoding as AesonEncoding -import Data.Char (isAscii, isLower, isDigit) -import Data.Monoid ((<>)) +import Data.Aeson (FromJSON, ToJSON) import Data.Text (Text) -import qualified Data.Text as T import GHC.Generics (Generic) +import Language.PureScript.Package.Types.PackageName (PackageName) + data PackageConfig = PackageConfig { name :: PackageName , depends :: [PackageName] @@ -33,71 +25,3 @@ data PackageInfo = PackageInfo , version :: Text , dependencies :: [PackageName] } deriving (Show, Eq, Generic, FromJSON, ToJSON) - -newtype PackageName - = PackageName Text - deriving (Show, Eq, Ord) - -instance ToJSON PackageName where - toJSON (PackageName t) = toJSON t - -instance FromJSON PackageName where - parseJSON = - withText "package name" fromText - -fromText :: Monad m => Text -> m PackageName -fromText t = - case mkPackageName t of - Right pkgName -> pure pkgName - Left errs -> fail $ "Invalid package name: " <> show errs - -instance ToJSONKey PackageName where - toJSONKey = - ToJSONKeyText - runPackageName - (AesonEncoding.text . runPackageName) - -instance FromJSONKey PackageName where - fromJSONKey = - FromJSONKeyTextParser fromText - -data PackageNameError - = NotEmpty - | TooLong Int - | InvalidChars String - | RepeatedSeparators - | MustNotBeginSeparator - | MustNotEndSeparator - deriving (Show, Eq, Ord) - --- | Smart constructor for package names. Based on Bower's requirements for --- | package names. -mkPackageName :: Text -> Either PackageNameError PackageName -mkPackageName = fmap PackageName . validateAll validators - where - dashOrDot = ['-', '.'] - validateAll vs x = mapM_ (validateWith x) vs >> return x - validateWith x (p, err) - | p x = Right x - | otherwise = Left (err x) - validChar c = isAscii c && (isLower c || isDigit c || c `elem` dashOrDot) - validators = - [ (not . T.null, const NotEmpty) - , (T.all validChar, InvalidChars . T.unpack . T.filter (not . validChar)) - , (firstChar (`notElem` dashOrDot), const MustNotBeginSeparator) - , (lastChar (`notElem` dashOrDot), const MustNotEndSeparator) - , (not . T.isInfixOf "--", const RepeatedSeparators) - , (not . T.isInfixOf "..", const RepeatedSeparators) - , (T.length >>> (<= 50), TooLong . T.length) - ] - firstChar p str = not (T.null str) && p (T.index str 0) - lastChar p = firstChar p . T.reverse - -runPackageName :: PackageName -> Text -runPackageName (PackageName t) = t - -preludePackageName :: PackageName -preludePackageName = PackageName "prelude" - -untitledPackageName :: PackageName -untitledPackageName = PackageName "untitled" diff --git a/src/Language/PureScript/Package/Types/PackageName.hs b/src/Language/PureScript/Package/Types/PackageName.hs new file mode 100644 index 0000000..0075a2e --- /dev/null +++ b/src/Language/PureScript/Package/Types/PackageName.hs @@ -0,0 +1,85 @@ +{-# LANGUAGE OverloadedStrings #-} + +module Language.PureScript.Package.Types.PackageName + ( PackageName + , mkPackageName + , runPackageName + , preludePackageName + , untitledPackageName + ) where + +import Control.Category ((>>>)) +import Data.Aeson (FromJSON, ToJSON, FromJSONKey(..), ToJSONKey(..), ToJSONKeyFunction(..), FromJSONKeyFunction(..), parseJSON, toJSON, withText) +import qualified Data.Aeson.Encoding as AesonEncoding +import Data.Char (isAscii, isLower, isDigit) +import Data.Monoid ((<>)) +import Data.Text (Text) +import qualified Data.Text as T + +newtype PackageName + = PackageName Text + deriving (Show, Eq, Ord) + +instance ToJSON PackageName where + toJSON (PackageName t) = toJSON t + +instance FromJSON PackageName where + parseJSON = + withText "package name" fromText + +fromText :: Monad m => Text -> m PackageName +fromText t = + case mkPackageName t of + Right pkgName -> pure pkgName + Left errs -> fail $ "Invalid package name: " <> show errs + +instance ToJSONKey PackageName where + toJSONKey = + ToJSONKeyText + runPackageName + (AesonEncoding.text . runPackageName) + +instance FromJSONKey PackageName where + fromJSONKey = + FromJSONKeyTextParser fromText + +data PackageNameError + = NotEmpty + | TooLong Int + | InvalidChars String + | RepeatedSeparators + | MustNotBeginSeparator + | MustNotEndSeparator + deriving (Show, Eq, Ord) + +-- | Smart constructor for package names. Based on Bower's requirements for +-- | package names. +mkPackageName :: Text -> Either PackageNameError PackageName +mkPackageName = fmap PackageName . validateAll validators + where + dashOrDot = ['-', '.'] + validateAll vs x = mapM_ (validateWith x) vs >> return x + validateWith x (p, err) + | p x = Right x + | otherwise = Left (err x) + validChar c = isAscii c && (isLower c || isDigit c || c `elem` dashOrDot) + validators = + [ (not . T.null, const NotEmpty) + , (T.all validChar, InvalidChars . T.unpack . T.filter (not . validChar)) + , (firstChar (`notElem` dashOrDot), const MustNotBeginSeparator) + , (lastChar (`notElem` dashOrDot), const MustNotEndSeparator) + , (not . T.isInfixOf "--", const RepeatedSeparators) + , (not . T.isInfixOf "..", const RepeatedSeparators) + , (T.length >>> (<= 50), TooLong . T.length) + ] + firstChar p str = not (T.null str) && p (T.index str 0) + lastChar p = firstChar p . T.reverse + +runPackageName :: PackageName -> Text +runPackageName (PackageName t) = t + +preludePackageName :: PackageName +preludePackageName = PackageName "prelude" + +untitledPackageName :: PackageName +untitledPackageName = PackageName "untitled" From 9eece6e93f1d6bf03b2952796ffc27ef318edfcb Mon Sep 17 00:00:00 2001 From: Matthew Leon Date: Thu, 10 Aug 2017 14:01:22 +0100 Subject: [PATCH 07/22] move PackageConfig type to separate module --- app/Main.hs | 3 ++- psc-package.cabal | 1 + src/Language/PureScript/Package/Types.hs | 10 +--------- .../PureScript/Package/Types/PackageConfig.hs | 18 ++++++++++++++++++ 4 files changed, 22 insertions(+), 10 deletions(-) create mode 100644 src/Language/PureScript/Package/Types/PackageConfig.hs diff --git a/app/Main.hs b/app/Main.hs index a19953e..6c9f522 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -34,7 +34,8 @@ import qualified Text.ParserCombinators.ReadP as Read import Turtle hiding (echo, fold, s, x) import qualified Turtle -import Language.PureScript.Package.Types (PackageConfig(..), name, depends, set, source, PackageInfo(..), repo, version, dependencies) +import Language.PureScript.Package.Types (PackageInfo(..), repo, version, dependencies) +import Language.PureScript.Package.Types.PackageConfig (PackageConfig(..), name, depends, set, source) import Language.PureScript.Package.Types.PackageName (PackageName, mkPackageName, runPackageName, untitledPackageName, preludePackageName) echoT :: Text -> IO () diff --git a/psc-package.cabal b/psc-package.cabal index 52a71dc..56147f6 100644 --- a/psc-package.cabal +++ b/psc-package.cabal @@ -17,6 +17,7 @@ library hs-source-dirs: src ghc-options: -Wall -fwarn-tabs -fwarn-incomplete-uni-patterns -fwarn-incomplete-record-updates -fwarn-identities exposed-modules: Language.PureScript.Package.Types, + Language.PureScript.Package.Types.PackageConfig, Language.PureScript.Package.Types.PackageName build-depends: base >= 4.7 && < 5, aeson -any, diff --git a/src/Language/PureScript/Package/Types.hs b/src/Language/PureScript/Package/Types.hs index fcf3e2f..9a4d498 100644 --- a/src/Language/PureScript/Package/Types.hs +++ b/src/Language/PureScript/Package/Types.hs @@ -3,8 +3,7 @@ {-# LANGUAGE DeriveGeneric #-} module Language.PureScript.Package.Types - ( PackageConfig(..) - , PackageInfo(..) + ( PackageInfo(..) ) where import Data.Aeson (FromJSON, ToJSON) @@ -13,13 +12,6 @@ import GHC.Generics (Generic) import Language.PureScript.Package.Types.PackageName (PackageName) -data PackageConfig = PackageConfig - { name :: PackageName - , depends :: [PackageName] - , set :: Text - , source :: Text - } deriving (Show, Generic, FromJSON, ToJSON) - data PackageInfo = PackageInfo { repo :: Text , version :: Text diff --git a/src/Language/PureScript/Package/Types/PackageConfig.hs b/src/Language/PureScript/Package/Types/PackageConfig.hs new file mode 100644 index 0000000..88ee8ca --- /dev/null +++ b/src/Language/PureScript/Package/Types/PackageConfig.hs @@ -0,0 +1,18 @@ +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE DeriveAnyClass #-} +{-# LANGUAGE DeriveGeneric #-} + +module Language.PureScript.Package.Types.PackageConfig (PackageConfig(..)) where + +import Data.Aeson (FromJSON, ToJSON) +import Data.Text (Text) +import GHC.Generics (Generic) + +import Language.PureScript.Package.Types.PackageName (PackageName) + +data PackageConfig = PackageConfig + { name :: PackageName + , depends :: [PackageName] + , set :: Text + , source :: Text + } deriving (Show, Generic, FromJSON, ToJSON) From a1ab389d6ac453acbaa388242d35176dc1d1c126 Mon Sep 17 00:00:00 2001 From: Matthew Leon Date: Thu, 10 Aug 2017 14:05:41 +0100 Subject: [PATCH 08/22] move PackageInfo to separate module --- app/Main.hs | 6 +++--- psc-package.cabal | 4 ++-- .../PureScript/Package/{Types.hs => Types/PackageInfo.hs} | 4 +--- 3 files changed, 6 insertions(+), 8 deletions(-) rename src/Language/PureScript/Package/{Types.hs => Types/PackageInfo.hs} (85%) diff --git a/app/Main.hs b/app/Main.hs index 6c9f522..6758c7c 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -34,9 +34,9 @@ import qualified Text.ParserCombinators.ReadP as Read import Turtle hiding (echo, fold, s, x) import qualified Turtle -import Language.PureScript.Package.Types (PackageInfo(..), repo, version, dependencies) -import Language.PureScript.Package.Types.PackageConfig (PackageConfig(..), name, depends, set, source) -import Language.PureScript.Package.Types.PackageName (PackageName, mkPackageName, runPackageName, untitledPackageName, preludePackageName) +import Language.PureScript.Package.Types.PackageConfig (PackageConfig(..), name, depends, set, source) +import Language.PureScript.Package.Types.PackageInfo (PackageInfo(..), repo, version, dependencies) +import Language.PureScript.Package.Types.PackageName (PackageName, mkPackageName, runPackageName, untitledPackageName, preludePackageName) echoT :: Text -> IO () echoT = Turtle.printf (Turtle.s % "\n") diff --git a/psc-package.cabal b/psc-package.cabal index 56147f6..a62ef84 100644 --- a/psc-package.cabal +++ b/psc-package.cabal @@ -16,8 +16,8 @@ cabal-version: >=1.10 library hs-source-dirs: src ghc-options: -Wall -fwarn-tabs -fwarn-incomplete-uni-patterns -fwarn-incomplete-record-updates -fwarn-identities - exposed-modules: Language.PureScript.Package.Types, - Language.PureScript.Package.Types.PackageConfig, + exposed-modules: Language.PureScript.Package.Types.PackageConfig, + Language.PureScript.Package.Types.PackageInfo, Language.PureScript.Package.Types.PackageName build-depends: base >= 4.7 && < 5, aeson -any, diff --git a/src/Language/PureScript/Package/Types.hs b/src/Language/PureScript/Package/Types/PackageInfo.hs similarity index 85% rename from src/Language/PureScript/Package/Types.hs rename to src/Language/PureScript/Package/Types/PackageInfo.hs index 9a4d498..bb5486c 100644 --- a/src/Language/PureScript/Package/Types.hs +++ b/src/Language/PureScript/Package/Types/PackageInfo.hs @@ -2,9 +2,7 @@ {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-} -module Language.PureScript.Package.Types - ( PackageInfo(..) - ) where +module Language.PureScript.Package.Types.PackageInfo (PackageInfo(..)) where import Data.Aeson (FromJSON, ToJSON) import Data.Text (Text) From f9586d4e83e9e57f57230c2cc8f28876797719df Mon Sep 17 00:00:00 2001 From: Matthew Leon Date: Thu, 10 Aug 2017 14:44:39 +0100 Subject: [PATCH 09/22] move PackageConfig functions to module --- app/Main.hs | 34 +------------- psc-package.cabal | 2 + .../PureScript/Package/Types/PackageConfig.hs | 47 ++++++++++++++++++- 3 files changed, 48 insertions(+), 35 deletions(-) diff --git a/app/Main.hs b/app/Main.hs index 6758c7c..eb19f9c 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -34,7 +34,7 @@ import qualified Text.ParserCombinators.ReadP as Read import Turtle hiding (echo, fold, s, x) import qualified Turtle -import Language.PureScript.Package.Types.PackageConfig (PackageConfig(..), name, depends, set, source) +import Language.PureScript.Package.Types.PackageConfig (PackageConfig(..), name, depends, set, source, readPackageFile, writePackageFile) import Language.PureScript.Package.Types.PackageInfo (PackageInfo(..), repo, version, dependencies) import Language.PureScript.Package.Types.PackageName (PackageName, mkPackageName, runPackageName, untitledPackageName, preludePackageName) @@ -45,36 +45,9 @@ exitWithErr :: Text -> IO a exitWithErr errText = errT errText >> exit (ExitFailure 1) where errT = traverse Turtle.err . textToLines -packageFile :: Path.FilePath -packageFile = "psc-package.json" - pathToTextUnsafe :: Turtle.FilePath -> Text pathToTextUnsafe = either (error "Path.toText failed") id . Path.toText -readPackageFile :: IO PackageConfig -readPackageFile = do - exists <- testfile packageFile - unless exists $ exitWithErr "psc-package.json does not exist. Maybe you need to run psc-package init?" - mpkg <- Aeson.decodeStrict . encodeUtf8 <$> readTextFile packageFile - case mpkg of - Nothing -> exitWithErr "Unable to parse psc-package.json" - Just pkg -> return pkg - -packageConfigToJSON :: PackageConfig -> Text -packageConfigToJSON = - TL.toStrict - . TB.toLazyText - . encodePrettyToTextBuilder' config - where - config = defConfig - { confCompare = - keyOrder [ "name" - , "set" - , "source" - , "depends" - ] - } - packageSetToJSON :: PackageSet -> Text packageSetToJSON = TL.toStrict @@ -83,11 +56,6 @@ packageSetToJSON = where config = defConfig { confCompare = compare } -writePackageFile :: PackageConfig -> IO () -writePackageFile = - writeTextFile packageFile - . packageConfigToJSON - type PackageSet = Map.Map PackageName PackageInfo cloneShallow diff --git a/psc-package.cabal b/psc-package.cabal index a62ef84..06357df 100644 --- a/psc-package.cabal +++ b/psc-package.cabal @@ -21,6 +21,8 @@ library Language.PureScript.Package.Types.PackageName build-depends: base >= 4.7 && < 5, aeson -any, + aeson-pretty -any, + turtle ==1.3.*, text default-language: Haskell2010 diff --git a/src/Language/PureScript/Package/Types/PackageConfig.hs b/src/Language/PureScript/Package/Types/PackageConfig.hs index 88ee8ca..4c6914a 100644 --- a/src/Language/PureScript/Package/Types/PackageConfig.hs +++ b/src/Language/PureScript/Package/Types/PackageConfig.hs @@ -2,17 +2,60 @@ {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-} -module Language.PureScript.Package.Types.PackageConfig (PackageConfig(..)) where +module Language.PureScript.Package.Types.PackageConfig ( + PackageConfig(..) +, readPackageFile +, writePackageFile +) where import Data.Aeson (FromJSON, ToJSON) +import qualified Data.Aeson as Aeson +import qualified Data.Aeson.Encode.Pretty as AesonEncode import Data.Text (Text) +import Data.Text.Encoding (encodeUtf8) +import qualified Data.Text.Lazy as TL +import qualified Data.Text.Lazy.Builder as TB import GHC.Generics (Generic) +import Turtle +import Prelude hiding (FilePath) import Language.PureScript.Package.Types.PackageName (PackageName) data PackageConfig = PackageConfig { name :: PackageName - , depends :: [PackageName] , set :: Text , source :: Text + , depends :: [PackageName] } deriving (Show, Generic, FromJSON, ToJSON) + +packageConfigToJSON :: PackageConfig -> Text +packageConfigToJSON = + TL.toStrict + . TB.toLazyText + . AesonEncode.encodePrettyToTextBuilder' config + where + config = AesonEncode.defConfig + { AesonEncode.confCompare = + AesonEncode.keyOrder [ "name" + , "set" + , "source" + , "depends" + ] + } + +packageFile :: FilePath +packageFile = "psc-package.json" + +readPackageFile :: IO PackageConfig +readPackageFile = do + exists <- testfile packageFile + unless exists $ die "psc-package.json does not exist. Maybe you need to run psc-package init?" + mpkg <- Aeson.decodeStrict . encodeUtf8 <$> readTextFile packageFile + case mpkg of + Nothing -> die "Unable to parse psc-package.json" + Just pkg -> return pkg + +writePackageFile :: PackageConfig -> IO () +writePackageFile = + writeTextFile packageFile + . packageConfigToJSON From 53428cdb9eab2fbb0aa9143fc3c0492921f0833b Mon Sep 17 00:00:00 2001 From: Matthew Leon Date: Thu, 10 Aug 2017 15:59:12 +0100 Subject: [PATCH 10/22] module for installOrUpdate Moved several support functions to their own modules as well. --- app/Main.hs | 46 ++-------------------- psc-package.cabal | 7 +++- src/Language/PureScript/Package/Git.hs | 42 ++++++++++++++++++++ src/Language/PureScript/Package/Install.hs | 20 ++++++++++ src/Language/PureScript/Package/Path.hs | 7 ++++ 5 files changed, 77 insertions(+), 45 deletions(-) create mode 100644 src/Language/PureScript/Package/Git.hs create mode 100644 src/Language/PureScript/Package/Install.hs create mode 100644 src/Language/PureScript/Package/Path.hs diff --git a/app/Main.hs b/app/Main.hs index eb19f9c..de7479f 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -37,6 +37,9 @@ import qualified Turtle import Language.PureScript.Package.Types.PackageConfig (PackageConfig(..), name, depends, set, source, readPackageFile, writePackageFile) import Language.PureScript.Package.Types.PackageInfo (PackageInfo(..), repo, version, dependencies) import Language.PureScript.Package.Types.PackageName (PackageName, mkPackageName, runPackageName, untitledPackageName, preludePackageName) +import Language.PureScript.Package.Install (installOrUpdate) +import Language.PureScript.Package.Path (pathToTextUnsafe) +import Language.PureScript.Package.Git (cloneShallow, listRemoteTags) echoT :: Text -> IO () echoT = Turtle.printf (Turtle.s % "\n") @@ -45,9 +48,6 @@ exitWithErr :: Text -> IO a exitWithErr errText = errT errText >> exit (ExitFailure 1) where errT = traverse Turtle.err . textToLines -pathToTextUnsafe :: Turtle.FilePath -> Text -pathToTextUnsafe = either (error "Path.toText failed") id . Path.toText - packageSetToJSON :: PackageSet -> Text packageSetToJSON = TL.toStrict @@ -58,37 +58,6 @@ packageSetToJSON = type PackageSet = Map.Map PackageName PackageInfo -cloneShallow - :: Text - -- ^ repo - -> Text - -- ^ branch/tag - -> Turtle.FilePath - -- ^ target directory - -> IO ExitCode -cloneShallow from ref into = - proc "git" - [ "clone" - , "-q" - , "-c", "advice.detachedHead=false" - , "--depth", "1" - , "-b", ref - , from - , pathToTextUnsafe into - ] empty .||. exit (ExitFailure 1) - -listRemoteTags - :: Text - -- ^ repo - -> Turtle.Shell Text -listRemoteTags from = let gitProc = inproc "git" - [ "ls-remote" - , "-q" - , "-t" - , from - ] empty - in lineToText <$> gitProc - getPackageSet :: PackageConfig -> IO () getPackageSet PackageConfig{ source, set } = do let pkgDir = ".psc-package" fromText set ".set" @@ -110,15 +79,6 @@ writePackageSet PackageConfig{ set } = let dbFile = ".psc-package" fromText set ".set" "packages.json" in writeTextFile dbFile . packageSetToJSON -installOrUpdate :: Text -> PackageName -> PackageInfo -> IO Turtle.FilePath -installOrUpdate set pkgName PackageInfo{ repo, version } = do - let pkgDir = ".psc-package" fromText set fromText (runPackageName pkgName) fromText version - exists <- testdir pkgDir - unless exists . void $ do - echoT ("Updating " <> runPackageName pkgName) - cloneShallow repo version pkgDir - pure pkgDir - getTransitiveDeps :: PackageSet -> [PackageName] -> IO [(PackageName, PackageInfo)] getTransitiveDeps db deps = Map.toList . fold <$> traverse (go Set.empty) deps diff --git a/psc-package.cabal b/psc-package.cabal index 06357df..3d8d2c7 100644 --- a/psc-package.cabal +++ b/psc-package.cabal @@ -18,11 +18,14 @@ library ghc-options: -Wall -fwarn-tabs -fwarn-incomplete-uni-patterns -fwarn-incomplete-record-updates -fwarn-identities exposed-modules: Language.PureScript.Package.Types.PackageConfig, Language.PureScript.Package.Types.PackageInfo, - Language.PureScript.Package.Types.PackageName + Language.PureScript.Package.Types.PackageName, + Language.PureScript.Package.Git, + Language.PureScript.Package.Install, + Language.PureScript.Package.Path build-depends: base >= 4.7 && < 5, aeson -any, aeson-pretty -any, - turtle ==1.3.*, + turtle == 1.3.*, text default-language: Haskell2010 diff --git a/src/Language/PureScript/Package/Git.hs b/src/Language/PureScript/Package/Git.hs new file mode 100644 index 0000000..5657430 --- /dev/null +++ b/src/Language/PureScript/Package/Git.hs @@ -0,0 +1,42 @@ +{-# LANGUAGE OverloadedStrings #-} + +module Language.PureScript.Package.Git ( + cloneShallow +, listRemoteTags +) where + +import Turtle +import Prelude hiding (FilePath) + +import Language.PureScript.Package.Path (pathToTextUnsafe) + +cloneShallow + :: Text + -- ^ repo + -> Text + -- ^ branch/tag + -> Turtle.FilePath + -- ^ target directory + -> IO ExitCode +cloneShallow from ref into = + proc "git" + [ "clone" + , "-q" + , "-c", "advice.detachedHead=false" + , "--depth", "1" + , "-b", ref + , from + , pathToTextUnsafe into + ] empty .||. exit (ExitFailure 1) + +listRemoteTags + :: Text + -- ^ repo + -> Turtle.Shell Text +listRemoteTags from = let gitProc = inproc "git" + [ "ls-remote" + , "-q" + , "-t" + , from + ] empty + in lineToText <$> gitProc diff --git a/src/Language/PureScript/Package/Install.hs b/src/Language/PureScript/Package/Install.hs new file mode 100644 index 0000000..a2576bd --- /dev/null +++ b/src/Language/PureScript/Package/Install.hs @@ -0,0 +1,20 @@ +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE NamedFieldPuns #-} + +module Language.PureScript.Package.Install (installOrUpdate) where + +import Turtle +import Prelude hiding (FilePath) + +import Language.PureScript.Package.Types.PackageInfo (PackageInfo(..)) +import Language.PureScript.Package.Types.PackageName (PackageName, runPackageName) +import Language.PureScript.Package.Git (cloneShallow) + +installOrUpdate :: Text -> PackageName -> PackageInfo -> IO FilePath +installOrUpdate set pkgName PackageInfo{ repo, version } = do + let pkgDir = ".psc-package" fromText set fromText (runPackageName pkgName) fromText version + exists <- testdir pkgDir + unless exists . void $ do + echo $ "Updating " <> unsafeTextToLine (runPackageName pkgName) + cloneShallow repo version pkgDir + pure pkgDir diff --git a/src/Language/PureScript/Package/Path.hs b/src/Language/PureScript/Package/Path.hs new file mode 100644 index 0000000..8f7e4d3 --- /dev/null +++ b/src/Language/PureScript/Package/Path.hs @@ -0,0 +1,7 @@ +module Language.PureScript.Package.Path (pathToTextUnsafe) where + +import Turtle (FilePath, Text, toText) +import Prelude (either, error, id, (.)) + +pathToTextUnsafe :: FilePath -> Text +pathToTextUnsafe = either (error "FilePath.toText failed") id . toText From 8103ed85624362ce3dd879aa44eea89f28b7d87e Mon Sep 17 00:00:00 2001 From: Matthew Leon Date: Thu, 10 Aug 2017 18:01:14 +0100 Subject: [PATCH 11/22] PackageSet module --- app/Main.hs | 39 +------------ psc-package.cabal | 4 +- .../PureScript/Package/Types/PackageSet.hs | 55 +++++++++++++++++++ 3 files changed, 59 insertions(+), 39 deletions(-) create mode 100644 src/Language/PureScript/Package/Types/PackageSet.hs diff --git a/app/Main.hs b/app/Main.hs index de7479f..045db53 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -7,8 +7,6 @@ module Main where import qualified Control.Foldl as Foldl import Control.Concurrent.Async (forConcurrently_) -import qualified Data.Aeson as Aeson -import Data.Aeson.Encode.Pretty import Data.Foldable (fold, for_, traverse_) import qualified Data.Graph as G import Data.List (maximumBy, nub) @@ -18,9 +16,6 @@ import Data.Ord (comparing) import qualified Data.Set as Set import Data.Text (pack) import qualified Data.Text as T -import Data.Text.Encoding (encodeUtf8) -import qualified Data.Text.Lazy as TL -import qualified Data.Text.Lazy.Builder as TB import qualified Data.Text.Read as TR import Data.Traversable (for) import Data.Version (Version(..), parseVersion, showVersion) @@ -37,9 +32,10 @@ import qualified Turtle import Language.PureScript.Package.Types.PackageConfig (PackageConfig(..), name, depends, set, source, readPackageFile, writePackageFile) import Language.PureScript.Package.Types.PackageInfo (PackageInfo(..), repo, version, dependencies) import Language.PureScript.Package.Types.PackageName (PackageName, mkPackageName, runPackageName, untitledPackageName, preludePackageName) +import Language.PureScript.Package.Types.PackageSet (PackageSet, getPackageSet, readPackageSet, writePackageSet) import Language.PureScript.Package.Install (installOrUpdate) import Language.PureScript.Package.Path (pathToTextUnsafe) -import Language.PureScript.Package.Git (cloneShallow, listRemoteTags) +import Language.PureScript.Package.Git (listRemoteTags) echoT :: Text -> IO () echoT = Turtle.printf (Turtle.s % "\n") @@ -48,37 +44,6 @@ exitWithErr :: Text -> IO a exitWithErr errText = errT errText >> exit (ExitFailure 1) where errT = traverse Turtle.err . textToLines -packageSetToJSON :: PackageSet -> Text -packageSetToJSON = - TL.toStrict - . TB.toLazyText - . encodePrettyToTextBuilder' config - where - config = defConfig { confCompare = compare } - -type PackageSet = Map.Map PackageName PackageInfo - -getPackageSet :: PackageConfig -> IO () -getPackageSet PackageConfig{ source, set } = do - let pkgDir = ".psc-package" fromText set ".set" - exists <- testdir pkgDir - unless exists . void $ cloneShallow source set pkgDir - -readPackageSet :: PackageConfig -> IO PackageSet -readPackageSet PackageConfig{ set } = do - let dbFile = ".psc-package" fromText set ".set" "packages.json" - exists <- testfile dbFile - unless exists $ exitWithErr $ format (fp%" does not exist") dbFile - mdb <- Aeson.decodeStrict . encodeUtf8 <$> readTextFile dbFile - case mdb of - Nothing -> exitWithErr "Unable to parse packages.json" - Just db -> return db - -writePackageSet :: PackageConfig -> PackageSet -> IO () -writePackageSet PackageConfig{ set } = - let dbFile = ".psc-package" fromText set ".set" "packages.json" - in writeTextFile dbFile . packageSetToJSON - getTransitiveDeps :: PackageSet -> [PackageName] -> IO [(PackageName, PackageInfo)] getTransitiveDeps db deps = Map.toList . fold <$> traverse (go Set.empty) deps diff --git a/psc-package.cabal b/psc-package.cabal index 3d8d2c7..cf47741 100644 --- a/psc-package.cabal +++ b/psc-package.cabal @@ -19,12 +19,14 @@ library exposed-modules: Language.PureScript.Package.Types.PackageConfig, Language.PureScript.Package.Types.PackageInfo, Language.PureScript.Package.Types.PackageName, + Language.PureScript.Package.Types.PackageSet, Language.PureScript.Package.Git, Language.PureScript.Package.Install, Language.PureScript.Package.Path build-depends: base >= 4.7 && < 5, aeson -any, aeson-pretty -any, + containers, turtle == 1.3.*, text default-language: Haskell2010 @@ -32,8 +34,6 @@ library executable psc-package build-depends: psc-package, base >=4 && <5, - aeson -any, - aeson-pretty -any, async -any, bytestring -any, containers -any, diff --git a/src/Language/PureScript/Package/Types/PackageSet.hs b/src/Language/PureScript/Package/Types/PackageSet.hs new file mode 100644 index 0000000..ec19ddf --- /dev/null +++ b/src/Language/PureScript/Package/Types/PackageSet.hs @@ -0,0 +1,55 @@ +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE NamedFieldPuns #-} + +module Language.PureScript.Package.Types.PackageSet ( + PackageSet +, packageSetToJSON +, getPackageSet +, readPackageSet +, writePackageSet +) where + +import qualified Data.Aeson as Aeson +import qualified Data.Aeson.Encode.Pretty as AesonEncode +import Data.Map (Map) +import Data.Text.Encoding (encodeUtf8) +import qualified Data.Text.Lazy as TL +import qualified Data.Text.Lazy.Builder as TB +import Turtle +import Prelude hiding (FilePath) + +import Language.PureScript.Package.Types.PackageConfig (PackageConfig(..)) +import Language.PureScript.Package.Types.PackageInfo (PackageInfo) +import Language.PureScript.Package.Types.PackageName (PackageName) +import Language.PureScript.Package.Git (cloneShallow) + +type PackageSet = Map PackageName PackageInfo + +packageSetToJSON :: PackageSet -> Text +packageSetToJSON = + TL.toStrict + . TB.toLazyText + . AesonEncode.encodePrettyToTextBuilder' config + where + config = AesonEncode.defConfig { AesonEncode.confCompare = compare } + +getPackageSet :: PackageConfig -> IO () +getPackageSet PackageConfig{ source, set } = do + let pkgDir = ".psc-package" fromText set ".set" + exists <- testdir pkgDir + unless exists . void $ cloneShallow source set pkgDir + +readPackageSet :: PackageConfig -> IO PackageSet +readPackageSet PackageConfig{ set } = do + let dbFile = ".psc-package" fromText set ".set" "packages.json" + exists <- testfile dbFile + unless exists $ die $ format (fp%" does not exist") dbFile + mdb <- Aeson.decodeStrict . encodeUtf8 <$> readTextFile dbFile + case mdb of + Nothing -> die "Unable to parse packages.json" + Just db -> return db + +writePackageSet :: PackageConfig -> PackageSet -> IO () +writePackageSet PackageConfig{ set } = + let dbFile = ".psc-package" fromText set ".set" "packages.json" + in writeTextFile dbFile . packageSetToJSON From 95891f404163e1ca26adf5fd3d826ecdcd7d2a4c Mon Sep 17 00:00:00 2001 From: Matthew Leon Date: Thu, 10 Aug 2017 18:22:30 +0100 Subject: [PATCH 12/22] Update module --- app/Main.hs | 27 ++--------------- psc-package.cabal | 5 ++-- .../PureScript/Package/Types/PackageSet.hs | 26 +++++++++++++++-- src/Language/PureScript/Package/Update.hs | 29 +++++++++++++++++++ 4 files changed, 57 insertions(+), 30 deletions(-) create mode 100644 src/Language/PureScript/Package/Update.hs diff --git a/app/Main.hs b/app/Main.hs index 045db53..5bb434f 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -6,7 +6,6 @@ module Main where import qualified Control.Foldl as Foldl -import Control.Concurrent.Async (forConcurrently_) import Data.Foldable (fold, for_, traverse_) import qualified Data.Graph as G import Data.List (maximumBy, nub) @@ -32,10 +31,11 @@ import qualified Turtle import Language.PureScript.Package.Types.PackageConfig (PackageConfig(..), name, depends, set, source, readPackageFile, writePackageFile) import Language.PureScript.Package.Types.PackageInfo (PackageInfo(..), repo, version, dependencies) import Language.PureScript.Package.Types.PackageName (PackageName, mkPackageName, runPackageName, untitledPackageName, preludePackageName) -import Language.PureScript.Package.Types.PackageSet (PackageSet, getPackageSet, readPackageSet, writePackageSet) +import Language.PureScript.Package.Types.PackageSet (PackageSet, getPackageSet, readPackageSet, writePackageSet, getTransitiveDeps) import Language.PureScript.Package.Install (installOrUpdate) import Language.PureScript.Package.Path (pathToTextUnsafe) import Language.PureScript.Package.Git (listRemoteTags) +import Language.PureScript.Package.Update (updateImpl) echoT :: Text -> IO () echoT = Turtle.printf (Turtle.s % "\n") @@ -44,29 +44,6 @@ exitWithErr :: Text -> IO a exitWithErr errText = errT errText >> exit (ExitFailure 1) where errT = traverse Turtle.err . textToLines -getTransitiveDeps :: PackageSet -> [PackageName] -> IO [(PackageName, PackageInfo)] -getTransitiveDeps db deps = - Map.toList . fold <$> traverse (go Set.empty) deps - where - go seen pkg - | pkg `Set.member` seen = - exitWithErr ("Cycle in package dependencies at package " <> runPackageName pkg) - | otherwise = - case Map.lookup pkg db of - Nothing -> - exitWithErr ("Package " <> runPackageName pkg <> " does not exist in package set") - Just info@PackageInfo{ dependencies } -> do - m <- fold <$> traverse (go (Set.insert pkg seen)) dependencies - return (Map.insert pkg info m) - -updateImpl :: PackageConfig -> IO () -updateImpl config@PackageConfig{ depends } = do - getPackageSet config - db <- readPackageSet config - trans <- getTransitiveDeps db depends - echoT ("Updating " <> pack (show (length trans)) <> " packages...") - forConcurrently_ trans . uncurry $ installOrUpdate (set config) - getPureScriptVersion :: IO Version getPureScriptVersion = do let pursProc = inproc "purs" [ "--version" ] empty diff --git a/psc-package.cabal b/psc-package.cabal index cf47741..d539fa8 100644 --- a/psc-package.cabal +++ b/psc-package.cabal @@ -22,10 +22,12 @@ library Language.PureScript.Package.Types.PackageSet, Language.PureScript.Package.Git, Language.PureScript.Package.Install, - Language.PureScript.Package.Path + Language.PureScript.Package.Path, + Language.PureScript.Package.Update build-depends: base >= 4.7 && < 5, aeson -any, aeson-pretty -any, + async -any, containers, turtle == 1.3.*, text @@ -34,7 +36,6 @@ library executable psc-package build-depends: psc-package, base >=4 && <5, - async -any, bytestring -any, containers -any, foldl -any, diff --git a/src/Language/PureScript/Package/Types/PackageSet.hs b/src/Language/PureScript/Package/Types/PackageSet.hs index ec19ddf..f4eeca9 100644 --- a/src/Language/PureScript/Package/Types/PackageSet.hs +++ b/src/Language/PureScript/Package/Types/PackageSet.hs @@ -7,20 +7,24 @@ module Language.PureScript.Package.Types.PackageSet ( , getPackageSet , readPackageSet , writePackageSet +, getTransitiveDeps ) where import qualified Data.Aeson as Aeson import qualified Data.Aeson.Encode.Pretty as AesonEncode +import Data.Foldable (fold) import Data.Map (Map) +import qualified Data.Map as Map +import qualified Data.Set as Set import Data.Text.Encoding (encodeUtf8) import qualified Data.Text.Lazy as TL import qualified Data.Text.Lazy.Builder as TB -import Turtle +import Turtle hiding (fold) import Prelude hiding (FilePath) import Language.PureScript.Package.Types.PackageConfig (PackageConfig(..)) -import Language.PureScript.Package.Types.PackageInfo (PackageInfo) -import Language.PureScript.Package.Types.PackageName (PackageName) +import Language.PureScript.Package.Types.PackageInfo (PackageInfo(..)) +import Language.PureScript.Package.Types.PackageName (PackageName, runPackageName) import Language.PureScript.Package.Git (cloneShallow) type PackageSet = Map PackageName PackageInfo @@ -53,3 +57,19 @@ writePackageSet :: PackageConfig -> PackageSet -> IO () writePackageSet PackageConfig{ set } = let dbFile = ".psc-package" fromText set ".set" "packages.json" in writeTextFile dbFile . packageSetToJSON + +getTransitiveDeps :: PackageSet -> [PackageName] -> IO [(PackageName, PackageInfo)] +getTransitiveDeps db deps = + Map.toList . fold <$> traverse (go Set.empty) deps + where + go seen pkg + | pkg `Set.member` seen = + die $ "Cycle in package dependencies at package " <> runPackageName pkg + | otherwise = + case Map.lookup pkg db of + Nothing -> + die $ "Package " <> runPackageName pkg <> " does not exist in package set" + Just info@PackageInfo{ dependencies } -> do + m <- fold <$> traverse (go (Set.insert pkg seen)) dependencies + return (Map.insert pkg info m) + diff --git a/src/Language/PureScript/Package/Update.hs b/src/Language/PureScript/Package/Update.hs new file mode 100644 index 0000000..4d3eea9 --- /dev/null +++ b/src/Language/PureScript/Package/Update.hs @@ -0,0 +1,29 @@ +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE NamedFieldPuns #-} + +module Language.PureScript.Package.Update (updateImpl) where + +import Control.Concurrent.Async (forConcurrently_) +import qualified Data.Text as T +import Turtle +import Prelude hiding (FilePath) + +import Language.PureScript.Package.Types.PackageConfig (PackageConfig(..)) +import Language.PureScript.Package.Types.PackageSet (readPackageSet, getTransitiveDeps) +import Language.PureScript.Package.Install (installOrUpdate) +import Language.PureScript.Package.Git (cloneShallow) + +updateImpl :: PackageConfig -> IO () +updateImpl config@PackageConfig{ depends } = do + getPackageSet config + db <- readPackageSet config + trans <- getTransitiveDeps db depends + echo ("Updating " <> unsafeTextToLine (T.pack (show (length trans))) <> " packages...") + forConcurrently_ trans . uncurry $ installOrUpdate (set config) + + where + getPackageSet :: PackageConfig -> IO () + getPackageSet PackageConfig{ source, set } = do + let pkgDir = ".psc-package" fromText set ".set" + exists <- testdir pkgDir + unless exists . void $ cloneShallow source set pkgDir From 18f3c3284be2725e083c23ba77df10c3b67cb7bd Mon Sep 17 00:00:00 2001 From: Matthew Leon Date: Thu, 10 Aug 2017 18:45:04 +0100 Subject: [PATCH 13/22] Initialize module --- app/Main.hs | 53 ++--------------- psc-package.cabal | 2 + src/Language/PureScript/Package/Initialize.hs | 58 +++++++++++++++++++ 3 files changed, 65 insertions(+), 48 deletions(-) create mode 100644 src/Language/PureScript/Package/Initialize.hs diff --git a/app/Main.hs b/app/Main.hs index 5bb434f..6c3b7b0 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -8,30 +8,28 @@ module Main where import qualified Control.Foldl as Foldl import Data.Foldable (fold, for_, traverse_) import qualified Data.Graph as G -import Data.List (maximumBy, nub) +import Data.List (nub) import qualified Data.Map as Map import Data.Maybe (fromMaybe, mapMaybe) -import Data.Ord (comparing) -import qualified Data.Set as Set import Data.Text (pack) import qualified Data.Text as T import qualified Data.Text.Read as TR import Data.Traversable (for) -import Data.Version (Version(..), parseVersion, showVersion) +import Data.Version (showVersion) import qualified Filesystem.Path.CurrentOS as Path import qualified Options.Applicative as Opts import qualified Paths_psc_package as Paths import System.Environment (getArgs) import qualified System.IO as IO import qualified System.Process as Process -import qualified Text.ParserCombinators.ReadP as Read import Turtle hiding (echo, fold, s, x) import qualified Turtle import Language.PureScript.Package.Types.PackageConfig (PackageConfig(..), name, depends, set, source, readPackageFile, writePackageFile) import Language.PureScript.Package.Types.PackageInfo (PackageInfo(..), repo, version, dependencies) -import Language.PureScript.Package.Types.PackageName (PackageName, mkPackageName, runPackageName, untitledPackageName, preludePackageName) -import Language.PureScript.Package.Types.PackageSet (PackageSet, getPackageSet, readPackageSet, writePackageSet, getTransitiveDeps) +import Language.PureScript.Package.Types.PackageName (PackageName, mkPackageName, runPackageName) +import Language.PureScript.Package.Types.PackageSet (PackageSet, readPackageSet, writePackageSet, getTransitiveDeps) +import Language.PureScript.Package.Initialize (initialize) import Language.PureScript.Package.Install (installOrUpdate) import Language.PureScript.Package.Path (pathToTextUnsafe) import Language.PureScript.Package.Git (listRemoteTags) @@ -44,47 +42,6 @@ exitWithErr :: Text -> IO a exitWithErr errText = errT errText >> exit (ExitFailure 1) where errT = traverse Turtle.err . textToLines -getPureScriptVersion :: IO Version -getPureScriptVersion = do - let pursProc = inproc "purs" [ "--version" ] empty - outputLines <- Turtle.fold (fmap lineToText pursProc) Foldl.list - case outputLines of - [onlyLine] - | results@(_ : _) <- Read.readP_to_S parseVersion (T.unpack onlyLine) -> - pure (fst (maximumBy (comparing (length . versionBranch . fst)) results)) - | otherwise -> exitWithErr "Unable to parse output of purs --version" - _ -> exitWithErr "Unexpected output from purs --version" - -initialize :: Maybe (Text, Maybe Text) -> IO () -initialize setAndSource = do - exists <- testfile "psc-package.json" - when exists $ exitWithErr "psc-package.json already exists" - echoT "Initializing new project in current directory" - pkgName <- packageNameFromPWD . pathToTextUnsafe . Path.filename <$> pwd - pkg <- case setAndSource of - Nothing -> do - pursVersion <- getPureScriptVersion - echoT ("Using the default package set for PureScript compiler version " <> - fromString (showVersion pursVersion)) - echoT "(Use --source / --set to override this behavior)" - pure PackageConfig { name = pkgName - , depends = [ preludePackageName ] - , source = "https://github.com/purescript/package-sets.git" - , set = "psc-" <> pack (showVersion pursVersion) - } - Just (set, source) -> - pure PackageConfig { name = pkgName - , depends = [ preludePackageName ] - , source = fromMaybe "https://github.com/purescript/package-sets.git" source - , set - } - - writePackageFile pkg - updateImpl pkg - where - packageNameFromPWD = - either (const untitledPackageName) id . mkPackageName - update :: IO () update = do pkg <- readPackageFile diff --git a/psc-package.cabal b/psc-package.cabal index d539fa8..54902ca 100644 --- a/psc-package.cabal +++ b/psc-package.cabal @@ -21,6 +21,7 @@ library Language.PureScript.Package.Types.PackageName, Language.PureScript.Package.Types.PackageSet, Language.PureScript.Package.Git, + Language.PureScript.Package.Initialize, Language.PureScript.Package.Install, Language.PureScript.Package.Path, Language.PureScript.Package.Update @@ -29,6 +30,7 @@ library aeson-pretty -any, async -any, containers, + foldl -any, turtle == 1.3.*, text default-language: Haskell2010 diff --git a/src/Language/PureScript/Package/Initialize.hs b/src/Language/PureScript/Package/Initialize.hs new file mode 100644 index 0000000..3ea6d8a --- /dev/null +++ b/src/Language/PureScript/Package/Initialize.hs @@ -0,0 +1,58 @@ +{-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE OverloadedStrings #-} + +module Language.PureScript.Package.Initialize (initialize) where + +import qualified Control.Foldl as Foldl +import Data.List (maximumBy) +import Data.Maybe (fromMaybe) +import Data.Ord (comparing) +import qualified Data.Text as T +import Data.Version (Version(..), parseVersion, showVersion) +import Text.ParserCombinators.ReadP (readP_to_S) +import Turtle +import Prelude hiding (FilePath) + +import Language.PureScript.Package.Types.PackageConfig (PackageConfig(..), name, depends, set, source, writePackageFile) +import Language.PureScript.Package.Types.PackageName (untitledPackageName, mkPackageName, preludePackageName) +import Language.PureScript.Package.Path (pathToTextUnsafe) +import Language.PureScript.Package.Update (updateImpl) + +initialize :: Maybe (Text, Maybe Text) -> IO () +initialize setAndSource = do + exists <- testfile "psc-package.json" + when exists $ die "psc-package.json already exists" + echo "Initializing new project in current directory" + pkgName <- packageNameFromPWD . pathToTextUnsafe . filename <$> pwd + pkg <- case setAndSource of + Nothing -> do + pursVersion <- getPureScriptVersion + echo ("Using the default package set for PureScript compiler version " <> + unsafeTextToLine (fromString (showVersion pursVersion))) + echo "(Use --source / --set to override this behavior)" + pure PackageConfig { name = pkgName + , depends = [ preludePackageName ] + , source = defaultSource + , set = "psc-" <> T.pack (showVersion pursVersion) + } + Just (set, source) -> + pure PackageConfig { name = pkgName + , depends = [ preludePackageName ] + , source = fromMaybe defaultSource source + , set + } + + writePackageFile pkg + updateImpl pkg + where + defaultSource = "https://github.com/purescript/package-sets.git" + packageNameFromPWD = either (const untitledPackageName) id . mkPackageName + getPureScriptVersion = do + let pursProc = inproc "purs" [ "--version" ] empty + outputLines <- Turtle.fold (fmap lineToText pursProc) Foldl.list + case outputLines of + [onlyLine] + | results@(_ : _) <- readP_to_S parseVersion (T.unpack onlyLine) -> + pure (fst (maximumBy (comparing (length . versionBranch . fst)) results)) + | otherwise -> die "Unable to parse output of purs --version" + _ -> die "Unexpected output from purs --version" From f72a597e8e1de0ffab923d83953b3c0533c8a824 Mon Sep 17 00:00:00 2001 From: Matthew Leon Date: Thu, 10 Aug 2017 18:50:03 +0100 Subject: [PATCH 14/22] replace exitWithErr with die --- app/Main.hs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/Main.hs b/app/Main.hs index 6c3b7b0..e6b5a83 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -38,10 +38,6 @@ import Language.PureScript.Package.Update (updateImpl) echoT :: Text -> IO () echoT = Turtle.printf (Turtle.s % "\n") -exitWithErr :: Text -> IO a -exitWithErr errText = errT errText >> exit (ExitFailure 1) - where errT = traverse Turtle.err . textToLines - update :: IO () update = do pkg <- readPackageFile @@ -73,7 +69,7 @@ packageNameFromString str = case mkPackageName (pack str) of Right pkgName -> pure pkgName - Left _ -> exitWithErr $ "Invalid package name: " <> pack (show str) + Left _ -> die $ "Invalid package name: " <> pack (show str) listDependencies :: IO () listDependencies = do From a7d0b32f909edbd2c01334fabc92dc36949b6c43 Mon Sep 17 00:00:00 2001 From: Matthew Leon Date: Thu, 10 Aug 2017 19:10:47 +0100 Subject: [PATCH 15/22] move appropriate functions into Update module --- app/Main.hs | 35 +++---------------- src/Language/PureScript/Package/Install.hs | 24 ++++++------- .../PureScript/Package/Types/PackageName.hs | 8 +++++ src/Language/PureScript/Package/Update.hs | 33 +++++++++++++++-- 4 files changed, 53 insertions(+), 47 deletions(-) diff --git a/app/Main.hs b/app/Main.hs index e6b5a83..5385acd 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -8,7 +8,6 @@ module Main where import qualified Control.Foldl as Foldl import Data.Foldable (fold, for_, traverse_) import qualified Data.Graph as G -import Data.List (nub) import qualified Data.Map as Map import Data.Maybe (fromMaybe, mapMaybe) import Data.Text (pack) @@ -25,32 +24,19 @@ import qualified System.Process as Process import Turtle hiding (echo, fold, s, x) import qualified Turtle -import Language.PureScript.Package.Types.PackageConfig (PackageConfig(..), name, depends, set, source, readPackageFile, writePackageFile) +import Language.PureScript.Package.Types.PackageConfig (PackageConfig(..), name, depends, set, source, readPackageFile) import Language.PureScript.Package.Types.PackageInfo (PackageInfo(..), repo, version, dependencies) -import Language.PureScript.Package.Types.PackageName (PackageName, mkPackageName, runPackageName) +import Language.PureScript.Package.Types.PackageName (PackageName, runPackageName, packageNameFromString) import Language.PureScript.Package.Types.PackageSet (PackageSet, readPackageSet, writePackageSet, getTransitiveDeps) import Language.PureScript.Package.Initialize (initialize) -import Language.PureScript.Package.Install (installOrUpdate) +import Language.PureScript.Package.Install (install) import Language.PureScript.Package.Path (pathToTextUnsafe) import Language.PureScript.Package.Git (listRemoteTags) -import Language.PureScript.Package.Update (updateImpl) +import Language.PureScript.Package.Update (update, updateImpl, installOrUpdate, updateAndWritePackageFile) echoT :: Text -> IO () echoT = Turtle.printf (Turtle.s % "\n") -update :: IO () -update = do - pkg <- readPackageFile - updateImpl pkg - echoT "Update complete" - -install :: String -> IO () -install pkgName' = do - pkg <- readPackageFile - pkgName <- packageNameFromString pkgName' - let pkg' = pkg { depends = nub (pkgName : depends pkg) } - updateAndWritePackageFile pkg' - uninstall :: String -> IO () uninstall pkgName' = do pkg <- readPackageFile @@ -58,19 +44,6 @@ uninstall pkgName' = do let pkg' = pkg { depends = filter (/= pkgName) $ depends pkg } updateAndWritePackageFile pkg' -updateAndWritePackageFile :: PackageConfig -> IO () -updateAndWritePackageFile pkg = do - updateImpl pkg - writePackageFile pkg - echoT "psc-package.json file was updated" - -packageNameFromString :: String -> IO PackageName -packageNameFromString str = - case mkPackageName (pack str) of - Right pkgName -> - pure pkgName - Left _ -> die $ "Invalid package name: " <> pack (show str) - listDependencies :: IO () listDependencies = do pkg@PackageConfig{ depends } <- readPackageFile diff --git a/src/Language/PureScript/Package/Install.hs b/src/Language/PureScript/Package/Install.hs index a2576bd..c123e2b 100644 --- a/src/Language/PureScript/Package/Install.hs +++ b/src/Language/PureScript/Package/Install.hs @@ -1,20 +1,18 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE NamedFieldPuns #-} -module Language.PureScript.Package.Install (installOrUpdate) where +module Language.PureScript.Package.Install (install) where -import Turtle +import Data.List (nub) import Prelude hiding (FilePath) -import Language.PureScript.Package.Types.PackageInfo (PackageInfo(..)) -import Language.PureScript.Package.Types.PackageName (PackageName, runPackageName) -import Language.PureScript.Package.Git (cloneShallow) +import Language.PureScript.Package.Types.PackageConfig (readPackageFile, depends) +import Language.PureScript.Package.Types.PackageName (packageNameFromString) +import Language.PureScript.Package.Update (updateAndWritePackageFile) -installOrUpdate :: Text -> PackageName -> PackageInfo -> IO FilePath -installOrUpdate set pkgName PackageInfo{ repo, version } = do - let pkgDir = ".psc-package" fromText set fromText (runPackageName pkgName) fromText version - exists <- testdir pkgDir - unless exists . void $ do - echo $ "Updating " <> unsafeTextToLine (runPackageName pkgName) - cloneShallow repo version pkgDir - pure pkgDir +install :: String -> IO () +install pkgName' = do + pkg <- readPackageFile + pkgName <- packageNameFromString pkgName' + let pkg' = pkg { depends = nub (pkgName : depends pkg) } -- TODO: ordnub + updateAndWritePackageFile pkg' diff --git a/src/Language/PureScript/Package/Types/PackageName.hs b/src/Language/PureScript/Package/Types/PackageName.hs index 0075a2e..30de9c0 100644 --- a/src/Language/PureScript/Package/Types/PackageName.hs +++ b/src/Language/PureScript/Package/Types/PackageName.hs @@ -4,6 +4,7 @@ module Language.PureScript.Package.Types.PackageName ( PackageName , mkPackageName , runPackageName + , packageNameFromString , preludePackageName , untitledPackageName ) where @@ -15,6 +16,7 @@ import Data.Char (isAscii, isLower, isDigit) import Data.Monoid ((<>)) import Data.Text (Text) import qualified Data.Text as T +import Turtle (die) newtype PackageName = PackageName Text @@ -78,6 +80,12 @@ mkPackageName = fmap PackageName . validateAll validators runPackageName :: PackageName -> Text runPackageName (PackageName t) = t +packageNameFromString :: String -> IO PackageName +packageNameFromString str = + case mkPackageName (T.pack str) of + Right pkgName -> pure pkgName + Left _ -> die $ "Invalid package name: " <> T.pack (show str) + preludePackageName :: PackageName preludePackageName = PackageName "prelude" diff --git a/src/Language/PureScript/Package/Update.hs b/src/Language/PureScript/Package/Update.hs index 4d3eea9..183057d 100644 --- a/src/Language/PureScript/Package/Update.hs +++ b/src/Language/PureScript/Package/Update.hs @@ -1,18 +1,30 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE NamedFieldPuns #-} -module Language.PureScript.Package.Update (updateImpl) where +module Language.PureScript.Package.Update ( + update +, updateImpl +, updateAndWritePackageFile +, installOrUpdate +) where import Control.Concurrent.Async (forConcurrently_) import qualified Data.Text as T import Turtle import Prelude hiding (FilePath) -import Language.PureScript.Package.Types.PackageConfig (PackageConfig(..)) +import Language.PureScript.Package.Types.PackageConfig (PackageConfig(..), readPackageFile, writePackageFile) +import Language.PureScript.Package.Types.PackageInfo (PackageInfo(..)) +import Language.PureScript.Package.Types.PackageName (PackageName, runPackageName) import Language.PureScript.Package.Types.PackageSet (readPackageSet, getTransitiveDeps) -import Language.PureScript.Package.Install (installOrUpdate) import Language.PureScript.Package.Git (cloneShallow) +update :: IO () +update = do + pkg <- readPackageFile + updateImpl pkg + echo "Update complete" + updateImpl :: PackageConfig -> IO () updateImpl config@PackageConfig{ depends } = do getPackageSet config @@ -27,3 +39,18 @@ updateImpl config@PackageConfig{ depends } = do let pkgDir = ".psc-package" fromText set ".set" exists <- testdir pkgDir unless exists . void $ cloneShallow source set pkgDir + +updateAndWritePackageFile :: PackageConfig -> IO () +updateAndWritePackageFile pkg = do + updateImpl pkg + writePackageFile pkg + echo "psc-package.json file was updated" + +installOrUpdate :: Text -> PackageName -> PackageInfo -> IO FilePath +installOrUpdate set pkgName PackageInfo{ repo, version } = do + let pkgDir = ".psc-package" fromText set fromText (runPackageName pkgName) fromText version + exists <- testdir pkgDir + unless exists . void $ do + echo $ "Updating " <> unsafeTextToLine (runPackageName pkgName) + cloneShallow repo version pkgDir + pure pkgDir From d0c931f6d750cb563d0d62239414d8f191b1bf5c Mon Sep 17 00:00:00 2001 From: Matthew Leon Date: Thu, 10 Aug 2017 19:21:26 +0100 Subject: [PATCH 16/22] Uninstall module --- app/Main.hs | 12 +++--------- psc-package.cabal | 1 + src/Language/PureScript/Package/Uninstall.hs | 12 ++++++++++++ 3 files changed, 16 insertions(+), 9 deletions(-) create mode 100644 src/Language/PureScript/Package/Uninstall.hs diff --git a/app/Main.hs b/app/Main.hs index 5385acd..94f49cb 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -26,24 +26,18 @@ import qualified Turtle import Language.PureScript.Package.Types.PackageConfig (PackageConfig(..), name, depends, set, source, readPackageFile) import Language.PureScript.Package.Types.PackageInfo (PackageInfo(..), repo, version, dependencies) -import Language.PureScript.Package.Types.PackageName (PackageName, runPackageName, packageNameFromString) +import Language.PureScript.Package.Types.PackageName (PackageName, runPackageName) import Language.PureScript.Package.Types.PackageSet (PackageSet, readPackageSet, writePackageSet, getTransitiveDeps) import Language.PureScript.Package.Initialize (initialize) import Language.PureScript.Package.Install (install) import Language.PureScript.Package.Path (pathToTextUnsafe) import Language.PureScript.Package.Git (listRemoteTags) -import Language.PureScript.Package.Update (update, updateImpl, installOrUpdate, updateAndWritePackageFile) +import Language.PureScript.Package.Uninstall (uninstall) +import Language.PureScript.Package.Update (update, updateImpl, installOrUpdate) echoT :: Text -> IO () echoT = Turtle.printf (Turtle.s % "\n") -uninstall :: String -> IO () -uninstall pkgName' = do - pkg <- readPackageFile - pkgName <- packageNameFromString pkgName' - let pkg' = pkg { depends = filter (/= pkgName) $ depends pkg } - updateAndWritePackageFile pkg' - listDependencies :: IO () listDependencies = do pkg@PackageConfig{ depends } <- readPackageFile diff --git a/psc-package.cabal b/psc-package.cabal index 54902ca..6bc2784 100644 --- a/psc-package.cabal +++ b/psc-package.cabal @@ -24,6 +24,7 @@ library Language.PureScript.Package.Initialize, Language.PureScript.Package.Install, Language.PureScript.Package.Path, + Language.PureScript.Package.Uninstall, Language.PureScript.Package.Update build-depends: base >= 4.7 && < 5, aeson -any, diff --git a/src/Language/PureScript/Package/Uninstall.hs b/src/Language/PureScript/Package/Uninstall.hs new file mode 100644 index 0000000..9852c1f --- /dev/null +++ b/src/Language/PureScript/Package/Uninstall.hs @@ -0,0 +1,12 @@ +module Language.PureScript.Package.Uninstall (uninstall) where + +import Language.PureScript.Package.Types.PackageConfig (readPackageFile, depends) +import Language.PureScript.Package.Types.PackageName (packageNameFromString) +import Language.PureScript.Package.Update (updateAndWritePackageFile) + +uninstall :: String -> IO () +uninstall pkgName' = do + pkg <- readPackageFile + pkgName <- packageNameFromString pkgName' + let pkg' = pkg { depends = filter (/= pkgName) $ depends pkg } + updateAndWritePackageFile pkg' From 777ffba2dd5b8d391f283afbbefb3153bb57f3b9 Mon Sep 17 00:00:00 2001 From: Matthew Leon Date: Thu, 10 Aug 2017 19:32:35 +0100 Subject: [PATCH 17/22] Verify module --- app/Main.hs | 26 +++------------- psc-package.cabal | 3 +- src/Language/PureScript/Package/Verify.hs | 37 +++++++++++++++++++++++ 3 files changed, 43 insertions(+), 23 deletions(-) create mode 100644 src/Language/PureScript/Package/Verify.hs diff --git a/app/Main.hs b/app/Main.hs index 94f49cb..570b242 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -1,15 +1,14 @@ {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} -{-# LANGUAGE TupleSections #-} module Main where import qualified Control.Foldl as Foldl -import Data.Foldable (fold, for_, traverse_) +import Data.Foldable (fold, traverse_) import qualified Data.Graph as G import qualified Data.Map as Map -import Data.Maybe (fromMaybe, mapMaybe) +import Data.Maybe (mapMaybe) import Data.Text (pack) import qualified Data.Text as T import qualified Data.Text.Read as TR @@ -33,7 +32,8 @@ import Language.PureScript.Package.Install (install) import Language.PureScript.Package.Path (pathToTextUnsafe) import Language.PureScript.Package.Git (listRemoteTags) import Language.PureScript.Package.Uninstall (uninstall) -import Language.PureScript.Package.Update (update, updateImpl, installOrUpdate) +import Language.PureScript.Package.Update (update, updateImpl) +import Language.PureScript.Package.Verify (verifyPackageSet) echoT :: Text -> IO () echoT = Turtle.printf (Turtle.s % "\n") @@ -189,24 +189,6 @@ checkForUpdates applyMinorUpdates applyMajorUpdates = do isMinorReleaseFrom (x : xs) (y : ys) = y == x && ys > xs isMinorReleaseFrom _ _ = False -verifyPackageSet :: IO () -verifyPackageSet = do - pkg <- readPackageFile - db <- readPackageSet pkg - - echoT ("Verifying " <> pack (show (Map.size db)) <> " packages.") - echoT "Warning: this could take some time!" - - let installOrUpdate' (name, pkgInfo) = (name, ) <$> installOrUpdate (set pkg) name pkgInfo - paths <- Map.fromList <$> traverse installOrUpdate' (Map.toList db) - - for_ (Map.toList db) $ \(name, _) -> do - let dirFor pkgName = fromMaybe (error ("verifyPackageSet: no directory for " <> show pkgName)) (Map.lookup pkgName paths) - echoT ("Verifying package " <> runPackageName name) - dependencies <- map fst <$> getTransitiveDeps db [name] - let srcGlobs = map (pathToTextUnsafe . ( ("src" "**" "*.purs")) . dirFor) dependencies - procs "purs" ("compile" : srcGlobs) empty - main :: IO () main = do IO.hSetEncoding IO.stdout IO.utf8 diff --git a/psc-package.cabal b/psc-package.cabal index 6bc2784..42928ac 100644 --- a/psc-package.cabal +++ b/psc-package.cabal @@ -25,7 +25,8 @@ library Language.PureScript.Package.Install, Language.PureScript.Package.Path, Language.PureScript.Package.Uninstall, - Language.PureScript.Package.Update + Language.PureScript.Package.Update, + Language.PureScript.Package.Verify build-depends: base >= 4.7 && < 5, aeson -any, aeson-pretty -any, diff --git a/src/Language/PureScript/Package/Verify.hs b/src/Language/PureScript/Package/Verify.hs new file mode 100644 index 0000000..6cf2014 --- /dev/null +++ b/src/Language/PureScript/Package/Verify.hs @@ -0,0 +1,37 @@ +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE TupleSections #-} + +module Language.PureScript.Package.Verify (verifyPackageSet) where + +import Data.Foldable (for_) +import qualified Data.Map as Map +import Data.Maybe (fromMaybe) +import qualified Data.Text as T +import Turtle +import Prelude hiding (FilePath) + +import Language.PureScript.Package.Types.PackageConfig (readPackageFile, set) +import Language.PureScript.Package.Types.PackageName (runPackageName) +import Language.PureScript.Package.Types.PackageSet (readPackageSet, getTransitiveDeps) +import Language.PureScript.Package.Path (pathToTextUnsafe) +import Language.PureScript.Package.Update (installOrUpdate) + +verifyPackageSet :: IO () +verifyPackageSet = do + pkg <- readPackageFile + db <- readPackageSet pkg + + echo $ + "Verifying " <> unsafeTextToLine (T.pack (show (Map.size db))) <> " packages." + echo "Warning: this could take some time!" + + let installOrUpdate' (name, pkgInfo) = (name, ) <$> installOrUpdate (set pkg) name pkgInfo + paths <- Map.fromList <$> traverse installOrUpdate' (Map.toList db) + + for_ (Map.toList db) $ \(name, _) -> do + let dirFor pkgName = fromMaybe (error ("verifyPackageSet: no directory for " <> show pkgName)) (Map.lookup pkgName paths) + echo $ "Verifying package " <> unsafeTextToLine (runPackageName name) + dependencies <- map fst <$> getTransitiveDeps db [name] + let srcGlobs = map (pathToTextUnsafe . ( ("src" "**" "*.purs")) . dirFor) dependencies + procs "purs" ("compile" : srcGlobs) empty + From 840405e2ef5e0a8d44df98b62e618a0f85eb9e90 Mon Sep 17 00:00:00 2001 From: Matthew Leon Date: Thu, 10 Aug 2017 22:59:32 +0100 Subject: [PATCH 18/22] Paths module --- app/Main.hs | 24 +++--------------- psc-package.cabal | 1 + src/Language/PureScript/Package/Paths.hs | 32 ++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 21 deletions(-) create mode 100644 src/Language/PureScript/Package/Paths.hs diff --git a/app/Main.hs b/app/Main.hs index 570b242..e6ca05c 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -1,6 +1,5 @@ {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} -{-# LANGUAGE RecordWildCards #-} module Main where @@ -23,13 +22,14 @@ import qualified System.Process as Process import Turtle hiding (echo, fold, s, x) import qualified Turtle -import Language.PureScript.Package.Types.PackageConfig (PackageConfig(..), name, depends, set, source, readPackageFile) +import Language.PureScript.Package.Types.PackageConfig (PackageConfig(..), depends, readPackageFile) import Language.PureScript.Package.Types.PackageInfo (PackageInfo(..), repo, version, dependencies) import Language.PureScript.Package.Types.PackageName (PackageName, runPackageName) -import Language.PureScript.Package.Types.PackageSet (PackageSet, readPackageSet, writePackageSet, getTransitiveDeps) +import Language.PureScript.Package.Types.PackageSet (readPackageSet, writePackageSet, getTransitiveDeps) import Language.PureScript.Package.Initialize (initialize) import Language.PureScript.Package.Install (install) import Language.PureScript.Package.Path (pathToTextUnsafe) +import Language.PureScript.Package.Paths (getPaths) import Language.PureScript.Package.Git (listRemoteTags) import Language.PureScript.Package.Uninstall (uninstall) import Language.PureScript.Package.Update (update, updateImpl) @@ -65,24 +65,6 @@ listPackages sorted = do vs = G.topSort (G.transposeG gr) fromNode (pkg, name, _) = (name, pkg) -getSourcePaths :: PackageConfig -> PackageSet -> [PackageName] -> IO [Turtle.FilePath] -getSourcePaths PackageConfig{..} db pkgNames = do - trans <- getTransitiveDeps db pkgNames - let paths = [ ".psc-package" - fromText set - fromText (runPackageName pkgName) - fromText version - "src" "**" "*.purs" - | (pkgName, PackageInfo{ version }) <- trans - ] - return paths - -getPaths :: IO [Turtle.FilePath] -getPaths = do - pkg@PackageConfig{..} <- readPackageFile - db <- readPackageSet pkg - getSourcePaths pkg db depends - listSourcePaths :: IO () listSourcePaths = do paths <- getPaths diff --git a/psc-package.cabal b/psc-package.cabal index 42928ac..3162cdf 100644 --- a/psc-package.cabal +++ b/psc-package.cabal @@ -24,6 +24,7 @@ library Language.PureScript.Package.Initialize, Language.PureScript.Package.Install, Language.PureScript.Package.Path, + Language.PureScript.Package.Paths, Language.PureScript.Package.Uninstall, Language.PureScript.Package.Update, Language.PureScript.Package.Verify diff --git a/src/Language/PureScript/Package/Paths.hs b/src/Language/PureScript/Package/Paths.hs new file mode 100644 index 0000000..c847f7b --- /dev/null +++ b/src/Language/PureScript/Package/Paths.hs @@ -0,0 +1,32 @@ +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE RecordWildCards #-} + +module Language.PureScript.Package.Paths (getPaths) where + +import Turtle +import Prelude hiding (FilePath) + +import Language.PureScript.Package.Types.PackageConfig (PackageConfig(..), readPackageFile) +import Language.PureScript.Package.Types.PackageInfo (PackageInfo(..)) +import Language.PureScript.Package.Types.PackageName (PackageName, runPackageName) +import Language.PureScript.Package.Types.PackageSet (PackageSet, readPackageSet, getTransitiveDeps) + +getPaths :: IO [FilePath] +getPaths = do + pkg@PackageConfig{..} <- readPackageFile + db <- readPackageSet pkg + getSourcePaths pkg db depends + where + getSourcePaths :: PackageConfig -> PackageSet -> [PackageName] -> IO [FilePath] + getSourcePaths PackageConfig{..} db pkgNames = do + trans <- getTransitiveDeps db pkgNames + let paths = [ ".psc-package" + fromText set + fromText (runPackageName pkgName) + fromText version + "src" "**" "*.purs" + | (pkgName, PackageInfo{ version }) <- trans + ] + return paths + From f24b5a0a6972bccf4eb097d0887ecd8ab1ca749c Mon Sep 17 00:00:00 2001 From: Matthew Leon Date: Fri, 11 Aug 2017 12:33:16 +0100 Subject: [PATCH 19/22] create a monad for logging with `echo` This allows library users to silence output to stdout by using `SilentT`, without requiring much change to the codebase. --- psc-package.cabal | 6 ++- src/Language/PureScript/Package/Echo.hs | 40 +++++++++++++++++++ src/Language/PureScript/Package/Git.hs | 5 ++- src/Language/PureScript/Package/Initialize.hs | 9 +++-- .../PureScript/Package/Types/PackageConfig.hs | 10 ++--- .../PureScript/Package/Types/PackageSet.hs | 12 ++++-- src/Language/PureScript/Package/Update.hs | 21 +++++----- src/Language/PureScript/Package/Verify.hs | 11 ++--- 8 files changed, 81 insertions(+), 33 deletions(-) create mode 100644 src/Language/PureScript/Package/Echo.hs diff --git a/psc-package.cabal b/psc-package.cabal index 3162cdf..7b74030 100644 --- a/psc-package.cabal +++ b/psc-package.cabal @@ -20,6 +20,7 @@ library Language.PureScript.Package.Types.PackageInfo, Language.PureScript.Package.Types.PackageName, Language.PureScript.Package.Types.PackageSet, + Language.PureScript.Package.Echo, Language.PureScript.Package.Git, Language.PureScript.Package.Initialize, Language.PureScript.Package.Install, @@ -34,8 +35,9 @@ library async -any, containers, foldl -any, - turtle == 1.3.*, - text + text -any, + transformers -any, + turtle == 1.3.* default-language: Haskell2010 executable psc-package diff --git a/src/Language/PureScript/Package/Echo.hs b/src/Language/PureScript/Package/Echo.hs new file mode 100644 index 0000000..e3d31ae --- /dev/null +++ b/src/Language/PureScript/Package/Echo.hs @@ -0,0 +1,40 @@ +module Language.PureScript.Package.Echo ( + MonadEcho(..) +, SilentT(..) +) where + +import Control.Monad.IO.Class (MonadIO, liftIO) +import Control.Monad.Trans.Class (MonadTrans, lift) +import Data.Text (Text) +import Data.Text.IO (putStrLn) +import Prelude hiding (putStrLn) + +class Applicative m => MonadEcho m where + echo :: Text -> m () +instance MonadEcho IO where + echo = putStrLn + +newtype SilentT m a = SilentT { runSilentT :: m a } + +instance Functor m => Functor (SilentT m) where + fmap f = SilentT . fmap f . runSilentT + {-# INLINE fmap #-} + +instance Applicative m => Applicative (SilentT m) where + pure = SilentT . pure + {-# INLINE pure #-} + f <*> a = SilentT (runSilentT f <*> runSilentT a) + {-# INLINE (<*>) #-} + +instance Monad m => Monad (SilentT m) where + return = SilentT . return + SilentT ma >>= f = SilentT $ ma >>= runSilentT . f + +instance MonadIO m => MonadIO (SilentT m) where + liftIO = lift . liftIO + +instance Applicative m => MonadEcho (SilentT m) where + echo = const . SilentT $ pure () + +instance MonadTrans SilentT where + lift = SilentT diff --git a/src/Language/PureScript/Package/Git.hs b/src/Language/PureScript/Package/Git.hs index 5657430..85fcb4c 100644 --- a/src/Language/PureScript/Package/Git.hs +++ b/src/Language/PureScript/Package/Git.hs @@ -11,13 +11,14 @@ import Prelude hiding (FilePath) import Language.PureScript.Package.Path (pathToTextUnsafe) cloneShallow - :: Text + :: MonadIO m + => Text -- ^ repo -> Text -- ^ branch/tag -> Turtle.FilePath -- ^ target directory - -> IO ExitCode + -> m ExitCode cloneShallow from ref into = proc "git" [ "clone" diff --git a/src/Language/PureScript/Package/Initialize.hs b/src/Language/PureScript/Package/Initialize.hs index 3ea6d8a..eccdbb2 100644 --- a/src/Language/PureScript/Package/Initialize.hs +++ b/src/Language/PureScript/Package/Initialize.hs @@ -10,15 +10,16 @@ import Data.Ord (comparing) import qualified Data.Text as T import Data.Version (Version(..), parseVersion, showVersion) import Text.ParserCombinators.ReadP (readP_to_S) -import Turtle +import Turtle hiding (echo) import Prelude hiding (FilePath) +import Language.PureScript.Package.Echo (MonadEcho(..), echo) import Language.PureScript.Package.Types.PackageConfig (PackageConfig(..), name, depends, set, source, writePackageFile) import Language.PureScript.Package.Types.PackageName (untitledPackageName, mkPackageName, preludePackageName) import Language.PureScript.Package.Path (pathToTextUnsafe) import Language.PureScript.Package.Update (updateImpl) -initialize :: Maybe (Text, Maybe Text) -> IO () +initialize :: (MonadIO m, MonadEcho m) => Maybe (Text, Maybe Text) -> m () initialize setAndSource = do exists <- testfile "psc-package.json" when exists $ die "psc-package.json already exists" @@ -27,8 +28,8 @@ initialize setAndSource = do pkg <- case setAndSource of Nothing -> do pursVersion <- getPureScriptVersion - echo ("Using the default package set for PureScript compiler version " <> - unsafeTextToLine (fromString (showVersion pursVersion))) + echo $ "Using the default package set for PureScript compiler version " <> + fromString (showVersion pursVersion) echo "(Use --source / --set to override this behavior)" pure PackageConfig { name = pkgName , depends = [ preludePackageName ] diff --git a/src/Language/PureScript/Package/Types/PackageConfig.hs b/src/Language/PureScript/Package/Types/PackageConfig.hs index 4c6914a..f43d528 100644 --- a/src/Language/PureScript/Package/Types/PackageConfig.hs +++ b/src/Language/PureScript/Package/Types/PackageConfig.hs @@ -46,16 +46,14 @@ packageConfigToJSON = packageFile :: FilePath packageFile = "psc-package.json" -readPackageFile :: IO PackageConfig +readPackageFile :: MonadIO m => m PackageConfig readPackageFile = do exists <- testfile packageFile unless exists $ die "psc-package.json does not exist. Maybe you need to run psc-package init?" - mpkg <- Aeson.decodeStrict . encodeUtf8 <$> readTextFile packageFile + mpkg <- liftIO $ Aeson.decodeStrict . encodeUtf8 <$> readTextFile packageFile case mpkg of Nothing -> die "Unable to parse psc-package.json" Just pkg -> return pkg -writePackageFile :: PackageConfig -> IO () -writePackageFile = - writeTextFile packageFile - . packageConfigToJSON +writePackageFile :: MonadIO m => PackageConfig -> m () +writePackageFile = liftIO . writeTextFile packageFile . packageConfigToJSON diff --git a/src/Language/PureScript/Package/Types/PackageSet.hs b/src/Language/PureScript/Package/Types/PackageSet.hs index f4eeca9..e7f6943 100644 --- a/src/Language/PureScript/Package/Types/PackageSet.hs +++ b/src/Language/PureScript/Package/Types/PackageSet.hs @@ -37,18 +37,18 @@ packageSetToJSON = where config = AesonEncode.defConfig { AesonEncode.confCompare = compare } -getPackageSet :: PackageConfig -> IO () +getPackageSet :: MonadIO m => PackageConfig -> m () getPackageSet PackageConfig{ source, set } = do let pkgDir = ".psc-package" fromText set ".set" exists <- testdir pkgDir unless exists . void $ cloneShallow source set pkgDir -readPackageSet :: PackageConfig -> IO PackageSet +readPackageSet :: MonadIO m => PackageConfig -> m PackageSet readPackageSet PackageConfig{ set } = do let dbFile = ".psc-package" fromText set ".set" "packages.json" exists <- testfile dbFile unless exists $ die $ format (fp%" does not exist") dbFile - mdb <- Aeson.decodeStrict . encodeUtf8 <$> readTextFile dbFile + mdb <- liftIO $ Aeson.decodeStrict . encodeUtf8 <$> readTextFile dbFile case mdb of Nothing -> die "Unable to parse packages.json" Just db -> return db @@ -58,7 +58,11 @@ writePackageSet PackageConfig{ set } = let dbFile = ".psc-package" fromText set ".set" "packages.json" in writeTextFile dbFile . packageSetToJSON -getTransitiveDeps :: PackageSet -> [PackageName] -> IO [(PackageName, PackageInfo)] +getTransitiveDeps + :: MonadIO m + => PackageSet + -> [PackageName] + -> m [(PackageName, PackageInfo)] getTransitiveDeps db deps = Map.toList . fold <$> traverse (go Set.empty) deps where diff --git a/src/Language/PureScript/Package/Update.hs b/src/Language/PureScript/Package/Update.hs index 183057d..07b7c1c 100644 --- a/src/Language/PureScript/Package/Update.hs +++ b/src/Language/PureScript/Package/Update.hs @@ -10,47 +10,48 @@ module Language.PureScript.Package.Update ( import Control.Concurrent.Async (forConcurrently_) import qualified Data.Text as T -import Turtle +import Turtle hiding (echo) import Prelude hiding (FilePath) +import Language.PureScript.Package.Echo (MonadEcho(..)) +import Language.PureScript.Package.Git (cloneShallow) import Language.PureScript.Package.Types.PackageConfig (PackageConfig(..), readPackageFile, writePackageFile) import Language.PureScript.Package.Types.PackageInfo (PackageInfo(..)) import Language.PureScript.Package.Types.PackageName (PackageName, runPackageName) import Language.PureScript.Package.Types.PackageSet (readPackageSet, getTransitiveDeps) -import Language.PureScript.Package.Git (cloneShallow) -update :: IO () +update :: (MonadIO m, MonadEcho m) => m () update = do pkg <- readPackageFile updateImpl pkg echo "Update complete" -updateImpl :: PackageConfig -> IO () +updateImpl :: (MonadIO m, MonadEcho m) => PackageConfig -> m () updateImpl config@PackageConfig{ depends } = do getPackageSet config db <- readPackageSet config trans <- getTransitiveDeps db depends - echo ("Updating " <> unsafeTextToLine (T.pack (show (length trans))) <> " packages...") - forConcurrently_ trans . uncurry $ installOrUpdate (set config) + echo $ "Updating " <> T.pack (show (length trans)) <> " packages..." + liftIO . forConcurrently_ trans . uncurry $ installOrUpdate (set config) where - getPackageSet :: PackageConfig -> IO () + getPackageSet :: MonadIO m => PackageConfig -> m () getPackageSet PackageConfig{ source, set } = do let pkgDir = ".psc-package" fromText set ".set" exists <- testdir pkgDir unless exists . void $ cloneShallow source set pkgDir -updateAndWritePackageFile :: PackageConfig -> IO () +updateAndWritePackageFile :: (MonadIO m, MonadEcho m) => PackageConfig -> m () updateAndWritePackageFile pkg = do updateImpl pkg writePackageFile pkg echo "psc-package.json file was updated" -installOrUpdate :: Text -> PackageName -> PackageInfo -> IO FilePath +installOrUpdate :: (MonadIO m, MonadEcho m) => Text -> PackageName -> PackageInfo -> m FilePath installOrUpdate set pkgName PackageInfo{ repo, version } = do let pkgDir = ".psc-package" fromText set fromText (runPackageName pkgName) fromText version exists <- testdir pkgDir unless exists . void $ do - echo $ "Updating " <> unsafeTextToLine (runPackageName pkgName) + echo $ "Updating " <> runPackageName pkgName cloneShallow repo version pkgDir pure pkgDir diff --git a/src/Language/PureScript/Package/Verify.hs b/src/Language/PureScript/Package/Verify.hs index 6cf2014..916926a 100644 --- a/src/Language/PureScript/Package/Verify.hs +++ b/src/Language/PureScript/Package/Verify.hs @@ -7,22 +7,23 @@ import Data.Foldable (for_) import qualified Data.Map as Map import Data.Maybe (fromMaybe) import qualified Data.Text as T -import Turtle +import Turtle hiding (echo) import Prelude hiding (FilePath) +import Language.PureScript.Package.Echo (MonadEcho(..)) +import Language.PureScript.Package.Path (pathToTextUnsafe) import Language.PureScript.Package.Types.PackageConfig (readPackageFile, set) import Language.PureScript.Package.Types.PackageName (runPackageName) import Language.PureScript.Package.Types.PackageSet (readPackageSet, getTransitiveDeps) -import Language.PureScript.Package.Path (pathToTextUnsafe) import Language.PureScript.Package.Update (installOrUpdate) -verifyPackageSet :: IO () +verifyPackageSet :: (MonadIO m, MonadEcho m) => m () verifyPackageSet = do pkg <- readPackageFile db <- readPackageSet pkg echo $ - "Verifying " <> unsafeTextToLine (T.pack (show (Map.size db))) <> " packages." + "Verifying " <> T.pack (show (Map.size db)) <> " packages." echo "Warning: this could take some time!" let installOrUpdate' (name, pkgInfo) = (name, ) <$> installOrUpdate (set pkg) name pkgInfo @@ -30,7 +31,7 @@ verifyPackageSet = do for_ (Map.toList db) $ \(name, _) -> do let dirFor pkgName = fromMaybe (error ("verifyPackageSet: no directory for " <> show pkgName)) (Map.lookup pkgName paths) - echo $ "Verifying package " <> unsafeTextToLine (runPackageName name) + echo $ "Verifying package " <> runPackageName name dependencies <- map fst <$> getTransitiveDeps db [name] let srcGlobs = map (pathToTextUnsafe . ( ("src" "**" "*.purs")) . dirFor) dependencies procs "purs" ("compile" : srcGlobs) empty From 74d0267197084cf85271eb8dc17efc84cd6e19de Mon Sep 17 00:00:00 2001 From: Matthew Leon Date: Fri, 11 Aug 2017 16:06:17 +0100 Subject: [PATCH 20/22] further conversions to MonadIO/Echo Also changes some functions parameters from String to Text. --- app/Main.hs | 4 ++-- src/Language/PureScript/Package/Install.hs | 13 ++++++++----- src/Language/PureScript/Package/Paths.hs | 4 ++-- .../PureScript/Package/Types/PackageName.hs | 1 + src/Language/PureScript/Package/Uninstall.hs | 10 +++++++--- 5 files changed, 20 insertions(+), 12 deletions(-) diff --git a/app/Main.hs b/app/Main.hs index e6ca05c..6f9df3c 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -203,10 +203,10 @@ main = do (Opts.info (pure update) (Opts.progDesc "Update dependencies")) , Opts.command "uninstall" - (Opts.info (uninstall <$> pkg Opts.<**> Opts.helper) + (Opts.info (uninstall . T.pack <$> pkg Opts.<**> Opts.helper) (Opts.progDesc "Uninstall the named package")) , Opts.command "install" - (Opts.info (install <$> pkg Opts.<**> Opts.helper) + (Opts.info (install . T.pack <$> pkg Opts.<**> Opts.helper) (Opts.progDesc "Install the named package")) , Opts.command "build" (Opts.info (exec ["purs", "compile"] diff --git a/src/Language/PureScript/Package/Install.hs b/src/Language/PureScript/Package/Install.hs index c123e2b..56cd4d0 100644 --- a/src/Language/PureScript/Package/Install.hs +++ b/src/Language/PureScript/Package/Install.hs @@ -3,16 +3,19 @@ module Language.PureScript.Package.Install (install) where -import Data.List (nub) -import Prelude hiding (FilePath) +import Control.Monad.IO.Class (MonadIO) +import Data.List (nub) +import Data.Text (Text) +import Prelude hiding (FilePath) +import Language.PureScript.Package.Echo (MonadEcho(..)) import Language.PureScript.Package.Types.PackageConfig (readPackageFile, depends) -import Language.PureScript.Package.Types.PackageName (packageNameFromString) +import Language.PureScript.Package.Types.PackageName (fromText) import Language.PureScript.Package.Update (updateAndWritePackageFile) -install :: String -> IO () +install :: (MonadIO m, MonadEcho m) => Text -> m () install pkgName' = do pkg <- readPackageFile - pkgName <- packageNameFromString pkgName' + pkgName <- fromText pkgName' let pkg' = pkg { depends = nub (pkgName : depends pkg) } -- TODO: ordnub updateAndWritePackageFile pkg' diff --git a/src/Language/PureScript/Package/Paths.hs b/src/Language/PureScript/Package/Paths.hs index c847f7b..692f3a3 100644 --- a/src/Language/PureScript/Package/Paths.hs +++ b/src/Language/PureScript/Package/Paths.hs @@ -12,13 +12,13 @@ import Language.PureScript.Package.Types.PackageInfo (PackageInfo(..)) import Language.PureScript.Package.Types.PackageName (PackageName, runPackageName) import Language.PureScript.Package.Types.PackageSet (PackageSet, readPackageSet, getTransitiveDeps) -getPaths :: IO [FilePath] +getPaths :: MonadIO m => m [FilePath] getPaths = do pkg@PackageConfig{..} <- readPackageFile db <- readPackageSet pkg getSourcePaths pkg db depends where - getSourcePaths :: PackageConfig -> PackageSet -> [PackageName] -> IO [FilePath] + getSourcePaths :: MonadIO m => PackageConfig -> PackageSet -> [PackageName] -> m [FilePath] getSourcePaths PackageConfig{..} db pkgNames = do trans <- getTransitiveDeps db pkgNames let paths = [ ".psc-package" diff --git a/src/Language/PureScript/Package/Types/PackageName.hs b/src/Language/PureScript/Package/Types/PackageName.hs index 30de9c0..14b450d 100644 --- a/src/Language/PureScript/Package/Types/PackageName.hs +++ b/src/Language/PureScript/Package/Types/PackageName.hs @@ -3,6 +3,7 @@ module Language.PureScript.Package.Types.PackageName ( PackageName , mkPackageName + , fromText , runPackageName , packageNameFromString , preludePackageName diff --git a/src/Language/PureScript/Package/Uninstall.hs b/src/Language/PureScript/Package/Uninstall.hs index 9852c1f..f55af66 100644 --- a/src/Language/PureScript/Package/Uninstall.hs +++ b/src/Language/PureScript/Package/Uninstall.hs @@ -1,12 +1,16 @@ module Language.PureScript.Package.Uninstall (uninstall) where +import Control.Monad.IO.Class (MonadIO) +import Data.Text (Text) + +import Language.PureScript.Package.Echo (MonadEcho(..)) import Language.PureScript.Package.Types.PackageConfig (readPackageFile, depends) -import Language.PureScript.Package.Types.PackageName (packageNameFromString) +import Language.PureScript.Package.Types.PackageName (fromText) import Language.PureScript.Package.Update (updateAndWritePackageFile) -uninstall :: String -> IO () +uninstall :: (MonadIO m, MonadEcho m) => Text -> m () uninstall pkgName' = do pkg <- readPackageFile - pkgName <- packageNameFromString pkgName' + pkgName <- fromText pkgName' let pkg' = pkg { depends = filter (/= pkgName) $ depends pkg } updateAndWritePackageFile pkg' From 188e2b8e5af875ecdf2f78fa5fec8ee8453f800e Mon Sep 17 00:00:00 2001 From: Matthew Leon Date: Fri, 11 Aug 2017 16:39:38 +0100 Subject: [PATCH 21/22] add documentation --- src/Language/PureScript/Package/Echo.hs | 7 ++++++- src/Language/PureScript/Package/Git.hs | 2 ++ src/Language/PureScript/Package/Initialize.hs | 2 ++ src/Language/PureScript/Package/Install.hs | 2 ++ src/Language/PureScript/Package/Path.hs | 2 ++ src/Language/PureScript/Package/Paths.hs | 2 ++ src/Language/PureScript/Package/Uninstall.hs | 2 ++ src/Language/PureScript/Package/Update.hs | 2 ++ src/Language/PureScript/Package/Verify.hs | 4 +++- 9 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/Language/PureScript/Package/Echo.hs b/src/Language/PureScript/Package/Echo.hs index e3d31ae..d32718c 100644 --- a/src/Language/PureScript/Package/Echo.hs +++ b/src/Language/PureScript/Package/Echo.hs @@ -1,3 +1,7 @@ +-- | Tools for optionally `echo`ing 'Text' to stdout. +-- +-- Use 'runSilentT' to silence 'echo'ed output in any 'MonadEcho'. + module Language.PureScript.Package.Echo ( MonadEcho(..) , SilentT(..) @@ -14,7 +18,8 @@ class Applicative m => MonadEcho m where instance MonadEcho IO where echo = putStrLn -newtype SilentT m a = SilentT { runSilentT :: m a } +-- | A `MonadEcho` that silences `echo`. +newtype SilentT m a = SilentT {runSilentT :: m a } instance Functor m => Functor (SilentT m) where fmap f = SilentT . fmap f . runSilentT diff --git a/src/Language/PureScript/Package/Git.hs b/src/Language/PureScript/Package/Git.hs index 85fcb4c..1e22acb 100644 --- a/src/Language/PureScript/Package/Git.hs +++ b/src/Language/PureScript/Package/Git.hs @@ -1,5 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} +-- | Functions for executing git. + module Language.PureScript.Package.Git ( cloneShallow , listRemoteTags diff --git a/src/Language/PureScript/Package/Initialize.hs b/src/Language/PureScript/Package/Initialize.hs index eccdbb2..046c6f0 100644 --- a/src/Language/PureScript/Package/Initialize.hs +++ b/src/Language/PureScript/Package/Initialize.hs @@ -1,6 +1,8 @@ {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} +-- | Initialize a new package, generating its psc-package.json file. + module Language.PureScript.Package.Initialize (initialize) where import qualified Control.Foldl as Foldl diff --git a/src/Language/PureScript/Package/Install.hs b/src/Language/PureScript/Package/Install.hs index 56cd4d0..676306c 100644 --- a/src/Language/PureScript/Package/Install.hs +++ b/src/Language/PureScript/Package/Install.hs @@ -1,6 +1,8 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE NamedFieldPuns #-} +-- | Install a new package and update the package file. + module Language.PureScript.Package.Install (install) where import Control.Monad.IO.Class (MonadIO) diff --git a/src/Language/PureScript/Package/Path.hs b/src/Language/PureScript/Package/Path.hs index 8f7e4d3..4027f84 100644 --- a/src/Language/PureScript/Package/Path.hs +++ b/src/Language/PureScript/Package/Path.hs @@ -1,3 +1,5 @@ +-- | Convert 'FilePath's to 'Text' + module Language.PureScript.Package.Path (pathToTextUnsafe) where import Turtle (FilePath, Text, toText) diff --git a/src/Language/PureScript/Package/Paths.hs b/src/Language/PureScript/Package/Paths.hs index 692f3a3..47f82ce 100644 --- a/src/Language/PureScript/Package/Paths.hs +++ b/src/Language/PureScript/Package/Paths.hs @@ -2,6 +2,8 @@ {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE RecordWildCards #-} +-- | Get the source paths for a package. + module Language.PureScript.Package.Paths (getPaths) where import Turtle diff --git a/src/Language/PureScript/Package/Uninstall.hs b/src/Language/PureScript/Package/Uninstall.hs index f55af66..ccfd36f 100644 --- a/src/Language/PureScript/Package/Uninstall.hs +++ b/src/Language/PureScript/Package/Uninstall.hs @@ -1,5 +1,7 @@ module Language.PureScript.Package.Uninstall (uninstall) where +-- | Remove a package from the package file. + import Control.Monad.IO.Class (MonadIO) import Data.Text (Text) diff --git a/src/Language/PureScript/Package/Update.hs b/src/Language/PureScript/Package/Update.hs index 07b7c1c..f9463ce 100644 --- a/src/Language/PureScript/Package/Update.hs +++ b/src/Language/PureScript/Package/Update.hs @@ -1,6 +1,8 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE NamedFieldPuns #-} +-- | Update (obtain) dependencies/packages. + module Language.PureScript.Package.Update ( update , updateImpl diff --git a/src/Language/PureScript/Package/Verify.hs b/src/Language/PureScript/Package/Verify.hs index 916926a..a9ac926 100644 --- a/src/Language/PureScript/Package/Verify.hs +++ b/src/Language/PureScript/Package/Verify.hs @@ -1,6 +1,8 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TupleSections #-} +-- | Check that a package set can compile. + module Language.PureScript.Package.Verify (verifyPackageSet) where import Data.Foldable (for_) @@ -30,7 +32,7 @@ verifyPackageSet = do paths <- Map.fromList <$> traverse installOrUpdate' (Map.toList db) for_ (Map.toList db) $ \(name, _) -> do - let dirFor pkgName = fromMaybe (error ("verifyPackageSet: no directory for " <> show pkgName)) (Map.lookup pkgName paths) + let dirFor pkgName = fromMaybe (error $ "verifyPackageSet: no directory for " <> show pkgName) (Map.lookup pkgName paths) echo $ "Verifying package " <> runPackageName name dependencies <- map fst <$> getTransitiveDeps db [name] let srcGlobs = map (pathToTextUnsafe . ( ("src" "**" "*.purs")) . dirFor) dependencies From f2460c67c77a6d236c2408470ed3047e48d6e3ed Mon Sep 17 00:00:00 2001 From: Matthew Leon Date: Fri, 11 Aug 2017 16:46:28 +0100 Subject: [PATCH 22/22] update package version --- psc-package.cabal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/psc-package.cabal b/psc-package.cabal index 7b74030..ceac3a5 100644 --- a/psc-package.cabal +++ b/psc-package.cabal @@ -1,5 +1,5 @@ name: psc-package -version: 0.2.0 +version: 0.3.0 synopsis: An experimental package manager for PureScript description: homepage: https://github.com/purescript/psc-package