src/git/exec.bend
ezx@1.11.0.0 · 153 lines · 17 definitions
1
2
3
4
5
6
7import Base
8import snap@1.4.0.0/main.bend as R
9import ezx@1.11.0.0/src/pkg/path.bend as P
10import ezx@1.11.0.0/src/sha/dump.bend as Dump
11import ezx@1.11.0.0/src/share/say.bend as Say
12import ezx@1.11.0.0/src/share/spin.bend as Spin
13import ezx@1.11.0.0/src/git/git.bend as G
14
15
16def ran(ok: Bool, what: String, text: String) -> IO(Unit):
17 match ok:
18 case True{}:
19 IO.pure(Unit, Unit{})
20 case False{}:
21 IO.die(Unit, 1, "ez: git " ++ what ++ ": " ++ text)
22
23
24def run(what: String, args: List<&2, String>) -> IO(Unit):
25 do IO<Unit>:
26 +out : String <- R.exec(args)
27 ran(R.ok(out), what, R.text(out))
28
29
30
31
32
33
34
35def anchored(+url: String) -> IO(String):
36 do IO<String>:
37 +here : String <- R.exec(["pwd"])
38 return P.anchor(String.trim(R.text(here)), url)
39
40
41
42
43def clone.say(+work: String, +url: String, +rev: String, +msg: String) -> IO(Unit):
44 do IO<Unit>:
45 +s : Say.Spin <- Spin.hold(msg)
46 +from : String <- anchored(url)
47 run("init", ["git", "init", "-q", work])
48 run("fetch", ["git", "-C", work, "fetch", "-q", "--depth", "1", from, rev])
49 run("checkout", ["git", "-C", work, "checkout", "-q", rev])
50 Spin.done(s)
51
52
53def clone(+work: String, +url: String, +rev: String) -> IO(Unit):
54 clone.say(work, url, rev, Say.git.fetch(url))
55
56
57
58
59def nar(+work: String) -> IO(String):
60 Dump.path(work)
61
62
63
64def weigh(+url: String, +rev: String) -> IO(String):
65 +work = ".ez/weigh-" ++ rev
66 do IO<String>:
67 _rm : String <- R.exec(["rm", "-rf", work])
68 _mk : String <- R.exec(["mkdir", "-p", work])
69 clone(work, url, rev)
70 _dg : String <- R.exec(["rm", "-rf", work ++ "/.git"])
71 +s : Say.Spin <- Spin.hold(Say.hashing(rev))
72 +nh : String <- nar(work)
73 Spin.done(s)
74 _cl : String <- R.exec(["rm", "-rf", work])
75 return nh
76
77
78def remote.got(empty: Bool, +rev: String, +branch: String, +url: String) -> IO(G.Tip):
79 match empty:
80 case True{}:
81 IO.die(G.Tip, 1, "ez: " ++ url ++ " has no HEAD")
82 case False{}:
83 IO.pure(G.Tip, G.Tip{rev, branch})
84
85
86def remote.said(ok: Bool, +url: String, +text: String) -> IO(G.Tip):
87 match ok:
88 case False{}:
89 IO.die(G.Tip, 1, "ez: git ls-remote " ++ url ++ ": " ++ text)
90 case True{}:
91 +rs = G.rows(String.lines(text))
92 remote.got(String.is_empty(G.tip.rev(rs)), G.tip.rev(rs), G.tip.branch(rs), url)
93
94
95
96def remote(+url: String) -> IO(G.Tip):
97 do IO<G.Tip>:
98 +from : String <- anchored(url)
99 +out : String <- R.exec(["git", "ls-remote", "--symref", from, "HEAD"])
100 remote.said(R.ok(out), url, R.text(out))
101
102
103
104def clone.bare(+work: String, +url: String) -> IO(Unit):
105 do IO<Unit>:
106 +s : Say.Spin <- Spin.hold(Say.git.fetch(url))
107 +from : String <- anchored(url)
108 run("clone", ["git", "clone", "--bare", "--filter=blob:none", "-q", from, work])
109 Spin.done(s)
110
111
112
113def descendant.no(no: Bool, +text: String) -> IO(Bool):
114 match no:
115 case True{}:
116 IO.pure(Bool, False{})
117 case False{}:
118 IO.die(Bool, 1, "ez: git merge-base: " ++ text)
119
120
121def descendant.pick(yes: Bool, no: Bool, text: String) -> IO(Bool):
122 match yes:
123 case True{}:
124 IO.pure(Bool, True{})
125 case False{}:
126 descendant.no(no, text)
127
128
129def descendant.code(+code: String, +text: String) -> IO(Bool):
130 descendant.pick(String.eq(code, "0"), String.eq(code, "1"), text)
131
132
133
134def descendant.clone(+work: String, +url: String, +pin: String, +tip: String) -> IO(Bool):
135 do IO<Bool>:
136 _rm : String <- R.exec(["rm", "-rf", work])
137 clone.bare(work, url)
138 +out : String <- R.exec(["git", "-C", work, "merge-base", "--is-ancestor",
139 pin, tip])
140 _cl : String <- R.exec(["rm", "-rf", work])
141 descendant.code(R.code(out), R.text(out))
142
143
144def descendant.go(same: Bool, work: String, url: String, pin: String, tip: String) -> IO(Bool):
145 match same:
146 case True{}:
147 IO.pure(Bool, True{})
148 case False{}:
149 descendant.clone(work, url, pin, tip)
150
151
152def descendant.at(+work: String, +url: String, +pin: String, +tip: String) -> IO(Bool):
153 descendant.go(String.eq(pin, tip), work, url, pin, tip)