diff options
| author | Gregor Kleen <gkleen@yggdrasil.li> | 2015-06-21 17:10:13 +0200 | 
|---|---|---|
| committer | Gregor Kleen <gkleen@yggdrasil.li> | 2015-06-21 17:10:13 +0200 | 
| commit | d8ea165173a2b7ba514bb3eafac3d21fc1f4d086 (patch) | |
| tree | 0d53f6c2db8ee286956eb57e39acaf62754e42b1 | |
| parent | 42c671b4a48dd1431ab43c1f842af33e2fe5cbe9 (diff) | |
| download | trivmix-d8ea165173a2b7ba514bb3eafac3d21fc1f4d086.tar trivmix-d8ea165173a2b7ba514bb3eafac3d21fc1f4d086.tar.gz trivmix-d8ea165173a2b7ba514bb3eafac3d21fc1f4d086.tar.bz2 trivmix-d8ea165173a2b7ba514bb3eafac3d21fc1f4d086.tar.xz trivmix-d8ea165173a2b7ba514bb3eafac3d21fc1f4d086.zip  | |
Switched build system structure & locks
| -rw-r--r-- | package.nix | 13 | ||||
| -rw-r--r-- | src/Trivmix.hs | 32 | ||||
| -rw-r--r-- | trivmix.cabal | 3 | ||||
| -rw-r--r-- | trivmix.nix | 17 | 
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 | |||
| 6 | stdenv.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 | |||
| 27 | import System.IO.Error | 27 | import System.IO.Error | 
| 28 | import System.IO | 28 | import System.IO | 
| 29 | 29 | ||
| 30 | import System.FileLock | ||
| 30 | import System.INotify | 31 | import System.INotify | 
| 31 | 32 | ||
| 32 | import Data.Char | 33 | import Data.Char | 
| @@ -164,12 +165,13 @@ handleFiles :: INotify -> MVar Level -> [FilePath] -> IO () | |||
| 164 | handleFiles inotify level files = do | 165 | handleFiles 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 | ||
| 217 | readLevel :: Chan Level -> MVar Level -> FilePath -> IO () | 219 | readLevel :: Chan Level -> MVar Level -> FilePath -> MVar () -> IO () | 
| 218 | readLevel levelChan current file = catch action handler | 220 | readLevel 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 | ||
| 237 | writeLevel :: FilePath -> Level -> IO () | 241 | writeLevel :: FilePath -> MVar () -> Level -> IO () | 
| 238 | writeLevel file level = do | 242 | writeLevel 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 | |||
| 247 | withMVarLock :: MVar () -> IO a -> IO a | ||
| 248 | withMVarLock 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 | ||
| 4 | name: trivmix | 4 | name: trivmix | 
| 5 | version: 2.3.0 | 5 | version: 2.4.0 | 
| 6 | -- synopsis: | 6 | -- synopsis: | 
| 7 | -- description: | 7 | -- description: | 
| 8 | license: PublicDomain | 8 | license: 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 | ||
| 8 | cabal.mkDerivation (self: { | 7 | cabal.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; | 
