diff options
-rw-r--r-- | fsmgr.cabal | 13 | ||||
-rw-r--r-- | fsmgr.hs | 63 | ||||
-rw-r--r-- | src/ConfigFile.hs | 77 |
3 files changed, 85 insertions, 68 deletions
diff --git a/fsmgr.cabal b/fsmgr.cabal index 95ec00c..3da9bf6 100644 --- a/fsmgr.cabal +++ b/fsmgr.cabal | |||
@@ -19,14 +19,13 @@ source-repository head | |||
19 | 19 | ||
20 | library | 20 | library |
21 | exposed-modules: | 21 | exposed-modules: |
22 | Crypto.Hash.Types.Digest.Read | 22 | Crypto.Hash.Types.Digest.Read, ConfigFile |
23 | other-modules: | 23 | other-modules: |
24 | Paths_fsmgr | 24 | Paths_fsmgr |
25 | hs-source-dirs: | 25 | hs-source-dirs: |
26 | src | 26 | src |
27 | build-depends: | 27 | build-depends: base >=4.7 && <5, rebase, optparse-applicative, typed-process, |
28 | base >=4.7 && <5, rebase, optparse-applicative, typed-process, | 28 | directory, filepath, yaml-combinators, lens, lens-aeson, cryptonite, memory, basement, shake |
29 | directory, filepath, yaml, lens, lens-aeson, cryptonite, memory, basement | ||
30 | default-language: Haskell2010 | 29 | default-language: Haskell2010 |
31 | 30 | ||
32 | executable fsmgr | 31 | executable fsmgr |
@@ -34,9 +33,9 @@ executable fsmgr | |||
34 | other-modules: | 33 | other-modules: |
35 | Paths_fsmgr | 34 | Paths_fsmgr |
36 | ghc-options: -threaded -rtsopts -with-rtsopts=-N -W -Wall | 35 | ghc-options: -threaded -rtsopts -with-rtsopts=-N -W -Wall |
37 | build-depends: | 36 | build-depends: fsmgr, |
38 | base >=4.7 && <5, rebase, optparse-applicative, typed-process, | 37 | base >=4.7 && <5, rebase, optparse-applicative, typed-process, |
39 | directory, filepath, yaml-combinators, lens, lens-aeson, cryptonite, memory, basement, fsmgr, shake | 38 | directory, filepath, yaml-combinators, lens, lens-aeson, cryptonite, memory, basement, shake |
40 | default-language: Haskell2010 | 39 | default-language: Haskell2010 |
41 | 40 | ||
42 | -- test-suite fsmgr-test | 41 | -- test-suite fsmgr-test |
@@ -10,72 +10,13 @@ | |||
10 | module Main where | 10 | module Main where |
11 | import Rebase.Prelude hiding (bool, hash, (<.>)) | 11 | import Rebase.Prelude hiding (bool, hash, (<.>)) |
12 | 12 | ||
13 | import Data.Yaml.Combinators | ||
14 | import Development.Shake hiding (getEnv) | 13 | import Development.Shake hiding (getEnv) |
15 | import Development.Shake.Command () | 14 | import Development.Shake.Command () |
16 | import Development.Shake.FilePath | 15 | import Development.Shake.FilePath |
17 | import qualified Rebase.Data.Set as Set | ||
18 | import qualified Rebase.Data.Text as Text | 16 | import qualified Rebase.Data.Text as Text |
19 | ;import Rebase.Data.Text (pack, unpack) | 17 | ;import Rebase.Data.Text (pack, unpack) |
20 | import Rebase.Data.Text.Encoding | 18 | |
21 | import qualified Rebase.Data.Vector as Vector | 19 | import ConfigFile |
22 | {- | ||
23 | |||
24 | Basic idea is to have a fs.yaml that specifies the build procedure. Analogous to | ||
25 | stack.yaml, it should specify everything (every source) directly or indirectly. | ||
26 | |||
27 | We want to make new images from CoW copies of old ones. We want to build these | ||
28 | things incrementally, but still end up with something that will be reproducible | ||
29 | from scratch. | ||
30 | |||
31 | Anyway, what we'll have is a list of packages, which will be unpacked first. | ||
32 | Then a list of debconf values, which will be applied. Then we will have the rest | ||
33 | of the other, slower changes to the image (including dpkg --configure -a). Some | ||
34 | changes can be assumed to produce the same results out of order. Oh right, and | ||
35 | the zeroeth step is to generate the empty (or just initial) filesystem image. | ||
36 | The initial filesystem image, if nonempty, is specified by filename (otherwise, | ||
37 | by size), while the hash of the configuration determines the output filename. | ||
38 | |||
39 | -- | ||
40 | |||
41 | 'Parent' param should be a config file, not hash. The hash will only be used to | ||
42 | determine whether we need to build it. | ||
43 | |||
44 | -} | ||
45 | |||
46 | newtype DebconfConfig = DebconfConfig Text deriving (Show, Read, Eq, Ord) | ||
47 | newtype Package = Package Text deriving (Show, Read, Eq, Ord) | ||
48 | data Patch = Patch deriving (Show, Read) | ||
49 | |||
50 | data BaseImageSpecification | ||
51 | = EmptyImageOfBytes Int | ||
52 | | ParentImageConfigFile FilePath | ||
53 | deriving (Show, Read) | ||
54 | |||
55 | data DiskImageConfig = DiskImageConfig { | ||
56 | initialImage :: BaseImageSpecification | ||
57 | , packages :: Set Package | ||
58 | , debconfConfig :: Maybe FilePath | ||
59 | , unpackOnly :: Bool | ||
60 | , binaries :: Vector Text | ||
61 | , chrootCommands :: Vector Text | ||
62 | } deriving (Show, Read) | ||
63 | |||
64 | parsePackageName :: Text -> Package | ||
65 | parsePackageName = Package -- TODO | ||
66 | |||
67 | diskImageConfigParser :: Parser DiskImageConfig | ||
68 | diskImageConfigParser = object $ | ||
69 | DiskImageConfig | ||
70 | <$> field "parent" ((EmptyImageOfBytes <$> integer) <> (ParentImageConfigFile . unpack <$> string)) | ||
71 | <*> (Set.fromList . toList . fmap parsePackageName <$> defaultField "packages" Vector.empty (array string)) | ||
72 | <*> (fmap unpack <$> optField "debconf" string) | ||
73 | <*> defaultField "unpack-only" False bool | ||
74 | <*> defaultField "binaries" Vector.empty (array string) | ||
75 | <*> defaultField "chroot-commands" Vector.empty (array string) | ||
76 | |||
77 | readCfg :: FilePath -> Action DiskImageConfig | ||
78 | readCfg yaml = either error id . parse diskImageConfigParser . encodeUtf8 . pack <$> readFile' yaml | ||
79 | 20 | ||
80 | noParent :: BaseImageSpecification -> Bool | 21 | noParent :: BaseImageSpecification -> Bool |
81 | noParent (EmptyImageOfBytes _) = True | 22 | noParent (EmptyImageOfBytes _) = True |
diff --git a/src/ConfigFile.hs b/src/ConfigFile.hs new file mode 100644 index 0000000..8b23582 --- /dev/null +++ b/src/ConfigFile.hs | |||
@@ -0,0 +1,77 @@ | |||
1 | {-# OPTIONS_GHC -fno-warn-type-defaults #-} | ||
2 | {-# LANGUAGE ExtendedDefaultRules #-} | ||
3 | {-# LANGUAGE LambdaCase #-} | ||
4 | {-# LANGUAGE NamedFieldPuns #-} | ||
5 | {-# LANGUAGE NoImplicitPrelude #-} | ||
6 | {-# LANGUAGE OverloadedStrings #-} | ||
7 | {-# LANGUAGE RecordWildCards #-} | ||
8 | {-# LANGUAGE ScopedTypeVariables #-} | ||
9 | |||
10 | module ConfigFile where | ||
11 | import Rebase.Prelude hiding (bool, hash, (<.>)) | ||
12 | |||
13 | import Data.Yaml.Combinators | ||
14 | import Development.Shake hiding (getEnv) | ||
15 | import Development.Shake.Command () | ||
16 | import qualified Rebase.Data.Set as Set | ||
17 | import Rebase.Data.Text (pack, unpack) | ||
18 | import Rebase.Data.Text.Encoding | ||
19 | import qualified Rebase.Data.Vector as Vector | ||
20 | {- | ||
21 | |||
22 | Basic idea is to have a fs.yaml that specifies the build procedure. Analogous to | ||
23 | stack.yaml, it should specify everything (every source) directly or indirectly. | ||
24 | |||
25 | We want to make new images from CoW copies of old ones. We want to build these | ||
26 | things incrementally, but still end up with something that will be reproducible | ||
27 | from scratch. | ||
28 | |||
29 | Anyway, what we'll have is a list of packages, which will be unpacked first. | ||
30 | Then a list of debconf values, which will be applied. Then we will have the rest | ||
31 | of the other, slower changes to the image (including dpkg --configure -a). Some | ||
32 | changes can be assumed to produce the same results out of order. Oh right, and | ||
33 | the zeroeth step is to generate the empty (or just initial) filesystem image. | ||
34 | The initial filesystem image, if nonempty, is specified by filename (otherwise, | ||
35 | by size), while the hash of the configuration determines the output filename. | ||
36 | |||
37 | -- | ||
38 | |||
39 | 'Parent' param should be a config file, not hash. The hash will only be used to | ||
40 | determine whether we need to build it. | ||
41 | |||
42 | -} | ||
43 | |||
44 | newtype DebconfConfig = DebconfConfig Text deriving (Show, Read, Eq, Ord) | ||
45 | newtype Package = Package Text deriving (Show, Read, Eq, Ord) | ||
46 | data Patch = Patch deriving (Show, Read) | ||
47 | |||
48 | data BaseImageSpecification | ||
49 | = EmptyImageOfBytes Int | ||
50 | | ParentImageConfigFile FilePath | ||
51 | deriving (Show, Read) | ||
52 | |||
53 | data DiskImageConfig = DiskImageConfig { | ||
54 | initialImage :: BaseImageSpecification | ||
55 | , packages :: Set Package | ||
56 | , debconfConfig :: Maybe FilePath | ||
57 | , unpackOnly :: Bool | ||
58 | , binaries :: Vector Text | ||
59 | , chrootCommands :: Vector Text | ||
60 | } deriving (Show, Read) | ||
61 | |||
62 | parsePackageName :: Text -> Package | ||
63 | parsePackageName = Package -- TODO | ||
64 | |||
65 | diskImageConfigParser :: Parser DiskImageConfig | ||
66 | diskImageConfigParser = object $ | ||
67 | DiskImageConfig | ||
68 | <$> field "parent" ((EmptyImageOfBytes <$> integer) <> (ParentImageConfigFile . unpack <$> string)) | ||
69 | <*> (Set.fromList . toList . fmap parsePackageName <$> defaultField "packages" Vector.empty (array string)) | ||
70 | <*> (fmap unpack <$> optField "debconf" string) | ||
71 | <*> defaultField "unpack-only" False bool | ||
72 | <*> defaultField "binaries" Vector.empty (array string) | ||
73 | <*> defaultField "chroot-commands" Vector.empty (array string) | ||
74 | |||
75 | readCfg :: FilePath -> Action DiskImageConfig | ||
76 | readCfg yaml = either error id . parse diskImageConfigParser . encodeUtf8 . pack <$> readFile' yaml | ||
77 | |||