src/add/relock.bend
ezx@1.11.0.0 · 227 lines · 27 definitions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15import Base
16import ezx@1.11.0.0/src/add/world.bend as A
17import ezx@1.11.0.0/src/add/plan.bend as AP
18import ezx@1.11.0.0/src/add/hub.bend as H
19import ezx@1.11.0.0/src/lock/plan.bend as P
20import ezx@1.11.0.0/src/lock/world.bend as W
21import ezx@1.11.0.0/src/lock/up.bend as Up
22import ezx@1.11.0.0/src/lock/lock.bend as L
23import ezx@1.11.0.0/src/ledger/manifest.bend as M
24import ezx@1.11.0.0/src/pkg/pkg.bend as K
25import ezx@1.11.0.0/src/relock/relock.bend as R
26
27
28
29type World is Data:
30 World{add: A.World, listing: W.Listing, locks: List<&2, W.Reply>}
31
32
33def add(world: World) -> A.World:
34 World{a, _listing, _locks} = world
35 a
36
37
38
39
40
41
42def found.pick(hit: Bool, body: String, rest: Unit -> String) -> String:
43 match hit:
44 case True{}:
45 body
46 case False{}:
47 rest(Unit{})
48
49
50def text.at(fs: List<&2, K.Source>, +at: String) -> String:
51 match fs:
52 case []:
53 ""
54 case K.Source{+p, body} <> t:
55 found.pick(String.eq(p, at), body, _u => text.at(t, at))
56
57
58def texts(+fs: List<&2, K.Source>, items: List<&2, K.Item>) -> List<&2, String>:
59 match items:
60 case []:
61 []
62 case K.Item{at, _sum} <> t:
63 text.at(fs, at) <> texts(fs, t)
64
65
66
67
68
69def seed.of(walk: K.Walked) -> List<&2, W.Reply>:
70 match walk:
71 case K.Walked{h, _root, +fs, ss}:
72 +manifest = K.manifest_of(ss)
73 [W.Reply{W.Pkg{h, L.Hub{}, ""},
74 W.Got{W.Lib{}, manifest, texts(fs, L.manifest.files(String.lines(manifest)))}}]
75 case K.Asks{_at}:
76 []
77 case K.Refused{_why}:
78 []
79
80
81
82def seeds.of(named: Bool, +aw: A.World) -> List<&2, W.Reply>:
83 match named:
84 case True{}:
85 A.hubs(aw)
86 case False{}:
87 seed.of(AP.walked(aw))
88
89
90def seeds(+aw: A.World) -> List<&2, W.Reply>:
91 seeds.of(A.named(aw), aw)
92
93
94
95
96def lock.world(world: World) -> W.World:
97 World{+a, listing, locks} = world
98 R.world(A.here(a), R.ledger(AP.command(a), A.ledger(a)), listing,
99 List.append(&2, W.Reply, seeds(a), locks))
100
101
102def lock(world: World) -> P.Plan:
103 P.plan(lock.world(world))
104
105
106
107
108
109def added.of(named: Bool, +aw: A.World) -> String:
110 match named:
111 case True{}:
112 H.hash(aw)
113 case False{}:
114 AP.hash(aw)
115
116
117def added(+aw: A.World) -> String:
118 added.of(A.named(aw), aw)
119
120
121def held(ps: List<&2, L.Pack>, +hash: String) -> Bool:
122 match ps:
123 case []:
124 False{}
125 case h <> t:
126 L.any.step(String.eq(L.pack.hash(h), hash), _u => held(t, hash))
127
128
129def unlocked(+hash: String) -> String:
130 "ez: no .bend file git lists imports " ++ hash ++ " yet, so ez.lock.toml does " ++
131 "not hold it. Import it, `git add` the file, and run `ez lock`."
132
133
134def notes.of(held: Bool, +hash: String) -> List<&2, P.Effect>:
135 match held:
136 case True{}:
137 []
138 case False{}:
139 [P.Say{unlocked(hash)}]
140
141
142def notes(+world: World) -> List<&2, P.Effect>:
143 notes.of(held(P.packs(lock.world(world)), added(add(world))), added(add(world)))
144
145
146
147
148
149
150
151def moved.of(moved: Bool, +name: String, +old: String, +new: String) -> String:
152 match moved:
153 case True{}:
154 "\nez: ez add moves " ++ name ++ " from " ++ old ++ " to " ++ new ++
155 "; a .bend file that imports " ++ old ++ " has to name " ++ new ++
156 " first, or `ez lock --upgrade --package " ++ name ++ "` moves it"
157 case False{}:
158 ""
159
160def tail.dep(+dep: M.Dep, +old: M.Dep) -> String:
161 "\nez: ez add wrote nothing, since it writes ez.toml and ez.lock.toml together" ++
162 moved.of(Bool.and(Bool.not(String.is_empty(M.dep.hash(old))),
163 Bool.not(String.eq(M.dep.hash(old), M.dep.hash(dep)))),
164 M.dep.name(dep), M.dep.hash(old), M.dep.hash(dep))
165
166
167def dep.of(named: Bool, +aw: A.World) -> M.Dep:
168 match named:
169 case True{}:
170 H.added(aw)
171 case False{}:
172 AP.added(aw)
173
174
175def tail(+aw: A.World) -> String:
176 +dep = dep.of(A.named(aw), aw)
177 tail.dep(dep, M.find(A.deps(aw), M.dep.name(dep)))
178
179
180def plan(world: World) -> P.Plan:
181 World{+a, +listing, +locks} = world
182 R.join(AP.command(a), lock(World{a, listing, locks}), notes(World{a, listing, locks}),
183 tail(a))
184
185
186def refuses(world: World) -> Bool:
187 R.refuses(plan(world))
188
189
190
191
192
193
194type Next is Data:
195 AskGit{asks: List<&2, Up.Ask>}
196 AskHub{asks: List<&2, W.Ask>}
197 AskLock{asks: List<&2, W.Ask>}
198 Planned{plan: P.Plan}
199
200
201def next.lock(st: P.Step, +world: World) -> Next:
202 match st:
203 case P.Asking{as, ups, ns}:
204 AskLock{R.asks(P.Asking{as, ups, ns})}
205 case P.Run{_pl}:
206 Planned{plan(world)}
207
208
209def next.made(refused: Bool, +world: World) -> Next:
210 match refused:
211 case True{}:
212 Planned{plan(world)}
213 case False{}:
214 next.lock(P.step(lock.world(world)), world)
215
216def next.add(nx: AP.Next, +world: World) -> Next:
217 match nx:
218 case AP.AskGit{asks}:
219 AskGit{asks}
220 case AP.AskHub{asks}:
221 AskHub{asks}
222 case AP.Planned{pl}:
223 next.made(R.refuses(pl), world)
224
225
226def next(+world: World) -> Next:
227 next.add(AP.next(add(world)), world)