`impl Display for RepoId` will produce a `rid:` prefix, which
contains a colon, and this trips up various filesystems. Use
`RepoId::canonicial` instead.
macOS's `sed` requires an argument for `-i`, which we don't provide
in the example. Providing it makes the test fail on Linux.
Since this command is deprecated anyway, we just skip macOS.
It looks like macOS does not like this command:
ln: -f: No such file or directory
Since `LICENSE` and `MIT` are both just empty here, we don't need to
link anything.
This is a small cleanup to path generation during testing.
1. Separate `rad_home` and `unix_home` to avoid confusion.
2. Remove now unnecessary `trait HasHome`.
3. Move setting `$USER` to the environment.
4. Make paths shorter overall, to fix macOS tests.
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"
This adds `conflicts_with` for `private` and `public` to simplify the logic that checks for the document visibility
(thank you Fintan)
Co-authored-by: Fintan Halpenny <fintan.halpenny@gmail.com>
Extend facilities for `rg` based hook generation to also cover includes
and excludes, then add a hook that helps catch usage of `git2` in the
`radicle` crate, *with the exception of* `…/raw.rs`.
At the same time, these hooks are also enabled to run pre-push, as they
are very quick, just for convenience of Jujutsu users, because Jujutsu
currently does not support Git's commit hooks.
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.
While it is possible to pass the passphrase via the environment, e.g.
`EnvironmentFile=<path to file that contains "RAD_PASSPHRASE=…">`
this is less secure than passing it via a file, because the environment
is inherited down the process tree.
Thus, allow using a systemd credential. The ID of the credential must be
xyz.radicle.node.passphrase
and is not user-configurable.
Passing the passphrase via file is now possible with
`LoadCredential=xyz.radicle.node.passphrase:<path to file that contains passphrase>`
This requires just a bit of plumbing in `radicle-node`.
Because this mechanism is more secure than using the environment
variable `RAD_PASSPHRASE`, it takes priority. That is, if both the
systemd credential is available, *and* the environment variable
`RAD_PASSPHRASE` is set, the former is preferred.
Heads-up:
1. The contents of the file must be valid UTF-8 (see documentation of
`std::fs::read_to_string`). Assuming that the passphrase is at some
point chosen by the user and typed on a keyboard, this does not
seem like a severe restriction.
2. The contents of the file are not processed otherwise, i.e. line
breaks (notably at the end of the file) are not stripped.
The related `issue/8bd040e9de05e7fc27e373ebc1649ff4ad930e7a` asked for a
very similar feature: Passing the passphrase via a file named by the
value of the of the environment variable `RAD_PASSPHRASE_FILE`.
It was also briefly discussed at
<https://radicle.zulipchat.com/#narrow/channel/369277-heartwood/topic/.60RAD_PASSPHRASE_FILE.60/with/529104447>.
While it is possible to use systemd credentials via
LoadCredential=xyz.radicle.node.secret:…
ExecStart=radicle-node … --secret "${CREDENTIALS_DIRECTORY}/xyz.radicle.node.secret"
Make usage more convenient and directly support passing the secret key
via a systemd credential. The ID of the credential must be
xyz.radicle.node.secret
and is not user-configurable.
A systemd service unit file might contain:
LoadCredential=xyz.radicle.node.secret:…
ExecStart=radicle-node …
This requires just a bit of plumbing in `radicle-node`.
The preference order for the path of the secret key is:
1. The command line argument `--secret`.
2. The systemd credential.
3. The configuration file.
4. The default location to preserve backward compatibility.
The reason to prefer the systemd credential over the configuration file
is that it uses a mechanism that is influenced by the environment of the
process, which is deemed "closer at runtime" or "more dynamic" than a
configuration file. Ad-hoc overrides are still possible via the
commandline argument.
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.
In an effort to reduce the change of version numbers, dependents of
`radicle-node` should not need to know about the modules:
- `control`
- `wire`
- `worker`
These are internal to the `radicle-node` running, and none of its dependents
accessed them.
This resulted in removing two unused type aliases.
To improve crate version churn, mark the error types as `non_exhaustive`.
This removes the need to change the version number of the crate when adding a
new variant.
Note that these errors are never matched on, so no other code is changed in
dependent crates.
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`.
The interface of the `Handle` has two methods: `Handle::repository` and
`Handle::repository_mut`. However, the calling logic would always access the
`Handle::repo` field.
This is cleaned up by making this field private, and using the
`Handle::repository` method instead. There were no calls to `repository_mut`,
and so the method was removed.
It is impossible to preserve the head of a revision and only change
the base of same revision via push.
Strenghthen the precondition for skipping updates to also consider the
base commit.
Without quorum for the default branch, the remote helper would report
an error, suggesting that the patch was not updated, while,
inconsistently, actually updating the ref in storage without creating
a new revision.
$ git push …
To rad://z…5/z…z
…
! [remote rejected] 612… -> patches/a77… (…)
error: failed to push some refs to 'rad://z…5/z…z'
…
$ git ls-remote rad://z…5/z…z
612… refs/heads/patches/a77…
This is very confusing.
Fix this by using a temporary reference name that is different from the
reference name that the patch would use, implementing cleanup via
`Drop`.
While at it, also move the logic into `patch_base` and share it
between `patch_open` and `patch_update`. Computation of the canonical
head via `stored.canonical_head` is moved to a branch that is only
taken if the user did not specify a base explicitly. This allows to
update patches even when there is no quorum for the default branch.
This function (and the helpers `ancestry` and `find_and_peel`) are
eagerly peeling to commits, leading to updates of tags that target the
same commit to be missed.
For example, there could be tag two tag objects with *different* OIDs
A and B, from *different* authors, using *different* tag names, signed
with *different* secret keys, and both pointing to *the same* commit C.
The implementation would consider A and B to be the same, just becuase
A and B both peel to C, skipping the update.
This is counterintuitive, and when combined with canonical references
can be quite confusing.
Change this to only reason about an ancestry if the two objects in
question really both are commits directly. Otherwise, treat cases where
no structure can be used as ancestry similarly to non-fast-forward
updates.