-
Notifications
You must be signed in to change notification settings - Fork 214
/
to-directory-tree.dhall
119 lines (104 loc) · 4.11 KB
/
to-directory-tree.dhall
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
-- This is an example on how to build a directory tree using the so-called
-- fixpointed method. See the documenatation of the `Dhall.DirectoryTree` module
-- for further information on it.
-- First, define some types recognized by the `dhall to-directory-tree` command.
-- A user, either identified by its numeric user id or its name.
let User = < UserId : Natural | UserName : Text >
-- Similarly, a group.
let Group = < GroupId : Natural | GroupName : Text >
-- The following two type aliases are a well-typed represenation of the bitmask
-- for permissions used by the DAC access control found on Unix systems. See for
-- example the chmod(5) manual entry.
-- How much access we do grant...
let Access =
{ execute : Optional Bool, read : Optional Bool, write : Optional Bool }
-- ... for whom.
let Mode =
{ user : Optional Access
, group : Optional Access
, other : Optional Access
}
-- A generic file system entry. It consists of a name, an abstract content and
-- some metadata which might be set (Some) or not (None).
let Entry =
\(content : Type) ->
{ name : Text
, content : content
, user : Optional User
, group : Optional Group
, mode : Optional Mode
}
-- This is the main program constructing our directory tree. It is a fixpoint
-- definition similar to how we deal with recursive types in arbitrary Dhall
-- programs but specialised to our use case. The first argument is the type of a
-- directory tree and the second one is a record where each field is a
-- constructor for a specific filesystem entry.
in \(tree : Type) ->
\ ( make
: { directory : Entry (List tree) -> tree, file : Entry Text -> tree }
) ->
-- Before we define the actual directory tree we define some Dhall schemas
-- and shortcuts for convenience.
-- A schema suitable for a directory...
let Directory =
{ Type =
{ name : Text
, content : List tree
, user : Optional User
, group : Optional Group
, mode : Optional Mode
}
, default =
{ content = [] : List tree
, user = None User
, group = None Group
, mode = None Mode
}
}
-- ... and one for a file.
let File =
{ Type =
{ name : Text
, content : Text
, user : Optional User
, group : Optional Group
, mode : Optional Mode
}
, default =
{ content = ""
, user = None User
, group = None Group
, mode = None Mode
}
}
-- Give someone full access to an filesystem entry.
let full_access
: Access
= { execute = Some True, read = Some True, write = Some True }
-- Give someone no access at all to an filesystem entry.
let no_access
: Access
= { execute = Some False, read = Some False, write = Some False }
-- These permissions
-- * grant full access to the user.
-- * retain the permissions of the primary group of the user.
-- * deny access to everyone else.
let semi_private
: Mode
= { user = Some full_access, group = None Access, other = Some no_access }
-- Now let's start with the directory tree ...
in [ -- Some file with a gentle greeting. No metadata is set explicitly.
make.file File::{ name = "some file", content = "Hello world!" }
-- A directory with some metadata set explicitely.
, make.directory
Directory::{
, name = "my private directory"
-- How owns the new directory: just_me
, user = Some (User.UserName "just_me")
-- We stick with the user's default group here.
, group = None Group
, mode = Some semi_private
, content = [] : List tree
}
]
: List tree