Wire up the `radicle-fetch` crate to the fetch logic in the
`radicle-node` worker.
Any required traits for storage, identity, tracking, and transport
used by `radicle-fetch`.
The worker adds a new module to run the `git upload-pack` process and
pipes the `stdout`/`stdin` to the respective channels.
The `Worker` type required adding a `FetchConfig` to easily allow the
configuration of fetches and passing the signer and tracking store
location through to the fetch `Handle`.
The channels code is adapted to have a new writer that always flushes
when a call to `write_all` is made. This is necessary since the
Gitoxide code never calls `flush`, and so it will hang since no data
is sent until `flush` is called.
Since `UserInfo` is used to set up a newly cloned repository, this
changed some of the SHA1 hashes output in the CLI test examples. It
was also necessary to update the CLI's clone code to be deterministic
in its output for tests.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
The `radicle-fetch` crate introduces a method for fetching from a
server using Git protocol V2, which provides the implementation
control over performing a sequence of fetches and validation over
domain data.
The protocol is built on top of the suite of Gitoxide crates[[0]]. It
builds wrappers on top of Gitoxide's refdb, odb, and transport layers
-- as well as taking the ls-refs and fetch code straight from the code
base to simplify for the needs of this crate.
[0]: https://github.com/Byron/gitoxide
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
Introduces a new COB type to store repository identity documents.
The reason for this change is to:
1. Simplify the code, as the identity document logic resembled a COB,
yet it had custom logic. This allows existing COB code to be used for
identities.
2. Make identity document update logic more flexible, since COB actions
can be added in the future.
3. Re-purpose existing tools around COBs to work on identities, eg. `rad
cob`.
4. Unify the concept of an identity change proposal, with regular identity
changes. This means we can remove the `id.proposal` COB in favor of
using the `id` COB itself.
Notes
-----
* Each repository has one Identity COB.
* The `Proposal` COB has been repurposed into the `Identity` COB.
* Identity documents are stored as *embeds* inside the Identity COB
actions.
* The action that contains new document versions is called `revision`,
just like the Patches COB.
* The namespaced `rad/id` ref is a symbolic reference to that Identity
COB.
* The canonical `rad/id` ref is a direct reference to the commit in the
Identity COB that contains the latest *accepted* revision of the
document.
* All commands for managing identities have been folded into `rad id`.
Hence `rad delegate` and `rad edit` are removed.
* The concept of "rebasing" an identity document is gone.
* The `rad id` output has been updated to match the style of other
commands.
* When a revision has enough signatures, it is automatically adopted as
the current identity, there is no longer the need for a "commit"
action.
* When an identity revision is proposed, and the current identity has a
threshold of `1`, that identity is automatically accepted due to the
above point.
* The idea of "verifying a peer's identity branch" no longer applies, as
COBs cannot be verified one history at a time.
* Since the root commit of the Identity COB does not have a "Resource"
to point to (it would have to point to itself, which is impossible),
we've made the resource id optional for COBs.
This commit introduces the `FileStats` struct, that adds the insertions
and deletions for each file to `DiffContent`.
Signed-off-by: Sebastian Martinez <me@sebastinez.dev>
When `EDITOR` or `VISUAL` are not set, we fallback to the most common
editors. It turns out many users don't have these variables set.
We also check if an editor has been configured with `git`.
Add `deny.toml` with a few exceptions, and update certain dependencies
to get rid of duplicates.
Running `cargo deny check` will yield some warnings still, but no
errors.
This change allows for files (blobs) to be embedded into COB entries.
This allows for things like image attachments in issue comments for example.
For now, we only enable this in the `issue` COB.
The way it works is that relevant COB actions carry metadata about which
files are attached to them; and we store those files as blobs inside the
COB entry's *tree* object, under an `embeds/` folder.
The `Embed<T>` type is used for the above, and either carries actual
content, or carries a content-id. Retrieving the actual content is as
simple as asking the repository for a blob with that content-id.
As a possible future extension, MIME types could be stored alongside the
files in a "metadata" file. This could help clients display the content
appropriately.
This improves response time of:
- GET /api/v1/projects/<RID>/tree/<OID>/ from 205.71ms down to 376.4µs
- GET /api/v1/projects/<RID>/tree/<OID>/.nix from 111.06ms down to 351.70µs
Signed-off-by: xphoniex <dj.2dixx@gmail.com>
This commit addresses a workaround previously implemented to
include the SQLite library bundled inside the binary.
The upstream have successfully merged the patch that implements this
solution [1], allowing us to safely incorporate it
into our codebase.
[1] Link to the merged patch: https://github.com/stainless-steel/sqlite/pull/71/files
Fixes: 431a389944
Signed-off-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
Instead of asking for the passphrase in `radicle-node`, we expect the
`RAD_PASSPHRASE` env var to be set.
This keeps `radicle-node` simpler and lower level, while the passphrase
prompt is still available via `rad node start`.
The `cyphernet` package has two feature flags that delegate to
underlying crates. These are:
* ed25519 = cyphergraphy/ed25519
* p2p-ed25519 = cypheraddr/p2p-ed25519
When attempting to install binaries, the compiler will result in an
error:
```
error[E0432]: unresolved import `cyphernet::addr::PeerAddr`
--> radicle/src/node.rs:26:9
|
26 | pub use cyphernet::addr::PeerAddr;
| ^^^^^^^^^^^^^^^^^^^^^^^^^ no `PeerAddr` in the root
```
The `PeerAddr` type is only exported when `p2p-ed25519` or
`cypheraddr/p2p-secp256k1` is enabled. The `radicle` crate was using
the `ed25519` flag. Instead, the `p2p-ed25519` flag should be used.
No explanation as to why the previous flag was working could be found,
but is being discussed on Zulip[[0]].
To update the dependencies, a `cargo update` was also excuted to
update the dependencies.
[0]: https://radicle.zulipchat.com/#narrow/stream/369277-heartwood/topic/cyphernet.20dubious.20feature.20flag
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
Our build was faking the inclusion of SQLite and dynamically
linking it in the 'radicle' crate and other components.
This patch solves the following error and requires reinstallation
of the `radicle-cli`, `radicle-node`, and, if used, the `radicle-httpd`
```
✗ Sync failed: internal error: malformed database schema (node-policies) - near "strict": syntax error (code 11): malformed database schema (node-policies) - near "strict": syntax error (code 11)
```
Tested-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
Signed-off-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
This adds the ability to the git-remote-helper to open and update
patches via a `git push` to the magic ref `refs/patches` and
`refs/heads/patches/<patch-id>`.
The main change is that we had to move away from offering the `connect`
capability in the remote helper, to offering `push` and `fetch`
individually.
To get a feel for how this works, see the `rad-patch-via-push.md`
example.
This change updates to the latest radicle-git-ext, which required a
few changes within the radicle family of crates.
One set of changes is that the radicle-git-ext crate subsumes
git-commit, git-trailers, and git-ref-format -- so all those imports
go through radicle-git-ext.
The commit code requires that parent `Oid`s point to commits, which
made some tests fail. One of the reasons for these failures is that
the patch tests used fabricated `Oid`s and so the verification would
fail. This is fixed by allowing the test context code to create
`PatchRequest`s that create valid commits.
The other reason for failure was that the identity `Action` passed an
`Oid` that pointed to a blob. This is fixed by removing that code and
making a note of it in documentation.
The final major change was moving the Refspec type into git-ref-format
and removing the AsRefspecs trait. The trait was not required and
could its usage could be replaced by simpler code.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
By introducing a small limitation: only allowing entries in the change
graph to be addressable, instead of individual operations; we
drastically simplify the CRDT implementation.
There are four advantages:
1. Op ids are just regular SHA-1s
2. There's no need for relative IDs, ops never refer to other ops within the
same commit
3. There's no need for a nonce, since commits can't collide, and neither can op IDs
4. `OpId` can just be an alias of `EntryId`
The disadvantage of course, is that we have to be mindful of how we
create op transactions, since each transaction creates an addressable
unit. For example, we must not include multiple patch revisions in the
same transaction.
It's fairly easy for a user to (by mistake or intentionally) create two
operations with the same OpId. This patch makes it much less likely,
and ensures that if the OpId is equal, it's because the operations
are identical.
Improvements to the CLI output as well as converging towards
`termion` as a backend.
The crates we were using for prompting and spinners were based on
a terminal backend called `console`, which is not really used
anywhere else. There were also limitations in terms of the output
of these crates.
Therefore, we switched to the `inquire` crate for prompting, using
the `termion` backend, which is very standard.
Additionally, we simplify the terminal output to use symbols:
! for Warning
✓ for Success
✗ for Error
... Instead of a mix of words and symbols.
We also include a modified version of the `yansi` crate which plays
well with our table formatting functions by automatically truncating
and padding output in a unicode-aware way.
The olpc-json crate's CanonicalFormatter does not escape certain
control characters, including new lines. This means that when a COB
gets serialized that includes new lines, those new lines are
serialized verbatim. Upon deserialization `serde_json` -- and any
other JSON deserializer -- will fail due to the encounter of these
control characters.
This behaviour was prevented in radicle-link with the definition of
its own CanoncialFormatter that encodes the control characters
correctly.
Inline this definition of the formatter, under MIT license, to ensure
the correct and remove oplc-cjson.
The behaviour is checked using a multiline test in the issue COB.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
Instead of showing just public keys we need to show the fully qualified
spec for a NID which is prefixed by `did🔑` While we want to maintain
`Author` and `ActorId` for internal use.
Signed-off-by: Sebastian Martinez <me@sebastinez.dev>
Introduces the `rad id` subcommand for interacting with the identity
proposal cob.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
There are few unrelated changes in this commit that I wasn't able to
split out, mostly due to laziness, so I'll list them here:
* The node startup logic is moved out of the main function, and into a
dedicated functionin `client.rs`.
* There is a tentative worker implementation that is untested, and
handles git replication both ways. It's likely lacking in various ways
but I wanted to get it in there anyway.
* `Address` was moved from `radicle-node` to `radicle`, because it's
needed to send `Connect` commands from the node handle.
* The `netservices` dependency was updated.
* Finally, there is a first end-to-end node test, which currently
doesn't use NoiseXK, but uses the new reactor in `netservices`.
Signed-off-by: Alexis Sellier <self@cloudhead.io>
We're using petgraph to encode an operation based CRDT (each graph node
is an operation) as a DAG, and one of the important things to ensure
is that the final state is not influenced by the order of concurrent
operations. In this case a concurrent operation would mean two potential
graph traversal orders, as there's no direct edge between the two
concurrent ops. This is essential a "partial order" of operations.
To be able to test this, we'd want some kind of control over how
neighbors are iterated over I guess, when there's more than one possible
sort order. Say we have a graph like this:
┌────────b◄─────┐
▼ │
a d
▲ │
└────────c◄─────┘
There are two possible topological traverse orders: [a, b, c, d] and [a,
c, b, d]. Having a way to go through these different orders would
be super handy.
One option would be to allow random order traversal. This would allow us
to test all orders by running the test enough times to likely test all
permutations.
Since petgraph doesn't support this, we implement our own simple DAG in
`radicle-dag`, which implements random-order topological orders.
For now, we don't make explicit use of these improvements, we simply
replace the underlying graph with our own.
This is a large change that introduces transport encryption via
a Noise_XK handshake. The inner `Service` now works directly
with `NodeId` and doesn't need to interact with socket addresses.
The transport logic takes place in `wire::transport`, and the
established sessions are passed down to `Service`.
Note that the i/o implementation in the `poll-reactor` crate still
needs testing, and there is still work to be done to integrate the
Git transport as part of this architecture.
Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
Sometimes it is more efficient to perform multiple operations at once
and store those in the collaborative object graph together.
Change the contents to be a non-empty sequence of byte sequences,
i.e. NonEmpty<Vec<u8>>. These are stored as blobs in a git tree in
order by their index in the non-empty sequence. They are, in turn,
retrieved in order of their original index.
Change the conversion of an `EntryWithClock` to return a non-empty
sequence of `Op`s, which are in turn used to apply many changes in
each `from_history` implementation.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
This will allow us to run commands other than `rad`
and to have tests that switch between different users.
Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
The latter is a fork of the former, which adds const generics
and a bunch of other quality of life improvements that aren't
in the original crate due to it being unmaintained.
Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
This was causing an issue in rust-analyzer, and probably would fail
in other ways via cargo. In any case it wasn't a good idea.
Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
I'm not entirely satisfied with `trycmd`, but it's a start.
If we choose to move to a different crate, or implement our own,
we can keep the example test cases.
Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
Add quickcheck tests for parse_refstr to ensure the correct
behaviour.
This required adding Arbitrary instances for TypeName and ObjectId, as
well as adding a mechanism for generating Invalid ObjectIds.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
To wire up radicle-cob, it is necessary to implement the traits for
the following types:
* `Repository`: `change::Storage`, `object::Storage`, and `Store`
* `project::Identity`: `identity::Identity`
For `Repository`, the `change::Storage` implementation is trivial, as
it uses the underlying `git2::Repository` implementation. Then
`object::Storage` simply defines the required references names and
does lookups or updates.
The aforementioned reference naming scheme is:
refs/namespaces/<ns>/refs/cobs/<typename>/<object_id>
For `project::Identity`, the `identity::Identity` implementation is
straight-forward.
To finalise the work, a simplified API is exposed as `radicle::cob`
where the `create`, `update`, `get`, and `list` functions are
redefined in terms of `radicle` specific types.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
This is a minimal port of the collaborative objects code from
radicle-link[0].
A `CollaborativeObject` is made up of a `History` of `Change`s that
are expected to be stored in a `git` backend.
The library exposes a CRU series of functions `create`, `get`, `list`,
and `update`.
This implementation differs, to previous one, in that it does not
assume any kind of identity system -- its only assumption is that
identities have an identifier and can be addressed in the `git`
database. This means that it does not require an `author` to be passed
in and it only uses the `resource` (previously `authorizing_identity`)
to store its content-address in the `Change`.
It also foregoes any caching to simplify the port and not make any
early optimisation assumptions.
[0]: https://github.com/radicle-dev/radicle-link/tree/master/cob
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
We implement a small proof-of-work on the node announcement message
to prevent the routing table from being filled by fake entries.
Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
The crypto types are useful to use in other components that are
separate from the radicle crate, e.g. the incoming radicle-cobs
crate.
Separate out the types into a radicle-crypto crate. This crate defines
the usual PublicKey, SecretKey, and Signature types. It also provides
the ssh functionality, under the `ssh` feature. It is also necessary
to provide the `From` impl for `Component` here, which again is
guarded by the `git-ref-format` feature.
The `Arbitrary` implementation are moved. The arbitrary decision of
redefining `ByteArray` in both radicle-crypto and radicle was made.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
Introduces a new `radicle-httpd` crate which will serve as the basis
for heartwood's HTTP backend.
The first part of this is a git server which allows projects to be
fetched from storage using plain `git`.
Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
The `git-ref-format`[0] and `radicle-git-ext`[1] crates are now
published to crates.io.
Switch the dependency to rely on them. This also required to update
the `git2` dependency to `0.15.0` as well as using the
`vendored-libgit2` feature -- avoiding the openssl dependency too.
[0]: https://crates.io/crates/git-ref-format
[1]: https://crates.io/crates/radicle-git-ext
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
The previous iteration of the storage layout for projects organised
peer's subtrees by the `refs/remotes` category. This layout leads to
problems when linking a working copy to the storage project. The fetch
refspec would look something like:
fetch = +refs/remotes/abc/heads/*:refs/remotes/rad/*
This works perfectly fine when running:
git fetch rad
but will fail when one tries to specify:
git fetch rad main
Instead, the command would need to be:
git fetch remotes/abc/heads/main
This patch proposes to move the use of `refs/namespaces` for each
peer. The layout looks similar in that each peer has a subtree, but
instead it is under `refs/namespaces/<peer>/refs/...`.
The previous refspec would look more familiar in its new form:
fetch = +refs/heads/*:refs/remotes/rad/*
With this in place running:
git --namespace=abc rad main
Will work as expected and place the reference under
`refs/remotes/rad/main`. Similary, `git --namespace=abc push` will
work as expected.
Another benefit of this approach is that the use of namespacing means
that a tag is pushed it will be placed under the respective namespace
rather than in the global `refs/tags` category.
The actual implementation needed to work around the fact that
`git2`/`libgit2` does not have any options for fetching or pushing
using namespaces. The working copy code uses processes to shell out to
`git` for namespacing needs.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>