summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--package.nix13
-rw-r--r--src/Trivmix.hs32
-rw-r--r--trivmix.cabal3
-rw-r--r--trivmix.nix17
4 files changed, 41 insertions, 24 deletions
diff --git a/package.nix b/package.nix
new file mode 100644
index 0000000..e15704a
--- /dev/null
+++ b/package.nix
@@ -0,0 +1,13 @@
1{ fetchgit
2, stdenv
3, callPackage
4}:
5
6stdenv.lib.overrideDerivation (callPackage ./trivmix.nix {}) (attrs : {
7 src = fetchgit {
8 url = git://git.yggdrasil.li/trivmix;
9 # nix-shell -p nix-prefetch-scripts --command 'nix-prefetch-git git://git.yggdrasil.li/beuteltier' 2>&1 | grep -E '(git revision|hash) is ' | sed -r 's/git revision is /rev = "/' | sed -r 's/hash is /sha256 = "/' | sed -r 's/$/";/'
10 rev = "f7ea4713957f57fa395779d6db0b020d6eb36512";
11 sha256 = "e6dc0910cee98ee3161617ebcca763f3f3e120497182d43629447a487213f8a1";
12 };
13})
diff --git a/src/Trivmix.hs b/src/Trivmix.hs
index 0c1a1a4..79b3804 100644
--- a/src/Trivmix.hs
+++ b/src/Trivmix.hs
@@ -27,6 +27,7 @@ import Control.Exception
27import System.IO.Error 27import System.IO.Error
28import System.IO 28import System.IO
29 29
30import System.FileLock
30import System.INotify 31import System.INotify
31 32
32import Data.Char 33import Data.Char
@@ -164,12 +165,13 @@ handleFiles :: INotify -> MVar Level -> [FilePath] -> IO ()
164handleFiles inotify level files = do 165handleFiles inotify level files = do
165 initLevel <- readMVar level 166 initLevel <- readMVar level
166 levelChanges <- (newChan :: IO (Chan Level)) 167 levelChanges <- (newChan :: IO (Chan Level))
168 stderrLock <- newMVar
167 let 169 let
168 handleFile file = do 170 handleFile file = do
169 levelChanges' <- dupChan levelChanges 171 levelChanges' <- dupChan levelChanges
170 forkIO $ forever $ do -- Broadcast level changes and update all files 172 forkIO $ forever $ do -- Broadcast level changes and update all files
171 readChan levelChanges' >>= writeLevel file 173 readChan levelChanges' >>= writeLevel file stderrLock
172 addWatch inotify watchedAttrs file (const $ readLevel levelChanges level file) 174 addWatch inotify watchedAttrs file (const $ readLevel levelChanges level file stderrLock)
173 mapM handleFile files 175 mapM handleFile files
174 forkIO $ forever $ do 176 forkIO $ forever $ do
175 readChan levelChanges >>= swapMVar level 177 readChan levelChanges >>= swapMVar level
@@ -193,7 +195,7 @@ onStateFile file initial action = do
193 hPutStrLn stderr $ "Removing ‘" ++ file ++ "’ (file)" 195 hPutStrLn stderr $ "Removing ‘" ++ file ++ "’ (file)"
194 removeFile file 196 removeFile file
195 acquireDir = (flip mapM) (reverse createDirs) $ \directory -> do 197 acquireDir = (flip mapM) (reverse createDirs) $ \directory -> do
196 hPutStrLn stderr $ "Creating ‘" ++ directory ++ "’ (dir" 198 hPutStrLn stderr $ "Creating ‘" ++ directory ++ "’ (dir)"
197 createDirectory directory 199 createDirectory directory
198 setFileMode directory defDirectoryMode 200 setFileMode directory defDirectoryMode
199 releaseDir = (flip mapM) createDirs $ \directory -> do 201 releaseDir = (flip mapM) createDirs $ \directory -> do
@@ -214,19 +216,21 @@ takeWhileM pred (x:xs) = do
214 False -> do 216 False -> do
215 return [] 217 return []
216 218
217readLevel :: Chan Level -> MVar Level -> FilePath -> IO () 219readLevel :: Chan Level -> MVar Level -> FilePath -> MVar () -> IO ()
218readLevel levelChan current file = catch action handler 220readLevel levelChan current file stderrLock = catch action handler
219 where 221 where
220 action = do 222 action = do
221 level <- readFile file >>= readIO . stripSpace 223 level <- withFileLock file Shared $ readFile file >>= readIO . stripSpace
222 oldLevel <- readMVar current 224 oldLevel <- readMVar current
223 when (oldLevel /= level) $ do 225 when (oldLevel /= level) $ do
224 writeChan levelChan level 226 writeChan levelChan level
225 hPutStrLn stderr $ "Detected new level: " ++ (show level) 227 withMVarLock stderrLock $
228 hPutStrLn stderr $ "Detected new level: " ++ (show level)
226 handler e = if isUserError e 229 handler e = if isUserError e
227 then do 230 then do
228 hPutStrLn stderr $ "Could not parse new level from ‘" ++ file ++ "’ - overwriting." 231 withMVarLock stderrLock $
229 readMVar current >>= writeLevel file 232 hPutStrLn stderr $ "Could not parse new level from ‘" ++ file ++ "’ - overwriting."
233 readMVar current >>= writeLevel file stderrLock
230 else throw e 234 else throw e
231 stripSpace = reverse . stripSpace' . reverse . stripSpace' 235 stripSpace = reverse . stripSpace' . reverse . stripSpace'
232 stripSpace' [] = [] 236 stripSpace' [] = []
@@ -234,7 +238,11 @@ readLevel levelChan current file = catch action handler
234 then stripSpace' xs 238 then stripSpace' xs
235 else l 239 else l
236 240
237writeLevel :: FilePath -> Level -> IO () 241writeLevel :: FilePath -> MVar () -> Level -> IO ()
238writeLevel file level = do 242writeLevel file stderrLock level = withFileLock file Exclusive $ do
239 hPutStrLn stderr $ "Writing out level ‘" ++ (show level) ++ "’ to ‘" ++ file ++ "’" 243 withMVarLock stderrLock $
244 hPutStrLn stderr $ "Writing out level ‘" ++ (show level) ++ "’ to ‘" ++ file ++ "’"
240 writeFile file (show level ++ "\n") 245 writeFile file (show level ++ "\n")
246
247withMVarLock :: MVar () -> IO a -> IO a
248withMVarLock lock = bracket_ (putMVar lock ()) (takeMVar lock)
diff --git a/trivmix.cabal b/trivmix.cabal
index b0d77a7..74001d7 100644
--- a/trivmix.cabal
+++ b/trivmix.cabal
@@ -2,7 +2,7 @@
2-- documentation, see http://haskell.org/cabal/users-guide/ 2-- documentation, see http://haskell.org/cabal/users-guide/
3 3
4name: trivmix 4name: trivmix
5version: 2.3.0 5version: 2.4.0
6-- synopsis: 6-- synopsis:
7-- description: 7-- description:
8license: PublicDomain 8license: PublicDomain
@@ -30,6 +30,7 @@ executable trivmix
30 , explicit-exception >=0.1 && <1 30 , explicit-exception >=0.1 && <1
31 , process >=1.2 && <2 31 , process >=1.2 && <2
32 , case-insensitive >=1.2 && <2 32 , case-insensitive >=1.2 && <2
33 , filelock >=0.1 && <1
33 hs-source-dirs: src 34 hs-source-dirs: src
34 default-language: Haskell2010 35 default-language: Haskell2010
35 ghc-options: -threaded 36 ghc-options: -threaded
diff --git a/trivmix.nix b/trivmix.nix
index a5ccb9b..f4228d2 100644
--- a/trivmix.nix
+++ b/trivmix.nix
@@ -1,23 +1,18 @@
1# This file was auto-generated by cabal2nix. Please do NOT edit manually! 1# This file was auto-generated by cabal2nix. Please do NOT edit manually!
2 2
3{ cabal, filepath, hinotify, jack, optparseApplicative 3{ cabal, caseInsensitive, explicitException, filelock, filepath
4, transformers, explicitException, process, caseInsensitive 4, hinotify, jack, optparseApplicative, transformers
5, fetchgit
6}: 5}:
7 6
8cabal.mkDerivation (self: { 7cabal.mkDerivation (self: {
9 pname = "trivmix"; 8 pname = "trivmix";
10 version = "2.3.0"; 9 version = "2.4.0";
11 src = fetchgit { 10 src = ./.;
12 url = git://git.yggdrasil.li/trivmix;
13 rev = "d5189cba07f63c3d2f8c575a31c1734f7c9aeed6";
14 sha256 = "88b215dc2d24b875359835b5a75acdd1d6172ad4d4e3fad9ce4cdc3ffec51ba3";
15 };
16 isLibrary = false; 11 isLibrary = false;
17 isExecutable = true; 12 isExecutable = true;
18 buildDepends = [ 13 buildDepends = [
19 filepath hinotify jack optparseApplicative transformers explicitException process 14 caseInsensitive explicitException filelock filepath hinotify jack
20 caseInsensitive 15 optparseApplicative transformers
21 ]; 16 ];
22 meta = { 17 meta = {
23 license = self.stdenv.lib.licenses.publicDomain; 18 license = self.stdenv.lib.licenses.publicDomain;