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.
`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.
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.
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.
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>
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.
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>
Make `git2` an *optional* dependency of `radicle-cob`, and refactor
`radicle` to depend on crates that in turn do not depend on `git2`
*non-optionally*
The main offending dependency of `radicle-cob` is `radicle-git-ext`
from the `radicle-git` workspace in repository
(rad:z6cFWeWpnZNHh9rUW8phgA3b5yGt) which *non-optionally* depends on
`git2`.
So, to achieve removal of this dependency:
1. The crate is refactored to depend on the new crates
`radicle-git-ref-format` `radicle-git-metadata`, and
`radicle-oid` introduced in the previous commits, instead of
`radicle-git-ext`.
2. Some code from the `radicle-git-ext` crate in the `radicle-git`
workspace in repository (rad:z6cFWeWpnZNHh9rUW8phgA3b5yGt) is
copied. See `crates/radicle-cob/src/backend/git/commit.rs`.
This cascades to `radicle` and its dependents.
Firstly, the there is an
`impl Deref<Target=git2::Oid> for radicle_git_ext::Oid`. This made
it very convenient to just deref to obtain the wrapped `git2::Oid`,
so there are many expressions of the shape `*oid` in `radicle` and
its dependents. However `radicle-oid` does not provide
`impl Deref<Target=git2::Oid> for radicle_oid::Oid`, as notably,
`Target` is an associated type, and not a type parameter, so an
implementation of `Deref` would tie the new `Oid` too tightly to a
particular implementation.
Instead, work with `impl From<radicle_oid::Oid> for git2::Oid`
(which can be enabled using the feature flag `radicle-oid/git2`).
This explains the changes from `*oid` to `oid.into()` at every
transition to "`git2` land".
Secondly, `radicle` and its dependents are refactored to also depend
on `radicle-git-ref-format` and (much less prominently)
`radicle-git-metadata` instead of `radicle-git-ext`
This is to avoid pulling in `git2` via these dependencies.
Thirdly, as the re-exports in `crates/radicle/src/git.rs` change,
they are at the same time also cleaned up. Notably, the types from
`radicle-git-ref-format` are re-exported under `fmt` only, not "twice".
While overall this obviously is very much a breaking change, these
changes should mostly amount to changing from `Deref` to `Into`, i.e.,
`*oid` → `oid.into()` and rewriting imports for `radicle::fmt`.
This is indicated by the mostly mechanical nature of the changes to
`crates/radicle-{cli,node,remote-helper}`.
For further details on the crate see its documentation in
`crates/radicle-oid/src/lib.rs`.
Changes to `crates/radicle{,-crypto}/Cargo.toml` are to preserve the
default features of their dependencies `serde` and `schemars`,
which are disabled to support `radicle-oid` being `no_std`.
In commit 2149770a4b the dependency
`tempfile` was made optional, and added to be enabled by the feature
flag `test`. However, the *tests of this crate itself* need the
dependency *unconditionally* as they want to create temporary
directories.
This was not noticed earlier, since the error does not surface when
the whole workspace is tested (`cargo test --workspace`), but only
when the crate itself is tested (`cargo test --package=radicle`),
because when testing the workspace, dependents of `radicle` will
enable the `test` feature flag.
`impl Display for RepoId` will produce a `rid:` prefix, which
contains a colon, and this trips up various filesystems. Use
`RepoId::canonicial` instead.
The following tests generated an unstable object ID, thus linearizing
history in a different order, causing failures. Fix this by using the
`stable-commits` feature of `radicle-cob`.
thread 'cob::identity::test::test_identity_redact_revision'
panicked at crates\radicle\src\cob\identity.rs:1338:9:
assertion `left == right` failed
left: [Oid(b4307ded046befba374bf8cd9fd787592ceb615c),
Oid(a04165e3d3717c5a1413ec78e852bd8e1bb049d4),
Oid(820d3faf5b507888173b26ccd1a2a81666bd2573),
Oid(30ca6f078a401bf542049594fbb1c8d2371c9819),
Oid(9e9c46971014b123a31cd1195078f95c2e319419)]
right: [Oid(b4307ded046befba374bf8cd9fd787592ceb615c),
Oid(a04165e3d3717c5a1413ec78e852bd8e1bb049d4),
Oid(820d3faf5b507888173b26ccd1a2a81666bd2573),
Oid(9e9c46971014b123a31cd1195078f95c2e319419),
Oid(30ca6f078a401bf542049594fbb1c8d2371c9819)]
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread 'cob::identity::test::test_identity_reject_concurrent'
panicked at crates\radicle\src\cob\identity.rs:1494:9:
assertion `left == right` failed
left: [Oid(b4307ded046befba374bf8cd9fd787592ceb615c),
Oid(bce4233f6a09d6e9c021ba436e3c6923a1a78f31),
Oid(7cacb23be7079c16c8ad1b2458ae5bac95a1295b),
Oid(12b00e2e871b699c84c20427a64e029934c15ec4),
Oid(07431c8d80c11492ef248e07126370e874de3435),
Oid(98b42450159a359c2f482652c66d79b05d0af624)]
right: [Oid(b4307ded046befba374bf8cd9fd787592ceb615c),
Oid(bce4233f6a09d6e9c021ba436e3c6923a1a78f31),
Oid(7cacb23be7079c16c8ad1b2458ae5bac95a1295b),
Oid(98b42450159a359c2f482652c66d79b05d0af624),
Oid(12b00e2e871b699c84c20427a64e029934c15ec4),
Oid(07431c8d80c11492ef248e07126370e874de3435)]
Fixes test `profile::test::canonicalize_home`.
Since `Home::new` canonicalizes its argument (which is what the test
wants to ensure), also canonicalize the expected value, which is
especially important on Windows as the canonicalization is more
complex than on Linux.
For example:
thread 'profile::test::canonicalize_home' panicked at crates\radicle\src\profile.rs:802:9:
assertion `left == right` failed
left: "C:\\Users\\runneradmin\\AppData\\Local\\Temp\\.tmpMnNkr6\\Home\\Radicle"
right: "C:\\Users\\RUNNER~1\\AppData\\Local\\Temp\\.tmpMnNkr6\\Home\\Radicle"
A refactoring internal to the `radicle` crate, with the goal of
making dependency on `git2` clearer and more controlled.
`radicle::raw` is changed from a complete re-export of `git2`
to a module that selectively re-exports (many) members of `git2`.
required to build the workspace (potentially breaking dependents
outside the workspace, but given just how many types are
re-exported, this seems unlikely).
In the future, no more `use git2::…` statements should be added
outside of `crates/radicle/src/git/raw.rs`. This is in an effort to
decrease dependence on `git2` in the future.
The dependencies `netservices`, `io-reactor` and `popol` served us well,
however they do not support Windows and are not actively maintained.
This change removes the aforementioned dependencies (and `libc` along
with them). It reuses the integration with `cyphernet` from
`netservices` for Noise and SOCKS.
The new module `reactor` is a rewrite of `io-reactor` on top of Mio.
Note that no tests were changed.
The `git-ref-format-core` crate is enough to implement everything
required by `radicle-crypto`, and has a much smaller dependency
footprint than `radicle-git-ext`. Notably, it does not depend on
`git2` and also does not depend on procedural macros.
The "seeds" command does only take a repository ID, and
carries the implicit assumption that the namespace with the same public
key as the Node ID of the receiving `radicle-node` process should be
used as reference for determining whether other nodes are in sync,
but no other namespace.
In the spirit of separating user and node identity, relax this, so that
the command also carries the public keys relative to which the sync
status should be computed. This allows to inspect sync status for
arbitrary namespaces via command.
For now, this feature is not exposed to the CLI, but `rad sync status`
always passes the public key of the active profile.
The "announce references" command does only take a repository ID, and
carries the implicit assumption that the namespace with the same public
key as the Node ID of the receiving `radicle-node` process should be
announced, but no other namespace.
In the spirit of separating user and node identity, relax this, so that
the command also carries the public keys for which the announcement
should be made. This allows to announce arbitrary namespaces out of
storage via command.
For now, this feature is not exposed to the CLI, but rather:
- `rad sync` always announce for the public key of the active profile.
- `git-remote-rad` ditto, as it calls the same codepath.
Some tests actually do not use qualified patterns. The removed lines
*should* not compile because the `qualified_pattern!` proc macro
*should* validate the string literals at compile time, but it contains
a bug and actually does not assert well-formedness of qualified
refspec patterns. Rectify.
On Windows, all attempts to clone repositories failed with
Fetch failed for rad:… from z6Mk…: Access is denied. (os error 5)
The reason is that, other than Unix-like systems, it forbids that
directories that are in use are moved.
To improve the situation, take back control over what is moved and
removed exactly by implementing `cleanup` instead of relying
on `impl Drop for tempfile::TempDir`.
A new type `TempRepository` is introduced to capture a repository that can be
used temporarily, and either cleaned up on failure, or moved on success.
This `TempRepository` can be constructed using `Storage::temporary_repository` –
renamed from `Storage::lock_repository` since it is only creating a temporary
resource and not locking it.
In the future (once Rust 1.89 is a little less cutting edge and more
widely available), we may opt for actual locking via
`std::fs::File::lock`.
Allow the fetch interface to accept anything that implements
`AsRef<Repository>`. This allows flexibility in the types that the `Handle` can
accept.
This change is motivated by wanting to introduce a type that is a temporary
repository that wraps a `Repository`.
With this change, the location of the secret SSH key can be configured
through `${RAD_HOME}/config.json` so that the node key does not have to
be placed under `${RAD_HOME}/keys` anymore.
Further, there is now an option to override `config.json` directly when
executing `radicle-node` via the command line argument
`--secret`.
The primary motivation is more flexible deployments, for example
leveraging external secret management solutions, like
<https://systemd.io/CREDENTIALS/>.
The secret key is fingerprinted by taking the fingerprint of the public
key corresponding to the secret key. This allows to detect when the
secret key changes.
When using Jujutsu and a non-colocated Git repository, the detection
using `git2` directly fails (just as `git` in a shell would fail)
because there is no `.git` directory found by traversing up the
filesystem hierarchy.
Add an invocation of `jj git root` as a fallback.
When run with a secret and public key that do not cryptographically
match, `fn radicle_cli::terminal::io::signer` would prompt the user
for a password to unlock the secret key, and then carry on with a
mismatching key pair.
Fix this by verifying that the keys match in `MemorySigner::load`
and only swallow errors initializing the signer in cases where
prompting for a password makes sense. It does not make sense in the
case of mismatched keys.
Previously it was possible to create an issue with an empty description
(i.e. an empty "root" comment), and also to change it later to a
non-empty string, however it was not possible to clear it again.
`radicle::run` interprets the `Output` returned by the `git`
process. However, depending on the application we have different
requirements for interpreting the output, e.g., how to handle errors.
Make `radicle::run` not interpret `Output`, but move this
logic to the respective binary crates (`radicle-remote-helper` and
`radicle-cli`).
The `verbosity` option is ignored, which makes it more difficult to
obtain debugging information if the "internal" push, i.e., the
`git push` invocation by `git-remote-rad` fails.
Provide two types for verbosity, and wire them up.
Ideally, we would like to use a name that is compliant with RFC 2606,
such as "radicle.example.com", but this would change *lots* of hashes,
which is not worth the hassle.
Instead, make changing this in the future as easy as changing one
constant.
This makes the default Radicle Explorer URL configurable at compile-time
via the environment variable `RADICLE_EXPLORER`.
In order to stay backwards compatible, we still default to
"app.radicle.xyz"