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.
A rewrite of the argument parsing portions of the `rad issue` subcommand
using `clap` instead of `lexopt`.
From a user's perspective, the look-and-feel of `rad issue` does not
change much. Although, the most prominent change is to rely on
`clap`'a default error template which looks a bit different from what we
use usually (`error: ...` vs. `✗ Error: ...`).
Leaving the above restriction aside, subcommand mis-usage is
reported more verbosely.
Also configure `clap` to use colored output for errors and help pages.
In help output, headers are colored with `Magenta` to match the overall
CLI styling.
Specify a type that captures the different actions that can be take
when using the `comment` command: `Comment`, `Reply`, and `Edit`.
Move the functions that run the corresponding actions into a `comment`
module.
To preserve the "default command" behaviour being `rad issue list`,
e.g., `rad issue --solved` behaving like `rad issue list --solved`,
introduce a new type `EmptyArgs`to also parse arguments without a
subcommand. In case no subcommand was parsed, construct `Command::List`
with from `EmptyArgs`.
Co-authored-by: Matthias Beyer <mail@beyermatthias.de>
Co-authored-by: Lorenz Leutgeb <lorenz.leutgeb@radicle.xyz>
Co-authored-by: Erik Kundt <erik@zirkular.io>
Co-authored-by: Fintan Halpenny <fintan.halpenny@gmail.com>