The Canonical type is generally constructed with the threshold, needed
for the quorum computation, in scope. To make it easier to use and
encapsulate its functionality, it now holds the threshold as an
additional field.
Relax the set of radicle-git depedencies to allow for patches. In
particular, the dependencies introduced some small improvements with
`0.*.1` updates.
All dependencies that are dependencies of multiple crates within the
workspace were pulled up to the root `Cargo.toml`. Dependencies that are
dependencies of just one crate within the workspace remain in the
`*/Cargo.toml` of that particular crate.
Generally, this helps us keep an overview of dependencies:
- If multiple crates depend on a crate, we will see the reference to
the workspce.
- Otherwise, we will see a line that specifies the version.
It is up to the maintainers to recognize when a dependency becomes a
dependency of multiple crates in the workspace, at which point it should
be moved to the workspace.
The tool `cargo-autoinherit` can be used to automatically pull *ALL*
dependencies to the workspace. I used this, and in a separate, manual
step, filtered out those dependencies that are dependencies of a single
crate only, moving those back manually.
At the same time, I also unified depending on sibling crates in the
workspace. This is now also done via workspace dependencies.
See:
- https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#inheriting-a-dependency-from-a-workspace
- https://github.com/mainmatter/cargo-autoinherit
Without this, rad clone fails with:
Error: checkout: git: failed to initialize repository with template 'hooks/README.sample': Permission denied; class=Os (2)
Extracting JSON Schemas from the Radicle crate can be done via
`radicle-cli` for `radicle::profile::Config` by executing:
rad config schema
However, for other JSON Schema metadata, this is not possible.
To allow other tools to extract JSON schemas as part of their build
process, introduce a new crate that only depends on `radicle`,
`schemars`, and `serde`, with a tiny binary that will reproduce various
schemas.
JSON Schema extraction via `schemars` is provided for configurations.
There are other interfaces that use JSON for (de-)serialization, such as
the communication with `radicle-node` via the control socket.
To ease implementation of tools that want to communicate via the control
socket, we add the respective `schemars` annotations.
The `schemars` crate is a dependency of multiple workspace crates in the
same version. Its version number is repeated multiple times in the
respective `*/Cargo.toml` files. This requires more maintenance effort
and risks versions drifting.
As long as all crates depend on the same version, it makes more sense to
have `schemars` as a workspace dependency.
See: <https://doc.rust-lang.org/cargo/reference/workspaces.html#the-dependencies-table>
The script would include the quotes and so running `build/build` would
result in:
$ build/build
Running build..
✓ Radicle key already in ssh-agent
Building Radicle 1.2.0..
Creating archive of repository at e9cf91… in build/heartwood-e9cf91….tar.gz..
Building image (radicle-build-1.2.0)..
[1/2] STEP 1/17: FROM rust:"1.85"-alpine3.20 AS builder
Error: creating build container: parsing reference "rust:\"1.85\"-alpine3.20": invalid reference format
Co-authored-by: Lorenz Leutgeb <lorenz.leutgeb@radicle.xyz>
This prepares the crate versions for a new release. The version bumps were
determined by the `cargo-semver-checks` tool.
However, there were some issues with the `radicle-fetch` crate – where when
attempting to check it, it was unable to compile due to the previous version
expecting the kind of `Doc` with a generic parameter. I believe this is due to
the version for `radicle` being specified as simply `0`. This prompted changing
the version specifications to use `major.minor` for all the internal crates.
This, for example, would mean that `radicle-fetch` that relies on `0.15` can use
`>=0.15.0,<0.16.0` – allowing any patch versions but must require a minor
version bump.
Do not assume the `rad` remote being present, in case other use other naming
remote schemes. Instead, build the remote using the `rad .` and `rad self --nid`
commands.
The symlinking process of `build/upload` was not working, due to the command
consuming stdin, and ignoring the subsequent targets platforms. Use `-n` to
prevent this, allowing every target binary to be uploaded correctly.
The output is also improved for better feedback during the upload process.
Instead of hardcoding the version of the Rust alpine file, introduce an `ARG` in
the `Dockerfile`. In `build/build`, we determine the version by inspecting
`rust-toolchain.toml`, and pass this value in. This ensures that the binaries
are built using the same toolchain that we develop with.
We ensure that the message of total synced seeds changes when we go over the
replication factor target. This can happen if the node is still waiting to
announce to a preferred seed, and other results are still being returned.
Similar to the `Fetcher` sans-IO approach, an `Announcer` sans-IO approach is
introduced. The previous `Handler::announce` was already quite close to using a
sans-IO approach, but using internally held state. This change makes the
business logic more reusable – and testable.
Similarly to the `Fetcher`, the `Announcer` is configured and then driven by
telling it when nodes have been synchronized with. It will continuously check if
it has reached its target, yielding to the caller to decide whether to keep
going. In contrast, it also provides a way to mark the process as timed out,
since announcing relies on waiting for events to come back in a timely manner.
This change improves the `rad clone` command in a few different ways.
The first improvement is to check if the repository already exists before
fetching. If it does exist, then there is no need for the fetch to be performed,
and can move straight to the checkout.
If the repository does not exist, then the fetch is performed, as per usual.
However, it uses a replication factor of 1, so that the fetch finishes as soon
as it has the repository in local storage.
The change also improves the output when failures occur while attempting to
perform the checkout phase. It will print the failure that occurred and provide
a hint message in each case to help debug the failure, or push the caller in the
direction of performing the correct action.
This required some changes in `test/commands.rs` setup. Some tests were using
the `rad-clone.md` to setup a clone, which would have different output if the
repository did not need to be fetched. In those cases, the `rad` method for
performing the clone is used instead.
Commit b608a788 (cli: `rad config schema` emits JSON Schema, 2025-04-28)
added a feature flag that enables the "schemars" optional dependency.
Crate radicle-node doesn't use this feature.
Crate radicle fails to compile when the feature is disabled.
This is reproducible with "flake check".
Fix it.
Note that a "cargo build" of the entire workspace doesn't fail, because the
feature is enabled due to "unification", since "radicle-cli" does use this
feature. From https://doc.rust-lang.org/cargo/reference/resolver.html#features:
> When building multiple packages in a workspace (such as with --workspace
> or multiple -p flags), the features [of the dependencies] of all of those
> packages are unified. If you have a circumstance where you want to avoid
> that unification for different workspace members, you will need to build
> them via separate cargo invocations.
Reword the help message of `--replicas` and `--max-replicas`, while also
improving the documentation on how the fetch and announce functionality works.
This patch changes separates the business logic of fetching from the process of
fetching itself. It does this through a sans-IO approach, where a `Fetcher`
provides the necessary state to help drive a fetch forward, without performing
any of the IO itself.
What the `Fetcher` cares about is:
- What nodes are going to be attempted to be fetched from
- In what order should they be attempted
- When should the fetching process be considered finished
The `Fetcher` is then used in `radicle-cli` to drive forward the `sync::fetch`
function, allowing it to only care about the IO.
Leverage `schemars` to generate a JSON Schema from our structs for
configurations and those occurring within them.
The output of `rad config schema` can be used by editors to provide a
smoother editing experience for the configuration file. Discovery
attributes (both keys and values) is greatly improved with the schema
helping in the background.
Refer to:
- https://json-schema.org
- https://code.visualstudio.com/docs/languages/json#_json-schemas-and-settings
- https://schemastore.org
- Print link direction.
- Shorten NIDs.
- Use single chars to indicate status, legend is provided via hint.
On nodes with only outgoing connections, link direction won't be very
interesting. But on seed nodes it sometimes *is* of interest in which
direction the connections are going.
Also, I hope that in the future we will enable more and more nodes to
connect directly to each other.
The table header "Dir." is an abbreviation for "Link Direction".
This change is to help separate the fact the namespacing by a `NodeId` is a
Radicle specific concern. The identifier can, in theory, be any kind of path
component, as long it is valid in Git.
The motivation for the change is to help separate the idea of a device's
`NodeId` vs an agent being an author – for future agent repository work.
The motivation of this change is to move away from tying signing to be
specifically for ed25519. The reason being that the protocol will want move
towards two different kinds of signing – the node signing artifacts, and an
author signing artifacts.
This change captures the former, node signing, by introducing a `Device` type
that is the `NodeId` – a PublicKey underneath the hood – and a signing
mechanism. This allows the replacement of the `Signer` trait being used – which
always assumed a `PublicKey`. Instead, the `Device` is constructed with
`NodeId`.
In `radicle-cob`, a signer is expected to implement
`signature::Signer<ExtendedSignature>`, and everywhere in `radicle`,
`radicle-node`, `radicle-cli`, and `radicle-remote-helper` is expected the
signer is expected to implement `signature::Signer<Signature>`.
A `Device` implements both of these but only requires
`signature::Signer<Signature>` to do so – since an `ExtendedSignature` is
essentially `(PublicKey, Signature)`, and the `NodeId` of the `Device` can be
used.
This declares the minimum supported Rust version, independently of the
`rust-toolchain.toml` file, which specifies the Rust version and
toolchain components the crate/workspace should be built with. The
MSRV affects other crates that depend on anything in this workspace,
but the toolchain file does not seem to affect them. This means the
MSRV is useful for those who build or develop dependents.
Signed-off-by: Lars Wirzenius <liw@liw.fi>
Debian policy is to install to /usr/bin, not /bin, so do that. This
silences a lintian warning without using an override.
Also fix removal of .crates*.toml files that cargo install creates.
Signed-off-by: Lars Wirzenius <liw@liw.fi>