mirror of
https://github.com/commercialhaskell/stackage-server.git
synced 2026-01-25 10:21:55 +01:00
commit
cafa6b0496
@ -74,6 +74,7 @@ import Handler.BuildVersion
|
|||||||
import Handler.PackageCounts
|
import Handler.PackageCounts
|
||||||
import Handler.Sitemap
|
import Handler.Sitemap
|
||||||
import Handler.BuildPlan
|
import Handler.BuildPlan
|
||||||
|
import Handler.Download
|
||||||
|
|
||||||
-- This line actually creates our YesodDispatch instance. It is the second half
|
-- This line actually creates our YesodDispatch instance. It is the second half
|
||||||
-- of the call to mkYesodData which occurs in Foundation.hs. Please see the
|
-- of the call to mkYesodData which occurs in Foundation.hs. Please see the
|
||||||
|
|||||||
41
Data/GhcLinks.hs
Normal file
41
Data/GhcLinks.hs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
module Data.GhcLinks
|
||||||
|
( GhcLinks(..)
|
||||||
|
, readGhcLinks
|
||||||
|
) where
|
||||||
|
|
||||||
|
import ClassyPrelude.Yesod
|
||||||
|
import Control.Monad.State.Strict (modify, execStateT)
|
||||||
|
import qualified Data.HashMap.Strict as HashMap
|
||||||
|
import Filesystem (readTextFile, isFile)
|
||||||
|
|
||||||
|
import Types
|
||||||
|
|
||||||
|
|
||||||
|
newtype GhcLinks = GhcLinks
|
||||||
|
{ ghcLinksMap :: HashMap (SupportedArch, GhcMajorVersion) Text }
|
||||||
|
-- ^ a map from (arch, ver) to yaml
|
||||||
|
|
||||||
|
supportedArches :: [SupportedArch]
|
||||||
|
supportedArches = [minBound .. maxBound]
|
||||||
|
|
||||||
|
supportedGhcMajorVersions :: [GhcMajorVersion]
|
||||||
|
supportedGhcMajorVersions = ["7.8"]
|
||||||
|
|
||||||
|
|
||||||
|
readGhcLinks :: FilePath -> IO GhcLinks
|
||||||
|
readGhcLinks dir = do
|
||||||
|
let opts =
|
||||||
|
[ (arch, ver)
|
||||||
|
| arch <- supportedArches
|
||||||
|
, ver <- supportedGhcMajorVersions
|
||||||
|
]
|
||||||
|
hashMap <- flip execStateT HashMap.empty
|
||||||
|
$ forM_ opts $ \(arch, ver) -> do
|
||||||
|
let fileName = "ghc-" <> ver <> "-links.yaml"
|
||||||
|
let path = dir
|
||||||
|
</> fpFromText (toPathPiece arch)
|
||||||
|
</> fpFromText fileName
|
||||||
|
whenM (liftIO $ isFile path) $ do
|
||||||
|
text <- liftIO $ readTextFile path
|
||||||
|
modify (HashMap.insert (arch, ver) text)
|
||||||
|
return $ GhcLinks hashMap
|
||||||
@ -5,12 +5,14 @@ module Data.WebsiteContent
|
|||||||
|
|
||||||
import ClassyPrelude.Yesod
|
import ClassyPrelude.Yesod
|
||||||
import Text.Markdown (markdown, msXssProtect, msAddHeadingId)
|
import Text.Markdown (markdown, msXssProtect, msAddHeadingId)
|
||||||
|
import Data.GhcLinks
|
||||||
|
|
||||||
data WebsiteContent = WebsiteContent
|
data WebsiteContent = WebsiteContent
|
||||||
{ wcHomepage :: !Html
|
{ wcHomepage :: !Html
|
||||||
, wcAuthors :: !Html
|
, wcAuthors :: !Html
|
||||||
, wcInstall :: !Html
|
, wcInstall :: !Html
|
||||||
, wcOlderReleases :: !Html
|
, wcOlderReleases :: !Html
|
||||||
|
, wcGhcLinks :: !GhcLinks
|
||||||
}
|
}
|
||||||
|
|
||||||
loadWebsiteContent :: FilePath -> IO WebsiteContent
|
loadWebsiteContent :: FilePath -> IO WebsiteContent
|
||||||
@ -20,6 +22,7 @@ loadWebsiteContent dir = do
|
|||||||
wcInstall <- readMarkdown "install.md"
|
wcInstall <- readMarkdown "install.md"
|
||||||
wcOlderReleases <- readHtml "older-releases.html" `catchIO`
|
wcOlderReleases <- readHtml "older-releases.html" `catchIO`
|
||||||
\_ -> readMarkdown "older-releases.md"
|
\_ -> readMarkdown "older-releases.md"
|
||||||
|
wcGhcLinks <- readGhcLinks $ dir </> "stackage-cli"
|
||||||
return WebsiteContent {..}
|
return WebsiteContent {..}
|
||||||
where
|
where
|
||||||
readHtml fp = fmap (preEscapedToMarkup . decodeUtf8 :: ByteString -> Html)
|
readHtml fp = fmap (preEscapedToMarkup . decodeUtf8 :: ByteString -> Html)
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import Handler.StackageIndex (getStackageIndexR)
|
|||||||
import Handler.StackageSdist (getStackageSdistR)
|
import Handler.StackageSdist (getStackageSdistR)
|
||||||
import Handler.Hoogle (getHoogleR, getHoogleDatabaseR)
|
import Handler.Hoogle (getHoogleR, getHoogleDatabaseR)
|
||||||
import Handler.BuildPlan (getBuildPlanR)
|
import Handler.BuildPlan (getBuildPlanR)
|
||||||
|
import Handler.Download (getGhcMajorVersionR)
|
||||||
|
|
||||||
handleAliasR :: Slug -> Slug -> [Text] -> Handler ()
|
handleAliasR :: Slug -> Slug -> [Text] -> Handler ()
|
||||||
handleAliasR user name pieces = do
|
handleAliasR user name pieces = do
|
||||||
@ -81,4 +82,5 @@ goSid sid pieces = do
|
|||||||
HoogleR -> getHoogleR slug >>= sendResponse
|
HoogleR -> getHoogleR slug >>= sendResponse
|
||||||
HoogleDatabaseR -> getHoogleDatabaseR slug >>= sendResponse
|
HoogleDatabaseR -> getHoogleDatabaseR slug >>= sendResponse
|
||||||
BuildPlanR -> getBuildPlanR slug >>= sendResponse
|
BuildPlanR -> getBuildPlanR slug >>= sendResponse
|
||||||
|
GhcMajorVersionR -> getGhcMajorVersionR slug >>= sendResponse
|
||||||
_ -> notFound
|
_ -> notFound
|
||||||
|
|||||||
79
Handler/Download.hs
Normal file
79
Handler/Download.hs
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
module Handler.Download
|
||||||
|
( getDownloadR
|
||||||
|
, getDownloadLtsSnapshotsJsonR
|
||||||
|
, getGhcMajorVersionR
|
||||||
|
, getDownloadGhcLinksR
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Import
|
||||||
|
import Data.Slug (SnapSlug)
|
||||||
|
import Data.GhcLinks
|
||||||
|
import Yesod.GitRepo (grContent)
|
||||||
|
|
||||||
|
executableFor :: SupportedArch -> StackageExecutable
|
||||||
|
executableFor Win32 = StackageWindowsExecutable
|
||||||
|
executableFor Win64 = StackageWindowsExecutable
|
||||||
|
executableFor _ = StackageUnixExecutable
|
||||||
|
|
||||||
|
-- TODO: link to s3
|
||||||
|
executableLink :: SupportedArch -> StackageExecutable -> Text
|
||||||
|
executableLink arch exe =
|
||||||
|
"https://s3.amazonaws.com/download.fpcomplete.com/stackage-cli/"
|
||||||
|
<> toPathPiece arch <> "/" <> toPathPiece exe
|
||||||
|
|
||||||
|
downloadCandidates :: [(SupportedArch, StackageExecutable)]
|
||||||
|
downloadCandidates =
|
||||||
|
map (\arch -> (arch, executableFor arch))
|
||||||
|
[minBound .. maxBound]
|
||||||
|
|
||||||
|
currentlySupported :: SupportedArch -> Bool
|
||||||
|
currentlySupported Linux64 = True
|
||||||
|
currentlySupported _ = False
|
||||||
|
|
||||||
|
getDownloadR :: Handler Html
|
||||||
|
getDownloadR = defaultLayout $ do
|
||||||
|
$(widgetFile "download")
|
||||||
|
|
||||||
|
ltsMajorVersions :: Handler [Lts]
|
||||||
|
ltsMajorVersions = liftM (map entityVal) $ runDB $ do
|
||||||
|
mapWhileIsJustM [0..] $ \x -> do
|
||||||
|
selectFirst [LtsMajor ==. x] [Desc LtsMinor]
|
||||||
|
|
||||||
|
mapWhileIsJustM :: Monad m => [a] -> (a -> m (Maybe b)) -> m [b]
|
||||||
|
mapWhileIsJustM [] _f = return []
|
||||||
|
mapWhileIsJustM (x:xs) f = f x >>= \case
|
||||||
|
Nothing -> return []
|
||||||
|
Just y -> (y:) `liftM` mapWhileIsJustM xs f
|
||||||
|
|
||||||
|
getDownloadLtsSnapshotsJsonR :: Handler Value
|
||||||
|
getDownloadLtsSnapshotsJsonR = liftM reverse ltsMajorVersions >>= \case
|
||||||
|
[] -> return $ object []
|
||||||
|
majorVersions@(latest:_) -> return $ object
|
||||||
|
$ ["lts" .= printLts latest]
|
||||||
|
++ map toObj majorVersions
|
||||||
|
where
|
||||||
|
toObj lts@(Lts major _ _) =
|
||||||
|
pack ("lts-" ++ show major) .= printLts lts
|
||||||
|
printLts (Lts major minor _) =
|
||||||
|
"lts-" ++ show major ++ "." ++ show minor
|
||||||
|
|
||||||
|
-- TODO: add this to db
|
||||||
|
ltsGhcMajorVersion :: Stackage -> Text
|
||||||
|
ltsGhcMajorVersion _ = "7.8"
|
||||||
|
|
||||||
|
getGhcMajorVersionR :: SnapSlug -> Handler Text
|
||||||
|
getGhcMajorVersionR slug = do
|
||||||
|
snapshot <- runDB $ getBy404 $ UniqueSnapshot slug
|
||||||
|
return $ ltsGhcMajorVersion $ entityVal snapshot
|
||||||
|
|
||||||
|
getDownloadGhcLinksR :: SupportedArch -> Text -> Handler TypedContent
|
||||||
|
getDownloadGhcLinksR arch fileName = do
|
||||||
|
ver <- maybe notFound return
|
||||||
|
$ stripPrefix "ghc-" >=> stripSuffix "-links.yaml"
|
||||||
|
$ fileName
|
||||||
|
ghcLinks <- getYesod >>= fmap wcGhcLinks . liftIO . grContent . websiteContent
|
||||||
|
case lookup (arch, ver) (ghcLinksMap ghcLinks) of
|
||||||
|
Just text -> return $ TypedContent yamlMimeType $ toContent text
|
||||||
|
Nothing -> notFound
|
||||||
|
where
|
||||||
|
yamlMimeType = "text/yaml"
|
||||||
@ -13,6 +13,8 @@ getSitemapR = sitemap $ do
|
|||||||
priority 1.0 $ HomeR
|
priority 1.0 $ HomeR
|
||||||
|
|
||||||
priority 0.9 $ LtsR []
|
priority 0.9 $ LtsR []
|
||||||
|
-- TODO: uncomment when this is presentable
|
||||||
|
--priority 0.9 $ DownloadR
|
||||||
priority 0.8 $ NightlyR []
|
priority 0.8 $ NightlyR []
|
||||||
|
|
||||||
priority 0.7 $ AllSnapshotsR
|
priority 0.7 $ AllSnapshotsR
|
||||||
|
|||||||
45
Types.hs
45
Types.hs
@ -2,6 +2,7 @@ module Types where
|
|||||||
|
|
||||||
import ClassyPrelude.Yesod
|
import ClassyPrelude.Yesod
|
||||||
import Data.BlobStore (ToPath (..), BackupToS3 (..))
|
import Data.BlobStore (ToPath (..), BackupToS3 (..))
|
||||||
|
import Data.Hashable (hashUsing)
|
||||||
import Text.Blaze (ToMarkup)
|
import Text.Blaze (ToMarkup)
|
||||||
import Database.Persist.Sql (PersistFieldSql (sqlType))
|
import Database.Persist.Sql (PersistFieldSql (sqlType))
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
@ -102,3 +103,47 @@ instance HasHackageRoot HackageRoot where
|
|||||||
data UnpackStatus = USReady
|
data UnpackStatus = USReady
|
||||||
| USBusy
|
| USBusy
|
||||||
| USFailed !Text
|
| USFailed !Text
|
||||||
|
|
||||||
|
data StackageExecutable
|
||||||
|
= StackageWindowsExecutable
|
||||||
|
| StackageUnixExecutable
|
||||||
|
deriving (Show, Read, Eq)
|
||||||
|
|
||||||
|
instance PathPiece StackageExecutable where
|
||||||
|
-- TODO: distribute stackage, not just stackage-setup
|
||||||
|
toPathPiece StackageWindowsExecutable = "stackage-setup.exe"
|
||||||
|
toPathPiece StackageUnixExecutable = "stackage-setup"
|
||||||
|
|
||||||
|
fromPathPiece "stackage-setup" = Just StackageUnixExecutable
|
||||||
|
fromPathPiece "stackage-setup.exe" = Just StackageWindowsExecutable
|
||||||
|
fromPathPiece _ = Nothing
|
||||||
|
|
||||||
|
type GhcMajorVersion = Text
|
||||||
|
|
||||||
|
data SupportedArch
|
||||||
|
= Win32
|
||||||
|
| Win64
|
||||||
|
| Linux32
|
||||||
|
| Linux64
|
||||||
|
| Mac32
|
||||||
|
| Mac64
|
||||||
|
deriving (Enum, Bounded, Show, Read, Eq)
|
||||||
|
|
||||||
|
instance Hashable SupportedArch where
|
||||||
|
hashWithSalt = hashUsing fromEnum
|
||||||
|
|
||||||
|
instance PathPiece SupportedArch where
|
||||||
|
toPathPiece Win32 = "win32"
|
||||||
|
toPathPiece Win64 = "win64"
|
||||||
|
toPathPiece Linux32 = "linux32"
|
||||||
|
toPathPiece Linux64 = "linux64"
|
||||||
|
toPathPiece Mac32 = "mac32"
|
||||||
|
toPathPiece Mac64 = "mac64"
|
||||||
|
|
||||||
|
fromPathPiece "win32" = Just Win32
|
||||||
|
fromPathPiece "win64" = Just Win64
|
||||||
|
fromPathPiece "linux32" = Just Linux32
|
||||||
|
fromPathPiece "linux64" = Just Linux64
|
||||||
|
fromPathPiece "mac32" = Just Mac32
|
||||||
|
fromPathPiece "mac64" = Just Mac64
|
||||||
|
fromPathPiece _ = Nothing
|
||||||
|
|||||||
@ -28,6 +28,7 @@
|
|||||||
/hoogle HoogleR GET
|
/hoogle HoogleR GET
|
||||||
/db.hoo HoogleDatabaseR GET
|
/db.hoo HoogleDatabaseR GET
|
||||||
/build-plan BuildPlanR GET
|
/build-plan BuildPlanR GET
|
||||||
|
/ghc-major-version GhcMajorVersionR GET
|
||||||
|
|
||||||
/aliases AliasesR PUT
|
/aliases AliasesR PUT
|
||||||
/alias/#Slug/#Slug/*Texts AliasR
|
/alias/#Slug/#Slug/*Texts AliasR
|
||||||
@ -57,3 +58,7 @@
|
|||||||
/upload2 UploadV2R PUT
|
/upload2 UploadV2R PUT
|
||||||
/build-version BuildVersionR GET
|
/build-version BuildVersionR GET
|
||||||
/package-counts PackageCountsR GET
|
/package-counts PackageCountsR GET
|
||||||
|
|
||||||
|
/download DownloadR GET
|
||||||
|
/download/lts-snapshots.json DownloadLtsSnapshotsJsonR GET
|
||||||
|
/download/#SupportedArch/#Text DownloadGhcLinksR GET
|
||||||
|
|||||||
@ -23,6 +23,7 @@ library
|
|||||||
Data.Slug
|
Data.Slug
|
||||||
Data.Tag
|
Data.Tag
|
||||||
Data.BlobStore
|
Data.BlobStore
|
||||||
|
Data.GhcLinks
|
||||||
Data.Hackage
|
Data.Hackage
|
||||||
Data.Hackage.DeprecationInfo
|
Data.Hackage.DeprecationInfo
|
||||||
Data.WebsiteContent
|
Data.WebsiteContent
|
||||||
@ -54,6 +55,7 @@ library
|
|||||||
Handler.PackageCounts
|
Handler.PackageCounts
|
||||||
Handler.Sitemap
|
Handler.Sitemap
|
||||||
Handler.BuildPlan
|
Handler.BuildPlan
|
||||||
|
Handler.Download
|
||||||
|
|
||||||
if flag(dev) || flag(library-only)
|
if flag(dev) || flag(library-only)
|
||||||
cpp-options: -DDEVELOPMENT
|
cpp-options: -DDEVELOPMENT
|
||||||
@ -90,6 +92,7 @@ library
|
|||||||
DeriveFunctor
|
DeriveFunctor
|
||||||
DeriveFoldable
|
DeriveFoldable
|
||||||
DeriveTraversable
|
DeriveTraversable
|
||||||
|
LambdaCase
|
||||||
|
|
||||||
build-depends:
|
build-depends:
|
||||||
base >= 4
|
base >= 4
|
||||||
@ -143,6 +146,7 @@ library
|
|||||||
, yesod-static >= 1.2
|
, yesod-static >= 1.2
|
||||||
, zlib
|
, zlib
|
||||||
, unordered-containers
|
, unordered-containers
|
||||||
|
, hashable
|
||||||
-- Avoid https://github.com/haskell/cabal/issues/1202
|
-- Avoid https://github.com/haskell/cabal/issues/1202
|
||||||
, Cabal >= 1.18
|
, Cabal >= 1.18
|
||||||
, lifted-base
|
, lifted-base
|
||||||
|
|||||||
21
templates/download.hamlet
Normal file
21
templates/download.hamlet
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<h1>Warning: pre-release
|
||||||
|
|
||||||
|
<p>The following executable is considered experimental.
|
||||||
|
<p>More operating systems and architectures will be supported upon official release.
|
||||||
|
|
||||||
|
<h1>Download
|
||||||
|
$forall (arch, exe) <- downloadCandidates
|
||||||
|
<ul .downloads>
|
||||||
|
$if currentlySupported arch
|
||||||
|
<li>
|
||||||
|
#{toPathPiece arch}:
|
||||||
|
<a href=#{executableLink arch exe}>
|
||||||
|
#{toPathPiece exe}
|
||||||
|
|
||||||
|
<h1>What is stackage-setup?
|
||||||
|
|
||||||
|
<p>The stackage-setup executable is an easy way to download and set up the basic executables needed for developing Haskell.
|
||||||
|
<p>After running stackage-setup, You can find these executables in:
|
||||||
|
<code>~/.stackage/environment/$group/$group-$version/bin/
|
||||||
|
<p>For example, ghc, ghc-pkg, haddock, etc for ghc-7.8.4 are installed here:
|
||||||
|
<code>~/.stackage/environment/ghc/ghc-7.8.4/bin/
|
||||||
Loading…
Reference in New Issue
Block a user