yackage 0.0.1.2 → 0.1.0
raw patch · 3 files changed
+51/−37 lines, 3 filesdep +hamletdep +transformersdep +warpdep −wai-extradep −yesoddep ~blaze-builderdep ~http-enumerator
Dependencies added: hamlet, transformers, warp, yesod-core, yesod-form
Dependencies removed: wai-extra, yesod
Dependency ranges changed: blaze-builder, http-enumerator
Files
- yackage-upload.hs +3/−3
- yackage.cabal +8/−5
- yackage.hs +40/−29
yackage-upload.hs view
@@ -14,7 +14,7 @@ [x, y] -> (x, "", y) [x, y, z] -> (x, y, z) _ -> error "Usage: yackage-upload <url> [password] <file>"- req <- parseUrl url+ req <- parseUrl $ S8.pack url body <- mkBody pass file let req' = req { method = "POST"@@ -22,9 +22,9 @@ [ ("Content-Type", "multipart/form-data; boundary=" `S8.append` bound) , ("Content-Length", S8.pack $ show $ L.length body) ]- , requestBody = body+ , requestBody = RequestBodyLBS body }- res <- httpLbs req'+ res <- withManager $ httpLbs req' L.putStrLn $ responseBody res bound = "YACKAGEUPLOAD"
yackage.cabal view
@@ -1,5 +1,5 @@ Name: yackage-Version: 0.0.1.2+Version: 0.1.0 Synopsis: Personal Hackage replacement for testing new packages. Description: This package installs a yackage executable that runs a simplistic hackage-like server. It allows you to upload packages produced via cabal sdist and install them via cabal. The trick is to add the yackage repository to your cabal config file, with a line such as:@@ -18,7 +18,8 @@ Executable yackage Main-is: yackage.hs Build-depends: base >= 4 && < 5- , yesod >= 0.6 && < 0.7+ , yesod-core >= 0.7 && < 0.8+ , warp , Cabal , bytestring , text@@ -30,12 +31,14 @@ , data-object-yaml , cmdargs , wai- , wai-extra+ , transformers+ , hamlet+ , yesod-form Executable yackage-upload Main-is: yackage-upload.hs- Build-depends: http-enumerator >= 0.2 && < 0.3- , blaze-builder >= 0.2.1.3 && < 0.3+ Build-depends: http-enumerator >= 0.5.1 && < 0.6+ , blaze-builder >= 0.2.1.3 && < 0.4 source-repository head type: git
yackage.hs view
@@ -1,7 +1,16 @@ {-# LANGUAGE OverloadedStrings, TypeFamilies, QuasiQuotes #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE TemplateHaskell #-}-import Yesod+{-# LANGUAGE MultiParamTypeClasses #-}+import Yesod.Core+import Yesod.Dispatch+import Yesod.Handler+import Yesod.Widget+import Yesod.Content+import Yesod.Form+import Yesod.Request+import Text.Hamlet+import Control.Monad.IO.Class (liftIO) import Distribution.Package import Distribution.PackageDescription import Distribution.PackageDescription.Parse@@ -9,7 +18,7 @@ import Data.Version import qualified Data.Map as Map import Data.Map (Map)-import Text.ParserCombinators.ReadP+import Text.ParserCombinators.ReadP hiding (string) import System.Directory import System.Environment import Data.Set (Set, toAscList)@@ -29,13 +38,14 @@ import Control.Monad (join, unless) import System.Console.CmdArgs import Network.Wai-import Network.Wai.Handler.SimpleServer (run)+import Network.Wai.Handler.Warp (run) data Args = Args { port :: Int , password :: Maybe String , localhost :: Bool , rootdir :: Maybe String+ , title :: String } deriving (Show, Data, Typeable) type CabalFile = FilePath@@ -45,6 +55,7 @@ { rootDir :: FilePath , packages :: MVar PackageDB , ypassword :: Maybe String+ , ytitle :: String } type PackageDB = Map PackageName (Set Version)@@ -98,26 +109,26 @@ y <- getYesod ps <- getYesod >>= liftIO . readMVar . packages >>= return . Map.toList defaultLayout $ do- setTitle "Yackage"- addHamlet [$hamlet|-%h1 Yackage-%form!method=post!enctype=multipart/form-data- %div- Upload a new file: $- %input!type=file!name=file- $maybe ypassword.y _- %div- Password: $- %input!type=password!name=password- %div- %input!type=submit!value=Upload-%dl- $forall ps p- %dt $unPackageName.fst.p$- %dd- $forall toAscList.snd.p v- %a!href=@(tarballR.fst.p).v@ $toSinglePiece.v$- \ $+ setTitle $ string $ ytitle y+ addHamlet [$hamlet|\+<h1>Yackage+<form method="post" enctype="multipart/form-data">+ <div>+ \Upload a new file: + <input type="file" name="file">+ $maybe _ <- ypassword y+ <div>+ \Password: + <input type="password" name="password">+ <div>+ <input type="submit" value="Upload">+<dl>+ $forall p <- ps+ <dt>#{unPackageName (fst p)}+ <dd>+ $forall v <- toAscList (snd p)+ <a href="@{tarballR (fst p) v}">#{toSinglePiece v}+ \ |] postRootR = do@@ -127,8 +138,7 @@ Just p -> do p' <- runFormPost' $ maybeStringInput "password" unless (Just p == p') $ permissionDenied "Invalid password"- rr <- getRequest- (_, files) <- liftIO $ reqRequestBody rr+ (_, files) <- runRequestBody content <- case lookup "file" files of Nothing -> error "No file upload found"@@ -187,6 +197,7 @@ , password = Nothing &= help "Optional password required to upload files" , localhost = False &= help "Only allow connections from localhost?" , rootdir = Nothing &= help "Root folder for Yackage config file and packages"+ , title = "Yackage" &= help "Page title displayed in browser" } &= program progname &= summary "Run a Yackage server" path <- case rootdir args of@@ -199,16 +210,16 @@ then parseConfig `fmap` join (decodeFile config) else return $ Map.empty m' <- liftIO $ newMVar m- app <- toWaiApp $ Yackage path m' $ password args+ app <- toWaiApp $ Yackage path m' (password args) (title args) let app' = if localhost args then onlyLocal app else app putStrLn $ "Running Yackage on port " ++ show (port args) ++ ", rootdir: " ++ path run (port args) app' onlyLocal app req =- if remoteHost req `elem` ["127.0.0.1", "::1", "localhost"]+ if takeWhile (/= ':') (show $ remoteHost req) `elem` ["127.0.0.1", "localhost"] then app req- else return $ Response status403 [("Content-Type", "text/plain")]- $ ResponseLBS "This Yackage server only talks to local clients"+ else return $ responseLBS status403 [("Content-Type", "text/plain")]+ "This Yackage server only talks to local clients" unPackageName (PackageName s) = s