Commit Graph

2242 Commits

Author SHA1 Message Date
Fintan Halpenny aa7dcd92db radicle: use a struct to help announce success counts
It is easy to mix up the order of a tuple, so a struct is introduced instead to
ensure that the correct counts are used.
2025-05-30 09:42:08 +02:00
Fintan Halpenny 5a0c14cf61 radicle: ensure preferred seeds are announced to
Ensure that the preferred seeds that are not in the synced set are announced to.
2025-05-30 09:40:50 +02:00
Fintan Halpenny c57d43f2f5 radicle: schemars test should be behind feature flag
A `#[cfg(feature = "schemars")]` was missed in the `profile/config.rs` module
since it was part of the test module.
2025-05-30 09:26:31 +02:00
Fintan Halpenny 5b4cbc2cd8 radicle: introduce announcer
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.
2025-05-26 12:31:03 +02:00
Fintan Halpenny fa9c6cd142 radicle: move PrivateNetwork to `node::sync`
This construction can be used more generally, for example in announcements, so
it is moved one level up.
2025-05-26 12:31:03 +02:00
Fintan Halpenny cc96b9ed7d cli: improve rad clone
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.
2025-05-26 11:56:56 +02:00
Johannes Altmanninger 059c804588 radicle: fix build when schemars feature is not enabled
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.
2025-05-24 22:39:38 +02:00
Lorenz Leutgeb 1a67ac18f3 cli: reword sync replicas help
Reword the help message of `--replicas` and `--max-replicas`, while also
improving the documentation on how the fetch and announce functionality works.
2025-05-23 17:22:48 +01:00
Fintan Halpenny eec4dd4505 radicle: improve sync fetching
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.
2025-05-23 17:22:48 +01:00
Fintan Halpenny c205322c56 node: fix e2e reader limit test
Either error can show up it, according to our wumpus hunter[^0]. Check for both
reasons.

[^0]: https://wumpus.liw.fi/log-f30760d6bb86d2978a5ed4df8ee45b9aa97778b4/log-2025-05-02T03:42:38Z.1885.fail.html
2025-05-22 11:02:34 +02:00
n4ch7 b608a78806 cli: `rad config schema` emits JSON Schema
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
2025-05-22 11:00:46 +02:00
Lorenz Leutgeb 5a2f26eaa7 cli/node/status: Redesign
- 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".
2025-05-22 10:45:32 +02:00
Lorenz Leutgeb ee12f76cbe cli/tests: Fix nextest running via Nix 2025-05-22 10:25:59 +02:00
Fintan Halpenny 9988b63bb2 cob: abstract namespace identifier
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.
2025-05-22 09:09:57 +02:00
Fintan Halpenny 1f4fcc5e6a radicle: move to `signature` crate
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.
2025-05-22 09:09:57 +02:00
Lorenz Leutgeb 41f9048d96 nix: Add flake check that builds at MSRV 2025-05-16 13:49:38 +02:00
Lars Wirzenius 105b65c2ac workspace: set rust-version (MSRV)
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>
2025-05-16 13:49:38 +02:00
Fintan Halpenny 9f2c4e3941 chore: use watch_file in .envrc 2025-05-15 14:54:13 +02:00
Lars Wirzenius 5a0a334ddd build(debian/rules): install into a location where Debian expects
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>
2025-05-12 17:14:50 +03:00
Lorenz Leutgeb e0d18b8656 systemd: Add example configuration for DNS-SD 2025-05-12 10:03:47 +01:00
Lorenz Leutgeb 98cf054b2c git: Add .direnv to .gitignore 2025-05-12 09:59:11 +02:00
Fintan Halpenny f5fa84fac6 test: set name and email for repository fixture
In fresh environments, without a global git config, the `user.name` and
`user.email` will not be set for the fixture repository. This causes issues when
tests are run and attempt to call `git2::Signature::now` – it will fail to read
a user name and email for the commit.

To remedy this, the name and email are set for the repository when initialising
it.
2025-05-09 10:30:44 +01:00
Lorenz Leutgeb 59a1021410 hook: Make `cargo check` and `cargo clippy` only execute pre-push
These hook take relatively long on my machine, and my impatience has
lead to me doing `git commit --no-verify`, which defeats the purpose of
having these hooks.

Note that others (like `alejandra`, `cargo fmt` and `shellcheck`) are
reasonably fast and will keep doing good.
2025-05-07 13:56:55 +01:00
Lorenz Leutgeb 5553a14752 cli/tests: Relax expectations in `rad-clone-partial-fail.md`
This test often fails on my machine(s) because it prints a different
error message, not "connection reset". I think it is fair to relax this
a little.
2025-04-29 20:37:56 +02:00
Lorenz Leutgeb f30760d6bb
cob: Add CobAction::produces_identifier and validation
Transactions will now fail/deny when adding multiple actions that
produce an identifier.
2025-04-28 16:19:02 +02:00
Lorenz Leutgeb e4d23fe56a
cli: Introduce `cob [create|update]` 2025-04-28 16:19:02 +02:00
Lorenz Leutgeb 547614a5bb
cli-test: Add current working directory to PATH 2025-04-28 16:19:02 +02:00
Sekhat Temporus 3018223328
cli: Allow multiple RIDs for `rad unseed`
To keep expectations similar to the seed command after the changes in
the companion patch:

rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5/patch/3be0e68b8948e65431a288f225454bafd93de34a
2025-04-26 10:01:11 +02:00
Sekhat Temporus 6bbe919c4b
cli: allow multiple RIDs for `rad seed`
Closes rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5/issue/f9ec8a2
2025-04-26 09:45:39 +02:00
Fintan Halpenny a90aabb1fe node: rate limiter for channel reads
This introduces rate limits for the `ChannelReader` to limit DDoS attacks and
attempts to upload repositories that are larger than a node is will to permit.

The limiter sets the total number of bytes it is will to accept in a single
exchange, defaulting to 500MB. This means that initial fetches will prevent
large repositories, but is plenty for new packfile data to be sent in subsequent
fetch exchanges.

The limit can be configured within the node's config file, under the limits.
2025-04-25 20:27:51 +02:00
Lorenz Leutgeb f13afe491d remote-helper: Print `git range-diff` invocation 2025-04-24 16:51:38 +02:00
Fintan Halpenny 6dcd56275e
node: upload-pack inter-thread communication
If an upload-pack is of a considerable size, the writer thread will be busy
writing bytes to the receiving side. During this period, the receiving side will
not be sending any bytes.

To ensure that the reader does not exit while the writing thread is performing
writes, the reading side will check when the last time a write was performed. If
it has not reached the timeout, then it can continue attempting to read.
Otherwise, it will break out of the loop; killing the upload-pack process safely.
2025-04-23 16:25:17 +02:00
Fintan Halpenny ce8ac663f7
radicle: use `git fetch` over libigt2 in checkout
Similarly to pushing using the `file://` protocol and `libgit2`, fetching will
be slow – so instead use `git fetch` directly to perform the `checkout`.
2025-04-23 16:21:51 +02:00
Lars Wirzenius a9fa31e5e6 docs: add links to to README.md to home page and Zulip
This makes it more obvious how to find more information about the
project and how to talk to the project.

Signed-off-by: Lars Wirzenius <liw@liw.fi>
2025-04-23 11:22:48 +02:00
Lorenz Leutgeb cbca3af260
chore: shellcheck fixes 2025-04-22 15:43:02 +02:00
Lorenz Leutgeb ce07e92a2e
Add Git pre-commit hooks via Nix 2025-04-22 15:43:02 +02:00
Lorenz Leutgeb 77386b0fce build: Upload Git archive of heartwood 2025-04-22 11:46:01 +02:00
Richard Levitte 10daedf96d cli: Add 'rad node inventory --nid <nid>'
This gives the possibility to see the inventory of another node than self.
This does replicatee the functionality of 'rad node routing --nid', but
feels like a more intuitive command to try.
2025-04-22 11:41:30 +02:00
Fintan Halpenny 8fd044833e
radicle: use `git push` to avoid `libgit2` push
In issue #[2836] of `libgit2`, the speed of `libgit2`'s `file://` protocol for
git operations is found to be very slow. This is further corrobarated by `rad
init` taking 13 hours to initialise the hardenedbsd [ports] repository.

There are two areas where the `heartwood` project uses `libgit2` to push using
the file protocol. The first is when via the `trasnport::local` smart transport
registration and the second is the final push to storage in the `git-remote-rad`
binary.

When both these `push` operations are changed to use the `git` binary instead,
the [ports] repository can be initialised in less than 10 minutes (nearly 100x
speed up).

This change is clearly required if `heartwood` wishes to support larger
repositories.

[2836]: https://github.com/libgit2/libgit2/issues/2836
[ports]: https://git.hardenedbsd.org/hardenedbsd/ports
2025-04-17 15:12:12 +02:00
Lorenz Leutgeb 433483e07a Add Lorenz Leutgeb to `.gitsigners` 2025-04-17 14:33:36 +02:00
Lorenz Leutgeb dc1ff882c5
cli/sync: Also print node addresses 2025-04-17 14:20:21 +02:00
Sebastian Thiel 72913b8c15
fetch: integrate the latest `gix-protocol` into `radicle-fetch`
Signed-off-by: Sebastian Thiel <sebastian.thiel@icloud.com>
2025-04-17 14:09:22 +02:00
Fintan Halpenny 96637aca7e
chore: update rust-toolchain
Update the rust toolchain version to 1.85.

Note that this is not the latest, however, it is the latest available in nixpgs,
so this version is good enough for now.
2025-04-17 10:39:34 +02:00
Derick Eddington 47c785b916
signals: Use `signals_receipts` crate instead
This resolves issues:
- 111cf90 (`handler` is not async-signal-safe)
- c8e0300 (`libc::signal` should not be used)
- b91c6c3 (Mutex can cause signals to be missed)

See also: patch 8e05702.

The API of `radicle-signals` is the same as before, and so uses of it
don't need to be and aren't changed.  The behavior is slightly different
in that:

- If the channel is full then signals will not be lost, which is an
  improvement.  This is achieved without blocking in the signal handler.
  This is possible because of the counters approach along with the
  internal receipts-processing thread of the `signals_receipts` crate.

- `install()` and `uninstall()` might block very briefly if necessary to
  acquire the mutex, which is now internal to and managed by the
  `signals_receipts` crate, only if there are concurrent calls to them
  (which is unlikely), but such blocking is guaranteed to be bounded to
  be very brief.  This is done so they no longer can fail to do their
  purpose, which is an improvement.  They still return errors if the
  handling is already installed or uninstalled, respectively, which
  preserves the previous use cases.

- The new `finish()` function is introduced.  This is provided in case
  it's ever needed to completely clean-up the facility, by terminating
  the internal receipts-processing thread, to be like it hadn't been
  installed before.

- The user must ensure that the notifications channel is disconnected,
  by dropping the receiver(s), when doing `uninstall()` or `finish()`.
  Such dropping usually occurs naturally, and already occurs for all the
  preexisting uses of `radicle_signals`.  (The `signals_receipts` crate
  is capable of a more robust approach, but this commit doesn't use
  that, to avoid changing the preexisting uses of `radicle_signals`.)

- The `TryFrom` impl for `Signal` is of `SignalNumber` which is `c_int`,
  instead of `i32`, because `c_int` (the type of signal numbers) might
  not be `i32` on all platforms (POSIX only requires `c_int` to be at
  least 32-bit).

The version of `radicle_signals` is incremented, to reflect those
changes and the substantially different internal implementation.

The new dependency on the `base64` crate is needed by the
`signals_receipts` crate for it to work on macOS, because its dependency
on the `sem_safe` crate uses `base64` as part of creating anonymous
semaphores on macOS (which lacks support for unnamed semaphores (in
violation of POSIX)).

Signed-off-by: Derick Eddington <kcired@pm.me>
Signed-off-by: Lorenz Leutgeb <lorenz@leutgeb.xyz>
2025-04-16 20:09:44 +02:00
tippfehlr c05434ebd5 cli: add emoji picker to `rad issue react`
The help shows that `--emoji` is optional, however it was not.
Instead of making `--emoji` mandatory, I added an emoji picker
for the emojis featured in the web ui.

`--emoji` is now (really) optional, but can be used to react
with other emojis not included in the selector or the web ui.
2025-04-16 17:12:06 +02:00
Fintan Halpenny 2af090ea1e cli: fallible comment selector
The usage of the `comment_select` used `unwrap`. It would be better to have the
function be fallible instead and provide a somewhat helpful message.
2025-04-16 16:02:58 +02:00
Lars Wirzenius 7eb07e1b4d chore(debian/changelog): update package version to match upstream
Signed-off-by: Lars Wirzenius <liw@liw.fi>
2025-04-16 12:26:31 +03:00
Lars Wirzenius 13ba2ef0ff fix(debian/rules): cargo install offline
We don't have network access under Ambient, so we need to run "cargo
install" with the "--offline" option to prevent it from trying to
check current available versions of crates.

Signed-off-by: Lars Wirzenius <liw@liw.fi>
2025-04-16 12:25:51 +03:00
Lars Wirzenius ebc8d037d9 ci(.radicle/ambient.yaml): CI plan for Radicle CI Ambient adapter
With this file, Radicle CI can use the Ambient adapter to run CI on
patches.

Signed-off-by: Lars Wirzenius <liw@liw.fi>
2025-04-16 12:25:51 +03:00
Richard Levitte 9abedf449b
cli: Don't use 'signer' where not necessary
In the 'clone' command, a 'signer' is instanciated just to get the
public key.  In the 'job' command, a 'signer' is instanciated early,
even when the subcommand doesn't use it.

That's unnecessary, and infers the potential use of RAD_PASSPHRASE.
In those cases, avoid instanciating a 'signer'.
2025-04-15 12:42:35 +02:00