An edge case was found where a delegate attempted to merge a patch,
but had not pushed to their default branch yet.
This resulted in the `old` not being defined and the check to revert
and/or merge not happening – so the patch continued to appear as open.
Since `old` only matters for the revert and merge check for the
default branch, resolving the `old` side does its best to find a
commit for the checks.
It does this by falling back to getting the canonical head before the
push, and using that as the old.
On Windows, SSH Agents commonly use a named pipe with a global default
name. This patch is to give users a more streamline experience as they
will not need to set the environment variable manually anymore.
When delegates collaborate on the repository identity, their voting
narrows the tree of active proposals to the chain of accepted
proposals. Thus, they crucially must understand which proposals are
siblings, i.e., which proposals share the same parent, because no
two sibling proposals should ever be accepted at the same time, as
this would mean a fork.
To ease collaboration of delegates and improve their overview, also
print the parent revision, if present. Note that the initial revision
is the only revision that has no parent.
Since `tor` and `i2p` are features, dependents may compile the
`radicle` crate without these features and will not be able to parse
`AddressType`.
Allow parsing of the `AddressType` to fail, and skip if that is the
case.
Further, the same holds for `Address`, and skip if that fails to parse
as well.
Finally, `Address` may parse an address string successfully to
`HostName`, but it may have an `AddressType` that does not match the
`HostName` variant. Guard against this, again skipping if they are not
equal.
For example, `HostName::Dns` is a `String` underneath, so there is
higher chance that something like `deadbeef.onion` parses to this
variant.
Parsing of IPv6 addresses not enclosed in square brackets causes a
warning to be logged.
This is too strict, since the user can not influence IPv6 addresses
received over the network, but only those in their configuration.
Remove the warning from parsing, and instead carry a boolean to warn the
user later.
The invalid timestamp error will only tell the timestamp of the
offending node's message.
Currently, there are issues where that error is occurring but the
timestamp seems legitimate. This patch adds the running node's
timestamp to help debug the issue.
Move logging-related module `radicle::logging` into its own crate.
While at it, remove the "logger" feature flag from `radicle`.
Co-authored-by: Lorenz Leutgeb <lorenz.leutgeb@radicle.dev>
`cargo check` fails because `human-panic` and `sysinfo` require at least
1.88.0.
+++ command cargo check --release --locked --all-targets
error: rustc 1.85.0 is not supported by the following packages:
human-panic@2.0.6 requires rustc 1.88
sysinfo@0.37.2 requires rustc 1.88
Bump MSRV to fix this.
1.88.0 introduced [let chains], which in turn has `clippy` warn about
nested if statements. All of these sites are fixed in this change.
1.87.0 introduced [`is_multiple_of`], which is a more readable version
of `x % y == 0`.
[let chains]: https://blog.rust-lang.org/2025/06/26/Rust-1.88.0/#let-chains
[`is_multiple_of`]: https://doc.rust-lang.org/std/primitive.usize.html#method.is_multiple_of
In `cb57e6560fe7767e79b87473a11261fbb82ce84c` the loading of systemd
credentials was refactored. The idea was to only change the accepted IDs
slightly after switching from radicle.xyz to radicle.dev. Unfortunately,
this was done in a sloppy way. The two cases for passphrase and secret
actually differ in ways that was overlooked.
Rectify these mistakes and restore the old behavior:
1. The logic to read the passphrase from the file that contains the
credential is moved out of `load_credential` since it only applies
to the passphrase, not the secret.
2. The warnings printed are now generic, and will not mention the
passphrase in case reading the path for the secret fails.
- Fixes a bug where the log level set in the config file was
ignored: `Logger` and `StderrLogger` captured the level in a
`self.level` field at construction time and checked it in
`Log::enabled`. After config was loaded, the global
`log::set_max_level` was updated but `self.level` was not,
so verbose messages were dropped by the per-instance filter
even when the global filter allowed them.
- Make `log::set_max_level` the single source of truth: remove
the `level` field and have `Log::enabled` defer to
`log::max_level()` so the two filters can no longer drift.
- Update call sites to construct loggers without a level.
- Disable the structured logger's internal filter (set to "trace") so
that it also falls back to `log::set_max_level`.
Canonical references can not be used to model symbolic references.
Relax this restriction by adding another member to the payload, named
"symbolic". Its key-value/name-target pairs then translate directly to
canonical symbolic references.
Care is taken to not allow circular references, and that there always
is a rule that could generate the target of a symbolic reference
(or a chain of symbolic references). Still, a symbolic reference may
dangle (for example when its target reference cannot be computed
because of divergence), but at least it can be prevented that a
symref *always* dangles, because there is no rule that would produce
its target.
Co-authored-by: Fintan Halpenny <fintan.halpenny@gmail.com>
Previously `test_fetch_emits_canonical_ref_update` was passing by
catching a leftover `CanonicalRefUpdated` event from the initial
repository fetch. Furthermore, the new commit was written to the
un-namespaced root. It can be proven to be the case by commenting out
the `alice.commit_to(...)` line and watching the test still pass.
Fix the test by committing to the namespaced default branch which will
trigger the `CanonicalRefUpdated` that is expected by Bob. Drains events
so we don't catch the wrong event, and explicitly announces.
The `commit_to` method should namespace the reference, so that node is
only ever committing the namespace of that particular node.
This prevents the node from committing to another node's namespace or
the canonical namespace.
Previously a rule like `refs/heads/releases-*` would be rewritten
incorrectly to `refs/heads/releases-**/*` matching the 'trailing
asterisk' rule.
Simplify the rewrite rule so that a trailing `*` becomes a prefix
matching rule. Add tests.
Reorganises the rules test suite into a `test` module and a `helper`
sub-module.
The former holds the original tests, removing the `test_` prefix.
The latter holds helper functions for test setup.
- Drop `type='ipv6'` rows whose bracket-stripped inner part contains
no `:`, since every valid IPv6 textual form has at least one
- Cover the offender (`[]:8776`), bracketed garbage (`[abc]:8776`),
the unspecified (`::`), loopback, and full forms in tests
- Keep `dns` and `ipv4` rows untouched
Migration 8 retyped any `[..]:N` dns row to ipv6 by bracket pattern
alone, without checking the inner part is parseable
- Decode each row independently so one corrupt entry no longer aborts
the whole address-book iterator
- Log a warn with the raw `value` and continue past parse failures
- Add a regression test that mimics the post-migration-8 state where a
legacy `[]:8776` row lands as `type='ipv6'`
A pre-`df8e4e6c` parser admitted `[]:8776` as `HostName::Dns("[]")`.
Migration 8 retyped any `[..]:N` dns row to `ipv6` without validating
the inner part, so on read `Address::from_str` rejects the row with
"invalid IPv6 address syntax", which bubbled up and caused
`available_peers()` to silently return empty, breaking peer discovery
for the affected node.
Update the output of `rad_jj_colocated_patch` so that it passes with the current version of `jj` being used:
```
jj --version
jj 0.35.0
```
Mark `rad_jj_bare` as `ignore` since it currently cannot determine the
RID from the `rad` remote.