darcswatch-0.3: src/Darcs/Watch/Storage.hs
{-
Copyright (C) 2008 Joachim Breitner
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
-}
module Darcs.Watch.Storage where
import Darcs
import Darcs.Watch.Data
import Data.Time
import qualified Data.ByteString.Char8 as B
import Data.ByteString.Char8 (ByteString)
import System.FilePath
import System.Directory
import Data.List
import Control.Applicative
import System.Directory
import Control.Monad
import Data.Char
-- | Adds a new patch bundle to the stogare
addBundle :: StorageConf -> PatchBundle -> IO BundleHash
addBundle path bundle = do
let hash = hash_bundle bundle
let dataFile = bundleDir path </> hash <.> "data"
ex <- doesFileExist dataFile
unless ex $ B.writeFile dataFile (B.pack "[]")
B.writeFile (bundleDir path </> hash <.> "bundle")
(make_bundle bundle)
return hash
-- | Retrieves a new patch bundle from the storage
getBundle :: StorageConf -> BundleHash -> IO PatchBundle
getBundle path hash =
either error id . scan_bundle <$> B.readFile (bundleDir path </> hash <.> "bundle")
-- | Retrieves the meta information for the handle
getBundleHistory :: StorageConf -> BundleHash -> IO [BundleHistory]
getBundleHistory path hash =
read <$> B.unpack <$> B.readFile (bundleDir path </> hash <.> "data")
-- | Adds a new entry to the bundle history (stamped with the current time)
changeBundleState :: StorageConf -> BundleHash -> Source -> BundleState -> IO ()
changeBundleState path hash source state = do
history <- getBundleHistory path hash
now <- getCurrentTime
B.writeFile (bundleDir path </> hash <.> "data") $ B.pack $ show $
(now, source, state) : history
listBundles :: StorageConf -> IO [BundleHash]
listBundles path = do
items <- getDirectoryContents (bundleDir path)
return $ map dropExtension
$ filter ( (".bundle" == ) .takeExtension )
$ items
updateRepository :: StorageConf -> (String -> IO ()) -> RepositoryURL -> IO Bool
updateRepository path write repo = do
let infoFile = repoDir path </> safeName repo <.> "data"
let repoFile = repoDir path </> safeName repo <.> "inventory"
ex <- doesFileExist infoFile
info <- if ex then read . B.unpack <$> B.readFile infoFile
else return (RepositoryInfo Nothing Nothing)
now <- getCurrentTime
(ps,changed) <- getInventory write (cacheDir path) repo
when changed $ B.writeFile repoFile (make_context ps)
B.writeFile infoFile $ B.pack $ show $ RepositoryInfo
{ lastCheck = Just now
, lastUpdate = if changed then Just now else lastUpdate info
}
return changed
readRepository :: StorageConf -> RepositoryURL -> IO [PatchInfo]
readRepository path repo = do
let repoFile = repoDir path </> safeName repo <.> "inventory"
ex <- doesFileExist repoFile
if ex then scan_context `fmap` B.readFile repoFile
else return []
getRepositoryInfo :: StorageConf -> RepositoryURL -> IO RepositoryInfo
getRepositoryInfo path repo = do
let infoFile = repoDir path </> safeName repo <.> "data"
ex <- doesFileExist infoFile
if ex then read . B.unpack <$> B.readFile infoFile
else return (RepositoryInfo Nothing Nothing)
bundleDir :: StorageConf -> FilePath
bundleDir path = path </> "bundles"
getBundleFileName :: StorageConf -> BundleHash -> FilePath
getBundleFileName path hash = bundleDir path </> hash <.> "bundle"
repoDir :: StorageConf -> FilePath
repoDir path = path </> "repos"
cacheDir :: StorageConf -> FilePath
cacheDir path = path </> "cache"
safeName n = map s n
where s c = if isSafeFileChar c then c else '_'
isSafeFileChar c = isAlpha c || isDigit c || c `elem` "-_.@:"