-- Copyright (C) 2006-2007 David Roundy -- -- 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; if not, write to the Free Software Foundation, -- Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. module Darcs.Repository.InternalTypes ( Repository , PristineType(..) , AccessType(..) , SAccessType(..) , repoAccessType , repoCache , modifyCache , repoFormat , modifyRepoFormat , repoLocation , withRepoDir , repoPristineType , unsafeCoerceRepoType , unsafeCoercePatchType , unsafeCoerceR , unsafeCoerceU , unsafeEndTransaction , unsafeStartTransaction , mkRepo ) where import Darcs.Prelude import Darcs.Util.Cache ( Cache ) import Darcs.Repository.Format ( RepoFormat, unsafeWriteRepoFormat ) import Darcs.Repository.Paths ( formatPath ) import Darcs.Util.Path ( AbsoluteOrRemotePath, toPath ) import System.Directory ( withCurrentDirectory ) import Unsafe.Coerce ( unsafeCoerce ) data PristineType = NoPristine | PlainPristine | HashedPristine deriving ( Show, Eq ) data AccessType = RO | RW deriving (Eq) data SAccessType (rt :: AccessType) where SRO :: SAccessType 'RO SRW :: SAccessType 'RW -- |A @Repository@ is a token representing the state of a repository on disk. -- It is parameterized by -- -- [@rt@] the access type (whether we are in a transaction or not), -- [@p@] the patch type, -- [@wU@] the witness for the unrecorded state (what's in the working tree now). -- [@wR@] the witness for -- -- * the recorded state when outside a transaction, or -- * the tentative state when inside a transaction. data Repository (rt :: AccessType) (p :: * -> * -> *) wU wR = Repo !String !RepoFormat !PristineType Cache (SAccessType rt) type role Repository nominal nominal nominal nominal repoLocation :: Repository rt p wU wR -> String repoLocation (Repo loc _ _ _ _) = loc -- | Perform an action with the current working directory set to the -- 'repoLocation'. withRepoDir :: Repository rt p wU wR -> IO a -> IO a withRepoDir repo = withCurrentDirectory (repoLocation repo) repoFormat :: Repository rt p wU wR -> RepoFormat repoFormat (Repo _ fmt _ _ _) = fmt repoPristineType :: Repository rt p wU wR -> PristineType repoPristineType (Repo _ _ pr _ _) = pr repoCache :: Repository rt p wU wR -> Cache repoCache (Repo _ _ _ c _) = c modifyCache :: (Cache -> Cache) -> Repository rt p wU wR -> Repository rt p wU wR modifyCache g (Repo l f p c a) = Repo l f p (g c) a repoAccessType :: Repository rt p wU wR -> SAccessType rt repoAccessType (Repo _ _ _ _ s) = s unsafeCoerceRepoType :: Repository rt p wU wR -> Repository rt' p wU wR unsafeCoerceRepoType = unsafeCoerce unsafeCoercePatchType :: Repository rt p wU wR -> Repository rt p' wU wR unsafeCoercePatchType = unsafeCoerce unsafeCoerceR :: Repository rt p wU wR -> Repository rt p wU wR' unsafeCoerceR = unsafeCoerce unsafeCoerceU :: Repository rt p wU wR -> Repository rt p wU' wR unsafeCoerceU = unsafeCoerce -- | Both 'unsafeStartTransaction' and 'unsafeEndTransaction' are "unsafe" in -- the sense that they merely "coerce" the type but do not actually perform the -- steps ('IO' actions) required to start or end a transaction (this is done by -- 'revertRepositoryChanges' and 'finalizeRepositoryChanges'). Technically this -- is not an actual coercion like with e.g. 'unsafeCoerceR', due to the -- singleton typed member, but in practical terms it is no less unsafe, because -- 'RO' vs. 'RW' changes whether @wR@ refers to the recorded or the tentative -- state, respectively. In particular, you will get different results if you -- are inside a transaction and read the patchset with a "coerced" Repository -- of access type 'RO. The same holds for other state that is modified in a -- transaction, like the pending patch or the rebase state. unsafeStartTransaction :: Repository 'RO p wU wR -> Repository 'RW p wU wR unsafeStartTransaction (Repo l f p c SRO) = Repo l f p c SRW unsafeEndTransaction :: Repository 'RW p wU wR -> Repository 'RO p wU wR unsafeEndTransaction (Repo l f p c SRW) = Repo l f p c SRO mkRepo :: AbsoluteOrRemotePath -> RepoFormat -> PristineType -> Cache -> Repository 'RO p wU wR mkRepo p f pr c = Repo (toPath p) f pr c SRO modifyRepoFormat :: (RepoFormat -> RepoFormat) -> Repository 'RW p wU wR -> IO (Repository 'RW p wU wR) modifyRepoFormat f (Repo l fmt p c a) = do let fmt' = f fmt unsafeWriteRepoFormat fmt' formatPath return $ Repo l fmt' p c a