2 | import public Control.Monad.Either
3 | import Pack.Config.Environment.Variable
4 | import Pack.Config.Types
5 | import Pack.Core.Logging
6 | import Pack.Core.Types
8 | import System.Directory
18 | mapMaybeM : Monad m => (a -> m (Maybe b)) -> List a -> m (List b)
19 | mapMaybeM f [] = pure []
20 | mapMaybeM f (x :: xs) = do
21 | Just vb <- f x | Nothing => mapMaybeM f xs
22 | (vb ::) <$> mapMaybeM f xs
25 | filterM : Monad m => (a -> m Bool) -> List a -> m (List a)
26 | filterM f [] = pure []
27 | filterM f (x :: xs) = do
28 | True <- f x | False => filterM f xs
29 | (x ::) <$> filterM f xs
32 | ignoreError : Monad m => EitherT err m () -> m ()
33 | ignoreError = ignore . runEitherT
40 | -> (toErr : err -> PackErr)
41 | -> (act : io (Either err a))
42 | -> EitherT PackErr io a
43 | eitherIO toErr = MkEitherT . map (mapFst toErr)
50 | -> (cleanup : EitherT err m ())
51 | -> (act : EitherT err m a)
53 | finally cleanup act = MkEitherT $
do
54 | res <- runEitherT act
60 | run : EitherT PackErr IO () -> IO ()
61 | run (MkEitherT io) = io >>= either fatal pure
70 | dispEnv : List EnvVar -> String
71 | dispEnv = unwords . map interpolate
75 | sys : HasIO io => (cmd : CmdArgList) -> EitherT PackErr io ()
77 | 0 <- system $
escapeCmd cmd | n => throwE (Sys cmd n)
82 | -> {auto ref : LogRef}
86 | logCmdOutput lvl msg =
87 | when (msg /= "") $
log ref lvl msg
89 | lineBufferedCmd : Env => CmdArgList -> CmdArgList
90 | lineBufferedCmd args = lineBufferingCmd %search ++ args
98 | -> (cmd : CmdArgList)
99 | -> EitherT PackErr io ()
100 | sysAndLog lvl cmd = do
101 | 0 <- runProcessingOutput
103 | (escapeCmd $
lineBufferedCmd cmd)
104 | | n => throwE (Sys cmd n)
107 | cmdWithEnv : CmdArgList -> List EnvVar -> String
108 | cmdWithEnv cmd [] = escapeCmd cmd
109 | cmdWithEnv cmd env = "\{dispEnv env} \{escapeCmd cmd}"
121 | {auto _ : HasIO io}
122 | -> (cmd : CmdArgList)
123 | -> (env : List EnvVar)
124 | -> EitherT PackErr io ()
125 | sysWithEnv cmd env = do
126 | 0 <- system (cmdWithEnv cmd env) | n => throwE (Sys cmd n)
131 | {auto _ : HasIO io}
133 | -> (lvl : LogLevel)
134 | -> (cmd : CmdArgList)
135 | -> (env : List EnvVar)
136 | -> EitherT PackErr io ()
137 | sysWithEnvAndLog lvl cmd env = do
138 | 0 <- runProcessingOutput
140 | (cmdWithEnv (lineBufferedCmd cmd) env)
141 | | n => throwE (Sys cmd n)
146 | sysRun : HasIO io => (cmd : CmdArgList) -> EitherT PackErr io String
148 | (res,0) <- run (escapeCmd cmd) | (_,n) => throwE (Sys cmd n)
161 | {auto _ : HasIO io}
162 | -> (cmd : CmdArgList)
163 | -> (env : List EnvVar)
164 | -> EitherT PackErr io String
165 | sysRunWithEnv cmd env = do
166 | (res,0) <- System.run (cmdWithEnv cmd env) | (_,n) => throwE (Sys cmd n)
175 | exists : HasIO io => (dir : Path Abs) -> io Bool
176 | exists = exists . interpolate
180 | fileExists : HasIO io => (f : File Abs) -> io Bool
181 | fileExists = exists . interpolate
185 | missing : HasIO io => (dir : Path Abs) -> io Bool
186 | missing = map not . exists
190 | fileMissing : HasIO io => (f : File Abs) -> io Bool
191 | fileMissing = map not . fileExists
195 | mkDir : HasIO io => (dir : Path Abs) -> EitherT PackErr io ()
196 | mkDir (PAbs _ [<]) = pure ()
197 | mkDir d = sys ["mkdir", "-p", d]
201 | mkParentDir : HasIO io => (p : Path Abs) -> EitherT PackErr io ()
202 | mkParentDir p = whenJust (parentDir p) mkDir
206 | rmDir : HasIO io => (dir : Path Abs) -> EitherT PackErr io ()
207 | rmDir dir = when !(exists dir) $
sys ["rm", "-rf", dir]
211 | curDir : HasIO io => EitherT PackErr io (Path Abs)
213 | Just s <- currentDir | Nothing => throwE NoCurDir
214 | case the FilePath (fromString s) of
215 | FP (PAbs u sx) => pure (PAbs u sx)
216 | FP (PRel _) => throwE NoCurDir
220 | chgDir : HasIO io => (dir : Path Abs) -> EitherT PackErr io ()
222 | True <- changeDir "\{dir}" | False => throwE (ChangeDir dir)
229 | {auto _ : HasIO io}
230 | -> (dir : Path Abs)
231 | -> (act : Path Abs -> EitherT PackErr io a)
232 | -> EitherT PackErr io a
234 | curDir >>= \cur => finally (chgDir cur) (chgDir dir >> act dir)
239 | {auto _ : HasIO io}
240 | -> (dir : Path Abs)
241 | -> EitherT PackErr io (List Body)
243 | ss <- eitherIO (DirEntries dir) (listDir "\{dir}")
244 | pure (mapMaybe parse ss)
248 | tomlFiles : {auto _ : HasIO io}
249 | -> (dir : Path Abs)
250 | -> EitherT PackErr io (List Body)
251 | tomlFiles dir = filter isTomlBody <$> entries dir
255 | htmlFiles : {auto _ : HasIO io}
256 | -> (dir : Path Abs)
257 | -> EitherT PackErr io (List Body)
258 | htmlFiles dir = filter isHtmlBody <$> entries dir
262 | currentEntries : HasIO io => EitherT PackErr io (List Body)
263 | currentEntries = curDir >>= entries
267 | copyDir : HasIO io => (from,to : Path Abs) -> EitherT PackErr io ()
268 | copyDir from to = do
270 | sys ["cp", "-r", from, to]
274 | copyDirInto : HasIO io => (from,parent : Path Abs) -> EitherT PackErr io ()
275 | copyDirInto from parent = do
277 | sys ["cp", "-r", from, "\{parent}/"]
282 | findInParentDirs : {auto _ : HasIO io}
285 | -> EitherT PackErr io (Maybe (File Abs))
286 | findInParentDirs p (PAbs d sb) = go sb
287 | where go : SnocList Body -> EitherT PackErr io (Maybe (File Abs))
288 | go [<] = pure Nothing
290 | let dir := PAbs d (sb :< b)
292 | (h :: _) <- filter p <$> entries dir | Nil => go sb
293 | pure $
Just (MkF dir h)
298 | findInAllParentDirs : {auto _ : HasIO io}
301 | -> EitherT PackErr io $
List $
File Abs
302 | findInAllParentDirs p = go [] where
303 | go : List (File Abs) -> Path Abs -> EitherT PackErr io $
List $
File Abs
304 | go presentRes currD = do
305 | Just af <- findInParentDirs p currD
306 | | Nothing => pure presentRes
307 | let nextRes = af::presentRes
308 | case parentDir $
parent af of
309 | Just parentD => go nextRes $
assert_smaller currD parentD
310 | Nothing => pure nextRes
312 | mkTmpDir : HasIO io => (pd : PackDirs) => EitherT PackErr io TmpDir
313 | mkTmpDir = go 100 0
316 | go : Nat -> Nat -> EitherT PackErr io TmpDir
317 | go 0 _ = throwE NoTmpDir
319 | let Just body := Body.parse ".tmp\{show n}" | Nothing => go k (S n)
320 | dir := pd.cache /> body
322 | False <- exists dir | True => go k (S n)
324 | warn {ref = MkLogRef Info}
326 | Too many temporary directories. Please remove all `.tmpXY`
327 | directories in `\{pd.cache}` or run `pack gc` to let pack
335 | {auto _ : HasIO io}
336 | -> {auto _ : PackDirs}
337 | -> (TmpDir => EitherT PackErr io a)
338 | -> EitherT PackErr io a
341 | finally (rmDir tmpDir) f
349 | rmFile : HasIO io => (f : File Abs) -> EitherT PackErr io ()
350 | rmFile f = when !(fileExists f) $
sys ["rm", f]
354 | read : HasIO io => File Abs -> EitherT PackErr io String
355 | read fn = eitherIO (ReadFile fn) (readFile "\{fn}")
360 | readIfExists : {auto _ : HasIO io}
361 | -> (file : File Abs)
363 | -> EitherT PackErr io String
364 | readIfExists file alt = do
365 | True <- fileExists file | False => pure alt
372 | write : HasIO io => File Abs -> String -> EitherT PackErr io ()
373 | write file str = do
375 | eitherIO (WriteFile file) (writeFile "\{file}" str)
380 | link : HasIO io => (from : Path Abs) -> (to : File Abs) -> EitherT PackErr io ()
384 | sys ["ln", "-s", from, to]
388 | copyFile : HasIO io => (from,to : File Abs) -> EitherT PackErr io ()
389 | copyFile from to = do
391 | sys ["cp", from, to]
395 | patch : {auto _ : HasIO io}
396 | -> (original : File Abs)
397 | -> (patch : File Abs)
398 | -> EitherT PackErr io ()
399 | patch o p = sys ["patch", o, p]