Commit Graph

2668 Commits

Author SHA1 Message Date
Fintan Halpenny 02318f199c radicle: Re-export `radicle_core::RepoId` 2026-01-09 14:04:18 +01:00
Fintan Halpenny 73827f5362 radicle: Re-export `radicle_core::NodeId` 2026-01-09 14:04:04 +01:00
Fintan Halpenny 7c016f9219 core: Introduce NodeId
A type for node IDs, which are Ed25519 public keys, is added to the
`radicle-core` crate.
2026-01-09 14:03:32 +01:00
Fintan Halpenny d5fea6324c core: Introduce RepoId
Introduce the `radicle-core` crate for housing data types that are at
the core of the Radicle protocol. The initial data type being added is
`RepoId`. To make the crate as lightweight as possible many of
dependencies are optional and gated by feature flags.
The crate is marked as `no_std` even though it unconditionally depends
on `radicle-crypto`, which is *not* `no_std`. This is to invite
refactoring of `radicle-crypto` to `no_std` at a later time.
2026-01-09 14:03:27 +01:00
Lorenz Leutgeb af3f07627b
chore: Update thiserror from 1 to 2
The section on breaking changes in the release notes at

    https://github.com/dtolnay/thiserror/releases/tag/2.0.0

look relatively tame. We gain support for `no_std`.
2026-01-09 10:47:23 +01:00
Fintan Halpenny d98033a1ff localtime: localise the localtime dependency
The `localtime` crate was defined by cloudhead, and is a minimal
repository with a single `lib.rs`.

Instead of using it as an external dependency, copy the code directly
into a new workspace crate `radicle-localtime`.

The default `serde` implementation goes through the `LocalTime`'s
seconds values rather than milliseconds, since this is the more common
format. This allows the removal of the `serde_ext` functions.
The one place milliseconds was used was for the
`radicle::cob::common::Timestamp` type, where the `Serialize` and
`Deserialize` implementations are manually written.

It also adds a `schemars` feature to remove `schemars_ext` functions
in `radicle` as well.
2026-01-08 14:58:41 +01:00
Fintan Halpenny 3168107df9 fetch: surface underlying I/O error
The message that is returned by `gix-transport` for I/O errors can be
unhelpful, since it does not provide the reason for what happened.

Instead, surface the error so that it provides more detail for logging.
2026-01-05 18:29:52 +01:00
Fintan Halpenny 75b665ff3a node/wire: manage logs for error establishing connection
Instead of logging all IO errors as an error, match on the kind of the
error, logging an info message, otherwise an error.

These errors are informational, and cannot necessarily be resolved by
the node operator – since it is a matter of not being able to connect
to another end.
2026-01-05 17:57:34 +01:00
Fintan Halpenny 47dc2c562c protocol/service: defensive storage.contains check
In the case of the `storage.contains` call returning an error, it
would be preferable to log the error and continue checking for missing
repositories.
2026-01-05 17:51:43 +01:00
Fintan Halpenny a46f8eb1d5 node: use `outbound.get` over `outbound.get_mut`
The following block did not need mutable access to the `outbound`
value.

To avoid confusion around mutable access, the call was downgraded to
`get` so that the reader can safely know there is no mutation
happening.
2026-01-05 17:45:54 +01:00
Fintan Halpenny b8a6e1a52f radicle/cob/stream: skip commits that do not have a manifest
For some COBs, parent commits can be specified for actions, for
example, patches will bundle their base and head commits as parents.

When the COB stream performs the revwalk, these commits will be
included, and will not have the manifest file – resulting in an error.

Instead, this error can be matched against, and the commit is skipped
instead. The other errors should still be resurfaced, since a commit
with a manifest should be expected to load the operation correctly,
and the commit should exist in the repository when attempting to load
it.

One might argue that a valid operation with a missing manifest could
occur, but that would mean that `radicle-cob` has performed an invalid
write. This is undetectable by the stream API, and is ambiguous with
the case of non-Op commits.
2025-12-28 14:01:01 +00:00
Defelo cf023f750d
cob: allow hyphens in `TypeName`
Also make sure to only allow ASCII characters and add some tests.
2025-12-15 14:30:27 +01:00
Fintan Halpenny 352c29c23c cargo(deny): allow Zlib
The Zlib license is included in the transitive dependencies.
It is safe to allow it since it is compatible with MIT and Apache-2.0.
2025-12-08 16:43:50 +00:00
Fintan Halpenny a66d44ebe2 workspace: update git-ref-format-core and radicle-surf
Update the above crates to their latest version, which now use MIT OR Apache-2.0 licensing.

This allows us to remove the exception entries in `deny.toml`.
2025-12-08 16:43:20 +00:00
Lorenz Leutgeb 4a5a51e6e5
node: Do not mix monotonic and system time
The `struct Epoch` introduced in e404f1038f
inadvertently made `radicle-node` suffer from
https://github.com/rust-lang/rust/issues/87906

That is, updating of the "current time" was skewed *way more*
than expected by a slowly ticking monotonic clock. Such slow
ticking can be caused by suspending the system.
2025-12-04 20:45:51 +01:00
Fintan Halpenny 58305cda32 protocol/limiter: impl AsTokens for limits
Provide `AsTokens` implementations for the `Outbound` and `Inbound`
newtypes of `RateLimit`.

This allows them to be used for the rate limiting method.
2025-12-02 14:18:18 +01:00
Fintan Halpenny c675683da9 protocol: IntoIterator for BoundedVec
Implement `IntoIterator` for the `BoundedVec`.

This allows the use of `into_iter` for returning the owned data,
rather than references via the `Deref` implementation.
2025-12-02 12:55:09 +00:00
Lorenz Leutgeb 37d4ae4a9f radicle/node: Revisit routeability of IP addresses
All IPv6 addresses would be considered globally routeable, even though
the Rust standard library offers convenience functions to check for
loopback, link-local addresses etc.

Improve checks for IPv6 routeability to catch the most obvious cases of
local or unspecified addresses.

Refactor the check for IPv4 routeability to be more readable and refer
to RFCs, IANA lists, and Rust stabilization tracking issues as
appropriate.
2025-12-01 12:34:02 +00:00
Lorenz Leutgeb f9a62e7d8d radicle/node: `Address::is_local` for DNS names
`Address:is_local` would return `false` for all DNS names. This is
incorrect, with one counterexample being the name "localhost", which
generally resolves to a local (usually loopback) address.

The function is changed to catch "localhost", but also the top level
domain ".localhost", which is reserved in RFC 2606, Section 2.

`Address::is_routable` would return `true` for all DNS names. While it
is much harder to decide global routeability based on a domain name, as
these usually have to be resolved to an address before being able to
judge routability, there is one particular class of names, namely local
ones (see above), which are not globally routable.
2025-12-01 12:34:02 +00:00
Lorenz Leutgeb dc624ed518
radicle/node/bootstrap: Remove IP addresses
Due to connection retries in `radicle-node` not choosing new addresses,
mistakenly using an IPv6 address when IPv6 is not supported would result
in failure to bootstrap.

Work around by removing IP addresses again. This means that DNS or Tor
will be required to bootrstrap.
2025-12-01 12:27:53 +01:00
Fintan Halpenny 45abb881a3 node: Only consider onion addresses if configured
There is an unfortunate lack of single-responsibility with handling the
addresses to connect to.

This is a band-aid fix until the point in time where this can better improved.
2025-11-28 21:52:39 +01:00
Fintan Halpenny 93d2ed8c61 cli/completion: Static shell completion for `rad`
Introduce the use of `clap_completion` for generating static completion.
The shells that are supported are the ones that are included in `clap_complete`:
- `bash`,
- `elvish`,
- `zsh`,
- `fish`, and
- `powershell`.

Co-authored-by: Michael Uti <utimichael9@gmail.com>
Co-authored-by: Lorenz Leutgeb <lorenz.leutgeb@radicle.xyz>
2025-11-28 20:47:25 +01:00
Sebastian Martinez 7e5a1ababc radicle: Skip invalid named folders
Instead of failing with an `InvalidId` error in
`radicle::storage::ReadStorage::repositories` for repos that don't have
a valid repository ID, skip them and log a warning.


Co-authored-by: Lorenz Leutgeb <lorenz.leutgeb@radicle.xyz>
2025-11-28 20:31:06 +01:00
Fintan Halpenny 0c70e17123 remote-helper: inform the user of an empty patch
The previous message is included in the error:

     ! [remote rejected] master -> refs/patches (patch commits are already included in the base branch)
     
To make it clearer to the user, also print a warning to tell them that the
commit was in the base branch – including the commit SHA:

    warn: attempted to create a patch using the commit f2de534b5e81d7c6e2dcaf58c3dd91573c0a0354, but this commit is already included in the base branch
2025-11-28 20:19:47 +01:00
Fintan Halpenny 28c8c1531f cli/sync: filter seeds without an address
If a seed for syncing does not have an address, the local node will not be able
to connect to it.

These can be filtered out so that no connection attempts are made for these nodes.
2025-11-28 20:05:26 +01:00
Defelo 0ec084fc23 remote-helper: Support push --force-with-lease
Previously, the remote helper would not support the `--force-with-lease` option.
This change introduces this support and ensures that it works as intended.

Co-authored-by: Fintan Halpenny <fintan.halpenny@gmail.com>
2025-11-25 10:48:30 +00:00
Sebastian Martinez 6d0c571ea9 radicle: Return individual results for repo in `repositories_by_id`
Change `repositories_by_id` to return `impl Iterator<Item = Result<RepositoryInfo,
RepositoryError>>`
instead of `Result<Vec<RepositoryInfo>, RepositoryError>`.
This allows callers to handle failures on a per-repository basis rather
than having the
entire operation fail if a single repository lookup fails.

Previously, the method would stop processing and return an error as soon
as any repository failed to load. Now it processes all repositories and
returns individual results, making the API more resilient and giving
callers
more control over error handling.
2025-11-06 10:43:04 +01:00
Lorenz Leutgeb c268e809e9 chore: Fix mistakes discovered by typos 2025-11-04 14:09:07 +00:00
Lorenz Leutgeb 11cbc2e515 hooks: Run "pre-push" by default 2025-11-04 14:04:24 +00:00
Erik Kundt 7ccdd4c810 ci: Activate all features when building docs
Currently, `cargo doc` fails on warnings for missing links to
`qcheck` and `radicle_git_ref_format`. This will enable the required
features to compile those modules in.
2025-11-03 11:30:43 +01:00
Yaroslav Halchenko 32d77641ab chore: Fix spelling errors with codespell 2025-11-01 12:11:02 +01:00
Yaroslav Halchenko f7e57361dc hooks: Add codespell
Co-authored-by: Lorenz Leutgeb <lorenz.leutgeb@radicle.xyz>
2025-11-01 12:06:08 +01:00
Lorenz Leutgeb 8e331ce182
node/reactor/transport: Implement `Debug`
The derived implmenetation prints read and write buffers, which is too
much even for trace logging (where we use this trait).
2025-11-01 11:20:43 +01:00
Fintan Halpenny bc1d9ed495 cli: remove lexopt dependency 2025-11-01 11:20:43 +01:00
Fintan Halpenny 83f26abaa0 cli/main: refactor external command
Refactors the external command logic into a struct.

This allows for methods to maitain the logic of an external command.
It also allows for a cleaner output for the executable name – avoiding the debug
output of OsString using `""`.
2025-11-01 11:20:43 +01:00
Fintan Halpenny f60922d125 cli/terminal: make args module private 2025-11-01 11:20:43 +01:00
Fintan Halpenny 961301f643 cli/terminal: clean up args::Error type
The other variants of `terminal::args::Error` were no longer used.
The only variant required is `Error::WithHint`.

The enum is also made private, since it is only used in this crate.
2025-11-01 11:20:43 +01:00
Fintan Halpenny a75db6a695 cli/terminal: remove argument helpers
These helper functions were for parsing arguments passed via lexopt.
Since `clap` is now the parser for these types, these functions are no longer
needed.
2025-11-01 11:20:43 +01:00
Fintan Halpenny fec8a27a36 cli/terminal: remove Help struct
The `Help` struct is no longer needed thanks to `clap`, so it is removed.
2025-11-01 11:20:43 +01:00
Fintan Halpenny e359435040 cli/main: move run_command_fn to main
This call was moved to the `main.rs` file, since that is where it is used.

It is renamed to `run` and its call site is cleaned up.
2025-11-01 11:20:43 +01:00
Fintan Halpenny 7533db62f9 cli/terminal: remove unused parameter 2025-11-01 11:20:43 +01:00
Fintan Halpenny 1f80eb61ed cli/terminal: remove unused trait 2025-11-01 11:20:43 +01:00
Fintan Halpenny d41ac59828 cli/help: remove the help module
The `help` module is no longer needed, since `clap` handles that.

This meant that the re-exports of each command's `ABOUT` could be removed and
the `const`s can now be private.
2025-11-01 11:20:43 +01:00
Fintan Halpenny 23332fa318 cli/main: migrate main to use clap
Now that all commands can be parsed by clap, remove any custom parsing and
directly use `CliArgs::parse`.

The `Diff` command was removed, since only one `external_command` can be
declared for a subcommand. The handling of `rad diff` is now done via the
`External` variant. If the subcommand name is `diff` then this is executed,
otherwise delegate to the possible `rad-{exe}` command.

Also of note, the `rad inspect` command has an alias `rad .`. This changes the
behaviour of `rad . --help`. Before, it would print the help of the `rad`
command. Now, it prints the help of `rad inspect`.

Co-authored-by: Lorenz Leutgeb <lorenz.leutgeb@radicle.xyz>
2025-11-01 11:20:43 +01:00
Fintan Halpenny 5053a1aa77 cli/unseed: rename options to args
Have consistent naming for args
2025-11-01 10:52:13 +01:00
Fintan Halpenny 6ca1292350 cli/unfollow: rename options to args
Have consistent naming for args
2025-11-01 10:52:13 +01:00
Fintan Halpenny 3c89525003 cli/sync: migrate to clap
Due to the idiosyncracies of this command there are a few things to note about
this migration.

The `rad sync` command acts as a default subcommand in itself, in that it has
options that do not apply to its subcommand, `rad sync status`. This means that
the options will print with `rad sync --help`, but they will not print with `rad
sync status`.

The `--inventory` flag is not compatible with any of the other flags and
options, thus they are all marked with `conflicts_with`. This cannot be done for
a positional argument, so `clap` will "helpfully" print out the usage, for
example, as:

    error: the argument '--inventory' cannot be used with '--fetch'

    Usage: rad sync --inventory [RID]

    For more information, try '--help'.

Which is incorrect, since `RID` is ignored. This is explained in the `--help`
documentation for `--inventory`.

Co-authored-by: Lorenz Leutgeb <lorenz.leutgeb@radicle.xyz>
2025-11-01 10:52:13 +01:00
Matthias Beyer d1e19a87b0 cli/patch: migrate patch CLI parsing to clap
Co-authored-by: Fintan Halpenny <fintan.halpenny@gmail.com>
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
2025-10-29 09:11:05 +00:00
Fintan Halpenny 3ea61f0f98 cli/patch: move comment actions
Moving the sub-comment actions to be beside the top level comment action. This
is mostly to provide a better diff for the next commit – that refactors due to
`clap` changes.
2025-10-29 09:11:05 +00:00
Lorenz Leutgeb e404f1038f node: Use `std::time` for reactor and wire
This reduces the exposure to the `localtime` crate, using
`std` instead.
2025-10-29 09:05:52 +00:00