diff options
author | Andrew Cady <d@jerkface.net> | 2019-10-15 12:32:41 -0400 |
---|---|---|
committer | Andrew Cady <d@jerkface.net> | 2019-10-15 13:43:16 -0400 |
commit | 4f6e2688618364d21435b8bda0aed724eec6b65a (patch) | |
tree | 878c0ea50f29bfd56b22eeb5627eaef5eb129cfc | |
parent | 79ddffdec78b05f12243acbbe0e82dfdc238e76f (diff) |
implement 'binaries-optional:' and 'skel-files-optional:' sections
-rw-r--r-- | fsmgr.hs | 59 | ||||
-rw-r--r-- | src/ConfigFile.hs | 34 |
2 files changed, 54 insertions, 39 deletions
@@ -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 | ||
12 | module Main where | 13 | module Main where |
13 | import Rebase.Prelude hiding (bool, hash, o, (<.>), join) | 14 | import Rebase.Prelude hiding (bool, hash, join, o, (<.>)) |
14 | 15 | ||
15 | import qualified Rebase.Data.Text as Text | 16 | import Rebase.Data.Text (pack, unpack) |
16 | ;import Rebase.Data.Text (pack, unpack) | 17 | import qualified Rebase.Data.Text as Text |
17 | 18 | ||
18 | import Development.Shake hiding (getEnv) | 19 | import Development.Shake hiding (getEnv) |
19 | import Development.Shake.Command () | 20 | import Development.Shake.Command () |
20 | import Development.Shake.FilePath | 21 | import Development.Shake.FilePath |
21 | 22 | ||
22 | import qualified Options.Applicative as Opt | 23 | import Options.Applicative hiding (action, command) |
23 | ;import Options.Applicative hiding (action, command) | 24 | import qualified Options.Applicative as Opt |
24 | 25 | ||
25 | import ConfigFile | 26 | import ConfigFile |
26 | import System.Directory (getCurrentDirectory, createDirectoryIfMissing) | 27 | import String |
27 | import System.Posix.Process (getProcessID) | 28 | import System.Directory (createDirectoryIfMissing, |
28 | import System.Posix.Types (CUid (..)) | 29 | getCurrentDirectory) |
29 | import System.Posix.User (getEffectiveUserID) | 30 | import System.Posix.Process (getProcessID) |
30 | import String | 31 | import System.Posix.Types (CUid (..)) |
32 | import System.Posix.User (getEffectiveUserID) | ||
31 | 33 | ||
32 | noParent :: BaseImageSpecification -> Bool | 34 | noParent :: BaseImageSpecification -> Bool |
33 | noParent (EmptyImageOfBytes _) = True | 35 | noParent (EmptyImageOfBytes _) = True |
@@ -36,10 +38,13 @@ noParent (ParentImageConfigFile _) = False | |||
36 | dynamicNames :: FilePath -> FilePath | 38 | dynamicNames :: FilePath -> FilePath |
37 | dynamicNames = replace "$(karch)" uname . replace "$(debarch)" debarch | 39 | dynamicNames = replace "$(karch)" uname . replace "$(debarch)" debarch |
38 | 40 | ||
41 | chomp :: String -> String | ||
42 | chomp = takeWhile (/= '\n') | ||
43 | |||
39 | debarch :: String | 44 | debarch :: String |
40 | debarch = unsafePerformIO $ do | 45 | debarch = 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 | ||
44 | uname :: String | 49 | uname :: String |
45 | uname = unsafePerformIO $ do | 50 | uname = 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 | ||
10 | module ConfigFile where | 10 | module ConfigFile where |
11 | import Rebase.Prelude hiding (bool, hash, (<.>)) | 11 | import Rebase.Prelude hiding (bool, hash, (<.>)) |
12 | 12 | ||
13 | import Data.Yaml.Combinators | 13 | import Data.Yaml.Combinators |
14 | import Development.Shake hiding (getEnv) | 14 | import Development.Shake hiding (getEnv) |
15 | import Development.Shake.Command () | 15 | import Development.Shake.Command () |
16 | import qualified Rebase.Data.Set as Set | 16 | import qualified Rebase.Data.Set as Set |
17 | import Rebase.Data.Text (pack, unpack) | 17 | import Rebase.Data.Text (pack, unpack) |
18 | import Rebase.Data.Text.Encoding | 18 | import Rebase.Data.Text.Encoding |
19 | import qualified Rebase.Data.Vector as Vector | 19 | import qualified Rebase.Data.Vector as Vector |
20 | {- | 20 | {- |
21 | 21 | ||
22 | Basic idea is to have a fs.yaml that specifies the build procedure. Analogous to | 22 | Basic 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 | ||
53 | data DiskImageConfig = DiskImageConfig { | 53 | data 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 | ||
63 | parsePackageName :: Text -> Package | 65 | parsePackageName :: 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 | ||
77 | readCfg :: FilePath -> Action DiskImageConfig | 81 | readCfg :: FilePath -> Action DiskImageConfig |
78 | readCfg yaml = either error id . parse diskImageConfigParser . encodeUtf8 . pack <$> readFile' yaml | 82 | readCfg yaml = either error id . parse diskImageConfigParser . encodeUtf8 . pack <$> readFile' yaml |