Specify devel port on command line
This commit is contained in:
parent
fdeaec8dd4
commit
3e51af2b34
@ -67,11 +67,14 @@ import GhcBuild (buildPackage,
|
|||||||
getBuildFlags)
|
getBuildFlags)
|
||||||
|
|
||||||
import qualified Config as GHC
|
import qualified Config as GHC
|
||||||
|
import Data.Conduit.Network (HostPreference (HostIPv4),
|
||||||
|
bindPort)
|
||||||
import Network (withSocketsDo)
|
import Network (withSocketsDo)
|
||||||
import Network.HTTP.Conduit (def, newManager)
|
import Network.HTTP.Conduit (def, newManager)
|
||||||
import Network.HTTP.ReverseProxy (ProxyDest (ProxyDest),
|
import Network.HTTP.ReverseProxy (ProxyDest (ProxyDest),
|
||||||
waiProxyTo)
|
waiProxyTo)
|
||||||
import Network.HTTP.Types (status200)
|
import Network.HTTP.Types (status200)
|
||||||
|
import Network.Socket (sClose)
|
||||||
import Network.Wai (responseLBS)
|
import Network.Wai (responseLBS)
|
||||||
import Network.Wai.Handler.Warp (run)
|
import Network.Wai.Handler.Warp (run)
|
||||||
import SrcLoc (Located)
|
import SrcLoc (Located)
|
||||||
@ -99,27 +102,29 @@ data DevelOpts = DevelOpts
|
|||||||
, successHook :: Maybe String
|
, successHook :: Maybe String
|
||||||
, failHook :: Maybe String
|
, failHook :: Maybe String
|
||||||
, buildDir :: Maybe String
|
, buildDir :: Maybe String
|
||||||
|
, develPort :: Int
|
||||||
} deriving (Show, Eq)
|
} deriving (Show, Eq)
|
||||||
|
|
||||||
getBuildDir :: DevelOpts -> String
|
getBuildDir :: DevelOpts -> String
|
||||||
getBuildDir opts = fromMaybe "dist" (buildDir opts)
|
getBuildDir opts = fromMaybe "dist" (buildDir opts)
|
||||||
|
|
||||||
defaultDevelOpts :: DevelOpts
|
defaultDevelOpts :: DevelOpts
|
||||||
defaultDevelOpts = DevelOpts False False False (-1) Nothing Nothing Nothing
|
defaultDevelOpts = DevelOpts False False False (-1) Nothing Nothing Nothing 3000
|
||||||
|
|
||||||
-- | Run a reverse proxy from port 3000 to 3001. If there is no response on
|
-- | Run a reverse proxy from port 3000 to 3001. If there is no response on
|
||||||
-- 3001, give an appropriate message to the user.
|
-- 3001, give an appropriate message to the user.
|
||||||
reverseProxy :: IO ()
|
reverseProxy :: DevelOpts -> Int -> IO ()
|
||||||
reverseProxy = withSocketsDo $ do
|
reverseProxy opts appPort = do
|
||||||
manager <- newManager def
|
manager <- newManager def
|
||||||
forever $ do
|
let loop = forever $ do
|
||||||
run 3000 $ waiProxyTo
|
run (develPort opts) $ waiProxyTo
|
||||||
(const $ return $ Right $ ProxyDest "127.0.0.1" 3001)
|
(const $ return $ Right $ ProxyDest "127.0.0.1" appPort)
|
||||||
onExc
|
onExc
|
||||||
manager
|
manager
|
||||||
putStrLn "Reverse proxy stopped, but it shouldn't"
|
putStrLn "Reverse proxy stopped, but it shouldn't"
|
||||||
threadDelay 1000000
|
threadDelay 1000000
|
||||||
putStrLn "Restarting reverse proxy"
|
putStrLn "Restarting reverse proxy"
|
||||||
|
loop `Ex.onException` exitFailure
|
||||||
where
|
where
|
||||||
onExc _ _ = return $ responseLBS
|
onExc _ _ = return $ responseLBS
|
||||||
status200
|
status200
|
||||||
@ -128,9 +133,26 @@ reverseProxy = withSocketsDo $ do
|
|||||||
]
|
]
|
||||||
"<h1>App not ready, please refresh</h1>"
|
"<h1>App not ready, please refresh</h1>"
|
||||||
|
|
||||||
|
checkPort :: Int -> IO Bool
|
||||||
|
checkPort p = do
|
||||||
|
es <- Ex.try $ bindPort p HostIPv4
|
||||||
|
case es of
|
||||||
|
Left (_ :: Ex.IOException) -> return False
|
||||||
|
Right s -> do
|
||||||
|
sClose s
|
||||||
|
return True
|
||||||
|
|
||||||
|
getPort :: Int -> IO Int
|
||||||
|
getPort p = do
|
||||||
|
avail <- checkPort p
|
||||||
|
if avail then return p else getPort (succ p)
|
||||||
|
|
||||||
devel :: DevelOpts -> [String] -> IO ()
|
devel :: DevelOpts -> [String] -> IO ()
|
||||||
devel opts passThroughArgs = withManager $ \manager -> do
|
devel opts passThroughArgs = withSocketsDo $ withManager $ \manager -> do
|
||||||
_ <- forkIO reverseProxy
|
avail <- checkPort $ develPort opts
|
||||||
|
unless avail $ error "devel port unavailable"
|
||||||
|
appPort <- getPort 17834
|
||||||
|
_ <- forkIO $ reverseProxy opts appPort
|
||||||
checkDevelFile
|
checkDevelFile
|
||||||
writeLock opts
|
writeLock opts
|
||||||
|
|
||||||
@ -138,7 +160,7 @@ devel opts passThroughArgs = withManager $ \manager -> do
|
|||||||
_ <- forkIO $ do
|
_ <- forkIO $ do
|
||||||
filesModified <- newEmptyMVar
|
filesModified <- newEmptyMVar
|
||||||
watchTree manager "." (const True) (\_ -> void (tryPutMVar filesModified ()))
|
watchTree manager "." (const True) (\_ -> void (tryPutMVar filesModified ()))
|
||||||
evalStateT (mainOuterLoop filesModified) Map.empty
|
evalStateT (mainOuterLoop appPort filesModified) Map.empty
|
||||||
_ <- getLine
|
_ <- getLine
|
||||||
writeLock opts
|
writeLock opts
|
||||||
exitSuccess
|
exitSuccess
|
||||||
@ -146,7 +168,7 @@ devel opts passThroughArgs = withManager $ \manager -> do
|
|||||||
bd = getBuildDir opts
|
bd = getBuildDir opts
|
||||||
|
|
||||||
-- outer loop re-reads the cabal file
|
-- outer loop re-reads the cabal file
|
||||||
mainOuterLoop filesModified = do
|
mainOuterLoop appPort filesModified = do
|
||||||
ghcVer <- liftIO ghcVersion
|
ghcVer <- liftIO ghcVersion
|
||||||
cabal <- liftIO $ D.findPackageDesc "."
|
cabal <- liftIO $ D.findPackageDesc "."
|
||||||
gpd <- liftIO $ D.readPackageDescription D.normal cabal
|
gpd <- liftIO $ D.readPackageDescription D.normal cabal
|
||||||
@ -158,10 +180,10 @@ devel opts passThroughArgs = withManager $ \manager -> do
|
|||||||
liftIO $ removeFileIfExists "yesod-devel/arargs.txt" -- the configure step, remove them to force
|
liftIO $ removeFileIfExists "yesod-devel/arargs.txt" -- the configure step, remove them to force
|
||||||
liftIO $ removeFileIfExists "yesod-devel/ldargs.txt" -- a cabal build first
|
liftIO $ removeFileIfExists "yesod-devel/ldargs.txt" -- a cabal build first
|
||||||
rebuild <- liftIO $ mkRebuild gpd ghcVer cabal opts ldar
|
rebuild <- liftIO $ mkRebuild gpd ghcVer cabal opts ldar
|
||||||
mainInnerLoop hsSourceDirs filesModified cabal gpd lib ghcVer rebuild
|
mainInnerLoop appPort hsSourceDirs filesModified cabal gpd lib ghcVer rebuild
|
||||||
|
|
||||||
-- inner loop rebuilds after files change
|
-- inner loop rebuilds after files change
|
||||||
mainInnerLoop hsSourceDirs filesModified cabal gpd lib ghcVer rebuild = go
|
mainInnerLoop appPort hsSourceDirs filesModified cabal gpd lib ghcVer rebuild = go
|
||||||
where
|
where
|
||||||
go = do
|
go = do
|
||||||
_ <- recompDeps hsSourceDirs
|
_ <- recompDeps hsSourceDirs
|
||||||
@ -185,7 +207,7 @@ devel opts passThroughArgs = withManager $ \manager -> do
|
|||||||
else "Starting development server..."
|
else "Starting development server..."
|
||||||
env0 <- liftIO getEnvironment
|
env0 <- liftIO getEnvironment
|
||||||
(_,_,_,ph) <- liftIO $ createProcess (proc "runghc" devArgs)
|
(_,_,_,ph) <- liftIO $ createProcess (proc "runghc" devArgs)
|
||||||
{ env = Just $ ("PORT", "3001") : ("DISPLAY_PORT", "3000") : env0
|
{ env = Just $ ("PORT", show appPort) : ("DISPLAY_PORT", show $ develPort opts) : env0
|
||||||
}
|
}
|
||||||
derefMap <- get
|
derefMap <- get
|
||||||
watchTid <- liftIO . forkIO . try_ $ flip evalStateT derefMap $ do
|
watchTid <- liftIO . forkIO . try_ $ flip evalStateT derefMap $ do
|
||||||
@ -201,7 +223,7 @@ devel opts passThroughArgs = withManager $ \manager -> do
|
|||||||
liftIO $ Ex.throwTo watchTid (userError "process finished")
|
liftIO $ Ex.throwTo watchTid (userError "process finished")
|
||||||
loop list
|
loop list
|
||||||
n <- liftIO $ cabal `isNewerThan` (bd </> "setup-config")
|
n <- liftIO $ cabal `isNewerThan` (bd </> "setup-config")
|
||||||
if n then mainOuterLoop filesModified else go
|
if n then mainOuterLoop appPort filesModified else go
|
||||||
|
|
||||||
runBuildHook :: Maybe String -> IO ()
|
runBuildHook :: Maybe String -> IO ()
|
||||||
runBuildHook (Just s) = do
|
runBuildHook (Just s) = do
|
||||||
|
|||||||
@ -62,8 +62,8 @@ getBuildFlags = do
|
|||||||
return argv2
|
return argv2
|
||||||
|
|
||||||
buildPackage :: [Located String] -> FilePath -> FilePath -> IO Bool
|
buildPackage :: [Located String] -> FilePath -> FilePath -> IO Bool
|
||||||
buildPackage a ld ar = buildPackage' a ld ar `Ex.catch` \(e::Ex.SomeException) -> do
|
buildPackage a ld ar = buildPackage' a ld ar `Ex.catch` \e -> do
|
||||||
putStrLn ("exception building package: " ++ show e)
|
putStrLn ("exception building package: " ++ show (e :: Ex.SomeException))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
buildPackage' :: [Located String] -> FilePath -> FilePath -> IO Bool
|
buildPackage' :: [Located String] -> FilePath -> FilePath -> IO Bool
|
||||||
|
|||||||
@ -53,6 +53,7 @@ data Command = Init
|
|||||||
, _develBuildDir :: Maybe String
|
, _develBuildDir :: Maybe String
|
||||||
, develIgnore :: [String]
|
, develIgnore :: [String]
|
||||||
, develExtraArgs :: [String]
|
, develExtraArgs :: [String]
|
||||||
|
, _develPort :: Int
|
||||||
}
|
}
|
||||||
| Test
|
| Test
|
||||||
| AddHandler
|
| AddHandler
|
||||||
@ -90,7 +91,7 @@ main = do
|
|||||||
Configure -> cabal ["configure"]
|
Configure -> cabal ["configure"]
|
||||||
Build es -> touch' >> cabal ("build":es)
|
Build es -> touch' >> cabal ("build":es)
|
||||||
Touch -> touch'
|
Touch -> touch'
|
||||||
Devel da s f r b _ig es -> devel (DevelOpts (optCabalPgm o == CabalDev) da (optVerbose o) r s f b) es
|
Devel da s f r b _ig es p -> devel (DevelOpts (optCabalPgm o == CabalDev) da (optVerbose o) r s f b p) es
|
||||||
Keter noRebuild -> keter (cabalCommand o) noRebuild
|
Keter noRebuild -> keter (cabalCommand o) noRebuild
|
||||||
Version -> do putStrLn ("yesod-core version:" ++ yesodVersion)
|
Version -> do putStrLn ("yesod-core version:" ++ yesodVersion)
|
||||||
putStrLn ("yesod version:" ++ showVersion Paths_yesod.version)
|
putStrLn ("yesod version:" ++ showVersion Paths_yesod.version)
|
||||||
@ -145,6 +146,8 @@ develOptions = Devel <$> switch ( long "disable-api" <> short 'd'
|
|||||||
<> help "ignore file changes in DIR" )
|
<> help "ignore file changes in DIR" )
|
||||||
)
|
)
|
||||||
<*> extraCabalArgs
|
<*> extraCabalArgs
|
||||||
|
<*> option ( long "port" <> short 'p' <> value 3000 <> metavar "N"
|
||||||
|
<> help "Devel server listening port" )
|
||||||
|
|
||||||
extraCabalArgs :: Parser [String]
|
extraCabalArgs :: Parser [String]
|
||||||
extraCabalArgs = many (strOption ( long "extra-cabal-arg" <> short 'e' <> metavar "ARG"
|
extraCabalArgs = many (strOption ( long "extra-cabal-arg" <> short 'e' <> metavar "ARG"
|
||||||
|
|||||||
@ -108,6 +108,7 @@ executable yesod
|
|||||||
, http-reverse-proxy >= 0.1.0.4
|
, http-reverse-proxy >= 0.1.0.4
|
||||||
, network
|
, network
|
||||||
, http-conduit
|
, http-conduit
|
||||||
|
, network-conduit
|
||||||
, project-template >= 0.1.1
|
, project-template >= 0.1.1
|
||||||
|
|
||||||
ghc-options: -Wall -threaded
|
ghc-options: -Wall -threaded
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user