1 {-# OPTIONS_GHC -cpp #-}
4 -- Copyright (C) 2003-2004 Jan Scheffczyk and David Roundy
6 -- This program is free software; you can redistribute it and/or modify
7 -- it under the terms of the GNU General Public License as published by
8 -- the Free Software Foundation; either version 2, or (at your option)
11 -- This program is distributed in the hope that it will be useful,
12 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
13 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 -- GNU General Public License for more details.
16 -- You should have received a copy of the GNU General Public License
17 -- along with this program; see the file COPYING. If not, write to
18 -- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 -- Boston, MA 02110-1301, USA.
23 module Darcs
.Population
( Population
, patchChanges
, applyToPop
,
27 getRepoPop
, getRepoPopVersion
,
29 lookup_pop
, lookup_creation_pop
,
32 import qualified Data
.ByteString
.Char8
as BC
( unpack
, singleton
, pack
)
33 import Data
.Maybe ( catMaybes )
34 import Darcs
.Utils
( withCurrentDirectory
)
36 import Darcs
.Hopefully
( PatchInfoAnd
, hopefully
, info
)
37 import Darcs
.Patch
.FileName
( fn2fp
, fp2fn
, fn2ps
, norm_path
)
38 import Darcs
.Patch
( RepoPatch
, applyToPop
, patchcontents
, patchChanges
,
40 import Darcs
.Ordered
( FL
(..), RL
(..), reverseRL
, concatRL
, mapRL
)
41 import Darcs
.Patch
.Info
( PatchInfo
, idpatchinfo
, to_xml
)
42 import Darcs
.Patch
.Set
( PatchSet
)
43 import Darcs
.Sealed
( Sealed
(..), seal
, unseal
)
44 import Darcs
.Repository
( withRepositoryDirectory
, ($-), read_repo
)
45 import Darcs
.Repository
.Pristine
( identifyPristine
, getPristinePop
)
46 import Darcs
.PopulationData
( Population
(..), PopTree
(..), Info
(..), DirMark
(..),
47 setPopState
, getPopFrom
)
48 import Printer
( empty, text
, ($$), (<>), Doc
)
49 import Control
.Monad
( liftM )
51 #include
"impossible.h"
53 -- | population of an empty repository
55 initPop
= Pop idpatchinfo
(PopDir i
[])
56 where i
= Info
{nameI
= BC
.singleton
'.',
57 modifiedByI
= idpatchinfo
,
58 modifiedHowI
= DullDir
,
60 creationNameI
= Just
(BC
.singleton
'.')}
62 -- | apply a patchset to a population
63 applyPatchSetPop
:: RepoPatch p
=> PatchSet p C
(x
) -> Population
-> Population
64 applyPatchSetPop ps pop
= applyPatchesPop
(reverseRL
$ concatRL ps
) pop
66 -- | apply Patches to a population
67 applyPatchesPop
:: Effect p
=> FL
(PatchInfoAnd p
) C
(x y
) -> Population
-> Population
68 applyPatchesPop NilFL
= id
69 applyPatchesPop
(hp
:>:hps
) = applyPatchesPop hps
.
70 applyToPop
(info hp
) (effect
$ patchcontents
$ hopefully hp
)
71 -- | get the pristine population from a repo
72 getRepoPop
:: FilePath -> IO Population
73 getRepoPop repobasedir
74 = withRepositoryDirectory
[] repobasedir
$- \repository
-> do
75 pinfo
<- (head . mapRL info
. concatRL
) `
liftM` read_repo repository
76 -- pinfo is the latest patchinfo
77 mp
<- withCurrentDirectory repobasedir
$
78 identifyPristine
>>= getPristinePop pinfo
80 (Just pop
) -> return pop
81 (Nothing
) -> getRepoPopVersion repobasedir pinfo
83 getRepoPopVersion
:: FilePath -> PatchInfo
-> IO Population
84 getRepoPopVersion repobasedir pinfo
= withRepositoryDirectory
[] repobasedir
$- \repository
->
85 do pips
<- concatRL `
liftM` read_repo repository
86 return $ (unseal applyPatchSetPop
) (mkPatchSet
$ dropWhileRL
((/=pinfo
).info
) pips
) initPop
87 where mkPatchSet
(Sealed xs
) = seal
$ xs
:<: NilRL
88 dropWhileRL
:: (FORALL
(x y
) a C
(x y
) -> Bool) -> RL a C
(r v
) -> Sealed
(RL a C
(r
))
89 dropWhileRL _ NilRL
= seal NilRL
90 dropWhileRL p xs
@(x
:<:xs
')
91 | p x
= dropWhileRL p xs
'
94 -- Routines for pulling data conveniently out of a Population
96 lookup_pop
:: FilePath -> Population
-> Maybe Population
97 lookup_pop f p
= lookup_pop
' (BC
.unpack
$ fn2ps
$ fp2fn f
) p
99 lookup_pop
' :: String -> Population
-> Maybe Population
100 lookup_pop
' f p
@(Pop _
(PopFile i
))
101 | BC
.unpack
(nameI i
) == f
= Just p
102 |
otherwise = Nothing
103 lookup_pop
' d p
@(Pop pinfo
(PopDir i c
))
104 | BC
.unpack
(nameI i
) == "." =
105 case catMaybes $ map (lookup_pop
' (dropDS d
).(Pop pinfo
)) c
of
109 | BC
.unpack
(nameI i
) == takeWhile (/='/') d
=
110 case dropWhile (=='/') $ dropWhile (/='/') d
of
112 d
' -> case catMaybes $ map (lookup_pop
' d
'.(Pop pinfo
)) c
of
116 |
otherwise = Nothing
117 where dropDS
('.':'/':f
) = dropDS f
120 lookup_creation_pop
:: PatchInfo
-> FilePath -> Population
-> Maybe Population
121 lookup_creation_pop pinfo f p
= lookup_creation_pop
' pinfo
(BC
.unpack
$ fn2ps
$ fp2fn f
) p
123 lookup_creation_pop
' :: PatchInfo
-> String -> Population
-> Maybe Population
124 lookup_creation_pop
' b a
(Pop pinfo pp
) = (Pop pinfo
) `
fmap` lcp pp
125 where lcp p
@(PopFile i
)
126 | fixname `
fmap` creationNameI i
== f
&& createdByI i
== who
= Just p
127 |
otherwise = Nothing
129 | fixname `
fmap` creationNameI i
== f
&& createdByI i
== who
= Just p
130 |
otherwise = case catMaybes $ map lcp c
of
133 fixname
= BC
.pack
. fn2fp
. norm_path
. fp2fn
. BC
.unpack
134 f
= Just
$ BC
.pack
$ fn2fp
$ norm_path
$ fp2fn a
137 modified_to_xml
:: Info
-> Doc
138 modified_to_xml i | modifiedHowI i
== DullDir
= empty
139 | modifiedHowI i
== DullFile
= empty
140 modified_to_xml i
= text
"<modified>"
141 $$ text
"<modified_how>" <> text
(show (modifiedHowI i
)) <>
142 text
"</modified_how>"
143 $$ to_xml
(modifiedByI i
)
144 $$ text
"</modified>"