src/ws/hop.bend
ezx@1.10.0.0 · 113 lines · 0 definitions
1# ws/hop: where a whole-workspace command runs (EZ-WS-2). `ez lock`, `ez
2# fetch` and `ez doctor` act on the whole workspace from any member, so run in
3# a member they run again at the root, with the same words, and end as that
4# run ends. Run at the root, or in a project of its own, they run where they
5# are. Which of the three it is, and the line that runs again, are decided
6# here; ws/run.bend only reads what the search needs and runs what this says.
7import Base
8import ezx@1.10.0.0/src/pkg/path.bend as P
9import ezx@1.10.0.0/src/ws/workspace.bend as W
10import ezx@1.10.0.0/src/ws/root.bend as R
11
12# where a command runs: where it is, again at the root's directory, or
13# nowhere, because the search for the root was refused
14type Hop is Data:
15 Here{}
16 Hop{dir: String}
17 Stop{why: String}
18
19# the root a member found, once it is known whether that is where ez runs
20def hop.within(+top: String, root: List<&2, String>, rel: List<&2, String>) -> Hop:
21 match rel:
22 case []:
23 Here{}
24 case _hd <> _tl:
25 Hop{P.join(top, W.segs.text(root))}
26
27# where a command runs, from what the search found. `top` is the top of the
28# checkout, as git printed it.
29def hop(+top: String, found: R.Found) -> Hop:
30 match found:
31 case R.Alone{}:
32 Here{}
33 case R.Within{root, rel}:
34 hop.within(top, root, rel)
35 case R.Broken{why}:
36 Stop{why}
37
38# the program as it was started, found again from another directory: a path
39# with a `/` in it taken from where ez was started, and a bare name looked up
40# on PATH as it was
41def program(+pwd: String, +prog: String) -> String:
42 Bool.pick(String, String.contains(prog, "/"), P.anchor(pwd, prog), prog)
43
44# the line that runs the same command at the root: a shell that changes to the
45# root's directory and hands every word on as it was, with no word read by the
46# shell, which takes them as its positional parameters
47def line(+dir: String, +pwd: String, +prog: String, words: List<&2, String>) -> List<&2, String>:
48 List.append(&2, String,
49 ["sh", "-c", "cd -- \"$1\" && shift && exec \"$@\"", "sh", dir, program(pwd, prog)], words)
50
51# ---------------------------------------------------------------------------
52# the library a member's own command uses
53
54# the BEND_LIB a command run in a member uses: the one the environment sets,
55# or, when it sets none, the root's `.ez/lib`, where the workspace's lock lays
56# its packages
57type Lib is Data:
58 Keep{}
59 Set{lib: String}
60
61# the root a member found, once it is known whether that is where ez runs
62def lib.within(+top: String, root: List<&2, String>, rel: List<&2, String>) -> Lib:
63 match rel:
64 case []:
65 Keep{}
66 case _hd <> _tl:
67 Set{P.join(P.join(top, W.segs.text(root)), ".ez/lib")}
68
69# the library, once it is known whether the environment sets one
70def lib.found(set: Bool, +top: String, found: R.Found) -> Lib:
71 match set:
72 case True{}:
73 Keep{}
74 case False{}:
75 match found:
76 case R.Alone{}:
77 Keep{}
78 case R.Within{root, rel}:
79 lib.within(top, root, rel)
80 case R.Broken{_why}:
81 Keep{}
82
83# the library a member's own command uses: `env` is BEND_LIB as the
84# environment has it, "" for unset
85def lib(+top: String, found: R.Found, +env: String) -> Lib:
86 lib.found(Bool.not(String.is_empty(env)), top, found)
87
88# the line that runs the same command where it is, with BEND_LIB set
89def lib.line(+lib: String, +pwd: String, +prog: String, words: List<&2, String>) -> List<&2, String>:
90 List.append(&2, String,
91 ["sh", "-c", "BEND_LIB=\"$1\"; export BEND_LIB; shift; exec \"$@\"", "sh", lib, program(pwd, prog)], words)
92
93# ---------------------------------------------------------------------------
94# the lock a member's own command reads
95
96# the root a member found, once it is known whether that is where ez runs
97def lock.within(+top: String, root: List<&2, String>, rel: List<&2, String>) -> String:
98 match rel:
99 case []:
100 "ez.lock.toml"
101 case _hd <> _tl:
102 P.join(P.join(top, W.segs.text(root)), "ez.lock.toml")
103
104# the lock a command run in a directory reads: the root's, which is the only
105# one a workspace has, or its own in a project of its own and at the root
106def lock(+top: String, found: R.Found) -> String:
107 match found:
108 case R.Alone{}:
109 "ez.lock.toml"
110 case R.Within{root, rel}:
111 lock.within(top, root, rel)
112 case R.Broken{_why}:
113 "ez.lock.toml"