1 {-# LANGUAGE DeriveGeneric #-}
4 -- Module: Distribution.Simple.FileMonitor.Types
6 -- Types for monitoring files and directories.
7 module Distribution
.Simple
.FileMonitor
.Types
8 ( -- * Globs with respect to a root
14 , MonitorFilePath
(..)
15 , MonitorKindFile
(..)
18 -- ** Utility constructors of t'MonitorFilePath'
21 , monitorNonExistentFile
22 , monitorFileExistence
24 , monitorNonExistentDirectory
25 , monitorDirectoryExistence
26 , monitorFileOrDirectory
28 , monitorFileGlobExistence
29 , monitorFileSearchPath
30 , monitorFileHashedSearchPath
34 import Distribution
.Compat
.Prelude
35 import Distribution
.Simple
.Glob
.Internal
39 import qualified Distribution
.Compat
.CharParsing
as P
40 import Distribution
.Parsec
41 import Distribution
.Pretty
42 import qualified Text
.PrettyPrint
as Disp
44 --------------------------------------------------------------------------------
48 -- | A file path specified by globbing, relative
49 -- to some root directory.
53 -- ^ what the glob is relative to
56 deriving (Eq
, Show, Generic
)
58 instance Binary RootedGlob
59 instance Structured RootedGlob
63 |
-- | e.g. @"/"@, @"c:\"@ or result of 'takeDrive'
66 deriving (Eq
, Show, Generic
)
68 instance Binary FilePathRoot
69 instance Structured FilePathRoot
71 ------------------------------------------------------------------------------
72 -- Types for specifying files to monitor
75 -- | A description of a file (or set of files) to monitor for changes.
77 -- Where file paths are relative they are relative to a common directory
78 -- (e.g. project root), not necessarily the process current directory.
81 { monitorKindFile
:: !MonitorKindFile
82 , monitorKindDir
:: !MonitorKindDir
83 , monitorPath
:: !FilePath
86 { monitorKindFile
:: !MonitorKindFile
87 , monitorKindDir
:: !MonitorKindDir
88 , monitorPathGlob
:: !RootedGlob
90 deriving (Eq
, Show, Generic
)
97 deriving (Eq
, Show, Generic
)
103 deriving (Eq
, Show, Generic
)
105 instance Binary MonitorFilePath
106 instance Binary MonitorKindFile
107 instance Binary MonitorKindDir
109 instance Structured MonitorFilePath
110 instance Structured MonitorKindFile
111 instance Structured MonitorKindDir
113 -- | Monitor a single file for changes, based on its modification time.
114 -- The monitored file is considered to have changed if it no longer
115 -- exists or if its modification time has changed.
116 monitorFile
:: FilePath -> MonitorFilePath
117 monitorFile
= MonitorFile FileModTime DirNotExists
119 -- | Monitor a single file for changes, based on its modification time
120 -- and content hash. The monitored file is considered to have changed if
121 -- it no longer exists or if its modification time and content hash have
123 monitorFileHashed
:: FilePath -> MonitorFilePath
124 monitorFileHashed
= MonitorFile FileHashed DirNotExists
126 -- | Monitor a single non-existent file for changes. The monitored file
127 -- is considered to have changed if it exists.
128 monitorNonExistentFile
:: FilePath -> MonitorFilePath
129 monitorNonExistentFile
= MonitorFile FileNotExists DirNotExists
131 -- | Monitor a single file for existence only. The monitored file is
132 -- considered to have changed if it no longer exists.
133 monitorFileExistence
:: FilePath -> MonitorFilePath
134 monitorFileExistence
= MonitorFile FileExists DirNotExists
136 -- | Monitor a single directory for changes, based on its modification
137 -- time. The monitored directory is considered to have changed if it no
138 -- longer exists or if its modification time has changed.
139 monitorDirectory
:: FilePath -> MonitorFilePath
140 monitorDirectory
= MonitorFile FileNotExists DirModTime
142 -- | Monitor a single non-existent directory for changes. The monitored
143 -- directory is considered to have changed if it exists.
144 monitorNonExistentDirectory
:: FilePath -> MonitorFilePath
145 -- Just an alias for monitorNonExistentFile, since you can't
146 -- tell the difference between a non-existent directory and
147 -- a non-existent file :)
148 monitorNonExistentDirectory
= monitorNonExistentFile
150 -- | Monitor a single directory for existence. The monitored directory is
151 -- considered to have changed only if it no longer exists.
152 monitorDirectoryExistence
:: FilePath -> MonitorFilePath
153 monitorDirectoryExistence
= MonitorFile FileNotExists DirExists
155 -- | Monitor a single file or directory for changes, based on its modification
156 -- time. The monitored file is considered to have changed if it no longer
157 -- exists or if its modification time has changed.
158 monitorFileOrDirectory
:: FilePath -> MonitorFilePath
159 monitorFileOrDirectory
= MonitorFile FileModTime DirModTime
161 -- | Monitor a set of files (or directories) identified by a file glob.
162 -- The monitored glob is considered to have changed if the set of files
163 -- matching the glob changes (i.e. creations or deletions), or for files if the
164 -- modification time and content hash of any matching file has changed.
165 monitorFileGlob
:: RootedGlob
-> MonitorFilePath
166 monitorFileGlob
= MonitorFileGlob FileHashed DirExists
168 -- | Monitor a set of files (or directories) identified by a file glob for
169 -- existence only. The monitored glob is considered to have changed if the set
170 -- of files matching the glob changes (i.e. creations or deletions).
171 monitorFileGlobExistence
:: RootedGlob
-> MonitorFilePath
172 monitorFileGlobExistence
= MonitorFileGlob FileExists DirExists
174 -- | Creates a list of files to monitor when you search for a file which
175 -- unsuccessfully looked in @notFoundAtPaths@ before finding it at
177 monitorFileSearchPath
:: [FilePath] -> FilePath -> [MonitorFilePath
]
178 monitorFileSearchPath notFoundAtPaths foundAtPath
=
179 monitorFile foundAtPath
180 : map monitorNonExistentFile notFoundAtPaths
182 -- | Similar to 'monitorFileSearchPath', but also instructs us to
183 -- monitor the hash of the found file.
184 monitorFileHashedSearchPath
:: [FilePath] -> FilePath -> [MonitorFilePath
]
185 monitorFileHashedSearchPath notFoundAtPaths foundAtPath
=
186 monitorFileHashed foundAtPath
187 : map monitorNonExistentFile notFoundAtPaths
189 ------------------------------------------------------------------------------
190 -- Parsing & pretty-printing
193 instance Pretty RootedGlob
where
194 pretty
(RootedGlob root pathglob
) = pretty root Disp
.<> pretty pathglob
196 instance Parsec RootedGlob
where
200 FilePathRelative
-> RootedGlob root
<$> parsec
201 _
-> RootedGlob root
<$> parsec
<|
> pure
(RootedGlob root GlobDirTrailing
)
203 instance Pretty FilePathRoot
where
204 pretty FilePathRelative
= Disp
.empty
205 pretty
(FilePathRoot root
) = Disp
.text root
206 pretty FilePathHomeDir
= Disp
.char
'~
' Disp
.<> Disp
.char
'/'
208 instance Parsec FilePathRoot
where
209 parsec
= root
<|
> P
.try home
<|
> P
.try drive
<|
> pure FilePathRelative
211 root
= FilePathRoot
"/" <$ P
.char
'/'
212 home
= FilePathHomeDir
<$ P
.string "~/"
214 dr
<- P
.satisfy
$ \c
-> (c
>= 'a
' && c
<= 'z
') ||
(c
>= 'A
' && c
<= 'Z
')
216 _
<- P
.char
'/' <|
> P
.char
'\\'
217 return (FilePathRoot
(toUpper dr
: ":\\"))