Mon Sep 21 21:49:32 CEST 2009 Petr Rockai * Refactor the syncing machinery of Monad somewhat. Mon Sep 21 21:56:36 CEST 2009 Petr Rockai * Move plainTreeIO from Monad to Plain. Wed Sep 23 18:57:10 CEST 2009 Petr Rockai * Refactor Monad into two type classes for read and write access, respectively. New patches: [Refactor the syncing machinery of Monad somewhat. Petr Rockai **20090921194932 Ignore-this: 6c34dcced6006410c22aea8f71550ca6 ] hunk ./Storage/Hashed/Darcs.hs 238 -> IO (a, Tree IO) hashedTreeIO action t dir = do runTreeMonad action $ initialState t syncHashed - where syncHashed = do - ch <- gets changed - modify $ \st -> st { changed = S.empty, changesize = 0 } + where syncHashed ch = do modify $ \st -> st { tree = darcsUpdateDirHashes $ tree st } forM_ (reverse $ S.toList ch) $ \c -> do let path = anchorPath "" c hunk ./Storage/Hashed/Darcs.hs 256 nblob = File $ Blob (decompress `fmap` BL.readFile fn) h newcontent = compress content fsCreateHashedFile fn newcontent - replaceItemAbs path (Just nblob) + replaceItem path (Just nblob) updateSub path s = do let !hash = darcsTreeHash s Just dirdata = darcsFormatDir s hunk ./Storage/Hashed/Darcs.hs 263 fn = dir BS.unpack (encodeBase16 hash) ns = SubTree (s { treeHash = hash }) fsCreateHashedFile fn (compress dirdata) - replaceItemAbs path (Just ns) + replaceItem path (Just ns) -------------------------------------------------------------- -- Reading and writing packed pristine. EXPERIMENTAL. hunk ./Storage/Hashed/Monad.hs 14 , readFile, writeFile, createDirectory, rename, unlink , fileExists, directoryExists, exists, withDirectory , tree, cwd, TreeState, TreeMonad, TreeIO, runTreeMonad - -- * Internal. - , replaceItemAbs, changesize, changed, initialState + , PathSet, initialState, replaceItem ) where import Prelude hiding ( readFile, writeFile ) hunk ./Storage/Hashed/Monad.hs 38 import Control.Monad.State.Strict import qualified Data.Set as S +type PathSet = S.Set AnchoredPath + -- | Internal state of the 'TreeIO' monad. Keeps track of the current Tree -- content, unsync'd changes and a current working directory (of the monad). data TreeState m = TreeState { cwd :: AnchoredPath hunk ./Storage/Hashed/Monad.hs 44 , tree :: Tree m - -- | Internal. - , changed :: S.Set AnchoredPath - -- | Internal. + , changed :: PathSet , changesize :: Int64 hunk ./Storage/Hashed/Monad.hs 46 - , sync :: TreeMonad m () } + , sync :: PathSet -> TreeMonad m () } -- | A 'TreeIO' monad. A sort of like IO but it keeps a 'TreeState' around as well, -- which is a sort of virtual filesystem. Depending on how you obtained your hunk ./Storage/Hashed/Monad.hs 58 type TreeMonad m = StateT (TreeState m) m type TreeIO = TreeMonad IO -initialState :: Tree m -> TreeMonad m () -> TreeState m +initialState :: Tree m -> (PathSet -> TreeMonad m ()) -> TreeState m initialState t s = TreeState { cwd = AnchoredPath [] , tree = t , changed = S.empty hunk ./Storage/Hashed/Monad.hs 65 , changesize = 0 , sync = s } +flush :: (Monad m) => TreeMonad m () +flush = do + current <- get + modify $ \st -> st { changed = S.empty, changesize = 0, cwd = AnchoredPath [] } + sync current (changed current) + modify $ \st -> st { cwd = cwd current } + runTreeMonad :: (Monad m) => TreeMonad m a -> TreeState m -> m (a, Tree m) runTreeMonad action initial = do (out, final) <- runStateT (do x <- action hunk ./Storage/Hashed/Monad.hs 75 - get >>= sync + flush return x) initial return (out, tree final) hunk ./Storage/Hashed/Monad.hs 83 -- tree mutations just for the purpose of getting the resulting Tree and -- throwing it away. virtualTreeMonad :: (Monad m) => TreeMonad m a -> Tree m -> m (a, Tree m) -virtualTreeMonad action t = runTreeMonad action $ initialState t (return ()) +virtualTreeMonad action t = runTreeMonad action $ initialState t (\_ -> return ()) virtualTreeIO :: TreeIO a -> Tree IO -> IO (a, Tree IO) virtualTreeIO = virtualTreeMonad hunk ./Storage/Hashed/Monad.hs 88 --- | Internal. -replaceItemAbs :: (Monad m) => AnchoredPath -> Maybe (TreeItem m) -> TreeMonad m () -replaceItemAbs path item = - modify $ \st -> st { tree = modifyTree (tree st) path item } - replaceItem :: (Monad m) => AnchoredPath -> Maybe (TreeItem m) -> TreeMonad m () replaceItem path item = modify $ \st -> st { tree = modifyTree (tree st) hunk ./Storage/Hashed/Monad.hs 108 -- ones, so the memory can be GCd). plainTreeIO :: TreeIO a -> Tree IO -> FilePath -> IO (a, Tree IO) plainTreeIO action t dir = runTreeMonad action $ initialState t syncPlain - where syncPlain = do - ch <- gets changed - modify $ \st -> st { changed = S.empty, changesize = 0 } + where syncPlain ch = do current <- gets tree forM_ (S.toList ch) $ \c -> do let path = anchorPath dir c hunk ./Storage/Hashed/Monad.hs 166 do expandTo p replaceItem p (Just blob) markChanged p - maybeSync + maybeFlush where blob = File $ Blob (return con) hash hash = sha256 con hunk ./Storage/Hashed/Monad.hs 190 replaceItem from Nothing -- | If buffers are becoming large, sync, otherwise do nothing. -maybeSync :: (Monad m) => TreeMonad m () -maybeSync = do x <- gets changesize - when (x > 100 * 1024 * 1024) $ get >>= sync +maybeFlush :: (Monad m) => TreeMonad m () +maybeFlush = do x <- gets changesize + when (x > 100 * 1024 * 1024) $ flush changeDirectoryAbs :: (Monad m) => AnchoredPath -> TreeMonad m () changeDirectoryAbs dir = modify (\st -> st { cwd = dir }) [Move plainTreeIO from Monad to Plain. Petr Rockai **20090921195636 Ignore-this: 24a4e05c25a22223043abf19af4b3c42 ] hunk ./Storage/Hashed/Monad.hs 10 -- work as advertised and the monads leak memory. So far, I'm at a loss why -- this happens. module Storage.Hashed.Monad - ( plainTreeIO, virtualTreeIO, virtualTreeMonad + ( virtualTreeIO, virtualTreeMonad , readFile, writeFile, createDirectory, rename, unlink , fileExists, directoryExists, exists, withDirectory , tree, cwd, TreeState, TreeMonad, TreeIO, runTreeMonad hunk ./Storage/Hashed/Monad.hs 101 modify $ \st -> st { tree = t' } _ -> return () --- | Run a 'TreeIO' action in a plain tree setting. Writes out changes to the --- plain tree every now and then (after the action is finished, the last tree --- state is always flushed to disk). XXX Modify the tree with filesystem --- reading and put it back into st (ie. replace the in-memory Blobs with normal --- ones, so the memory can be GCd). -plainTreeIO :: TreeIO a -> Tree IO -> FilePath -> IO (a, Tree IO) -plainTreeIO action t dir = runTreeMonad action $ initialState t syncPlain - where syncPlain ch = do - current <- gets tree - forM_ (S.toList ch) $ \c -> do - let path = anchorPath dir c - case find current c of - Just (File b) -> do - liftIO $ readBlob b >>= BL.writeFile path - let nblob = File $ Blob (BL.readFile path) NoHash - modify $ \st -> st { tree = modifyTree (tree st) c - (Just nblob) } - Just (SubTree _) -> - liftIO $ createDirectoryIfMissing False path - _ -> fail $ "Foo at " ++ path - -- | Check for existence of a file. fileExists :: (MonadError e m) => AnchoredPath -> TreeMonad m Bool fileExists p = do expandTo p hunk ./Storage/Hashed/Plain.hs 16 import Storage.Hashed.Hash( Hash( NoHash) ) import Storage.Hashed.Tree( Tree( listImmediate ), TreeItem(..), ItemType(..) , Blob(..), emptyTree, makeTree, makeTreeWithHash - , list, readBlob, find ) + , list, readBlob, find, modifyTree ) +import Storage.Hashed.Monad( TreeIO, runTreeMonad, initialState, tree ) +import qualified Data.Set as S +import Control.Monad.State( liftIO, gets, modify ) readPlainDir :: FilePath -> IO [(FilePath, FileStatus)] readPlainDir dir = hunk ./Storage/Hashed/Plain.hs 61 createDirectoryIfMissing True (anchorPath dir p) write _ = return () write' p b = readBlob b >>= BL.writeFile (anchorPath dir p) + +-- | Run a 'TreeIO' action in a plain tree setting. Writes out changes to the +-- plain tree every now and then (after the action is finished, the last tree +-- state is always flushed to disk). XXX Modify the tree with filesystem +-- reading and put it back into st (ie. replace the in-memory Blobs with normal +-- ones, so the memory can be GCd). +plainTreeIO :: TreeIO a -> Tree IO -> FilePath -> IO (a, Tree IO) +plainTreeIO action t dir = runTreeMonad action $ initialState t syncPlain + where syncPlain ch = do + current <- gets tree + forM_ (S.toList ch) $ \c -> do + let path = anchorPath dir c + case find current c of + Just (File b) -> do + liftIO $ readBlob b >>= BL.writeFile path + let nblob = File $ Blob (BL.readFile path) NoHash + modify $ \st -> st { tree = modifyTree (tree st) c + (Just nblob) } + Just (SubTree _) -> + liftIO $ createDirectoryIfMissing False path + _ -> fail $ "Foo at " ++ path + [Refactor Monad into two type classes for read and write access, respectively. Petr Rockai **20090923165710 Ignore-this: d441c26569ff1b19df7106c9d0fe301b ] hunk ./Storage/Hashed/Monad.hs 1 -{-# LANGUAGE ScopedTypeVariables, BangPatterns #-} +{-# LANGUAGE ScopedTypeVariables, BangPatterns, TypeSynonymInstances, UndecidableInstances #-} -- | An experimental monadic interface to Tree mutation. The main idea is to -- simulate IO-ish manipulation of real filesystem (that's the state part of hunk ./Storage/Hashed/Monad.hs 58 type TreeMonad m = StateT (TreeState m) m type TreeIO = TreeMonad IO +class (Functor m, Monad m) => TreeRO m where + currentDirectory :: m AnchoredPath + changeDirectory :: AnchoredPath -> m () + withDirectory :: (MonadError e m) => AnchoredPath -> m a -> m a + expandTo :: (MonadError e m) => AnchoredPath -> m () + -- | Grab content of a file in the current Tree at the given path. + readFile :: (MonadError e m) => AnchoredPath -> m BL.ByteString + -- | Check for existence of a node (file or directory, doesn't matter). + exists :: (MonadError e m) => AnchoredPath -> m Bool + -- | Check for existence of a directory. + directoryExists :: (MonadError e m) => AnchoredPath -> m Bool + -- | Check for existence of a file. + fileExists :: (MonadError e m) => AnchoredPath -> m Bool + +class TreeRO m => TreeRW m where + -- | Change content of a file at a given path. The change will be + -- eventually flushed to disk, but might be buffered for some time. + writeFile :: (MonadError e m) => AnchoredPath -> BL.ByteString -> m () + createDirectory :: (MonadError e m) => AnchoredPath -> m () + unlink :: (MonadError e m) => AnchoredPath -> m () + rename :: (MonadError e m) => AnchoredPath -> AnchoredPath -> m () + initialState :: Tree m -> (PathSet -> TreeMonad m ()) -> TreeState m initialState t s = TreeState { cwd = AnchoredPath [] , tree = t hunk ./Storage/Hashed/Monad.hs 115 modify $ \st -> st { tree = modifyTree (tree st) (cwd st `catPaths` path) item } -expandTo :: (Monad m, MonadError e m) => AnchoredPath -> TreeMonad m () -expandTo p = - do t <- gets tree - case find t p of - Nothing -> do t' <- lift $ expandPath t p `catchError` \_ -> return t - modify $ \st -> st { tree = t' } - _ -> return () - --- | Check for existence of a file. -fileExists :: (MonadError e m) => AnchoredPath -> TreeMonad m Bool -fileExists p = do expandTo p - (isJust . (flip findFile p)) `fmap` gets tree - --- | Check for existence of a directory. -directoryExists :: (MonadError e m) => AnchoredPath -> TreeMonad m Bool -directoryExists p = do expandTo p - (isJust . (flip findTree p)) `fmap` gets tree - --- | Check for existence of a node (file or directory, doesn't matter). -exists :: (MonadError e m) => AnchoredPath -> TreeMonad m Bool -exists p = do expandTo p - (isJust . (flip find p)) `fmap` gets tree - --- | Grab content of a file in the current Tree at the given path. -readFile :: (MonadError e m) => AnchoredPath -> TreeMonad m BL.ByteString -readFile p = do expandTo p - t <- gets tree - let f = findFile t p - case f of - Nothing -> fail $ "No such file " ++ show p - Just x -> lift (readBlob x) - -- | Internal. Mark a given path as changed, so the next sync will flush the -- modified object to disk. markChanged :: (Functor m, Monad m) => AnchoredPath -> TreeMonad m () hunk ./Storage/Hashed/Monad.hs 128 where paths = let (AnchoredPath x) = p in S.fromList $ map AnchoredPath $ inits x --- | Change content of a file at a given path. The change will be eventually --- flushed to disk, but might be buffered for some time. -writeFile :: (Functor m, MonadError e m) => AnchoredPath -> BL.ByteString -> TreeMonad m () -writeFile p con = - do expandTo p - replaceItem p (Just blob) - markChanged p - maybeFlush - where blob = File $ Blob (return con) hash - hash = sha256 con - -createDirectory :: (MonadError e m) => AnchoredPath -> TreeMonad m () -createDirectory p = do expandTo p - replaceItem p $ Just $ SubTree emptyTree - -unlink :: (MonadError e m) => AnchoredPath -> TreeMonad m () -unlink p = do expandTo p - replaceItem p Nothing - -rename :: (MonadError e m) => AnchoredPath -> AnchoredPath -> TreeMonad m () -rename from to = do expandTo from - tr <- gets tree - let item = find tr from - found_to = find tr to - unless (isNothing found_to) $ - fail $ "Error renaming: destination " ++ show to ++ " exists." - unless (isNothing item) $ do - replaceItem to item - replaceItem from Nothing - -- | If buffers are becoming large, sync, otherwise do nothing. maybeFlush :: (Monad m) => TreeMonad m () maybeFlush = do x <- gets changesize hunk ./Storage/Hashed/Monad.hs 133 when (x > 100 * 1024 * 1024) $ flush -changeDirectoryAbs :: (Monad m) => AnchoredPath -> TreeMonad m () -changeDirectoryAbs dir = modify (\st -> st { cwd = dir }) +instance (Monad m, MonadError e m) => TreeRO (TreeMonad m) where + expandTo p = + do t <- gets tree + case find t p of + Nothing -> do t' <- lift $ expandPath t p `catchError` \_ -> return t + modify $ \st -> st { tree = t' } + _ -> return () + + fileExists p = + do expandTo p + (isJust . (flip findFile p)) `fmap` gets tree + + directoryExists p = + do expandTo p + (isJust . (flip findTree p)) `fmap` gets tree + + exists p = + do expandTo p + (isJust . (flip find p)) `fmap` gets tree + + readFile p = + do expandTo p + t <- gets tree + let f = findFile t p + case f of + Nothing -> fail $ "No such file " ++ show p + Just x -> lift (readBlob x) + + changeDirectory dir = modify (\st -> st { cwd = cwd st `catPaths` dir }) + currentDirectory = gets cwd + withDirectory dir action = + do old <- currentDirectory + changeDirectory dir + res <- action `catchError` (\e -> changeDirectoryAbs old >> throwError e) + changeDirectoryAbs old + return res hunk ./Storage/Hashed/Monad.hs 170 -changeDirectory :: (Monad m) => AnchoredPath -> TreeMonad m () -changeDirectory dir = modify (\st -> st { cwd = cwd st `catPaths` dir }) +instance (Functor m, Monad m, MonadError e m) => TreeRW (TreeMonad m) where + writeFile p con = + do expandTo p + replaceItem p (Just blob) + markChanged p + maybeFlush + where blob = File $ Blob (return con) hash + hash = sha256 con hunk ./Storage/Hashed/Monad.hs 179 -currentDirectory :: (Monad m) => TreeMonad m AnchoredPath -currentDirectory = gets cwd + createDirectory p = + do expandTo p + replaceItem p $ Just $ SubTree emptyTree + + unlink p = + do expandTo p + replaceItem p Nothing + + rename from to = + do expandTo from + tr <- gets tree + let item = find tr from + found_to = find tr to + unless (isNothing found_to) $ + fail $ "Error renaming: destination " ++ show to ++ " exists." + unless (isNothing item) $ do + replaceItem to item + replaceItem from Nothing + +changeDirectoryAbs :: (Monad m) => AnchoredPath -> TreeMonad m () +changeDirectoryAbs dir = modify (\st -> st { cwd = dir }) hunk ./Storage/Hashed/Monad.hs 201 -withDirectory :: (Monad m, MonadError e m) => AnchoredPath -> TreeMonad m a -> TreeMonad m a -withDirectory dir action = do - old <- currentDirectory - changeDirectory dir - res <- action `catchError` (\e -> changeDirectoryAbs old >> throwError e) - changeDirectoryAbs old - return res Context: [Refactor hashedTreeIO to avoid updateFile code duplication. Petr Rockai **20090912132806 Ignore-this: fd10e3848643786e98c54eda18a92aca ] [Move Hash matching into the Hash module, from Tree/diffTrees. Petr Rockai **20090912132336 Ignore-this: a5b314e6014c4c9b07b873eea0924d11 ] [Provide a global updateIndex instead of giving an index-specific one. Petr Rockai **20090912110451 Ignore-this: 809eebf87932dbf58ebb42a7852e6fd8 ] [Add Plain to the module list in the cabal file. Petr Rockai **20090912103856 Ignore-this: d171ce849ebf285cdac65ad3bb4b03f4 ] [Rename pokeBS to unsafePokeBS. Petr Rockai **20090912103821 Ignore-this: 3cab6762da2ac2909402e60116977234 ] [Rename read to readBlob to avoid an annoying conflict with Prelude. Petr Rockai **20090906180217 Ignore-this: 9375623f3011913a555b9b0d43e445f9 ] [Migrate the plain format code into Storage.Hashed.Plain. Petr Rockai **20090906175843 Ignore-this: f0e9f89affefd030202b928139ce02e5 ] [Code formatting in diffTrees. Petr Rockai **20090906175009 Ignore-this: 2c57932f958ccde49d60bf1bfce8d90b ] [Leave out subtrees that are empty on both sides in diffTrees. Petr Rockai **20090906174817 Ignore-this: 30dc7d256dad5ea2dac1cd44d7dcc55c ] [Move all the darcs-specific bits into Storage.Hashed.Darcs. Petr Rockai **20090906174308 Ignore-this: fc4345281a0f5baf37c45380623620cf ] [Afterall, leaving out empty subtrees in diffTrees was not such a great idea. Petr Rockai **20090811092614 Ignore-this: 652f85cc0f8c3820aa2916a3bf66d77f ] [Implement rudimentary writeDarcsHashed to dump a full Tree. Petr Rockai **20090810220607 Ignore-this: 81c9f9be8926d72900f1ef4cb909861e ] [A little more verbose assertions in unit tests. Petr Rockai **20090810210631 Ignore-this: 7db688f321ac5f3a57489bfa4e9500e1 ] [A little more legible error message. Petr Rockai **20090810210613 Ignore-this: f3e5b0b9f4ced11c4a551765740b8800 ] [One more optimisation and refactoring pass through Index. Petr Rockai **20090810210429 Ignore-this: a63e34e237e58085e951f5d8e3d4235e ] [Make equals_testdata actually check for equality instead of subset. Petr Rockai **20090810210404 Ignore-this: b4c70f567c7fc90b0ad0db2cc8a00c15 ] [Use Maybe in darcsFormatDir and NoHash in darcsTreeHash for failure. Petr Rockai **20090810210159 Ignore-this: 3596feb2c06dbc884377656b943f7ec9 ] [Update the hashes before using them in writePackedDarcsPristine. Petr Rockai **20090810210122 Ignore-this: baa3c39c33ce302bd1a796860548193d ] [Fix up the Packed unit tests. Petr Rockai **20090810205728 Ignore-this: 3455fea6f12e38a55adc58fd6cf8388a ] [Fix the binary search in readPack's _lookup. Petr Rockai **20090810204853 Ignore-this: 95eaf7192fe118f15df590843a823fcb ] [Remove DarcsSHA256 from the Hash type. Petr Rockai **20090810161924 Ignore-this: 894471fde01d60a84aa7eb8be5d0021f ] [Add rawHash :: Hash -> BS.ByteString to Hash. Petr Rockai **20090810144202 Ignore-this: 4a20c4465c719330e546f0af5ed6ada9 ] [Add align :: Integral a => a -> a -> a to Utils (+ QC properties). Petr Rockai **20090810144052 Ignore-this: 1b348aa820f65d07fcc3cfb50c21e5e9 ] [Leave out empty SubTrees out of diffTrees result. Petr Rockai **20090810143756 Ignore-this: 9199ed92c5bb00cecc261e600e71a997 ] [The darcs and nondarcs SHA256s match if the actual hashes match. Petr Rockai **20090810143727 Ignore-this: 85a551d07a23df7ca2b6312b4e2f398 ] [Add an anchoredRoot constant to AnchoredPath module. Petr Rockai **20090810143542 Ignore-this: ef47b6fa9bc3b72dac4b62923cb45c8d ] [Reorder the index testcases to facilitate post-mortem index analysis. Petr Rockai **20090810095224 Ignore-this: 22e4ea81c2ba74308945cd2802666fe9 ] [Note the Index rewrite in NEWS. Petr Rockai **20090809093845 Ignore-this: 480b4ff80461ffbdb0ea3b62205ee1fc ] [Further optimisation of Index (changes layout -> new magic, HSI3). Petr Rockai **20090808221554 Ignore-this: c35be4ffd429cb8f61ebd47d8b144fac ] [Massive rewrite of Index, leading to better, cleaner *and* faster code. Petr Rockai **20090808203916 Ignore-this: 529ccd4f87c8fd9235f5605854b7d166 ] [Rework do_stat to reduce allocations and control flow. Petr Rockai **20090808203836 Ignore-this: 244a94e36f1808e39c7b394d18a87742 ] [Some reasonable primitives to work with current directory in Monad. Petr Rockai **20090807185457 Ignore-this: 6234fc8c56dd26869e2080d32487761e ] [Rework updateTreePostorder to updateSubtrees and updateTree. Petr Rockai **20090807154757 Ignore-this: f800adb575bc6170b2c950acaa79e002 The rework also propagated into darcsUpdateHashes, which is now darcsUpdateDirHashes, and a version that recomputes everything from file content is available as darcsUpdateHashes (lives in IO, unlike the former). ] [Explicit errors in Index on empty paths in Index. Petr Rockai **20090807154710 Ignore-this: c028a206529d621cdafdc8fbbf409f62 ] [Fix size miscalculation in Index introduced in the magic number cleanup. Petr Rockai **20090807154626 Ignore-this: 6d231b476741ecf2715840839bfc0aec ] [Lift filter into a type class and overload it for IndexTree. Petr Rockai **20090807101710 Ignore-this: a47cb96c9c9bb0f3f2578005f11da92b ] [Hide the (dangerous) Tree originating from readIndex in a newtype. Petr Rockai **20090807092216 Ignore-this: 539e3f879394ad616534eeba9bc7aaf3 ] [Generalize the type of restrict a little. Petr Rockai **20090807092204 Ignore-this: a71d124c3a46f5d57988457e87cef761 ] [Civilise usage of magic numbers in Index. Petr Rockai **20090805215350 Ignore-this: c6c879d3fe75a3a061e64fa92691b79b ] [Add makeBlob/makeBlobBS to create blobs from bytestrings conveniently. Petr Rockai **20090805194651 Ignore-this: d5eaa739a462d4f84fd8b54bb8dedae6 ] [Copy-edit the Index haddock a little. Petr Rockai **20090805110628 Ignore-this: 3c2f81760ef59329f5a67314509da5a9 ] [Get rid of finish, and provide expandUpdate instead, and use that in Index. Petr Rockai **20090805104409 Ignore-this: e1f224d36dc47e0abf7282f8270f34f ] [Make x `appendPath` (Name ".") a noop, keeping the AnchoredPath canonical. Petr Rockai **20090805104248 Ignore-this: d3619ff94998dc36da60aebd783af2ee ] [It *may* make some sense to also *run* the Monad test. Petr Rockai **20090803115732 Ignore-this: 4a4ead07ed7a5f1761ebb1696c8e0d0f ] [First trivial testcase for TreeMonad. Petr Rockai **20090803115212 Ignore-this: 95943e6bc0c4ced5dab6a926ac2c5741 ] [Move the Show Tree instance from Tree to Test module. Petr Rockai **20090803115130 Ignore-this: ccb75296b6321db6d8445adf9cdff3c3 ] [Remove name{To,From}FilePath from AnchoredPath module. Petr Rockai **20090803112019 Ignore-this: eed0f7fa612ca37d5ea649a54bb52280 ] [Make the Arbitrary Tree instance also produce Stub nodes. Petr Rockai **20090803102016 Ignore-this: 12bc5e6a0f6807d66c19ac5d4433d0ff ] [Update NEWS with Tree generalisation. Petr Rockai **20090803085725 Ignore-this: 93d541df6812bed50183cfccb32f9271 ] [Also handle the old-style _darcs/current pristine trees. Petr Rockai **20090803084930 Ignore-this: b51949eb58d6197ce940b798647a5be9 ] [Generalise much of the TreeIO interface to work on arbitrary TreeMonad. Petr Rockai **20090803083331 Ignore-this: 9fba7fd044480bbdf00ac38440575691 ] [Rudimentary support for SHA1 hashes (darcs generates those sometimes). Petr Rockai **20090803083315 Ignore-this: 36fa4aae84292b83d2af87f2160f6c3c ] [Complain in readDarcsPristine when the root pointer is bad. Petr Rockai **20090803083300 Ignore-this: 8ba330f24ea0e044b96e7ddf074e3b75 ] [Generalize the TreeIO monad into a monad transformer. Petr Rockai **20090803064950 Ignore-this: 853a0e18356ce6c5db5c6cabf71f3b20 ] [Generalize the Tree datatype over a monad to use. Petr Rockai **20090803064049 Ignore-this: 21e5c270af97bb9efd9c4854ef0ab495 ] [Drop readOrUpgradeIndex (it's been deprecated and we broke API in 0.4). Petr Rockai **20090803063925 Ignore-this: 1c9f7acdf088fd4d1c90e8d4b13874ea ] [Implement lookup functionality for packs. Petr Rockai **20090802095701 Ignore-this: cc522711938c01a571f7ed50efb4985b ] [Fail gracefully in looseLookup for NoHash. Petr Rockai **20090802095642 Ignore-this: 71e263118401d632393ab3e58b149ece ] [Fix collateral from using plain hashes in object storage. (Ow, ugly.) Petr Rockai **20090729160212 Ignore-this: 838c1f112406101ebfe7289f82adc89c ] [Haddock header for Packed. Petr Rockai **20090729153838 Ignore-this: b6aca7836b77e24e6a4d7715f42081ba ] [Rename readOS to load. Petr Rockai **20090729153826 Ignore-this: 434284ba9b9ca31bc00ef593e78ce156 ] [The hatchery cleanup for compact is a removeFile (for now, anyway). Petr Rockai **20090729153745 Ignore-this: d2c90e56ad321890baaa7870956028fb ] [Use "plain" hashes in Packed (instead of the size-carrying darcs ones). Petr Rockai **20090729153641 Ignore-this: 5da05603badc65bfeed86c3700b415e9 ] [Move the darcs-specific packing bits into Darcs. Petr Rockai **20090729153506 Ignore-this: eb293efdff697d9e9415d0818dc0821b ] [Bundle NEWS in source distribution. Petr Rockai **20090727110112 Ignore-this: 4f4ecf107932b2f2816bba0a81d6e162 ] [Add a NEWS file. Petr Rockai **20090727110029 Ignore-this: ef7ef49e9ea40cd47b9b7524f7185ead ] [Sprinkle a few haddocks around the Hash module. Petr Rockai **20090727104019 Ignore-this: c346d03f95d85e5a8bdd32b3f17af17 ] [Add a generic sha256 function to the Hash module. Petr Rockai **20090727103944 Ignore-this: 8acce5572552abf91fb8d4e5e30d86b5 ] [We can now base64/url-encode (and decode) all Hash types. Petr Rockai **20090727103856 Ignore-this: d489776258887d165c82ac2cacf6a281 ] [Bump version to 0.4.0. Petr Rockai **20090726133807 Ignore-this: c2584a9b9b408eb235c72333c3df4de4 ] [Refactor Hash datatypes extensively. Petr Rockai **20090726105657 Ignore-this: feee380e33489b5665a90c6de57cba04 ] [Do not forget to update hashes before syncing a hashed tree in Monad. Petr Rockai **20090726105625 Ignore-this: 5a0c870b6feceb6934013febb9042ddd ] [Avoid calling expandPath when not needed, in Monad. Petr Rockai **20090726105114 Ignore-this: ed206ac93dec1e4316e6dc1268c90c89 ] [Do not forget to reset changesize in Monad, upon sync. Petr Rockai **20090726105044 Ignore-this: cf6a9050f80be464545da7a799afb76b ] [Move floatPath into the AnchoredPath module. Petr Rockai **20090726103839 Ignore-this: 69167d23ff427fb43c1ff01596be1c0d ] [Do not include _darcs/index in the testdata. Petr Rockai **20090726093249 Ignore-this: e83640b403b599c8983d9df1987578e5 ] [Avoid removing an in-use file on win32. Petr Rockai **20090720105955 Ignore-this: b6924f7a5b412209db789fb24cfbb925 ] [Minor formatting fix. Petr Rockai **20090720091307 Ignore-this: 76e931c3f1da94edcaa63d0bb3f164e5 ] [Do not remove associated Tree hashes in filter. Petr Rockai **20090720091233 Ignore-this: 7e56d31ea8a26524d98fb687daa7de36 ] [Do not fail when a nonexistent file is marked as changed in Monad. Petr Rockai **20090720091205 Ignore-this: 8476cfd6f6e7a850a08d1a4b3fff0d3e ] [A rudimentary implementation of createPack (which in turn enables compaction). Petr Rockai **20090719112607 Ignore-this: e7c1250a5729d2afc3fb5d55e02596ea ] [Use readOS after create to populate the in-memory structure. Petr Rockai **20090719112321 Ignore-this: 67cc381cef32999e4ab7ccd5878b13a9 ] [More complete OS field initialisation (although dummy so far). Petr Rockai **20090719112126 Ignore-this: 49dc472a66b0a9b10e237313b07c0e5d ] [Implement post-compaction cleanup for loose hatcheries. Petr Rockai **20090719112024 Ignore-this: d0d2dd42cfd80a25487458cd7b6ea91c ] [More utilities for darcs hashed trees embedded in an object storage. Petr Rockai **20090719111812 Ignore-this: 212e62ff97aa08c2cd743533caf3e934 ] [Add a function to postorder-traverse and update a Tree. Petr Rockai **20090719111705 Ignore-this: 7ea52eec3035bdf374a52fdebd5e78f1 ] [Test live object collection for darcs pristine trees. Petr Rockai **20090718142606 Ignore-this: a2271fa9ca1b113958548719da3de302 ] [Implement rudimentary darcsPristineRefs (for chasing references). Petr Rockai **20090718142530 Ignore-this: 735e6e62a46534c9c52d14873544a82 ] [Obliterate embarassingly useless iterateM and fix mfixFrom (IO is too strict...). Petr Rockai **20090718134928 Ignore-this: 5263adba06aea23c6aea678a218bbaa8 ] [Also cover the items part of the expandPath-produced Tree. Petr Rockai **20090718122147 Ignore-this: 21ec9284edfdb7b12ca36945acb94df2 ] [Expand the expandPath testcase to cover more possibilities. Petr Rockai **20090718121919 Ignore-this: 848fad8e119e478f6eba73ecf29967f2 ] [Add another QC property for restrict. Petr Rockai **20090718120547 Ignore-this: 69254e4672d0dd8f0b8c0c62172d7501 ] [Add a simple QC property for restrict. Petr Rockai **20090718120136 Ignore-this: da90db5c53a240b30fb422ead6ee8dcd ] [Add a testcase for writePlainTree. Petr Rockai **20090718120120 Ignore-this: 153f8a16f774b48e870f635fae0747e2 ] [Add a small testcase for diffTree of identical trees. Petr Rockai **20090718114836 Ignore-this: 47e75079074babbee32089b2f603e837 ] [Add a testcase for readOS. Petr Rockai **20090718080127 Ignore-this: 9fd7da5338959f3368c8e28b5f7b8361 ] [Improve haddock. Petr Rockai **20090718074618 Ignore-this: edc4620e92e9d2705ccb9cd40e04014d ] [In hatch, discard objects that are already in the storage. Petr Rockai **20090718064454 Ignore-this: b78f8b721d54b4172cef525300fd18b0 ] [Clean up the interface implementing darcs hashed trees in object storage. Petr Rockai **20090718064053 Ignore-this: f34dcf63e8b5b51cf1c7ce059e694a4a ] [Add an example-style testcase for reachable. Petr Rockai **20090717213045 Ignore-this: fd401588b70cc6fb3095b2e8014969d5 ] [Rudimentary testcase for creating and using object stores. Petr Rockai **20090717211857 Ignore-this: f7c5398520299a826627d16e1c0fee0e ] [Factor out a "equals_testdata" for checking tree contents (in Test). Petr Rockai **20090717211815 Ignore-this: 507af4cb2656b7fb510ac0d684101503 ] [Add readPackedDarcsPristine to Packed (mostly for testing purposes). Petr Rockai **20090717211734 Ignore-this: af9ee256dd14529ce4e8eeb04948244f ] [More work on creating and reading object stores. Petr Rockai **20090717211637 Ignore-this: 86ff4fbb2053b3eeee28d9716d43eed3 ] [Implement rudimentary blockLookup for Loose hatchery. Petr Rockai **20090717204802 Ignore-this: d9cbf06cf570d0cda9f717452112351 ] [Factor darcsParseDir out of readDarcsHashedDir. Petr Rockai **20090717202842 Ignore-this: 6d6d4ef52de60d3873c950f768836c04 ] [Further work on Packed: implement creation and hatching for Loose hatchery. Petr Rockai **20090717191555 Ignore-this: 317020a0295a8a6a02c8fc2d645ceeb4 ] [Improve the modifyTree testcases slightly. Petr Rockai **20090717110252 Ignore-this: fa02c59b1ccd33f102bc0ffb7d56fb45 ] [A basic testcase for diffTrees. Petr Rockai **20090717105531 Ignore-this: e1d60229e1e5d0765151f9047efddaf6 ] [Minor tidying of the Test module. Petr Rockai **20090717105502 Ignore-this: 7b2cdb9033bcbbbaeceabd74bfa6f987 ] [Add a testcase for modifyTree used for removal (with Nothing passed). Petr Rockai **20090717093808 Ignore-this: ea04c000d6a51291c227f1f8d6088198 ] [Check plain tree contents in addition to pristine. Petr Rockai **20090717092400 Ignore-this: 595ffe003bf130cb1146cbef43b372b1 ] [Add some bad and ugly filenames to the test data. Petr Rockai **20090717092309 Ignore-this: 48345c1b17e3abecf1aee6fa85c6fcbc ] [Add a check that mmaping empty file works. Petr Rockai **20090717090736 Ignore-this: 6794afd67986fd0671dbe8d19043f361 ] [More prototyping in Packed. Petr Rockai **20090717090015 Ignore-this: 1d88b270b1a026c20f975aee4c07965 ] [Also derive Ord for Hash. Petr Rockai **20090717085420 Ignore-this: d589c4955d98eb9cb74497909499bdd7 ] [One more QC property for "reachable". Petr Rockai **20090717085414 Ignore-this: a8c79180bfb2119d3fca7962a6352997 ] [Haddock the new utility functions. Petr Rockai **20090717084721 Ignore-this: 3c35b527e4c6257170e97fa2d155ec2e ] [Add "reachable" to Utils (comes with a pair of QC properties). Petr Rockai **20090717084039 Ignore-this: fc382efe1a45f1f8a83ae680cbe09762 ] [Add iterateM and (m)fixFrom to Utils (comes with QC and unit test respectively). Petr Rockai **20090717083832 Ignore-this: f89cc289429d6b083d4689de924be96c ] [Fix QC tests to start with prop_, while unit tests start with check_. Petr Rockai **20090717072906 Ignore-this: 186bd59b68a1663e2d77b93fc6fb7805 ] [Reorder test groups. Petr Rockai **20090717072750 Ignore-this: f283f492572d190325f2bfe0aab3081e ] [Haskell *still* can't read my mind. Make Packed compile (and expose it). Petr Rockai **20090716145814 Ignore-this: 145c24365cbc85e694f4f0ccede1ae18 ] [Haddock tweaks. Petr Rockai **20090716133029 Ignore-this: 20b10acfec2a27b8474530c1773abcbd ] [Start out on Storage.Hashed.Packed (for a lack of better name). Petr Rockai **20090716132928 Ignore-this: efafa1902d1ce81783bca0288f2c3fdc ] [Avoid unused import warning in Utils. Petr Rockai **20090716092806 Ignore-this: 93066d561b3d3386122b750a3b4f2b02 ] [Import Bundled.Posix qualified in Test to avoid future name clashes. Petr Rockai **20090716092725 Ignore-this: 13e791dc204cb9f7d832d3a4bc9e71a ] [Refuse to overwrite files in TreeIO rename (darcs relies on this). Petr Rockai **20090716092614 Ignore-this: c310e227b908966c4741749560cab763 ] [Properly encode whitespace in darcsFormatDir. Petr Rockai **20090716092558 Ignore-this: 7a34077e58c2b00349ff3e8ee1ca60e9 ] [TAG 0.3.6 Petr Rockai **20090715083250 Ignore-this: bbb4baadcd63b785b5c061a8037beaa1 ] Patch bundle hash: 11e7f0acce51a0c46167c90ceef6de86f5a393d4