5
5
-- | Create a package.dhall from files and directory contents.
6
6
7
7
module Dhall.Package
8
- ( Recurse (.. )
8
+ ( Options
9
+ , defaultOptions
10
+ , characterSet
11
+ , packageFileName
12
+ , packagingMode
13
+ , PackagingMode (.. )
9
14
, writePackage
10
15
, getPackagePathAndContent
11
16
, PackageError (.. )
@@ -14,7 +19,6 @@ module Dhall.Package
14
19
import Control.Exception (Exception , throwIO )
15
20
import Control.Monad
16
21
import Data.List.NonEmpty (NonEmpty (.. ))
17
- import Data.Maybe (fromMaybe )
18
22
import Data.Text (Text )
19
23
import qualified Data.Text as Text
20
24
import Data.Traversable (for )
@@ -35,22 +39,60 @@ import qualified Dhall.Map as Map
35
39
import Dhall.Pretty (CharacterSet (.. ))
36
40
import qualified Dhall.Pretty
37
41
import Dhall.Util (_ERROR , renderExpression )
42
+ import Lens.Family (LensLike' )
38
43
import System.Directory
39
44
import System.FilePath
40
45
46
+ -- | Options for package creation.
47
+ data Options = Options
48
+ { optionsCharacterSet :: CharacterSet
49
+ , optionsPackageFileName :: String
50
+ , optionsPackagingMode :: PackagingMode
51
+ }
52
+
53
+ -- | The default options used for packaging.
54
+ --
55
+ -- The default values for the different settings are:
56
+ --
57
+ -- * The character set used is the one given by 'Dhall.Pretty.defaultCharacterSet'.
58
+ -- * The package file name is @package.dhall@.
59
+ -- * The packaging mode is 'OnlyThisPackage'.
60
+ defaultOptions :: Options
61
+ defaultOptions = Options
62
+ { optionsCharacterSet = Dhall.Pretty. defaultCharacterSet
63
+ , optionsPackageFileName = " package.dhall"
64
+ , optionsPackagingMode = OnlyThisPackage
65
+ }
66
+
67
+ -- | Access the character set used to render the package content.
68
+ characterSet :: Functor f => LensLike' f Options CharacterSet
69
+ characterSet k s =
70
+ fmap (\ x -> s { optionsCharacterSet = x }) (k (optionsCharacterSet s))
71
+
72
+ -- | Access the file name used for the package file.
73
+ packageFileName :: Functor f => LensLike' f Options String
74
+ packageFileName k s =
75
+ fmap (\ x -> s { optionsPackageFileName = x }) (k (optionsPackageFileName s))
76
+
77
+ -- | Access the packaging mode.
78
+ -- See the documentation of 'getPackagePathAndContent'.
79
+ packagingMode :: Functor f => LensLike' f Options PackagingMode
80
+ packagingMode k s =
81
+ fmap (\ x -> s { optionsPackagingMode = x }) (k (optionsPackagingMode s))
82
+
41
83
-- | Whether to recursively create a package for each subdirectory or not.
42
84
-- See the documentation of 'getPackagePathAndContent'.
43
- data Recurse
44
- = Recurse
45
- | Exact
85
+ data PackagingMode
86
+ = OnlyThisPackage
87
+ | RecursiveSubpackages
46
88
47
89
-- | Create a package.dhall from files and directory contents.
48
90
-- For a description of how the package file is constructed see
49
91
-- 'getPackagePathAndContent'.
50
- writePackage :: CharacterSet -> Recurse -> Maybe String -> NonEmpty FilePath -> IO ()
51
- writePackage characterSet doRecurse outputFn inputs = do
52
- (outputPath, expr) <- getPackagePathAndContent characterSet doRecurse outputFn inputs
53
- renderExpression characterSet True (Just outputPath) expr
92
+ writePackage :: Options -> NonEmpty FilePath -> IO ()
93
+ writePackage options inputs = do
94
+ (outputPath, expr) <- getPackagePathAndContent options inputs
95
+ renderExpression (optionsCharacterSet options) True (Just outputPath) expr
54
96
55
97
-- | Get the path and the Dhall expression for a package file.
56
98
--
@@ -76,8 +118,11 @@ writePackage characterSet doRecurse outputFn inputs = do
76
118
-- * If the path points to a regular file, it is included in the package
77
119
-- unless it is the path of the package file itself.
78
120
--
79
- getPackagePathAndContent :: CharacterSet -> Recurse -> Maybe String -> NonEmpty FilePath -> IO (FilePath , Expr s Import )
80
- getPackagePathAndContent characterSet doRecurse outputFn (path :| paths) = do
121
+ getPackagePathAndContent
122
+ :: Options
123
+ -> NonEmpty FilePath
124
+ -> IO (FilePath , Expr s Import )
125
+ getPackagePathAndContent options (path :| paths) = do
81
126
outputDir <- do
82
127
isDirectory <- doesDirectoryExist path
83
128
return $ if isDirectory then path else takeDirectory path
@@ -93,9 +138,13 @@ getPackagePathAndContent characterSet doRecurse outputFn (path :| paths) = do
93
138
return relativeDir
94
139
95
140
resultMap <- go Map. empty checkOutputDir (path: paths)
96
- return (outputDir </> outputFn' , RecordLit $ Map. sort resultMap)
141
+ return (outputDir </> outputFn, RecordLit $ Map. sort resultMap)
97
142
where
98
- go :: Map Text (RecordField s Import ) -> (FilePath -> IO FilePath ) -> [FilePath ] -> IO (Map Text (RecordField s Import ))
143
+ go
144
+ :: Map Text (RecordField s Import )
145
+ -> (FilePath -> IO FilePath )
146
+ -> [FilePath ]
147
+ -> IO (Map Text (RecordField s Import ))
99
148
go ! acc _checkOutputDir [] = return acc
100
149
go ! acc checkOutputDir (p: ps) = do
101
150
isDirectory <- doesDirectoryExist p
@@ -113,29 +162,31 @@ getPackagePathAndContent characterSet doRecurse outputFn (path :| paths) = do
113
162
then ([entry'], mempty )
114
163
else mempty
115
164
) entries
116
- subpackages <- case doRecurse of
117
- Recurse ->
165
+ subpackages <- case optionsPackagingMode options of
166
+ RecursiveSubpackages ->
118
167
for subdirectories $ \ subdirectory -> do
119
- writePackage characterSet Recurse outputFn (subdirectory :| [] )
120
- return (subdirectory </> outputFn' )
121
- Exact -> return []
168
+ writePackage options (subdirectory :| [] )
169
+ return (subdirectory </> outputFn)
170
+ OnlyThisPackage -> return []
122
171
go acc checkOutputDir (dhallFiles <> subpackages <> ps)
123
172
| isFile -> do
124
173
dir <- checkOutputDir $ takeDirectory p
125
174
126
175
let p' = normalise $ dir </> takeFileName p
127
176
128
- let resultMap = if p' == outputFn'
177
+ let resultMap = if p' == outputFn
129
178
then Map. empty
130
- else filepathToMap outputFn' p'
179
+ else filepathToMap outputFn p'
131
180
132
181
acc' <- mergeMaps acc resultMap
133
182
go acc' checkOutputDir ps
134
183
| otherwise -> throwIO $ InvalidPath p
135
184
185
+ hasDhallExtension :: FilePath -> Bool
136
186
hasDhallExtension entry = takeExtension entry == " .dhall"
137
187
138
- outputFn' = fromMaybe " package.dhall" outputFn
188
+ outputFn :: String
189
+ outputFn = optionsPackageFileName options
139
190
140
191
-- | Construct a nested 'Map' from a 'FilePath'.
141
192
-- For example, the filepath @some/file/path.dhall@ will result in something
0 commit comments