git annex webapp now opens a browser to the webapp
Also, starts the assistant if it wasn't already running.
This commit is contained in:
parent
e6ce54de82
commit
1ffef3ad75
6 changed files with 122 additions and 23 deletions
|
@ -152,7 +152,7 @@ startDaemon assistant foreground
|
||||||
, mountWatcherThread st dstatus scanremotes
|
, mountWatcherThread st dstatus scanremotes
|
||||||
, transferScannerThread st scanremotes transferqueue
|
, transferScannerThread st scanremotes transferqueue
|
||||||
#ifdef WITH_WEBAPP
|
#ifdef WITH_WEBAPP
|
||||||
, webAppThread dstatus
|
, webAppThread st dstatus
|
||||||
#endif
|
#endif
|
||||||
, watchThread st dstatus transferqueue changechan
|
, watchThread st dstatus transferqueue changechan
|
||||||
]
|
]
|
||||||
|
|
|
@ -10,10 +10,12 @@
|
||||||
module Assistant.Threads.WebApp where
|
module Assistant.Threads.WebApp where
|
||||||
|
|
||||||
import Assistant.Common
|
import Assistant.Common
|
||||||
|
import Assistant.ThreadedMonad
|
||||||
import Assistant.DaemonStatus
|
import Assistant.DaemonStatus
|
||||||
import Utility.WebApp
|
import Utility.WebApp
|
||||||
|
|
||||||
import Yesod
|
import Yesod
|
||||||
|
import Network.Socket (PortNumber)
|
||||||
|
|
||||||
data WebApp = WebApp DaemonStatusHandle
|
data WebApp = WebApp DaemonStatusHandle
|
||||||
|
|
||||||
|
@ -30,14 +32,33 @@ getHomeR = defaultLayout [whamlet|Hello, World<p><a href=@{ConfigR}>config|]
|
||||||
getConfigR :: Handler RepHtml
|
getConfigR :: Handler RepHtml
|
||||||
getConfigR = defaultLayout [whamlet|<a href=@{HomeR}>main|]
|
getConfigR = defaultLayout [whamlet|<a href=@{HomeR}>main|]
|
||||||
|
|
||||||
webAppThread :: DaemonStatusHandle -> IO ()
|
webAppThread :: ThreadState -> DaemonStatusHandle -> IO ()
|
||||||
webAppThread dstatus = do
|
webAppThread st dstatus = do
|
||||||
app <- toWaiApp (WebApp dstatus)
|
app <- toWaiApp (WebApp dstatus)
|
||||||
app' <- ifM debugEnabled
|
app' <- ifM debugEnabled
|
||||||
( return $ httpDebugLogger app
|
( return $ httpDebugLogger app
|
||||||
, return app
|
, return app
|
||||||
)
|
)
|
||||||
runWebApp app' browser
|
runWebApp app' $ \p -> runThreadState st $ writeHtmlShim p
|
||||||
|
|
||||||
|
{- Creates a html shim file that's used to redirect into the webapp. -}
|
||||||
|
writeHtmlShim :: PortNumber -> Annex ()
|
||||||
|
writeHtmlShim port = do
|
||||||
|
htmlshim <- fromRepo gitAnnexHtmlShim
|
||||||
|
liftIO $ writeFile htmlshim $ genHtmlShim port
|
||||||
|
|
||||||
|
{- TODO: generate this static file using Yesod. -}
|
||||||
|
genHtmlShim :: PortNumber -> String
|
||||||
|
genHtmlShim port = unlines
|
||||||
|
[ "<html>"
|
||||||
|
, "<head>"
|
||||||
|
, "<meta http-equiv=\"refresh\" content=\"0; URL=" ++ url ++ "\">"
|
||||||
|
, "</head>"
|
||||||
|
, "<body>"
|
||||||
|
, "<p>"
|
||||||
|
, "<a href=\"" ++ url ++ "\">Starting webapp...</a>"
|
||||||
|
, "</p>"
|
||||||
|
, "</body>"
|
||||||
|
]
|
||||||
where
|
where
|
||||||
browser p = void $
|
url = "http://localhost:" ++ show port ++ "/"
|
||||||
runBrowser $ "http://" ++ localhost ++ ":" ++ show p
|
|
||||||
|
|
58
Command/WebApp.hs
Normal file
58
Command/WebApp.hs
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
{- git-annex webapp launcher
|
||||||
|
-
|
||||||
|
- Copyright 2012 Joey Hess <joey@kitenet.net>
|
||||||
|
-
|
||||||
|
- Licensed under the GNU GPL version 3 or higher.
|
||||||
|
-}
|
||||||
|
|
||||||
|
module Command.WebApp where
|
||||||
|
|
||||||
|
import Common.Annex
|
||||||
|
import Command
|
||||||
|
import Assistant
|
||||||
|
import Utility.WebApp
|
||||||
|
import Utility.Daemon
|
||||||
|
import qualified Annex
|
||||||
|
|
||||||
|
import Control.Concurrent
|
||||||
|
import System.Posix.Process
|
||||||
|
|
||||||
|
def :: [Command]
|
||||||
|
def = [command "webapp" paramNothing seek "launch webapp"]
|
||||||
|
|
||||||
|
seek :: [CommandSeek]
|
||||||
|
seek = [withNothing start]
|
||||||
|
|
||||||
|
start :: CommandStart
|
||||||
|
start = notBareRepo $ do
|
||||||
|
r <- checkpid
|
||||||
|
when (r == Nothing) $
|
||||||
|
startassistant
|
||||||
|
f <- liftIO . absPath =<< fromRepo gitAnnexHtmlShim
|
||||||
|
let url = "file://" ++ f
|
||||||
|
ifM (liftIO $ runBrowser url)
|
||||||
|
( stop
|
||||||
|
, error $ "failed to start web browser on url " ++ url
|
||||||
|
)
|
||||||
|
where
|
||||||
|
checkpid = do
|
||||||
|
pidfile <- fromRepo gitAnnexPidFile
|
||||||
|
liftIO $ checkDaemon pidfile
|
||||||
|
startassistant = do
|
||||||
|
{- Fork a separate process to run the assistant,
|
||||||
|
- with a copy of the Annex state. -}
|
||||||
|
state <- Annex.getState id
|
||||||
|
liftIO $ void $ forkProcess $
|
||||||
|
Annex.eval state $ startDaemon True False
|
||||||
|
waitdaemon (100 :: Int)
|
||||||
|
waitdaemon 0 = error "failed to start git-annex assistant"
|
||||||
|
waitdaemon n = do
|
||||||
|
r <- checkpid
|
||||||
|
case r of
|
||||||
|
Just _ -> return ()
|
||||||
|
Nothing -> do
|
||||||
|
liftIO $
|
||||||
|
threadDelay 100000 -- 0.1 seconds
|
||||||
|
|
||||||
|
|
||||||
|
waitdaemon (n - 1)
|
|
@ -63,6 +63,9 @@ import qualified Command.Version
|
||||||
#ifdef WITH_ASSISTANT
|
#ifdef WITH_ASSISTANT
|
||||||
import qualified Command.Watch
|
import qualified Command.Watch
|
||||||
import qualified Command.Assistant
|
import qualified Command.Assistant
|
||||||
|
#ifdef WITH_WEBAPP
|
||||||
|
import qualified Command.WebApp
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
cmds :: [Command]
|
cmds :: [Command]
|
||||||
|
@ -108,6 +111,9 @@ cmds = concat
|
||||||
#ifdef WITH_ASSISTANT
|
#ifdef WITH_ASSISTANT
|
||||||
, Command.Watch.def
|
, Command.Watch.def
|
||||||
, Command.Assistant.def
|
, Command.Assistant.def
|
||||||
|
#ifdef WITH_WEBAPP
|
||||||
|
, Command.WebApp.def
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ module Locations (
|
||||||
gitAnnexPidFile,
|
gitAnnexPidFile,
|
||||||
gitAnnexDaemonStatusFile,
|
gitAnnexDaemonStatusFile,
|
||||||
gitAnnexLogFile,
|
gitAnnexLogFile,
|
||||||
|
gitAnnexHtmlShim,
|
||||||
gitAnnexSshDir,
|
gitAnnexSshDir,
|
||||||
gitAnnexRemotesDir,
|
gitAnnexRemotesDir,
|
||||||
isLinkToAnnex,
|
isLinkToAnnex,
|
||||||
|
@ -166,6 +167,10 @@ gitAnnexDaemonStatusFile r = gitAnnexDir r </> "daemon.status"
|
||||||
gitAnnexLogFile :: Git.Repo -> FilePath
|
gitAnnexLogFile :: Git.Repo -> FilePath
|
||||||
gitAnnexLogFile r = gitAnnexDir r </> "daemon.log"
|
gitAnnexLogFile r = gitAnnexDir r </> "daemon.log"
|
||||||
|
|
||||||
|
{- Html shim file used to launch the webapp. -}
|
||||||
|
gitAnnexHtmlShim :: Git.Repo -> FilePath
|
||||||
|
gitAnnexHtmlShim r = gitAnnexDir r </> "webapp.html"
|
||||||
|
|
||||||
{- .git/annex/ssh/ is used for ssh connection caching -}
|
{- .git/annex/ssh/ is used for ssh connection caching -}
|
||||||
gitAnnexSshDir :: Git.Repo -> FilePath
|
gitAnnexSshDir :: Git.Repo -> FilePath
|
||||||
gitAnnexSshDir r = addTrailingPathSeparator $ gitAnnexDir r </> "ssh"
|
gitAnnexSshDir r = addTrailingPathSeparator $ gitAnnexDir r </> "ssh"
|
||||||
|
|
|
@ -62,24 +62,33 @@ lockPidFile onfailure file = do
|
||||||
where
|
where
|
||||||
newfile = file ++ ".new"
|
newfile = file ++ ".new"
|
||||||
|
|
||||||
{- Stops the daemon.
|
{- Checks if the daemon is running, by checking that the pid file
|
||||||
|
- is locked by the same process that is listed in the pid file.
|
||||||
-
|
-
|
||||||
- The pid file is used to get the daemon's pid.
|
- If it's running, returns its pid. -}
|
||||||
-
|
checkDaemon :: FilePath -> IO (Maybe ProcessID)
|
||||||
- To guard against a stale pid, check the lock of the pid file,
|
checkDaemon pidfile = do
|
||||||
- and compare the process that has it locked with the file content.
|
v <- catchMaybeIO $
|
||||||
-}
|
openFd pidfile ReadOnly (Just stdFileMode) defaultFileFlags
|
||||||
stopDaemon :: FilePath -> IO ()
|
case v of
|
||||||
stopDaemon pidfile = do
|
Just fd -> do
|
||||||
fd <- openFd pidfile ReadOnly (Just stdFileMode) defaultFileFlags
|
locked <- getLock fd (ReadLock, AbsoluteSeek, 0, 0)
|
||||||
locked <- getLock fd (ReadLock, AbsoluteSeek, 0, 0)
|
p <- readish <$> readFile pidfile
|
||||||
p <- readish <$> readFile pidfile
|
return $ check locked p
|
||||||
case (locked, p) of
|
Nothing -> return Nothing
|
||||||
(Nothing, _) -> noop
|
where
|
||||||
(_, Nothing) -> noop
|
check Nothing _ = Nothing
|
||||||
(Just (pid, _), Just pid')
|
check _ Nothing = Nothing
|
||||||
| pid == pid' -> signalProcess sigTERM pid
|
check (Just (pid, _)) (Just pid')
|
||||||
| otherwise -> error $
|
| pid == pid' = Just pid
|
||||||
|
| otherwise = error $
|
||||||
"stale pid in " ++ pidfile ++
|
"stale pid in " ++ pidfile ++
|
||||||
" (got " ++ show pid' ++
|
" (got " ++ show pid' ++
|
||||||
"; expected" ++ show pid ++ " )"
|
"; expected" ++ show pid ++ " )"
|
||||||
|
|
||||||
|
{- Stops the daemon, safely. -}
|
||||||
|
stopDaemon :: FilePath -> IO ()
|
||||||
|
stopDaemon pidfile = go =<< checkDaemon pidfile
|
||||||
|
where
|
||||||
|
go Nothing = noop
|
||||||
|
go (Just pid) = signalProcess sigTERM pid
|
||||||
|
|
Loading…
Reference in a new issue