Skip to content

Commit 4f9c1ee

Browse files
authored
implement add-from-bower (#77)
1 parent 043bed0 commit 4f9c1ee

File tree

1 file changed

+62
-3
lines changed

1 file changed

+62
-3
lines changed

app/Main.hs

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,17 @@
55
{-# LANGUAGE RecordWildCards #-}
66
{-# LANGUAGE TupleSections #-}
77
{-# LANGUAGE DeriveTraversable #-}
8+
{-# LANGUAGE ScopedTypeVariables #-}
89

910
module Main where
1011

1112
import qualified Control.Foldl as Foldl
1213
import Control.Concurrent.Async (forConcurrently_)
1314
import qualified Data.Aeson as Aeson
15+
import Data.Aeson.Types (fieldLabelModifier)
1416
import Data.Aeson.Encode.Pretty
1517
import Data.Foldable (fold, foldMap, traverse_)
18+
import qualified Data.Bifunctor as Bifunctor
1619
import qualified Data.Graph as G
1720
import Data.List (maximumBy, nub)
1821
import qualified Data.List as List
@@ -36,7 +39,7 @@ import System.Environment (getArgs)
3639
import qualified System.IO as IO
3740
import qualified System.Process as Process
3841
import qualified Text.ParserCombinators.ReadP as Read
39-
import Turtle hiding (arg, echo, fold, prefix, s, x)
42+
import Turtle hiding (arg, fold, s, x)
4043
import qualified Turtle
4144
import Types (PackageName, mkPackageName, runPackageName, untitledPackageName, preludePackageName)
4245

@@ -60,6 +63,9 @@ data PackageConfig = PackageConfig
6063
pathToTextUnsafe :: Turtle.FilePath -> Text
6164
pathToTextUnsafe = either (error "Path.toText failed") id . Path.toText
6265

66+
shellToIOText :: Turtle.Shell Line -> IO [Text]
67+
shellToIOText shellLines = Turtle.fold (fmap lineToText shellLines) Foldl.list
68+
6369
readPackageFile :: IO PackageConfig
6470
readPackageFile = do
6571
exists <- testfile packageFile
@@ -82,6 +88,7 @@ packageConfigToJSON =
8288
, "source"
8389
, "depends"
8490
]
91+
, confIndent = Spaces 2
8592
}
8693

8794
packageSetToJSON :: PackageSet -> Text
@@ -90,7 +97,7 @@ packageSetToJSON =
9097
. TB.toLazyText
9198
. encodePrettyToTextBuilder' config
9299
where
93-
config = defConfig { confCompare = compare }
100+
config = defConfig { confCompare = compare, confIndent = Spaces 2 }
94101

95102
writePackageFile :: PackageConfig -> IO ()
96103
writePackageFile =
@@ -203,7 +210,7 @@ installImpl config@PackageConfig{ depends } = do
203210
getPureScriptVersion :: IO Version
204211
getPureScriptVersion = do
205212
let pursProc = inproc "purs" [ "--version" ] empty
206-
outputLines <- Turtle.fold (fmap lineToText pursProc) Foldl.list
213+
outputLines <- shellToIOText pursProc
207214
case outputLines of
208215
[onlyLine]
209216
| results@(_ : _) <- Read.readP_to_S parseVersion (T.unpack onlyLine) ->
@@ -462,6 +469,55 @@ verify arg = do
462469
let srcGlobs = map (pathToTextUnsafe . (</> ("src" </> "**" </> "*.purs")) . dirFor) dependencies
463470
procs "purs" ("compile" : srcGlobs) empty
464471

472+
data BowerInfoRepo = BowerInfoRepo
473+
{ url :: Text
474+
} deriving (Show, Eq, Generic, Aeson.FromJSON)
475+
476+
data BowerInfo = BowerInfo
477+
{ bower_name :: Text
478+
, bower_repository :: BowerInfoRepo
479+
, bower_dependencies :: Map.Map Text Text
480+
, bower_version :: Text
481+
} deriving (Show, Eq, Generic)
482+
instance Aeson.FromJSON BowerInfo where
483+
parseJSON = Aeson.genericParseJSON Aeson.defaultOptions
484+
{ fieldLabelModifier = drop 6
485+
}
486+
487+
data BowerOutput = BowerOutput
488+
{ latest :: BowerInfo
489+
} deriving (Show, Eq, Generic, Aeson.FromJSON)
490+
491+
addFromBower :: String -> IO ()
492+
addFromBower name = do
493+
let bowerProc = inproc "bower" [ "info", T.pack name, "--json", "-l=error" ] empty
494+
result <- fold <$> shellToIOText bowerProc
495+
if T.null result
496+
then exitWithErr "Error: Does the package exist on Bower?"
497+
else do
498+
let result' = do
499+
bowerOutput <- Aeson.eitherDecodeStrict $ encodeUtf8 result
500+
let bowerInfo = latest bowerOutput
501+
pkgName <- mkPackageName' $ bower_name bowerInfo
502+
packageNames <- traverse mkPackageName' $ Map.keys (bower_dependencies bowerInfo)
503+
pure $
504+
( pkgName
505+
, PackageInfo
506+
(url $ bower_repository bowerInfo)
507+
("v" <> bower_version bowerInfo)
508+
packageNames
509+
)
510+
case result' of
511+
Right (pkgName, info) -> do
512+
pkg <- readPackageFile
513+
db <- readPackageSet pkg
514+
writePackageSet pkg $ Map.insert pkgName info db
515+
echoT $ "Successfully wrote " <> runPackageName pkgName <> " to package set."
516+
Left errors -> echoT $ "Errors processing Bower Info: " <> (T.pack errors)
517+
where
518+
stripBowerNamePrefix s = fromMaybe s $ T.stripPrefix "purescript-" s
519+
mkPackageName' = Bifunctor.first show . mkPackageName . stripBowerNamePrefix
520+
465521
main :: IO ()
466522
main = do
467523
IO.hSetEncoding IO.stdout IO.utf8
@@ -526,6 +582,9 @@ main = do
526582
<|> (VerifyAll <$> optional (fromString <$> after)))
527583
Opts.<**> Opts.helper)
528584
(Opts.progDesc "Verify that the named package builds correctly. If no package is specified, verify that all packages in the package set build correctly."))
585+
, Opts.command "add-from-bower"
586+
(Opts.info (addFromBower <$> pkg Opts.<**> Opts.helper)
587+
(Opts.progDesc "Add a package from the Bower registry to the package set. This requires Bower to be installed on your system."))
529588
]
530589
where
531590
pkg = Opts.strArgument $

0 commit comments

Comments
 (0)