1 # share/pin: a plain `ez lock` refuses a `[tools.*]` pin it would have to fill. 2 # It copies every pin as the ledger has it and never asks a remote, so a pin 3 # with no commit or no NAR hash stops it, naming the upgrade that fills the 4 # pin. Filling and moving a pin is `ez lock --upgrade`'s, in lock/up.bend. 5 import Base 6 import ../ledger/manifest.bend as M 7 8 # why a plain lock cannot copy a git pin as it stands, or "" when it can. The 9 # lock copies `rev` and `narHash` out of the ledger and never asks a remote 10 # for them, so a pin missing either is refused rather than filled, and the 11 # upgrade that fills it is named. 12 def gap.git(no_rev: Bool, no_nar: Bool, +name: String) -> String: 13 match no_rev: 14 case True{}: 15 "ez: tools." ++ name ++ " has no rev; run `ez lock --upgrade --package " ++ 16 name ++ "` to pin it" 17 case False{}: 18 match no_nar: 19 case True{}: 20 "ez: tools." ++ name ++ " has no narHash; run `ez lock --upgrade --package " ++ 21 name ++ "` to pin it" 22 case False{}: 23 "" 24 25 # why a plain lock cannot copy a pin as it stands, or "" when it can. A pin 26 # with no repo has nothing to pin, under a plain lock or an upgrade. 27 def gap(pin: M.Tool) -> String: 28 M.Tool{n, _e, _b, s} = pin 29 match s: 30 case M.Hub{_named}: 31 "ez: tools." ++ n ++ " has no git" 32 case M.Git{_url, rev, _tag, _root, nar, _vend}: 33 gap.git(String.is_empty(rev), String.is_empty(nar), n) 34 35 # this pin's gap when it has one, otherwise the rest's. The rest arrives as a 36 # thunk and only the arm that wants it applies it, so the first gap stops the 37 # scan. 38 def gaps.step(none: Bool, here: String, rest: Unit -> String) -> String: 39 match none: 40 case True{}: 41 rest(Unit{}) 42 case False{}: 43 here 44 45 # the first pin, in ledger order, a plain lock cannot copy, or "" when it can 46 # copy every one 47 def gaps(ts: List<&2, M.Tool>) -> String: 48 match ts: 49 case []: 50 "" 51 case h <> t: 52 +here = gap(h) 53 gaps.step(String.is_empty(here), here, _u => gaps(t))