summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Cady <d@jerkface.net>2019-10-15 12:32:41 -0400
committerAndrew Cady <d@jerkface.net>2019-10-15 13:43:16 -0400
commit4f6e2688618364d21435b8bda0aed724eec6b65a (patch)
tree878c0ea50f29bfd56b22eeb5627eaef5eb129cfc
parent79ddffdec78b05f12243acbbe0e82dfdc238e76f (diff)
implement 'binaries-optional:' and 'skel-files-optional:' sections
-rw-r--r--fsmgr.hs59
-rw-r--r--src/ConfigFile.hs34
2 files changed, 54 insertions, 39 deletions
diff --git a/fsmgr.hs b/fsmgr.hs
index a96bc1b..c290a74 100644
--- a/fsmgr.hs
+++ b/fsmgr.hs
@@ -1,33 +1,35 @@
1{-# LANGUAGE ViewPatterns #-}
2{-# OPTIONS_GHC -fno-warn-type-defaults #-} 1{-# OPTIONS_GHC -fno-warn-type-defaults #-}
3{-# LANGUAGE DuplicateRecordFields #-} 2{-# LANGUAGE DuplicateRecordFields #-}
4{-# LANGUAGE ExtendedDefaultRules #-} 3{-# LANGUAGE ExtendedDefaultRules #-}
4{-# LANGUAGE FlexibleContexts #-}
5{-# LANGUAGE LambdaCase #-} 5{-# LANGUAGE LambdaCase #-}
6{-# LANGUAGE NamedFieldPuns #-} 6{-# LANGUAGE NamedFieldPuns #-}
7{-# LANGUAGE NoImplicitPrelude #-} 7{-# LANGUAGE NoImplicitPrelude #-}
8{-# LANGUAGE OverloadedStrings #-} 8{-# LANGUAGE OverloadedStrings #-}
9{-# LANGUAGE RecordWildCards #-} 9{-# LANGUAGE RecordWildCards #-}
10{-# LANGUAGE ScopedTypeVariables #-} 10{-# LANGUAGE ScopedTypeVariables #-}
11{-# LANGUAGE ViewPatterns #-}
11 12
12module Main where 13module Main where
13import Rebase.Prelude hiding (bool, hash, o, (<.>), join) 14import Rebase.Prelude hiding (bool, hash, join, o, (<.>))
14 15
15import qualified Rebase.Data.Text as Text 16import Rebase.Data.Text (pack, unpack)
16 ;import Rebase.Data.Text (pack, unpack) 17import qualified Rebase.Data.Text as Text
17 18
18import Development.Shake hiding (getEnv) 19import Development.Shake hiding (getEnv)
19import Development.Shake.Command () 20import Development.Shake.Command ()
20import Development.Shake.FilePath 21import Development.Shake.FilePath
21 22
22import qualified Options.Applicative as Opt 23import Options.Applicative hiding (action, command)
23 ;import Options.Applicative hiding (action, command) 24import qualified Options.Applicative as Opt
24 25
25import ConfigFile 26import ConfigFile
26import System.Directory (getCurrentDirectory, createDirectoryIfMissing) 27import String
27import System.Posix.Process (getProcessID) 28import System.Directory (createDirectoryIfMissing,
28import System.Posix.Types (CUid (..)) 29 getCurrentDirectory)
29import System.Posix.User (getEffectiveUserID) 30import System.Posix.Process (getProcessID)
30import String 31import System.Posix.Types (CUid (..))
32import System.Posix.User (getEffectiveUserID)
31 33
32noParent :: BaseImageSpecification -> Bool 34noParent :: BaseImageSpecification -> Bool
33noParent (EmptyImageOfBytes _) = True 35noParent (EmptyImageOfBytes _) = True
@@ -36,10 +38,13 @@ noParent (ParentImageConfigFile _) = False
36dynamicNames :: FilePath -> FilePath 38dynamicNames :: FilePath -> FilePath
37dynamicNames = replace "$(karch)" uname . replace "$(debarch)" debarch 39dynamicNames = replace "$(karch)" uname . replace "$(debarch)" debarch
38 40
41chomp :: String -> String
42chomp = takeWhile (/= '\n')
43
39debarch :: String 44debarch :: String
40debarch = unsafePerformIO $ do 45debarch = unsafePerformIO $ do
41 Stdout out <- cmd "dpkg-architecture -q DEB_BUILD_ARCH" 46 Stdout out <- cmd "dpkg-architecture -q DEB_BUILD_ARCH"
42 return out 47 return $ chomp out
43 48
44uname :: String 49uname :: String
45uname = unsafePerformIO $ do 50uname = unsafePerformIO $ do
@@ -76,15 +81,21 @@ buildRoot config@DiskImageConfig{..} finalOut = do
76 {- 2.5. install apt package cache -} 81 {- 2.5. install apt package cache -}
77 -- TODO 82 -- TODO
78 {- 3. binaries -} 83 {- 3. binaries -}
79 forM_ (unpack <$> binaries) $ \b -> do 84 let go b = do
80 p <- fromMaybe (fail $ "not found in ${PATH}: " ++ b) <$> liftIO (pathLocate b) 85 p <- fromMaybe (fail $ "not found in ${PATH}: " ++ b) <$> liftIO (pathLocate b)
81 cmd_ "cp -L" [p] [mountpoint </> "usr/local/bin" </> b] 86 cmd_ "cp -L" [p] [mountpoint </> "usr/local/bin" </> b]
87 in do
88 forM_ (unpack <$> binaries) go
89 forM_ (unpack <$> optionalBinaries) $ ignoreErrors . go
82 {- 3.5 skel -} 90 {- 3.5 skel -}
83 forM_ (unpack <$> skelFiles) $ \f -> do 91 let go f = do
84 homeDir <- getHomeDir 92 homeDir <- getHomeDir
85 target <- absPath mountpoint <&> (</> "etc/skel") 93 target <- absPath mountpoint <&> (</> "etc/skel")
86 cmd_ "mkdir -p" [target] 94 cmd_ "mkdir -p" [target]
87 cmd_ (Cwd homeDir) "cp -r --preserve=mode,timestamps -L --parents -t" [target] [f] 95 cmd_ (Cwd homeDir) "cp -r --preserve=mode,timestamps -L --parents -t" [target] [f]
96 in do
97 forM_ (unpack <$> skelFiles) go
98 forM_ (unpack <$> optionalSkelFiles) $ ignoreErrors . go
88 {- 4. custom setup commands -} 99 {- 4. custom setup commands -}
89 forM_ chrootCommands $ \c -> do 100 forM_ chrootCommands $ \c -> do
90 cmd_ "chroot" [mountpoint] "/bin/sh -c" [unpack c] 101 cmd_ "chroot" [mountpoint] "/bin/sh -c" [unpack c]
diff --git a/src/ConfigFile.hs b/src/ConfigFile.hs
index 086ac7c..bc5e254 100644
--- a/src/ConfigFile.hs
+++ b/src/ConfigFile.hs
@@ -8,15 +8,15 @@
8{-# LANGUAGE ScopedTypeVariables #-} 8{-# LANGUAGE ScopedTypeVariables #-}
9 9
10module ConfigFile where 10module ConfigFile where
11import Rebase.Prelude hiding (bool, hash, (<.>)) 11import Rebase.Prelude hiding (bool, hash, (<.>))
12 12
13import Data.Yaml.Combinators 13import Data.Yaml.Combinators
14import Development.Shake hiding (getEnv) 14import Development.Shake hiding (getEnv)
15import Development.Shake.Command () 15import Development.Shake.Command ()
16import qualified Rebase.Data.Set as Set 16import qualified Rebase.Data.Set as Set
17import Rebase.Data.Text (pack, unpack) 17import Rebase.Data.Text (pack, unpack)
18import Rebase.Data.Text.Encoding 18import Rebase.Data.Text.Encoding
19import qualified Rebase.Data.Vector as Vector 19import qualified Rebase.Data.Vector as Vector
20{- 20{-
21 21
22Basic idea is to have a fs.yaml that specifies the build procedure. Analogous to 22Basic idea is to have a fs.yaml that specifies the build procedure. Analogous to
@@ -51,13 +51,15 @@ data BaseImageSpecification
51 deriving (Show, Read) 51 deriving (Show, Read)
52 52
53data DiskImageConfig = DiskImageConfig { 53data DiskImageConfig = DiskImageConfig {
54 initialImage :: BaseImageSpecification 54 initialImage :: BaseImageSpecification
55, packages :: Set Package 55, packages :: Set Package
56, debconfConfig :: Maybe FilePath 56, debconfConfig :: Maybe FilePath
57, unpackOnly :: Bool 57, unpackOnly :: Bool
58, binaries :: Vector Text 58, binaries :: Vector Text
59, chrootCommands :: Vector Text 59, optionalBinaries :: Vector Text
60, skelFiles :: Vector Text 60, chrootCommands :: Vector Text
61, skelFiles :: Vector Text
62, optionalSkelFiles :: Vector Text
61} deriving (Show, Read) 63} deriving (Show, Read)
62 64
63parsePackageName :: Text -> Package 65parsePackageName :: Text -> Package
@@ -71,8 +73,10 @@ diskImageConfigParser = object $
71 <*> (fmap unpack <$> optField "debconf" string) 73 <*> (fmap unpack <$> optField "debconf" string)
72 <*> defaultField "unpack-only" False bool 74 <*> defaultField "unpack-only" False bool
73 <*> defaultField "binaries" Vector.empty (array string) 75 <*> defaultField "binaries" Vector.empty (array string)
76 <*> defaultField "binaries-optional" Vector.empty (array string)
74 <*> defaultField "chroot-commands" Vector.empty (array string) 77 <*> defaultField "chroot-commands" Vector.empty (array string)
75 <*> defaultField "skel-files" Vector.empty (array string) 78 <*> defaultField "skel-files" Vector.empty (array string)
79 <*> defaultField "skel-files-optional" Vector.empty (array string)
76 80
77readCfg :: FilePath -> Action DiskImageConfig 81readCfg :: FilePath -> Action DiskImageConfig
78readCfg yaml = either error id . parse diskImageConfigParser . encodeUtf8 . pack <$> readFile' yaml 82readCfg yaml = either error id . parse diskImageConfigParser . encodeUtf8 . pack <$> readFile' yaml