mirror of
https://github.com/urbit/shrub.git
synced 2024-12-13 16:03:36 +03:00
Merge branch 'test' of https://github.com/urbit/urbit into test
This commit is contained in:
commit
56f03cc709
@ -1787,7 +1787,7 @@
|
||||
%- aeon-to-tako
|
||||
let
|
||||
?^(r.mun ~ [~ [t.yak (forge-nori yak)]])
|
||||
::?> ?=(^ hit) ?^(r.mun ~ [~ i.hit]) :: what do?? need [@da nori]
|
||||
::?> ?=(^ hit) ?^(r.mun ~ [~ i.hit]) :: what do?? need [@da nori]
|
||||
(query(ank ank:(descend-path:(zu ank) r.mun)) p.mun)
|
||||
::
|
||||
++ read-at-aeon :: read-at-aeon:ze
|
||||
|
@ -49,8 +49,6 @@ to clay is stored in this state.
|
||||
`fat` is the set of domestic servers. This stores all the information that is
|
||||
specfic to a particular ship on this pier. The keys to this map are the ships
|
||||
on the current pier.
|
||||
|
||||
`hoy` is the set of foreign servers that we know anything about. This stores
|
||||
all the information that is specific to a particular foreign ship. The keys to
|
||||
this map are all the ships whose filesystems we have attempted to access
|
||||
through clay.
|
||||
@ -954,9 +952,8 @@ actually try to read the data.
|
||||
!!
|
||||
=+ ezy=?~(ref ~ (~(get by haw.u.ref) mun))
|
||||
?^ ezy ezy
|
||||
=+ nao=(~(aeon ze lim dom ran) q.mun)
|
||||
:: ~& [%aver-mun nao [%from syd lim q.mun]]
|
||||
?~(nao ~ [~ (~(avid ze lim dom ran) u.nao mun)])
|
||||
=+ nao=(~(case-to-aeon ze lim dom ran) q.mun)
|
||||
?~(nao ~ [~ (~(read-at-aeon ze lim dom ran) u.nao mun)])
|
||||
```
|
||||
|
||||
We check immediately that we're not requesting the `rang` for any time other
|
||||
@ -971,21 +968,21 @@ specified by the given case, and then we try to get the data there.
|
||||
|
||||
Here, we jump into `arvo/zuse.hoon`, which is where much of the algorithmic
|
||||
code is stored, as opposed to the clay interface, which is stored in
|
||||
`arvo/clay.hoon`. We examine `++aeon:ze`.
|
||||
`arvo/clay.hoon`. We examine `++case-to-aeon:ze`.
|
||||
|
||||
```
|
||||
++ aeon :: aeon:ze
|
||||
++ case-to-aeon :: case-to-aeon:ze
|
||||
|= lok=case :: act count through
|
||||
^- (unit ,@ud)
|
||||
^- (unit aeon)
|
||||
?- -.lok
|
||||
%da
|
||||
?: (gth p.lok lim) ~
|
||||
|- ^- (unit ,@ud)
|
||||
|- ^- (unit aeon)
|
||||
?: =(0 let) [~ 0] :: avoid underflow
|
||||
?: %+ gte p.lok
|
||||
=< t
|
||||
%- ~(got by hut)
|
||||
%- ~(got by hit)
|
||||
%- tako-to-yaki
|
||||
%- aeon-to-tako
|
||||
let
|
||||
[~ let]
|
||||
$(let (dec let))
|
||||
@ -998,7 +995,7 @@ code is stored, as opposed to the clay interface, which is stored in
|
||||
We handle each type of `case` differently. The latter two types are easy.
|
||||
|
||||
If we're requesting a revision by label, then we simply look up the requested
|
||||
label in `lab` from the given dome. If it exists, that is our number; else we
|
||||
label in `lab` from the given dome. If it exists, that is our aeon; else we
|
||||
produce null, indicating the requested revision does not yet exist.
|
||||
|
||||
If we're requesting a revision by number, we check if we've yet reached that
|
||||
@ -1010,30 +1007,30 @@ scan backwards until we find the first revision committed before that date, and
|
||||
we produce that. If we requested a date before any revisions were committed,
|
||||
we produce `0`.
|
||||
|
||||
Assuming we got a valid version number, `++aver` calls `++avid:ze`, which reads
|
||||
the requested data at the given revision.
|
||||
Assuming we got a valid version number, `++aver` calls `++read-at-aeon:ze`,
|
||||
which reads the requested data at the given revision.
|
||||
|
||||
```
|
||||
++ avid :: avid:ze
|
||||
|= [oan=@ud mun=mood] :: seek and read
|
||||
++ read-at-aeon :: read-at-aeon:ze
|
||||
|= [oan=aeon mun=mood] :: seek and read
|
||||
^- (unit)
|
||||
?: &(?=(%w p.mun) !?=(%ud -.q.mun)) :: NB only for speed
|
||||
?^(r.mun ~ [~ oan])
|
||||
(auto:(argo oan) mun)
|
||||
(read:(rewind oan) mun)
|
||||
```
|
||||
|
||||
If we're requesting the revision number with a case other than by number, then
|
||||
we go ahead and just produce the number we were given. Otherwise, we call
|
||||
`++argo` to rewind our state to the given revision, and then we call `++auto`
|
||||
`++rewind` to rewind our state to the given revision, and then we call `++read`
|
||||
to get the requested information.
|
||||
|
||||
```
|
||||
++ argo :: argo:ze
|
||||
|= oan=@ud :: rewind to aeon
|
||||
++ rewind :: rewind:ze
|
||||
|= oan=aeon :: rewind to aeon
|
||||
^+ +>
|
||||
?: =(let oan) +>
|
||||
?: (gth oan let) !! :: don't have this version
|
||||
+>(ank (azel q:(~(got by hut) (~(got by hit) oan))), let oan)
|
||||
?: (gth oan let) !! :: don't have version
|
||||
+>(ank (checkout-ankh q:(tako-to-yaki (aeon-to-tako oan))), let oan)
|
||||
```
|
||||
|
||||
If we're already at the requested version, we do nothing. If we're requesting
|
||||
@ -1041,11 +1038,11 @@ a version later than our head, we are unable to comply.
|
||||
|
||||
Otherwise, we get the hash of the commit at the number, and from that we get
|
||||
the commit itself (the yaki), which has the map of path to lobe that represents
|
||||
a version of the filesystem. We call `++azel` to checkout the commit, and we
|
||||
a version of the filesystem. We call `++checkout-ankh` to checkout the commit, and we
|
||||
replace `ank` in our context with the result.
|
||||
|
||||
```
|
||||
++ azel :: azel:ze
|
||||
++ checkout-ankh :: checkout-ankh:ze
|
||||
|= hat=(map path lobe) :: checkout commit
|
||||
^- ankh
|
||||
%- cosh
|
||||
@ -1054,7 +1051,7 @@ replace `ank` in our context with the result.
|
||||
^- ankh
|
||||
%- cosh
|
||||
?~ pat
|
||||
=+ zar=(zaul bar)
|
||||
=+ zar=(lobe-to-noun bar)
|
||||
ank(q [~ (sham zar) zar])
|
||||
=+ nak=(~(get by r.ank) i.pat)
|
||||
%= ank
|
||||
@ -1064,16 +1061,16 @@ replace `ank` in our context with the result.
|
||||
```
|
||||
|
||||
Twice we call `++cosh`, which hashes a commit, updating `p` in an `ankh`.
|
||||
Let's jump into that algorithm before we describe `++azel`.
|
||||
Let's jump into that algorithm before we describe `++checkout-ankh`.
|
||||
|
||||
```
|
||||
++ cosh :: locally rehash
|
||||
|= ank=ankh
|
||||
ank(p dash:(zu ank))
|
||||
|= ank=ankh :: NB v/unix.c
|
||||
ank(p rehash:(zu ank))
|
||||
```
|
||||
|
||||
We simply replace `p` in the hash with the `cash` we get from a call to
|
||||
`++dash:zu`.
|
||||
`++rehash:zu`.
|
||||
|
||||
```
|
||||
++ zu !: :: filesystem
|
||||
@ -1081,7 +1078,7 @@ We simply replace `p` in the hash with the `cash` we get from a call to
|
||||
=| myz=(list ,[p=path q=miso]) :: changes in reverse
|
||||
=| ram=path :: reverse path into
|
||||
|%
|
||||
++ dash :: local rehash
|
||||
++ rehash :: local rehash
|
||||
^- cash
|
||||
%+ mix ?~(q.ank 0 p.u.q.ank)
|
||||
=+ axe=1
|
||||
@ -1098,43 +1095,40 @@ We simply replace `p` in the hash with the `cash` we get from a call to
|
||||
checkout of the filesystem and access the actual data inside it. One of the
|
||||
things we can do with it is to create a recursive hash of the node.
|
||||
|
||||
In `++dash`, if this node is a file, then we xor the remainder of the hash with
|
||||
the hash of the contents of the file. The remainder of the hash is `0` if we
|
||||
have no children, else we descend into our children. Basically, we do a half
|
||||
SHA-256 of the xor of the axis of this child and the half SHA-256 of the xor of
|
||||
the name of the child and the hash of the child. This is done for each child
|
||||
and all the results are xored together.
|
||||
In `++rehash`, if this node is a file, then we xor the remainder of the hash
|
||||
with the hash of the contents of the file. The remainder of the hash is `0` if
|
||||
we have no children, else we descend into our children. Basically, we do a
|
||||
half SHA-256 of the xor of the axis of this child and the half SHA-256 of the
|
||||
xor of the name of the child and the hash of the child. This is done for each
|
||||
child and all the results are xored together.
|
||||
|
||||
Now we return to our discussion of `++azel`.
|
||||
Now we return to our discussion of `++checkout-ankh`.
|
||||
|
||||
We fold over every path in this version of the filesystem and create a great
|
||||
ankh out of them. First, we call `++zaul` to get the raw data referred to be
|
||||
each lobe.
|
||||
ankh out of them. First, we call `++lobe-to-noun` to get the raw data referred
|
||||
to be each lobe.
|
||||
|
||||
```
|
||||
++ zaul :: grab blob
|
||||
++ lobe-to-noun :: grab blob
|
||||
|= p=lobe :: ^- *
|
||||
%- zaru
|
||||
(zaal p)
|
||||
%- blob-to-noun
|
||||
(lobe-to-blob p)
|
||||
```
|
||||
|
||||
This converts a lobe into the raw data it refers to by first getting the blob
|
||||
with `++zaal` and converting that into data with `++zaru`.
|
||||
with `++lobe-to-blob` and converting that into data with `++blob-to-noun`.
|
||||
|
||||
```
|
||||
++ zaal :: grab blob
|
||||
|= p=lobe :: (raw)
|
||||
^- blob
|
||||
(~(got by lat) p)
|
||||
++ lobe-to-blob ~(got by lat) :: grab blob
|
||||
```
|
||||
|
||||
This just grabs the blob that the lobe refers to.
|
||||
|
||||
```
|
||||
++ zaru :: grab blob
|
||||
++ blob-to-noun :: grab blob
|
||||
|= p=blob
|
||||
?- -.p
|
||||
%delta (lump r.p (zaul q.p))
|
||||
%delta (lump r.p (lobe-to-noun q.p))
|
||||
%direct q.p
|
||||
%indirect q.p
|
||||
==
|
||||
@ -1211,10 +1205,10 @@ are what we expect them to be (`p.i.rug`), crashing on failure. If they're
|
||||
good, then we append the new lines in `q.i.rug` onto `war`.
|
||||
|
||||
And that's really it. List merges are pretty easy. Anyway, if you recall, we
|
||||
were discussing `++azel`.
|
||||
were discussing `++checkout-ankh`.
|
||||
|
||||
```
|
||||
++ azel :: azel:ze
|
||||
++ checkout-ankh :: checkout-ankh:ze
|
||||
|= hat=(map path lobe) :: checkout commit
|
||||
^- ankh
|
||||
%- cosh
|
||||
@ -1223,7 +1217,7 @@ were discussing `++azel`.
|
||||
^- ankh
|
||||
%- cosh
|
||||
?~ pat
|
||||
=+ zar=(zaul bar)
|
||||
=+ zar=(lobe-to-noun bar)
|
||||
ank(q [~ (sham zar) zar])
|
||||
=+ nak=(~(get by r.ank) i.pat)
|
||||
%= ank
|
||||
@ -1235,7 +1229,7 @@ were discussing `++azel`.
|
||||
If the path is null, then we calculate `zar`, the raw data at the path `pat` in
|
||||
this version. We produce the given ankh with the correct data.
|
||||
|
||||
Otherwise, we try to get the child we're looking at from our parent `ankh`. If
|
||||
Otherwise, we try to get the child we're looking at from our parent ankh. If
|
||||
it's already been created, this succeeds; otherwise, we simply create a default
|
||||
blank ankh. We place ourselves in our parent after recursively computing our
|
||||
children.
|
||||
@ -1271,7 +1265,7 @@ In the recursion, we our path is `/english` and our ankh is again blank. We
|
||||
try to get the `english` child of our ankh, but this of course fails. Thus,
|
||||
we update our blank `/greeting` ankh with a child `english` produced by recursing.
|
||||
|
||||
Now our path is null, so we call `++zaul` to get the actual data, and we place
|
||||
Now our path is null, so we call `++lobe-to-noun` to get the actual data, and we place
|
||||
it in the brand-new ankh.
|
||||
|
||||
Next, we process `/greeting/russian/short`. Since our path is not null, we try
|
||||
@ -1310,54 +1304,55 @@ depending on what order the paths come in, but the resulting tree is
|
||||
independent of order.
|
||||
|
||||
At any rate, we were talking about something important, weren't we? If you
|
||||
recall, that concludes our discussion of `++argo`, which was called from
|
||||
`++avid`. In summary, `++argo` returns a context in which our current state is
|
||||
(very nearly) as it was when the specified version of the desk was the head.
|
||||
This allows `++avid` to call `++auto` to read the requested information.
|
||||
recall, that concludes our discussion of `++rewind`, which was called from
|
||||
`++read-at-aeon`. In summary, `++rewind` returns a context in which our
|
||||
current state is (very nearly) as it was when the specified version of the desk
|
||||
was the head. This allows `++read-at-aeon` to call `++read` to read the
|
||||
requested information.
|
||||
|
||||
```
|
||||
++ auto :: auto:ze
|
||||
++ read :: read:ze
|
||||
|= mun=mood :: read at point
|
||||
^- (unit)
|
||||
?: ?=(%v p.mun)
|
||||
[~ `dome`+<+<.auto]
|
||||
[~ `dome`+<+<.read]
|
||||
?: &(?=(%w p.mun) !?=(%ud -.q.mun))
|
||||
?^(r.mun ~ [~ let])
|
||||
?: ?=(%w p.mun)
|
||||
=+ ^= yak
|
||||
%- ~(got by hut)
|
||||
%- ~(got by hit)
|
||||
%- tako-to-yaki
|
||||
%- aeon-to-tako
|
||||
let
|
||||
?^(r.mun ~ [~ [t.yak (azul yak)]])
|
||||
::?> ?=(^ hit) ?^(r.mun ~ [~ i.hit]) :: what do?? need [@da nori]
|
||||
(amor(ank ank:(deny:(zu ank) r.mun)) p.mun)
|
||||
?^(r.mun ~ [~ [t.yak (forge-nori yak)]])
|
||||
::?> ?=(^ hit) ?^(r.mun ~ [~ i.hit]) :: what do?? need [@da nori]
|
||||
(query(ank ank:(descend-path:(zu ank) r.mun)) p.mun)
|
||||
```
|
||||
|
||||
If we're requesting the dome, then we just return that immediately.
|
||||
|
||||
If we're requesting the revision number of the desk and we're not requesting it
|
||||
by number, then we just return the current number of this desk. Note of course
|
||||
that this was really already handled in `++avid`.
|
||||
that this was really already handled in `++read-at-aeon`.
|
||||
|
||||
If we're requesting a `%w` with a specific revision number, then we do
|
||||
something or other with the commit there. It's kind of weird, and it doesn't
|
||||
seem to work, so we'll ignore this case.
|
||||
|
||||
Otherwise, we descend into the ankh tree with `++deny:zu` to the given path,
|
||||
and then we handle specific request in `++amor`.
|
||||
Otherwise, we descend into the ankh tree to the given path with
|
||||
`++descend-path:zu`, and then we handle specific request in `++query`.
|
||||
|
||||
```
|
||||
++ deny :: descend recursively
|
||||
++ descend-path :: descend recursively
|
||||
|= way=path
|
||||
^+ +>
|
||||
?~(way +> $(way t.way, +> (dent i.way)))
|
||||
?~(way +> $(way t.way, +> (descend i.way)))
|
||||
```
|
||||
|
||||
This is simple recursion down into the ankh tree. `++dent` descends one level,
|
||||
so this will eventually get us down to the path we want.
|
||||
This is simple recursion down into the ankh tree. `++descend` descends one
|
||||
level, so this will eventually get us down to the path we want.
|
||||
|
||||
```
|
||||
++ dent :: descend
|
||||
++ descend :: descend
|
||||
|= lol=@ta
|
||||
^+ +>
|
||||
=+ you=(~(get by r.ank) lol)
|
||||
@ -1372,24 +1367,25 @@ Once we've decscended to the correct level, we need to actually deal with the
|
||||
request.
|
||||
|
||||
```
|
||||
++ amor :: amor:ze
|
||||
++ query :: query:ze
|
||||
|= ren=?(%u %v %x %y %z) :: endpoint query
|
||||
^- (unit ,*)
|
||||
?- ren
|
||||
%u [~ `rang`+<+>.amor]
|
||||
%v [~ `dome`+<+<.amor]
|
||||
%u [~ `rang`+<+>.query]
|
||||
%v [~ `dome`+<+<.query]
|
||||
%x ?~(q.ank ~ [~ q.u.q.ank])
|
||||
%y [~ ache]
|
||||
%y [~ as-arch]
|
||||
%z [~ ank]
|
||||
==
|
||||
```
|
||||
|
||||
Now that everything's set up, it's really easy. If they're requesting the rang
|
||||
, dome, or ankh, we give it to them. If the contents of a file, we give it to
|
||||
them if it is in fact a file. If the `arch`, then we calculate it with `++ache`.
|
||||
Now that everything's set up, it's really easy. If they're requesting the
|
||||
rang, dome, or ankh, we give it to them. If the contents of a file, we give it
|
||||
to them if it is in fact a file. If the `arch`, then we calculate it with
|
||||
`++as-arch`.
|
||||
|
||||
```
|
||||
++ ache :: ache:ze
|
||||
++ as-arch :: as-arch:ze
|
||||
^- arch :: arch report
|
||||
:+ p.ank
|
||||
?~(q.ank ~ [~ p.u.q.ank])
|
||||
@ -1411,19 +1407,19 @@ rave. If the head was `&`, then it was a single request, so we handled it
|
||||
above. If `|`, then we handle it with the following code.
|
||||
|
||||
```
|
||||
=+ nab=(~(aeon ze lim dom ran) p.p.rav)
|
||||
=+ nab=(~(case-to-aeon ze lim dom ran) p.p.rav)
|
||||
?~ nab
|
||||
?> =(~ (~(aeon ze lim dom ran) q.p.rav))
|
||||
?> =(~ (~(case-to-aeon ze lim dom ran) q.p.rav))
|
||||
(duce hen (rive rav))
|
||||
=+ huy=(~(aeon ze lim dom ran) q.p.rav)
|
||||
=+ huy=(~(case-to-aeon ze lim dom ran) q.p.rav)
|
||||
?: &(?=(^ huy) |((lth u.huy u.nab) &(=(0 u.huy) =(0 u.nab))))
|
||||
(blub hen)
|
||||
=+ top=?~(huy let.dom u.huy)
|
||||
=+ sar=(~(apax ze lim dom ran) u.nab r.p.rav)
|
||||
=+ ear=(~(apax ze lim dom ran) top r.p.rav)
|
||||
=+ sar=(~(lobes-at-path ze lim dom ran) u.nab r.p.rav)
|
||||
=+ ear=(~(lobes-at-path ze lim dom ran) top r.p.rav)
|
||||
=. +>.$
|
||||
?: =(sar ear) +>.$
|
||||
=+ fud=(~(gack ze lim dom ran) u.nab top)
|
||||
=+ fud=(~(make-nako ze lim dom ran) u.nab top)
|
||||
(bleb hen u.nab fud)
|
||||
?^ huy
|
||||
(blub hen)
|
||||
@ -1433,9 +1429,9 @@ above. If `|`, then we handle it with the following code.
|
||||
==
|
||||
```
|
||||
|
||||
Recall that `++aeon:ze` produces the revision number that a case corresponds
|
||||
to, if it corresponds to any. If it doesn't yet correspond to a revision, then
|
||||
it produces null.
|
||||
Recall that `++case-to-aeon:ze` produces the revision number that a case
|
||||
corresponds to, if it corresponds to any. If it doesn't yet correspond to a
|
||||
revision, then it produces null.
|
||||
|
||||
Thus, we first check to see if we've even gotten to the beginning of the range
|
||||
of revisions requested. If not, then we assert that we haven't yet gotten to
|
||||
@ -1462,8 +1458,9 @@ If there will be more revisions in the subscription, then we call `++duce`,
|
||||
adding the duct to our subscribers. We modify the rove to start at the next
|
||||
revision since we've already handled all the revisions up to the present.
|
||||
|
||||
We glossed over the calls to `++apax`, `++gack`, and `++bleb`, so we'll get
|
||||
back to those right now. `++bleb` is simple, so we'll start with that.
|
||||
We glossed over the calls to `++lobes-at-path`, `++make-nako`, and `++bleb`, so
|
||||
we'll get back to those right now. `++bleb` is simple, so we'll start with
|
||||
that.
|
||||
|
||||
```
|
||||
++ bleb :: ship sequence
|
||||
@ -1477,11 +1474,11 @@ the updates since that revision. We use `++blab` to produce this result to
|
||||
the subscriber. The case is `%w` with a revision number of the beginning of the
|
||||
subscription, and the data is the nako itself.
|
||||
|
||||
We call `++apax:ze` to get the data at the particular path.
|
||||
We call `++lobes-at-path:ze` to get the data at the particular path.
|
||||
|
||||
```
|
||||
++ apax :: apax:ze
|
||||
|= [oan=@ud pax=path] :: data at path
|
||||
++ lobes-at-path :: lobes-at-path:ze
|
||||
|= [oan=aeon pax=path] :: data at path
|
||||
^- (map path lobe)
|
||||
?: =(0 oan) ~
|
||||
%- mo
|
||||
@ -1489,8 +1486,8 @@ We call `++apax:ze` to get the data at the particular path.
|
||||
%. ~
|
||||
%~ tap by
|
||||
=< q
|
||||
%- ~(got by hut)
|
||||
%- ~(got by hit)
|
||||
%- tako-to-yaki
|
||||
%- aeon-to-tako
|
||||
oan
|
||||
|= [p=path q=lobe]
|
||||
?| ?=(~ pax)
|
||||
@ -1510,20 +1507,20 @@ the hash of their data. This is simple and efficient to calculate and compare
|
||||
to later revisions. This allows us to easily tell if a node or its children
|
||||
have changed.
|
||||
|
||||
Finally, we will describe `++gack:ze`.
|
||||
Finally, we will describe `++make-nako:ze`.
|
||||
|
||||
```
|
||||
++ gack :: gack a through b
|
||||
|= [a=@ud b=@ud]
|
||||
^- [(map ,@ud tako) @ud (set yaki) (set blob)]
|
||||
++ make-nako :: gack a through b
|
||||
|= [a=aeon b=aeon]
|
||||
^- [(map aeon tako) aeon (set yaki) (set blob)]
|
||||
:_ :- b
|
||||
%- hack
|
||||
%+ pack
|
||||
(~(get by hit) a) :: if a not found, a=0
|
||||
%- need (~(get by hit) b)
|
||||
^- (map ,@ud tako)
|
||||
=- [(takos-to-yakis -<) (lobes-to-blobs ->)]
|
||||
%+ reachable-between-takos
|
||||
(~(get by hit) a) :: if a not found, a=0
|
||||
(aeon-to-tako b)
|
||||
^- (map aeon tako)
|
||||
%- mo %+ skim (~(tap by hit) ~)
|
||||
|= [p=@ud *]
|
||||
|= [p=aeon *]
|
||||
&((gth p a) (lte p b))
|
||||
```
|
||||
|
||||
@ -1537,18 +1534,18 @@ commits and produce all those numbered greater than `a` and not greater than
|
||||
The second is even easier to produce -- `b` is clearly our most recent commit.
|
||||
|
||||
The third and fourth are slightly more interesting, though not too terribly
|
||||
difficult. First, we call `++pack`.
|
||||
difficult. First, we call `++reachable-between-takos`.
|
||||
|
||||
```
|
||||
++ pack
|
||||
|= [a=(unit tako) b=tako] :: pack a through b
|
||||
++ reachable-between-takos
|
||||
|= [a=(unit tako) b=tako] :: pack a through b
|
||||
^- [(set tako) (set lobe)]
|
||||
=+ ^= sar
|
||||
?~ a ~
|
||||
(zule r:(need (~(get by hut) u.a)))
|
||||
=+ yak=`yaki`(need (~(get by hut) b))
|
||||
%+ garf (garg ~ sar) :: get lobes
|
||||
|- ^- (set tako) :: walk onto sar
|
||||
(reachable-takos r:(tako-to-yaki u.a))
|
||||
=+ yak=`yaki`(tako-to-yaki b)
|
||||
%+ new-lobes-takos (new-lobes ~ sar) :: get lobes
|
||||
|- ^- (set tako) :: walk onto sar
|
||||
?: (~(has in sar) r.yak)
|
||||
~
|
||||
=+ ber=`(set tako)`(~(put in `(set tako)`~) `tako`r.yak)
|
||||
@ -1557,71 +1554,33 @@ difficult. First, we call `++pack`.
|
||||
%+ roll p.yak
|
||||
|= [yek=tako bar=(set tako)]
|
||||
^- (set tako)
|
||||
?: (~(has in bar) yek) :: save some time
|
||||
?: (~(has in bar) yek) :: save some time
|
||||
bar
|
||||
%- ~(uni in bar)
|
||||
^$(yak (need (~(get by hut) yek)))
|
||||
^$(yak (tako-to-yaki yek))
|
||||
```
|
||||
|
||||
We take a possible starting commit and a definite ending commit, and we produce
|
||||
the set of commits and the set of data between them.
|
||||
|
||||
We let `sar` be the set of commits reachable from `a`. If `a` is null, then
|
||||
obviously no commits are reachable. Otherwise, we call `++zule` to calculate this.
|
||||
|
||||
```
|
||||
++ hack :: trivial
|
||||
|= [a=(set tako) b=(set lobe)]
|
||||
^- [(set yaki) (set blob)]
|
||||
:- %- sa %+ turn (~(tap by a) ~)
|
||||
|= tak=tako
|
||||
(need (~(get by hut) tak))
|
||||
%- sa %+ turn (~(tap by b) ~)
|
||||
|= lob=lobe
|
||||
(need (~(get by lat) lob))
|
||||
```
|
||||
obviously no commits are reachable. Otherwise, we call `++reachable-takos` to
|
||||
calculate this.
|
||||
|
||||
The type signature says everything you need to know about this. We take a set
|
||||
of hashes of commits and data and convert them into the actual commits and data
|
||||
in the most straightforward way possible.
|
||||
|
||||
```
|
||||
++ zule :: reachable
|
||||
|= p=tako :: XX slow
|
||||
++ reachable-takos :: reachable
|
||||
|= p=tako :: XX slow
|
||||
^- (set tako)
|
||||
=+ y=(~(got by hut) p)
|
||||
=+ y=(tako-to-yaki p)
|
||||
=+ t=(~(put in _(set tako)) p)
|
||||
%+ roll p.y
|
||||
|= [q=tako s=_t]
|
||||
?: (~(has in s) q) :: already done
|
||||
s :: hence skip
|
||||
(~(uni in s) ^$(p q)) :: otherwise traverse
|
||||
?: (~(has in s) q) :: already done
|
||||
s :: hence skip
|
||||
(~(uni in s) ^$(p q)) :: otherwise traverse
|
||||
```
|
||||
|
||||
```
|
||||
++ garg :: object hash set
|
||||
|= [b=(set lobe) a=(set tako)] :: that aren't in b
|
||||
^- (set lobe)
|
||||
%+ roll (~(tap in a) ~)
|
||||
|= [tak=tako bar=(set lobe)]
|
||||
^- (set lobe)
|
||||
=+ yak=(need (~(get by hut) tak))
|
||||
%+ roll (~(tap by q.yak) ~)
|
||||
|= [[path lob=lobe] far=_bar]
|
||||
^- (set lobe)
|
||||
?~ (~(has in b) lob) :: don't need
|
||||
far
|
||||
=+ gar=(need (~(get by lat) lob))
|
||||
?- -.gar
|
||||
%direct (~(put in far) lob)
|
||||
%delta (~(put in $(lob q.gar)) lob)
|
||||
%indirect (~(put in $(lob s.gar)) lob)
|
||||
==
|
||||
```
|
||||
|
||||
```
|
||||
++ garf :: garg & repack
|
||||
|= [b=(set lobe) a=(set tako)]
|
||||
^- [(set tako) (set lobe)]
|
||||
[a (garg b a)]
|
||||
```
|
||||
|
Loading…
Reference in New Issue
Block a user