summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fsmgr.cabal13
-rw-r--r--fsmgr.hs63
-rw-r--r--src/ConfigFile.hs77
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
20library 20library
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
32executable fsmgr 31executable 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
diff --git a/fsmgr.hs b/fsmgr.hs
index 626f79f..d5df8ac 100644
--- a/fsmgr.hs
+++ b/fsmgr.hs
@@ -10,72 +10,13 @@
10module Main where 10module Main where
11import Rebase.Prelude hiding (bool, hash, (<.>)) 11import Rebase.Prelude hiding (bool, hash, (<.>))
12 12
13import Data.Yaml.Combinators
14import Development.Shake hiding (getEnv) 13import Development.Shake hiding (getEnv)
15import Development.Shake.Command () 14import Development.Shake.Command ()
16import Development.Shake.FilePath 15import Development.Shake.FilePath
17import qualified Rebase.Data.Set as Set
18import qualified Rebase.Data.Text as Text 16import qualified Rebase.Data.Text as Text
19 ;import Rebase.Data.Text (pack, unpack) 17 ;import Rebase.Data.Text (pack, unpack)
20import Rebase.Data.Text.Encoding 18
21import qualified Rebase.Data.Vector as Vector 19import ConfigFile
22{-
23
24Basic idea is to have a fs.yaml that specifies the build procedure. Analogous to
25stack.yaml, it should specify everything (every source) directly or indirectly.
26
27We want to make new images from CoW copies of old ones. We want to build these
28things incrementally, but still end up with something that will be reproducible
29from scratch.
30
31Anyway, what we'll have is a list of packages, which will be unpacked first.
32Then a list of debconf values, which will be applied. Then we will have the rest
33of the other, slower changes to the image (including dpkg --configure -a). Some
34changes can be assumed to produce the same results out of order. Oh right, and
35the zeroeth step is to generate the empty (or just initial) filesystem image.
36The initial filesystem image, if nonempty, is specified by filename (otherwise,
37by 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
42determine whether we need to build it.
43
44-}
45
46newtype DebconfConfig = DebconfConfig Text deriving (Show, Read, Eq, Ord)
47newtype Package = Package Text deriving (Show, Read, Eq, Ord)
48data Patch = Patch deriving (Show, Read)
49
50data BaseImageSpecification
51 = EmptyImageOfBytes Int
52 | ParentImageConfigFile FilePath
53 deriving (Show, Read)
54
55data 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
64parsePackageName :: Text -> Package
65parsePackageName = Package -- TODO
66
67diskImageConfigParser :: Parser DiskImageConfig
68diskImageConfigParser = 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
77readCfg :: FilePath -> Action DiskImageConfig
78readCfg yaml = either error id . parse diskImageConfigParser . encodeUtf8 . pack <$> readFile' yaml
79 20
80noParent :: BaseImageSpecification -> Bool 21noParent :: BaseImageSpecification -> Bool
81noParent (EmptyImageOfBytes _) = True 22noParent (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
10module ConfigFile where
11import Rebase.Prelude hiding (bool, hash, (<.>))
12
13import Data.Yaml.Combinators
14import Development.Shake hiding (getEnv)
15import Development.Shake.Command ()
16import qualified Rebase.Data.Set as Set
17import Rebase.Data.Text (pack, unpack)
18import Rebase.Data.Text.Encoding
19import qualified Rebase.Data.Vector as Vector
20{-
21
22Basic idea is to have a fs.yaml that specifies the build procedure. Analogous to
23stack.yaml, it should specify everything (every source) directly or indirectly.
24
25We want to make new images from CoW copies of old ones. We want to build these
26things incrementally, but still end up with something that will be reproducible
27from scratch.
28
29Anyway, what we'll have is a list of packages, which will be unpacked first.
30Then a list of debconf values, which will be applied. Then we will have the rest
31of the other, slower changes to the image (including dpkg --configure -a). Some
32changes can be assumed to produce the same results out of order. Oh right, and
33the zeroeth step is to generate the empty (or just initial) filesystem image.
34The initial filesystem image, if nonempty, is specified by filename (otherwise,
35by 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
40determine whether we need to build it.
41
42-}
43
44newtype DebconfConfig = DebconfConfig Text deriving (Show, Read, Eq, Ord)
45newtype Package = Package Text deriving (Show, Read, Eq, Ord)
46data Patch = Patch deriving (Show, Read)
47
48data BaseImageSpecification
49 = EmptyImageOfBytes Int
50 | ParentImageConfigFile FilePath
51 deriving (Show, Read)
52
53data 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
62parsePackageName :: Text -> Package
63parsePackageName = Package -- TODO
64
65diskImageConfigParser :: Parser DiskImageConfig
66diskImageConfigParser = 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
75readCfg :: FilePath -> Action DiskImageConfig
76readCfg yaml = either error id . parse diskImageConfigParser . encodeUtf8 . pack <$> readFile' yaml
77