1 # hub/hub: a file fetched from the hub, and checked against the hash that names 2 # it. bend accepts any prefix of the sha256, and a package's `0x` name is the 3 # first 32 characters of its manifest's digest, so the check is a prefix test. 4 import Base 5 import ../share/sha.bend as Sha 6 7 # The GET is ezhttp's, run by hub/get. What is kept here is the answer's shape: a status on 8 # its own first line and then the text, the shape a run answers with and the 9 # one curl's answer had, so `R.ok` and `R.text` read it. 10 11 # a status other than 200 is a miss with the number in it, never a body 12 def get.status(ok: Bool, status: U32, body: String) -> String: 13 match ok: 14 case True{}: 15 "0\n" ++ body 16 case False{}: 17 "22\nthe server answered " ++ U32.show(status) 18 19 # a file url read off the disk. curl served these too, and a test that wants a 20 # body without a server to serve it is the reason to keep them. 21 def get.file.got(got: Maybe<&2, String>, path: String) -> String: 22 match got: 23 case None{}: 24 "2\n" ++ path ++ " is not there" 25 case Some{s}: 26 "0\n" ++ s 27 28 # a body is the one that was asked for when its digest starts with the hash 29 def matches(want: String, +body: String) -> Bool: 30 String.starts_with(Sha.hex(body), want) 31 32 # what a fetch answered: the body when it arrived and hashed right, otherwise 33 # the reason, so a caller never mistakes an error page for a package file 34 type Got is Data: 35 Miss{why: String} 36 Have{body: String} 37 38 # the digest's verdict on a body that did arrive 39 def judge.hash(good: Bool, url: String, body: String) -> Got: 40 match good: 41 case True{}: 42 Have{body} 43 case False{}: 44 Miss{url ++ " does not hash to what was asked for"} 45 46 # a fetch judged, once the run and the digest are both known 47 def judge(ok: Bool, good: Bool, url: String, body: String) -> Got: 48 match ok: 49 case False{}: 50 Miss{url ++ ": " ++ body} 51 case True{}: 52 judge.hash(good, url, body) 53 54 # a fetch's outcome on one line 55 def show(got: Got) -> String: 56 match got: 57 case Miss{why}: 58 "miss " ++ why 59 case Have{body}: 60 "have " ++ body