cabal-src-0.2.4: hackage-docs.hs
{-# LANGUAGE NoImplicitPrelude, OverloadedStrings #-}
import Distribution.PackageDescription
import Distribution.PackageDescription.Parse
import Distribution.Verbosity
import Distribution.Package
import ClassyPrelude.Conduit
import Distribution.Text (display)
import Data.Conduit.Process
import System.IO.Temp
import Network.HTTP.Client
import Network.HTTP.Client.MultipartFormData
import Network.HTTP.Client.TLS
main :: IO ()
main = withManager tlsManagerSettings $ \man -> do
rawCreds <- readFile "/hackage-creds" `catchIO` \_ ->
error "This tool requires a file /hackage-creds to be present and readable,\ncontaining your username and password for Hackage"
(username, password) <-
case words $ decodeUtf8 rawCreds of
[x, y] -> return (encodeUtf8 x, encodeUtf8 y)
_ -> error "/hackage-creds didn't look like how I wanted"
srcsRaw <- readFile "sources.txt" `catchIO` \_ -> return "."
forM_ (lines $ decodeUtf8 srcsRaw) (processDir username password man . fpFromText)
terror :: Text -> a
terror = error . unpack
processDir :: ByteString -> ByteString -> Manager -> FilePath -> IO ()
processDir username password man dir = do
putStrLn $ "Processing " ++ fpToText dir
cabals <- runResourceT $ sourceDirectory dir $$ foldMapC
(\fp -> if hasExtension fp "cabal"
then asSet $ singletonSet fp
else mempty)
cabal <- case setToList cabals of
[] -> terror $ "No cabal files found in " ++ fpToText dir
[x] -> return x
xs -> terror $ "Multiple cabal files found in " ++ fpToText dir ++ ": " ++ tshow xs
gpd <- readPackageDescription normal $ fpToString cabal
case condLibrary gpd of
Nothing -> putStrLn $ concat
[ "No library in "
, fpToText cabal
, ", skipping"
]
Just _ -> do
let pd = packageDescription gpd
PackageIdentifier name' version' = package pd
name = pack $ display name'
version = pack $ display version'
runIn dir "cabal"
[ "haddock"
, "--hoogle"
, "--hyperlink-source"
, "--html-location=/package/$pkg-$version/docs"
, "--contents-location=/package/$pkg-$version"
]
withSystemTempDirectory "build-docs.XXXXXX" $ \tmp -> do
let docsdir = concat
[ pack tmp
, "/"
, name
, "-"
, version
, "-docs"
]
tarball = docsdir ++ ".tar.gz"
runIn dir "cp"
[ "-R"
, "dist/doc/html/" ++ name
, docsdir
]
runIn dir "tar"
[ "cvz"
, "-C"
, pack tmp
, "--format=ustar"
, "-f"
, tarball
, concat
[ name
, "-"
, version
, "-docs"
]
]
let url = unpack $ concat
[ "https://hackage.haskell.org/package/"
, name
, "-"
, version
, "/docs"
]
bs <- readFile $ fpFromText tarball
let req = applyBasicAuth username password $ (fromString url)
{ method = "PUT"
, requestHeaders =
[ ("Content-Type", "application/x-tar")
, ("Content-Encoding", "gzip")
]
, requestBody = RequestBodyBS bs
}
httpLbs req man >>= print
runIn :: FilePath -> Text -> [Text] -> IO ()
runIn dir cmd args = do
print (dir, cmd, args)
withCheckedProcess cp $ \ClosedStream Inherited Inherited -> return ()
where
cp = (proc (unpack cmd) (map unpack args)) { cwd = Just $ fpToString dir }