mirror of
https://github.com/urbit/shrub.git
synced 2024-12-14 01:08:54 +03:00
Merge branch 'test'
This commit is contained in:
commit
3c01a8a5d4
@ -86,6 +86,7 @@
|
||||
++ peer-drum (wrap peer):from-drum
|
||||
++ poke-dill-belt (wrap poke-dill-belt):from-drum
|
||||
++ poke-drum-link (wrap poke-link):from-drum
|
||||
++ poke-drum-unlink (wrap poke-unlink):from-drum
|
||||
::++ poke-drum-exit (wrap poke-exit):from-drum
|
||||
++ poke-drum-start (wrap poke-start):from-drum
|
||||
++ poke-helm-hi (wrap poke-hi):from-helm
|
||||
|
@ -1430,8 +1430,8 @@
|
||||
^- (bolt type)
|
||||
%+ (clef %slit) (fine cof gat sam)
|
||||
|= [cof=cafe gat=type sam=type]
|
||||
%+ cool |.(>sam<)
|
||||
%+ cool |.(>(~(peek ut gat) %free 6)<)
|
||||
%+ cool |.(%.(%have ~(dunk ut sam)))
|
||||
%+ cool |.(%.(%want ~(dunk ut (~(peek ut gat) %free 6))))
|
||||
=+ top=(mule |.((slit gat sam)))
|
||||
?- -.top
|
||||
| (flaw cof p.top)
|
||||
|
@ -1,2 +0,0 @@
|
||||
/: /%%%/tree/pub/blog /% /hymn/
|
||||
-<
|
@ -1,2 +0,0 @@
|
||||
/: /%%%/tree/pub/blog /% /json/
|
||||
-<
|
2
docs/hymn.hook
Normal file
2
docs/hymn.hook
Normal file
@ -0,0 +1,2 @@
|
||||
/: /%%%/tree/pub/docs /% /hymn/
|
||||
-<
|
2
docs/json.hook
Normal file
2
docs/json.hook
Normal file
@ -0,0 +1,2 @@
|
||||
/: /%%%/tree/pub/docs /% /json/
|
||||
-<
|
2
front/hymn.hook
Normal file
2
front/hymn.hook
Normal file
@ -0,0 +1,2 @@
|
||||
/: /%%%/tree/pub/front /% /hymn/
|
||||
-<
|
2
front/json.hook
Normal file
2
front/json.hook
Normal file
@ -0,0 +1,2 @@
|
||||
/: /%%%/tree/pub/front /% /json/
|
||||
-<
|
15
gen/hood/unlink.hoon
Normal file
15
gen/hood/unlink.hoon
Normal file
@ -0,0 +1,15 @@
|
||||
::
|
||||
:::: /hoon/link/hood/gen
|
||||
::
|
||||
/? 314
|
||||
::
|
||||
::::
|
||||
!:
|
||||
:- %say
|
||||
|= $: [now=@da eny=@uvI byk=beak]
|
||||
[arg=$?([dap=term ~] [who=ship dap=term ~]) ~]
|
||||
==
|
||||
:- %drum-unlink
|
||||
?~ +.arg
|
||||
[p.byk dap.arg]
|
||||
[who.arg dap.arg]
|
16
gen/moon.hoon
Normal file
16
gen/moon.hoon
Normal file
@ -0,0 +1,16 @@
|
||||
::
|
||||
:::: /hoon/ticket/gen
|
||||
::
|
||||
/? 314
|
||||
::
|
||||
::::
|
||||
!:
|
||||
:- %say
|
||||
|= $: [now=@da eny=@uvI bec=beak]
|
||||
[~ ~]
|
||||
==
|
||||
:- %noun
|
||||
?> =(1 (met 5 p.bec))
|
||||
=+ mon=(mix (lsh 5 1 (end 5 1 eny)) p.bec)
|
||||
=+ tic=((hard ,@p) .^(/a/(scot %p p.bec)/tick/(scot %da now)/(scot %p mon)))
|
||||
"moon: {<`@p`mon>}; ticket: {<tic>}"
|
@ -178,6 +178,11 @@
|
||||
=< se-abet =< se-view
|
||||
(se-link gyl)
|
||||
::
|
||||
++ poke-unlink ::
|
||||
|= gyl=gill
|
||||
=< se-abet =< se-view
|
||||
(se-klin gyl)
|
||||
::
|
||||
:: ++ poke-exit ::
|
||||
:: |=(~ se-abet:(se-blit `dill-blit`[%qit ~])) :: XX find bone
|
||||
:: ::
|
||||
@ -407,6 +412,10 @@
|
||||
?~ t.yal i.yal
|
||||
:(welp i.yal ", " $(yal t.yal))
|
||||
::
|
||||
++ se-klin :: disconnect app
|
||||
|= gyl=gill
|
||||
+>(eel (~(del in eel) gyl))
|
||||
::
|
||||
++ se-link :: connect to app
|
||||
|= gyl=gill
|
||||
+>(eel (~(put in eel) gyl))
|
||||
|
@ -275,6 +275,7 @@ window.urb.util = {
|
||||
},
|
||||
basepath: function(spur, pathname){
|
||||
spur = spur || ''
|
||||
if(spur === '/') spur = ''
|
||||
pathname = pathname || window.location.pathname
|
||||
if(pathname[0] == '/') pathname = pathname.slice(1)
|
||||
pathname = pathname.split("/")
|
||||
|
150
pub/doc/arvo.mdy
150
pub/doc/arvo.mdy
@ -1,150 +0,0 @@
|
||||
---
|
||||
sort: 2
|
||||
---
|
||||
|
||||
arvo
|
||||
====
|
||||
|
||||
Our operating system.
|
||||
|
||||
arvo is composed of modules called vanes:
|
||||
|
||||
<list dataPreview="true"></list>
|
||||
|
||||
<hr></hr>
|
||||
|
||||
At a high level `%arvo` takes a mess of unix io events and turns them
|
||||
into something clean and structured for the programmer.
|
||||
|
||||
`%arvo` is designed to avoid the usual state of complex event networks:
|
||||
event spaghetti. We keep track of every event's cause so that we have a
|
||||
clear causal chain for every computation. At the bottom of every chain
|
||||
is a unix io event, such as a network request, terminal input, file
|
||||
sync, or timer event. We push every step in the path the request takes
|
||||
onto the chain until we get to the terminal cause of the computation.
|
||||
Then we use this causal stack to route results back to the caller.
|
||||
|
||||
`++ducts`
|
||||
---------
|
||||
|
||||
The `%arvo` causal stack is called a `++duct`. This is represented
|
||||
simply as a list of paths, where each path represents a step in the
|
||||
causal chain. The first element in the path is the first letter of
|
||||
whichever vane handled that step in the computation, or the empty span
|
||||
for unix.
|
||||
|
||||
Here's a duct that was recently observed in the wild:
|
||||
|
||||
~[
|
||||
/g/a/~zod/4_shell_terminal/u/time
|
||||
/g/a/~zod/shell_terminal/u/child/4/main
|
||||
/g/a/~zod/terminal/u/txt
|
||||
/d/term-mess
|
||||
//term/1
|
||||
]
|
||||
|
||||
This is the duct the timer vane receives when "timer" sample app asks
|
||||
the timer vane to set a timer. This is also the duct over which the
|
||||
response is produced at the specified time. Unix sent a terminal
|
||||
keystroke event (enter), and arvo routed it to %dill(our terminal),
|
||||
which passed it on to the %gall app terminal, which sent it to shell,
|
||||
its child, which created a new child (with process id 4), which on
|
||||
startup asked the timer vane to set a timer.
|
||||
|
||||
The timer vane saves this duct, so that when the specified time arrives
|
||||
and unix sends a wakeup event to the timer vane, it can produce the
|
||||
response on the same duct. This response is routed to the place we
|
||||
popped off the top of the duct, i.e. the time app. This app produces the
|
||||
text "ding", which falls down to the shell, which drops it through to
|
||||
the terminal. Terminal drops this down to dill, which converts it into
|
||||
an effect that unix will recognize as a request to print "ding" to the
|
||||
screen. When dill produces this, the last path in the duct has an
|
||||
initial element of the empty span, so this is routed to unix, which
|
||||
applies the effects.
|
||||
|
||||
This is a call stack, with a crucial feature: the stack is a first-class
|
||||
citizen. You can respond over a duct zero, one, or many times. You can
|
||||
save ducts for later use. There are definitely parallels to Scheme-style
|
||||
continuations, but simpler and with more structure.
|
||||
|
||||
Making Moves
|
||||
------------
|
||||
|
||||
If ducts are a call stack, then how do we make calls and produce
|
||||
results? Arvo processes "moves" which are a combination of message data
|
||||
and metadata. There are two types of moves. A `%pass` move is analogous
|
||||
to a call:
|
||||
|
||||
[duct %pass return-path=path vane-name=@tD data=card]
|
||||
|
||||
Arvo pushes the return path (preceded by the first letter of the vane
|
||||
name) onto the duct and sends the given data, a card, to the vane we
|
||||
specified. Any response will come along the same duct with the path
|
||||
`return-path`.
|
||||
|
||||
A `%give` move is analogous to a return:
|
||||
|
||||
[duct %give data=card]
|
||||
|
||||
Arvo pops the top path off the duct and sends the given card back to the
|
||||
caller.
|
||||
|
||||
Vanes
|
||||
-----
|
||||
|
||||
As shown above, we use arvo proper to route and control the flow of
|
||||
moves. However, arvo proper is rarely directly responsible for
|
||||
processing the event data that directly causes the desired outcome of a
|
||||
move. This event data is contained within a card, which is simply a
|
||||
`(pair term noun)`. Instead, arvo proper passes the card off to one of
|
||||
its vanes, which each present an interface to clients for a particular
|
||||
well-defined, stable, and general-purpose piece of functionality.
|
||||
|
||||
As of this writing, we have seven vanes, which each provide the
|
||||
following services:
|
||||
|
||||
- `%ames` name of both our network and the vane that communicates over
|
||||
it
|
||||
- `%clay` version-controlled, referentially- transparent, and global
|
||||
filesystem
|
||||
- `%dill` terminal driver. Unix sends keyboard events to `%dill` from
|
||||
either the console or telnet, and `%dill` produces terminal output.
|
||||
- `%eyre` http server. Unix sends http messages to `%eyre`, and
|
||||
`%eyre` produces http messages in response
|
||||
- `%ford` handles resources and publishing
|
||||
- `%gall` manages our userspace applications.. `%gall` keeps state and
|
||||
manages subscribers
|
||||
- `%time` a simple timer
|
||||
|
||||
Cards
|
||||
-----
|
||||
|
||||
Cards are the vane-specific portion of a move. Each vane defines a
|
||||
protocol for interacting with other vanes (via arvo) by defining four
|
||||
types of cards: kisses, gifts, notes, and signs.
|
||||
|
||||
When one vane is `%pass`ed a card in its `++kiss`, arvo activates the
|
||||
`++call` gate with the card as its argument. To produce a result, the
|
||||
vane `%give`s one of the cards defined in its `++gift`. If the vane
|
||||
needs to request something of another vane, it `%pass`es it a `++note`
|
||||
card. When that other vane returns a result, arvo activates the `++take`
|
||||
gate of the initial vane with one of the cards defined in its `++sign`.
|
||||
|
||||
In other words, there are only four ways of seeing a move: (1) as a
|
||||
request seen by the caller, which is a ++note. (2) that same request as
|
||||
seen by the callee, a `++kiss`. (3) the response to that first request
|
||||
as seen by the callee, a `++gift`. (4) the response to the first request
|
||||
as seen by the caller, a `++sign`.
|
||||
|
||||
When a `++kiss` card is passed to a vane, arvo calls its `++call` gate,
|
||||
passing it both the card and its duct. This gate must be defined in
|
||||
every vane. It produces two things in the following order: a list of
|
||||
moves and a possibly-modified copy of its context. The moves are used to
|
||||
interact with other vanes, while the new context allows the vane to save
|
||||
its state. The next time arvo activates the vane it will have this
|
||||
context as its subject.
|
||||
|
||||
This overview has detailed how to pass a card to a particular vane. To
|
||||
see the cards each vane can be `%pass`ed as a `++kiss` or return as a
|
||||
`++gift` (as well as the semantics tied to them), each vane's public
|
||||
interface is explained in detail in its respective overview.
|
@ -1,29 +0,0 @@
|
||||
<div class="short">
|
||||
|
||||
`%ames`
|
||||
=======
|
||||
|
||||
Our networking protocol.
|
||||
|
||||
`%ames` is the name of both our network and the vane that communicates
|
||||
over it. When Unix receives a packet over the correct UDP port, it pipes
|
||||
it straight into `%ames` for handling. Also, all packets sent over the
|
||||
`%ames` network are sent by the `%ames` vane. Apps and vanes may use
|
||||
`%ames` to directly send messages to other ships. In general, apps use
|
||||
gall and clay to communicate with other ships rather than using `%ames`
|
||||
directly, but this isn't a requirement. Of course, gall and clay use
|
||||
`%ames` behind the scenes to communicate across the network. These are
|
||||
the only two vanes that use `%ames`.
|
||||
|
||||
`%ames` includes several significant components. Although the actual
|
||||
crypto algorithms are defined in zuse, they're used extensively in
|
||||
`%ames` for encrypting and decrypting packets. Congestion control and
|
||||
routing is handled entirely in `%ames`. Finally, the actual `%ames`
|
||||
protocol itself, including how to route incoming packets to the correct
|
||||
vane or app, is defined in `%ames`.
|
||||
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
</hr>
|
||||
<list></list>
|
File diff suppressed because it is too large
Load Diff
@ -1,8 +0,0 @@
|
||||
<div class="short">
|
||||
|
||||
`%arvo`
|
||||
=======
|
||||
|
||||
Our operating system.
|
||||
|
||||
</div>
|
@ -1,4 +0,0 @@
|
||||
`%arvo` commentary
|
||||
==================
|
||||
|
||||
`%arvo` is our operating system.
|
@ -1,27 +0,0 @@
|
||||
<div class="short">
|
||||
|
||||
`%clay`
|
||||
=======
|
||||
|
||||
Our filesystem.
|
||||
|
||||
`%clay` is version-controlled, referentially-transparent, and global.
|
||||
While this filesystem is stored in `%clay`, it is mirrored to Unix for
|
||||
convenience. Unix tells `%clay`s whenever a file changes in the Unix
|
||||
copy of the filesystem so that the change may be applied. `%clay` tells
|
||||
unix whenever an app or vane changes the filesystem so that the change
|
||||
can be effected in Unix. Apps and vanes may use `%clay` to write to the
|
||||
filesystem, query it, and subscribe to changes in it. Ford and gall use
|
||||
`%clay` to serve up apps and web pages.
|
||||
|
||||
`%clay` includes three components. First is the filesystem/version
|
||||
control algorithms, which are mostly defined in `++ze` and `++zu` in
|
||||
zuse. Second is the write, query, and subscription logic. Finally, there
|
||||
is the logic for communicating requests to, and receiving requests from,
|
||||
foreign ships.
|
||||
|
||||
</div>
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
<list></list>
|
@ -1,415 +0,0 @@
|
||||
# clay
|
||||
|
||||
## high-level
|
||||
|
||||
clay is the primary filesystem for the arvo operating system,
|
||||
which is the core of an urbit. The architecture of clay is
|
||||
intrinsically connected with arvo, but we assume no knowledge of
|
||||
either arvo or urbit. We will point out only those features of
|
||||
arvo that are necessary for an understanding of clay, and we will
|
||||
do so only when they arise.
|
||||
|
||||
The first relevant feature of arvo is that it is a deterministic
|
||||
system where input and output are defined as a series of events
|
||||
and effects. The state of arvo is simply a function of its event
|
||||
log. None of the effects from an event are emitted until the
|
||||
event is entered in the log and persisted, either to disk or
|
||||
another trusted source of persistence, such as a Kafka cluster.
|
||||
Consequently, arvo is a single-level store: everything in its
|
||||
state is persistent.
|
||||
|
||||
In a more traditional OS, everything in RAM can be erased at any
|
||||
time by power failure, and is always erased on reboot. Thus, a
|
||||
primary purpose of a filesystem is to ensure files persist across
|
||||
power failures and reboots. In arvo, both power failures and
|
||||
reboots are special cases of suspending computation, which is
|
||||
done safely since our event log is already persistent. Therefore,
|
||||
clay is not needed in arvo for persistence. Why, then, do we have a
|
||||
filesystem? There are two answers to this question.
|
||||
|
||||
First, clay provides a filesystem tree, which is a convenient
|
||||
user interface for some applications. Unix has the useful concept
|
||||
of virtual filesystems, which are used for everything from direct
|
||||
access to devices, to random number generators, to the /proc
|
||||
tree. It is easy and intuitive to read from and write to a
|
||||
filesystem tree.
|
||||
|
||||
Second, clay has a distributed revision control system baked into
|
||||
it. Traditional filesystems are not revision controlled, so
|
||||
userspace software -- such as git -- is written on top of them to
|
||||
do so. clay natively provides the same functionality as modern
|
||||
DVCSes, and more.
|
||||
|
||||
clay has two other unique properties that we'll cover later on:
|
||||
it supports typed data and is referentially transparent.
|
||||
|
||||
### Revision Control
|
||||
|
||||
Every urbit has one or more "desks", which are independently
|
||||
revision-controlled branches. Each desk contains its own mark
|
||||
definitions, apps, doc, and so forth.
|
||||
|
||||
Traditionally, an urbit has at least a base and a home desk. The
|
||||
base desk has all the system software from the distribution. the
|
||||
home desk is a fork of base with all the stuff specific to the
|
||||
user of the urbit.
|
||||
|
||||
A desk is a series of numbered commits, the most recent of which
|
||||
represents the current state of the desk. A commit is composed of
|
||||
(1) an absolute time when it was created, (2) a list of zero or
|
||||
more parents, and (3) a map from paths to data.
|
||||
|
||||
Most commits have exactly one parent, but the initial commit on a
|
||||
desk may have zero parents, and merge commits have more than one
|
||||
parent.
|
||||
|
||||
The non-meta data is stored in the map of paths to data. It's
|
||||
worth noting that no constraints are put on this map, so, for
|
||||
example, both /a/b and /a/b/c could have data. This is impossible
|
||||
in a traditional Unix filesystem since it means that /a/b is both
|
||||
a file and a directory. Conventionally, the final element in the
|
||||
path is its mark -- much like a filename extension in Unix. Thus,
|
||||
/doc/readme.md in Unix is stored as /doc/readme/md in urbit.
|
||||
|
||||
The data is not stored directly in the map; rather, a hash of the
|
||||
data is stored, and we maintain a master blob store. Thus, if the
|
||||
same data is referred to in multiple commits (as, for example,
|
||||
when a file doesn't change between commits), only the hash is
|
||||
duplicated.
|
||||
|
||||
In the master blob store, we either store the data directly, or
|
||||
else we store a diff against another blob. The hash is dependent
|
||||
only on the data within and not on whether or not it's stored
|
||||
directly, so we may on occasion rearrange the contents of the
|
||||
blob store for performance reasons.
|
||||
|
||||
Recall that a desk is a series of numbered commits. Not every
|
||||
commit in a desk must be numbered. For example, if the base desk
|
||||
has had 50 commits since home was forked from it, then a merge
|
||||
from base to home will only add a single revision number to home,
|
||||
although the full commit history will be accessible by traversing
|
||||
the parentage of the individual commits.
|
||||
|
||||
We do guarantee that the first commit is numbered 1, commits are
|
||||
numbered consecutively after that (i.e. there are no "holes"),
|
||||
the topmost commit is always numbered, and every numbered commit
|
||||
is an ancestor of every later numbered commit.
|
||||
|
||||
There are three ways to refer to particular commits in the
|
||||
revision history. Firstly, one can use the revision number.
|
||||
Secondly, one can use any absolute time between the one numbered
|
||||
commit and the next (inclusive of the first, exclusive of the
|
||||
second). Thirdly, every desk has a map of labels to revision
|
||||
numbers. These labels may be used to refer to specific commits.
|
||||
|
||||
Additionally, clay is a global filesystem, so data on other urbit
|
||||
is easily accessible the same way as data on our local urbit. In
|
||||
general, the path to a particular revision of a desk is
|
||||
/~urbit-name/desk-name/revision. Thus, to get /try/readme/md
|
||||
from revision 5 of the home desk on ~sampel-sipnym, we refer to
|
||||
/~sampel-sipnym/home/5/try/readme/md. Clay's namespace is thus
|
||||
global and referentially transparent.
|
||||
|
||||
XXX reactivity here?
|
||||
|
||||
### A Typed Filesystem
|
||||
|
||||
Since clay is a general filesystem for storing data of arbitrary
|
||||
types, in order to revision control correctly it needs to be
|
||||
aware of types all the way through. Traditional revision control
|
||||
does an excellent job of handling source code, so for source code
|
||||
we act very similar to traditional revision control. The
|
||||
challenge is to handle other data similarly well.
|
||||
|
||||
For example, modern VCSs generally support "binary files", which
|
||||
are files for which the standard textual diffing, patching, and
|
||||
merging algorithms are not helpful. A "diff" of two binary files
|
||||
is just a pair of the files, "patching" this diff is just
|
||||
replacing the old file with the new one, and "merging"
|
||||
non-identical diffs is always a conflict, which can't even be
|
||||
helpfully annotated. Without knowing anything about the structure
|
||||
of a blob of data, this is the best we can do.
|
||||
|
||||
Often, though, "binary" files have some internal structure, and
|
||||
it is possible to create diff, patch, and merge algorithms that
|
||||
take advantage of this structure. An image may be the result of a
|
||||
base image with some set of operations applied. With algorithms
|
||||
aware of this set of operations, not only can revision control
|
||||
software save space by not having to save every revision of the
|
||||
image individually, these transformations can be made on parallel
|
||||
branches and merged at will.
|
||||
|
||||
Suppose Alice is tasked with touching up a picture, improving the
|
||||
color balance, adjusting the contrast, and so forth, while Bob
|
||||
has the job of cropping the picture to fit where it's needed and
|
||||
adding textual overlay. Without type-aware revision control,
|
||||
these changes must be made serially, requiring Alice and Bob to
|
||||
explicitly coordinate their efforts. With type-aware revision
|
||||
control, these operations may be performed in parallel, and then
|
||||
the two changesets can be merged programmatically.
|
||||
|
||||
Of course, even some kinds of text files may be better served by
|
||||
diff, patch, and merge algorithms aware of the structure of the
|
||||
files. Consider a file containing a pretty-printed JSON object.
|
||||
Small changes in the JSON object may result in rather significant
|
||||
changes in how the object is pretty-printed (for example, by
|
||||
addding an indentation level, splitting a single line into
|
||||
multiple lines).
|
||||
|
||||
A text file wrapped at 80 columns also reacts suboptimally with
|
||||
unadorned Hunt-McIlroy diffs. A single word inserted in a
|
||||
paragraph may push the final word or two of the line onto the
|
||||
next line, and the entire rest of the paragraph may be flagged as
|
||||
a change. Two diffs consisting of a single added word to
|
||||
different sentences may be flagged as a conflict. In general,
|
||||
prose should be diffed by sentence, not by line.
|
||||
|
||||
As far as the author is aware, clay is the first generalized,
|
||||
type-aware revision control system. We'll go into the workings
|
||||
of this system in some detail.
|
||||
|
||||
### Marks
|
||||
|
||||
Central to a typed filesystem is the idea of types. In clay, we
|
||||
call these "marks". A mark is a file that defines a type,
|
||||
conversion routines to and from the mark, and diff, patch, and
|
||||
merge routines.
|
||||
|
||||
For example, a `%txt` mark may be a list of lines of text, and it
|
||||
may include conversions to `%mime` to allow it to be serialized
|
||||
and sent to a browswer or to the unix filesystem. It will also
|
||||
include Hunt-McIlroy diff, patch, and merge algorithms.
|
||||
|
||||
A `%json` mark would be defined as a json object in the code, and
|
||||
it would have a parser to convert from `%txt` and a printer to
|
||||
convert back to `%txt`. The diff, patch, and merge algorithms are
|
||||
fairly straightforward for json, though they're very different
|
||||
from the text ones.
|
||||
|
||||
More formally, a mark is a core with three arms, `++grab`,
|
||||
`++grow`, and `++grad`. In `++grab` is a series of functions to
|
||||
convert from other marks to the given mark. In `++grow` is a
|
||||
series of functions to convert from the given mark to other
|
||||
marks. In `++grad` is `++diff`, `++pact`, `++join`, and `++mash`.
|
||||
|
||||
The types are as follows, in an informal pseudocode:
|
||||
|
||||
++ grab:
|
||||
++ mime: <mime> -> <mark-type>
|
||||
++ txt: <txt> -> <mark-type>
|
||||
...
|
||||
++ grow:
|
||||
++ mime: <mark-type> -> <mime>
|
||||
++ txt: <mark-type> -> <txt>
|
||||
...
|
||||
++ grad
|
||||
++ diff: (<mark-type>, <mark-type>) -> <diff-type>
|
||||
++ pact: (<mark-type>, <diff-type>) -> <mark-type>
|
||||
++ join: (<diff-type>, <diff-type>) -> <diff-type> or NULL
|
||||
++ mash: (<diff-type>, <diff-type>) -> <diff-type>
|
||||
|
||||
These types are basically what you would expect. Not every mark
|
||||
has each of these functions defined -- all of them are optional
|
||||
in the general case.
|
||||
|
||||
In general, for a particular mark, the `++grab` and `++grow` entries
|
||||
(if they exist) should be inverses of each other.
|
||||
|
||||
In `++grad`, `++diff` takes two instances of a mark and produces
|
||||
a diff of them. `++pact` takes an instance of a mark and patches
|
||||
it with the given diff. `++join` takes two diffs and attempts to
|
||||
merge them into a single diff. If there are conflicts, it
|
||||
produces null. `++mash` takes two diffs and forces a merge,
|
||||
annotating any conflicts.
|
||||
|
||||
In general, if `++diff` called with A and B produces diff D, then
|
||||
`++pact` called with A and D should produce B. Also, if `++join`
|
||||
of two diffs does not produce null, then `++mash` of the same
|
||||
diffs should produce the same result.
|
||||
|
||||
Alternately, instead of `++diff`, `++pact`, `++join`, and
|
||||
`++mash`, a mark can provide the same functionality by defining
|
||||
`++sted` to be the name of another mark to which we wish to
|
||||
delegate the revision control responsibilities. Then, before
|
||||
running any of those functions, clay will convert to the other
|
||||
mark, and convert back afterward. For example, the `%hoon` mark
|
||||
is revision-controlled in the same way as `%txt`, so its `++grad`
|
||||
is simply `++sted %txt`. Of course, `++txt` must be defined in
|
||||
`++grow` and `++grab` as well.
|
||||
|
||||
Every file in clay has a mark, and that mark must have a
|
||||
fully-functioning `++grad`. Marks are used for more than just
|
||||
clay, and other marks don't need a `++grad`, but if a piece of
|
||||
data is to be saved to clay, we must know how to revision-control
|
||||
it.
|
||||
|
||||
Additionally, if a file is to be synced out to unix, then it must
|
||||
have conversion routines to and from the `%mime` mark.
|
||||
|
||||
##Using clay
|
||||
|
||||
### Reading and Subscribing
|
||||
|
||||
When reading from Clay, there are three types of requests. A
|
||||
`%sing` request asks for data at single revsion. A `%next`
|
||||
request asks to be notified the next time there's a change to
|
||||
given file. A `%many` request asks to be notified on every
|
||||
change in a desk for a range of changes.
|
||||
|
||||
For `%sing` and `%next`, there are generally three things to be
|
||||
queried. A `%u` request simply checks for the existence of a
|
||||
file at a path. A `%x` request gets the data in the file at a
|
||||
path. A `%y` request gets a hash of the data in the file at the
|
||||
path combined with all its children and their data. Thus, `%y`
|
||||
of a node changes if it or any of its children change.
|
||||
|
||||
A `%sing` request is fulfilled immediately if possible. If the
|
||||
requested revision is in the future, or is on another ship for
|
||||
which we don't have the result cached, we don't respond
|
||||
immediately. If the requested revision is in the future, we wait
|
||||
until the revision happens before we respond to the request. If
|
||||
the request is for data on another ship, we pass on the request
|
||||
to the other ship. In general, Clay subscriptions, like most
|
||||
things in Urbit, aren't guaranteed to return immediately.
|
||||
They'll return when they can, and they'll do so in a
|
||||
referentially transparent manner.
|
||||
|
||||
A `%next` request checks query at the given revision, and it
|
||||
produces the result of the query the next time it changes, along
|
||||
with the revsion number when it changes. Thus, a `%next` of a
|
||||
`%u` is triggered when a file is added or deleted, a `%next` of a
|
||||
`%x` is triggered when a file is added, deleted, or changed, and
|
||||
a `%next` of a `%y` is triggered when a file or any of its
|
||||
children is added, deleted, or changed.
|
||||
|
||||
A `%many` request is triggered every time the given desk has a
|
||||
new revision. Unlike a `%next`, a `%many` has both a start and
|
||||
an end revsion, after which it stops returning. For `%next`, a
|
||||
single change is reported, and if the caller wishes to hear of
|
||||
the next change, it must resubscribe. For `%many`, every revsion
|
||||
from the start to the end triggers a response. Since a `%many`
|
||||
request doesn't ask for any particular data, there aren't `%u`,
|
||||
`%x`, and `%y` versions for it.
|
||||
|
||||
### Unix sync
|
||||
|
||||
One of the primary functions of clay is as a convenient user
|
||||
interface. While tools exist to use clay from within urbit, it's
|
||||
often useful to be able to treat clay like any other filesystem
|
||||
from the Unix perspective -- to "mount" it, as it were.
|
||||
|
||||
From urbit, you can run `|mount /path/to/directory %mount-point`,
|
||||
and this will mount the given clay directory to the mount-point
|
||||
directory in Unix. Every file is converted to `%mime` before it's
|
||||
written to Unix, and converted back when read from Unix. The
|
||||
entire directory is watched (a la Dropbox), and every change is
|
||||
auto-committed to clay.
|
||||
|
||||
### Merging
|
||||
|
||||
Merging is a fundamental operation for a distributed revision
|
||||
control system. At their root, clay's merges are similar to
|
||||
git's, but with some additions to accomodate typed data. There
|
||||
are seven different merge strategies.
|
||||
|
||||
Throughout our discussion, we'll say that the merge is from
|
||||
Alice's desk to Bob's. Recall that a commit is a date (for all
|
||||
new commits this will be the current date), a list of parents,
|
||||
and the data itself.
|
||||
|
||||
A `%init` merge should be used iff it's the first commit to a
|
||||
desk. The head of Alice's desk is used as the number 1 commit to
|
||||
Bob's desk. Obviously, the ancestry remains intact through
|
||||
traversing the parentage of the commit even though previous
|
||||
commits are not numbered for Bob's desk.
|
||||
|
||||
A `%this` merge means to keep what's in Bob's desk, but join the
|
||||
ancestry. Thus, the new commit has the head of each desk as
|
||||
parents, but the data is exactly what's in Bob's desk. For those
|
||||
following along in git, this is the 'ours' merge strategy, not
|
||||
the '--ours' option to the 'recursive' merge strategy. In other
|
||||
words, even if Alice makes a change that does not conflict with
|
||||
Bob, we throw it away. It's Bob's way or the highway.
|
||||
|
||||
A `%that` merge means to take what's in Alice's desk, but join
|
||||
the ancestry. This is the reverse of `%this`.
|
||||
|
||||
A `%fine` merge is a "fast-forward" merge. This succeeds iff one
|
||||
head is in the ancestry of the other. In this case, we use the
|
||||
descendant as our new head.
|
||||
|
||||
For `%meet`, `%mate`, and `%meld` merges, we first find the most
|
||||
recent common ancestor to use as our merge base. If we have no
|
||||
common ancestors, then we fail. If we have more than one most
|
||||
recent common ancestor, then we have a criss-cross situation,
|
||||
which should be handled delicately. At present, we delicately
|
||||
throw up our hands and give up, but something akin to git's
|
||||
'recursive' strategy should be implemented in the future.
|
||||
|
||||
There's a functional inclusion ordering on `%fine`, `%meet`,
|
||||
`%mate`, and `%meld` such that if an earlier strategy would have
|
||||
succeeded, then every later strategy will produce the same
|
||||
result. Put another way, every earlier strategy is the same as
|
||||
every later strategy except with a restricted domain.
|
||||
|
||||
A `%meet` merge only succeeds if the changes from the merge base
|
||||
to Alice's head (hereafter, "Alice's changes") are in different
|
||||
files than Bob's changes. In this case, the parents are both
|
||||
Alice's and Bob's heads, and the data is the merge base plus
|
||||
Alice's changed files plus Bob's changed files.
|
||||
|
||||
A `%mate` merge attempts to merge changes to the same file when
|
||||
both Alice and bob change it. If the merge is clean, we use it;
|
||||
otherwise, we fail. A merge between different types of changes --
|
||||
for example, deleting a file vs changing it -- is always a
|
||||
conflict. If we succeed, the parents are both Alice's and Bob's
|
||||
heads, and the data is the merge base plus Alice's changed files
|
||||
plus Bob's changed files plus the merged files.
|
||||
|
||||
A `%meld` merge will succeed even if there are conflicts. If
|
||||
there are conflicts in a file, then we use the merge base's
|
||||
version of that file, and we produce a set of files with
|
||||
conflicts. The parents are both Alice's and Bob's heads, and the
|
||||
data is the merge base plus Alice's changed files plus Bob's
|
||||
changed files plus the successfully merged files plus the merge
|
||||
base's version of the conflicting files.
|
||||
|
||||
That's the extent of the merge options in clay proper. In
|
||||
userspace there's a final option `%auto`, which is the most
|
||||
common. `%auto` checks to see if Bob's desk exists, and if it
|
||||
doesn't we use a `%init` merge. Otherwise, we progressively try
|
||||
`%fine`, `%meet`, and `%mate` until one succeeds.
|
||||
|
||||
If none succeed, we merge Bob's desk into a scratch desk. Then,
|
||||
we merge Alice's desk into the scratch desk with the `%meld`
|
||||
option to force the merge. For each file in the produced set of
|
||||
conflicting files, we call the `++mash` function for the
|
||||
appropriate mark, which annotates the conflicts if we know how.
|
||||
|
||||
Finally, we display a message to the user informing them of the
|
||||
scratch desk's existence, which files have annotated conflicts,
|
||||
and which files have unannotated conflicts. When the user has
|
||||
resolved the conflicts, they can merge the scratch desk back into
|
||||
Bob's desk. This will be a `%fine` merge since Bob's head is in
|
||||
the ancestry of the scratch desk.
|
||||
|
||||
### Autosync
|
||||
|
||||
Tracking and staying in sync with another desk is another
|
||||
fundamental operation. We call this "autosync". This doesn't mean
|
||||
simply mirroring a desk, since that wouldn't allow local changes.
|
||||
We simply want to apply changes as they are made upstream, as
|
||||
long as there are no conflicts with local changes.
|
||||
|
||||
This is implemented by watching the other desk, and, when it has
|
||||
changes, merging these changes into our desk with the usual merge
|
||||
strategies.
|
||||
|
||||
Note that it's quite reasonable for two desks to be autosynced to
|
||||
each other. This results in any change on one desk being mirrored
|
||||
to the other and vice versa.
|
||||
|
||||
Additionally, it's fine to set up an autosync even if one desk,
|
||||
the other desk, or both desks do not exist. The sync will be
|
||||
activated when the upstream desk comes into existence and will
|
||||
create the downstream desk if needed.
|
File diff suppressed because it is too large
Load Diff
@ -1,27 +0,0 @@
|
||||
<div class="short">
|
||||
|
||||
`%dill`
|
||||
=======
|
||||
|
||||
Our terminal driver.
|
||||
|
||||
Unix sends keyboard events to `%dill` from either the console or telnet,
|
||||
and `%dill` produces terminal output. The only app that should directly
|
||||
talk to `%dill` is the terminal app. Command-line apps are run by,
|
||||
receive input from, and produce output to, the `%shell` app, which is
|
||||
controlled by `%terminal`, which talks to `%dill`, which talks to unix.
|
||||
Clay also uses `%dill` directly to print out the filesystem change
|
||||
events, but this is questionable behavior.
|
||||
|
||||
`%dill` has two main components. First, it controls the terminal on a
|
||||
very basic, event-by-event level. This includes keeping track of things
|
||||
like the dimensions of the terminal, the prompt type (plain text or
|
||||
password), which duct to produce effects on, and so forth. Second, it
|
||||
handles terminal events, keystroke by keystroke. Most characters are
|
||||
simply pushed onto the buffer and blitted to the screen, but some
|
||||
characters, including control-modified keys, arrow keys, etc. require
|
||||
special handling. Most of the readline functionality is in `%dill`.
|
||||
|
||||
</div>
|
||||
|
||||
------------------------------------------------------------------------
|
@ -1,5 +0,0 @@
|
||||
Dill: Reference
|
||||
===============
|
||||
|
||||
Dill: Commentary
|
||||
================
|
@ -1,63 +0,0 @@
|
||||
<div class="short">
|
||||
|
||||
`%eyre`
|
||||
=======
|
||||
|
||||
Our http server.
|
||||
|
||||
Unix sends http messages to `%eyre`, and `%eyre` produces http messages
|
||||
in response. In general, apps and vanes do not call `%eyre`; rather,
|
||||
`%eyre` calls apps and vanes. `%eyre` uses `%ford` and `%gall` to
|
||||
functionally publish pages and facilitate communication with apps.
|
||||
|
||||
`%eyre` primarily parses web requests and handles them in a variety of
|
||||
ways, depending on the control string. Nearly all of these are
|
||||
essentially stateless, like functional publishing with `%ford`.
|
||||
Additionally, there's a fairly significant component that handles
|
||||
`%gall` messaging and subscriptions, which must be stateful.
|
||||
|
||||
</div>
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
HTTP Methods
|
||||
============
|
||||
|
||||
`GET` `gog` `https://[ship-name].urbit.org/gog/[service]` Owner
|
||||
requesting a page on her own Urbit. `gig`
|
||||
`https://[ship-name].urbit.org/gig/[user-name]/[service]` Another user
|
||||
requesting a page on a foreign Urbit.
|
||||
|
||||
`goe`
|
||||
`https://[ship-name].urbit.org/goe/[service]/[port]/[stream]/[sequence]`
|
||||
`https://[ship-name].urbit.org/goe/[service]/[port]/[stream]/[sequence].json`
|
||||
Pulls a specific response to her subscription on her own Urbit. `gie`
|
||||
`https://[ship-name].urbit.org/gie/[user-name]/[service]/[port]/[stream]/[sequence]`
|
||||
`https://[ship-name].urbit.org/gie/[user-name]/[service]/[port]/[stream]/[sequence].json`
|
||||
Pulls a specific response to her subscription on a foreign Urbit.
|
||||
|
||||
`PUT` `tos`
|
||||
`https://[ship-name].urbit.org/tos/[service]/[port]/[stream]/[path]`
|
||||
`{oryx: [string]}` Initiate a subscription on her own Urbit. `tis`
|
||||
`https://[ship-name].urbit.org/tis/[user-name]/[service]/[port]/[stream]/[path]`
|
||||
`{oryx: [string]}` Initiate a subscription on a foreign Urbit.
|
||||
|
||||
`tom` `https://[ship-name].urbit.org/tom/[service]/[port]/[sequence]`
|
||||
`{oryx: [string], xyro: [json]}` Send a message to her Urbit with
|
||||
sequence number `[sequence]`. `tim`
|
||||
`https://[ship-name].urbit.org/tim/[user-name]/[service]/[port]/[sequence]`
|
||||
`{oryx: [string], xyro: [json]}` Send a message to a foreign Urbit with
|
||||
sequence number `[sequence]`.
|
||||
|
||||
`tou` `https://[ship-name].urbit.org/tou/[service]/[port]/[stream]`
|
||||
Unsubscribe from stream `[stream]` on her Urbit. `tiu`
|
||||
`https://[ship-name].urbit.org/tiu/[user-name]/[service]/[port]/[stream]`
|
||||
Unsubscribe from stream `[stream]` on a foreign Urbit.
|
||||
|
||||
urb.js
|
||||
======
|
||||
|
||||
|
||||
<hr>
|
||||
</hr>
|
||||
<list></list>
|
@ -1,273 +0,0 @@
|
||||
Eyre: Reference
|
||||
===============
|
||||
|
||||
## State
|
||||
|
||||
Stored
|
||||
|
||||
- `++bolo`
|
||||
- `++cyst`
|
||||
- `++stem`
|
||||
|
||||
Runtime
|
||||
|
||||
- `perk`
|
||||
+ `perk-auth`
|
||||
- `pest`
|
||||
- `even`
|
||||
|
||||
## Cores
|
||||
|
||||
- `++handle`
|
||||
+ `++parse`
|
||||
- `++as...`
|
||||
- `++ya`
|
||||
- `++ix`
|
||||
|
||||
Eyre: Commentary
|
||||
================
|
||||
|
||||
Let us follow the loading of a simple cli app, as it bounces from
|
||||
browser to server to browser and back.
|
||||
|
||||
## Initial request[#init]
|
||||
|
||||
An http request for `http://sampel-sipnym.urbit.org/cli` will be [redirected](dns)
|
||||
to the `%eyre` on ~sampel-sipnym, and come in as a `%this` kiss.
|
||||
|
||||
From arvo, requests enter `++call`, which after some type reification are passed
|
||||
along to `++apex:ye`. In the case of a `%this` kiss, its components are
|
||||
parsed(see `++zest:epur`, `++eat-headers`) and handed off to `++handle`, wrapped
|
||||
in `++emule` to produce a `++fail` page in case of error. `++apex:handle` will
|
||||
`++process` the request to a `pest` or a `++done` core, and in the former case
|
||||
`++resolve` the pest into an outgoing card.
|
||||
|
||||
XX it also seems to affect the current ship, test that serving ship name is consistently correct
|
||||
|
||||
The pest is produced by `++process`, which will first further `++parse` the
|
||||
request, and if this does not make the response immediately obvious,
|
||||
`++process-parsed` the resulting `perk`.
|
||||
|
||||
`++parse` produces the `perk`, by attempting to interpret the `pork`(url path)
|
||||
[`++as-magic-filename`](#mage), `++as-beam`, and `++as-aux-request`. In this
|
||||
case, `/cli` is parsed by the second case as a `%beam` query to `/=cli=`: a path
|
||||
which starts with a valid ship name is expected to be a full clay(well, ford)
|
||||
path, and one starting with a term implies the current serving ship and a case
|
||||
of `0`, the current revision.
|
||||
|
||||
XX spur: when the desks are merged, `/cli` shall point to `/=main=/pub/cli`
|
||||
|
||||
The parsed `perk` generates a `%f %boil` note, `mark`ed as its extension(here
|
||||
defaulting to `%urb`) and `wire`d with `~` to return unaltered to the client. It
|
||||
goes on to `++resolve` by being passed to `++ford-get-beam`, which translates
|
||||
the perk it into a `%boil` `++ford-req`, adding an `++fcgi` path-segment
|
||||
containing query string and `++fcgi-cred:for-client` auth information.
|
||||
|
||||
`%ford`s translation of `/=cli=/hymn/hook` to a self-refreshing `%urb` html page
|
||||
[deserves its own commentary](../ford/commentary), but we resume in `%eyre`
|
||||
when the `%made` sign arrives in `++take`, and soon after `++axon:ye`. There the
|
||||
`wire`, or rather the `whir` it has been verified to be, determines that the
|
||||
response should be served immediately. However, as the mark is not `%mime`,
|
||||
another trip to `%ford` is required to encode it, on the same wire; afterwards,
|
||||
the value of the `%mime` cage is verified to be of the correct type, and finally
|
||||
delivered back up the requesting duct as a succesful `%thou` HTTP response.
|
||||
|
||||
XX `%cast %mime` used to be in ford-get-beam, is there a reason it was removed?
|
||||
|
||||
## Back into the breach, or: auxilary requests
|
||||
|
||||
Now, it was mentioned that this result is self-refreshing: the `%urb`
|
||||
translation door injects a `;script@"/~/on/{deps}.js"` into every page, `deps`
|
||||
is a ford-readable hash of the set of resources that page construction depended
|
||||
on.
|
||||
|
||||
This triggers another `%this` request. Its handling is identical to that of
|
||||
`/cli` up until `++parse`, where it is seen not `++as-beam` but
|
||||
`++as-aux-request`(auxillary requests starting with `/~/` or `/~~/`).
|
||||
`/on/[hash]` is a long-`%poll`, which `++process-parsed`, for a `.js` mark,
|
||||
answers with a direct `%js`. Its contents are the static `++poll:js`, which
|
||||
initiates the long-polling loop, run against an injected `urb.js` of
|
||||
`{poll:[hash]}`.
|
||||
|
||||
A `%js` `pest` is `resolve`d as a `text/javascript` success `%this`.
|
||||
|
||||
When `poll.js` is recieved by the client, it opens an `XMLHttpRequest` for
|
||||
`/~/on/{window.urb.poll}.json`, bringing us back to `%poll:process`.
|
||||
|
||||
In the case of a non-`%js` `/~/on/`, `%poll:process-parsed` turns into a
|
||||
`++new-dependency`, which stores the listening duct, and `pass-note`s a `%wasp`
|
||||
with the deps-hash back to `%ford` whence it came. While this occured, the page
|
||||
has loaded.
|
||||
|
||||
Some indeterminate amount of time afterwards, with dropped `/~/on/{...}.json`s
|
||||
being retried upon expiring and also being stored, a `%news` sign arrives in
|
||||
`++axon`, and the hash in question is retrieved from the wire, and the listening
|
||||
long-polls retrieved by the hash. Each receives a 205 "Reload parent view" HTTP
|
||||
response, which `poll.js` dutifully executes, and a fixed typo of markdown is
|
||||
rendered.
|
||||
|
||||
## Authentication.
|
||||
|
||||
Now, while this accurately reflects the presentation of e.g. a markdown file,
|
||||
`/cli` is an application front-end, and one that permits only owner access. Its
|
||||
second script is `@"/~~/~/at/main/lib/urb.js"`, semantically equivalent to
|
||||
`/~/as/own/~/at/main/lib/urb.js`, and handled as follows.
|
||||
|
||||
In `++as-aux-request`, `%as %own` becomes `%auth %get our` perk, which
|
||||
`++process` passes to `++process-parsed` passes to `++process-auth`. There, a
|
||||
`yac` "ya" core is built `++for-client`: a `++cookie-prefix`, which is just the
|
||||
serving ship name, is used to get a `++session-from-cookies`, here nil as the
|
||||
client has no cookie set. In lieu of a cookie, a `++new-ya` is constructed, with
|
||||
a random token `hole` and a `++new-cyst` which fills out `cyst` session state
|
||||
from request data.
|
||||
|
||||
Returning to `++process-auth`, `%get` checks if the yac is authenticated with
|
||||
the requested credentials(`anon` requests are always granted), which for the
|
||||
fresh new `cyst` is not the case (more on success [later](#auth-ok)). Unless
|
||||
authentiacting as a [foreign ship](#xeno), the only thing left is to
|
||||
`++show-login-page`, which detects that the requested resource is not `%html`,
|
||||
and produces a `%red` pest. For `%js`, `%red`irections `++resolve` to
|
||||
`++auth-redir:js`, a line of javascript which prepends `/~~` to the url path.
|
||||
|
||||
The owner-authenticated main page request similarly ends in `++show-login-page`,
|
||||
which for the empty session is an `[%htme ++login-page:xml]`, `resolve`d to
|
||||
`++give-html` with a 401 "unathorized".
|
||||
|
||||
The login page shows a simple prompt, and requests `/~/at/auth.js` to handle the
|
||||
submission. And so we are, once again, attempting to divine if what we're doing
|
||||
makes sense `++as-aux-request`.
|
||||
|
||||
To understand `/~/at`, there will first be a brief diversion to `~/auth.json`.
|
||||
`auth.json`, perk `[%auth %json]`, in `++process-auth` serves `++stat-json:ya`,
|
||||
containing such information as the serving ship, which identities are associated
|
||||
with this session, and `oryx`, a CSRF token. An oryx must be present on all
|
||||
stateful requests, in this case executing a log in. It also saves the new/old
|
||||
session using `abet`.
|
||||
|
||||
XX explain `ixor` here and not [later](#ixor)?
|
||||
|
||||
`/~/at` is an alternate interface, which injects `auth.json` data into the
|
||||
requested file. `/~/at/auth.js`, then, is a request for the built-in `auth:js`
|
||||
(parsed to and processed from an `[%auth %js ~]` perk), with session data added
|
||||
as `window.urb`. And indeed, ``[`%js /~/at/auth]`` is parsed to
|
||||
``[%auth at [`%js /auth]``, which in `++process-auth` is re-`process`ed to
|
||||
`[%js ++auth:js]`, which is `++resolve`d after an `++add-json` of
|
||||
the relevant data. The yac cookies are also passed to `resolve`, which
|
||||
`++add-cookies` injects into the `httr`.
|
||||
|
||||
It is at this point that there is first occasion for user input, namely the password.
|
||||
|
||||
The `auth:js` script sends a `PUT` request, also to `/~/auth.json`. In `parse`,
|
||||
the first nontrivial `++check-oryx` occurs, `++grab-body` the request oryx and
|
||||
ensuring it is recorded for the session. The request parsed with `++need-body`
|
||||
to a `[%auth %try {password}]` perk. `%get:process-auth` checks it against
|
||||
`++load-secret`, upon success updates the session with `++logon:ya`, and
|
||||
serves a fresh `auth.json` which reflects the changed `user`. Upon recieving
|
||||
this, the page is refreshed to retry the original request.
|
||||
|
||||
## Post-authentication: app communication. [#auth-ok]
|
||||
|
||||
Upon refresh, `/~~/cli` brings us for the third time to `%get:process-auth`, but
|
||||
this time the cookie is set, and the `yac` fetched contains the serving ship as
|
||||
authenticated. The `++handle` sample is updated to reflect the requesting ship,
|
||||
and the `process` continues for the rest of the pork, once again serving the
|
||||
ford page.
|
||||
|
||||
The `/~/on/[deps].json` poll starts anew, and `/~~/~/at/main/lib/urb.js` we now
|
||||
know to serve the window.urb necessary to make requests, and the `urb.js`
|
||||
standard library which extends it with a number of wrappers to them and other
|
||||
useful functions.
|
||||
|
||||
---
|
||||
|
||||
One of those functions is `urb.bind`, which is used to subscribe to application
|
||||
data. Userspace javascript sets `urb.appl` to `/tic`, and binds `lines` to a
|
||||
`;pre;` text display, using a callback.
|
||||
|
||||
This triggers a `PUT` to `/~/is/{ixor}/cli/lines.json`, where `ixor` is a hash
|
||||
of `oryx` that identifies the connection. `++as-aux-request`, an `%is` is a
|
||||
`%subs` subscription update update, which for `%put` forwards to
|
||||
`++add-subs:ix`, the ix core fetched `++for-view` by hashing the request
|
||||
`++oryx-to-ixor`.
|
||||
|
||||
[#ixor] A view has all the state associated with a client that must be
|
||||
remembered between events. In this case, this is what app/path the request duct
|
||||
is associated with; but mainly, `++add-subs:ix` will `pass-note` to `%gall` so
|
||||
it `%show`s the data on the path, current and future.
|
||||
|
||||
This will immediately(assuming the ship is local) result in a `%nice` by the
|
||||
`/cli` app, returning `{ok:true}` `++nice-json` to `urb.bind`'s second callback
|
||||
as `{ok:true}`. The initial `%rush` results also arrive, and in `++axon` are
|
||||
converted to json using `++back`(ford `%cast` wrapper), and when `%made` get
|
||||
passed to `++get-rush:ix`. There the source application/path are decoded by
|
||||
duct, and then the full event goes to `++get-even`; `++add-even` inserts it to
|
||||
the queue, and as there is no long poll it simply stays there.
|
||||
|
||||
Upon receipt, the client realizes the long-poll isn't actually running, so that
|
||||
is started using `urb.poll`. At `/~/of/{ixor}`, perk
|
||||
`[%view ixor ~ {sequence-number}]`, it is `process`ed by `++poll:ix` (the cyst
|
||||
is retrieved by `++ire-ix` form global state, using the perk `ixor`): the
|
||||
sequence number is in the past, so the previously recieved `%rush` is
|
||||
`++give-even`. After deleting the previous message in the queue and invoking
|
||||
`++pass-took` to signal `%gall` of this occurrence, the data is annotated with
|
||||
the source app+path `++subs-to-json`, and returned to the polling duct.
|
||||
|
||||
On the client, the user callback receives the `/cli` history, and displays it on
|
||||
the page. The `/~/of` long poll is continued, this time reaching `++poll:ix`
|
||||
with the "pending" sequence number, and being stored in the `cyst` for its troubles.
|
||||
|
||||
---
|
||||
|
||||
Its next update proceeds idenitcally, but first it must be triggered, which
|
||||
happens when the user enters "(add 2 2)\n", firing an `urb.send` from the event
|
||||
handler. This sends a `POST` request to `/~/to/cli/json.json`, perk `%mess`,
|
||||
`++process`ed to a `%g %mess`. Were the mark not `%json`, a `%ford` conversion
|
||||
would occur first, and `%made:axon` would send the gall message proper. In
|
||||
either case, eventually a `%mean` or `%nice` arrives, is encoded as json, and
|
||||
sent to the client callback.
|
||||
|
||||
## A path not taken: magic filenames [#mage]
|
||||
|
||||
The `/robots.txt` and `/favicon.(ico|png)` files are static, and served
|
||||
immediately when caught by a `++parse`.
|
||||
|
||||
XX index.html?
|
||||
|
||||
## A path not taken: foreign auth [#xeno]
|
||||
|
||||
While this example details a login `/~/as/own`, it is possible to be
|
||||
authenticated as any ship on the network. A request for such seen in
|
||||
`%get:process-auth` is passed to `++foreign-auth:ya`, which sends an
|
||||
`%ames /lon` message to the ship in question. The foreign ship stores the
|
||||
inquiry, calculates(the local) `++our-host` and responds with a `/hat`,
|
||||
containing the redirection host, which is stored by `++foreign-hat`; it is later
|
||||
used to send the client to a `/~/am` url on the foreign client, which acts as a
|
||||
normal login page but later sends the client back. XX expand, basically the
|
||||
status quo is you're logged in and `/~/as/foo` is ignored, just setting your
|
||||
`urb.user` XX
|
||||
|
||||
|
||||
## A path not taken: deauthentication
|
||||
|
||||
`/~/away`, perk `[%away ~]`, produces a static `++logout-page:xml`, which also
|
||||
uses `/~/at/auth.js`, to send a `DELETE /~/auth.json`, perk `[%auth %del]`. This
|
||||
executes `++logoff:ya` for the cookie session, resolving to `++abut` to wipe it
|
||||
from memory.
|
||||
|
||||
## A path not taken: unsubscription
|
||||
|
||||
`DELETE /~/is/app/path/within` works much like `PUT /~/is/app/path/within`,
|
||||
`++del-subs:ix` acting as reverse of `++add-subs` by deleting the duct binding
|
||||
and sending `%g %nuke`.
|
||||
|
||||
|
||||
XX unmentioned arms: abet, add-poll, adit, ames-gram, anon, ares-to-json, bolo, cyst, doze, even, ford-kill, get-mean, gift, give-json, give-thou, gram, hapt, hasp, host-to-ship, ix, ixor, js, kiss, load, mean-json, move, note, pass-note, perk, perk-auth, pest, poke-test, print-subs, render-tang, resp, root-beak, scry, ses-authed, ses-ya, sign, silk, sine, stay, stem, teba, titl, to-oryx, urb, wait-era, wake, whir, wush, xml, ya, ye
|
||||
|
||||
## Appendix A: DNS [#dns]
|
||||
|
||||
The `*.urbit.org` domain can be used to access destroyers and cruisers. In the
|
||||
common case oh hosted ships, this is done by dynamic DNS directly to the hosting
|
||||
instance. We do not speak of the uncommon case. When ports are blocked and
|
||||
infrastructure crumbles around you, only imported martian networking can be
|
||||
trusted: the `%get` and `%got` [gram]()s are used to proxy [`%this` requests]() and
|
||||
[`%thou` responses]() respectively.
|
@ -1,128 +0,0 @@
|
||||
<div class="short">
|
||||
|
||||
`%ford`
|
||||
=======
|
||||
|
||||
Our typed and marked computation engine.
|
||||
|
||||
A variety of different services are provided by `%ford`, but they mostly
|
||||
involve compiling hook files, slapping/slammming code with marked data,
|
||||
and converting data between marks, including validating data to a mark.
|
||||
Throughout every computation, `%ford` keeps track of which resources are
|
||||
dependencies so that the client may be aware when one or more
|
||||
dependencies are updated.
|
||||
|
||||
`%ford` neither accepts unix events nor produces effects. It exists
|
||||
entirely for the benefit of applications and other vanes, in particular
|
||||
`%gall`. `%eyre` exposes the functional publishing aspects of `%ford`
|
||||
while `%gall` uses `%ford` to control the execution of applications.
|
||||
`%clay` is intended to use `%ford` to managed marked data, but this is
|
||||
not yet reality.
|
||||
|
||||
</div>
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
<list></list>
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
Cards
|
||||
=====
|
||||
|
||||
`%ford` accepts just one card, `%exec`. This is misleading, however,
|
||||
since there are fourteen different `silk`s that may be used with it. In
|
||||
every case, the expected response to a `%exec` card is a `%made` gift
|
||||
with either an error or the produced result along with its set of
|
||||
dependencies.
|
||||
|
||||
Silks may autocons, so that the product of a cell of silks is a cell of
|
||||
the product of the two silks.
|
||||
|
||||
`%bake`
|
||||
================
|
||||
|
||||
Tries to functionally produce the file at a given beam with the given
|
||||
mark and heel. It fails if there is no way to translate at this level.
|
||||
|
||||
`%boil`
|
||||
================
|
||||
|
||||
Functionally produces the file at a given beam with the given mark and
|
||||
heel. If there is no way to translate at this beam, we pop levels off
|
||||
the stack and attempt to bake there until we find a level we can bake.
|
||||
This should almost always be called instead of `%bake`.
|
||||
|
||||
`%call`
|
||||
================
|
||||
|
||||
Slams the result of one silk against the result of another.
|
||||
|
||||
`%cast`
|
||||
================
|
||||
|
||||
Translates the given silk to the given mark, if possible. This is one of
|
||||
the critical and fundamental operations of ford.
|
||||
|
||||
`%diff`
|
||||
================
|
||||
|
||||
Diffs the two given silks (which must be of the same mark), producing a
|
||||
cage of the mark specified in `++mark` in `++grad` for the mark of the
|
||||
two silks.
|
||||
|
||||
`%done`
|
||||
================
|
||||
|
||||
Produces exactly its input. This is rarely used on its own, but many
|
||||
silks are recursively defined in terms of other silks, so we often need
|
||||
a silk that simply produces its input. A monadic return, if you will.
|
||||
|
||||
`%dude`
|
||||
================
|
||||
|
||||
Computes the given silk with the given tank as part of the stack trace
|
||||
if there is an error.
|
||||
|
||||
`%dune`
|
||||
================
|
||||
|
||||
Produces an error if the cage is empty. Otherwise, it produces the value
|
||||
in the unit.
|
||||
|
||||
`%mute`
|
||||
================
|
||||
|
||||
Takes a silk and a list of changes to make to the silk. At each wing in
|
||||
the list we put the value of the associated silk.
|
||||
|
||||
`%pact`
|
||||
================
|
||||
|
||||
Applies the second silk as a patch to the first silk. The second silk
|
||||
must be of the mark specified in `++mark` in `++grad` for the mark of
|
||||
the first silk.
|
||||
|
||||
`%plan`
|
||||
================
|
||||
|
||||
Performs a structured assembly directly. This is not generally directly
|
||||
useful because several other silks perform supersets of this
|
||||
functionality. We don't usually have naked hoods outside ford.
|
||||
|
||||
`%reef`
|
||||
================
|
||||
|
||||
Produces a core containing the entirety of zuse and hoon, suitable for
|
||||
running arbitrary code against. The mark is `%noun`.
|
||||
|
||||
`%ride`
|
||||
================
|
||||
|
||||
Slaps a twig against a subject silk. The mark of the result is `%noun`.
|
||||
|
||||
`%vale`
|
||||
================
|
||||
|
||||
Validates untyped data from a ship against a given mark. This is an
|
||||
extremely useful function.
|
File diff suppressed because it is too large
Load Diff
@ -1,161 +0,0 @@
|
||||
<div class="short">
|
||||
|
||||
`%gall`
|
||||
=======
|
||||
|
||||
Our application server manager.
|
||||
|
||||
It allows applications and vanes to send messages to applications and
|
||||
subscribe to data streams. This requires `%gall` to be a sort of a
|
||||
hypervisor. Messages coming into `%gall` are routed to the intended
|
||||
application, and the response comes back along the same route. If the
|
||||
intended target is on another ship, `%gall` will behind-the-scenes route
|
||||
it through ames to the other ship to run. This provides an abstraction
|
||||
where all apps on all ships are communicated with over the same
|
||||
interface.
|
||||
|
||||
`%gall` neither accepts events from unix nor produces effects. It exists
|
||||
entirely for the benefit of other vanes and, in particular,
|
||||
applications. Eyre exposes `%gall`'s interface over http, and ames does
|
||||
the same over the ames network. `%gall` uses ford to compile and run the
|
||||
applications.
|
||||
|
||||
</div>
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
Cards
|
||||
=====
|
||||
|
||||
`%gall` accepts the following cards. The first three are the most
|
||||
commonly used, while the others are primarily used internally.
|
||||
|
||||
`%mess`
|
||||
================
|
||||
|
||||
Sends a message to an app. This will result in a call to the app's
|
||||
`++poke` arm. The response is exactly one of a `%nice` if the action
|
||||
succeeded or a `%mean` if not.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
`%show`
|
||||
================
|
||||
|
||||
Subscribes to a stream from an app. This will result in a call to the
|
||||
app's either `++peek` or `++peer` arm. The first response will always be
|
||||
either a `%nice` or a `%mean`, indicating whether or not the
|
||||
subscription was successful. After the first response, there will be
|
||||
zero or more responses of either `%rush` or `%rust`, which communicate
|
||||
either a differntial or full update to the data stream. There may be a
|
||||
`%mean`, which indicates that the subscription has been canceled and no
|
||||
more responses will be received along this stream.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
`%nuke`
|
||||
================
|
||||
|
||||
Unsubscribes the current duct from its stream. This receives a response
|
||||
of either a `%nice` or a `%mean`. Note that a response of `%nice` does
|
||||
not imply that the current duct was in fact subscribed to any stream.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
`%init`
|
||||
================
|
||||
|
||||
Initializes a ship's apps. This should be called exactly once for each
|
||||
ship on the pier. This produces no moves in response.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
`%sire`
|
||||
================
|
||||
|
||||
Instantiates a child app. The app will be at path `[p parent-path]`, and
|
||||
it will be an instance of the `q` app. The only response will be `%gone`
|
||||
when the child dies.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
`%rote`
|
||||
================
|
||||
|
||||
Signifies a remote request from ames. `r` should be of type `rook`. This
|
||||
how an app on a foreign ship may send a `%mess`, `%show`, or `%nuke`
|
||||
card. Note that `%gall` automatically converts `%mess`, `%show`, and
|
||||
`%nuke` into ames messages behind the scenes, so the only entity that
|
||||
should use `%rote` and `%roth` is ames. Formally, the response is either
|
||||
a `%nice` or a `%mean`, which ames uses to give a positive or negative
|
||||
ack. A logical response comes by passing a `%roth` card.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
`%roth`
|
||||
================
|
||||
|
||||
Gives the response received from a remote request. `r` should be of type
|
||||
`roon`. This is how an app responds to a foreign request with a `%rush`,
|
||||
`%rust`, `%nice`, or `%mean`. The response is either a `%nice` or a
|
||||
`%mean`. Even though we, as the proverb goes, "never ack an ack", we do
|
||||
need to acknowledge these responses since they're really independent
|
||||
one-way messages.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
`%wipe`
|
||||
================
|
||||
|
||||
Wipes the given app from memory. This is generally considered a hack,
|
||||
but it is sometimes useful during development to wipe the state of an
|
||||
app. We don't guarantee that this actually completely wipes the app.
|
||||
Generally, you want to use a `%cide` card if you actually want to kill
|
||||
an app. This gives no response.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
`%cide`
|
||||
================
|
||||
|
||||
Kills an app and all its children. Even though it's not technically a
|
||||
part of `%gall`'s interface since it's not in `++kiss` and can't be
|
||||
called from the outside, it's worth mentioning `%cide`, which may be
|
||||
called from within `%gall` apps. It should call `++part` to allow the
|
||||
app any last words. This gives no response.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
Service Gates
|
||||
=============
|
||||
|
||||
[`++poke`]()
|
||||
============
|
||||
|
||||
Handles incoming messages. Most commonly with an associated `%logo`. For
|
||||
example `++poke-json` handles an incoming JSON request from `%eyre`.
|
||||
|
||||
[`++peer`]()
|
||||
============
|
||||
|
||||
Handles incoming subscriptions.
|
||||
|
||||
[`++pull`]()
|
||||
============
|
||||
|
||||
Handles dropping subscribers.
|
||||
|
||||
[`++pour`]()
|
||||
============
|
||||
|
||||
Handles responses to `%pass` moves.
|
||||
|
||||
[`++park`]()
|
||||
============
|
||||
|
||||
Save state on update.
|
||||
|
||||
[`++prep`]()
|
||||
============
|
||||
|
||||
Load state on update.
|
@ -1,5 +0,0 @@
|
||||
Gall: Reference
|
||||
===============
|
||||
|
||||
Gall: Commentary
|
||||
================
|
@ -1,21 +0,0 @@
|
||||
<div class="short">
|
||||
|
||||
`%time`
|
||||
=======
|
||||
|
||||
Our simple timer.
|
||||
|
||||
It allows vanes and applications to set and timer events, which are
|
||||
managed in a simple priority queue. `%time` produces effects to start
|
||||
the unix timer, and when the requested `%time` passes, unix sends wake
|
||||
events to `%time`, which time routes back to original sender. We don't
|
||||
guarantee that a timer event will happen at exactly the `%time` it was
|
||||
set for, or even that it'll be particularly close. A timer event is a
|
||||
request to not be woken until after the given time.
|
||||
|
||||
`%eyre` uses `%time` for timing out sessions, and `%clay` uses `%time`
|
||||
for keeping track of time-specified file requests. `%ames` should
|
||||
probably use `%time` to keep track of things like network timeouts and
|
||||
retry timing, but it currently uses its own alarm system.
|
||||
|
||||
</div>
|
@ -1,344 +0,0 @@
|
||||
<div class="short">
|
||||
|
||||
CLI Apps
|
||||
========
|
||||
|
||||
Our simple command-line applications.
|
||||
|
||||
You can find them in `/main/app`.
|
||||
|
||||
</div>
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `:?begin`
|
||||
|
||||
`~zod:dojo> :?begin [~ship-name [~valid-ticket-for-ship]]`
|
||||
|
||||
Start a ship. `:?begin` collects all of the necessary information to
|
||||
start an Urbit ship. Takes an option `[~ship-name]` or
|
||||
`[~ship-name [~valid-ticket-for-ship]]` pair.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `+cat`
|
||||
|
||||
`~zod:dojo> +cat /path/to/file [...]`
|
||||
|
||||
"cat" a file. `+cat` either prints a file, or concatenates and then
|
||||
prints multiple files to the terminal.
|
||||
|
||||
~zod:dojo> +cat %/spec/nock/5/txt
|
||||
> +cat %/spec/nock/5/txt
|
||||
/~zod/home/~2015.6.29..22.33.04..fc76/spec/nock/5/txt
|
||||
A noun is an atom or a cell.
|
||||
…
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `|cp`
|
||||
|
||||
`~zod:dojo> |cp /path/to/source /path/to/destination`
|
||||
|
||||
Copy a file to a given location.
|
||||
|
||||
~zod:dojo> |cp %/spec/nock/5/txt %/try/6/txt
|
||||
> |cp %/spec/nock/5/txt %/try/6/txt
|
||||
+ /~zod/home/2/try/6/txt
|
||||
>=
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `grep`
|
||||
|
||||
<mark>GONE</mark>
|
||||
|
||||
`~zod:dojo> :grep 'literal'`
|
||||
"grep" a file or standard input. Currently only supports a literal cord,
|
||||
but will eventuall support regular expressions.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `|hi`
|
||||
|
||||
`~zod:dojo> |hi ~ship ["message"]`
|
||||
|
||||
Send a ship a message which is empty by default, becoming their neighbor
|
||||
in the process. Often used to ping ships to check connectivity.
|
||||
|
||||
|
||||
~zod:dojo> |hi ~doznec
|
||||
> |hi ~doznec
|
||||
ames: czar zod.urbit.org: ip .192.241.195.84
|
||||
>=
|
||||
hi ~doznec succesful
|
||||
; ~doznec is your neighbor
|
||||
; ~doznec is your neighbor
|
||||
|
||||
and on ~doznec
|
||||
|
||||
~doznec:dojo>
|
||||
< ~zod:
|
||||
; ~zod is your neighbor
|
||||
|
||||
|
||||
send a message
|
||||
|
||||
~zod:dojo> |hi ~doznec "say something"
|
||||
>=
|
||||
hi ~doznec succesful
|
||||
|
||||
and on ~doznec
|
||||
|
||||
< ~zod: say something
|
||||
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `:into`
|
||||
|
||||
<mark>GONE</mark>
|
||||
|
||||
`~zod:dojo> :into /path/to/file 'contents'`
|
||||
|
||||
Write text to a file. If the specified file does not exist, create a
|
||||
file by that name. If it does exist, replace its contents.
|
||||
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `|label`
|
||||
|
||||
<mark>GONE? returns file not found</mark>
|
||||
|
||||
`~zod:dojo> |label %path %label`
|
||||
|
||||
"label". Add a label to a change number.
|
||||
|
||||
~zod:dojo> |label %try %zebra
|
||||
= new /~zod/try/3
|
||||
~zod:dojo> :ls /=try/zebra
|
||||
readme
|
||||
|
||||
Note that adding a label is part of the delta stream and creates a new
|
||||
change number, `3`.
|
||||
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `+ls`
|
||||
|
||||
`~zod:dojo> :+ls path/to/directory`
|
||||
|
||||
"ls". List files at a path. Unlike "ls" in Unix, the current path `%`
|
||||
must be explicitly given (you cannot call `+ls` with no arguments to
|
||||
display the files at the current path).
|
||||
|
||||
~zod:dojo> +ls %try
|
||||
> +ls %/try/
|
||||
readme/md
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `|mount`
|
||||
|
||||
`~zod:dojo> |mount /path/to/directory/version %mount-point`
|
||||
|
||||
Your files are not synced to unix by default.
|
||||
To sync a subtree to unix, run `|mount /path/to/directory %mount-point`.
|
||||
This will sync it into `<pier>/<mount-point>.`
|
||||
If you want to sync your whole home desk into f0/home, for example,
|
||||
run `|mount % %home` You can also [`|unmount`]().
|
||||
|
||||
~zod:dojo> |mount /~zod/base/0 %base
|
||||
> |mount /~zod/base %base
|
||||
>=
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `|mv`
|
||||
|
||||
`~zod:dojo> |mv /path/to/source /path/to/destination`
|
||||
|
||||
Move a file to a given location, creating a new revision of the source
|
||||
that omits the moved file.
|
||||
|
||||
~zod:dojo> |mv %/try/6/txt %/try/7/txt
|
||||
> |mv %/try/6/txt %/try/7/txt
|
||||
+ /~zod/home/3/try/7/txt
|
||||
>=
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `|reload`
|
||||
|
||||
`~zod:dojo> |reload %vane-name [...]`
|
||||
|
||||
Reload the standard library (zuse) and/or arvo vanes. If zuse is
|
||||
reloaded, vanes depending on the changes must be reloaded as well. For
|
||||
example `|reload %zuse %ford` is necessary to make use of changes in
|
||||
application code or the REPL.
|
||||
|
||||
Possible values for %vane-name see [Overview](overview "overview"):
|
||||
|
||||
~zod:dojo> |reload %zuse
|
||||
[%tang /~zod/home/~2015.6.29..23.50.29..134d/arvo/zuse ~hillyx-salhet]
|
||||
> |reload %zuse
|
||||
>=
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `|reset`
|
||||
|
||||
`~zod:dojo> |reset`
|
||||
|
||||
Reloads all vanes. See [`|reload`]() for reloading only or a specific vane.
|
||||
|
||||
~zod:dojo> |reset
|
||||
[%vega-start /~zod/home/~2015.6.29..23.51.42..f335/arvo/hoon]
|
||||
%vega-parsed
|
||||
[%vega-compiled %163 163]
|
||||
%hoon-load
|
||||
[%tang /~zod/home/~2015.6.29..23.51.42..f335/arvo/zuse ~hillyx-salhet]
|
||||
[%vane %a /~zod/home/~2015.6.29..23.51.42..f335/arvo/ames ~tilwyl-talren]
|
||||
%ames-reload
|
||||
[%vane %c /~zod/home/~2015.6.29..23.51.42..f335/arvo/clay ~molmur-panlus]
|
||||
[%vane %d /~zod/home/~2015.6.29..23.51.42..f335/arvo/dill ~sicbet-miphes]
|
||||
[%vane %e /~zod/home/~2015.6.29..23.51.42..f335/arvo/eyre ~solrux-sibnep]
|
||||
[gub=30 hov=19 ged=18 ded=1 pox=1 ask=1 kes=1 ney=35 dop=1 liz=1 wup=1 sop=1 wix=1]
|
||||
[%vane %f /~zod/home/~2015.6.29..23.51.42..f335/arvo/ford ~librem-sopseg]
|
||||
[%vane %g /~zod/home/~2015.6.29..23.51.42..f335/arvo/gall ~sidsub-fasrev]
|
||||
[%vane %t /~zod/home/~2015.6.29..23.51.42..f335/arvo/time ~ritwyn-lanrev]
|
||||
> |reset
|
||||
<<<reset>>>
|
||||
>=
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `|rm`
|
||||
|
||||
`~zod:dojo> |rm /path/to/source`
|
||||
|
||||
Remove a file.
|
||||
|
||||
~zod:dojo> |rm %/try/7/txt
|
||||
>=
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `+solid`
|
||||
|
||||
`~zod:dojo> +solid`
|
||||
|
||||
compiles a kernel into a new full urbit.pill
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `|sync`
|
||||
|
||||
`~zod:dojo> |sync %source-desk ~hidduc-posmeg %target-desk`
|
||||
|
||||
Sets up a subscription to the source desk on the target ship name to the
|
||||
target desk on your ship.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `+ticket`
|
||||
|
||||
`~zod:dojo> +ticket ~ship-name`
|
||||
|
||||
Creates a will for a ship. `+ticket` outputs the ticket for a Urbit
|
||||
ship. Takes an option `[~ship-name]`. On destroyes this command creates
|
||||
a yacht and takes the option \`[\~yacht-name-destroyer-name]
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `:thumb`
|
||||
|
||||
<mark>GONE</mark>
|
||||
|
||||
`~zod:dojo> :thumb ~ship-name`
|
||||
|
||||
Show the ships information. Only works if you issued a [`:hi`]
|
||||
[\`\~ship-name] beforehand.
|
||||
|
||||
This command is not avaible since the switch from batz to `%gall`!
|
||||
|
||||
Use this for the time beeing: - will:
|
||||
`~zod/try=> ((hard (unit gcos)) .^(%a /=gcos=/~ship-name))` - raw will:
|
||||
`~zod/try=> ((hard will) .^(%a /=will=/~ship-name))`
|
||||
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `|unmount`
|
||||
|
||||
`~zod:dojo> |unmount /path/to/directory`
|
||||
|
||||
Your files are not synced to unix by default.
|
||||
To sync a subtree to unix, run `|mount`.
|
||||
You can unmount with either `|unmount /path/to/directory`
|
||||
or `|unmount %mount-point`.
|
||||
|
||||
~zod:dojo> |unmount %base
|
||||
> |unmount %base
|
||||
>=
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `|unsync`
|
||||
|
||||
`~zod:dojo> |unsync %source-desk ~hidduc-posmeg %target-desk`
|
||||
|
||||
Cancels the subscription to the source desk on the target ship name to
|
||||
the target desk on your ship.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `|verb`
|
||||
|
||||
`~zod:dojo> |verb`
|
||||
|
||||
Turn verbose arvo mode on/off.
|
||||
|
||||
You'll see events, internal cards, and effects.
|
||||
|
||||
[%unix p=%wake //temp]
|
||||
[ %give
|
||||
%t
|
||||
%wake
|
||||
~[
|
||||
/c/tyme
|
||||
/g/a/~zod/._~~.58_~~.shell_~~.terminal__/w/drug/~zod/main
|
||||
/g/a/~harnyr-darlux-bitrux-litnum--falbec-tacsev-magdus-tobsyn/began/u
|
||||
/g/a/~harnyr-darlux-bitrux-litnum--falbec-tacsev-magdus-tobsyn/._~~.2_~~.shell_~~.terminal__/u/to-gan
|
||||
/g/a/~harnyr-darlux-bitrux-litnum--falbec-tacsev-magdus-tobsyn/._~~.shell_~~.terminal__/u/child/2/main
|
||||
/g/a/~harnyr-darlux-bitrux-litnum--falbec-tacsev-magdus-tobsyn/terminal/u/txt
|
||||
/d/term-mess
|
||||
//term/1
|
||||
]
|
||||
]
|
||||
[ %give
|
||||
%c
|
||||
%writ
|
||||
~[
|
||||
/g/a/~zod/._~~.58_~~.shell_~~.terminal__/w/drug/~zod
|
||||
/g/a/~harnyr-darlux-bitrux-litnum--falbec-tacsev-magdus-tobsyn/began/u
|
||||
/g/a/~harnyr-darlux-bitrux-litnum--falbec-tacsev-magdus-tobsyn/._~~.2_~~.shell_~~.terminal__/u/to-gan
|
||||
/g/a/~harnyr-darlux-bitrux-litnum--falbec-tacsev-magdus-tobsyn/._~~.shell_~~.terminal__/u/child/2/main
|
||||
/g/a/~harnyr-darlux-bitrux-litnum--falbec-tacsev-magdus-tobsyn/terminal/u/txt
|
||||
/d/term-mess
|
||||
//term/1
|
||||
]
|
||||
]
|
||||
...
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `|ye`
|
||||
|
||||
`~zod:dojo> |ye ["message"]`
|
||||
|
||||
Send a message to all ships. Often used to announce a continuity breach.
|
||||
|
||||
------------------------------------------------------------------------
|
@ -1,28 +0,0 @@
|
||||
---
|
||||
sort: 1
|
||||
---
|
||||
|
||||
<div class="short">
|
||||
|
||||
hoon
|
||||
====
|
||||
|
||||
hoon is our programming language.
|
||||
|
||||
hoon is a strict, typed, functional language that compiles itself to
|
||||
nock. The hoon compiler is 4000 lines of hoon. Adding standard
|
||||
libraries, the self-compiling kernel is 8000 lines. The hoon compiler is
|
||||
located towards the bottom of `/=main=/arvo/hoon.hoon`. The standard
|
||||
library is split between `/=main=/arvo/hoon.hoon` and
|
||||
`/=main=/arvo/zuse.hoon`.
|
||||
|
||||
hoon has no particular familial relationship to other languages you may
|
||||
know. It uses its own type inference algorithm and is as different from
|
||||
Haskell as from Lisp. hoon syntax is also completely unfamiliar. hoon
|
||||
uses ascii digraphs, which we call 'runes', instead of reserved words.
|
||||
|
||||
</div>
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
<list></list>
|
@ -1,16 +0,0 @@
|
||||
---
|
||||
sort: 3
|
||||
---
|
||||
|
||||
<div class="short">
|
||||
|
||||
Interpreter
|
||||
==========
|
||||
|
||||
The urbit interpreter and C code.
|
||||
|
||||
</div>
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
<list></list>
|
@ -1,345 +0,0 @@
|
||||
<div class="short">
|
||||
|
||||
Glossary
|
||||
========
|
||||
|
||||
### arm
|
||||
|
||||
A key-value pair of a name ([++term]()) to an expression ([++foot()]).
|
||||
Used primarily in [core]() construction. Arms can contain either
|
||||
functions or data. You can think of them like named properties inside an
|
||||
object.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### atom
|
||||
|
||||
An atom is a natural number. More here..?
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### axil
|
||||
|
||||
An `[%axil p=base]` is a simple [`++tile`]() for a few basic icons: an
|
||||
atom of any odor, a noun (`*`) , a cell of nouns (`^`), a loobean (`?`),
|
||||
and null (`~`).
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### battery
|
||||
|
||||
[Cores], at the most basic level, are of the structure [battery
|
||||
payload]. The battery consists of the code contained within a core.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `%bark`
|
||||
|
||||
A `[%bark p=term q=tile]` is a [`++tile`]() with a name wrapped around
|
||||
it. Its [icon]() is a [`++face`](). The rune associated with a
|
||||
[`%bark`]() is [`$=`]().
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### bunt
|
||||
|
||||
The bunt of a [`++tile`]() produces a [`++twig`]() that creates a blank
|
||||
default example its [icon](). Bunting is like explicitly asking for the
|
||||
default value of a type. Unlike in other languages, this always exists
|
||||
in Hoon. See also [`$*`]().
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `%bush`
|
||||
|
||||
a [`[%bush p=tile q=tile]`]() is a [`++tile`]() in which there are two
|
||||
kinds of [nouns](): cells whose head is a cell (`++tile` p) and cells
|
||||
whose head is an atom (`++tile` q). Its default value is the value of
|
||||
`q`, and its icon is a [`++fork`]()
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### cell
|
||||
|
||||
A cell is an ordered pair of nouns.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### clam
|
||||
|
||||
The clam of a [`++tile`]() is a [gate]() that accepts an arbitrary
|
||||
[noun]() and always produces a member of the [icon]() of the `++tile`.
|
||||
If the gate is passed a [sample]() that is a member of the icon, it will
|
||||
produce that sample. If the gate is passed a noun outside of the domain
|
||||
of the icon, it will produced the [bunt]() of the icon. You can think of
|
||||
a clam as a validator function for an icon. To clam a `++tile` is to
|
||||
produce its clam. See also: [`$,`](). SEE ALSO!!
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### context
|
||||
|
||||
In [gate]() construction, an arm is pulled from a [core]() and pushed
|
||||
onto the subject creating a structure of [formula [sample context]],
|
||||
where the context is the previous subject, commonly a core. In Hoon, the
|
||||
whole kernel is typically included in your subject, so you can think of
|
||||
context in hoon in a similar way to context in the traditional
|
||||
functional programming sense.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### cons
|
||||
|
||||
Cell constructor, similar to [cons in other functional
|
||||
languages](http://en.wikipedia.org/wiki/Cons). Constructs a cell
|
||||
containing two [`++twigs`]() into a twig that produces a cell of the
|
||||
results of the two original sub-twigs.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### core
|
||||
|
||||
At the Nock level, a core is any [subject]() that contains both code and
|
||||
data, named battery and payload respectively. At the Hoon level, a core
|
||||
is very similar to an object with named properties that can be either
|
||||
functions or data. For more information, see the [`|` rune section]() of
|
||||
the Hoon library.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `%cube`
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### door
|
||||
|
||||
A door is a [core]() with a sample. Door are used.../you can think of
|
||||
doors...
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### dry
|
||||
|
||||
In a dry computation, typechecking occurs at compile-time to ensure that
|
||||
all inputs match its [sample]() [++tile](). The formal term for dry is
|
||||
`%ash`.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### engine
|
||||
|
||||
Engines are [core]()s that contain several [arm]()s that each perform
|
||||
one of a related set of operations on the core's sample. For example,
|
||||
there is a container engine for all of the set operations. You can think
|
||||
of engines as objects with methods that modify its data.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `%face`
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### fern
|
||||
|
||||
A `[%fern p=[i=tile t=(list tile)]]` is a [`++tile`]() for a non-empty
|
||||
list of cases. Its icon is naturally a [`%fork`](). The programmer is
|
||||
responsible for ensuring that the cases are actually orthogonal (unlike
|
||||
with the structured `%fork`s, [`%bush`](), [`%kelp`]() and [`%reed`]).
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### fishing
|
||||
|
||||
To fish is to test if a [noun]() matches a specific `++tile`, using the
|
||||
natural rune [`?=`](). Some languages call fishing "pattern matching".
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### frond
|
||||
|
||||
A frond is a case of a [kelp](), which is a [discriminated (or tagged)
|
||||
union](http://en.wikipedia.org/wiki/Tagged_union).
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### gate
|
||||
|
||||
A [gate]() is a [core]() with one arm [`$`]() with a [payload]() that is
|
||||
a cell of the form [[sample]() [context]()]. Gates are the closest thing
|
||||
Hoon has to functions in the traditional sense.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `%gold`
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### herb
|
||||
|
||||
An `[%herb p=twig]`....
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### icon
|
||||
|
||||
The icon of a [`++tile`]() is the type associated with that `++tile`. A
|
||||
`++tile` is a convenient way of specifying a type, which is its icon.
|
||||
`++tile`s are used in a similar way to [type signatures]() for their
|
||||
icons.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `%iron`
|
||||
|
||||
`%iron` is a variance type for [cores]() where their [sample]()s cannot
|
||||
be read. You can think of can be thought of as similar to a private
|
||||
function.
|
||||
|
||||
Not quite sure about this one.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `%kelp`
|
||||
|
||||
a [`%kelp p=[i=line t=(list line)]`] is a [discriminated, or tagged,
|
||||
union](http://en.wikipedia.org/wiki/Tagged_union). In Hoon, the head,
|
||||
which is called the stem, must be a [`%leaf`](). The tail, which can be
|
||||
anything, is the bulb. Cases of a kelp are known as [fronds]().
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### kick
|
||||
|
||||
To pull the empty name `$` on a core is to kick it. You can think of
|
||||
kicking like calling a function with its default arguments.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### noun
|
||||
|
||||
A noun is an [atom]() or a [cell](). Everything in Hoon is a noun.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `%$` buc
|
||||
|
||||
`%$`, or `$` for short, is the empty name in Hoon.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### leg
|
||||
|
||||
If the result of [pulling]() something from `x` is a subtree, then it is
|
||||
a leg.
|
||||
|
||||
More here? Existing doc isn't quite clear here..
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `%lead`
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `%leaf`
|
||||
|
||||
A `%leaf` is a [`++tile`]() consisting of an atomic constant of value
|
||||
`q` and odor `p`. Its icon is a [`%cube`](). The syntax for a leaf is
|
||||
the same as the syntax for a [`++twig`](), except that % is never
|
||||
required to generate a cube. For instance, as a twig, 7 has a type of
|
||||
[%atom %ud]; %7 has a type of [%cube 7 [%atom %ud]]. But the icon of the
|
||||
leaf 7 is, again, [%cube 7 [%atom %ud]].
|
||||
|
||||
Copied the bottom half from existing doc. Not sure about this one...
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### loobean
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### payload
|
||||
|
||||
[Cores](), at the most basic level, are of the structure [battery
|
||||
payload]. The payload consists of the data contained within a core. You
|
||||
can think of the payload as similar to the data of an object.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### pull
|
||||
|
||||
To access a [wing]() or [limb]() in a [core]() is to pull it. For
|
||||
instance, when we write `a.b.x` (a within b from x), we are pulling the
|
||||
wing `a.b` from `x`.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `%reed`
|
||||
|
||||
A `[%reed p=tile q=tile]` is a [`++tile`]() whose [icon]() contains two
|
||||
kinds of nouns: atoms of `++tile` `p` and cells of `++tile` `q`. The
|
||||
rune associated with reeds is [`$|`]().
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### sample
|
||||
|
||||
In [gate]() construction, an arm is pulled from a [core]() and pushed
|
||||
onto the subject creating a structure of [formula [sample context]],
|
||||
where the sample represents the gate's inputs. All gates are constructed
|
||||
with a default sample value. Thus, when we call a gate with arguments,
|
||||
we are actually replacing its sample.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### slam
|
||||
|
||||
To pull the empty name `$` on a [gate]() `g` with its [sample]()
|
||||
replaced by a given input `a` is to slam `g` with `a`. You can think of
|
||||
slamming like passing input parameters to a function that's being
|
||||
called.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### subject
|
||||
|
||||
All Hoon expressions a parsed into abstract syntax trees, which in Hoon
|
||||
are called [++twig]()s. Twigs are [nouns]() that are converted into Nock
|
||||
expressions, which are all of the basic form [subject formula], where
|
||||
the subject is the data and the formula is the program. Thus, in both
|
||||
Hoon and Nock, subject can refer to any piece of data that is being
|
||||
operated on by a formula.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `++tile`
|
||||
|
||||
A `++tile` is a convenient way of specifying a type, which is its icon.
|
||||
`++tile`s are used in a similar way to [type signatures]() for their
|
||||
icons.
|
||||
|
||||
SOMETHING ABOUT THE DIFFERENCE BETWEEN TWIG AND TILE AUTOCONS.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### weed
|
||||
|
||||
A `[%weed p=twig]`
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### wet
|
||||
|
||||
In wet computations, the product type is checked to be the same as the
|
||||
input type, rather than the [sample]() [tile](). The formal term for wet
|
||||
is `%elm`.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### wing
|
||||
|
||||
A wing is a list of limbs. For example, when we [pull] `a.b` from `x`,
|
||||
`a.b` is a wing. `a` and `b` individually are both [limbs]().
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
</div>
|
@ -1,183 +0,0 @@
|
||||
<div class="short">
|
||||
|
||||
vere
|
||||
====
|
||||
|
||||
vere is the Urbit virtual machine.
|
||||
|
||||
bin/vere -c ship
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
Options
|
||||
-------
|
||||
|
||||
### `-b`
|
||||
|
||||
Batch create
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `-c`
|
||||
|
||||
Create
|
||||
|
||||
Creates a new pier. Takes a folder name, such as `pier`.
|
||||
|
||||
bin/vere -c pier
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `-d`
|
||||
|
||||
Daemon
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `-D`
|
||||
|
||||
Dry compute
|
||||
|
||||
dry compute the north and/or south events
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `-f`
|
||||
|
||||
Fuzz testing
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `-k`
|
||||
|
||||
Kernel version
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `-l`
|
||||
|
||||
Raft port
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `-L`
|
||||
|
||||
Localhost.
|
||||
|
||||
Routes all networking over `0.0.0.0` and checks the keys.
|
||||
|
||||
bin/vere -L -I ~del -c fz
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `-M`
|
||||
|
||||
Memory madness
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `-n`
|
||||
|
||||
Unix hostname
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `-p`
|
||||
|
||||
Specify the [`%ames`](/doc/arvo/ames) udp listening port.
|
||||
|
||||
bin/vere -p 42665
|
||||
|
||||
It can sometimes help if you get a port pointed at you and run vere with
|
||||
`-p` to specify the [`%ames`](/doc/arvo/ames) udp listening port. VMs
|
||||
and [docker](http://www.docker.com/) containers and the like tend to put
|
||||
up some pretty effective barriers to
|
||||
[NAT](http://en.wikipedia.org/wiki/Network_address_translation) [hole
|
||||
punching](http://en.wikipedia.org/wiki/TCP_hole_punching).
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `-P`
|
||||
|
||||
Profile
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `-q`
|
||||
|
||||
Quite
|
||||
|
||||
Inverse of [`-v`](#-v)
|
||||
|
||||
See also: [`:verb`](/doc/arvo/util#verb))
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `-r`
|
||||
|
||||
Raft flotilla
|
||||
|
||||
Also needs the [`-l`](#-l) option set.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `-F`
|
||||
|
||||
Fake
|
||||
|
||||
Routes all networking over `0.0.0.0` and doesn't check any keys. This
|
||||
allows you to start any carrier.
|
||||
|
||||
bin/vere -F -I ~zod -c zod
|
||||
|
||||
You get an isolated network with just yourself but you can [`:ticket`]()
|
||||
other ships or start other ships or start other carriers.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `-I`
|
||||
|
||||
Imperial
|
||||
|
||||
Takes a carrier name, such as `~zod`.
|
||||
|
||||
bin/vere -F -I ~zod -c zod
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `-v`
|
||||
|
||||
Verbose
|
||||
|
||||
Inverse of [`-q`](#-q)
|
||||
|
||||
See also: [`:verb`](reference/arvo/util.md#verb).
|
||||
|
||||
bin/vere -v mypier
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
### `-X`
|
||||
|
||||
Skip last event
|
||||
|
||||
bin/vere -Xwtf mypier
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
Tips
|
||||
====
|
||||
|
||||
Inability to mmap 2Gb with `MAP_FIXED`
|
||||
--------------------------------------
|
||||
|
||||
It's probably because of
|
||||
[ASLR](http://en.wikipedia.org/wiki/Address_space_layout_randomization)
|
||||
(some shared library got its data mapped in the middle of your address
|
||||
space). If so, applying
|
||||
|
||||
bash setarch `uname -m` -R ./bin/vere
|
||||
|
||||
should help.
|
||||
|
||||
</div>
|
@ -1,41 +0,0 @@
|
||||
---
|
||||
sort: 0
|
||||
---
|
||||
|
||||
<div class="short">
|
||||
|
||||
nock
|
||||
====
|
||||
|
||||
nock is our machine code.
|
||||
|
||||
nock is a homoiconic combinator algebra, not much fancier than SKI
|
||||
combinators. The spec fits on a T-shirt and gzips to 340 bytes.
|
||||
|
||||
Think of nock as a kind of functional assembly language. It's not like
|
||||
assembly language in that it's directly executed by the hardware. It is
|
||||
like assembly language in that:
|
||||
|
||||
- Everything in Urbit executes as nock.
|
||||
- You wouldn't want to program directly in nock.
|
||||
- Learning to program directly in nock is a great way to start
|
||||
understanding urbit from the ground up.
|
||||
|
||||
Just as Unix runs C programs by compiling them to assembler, Urbit runs
|
||||
Hoon programs by compiling them to nock. You could try to learn Hoon
|
||||
without learning nock. But just as C is a thin wrapper over the physical
|
||||
CPU, Hoon is a thin wrapper over the nock virtual machine. It's a tall
|
||||
stack made of thin layers, which is much easier to learn a layer at a
|
||||
time.
|
||||
|
||||
And unlike most fundamental theories of computing, there's really
|
||||
nothing smart or interesting about nock. Of course, in a strictly formal
|
||||
sense, all of computing is math. But that doesn't mean it needs to feel
|
||||
like math. nock is a simple mechanical device and it's meant to feel
|
||||
that way.
|
||||
|
||||
</div>
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
<list></list>
|
@ -1,10 +0,0 @@
|
||||
---
|
||||
sort: 4
|
||||
---
|
||||
|
||||
Tools
|
||||
====
|
||||
|
||||
User-level tools and utilities.
|
||||
|
||||
<list dataPreview="true"></list>
|
@ -1,209 +0,0 @@
|
||||
`%clay`
|
||||
========
|
||||
|
||||
`%clay` filesystem utilities.
|
||||
|
||||
## Paths
|
||||
|
||||
### Structure
|
||||
|
||||
Urbit paths have a very specific structure. First, since the clay
|
||||
filesystem has a global namespace, the first element in any path
|
||||
is the particular urbit whose filesystem you are trying to
|
||||
access.
|
||||
|
||||
The second element specifies which desk you wish to access on
|
||||
that urbit. Desks are independent branches (in the
|
||||
revision-control sense) of their filesystem.
|
||||
|
||||
The third element specifies the revision number for that
|
||||
desk. The remainder of the path is the path to the file.
|
||||
|
||||
Thus, a path in clay is:
|
||||
|
||||
`/urbit/desk/revision/path`.
|
||||
|
||||
For example, to get revision 5 of `/try/readme/md` off the `home`
|
||||
desk on `~sampel-sipnym`, use:
|
||||
|
||||
`/~sampel-sipnym/home/5/try/readme/md`.
|
||||
|
||||
### Shortcuts
|
||||
|
||||
`%` refers to the current working
|
||||
directory. `%%` refers to our parent, `%%%` refers to our
|
||||
grandparent, and so forth.
|
||||
|
||||
For example:
|
||||
|
||||
XX TBD
|
||||
|
||||
|
||||
From the other direction, inserting a `=` into a path copies the
|
||||
corresponding element from the current path into the path that
|
||||
you're trying to access.
|
||||
|
||||
For example, if the current path is referencing our ship at the
|
||||
current time, to reference `/try/readme`, use:
|
||||
|
||||
`/===try/readme`.
|
||||
|
||||
|
||||
### Accessing commits
|
||||
|
||||
There are three ways to refer to particular commits in the
|
||||
revision history. First, one can use the revision number.
|
||||
Second, one can use any absolute time between the one numbered
|
||||
commit and the next (inclusive of the first, exclusive of the
|
||||
second). Thirdly, every desk has a map of labels to revision
|
||||
numbers. These labels may be used to refer to specific commits.
|
||||
|
||||
|
||||
## `ls`
|
||||
|
||||
`+ls /path` gives a directory listing at a path
|
||||
|
||||
## `cat`
|
||||
|
||||
`+cat /path`
|
||||
prints out the file at the given path.
|
||||
|
||||
## `mount`
|
||||
|
||||
It's often useful to "mount" the clay filesystem to unix, so that
|
||||
you can interact with it with the traditional unix tools. The
|
||||
syntax to do this is as follows:
|
||||
|
||||
|mount /path [%mount-point]
|
||||
|
||||
This mirrors the desk out to unix in at the path
|
||||
`<pier-directory> <mount-point>`. If you don't supply a
|
||||
`%mount-point`, we use the last element in the path. Thus, if
|
||||
you mount `%/pub/doc`, it'll by default put it in `doc`.
|
||||
|
||||
*The mount point is monitored Dropbox-style, so every change you
|
||||
make to the file in unix is automatically commited to clay.*
|
||||
|
||||
You can unmount by specifying either the path or the mount point.
|
||||
|
||||
|unmount /path
|
||||
|unmount %mount-point
|
||||
|
||||
## `merge`
|
||||
|
||||
Often, it's useful to be able to merge a desk into another desk.
|
||||
The other desk does not, of course, need to be on the same urbit:
|
||||
for example, the standard way to distribute an app is to put it
|
||||
on a desk and let other people merge it into their own urbit.
|
||||
|
||||
The syntax is as follows:
|
||||
|
||||
|merge %to-desk ~from-urbit %from-desk [%strategy]
|
||||
|
||||
There are seven different merge strategies. Throughout our
|
||||
discussion, we'll say that the merge is from Alice's desk to
|
||||
Bob's.
|
||||
|
||||
### Native strategies
|
||||
|
||||
A `%init` merge should be used iff it's the first commit to a
|
||||
desk. The head of Alice's desk is used as the number 1 commit to
|
||||
Bob's desk. Obviously, the ancestry remains intact when
|
||||
traversing the parentage of the commit, even though previous
|
||||
commits are not numbered for Bob's desk.
|
||||
|
||||
A `%this` merge means to keep what's in Bob's desk, but join the
|
||||
ancestry. Thus, the new commit has the head of each desk as
|
||||
parents, but the data is exactly what's in Bob's desk. For those
|
||||
following along in git, this is the 'ours' merge strategy, not
|
||||
the '--ours' option to the 'recursive' merge strategy. In other
|
||||
words, even if Alice makes a change that does not conflict with
|
||||
Bob, we throw it away.
|
||||
|
||||
A `%that` merge means to take what's in Alice's desk, but join
|
||||
the ancestry. This is the reverse of `%this`.
|
||||
|
||||
A `%fine` merge is a "fast-forward" merge. This succeeds iff one
|
||||
head is in the ancestry of the other. In this case, we use the
|
||||
descendant as our new head.
|
||||
|
||||
For `%meet`, `%mate`, and `%meld` merges, we first find the most
|
||||
recent common ancestor to use as our merge base. If we have no
|
||||
common ancestors, then we fail. If we have multiple most
|
||||
recent common ancestors, then we have a criss-cross situation,
|
||||
which should be handled delicately. At present, we don't handle
|
||||
this kind of situation, but something akin to git's 'recursive'
|
||||
strategy should be implemented in the future.
|
||||
|
||||
There's a functional inclusion ordering on `%fine`, `%meet`,
|
||||
`%mate`, and `%meld` such that if an earlier strategy would have
|
||||
succeeded, then every later strategy will produce the same
|
||||
result. Put another way, every earlier strategy is the same as
|
||||
every later strategy except with a restricted domain.
|
||||
|
||||
A `%meet` merge only succeeds if the changes from the merge base
|
||||
to Alice's head (hereafter, "Alice's changes") are in different
|
||||
files than Bob's changes. In this case, the parents are both
|
||||
Alice's and Bob's heads, and the data is the merge base plus
|
||||
Alice's changed files plus Bob's changed files.
|
||||
|
||||
A `%mate` merge attempts to merge changes to the same file when
|
||||
both Alice and Bob change it. If the merge is clean, we use it;
|
||||
otherwise, we fail. A merge between different types of changes --
|
||||
for example, deleting a file vs changing it -- is always a
|
||||
conflict. If we succeed, the parents are both Alice's and Bob's
|
||||
heads, and the data is the merge base plus Alice's changed files
|
||||
plus Bob's changed files plus the merged files.
|
||||
|
||||
A `%meld` merge will succeed even if there are conflicts. If
|
||||
there are conflicts in a file, then we use the merge base's
|
||||
version of that file, and we produce a set of files with
|
||||
conflicts. The parents are both Alice's and Bob's heads, and the
|
||||
data is the merge base plus Alice's changed files plus Bob's
|
||||
changed files plus the successfully merged files plus the merge
|
||||
base's version of the conflicting files.
|
||||
|
||||
### Metastrategies
|
||||
|
||||
There's also a meta-strategy `%auto`, which is the most common.
|
||||
If no strategy is supplied, then `%auto` is assumed. `%auto`
|
||||
checks to see if Bob's desk exists, and if it doesn't we use a
|
||||
`%init` merge. Otherwise, we progressively try `%fine`,
|
||||
`%meet`, and `%mate` until one succeeds.
|
||||
|
||||
If none succeed, we merge Bob's desk into a scratch desk. Then,
|
||||
we merge Alice's desk into the scratch desk with the `%meld`
|
||||
option to force the merge. For each file in the produced set of
|
||||
conflicting files, we call the `++mash` function for the
|
||||
appropriate mark, which annotates the conflicts if we know how.
|
||||
|
||||
Finally, we display a message to the user informing them of the
|
||||
scratch desk's existence, which files have annotated conflicts,
|
||||
and which files have unannotated conflicts. When the user has
|
||||
resolved the conflicts, they can merge the scratch desk back into
|
||||
Bob's desk. This will be a `%fine` merge since Bob's head is in
|
||||
the ancestry of the scratch desk.
|
||||
|
||||
## Autosync
|
||||
|
||||
Since clay is reactive, it's possible for changes to the
|
||||
filesystem to cause various actions. An important use of this is
|
||||
in enabling "autosync". When a desk is synced to another, any
|
||||
changes to the first desk are automatically applied to the
|
||||
second.
|
||||
|
||||
This isn't simply mirroring, since the local desk might have
|
||||
changes of its own. We use the full merge capabilities of clay
|
||||
to try to make the merge clean. If there are conflicts, it'll
|
||||
notify you and let you resolve them.
|
||||
|
||||
There can be complex sync flows, some of which are useful.
|
||||
Often, many urbits will be synced to some upstream desk that is
|
||||
trusted to provide updates. Sometimes, it's useful to sync two
|
||||
desks to each other, so that changes to one or the other are
|
||||
mirrored.
|
||||
|
||||
The syntax for syncing and unsyncing desks is as follows:
|
||||
|
||||
|sync %to-desk ~from-urbit %from-desk
|
||||
|unsync %to-desk ~from-urbit %from-desk
|
@ -1,95 +0,0 @@
|
||||
`+ticket`
|
||||
===================
|
||||
|
||||
Connecting your planet to moons.
|
||||
|
||||
The Urbit namespace is designed for you to have a planet in the
|
||||
cloud and your other devices (pc, laptop, phone) are moons. Once you
|
||||
have a moon, you can setup 2 way sync of various desks, much like
|
||||
Dropbox or a reactive git. If you `|mount` the desks, you can
|
||||
have synchronization between directories on your moon and planet's
|
||||
systems.
|
||||
|
||||
Creating your moon
|
||||
------------------
|
||||
|
||||
Each planet can issue 2^32 moons. Moon names look like two planet
|
||||
names glued together and always end with the signing planet name. So
|
||||
for the planet `~matfeb-sablud` one could generate a moon `~talsur-
|
||||
todres-matfeb-sablud`.
|
||||
|
||||
### On your planet
|
||||
|
||||
All of your moons will sync from your `%kids` desk. Your planet
|
||||
should come with one by default, but let's check to see:
|
||||
|
||||
```
|
||||
> +ls /=kids=
|
||||
```
|
||||
|
||||
You should get a list of directories. If you just get `~` you can
|
||||
set one up with the following command:
|
||||
|
||||
```
|
||||
>|sync %kids our %base
|
||||
```
|
||||
|
||||
To generate a random moon you can run the following in the `dojo`:
|
||||
|
||||
```
|
||||
+ticket =+(`@p`(cat 5 our (mod eny (pow 2 32))) ~&(- -))
|
||||
```
|
||||
|
||||
The output will print your moon name above the line with the
|
||||
command. It will look something like this:
|
||||
|
||||
```
|
||||
~some-moon-some-planet
|
||||
> +ticket =+(`@p`(cat 5 our (mod eny (pow 2 32))) ~&(- -))
|
||||
~some-ticket
|
||||
```
|
||||
|
||||
You'll use both of these values to create your moon in the next
|
||||
step.
|
||||
|
||||
### On your PC/laptop
|
||||
|
||||
```
|
||||
> bin/urbit -w some-moon-some-planet -t some-ticket
|
||||
```
|
||||
|
||||
Wait for it to boot up and there you have it. You've created your
|
||||
moon which is tied to your planet.
|
||||
|
||||
When you first boot your moon you will have a shell that is connected
|
||||
to your planet. This might or might not be what you want. To get a
|
||||
local shell, type `^d` at the dojo prompt, which should drop you into
|
||||
the task manager. Then type `*dojo` to get a shell connected to your
|
||||
moon.
|
||||
|
||||
Setting up 2-way sync
|
||||
---------------------
|
||||
|
||||
To create a 2 way syncronized desk between your moon and your
|
||||
planet, simply do the following:
|
||||
|
||||
On the moon:
|
||||
|
||||
```
|
||||
> |sync %home ~matfeb-sablud %home
|
||||
> |mount /=home= %home :: So you can see the files from Unix
|
||||
```
|
||||
|
||||
On the planet:
|
||||
|
||||
```
|
||||
> |sync %home ~hobdyl-pontyr-matfeb-sablud %home
|
||||
```
|
||||
|
||||
The initial sync takes a little while, but after that you should be
|
||||
able to create and edit files and have them sync up on the paired
|
||||
system, much like your own personal Dropbox.
|
||||
|
||||
---
|
||||
|
||||
[This guide brought to you by `~matfeb-sablud`]
|
24
pub/docs.mdy
Normal file
24
pub/docs.mdy
Normal file
@ -0,0 +1,24 @@
|
||||
---
|
||||
logo: black
|
||||
anchor: none
|
||||
layout: no-anchor
|
||||
---
|
||||
|
||||
<div class="short">
|
||||
|
||||
# Urbit documentation
|
||||
|
||||
The Urbit doc is divided into three parts: [user doc](docs/user),
|
||||
[developer doc](docs/dev), and [theory](docs/theory) (whitepaper, essays,
|
||||
videos, etc).
|
||||
|
||||
If you want to try Urbit, start with the user doc. If you want
|
||||
to learn about Urbit, try the theory. Or just start with the
|
||||
user doc; it doesn't assume any prior knowledge.
|
||||
|
||||
The most fun thing to do with Urbit is code, but the developer
|
||||
doc remains under construction. Sorry. We'll have more soon.
|
||||
|
||||
<list dataSort="true"></list>
|
||||
|
||||
</div>
|
27
pub/docs/dev.mdy
Normal file
27
pub/docs/dev.mdy
Normal file
@ -0,0 +1,27 @@
|
||||
---
|
||||
logo: black
|
||||
title: Developer doc
|
||||
sort: 2
|
||||
---
|
||||
<div class="short">
|
||||
|
||||
# Developer documentation
|
||||
|
||||
Urbit has three programming layers: Nock (combinator nano-VM),
|
||||
Hoon (strict functional language), and Arvo (functional OS).
|
||||
|
||||
To code in Urbit, the least you need to learn is Hoon, plus a
|
||||
little bit of Arvo. Nock is a sort of functional assembly
|
||||
language -- you don't need to know it, but it's useful to.
|
||||
Nock is also the easiest thing in the world to learn.
|
||||
|
||||
You can program for Arvo without knowing much about Arvo
|
||||
internals, but again it helps. But you need to know Hoon.
|
||||
Don't worry, it's easier than it looks.
|
||||
|
||||
Alas, the developer doc is still under construction. We'll have
|
||||
more soon.
|
||||
|
||||
<list></list>
|
||||
|
||||
</div>
|
14
pub/docs/dev/arvo.mdy
Normal file
14
pub/docs/dev/arvo.mdy
Normal file
@ -0,0 +1,14 @@
|
||||
---
|
||||
logo: black
|
||||
title: Arvo
|
||||
sort: 3
|
||||
---
|
||||
<div class="short">
|
||||
|
||||
# Arvo
|
||||
|
||||
Arvo is a functional operating system.
|
||||
|
||||
Watch this space for actual documentation.
|
||||
|
||||
</div>
|
11
pub/docs/dev/client.mdy
Normal file
11
pub/docs/dev/client.mdy
Normal file
@ -0,0 +1,11 @@
|
||||
---
|
||||
logo: black
|
||||
title: Frontend tools
|
||||
sort: 4
|
||||
hide: true
|
||||
---
|
||||
|
||||
Frontend tools
|
||||
==============
|
||||
|
||||
<list></list>
|
@ -1,8 +1,12 @@
|
||||
# `:tree`
|
||||
|
||||
`:tree` static file hosting internals.
|
||||
`:tree` is the web filesystem interface. Odds are this file has been rendered for you by `:tree`.
|
||||
|
||||
`:tree` is a single-page app that uses a backend in `/home/tree` to load contents from `%clay` as the user navigates around as `%json`. The frontend lives in `/home/pub/tree` and is a fairly straightforward [React](https://facebook.github.io/react/) / [Flux](https://facebook.github.io/flux/) app.
|
||||
`:tree` is a single-page app that uses a backend in `/home/tree` to load
|
||||
contents from `%clay` as the user navigates around as `%json`. The frontend
|
||||
lives in `/home/pub/tree` and is a fairly straightforward
|
||||
[React](https://facebook.github.io/react/) /
|
||||
[Flux](https://facebook.github.io/flux/) app.
|
||||
|
||||
## Frontend
|
||||
|
||||
@ -14,9 +18,14 @@ The CSS is written in [Stylus](https://learnboost.github.io/stylus/). The main e
|
||||
|
||||
### JS
|
||||
|
||||
The JS is written in [CoffeeScript](http://coffeescript.org/) and packaged with [Browserify](http://browserify.org/). The main entry point is `main.coffee` and is compiled with `browserify -t coffeeify main.coffee > main.js`. You'll need to `npm install` first.
|
||||
The JS is written in [CoffeeScript](http://coffeescript.org/) and packaged with
|
||||
[Browserify](http://browserify.org/). The main entry point is `main.coffee` and
|
||||
is compiled with `browserify -t coffeeify main.coffee > main.js`. You'll need
|
||||
to `npm install` first.
|
||||
|
||||
Each page is loaded as JSON and then rendered using React on the page. This allows us to write JSX in our markdown to implement simple components. Check out `/home/pub/tree/src/js/components` to see the component library.
|
||||
Each page is loaded as JSON and then rendered using React on the page. This
|
||||
allows us to write JSX in our markdown to implement simple components. Check
|
||||
out `/home/pub/tree/src/js/components` to see the component library.
|
||||
|
||||
You'll notice that some of these doc pages use things like `<list>` in the raw markdown files.
|
||||
|
213
pub/docs/dev/contributing.mdy
Normal file
213
pub/docs/dev/contributing.mdy
Normal file
@ -0,0 +1,213 @@
|
||||
---
|
||||
title: Contributing
|
||||
sort: 6
|
||||
---
|
||||
|
||||
# Contributing to urbit
|
||||
|
||||
Thank you for your interest in contributing to urbit.
|
||||
|
||||
## Development practice
|
||||
|
||||
You may have an identity on the live network, but doing all your
|
||||
development on the live network would be cumbersome and unnecessary.
|
||||
Standard practice in urbit development is to work on a fake `~zod`. A
|
||||
fake `~zod` will get its initial files from the `urb/zod/` directory
|
||||
rather than trying to sync them over the network, which is invaluable
|
||||
for working in Hoon. Also, a fake `~zod` or any fake urbit instances you
|
||||
start do not talk to the live network, but to a fake network that exists
|
||||
only on your computer.
|
||||
|
||||
To start a fake `~zod`, the command is:
|
||||
|
||||
bin/urbit -F -I zod -c [pier directory]
|
||||
|
||||
To resume one that was already created, just as on the live network,
|
||||
remove `-c` (but leave the rest of the options there). `-F` uses the
|
||||
fake network, and `-I` starts an "imperial" instance - that is, an 8-bit
|
||||
galaxy.
|
||||
|
||||
## Kernel development
|
||||
|
||||
Working on either C or non-kernel Hoon should not bring any surprises,
|
||||
but the Hoon kernel (anything under `urb/zod/arvo/`) is bootstrapped
|
||||
from `urbit.pill` in `urb/`, and must be manually recompiled if any
|
||||
changes are made. The command to manually recompile the kernel and
|
||||
install the new kernel is `|reset` in `dojo`. This rebuilds from the
|
||||
`arvo` directory in the `home` desk in `%clay`. Currently, `|reset`
|
||||
does not reload apps like `dojo` itself, which will still reference the
|
||||
old kernel. To force them to reload, make a trivial edit to their main
|
||||
source file (under the `ape` directory) in `%clay`.
|
||||
|
||||
If you do any kernel development, be sure to read the section below about
|
||||
pills.
|
||||
|
||||
## Git practice
|
||||
|
||||
Since we use the GitHub issue tracker, it is helpful to contribute via a
|
||||
GitHub pull request. If you already know what you are doing, skip down
|
||||
to the Style section.
|
||||
|
||||
Start by cloning the repository on your work machine:
|
||||
|
||||
git clone https://github.com/urbit/urbit
|
||||
|
||||
And, additionally, fork the repository on GitHub by clicking the "Fork"
|
||||
button. Add your fork as a remote:
|
||||
|
||||
git remote add [username] https://github.com/[username]/urbit
|
||||
|
||||
and set it as the default remote to push to:
|
||||
|
||||
git config --local remote.pushDefault [username]
|
||||
|
||||
This is good practice for any project that uses git. You will pull
|
||||
upstream branches from urbit/urbit and push to your personal urbit fork
|
||||
by default.
|
||||
|
||||
Next, check out `test`, which is the mainline development branch, and
|
||||
base a new branch on it to do your work on:
|
||||
|
||||
git checkout test
|
||||
git checkout -b [branch name]
|
||||
|
||||
Now you are free to do your work on this branch. When finished, you may
|
||||
want to clean up your commits:
|
||||
|
||||
git rebase -i test
|
||||
|
||||
Then you can push to your public fork with `git push` and make a pull
|
||||
request via the GitHub UI. Make sure you request to merge your branch
|
||||
into `test`, not `master`.
|
||||
|
||||
After your changes are merged upstream, you can delete your branch (via
|
||||
github UI or `git push :[branch]` remotely, and with `git branch -d`
|
||||
locally).
|
||||
|
||||
## Style
|
||||
|
||||
The urbit project uses two-space indentation and avoids tab characters.
|
||||
In C code, it should not be too difficult to mimic the style of the code
|
||||
around you, which is just fairly standard K&R with braces on every
|
||||
compound statement. One thing to watch out for is top-level sections in
|
||||
source files that are denoted by comments and are actually indented one
|
||||
level.
|
||||
|
||||
Hoon will be a less familiar language to many contributors. Some of our
|
||||
less obvious stylistic rules are:
|
||||
|
||||
- Keep your source files 80 characters or less wide. Many urbit
|
||||
developers use 80 character terminals/tmux panes/&c.
|
||||
- Tab characters are actually a syntax error, so be extra sure your
|
||||
editor is not inserting any. Trailing whitespace is *usually* not a
|
||||
syntax error, but avoiding it is encouraged.
|
||||
- The kernel convention is that line comments start at column 57 with
|
||||
the `::` followed by 2 spaces. This leaves 20 characters for the
|
||||
comment. Outside the kernel, things are less strict.
|
||||
- Tall arms within a core are conventionally separated by empty comments
|
||||
(just `::`) at the same indentation level as the initial `++` or `+-`.
|
||||
The last arm in a core is not followed by an empty comment, because it
|
||||
is visually closed by the `--` that closes the core. The empty comment
|
||||
is also sometimes omitted in data structure definitions.
|
||||
|
||||
## The kernel and pills
|
||||
|
||||
urbit bootstraps itself using a binary blob called `urbit.pill`, which
|
||||
we do indeed keep in version control. This creates some special
|
||||
requirements. If you are not changing anything in the kernel (everything
|
||||
under `urb/zod/arvo/`) then you can skim this section (please do not
|
||||
skip it entirely, though). If you *are* working there, then this
|
||||
section is critically important!
|
||||
|
||||
The procedure for creating `urbit.pill` is often called "soliding". It
|
||||
is somewhat similar to `|reset`, but instead of replacing your running
|
||||
kernel, it writes the compiled kernel to a file. The command to solid
|
||||
is, on a fakezod:
|
||||
|
||||
.urbit/pill +solid
|
||||
|
||||
When the compilation finishes, your `urbit.pill` will be found in the
|
||||
`[pier]/.urb/put/` directory. Copy it into `urb/` and add it to your
|
||||
commit.
|
||||
|
||||
The requirement here is that every commit that changes the kernel must
|
||||
come with an `urbit.pill` built from the same code in `urb/zod/arvo/`
|
||||
for that commit. (Only changing the actual Hoon code counts, so a change
|
||||
to a jet with no corresponding Hoon change does not require a new pill.)
|
||||
This is so that checking out an arbitrary revision and starting up a
|
||||
fakezod actually works as expected. However you do this is fine, but I
|
||||
like to do it as part of my committing process - just before `git
|
||||
commit`, I fire up a new fakezod. This will use the previous
|
||||
`urbit.pill`, but the kernel code in `%clay` will be copied from
|
||||
`urb/zod/arvo/`, so `+solid` will compile it. Then I copy `urbit.pill`
|
||||
into `urb/` and make my commit.
|
||||
|
||||
If you rebase or interactive rebase your commits, be sure to preserve
|
||||
this property on all the commits you end up with. If multiple people
|
||||
were collaborating on your branch, you may end up with conflicts in
|
||||
`urbit.pill` and have to merge the branch into itself to resolve them.
|
||||
Just do the same procedure to create a new, merged pill before
|
||||
committing the merge. Otherwise, just make sure to use the correct
|
||||
`urbit.pill` for each commit.
|
||||
|
||||
## Debug urbit with `gdb`
|
||||
|
||||
Follow the build instructions in README.md but run `make` with argument `DEBUG=yes`:
|
||||
|
||||
(If you've already built urbit first run `make clean`.)
|
||||
|
||||
make DEBUG=yes
|
||||
|
||||
Run `gdb`, while loading `bin/urbit` and its symbol table:
|
||||
|
||||
gdb bin/urbit
|
||||
|
||||
Set a breakpoint on `main()` (optional):
|
||||
|
||||
break main
|
||||
|
||||
Run your urbit comet `mycomet`:
|
||||
|
||||
run mycomet
|
||||
|
||||
Continue from the breakpoint on `main()`:
|
||||
|
||||
continue
|
||||
|
||||
## What to work on
|
||||
|
||||
If you are not thinking of contributing with a specific goal in mind,
|
||||
the GitHub issue tracker is the first place you should look for ideas.
|
||||
Issues are tagged with a priority and a difficulty. A good place to
|
||||
start is on either a low-difficulty issue or a low-priority issue.
|
||||
Higher priority issues are likely to be assigned to someone - if this is
|
||||
the case, then contacting that person to coordinate before starting to
|
||||
work is probably a good idea.
|
||||
|
||||
There is also a "help wanted" tag for things that we are especially
|
||||
eager to have outside contributions on. Check here first!
|
||||
|
||||
## Staying in touch
|
||||
|
||||
The urbit developers communicate on urbit itself. Joining the
|
||||
`~doznec/urbit-meta` channel on `talk` is highly recommended.
|
||||
Subscribing to `urbit-dev` on Google Groups is also recommended, since
|
||||
this is where continuity breach notifications are sent.
|
||||
|
||||
You can also contact one of the following people:
|
||||
|
||||
- Philip Monk
|
||||
|
||||
email: philip.monk@tlon.io
|
||||
|
||||
urbit: `~wictuc-folrex`
|
||||
|
||||
GitHub: [@philipcmonk](https://github.com/philipcmonk/)
|
||||
|
||||
- Raymond Pasco
|
||||
|
||||
email: ray@the.ug
|
||||
|
||||
urbit: `~ramtev-wisbyt`
|
||||
|
||||
GitHub: [@juped](https://github.com/juped/)
|
15
pub/docs/dev/hoon.mdy
Normal file
15
pub/docs/dev/hoon.mdy
Normal file
@ -0,0 +1,15 @@
|
||||
---
|
||||
logo: black
|
||||
title: Hoon
|
||||
sort: 2
|
||||
---
|
||||
|
||||
<div class="short">
|
||||
|
||||
# Hoon
|
||||
|
||||
Hoon is a strict, typed, pure functional language.
|
||||
|
||||
Watch this space for actual documentation.
|
||||
|
||||
</div>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user