src/sha/dump.bend
ezx@1.11.0.0 · 124 lines · 13 definitions
1
2
3
4
5
6import Base
7import snap@1.4.0.0/main.bend as R
8import ezx@1.11.0.0/src/io/file.bend as F
9import ezx@1.11.0.0/src/sha/nar.bend as Nar
10
11
12def said(ok: Bool, +why: String, +text: String) -> IO(String):
13 match ok:
14 case False{}:
15 IO.die(String, 1, "ez: nar hash: " ++ why ++ text)
16 case True{}:
17 IO.pure(String, text)
18
19
20
21def printed.at(ends: Bool, tail: String, rest: Unit -> String) -> String:
22 match ends:
23 case True{}:
24 tail
25 case False{}:
26 rest(Unit{})
27
28
29def printed(out: String) -> String:
30 match out:
31 case SNil{}:
32 ""
33 case SCon{c, +t}:
34 printed.at(Char.is_eq(c, '\n'), t, _u => printed(t))
35
36
37def under.top(+top: String, +at: String) -> String:
38 Bool.pick(String, String.is_empty(at), top, top ++ "/" ++ at)
39
40def file.got(got: Maybe<&2, String>, +path: String) -> IO(String):
41 match got:
42 case None{}:
43 IO.die(String, 1, "ez: nar hash: " ++ path ++ ": unreadable")
44 case Some{s}:
45 IO.pure(String, s)
46
47
48def file.of(+path: String) -> IO(String):
49 do IO<String>:
50 m : Maybe<&2, String> <- F.read(path)
51 file.got(m, path)
52
53
54
55def ent.other(
56 known: Bool,
57 +kind: String,
58 +name: String,
59 +at: String,
60 +target: String,
61 +path: String
62) -> IO(Nar.Ent):
63 match known:
64 case True{}:
65 IO.pure(Nar.Ent, Nar.Ent{kind, False{}, name, at, target})
66 case False{}:
67 IO.die(Nar.Ent, 1, "ez: nar hash: " ++ path ++ ": not a file, directory, or symlink")
68
69
70def ent.read(
71 file: Bool,
72 +kind: String,
73 +mode: String,
74 +name: String,
75 +at: String,
76 +target: String,
77 +path: String
78) -> IO(Nar.Ent):
79 match file:
80 case True{}:
81 do IO<Nar.Ent>:
82 body : String <- file.of(path)
83 return Nar.Ent{kind, Nar.owner.exec(mode), name, at, body}
84 case False{}:
85 ent.other(Bool.or(String.eq(kind, "d"), String.eq(kind, "l")), kind, name, at,
86 target, path)
87
88
89def ent.of(+top: String, row: Nar.Row) -> IO(Nar.Ent):
90 Nar.Row{+kind, +mode, +name, +at, +target} = row
91 ent.read(String.eq(kind, "f"), kind, mode, name, at, target, under.top(top, at))
92
93
94def ents(+top: String, rs: List<&2, Nar.Row>) -> IO(List<&2, Nar.Ent>):
95 match rs:
96 case []:
97 IO.pure(List<&2, Nar.Ent>, [])
98 case +h <> t:
99 do IO<List<&2, Nar.Ent>>:
100 e : Nar.Ent <- ent.of(top, h)
101 rest : List<&2, Nar.Ent> <- ents(top, t)
102 return e <> rest
103
104
105def built(got: Maybe<&2, String>, +path: String) -> IO(String):
106 match got:
107 case None{}:
108 IO.die(String, 1, "ez: nar hash: " ++ path ++ ": the listing does not make a tree")
109 case Some{node}:
110 IO.pure(String, node)
111
112
113def dump(+path: String) -> IO(String):
114 do IO<String>:
115 +out : String <- R.exec(Nar.listing.argv(path))
116 text : String <- said(R.ok(out), path ++ ": ", printed(out))
117 es : List<&2, Nar.Ent> <- ents(path, Nar.rows(Nar.cut(text)))
118 built(Nar.tree(es), path)
119
120
121def path(+work: String) -> IO(String):
122 do IO<String>:
123 node : String <- dump(work)
124 return Nar.sri(Nar.archive(node))