Instead of returning the unsigned references, the validation of a
repository's remotes returns the set of validation errors. The caller
is then expected to handle these validation errors appropriately, for
example, by logging them and re-raising an error.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
This change allows users to track/untrack peers and repos without a
running node. This fixes a bug when running `rad init` without the node
running, where the repo would be tracked with a different scope than
what was specified on the CLI.
The `AliasStore` mechanism was added but not used in the `rad node`
command. Since the launched node itself can display aliases based on
the address book, it would make sense if the `rad node` command could
do this as well.
Use the `Profile`'s `AliasStore` implementation to fallback to an
alias if the tracking store does not contain an alias -- essentially
using the address book instead.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
The `rad patch checkout` command would blindly create a branch when
being executed. If there was a branch already existing and user had
committed to that branch, switched without updating the patch, and
then switched back, then they would lose the commit on that branch --
the original commit of the patch would be taken instead.
Fix this by first checking if the branch existed beforehand, and
setting the workspace to use that branch's commit.
Add a test to ensure that this works as expected.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
When specifying a `patch.base` to point to for stacking patches, it's
useful to accept any kind of revspec, e.g. `HEAD^`.
Change the argument parsing to use the `Rev` type instead, and change
the `rad-patch-ahead-behind` to use `HEAD^` to test the example usage.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
When testing the CLI, "since"-calculations will result in different
values over time:
now
1 month ago
2 months ago
10 months ago
1 year ago
10 years ago
Initially, the solution was to use the wildcard match from `snapbox`,
`[..]`, to match on these values. However, since these values change
in length it means that they will affect the width of the tables
produced by the CLI.
To ensure the width is stable across runs over time it's possible to
use a time that is the same as the commit time used at testing.
To do this the `Timestamp` type is now a newtype which has a
constructor `now` which will use the `RAD_COMMIT_TIME` env variable
for construction, if it's available and in debug mode. This ensure
that all "since"-calculations will result in `now`.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
Introduces a new COB type to store repository identity documents.
The reason for this change is to:
1. Simplify the code, as the identity document logic resembled a COB,
yet it had custom logic. This allows existing COB code to be used for
identities.
2. Make identity document update logic more flexible, since COB actions
can be added in the future.
3. Re-purpose existing tools around COBs to work on identities, eg. `rad
cob`.
4. Unify the concept of an identity change proposal, with regular identity
changes. This means we can remove the `id.proposal` COB in favor of
using the `id` COB itself.
Notes
-----
* Each repository has one Identity COB.
* The `Proposal` COB has been repurposed into the `Identity` COB.
* Identity documents are stored as *embeds* inside the Identity COB
actions.
* The action that contains new document versions is called `revision`,
just like the Patches COB.
* The namespaced `rad/id` ref is a symbolic reference to that Identity
COB.
* The canonical `rad/id` ref is a direct reference to the commit in the
Identity COB that contains the latest *accepted* revision of the
document.
* All commands for managing identities have been folded into `rad id`.
Hence `rad delegate` and `rad edit` are removed.
* The concept of "rebasing" an identity document is gone.
* The `rad id` output has been updated to match the style of other
commands.
* When a revision has enough signatures, it is automatically adopted as
the current identity, there is no longer the need for a "commit"
action.
* When an identity revision is proposed, and the current identity has a
threshold of `1`, that identity is automatically accepted due to the
above point.
* The idea of "verifying a peer's identity branch" no longer applies, as
COBs cannot be verified one history at a time.
* Since the root commit of the Identity COB does not have a "Resource"
to point to (it would have to point to itself, which is impossible),
we've made the resource id optional for COBs.
This commit introduces the `FileStats` struct, that adds the insertions
and deletions for each file to `DiffContent`.
Signed-off-by: Sebastian Martinez <me@sebastinez.dev>
Previously we only syntax highlighted files that were blobs inside the
git repo. This doesn't work when diffing files in the working copy.
We solve that by looking for files in the working copy if they aren't
found in the ODB.
* `args::rev` now parses things like `master`, `HEAD`, `3f25ea5`.
* `args::oid` is for parsing full or short oids, like `3f25ea5`.
Both return a `Rev`, since short oids can't be properly represented with
the `git2::Oid` type.
The `Element::render` function now takes a constraint object. This
allows the parent element to influence how the child is rendered. This
is useful eg. to have elements take up more space than they need to fill
some space.
We also make various changes needed for pretty diffs, such as merging
styles, a new `Filled` type, and some color theming.
Changes the behavior of `git fetch` by running a radicle network-level
fetch (ie. `rad sync --fetch`) before fetching refs from storage. This
avoids having to run `rad sync` before `git fetch`; and tries to make
sure that refs are always fresh.
As a delegate, you shouldn't be able to delete your default branch.
This would most likely happen by mistake, and it prevents the canonical
head from being calculated correctly.
On push, we check whether the resulting state would cause a
divergence/fork in the canonical head, and if so, prevent the push from
happening.
This is to avoid situations where delegates have to then rollback their
heads.
Note that this doesn't prevent forks from happening altogether, as they
could happen asychronously, but it mitigates the problem.
The `Patch` API and semantics are changed a little bit:
* It's now valid again to propose a revision without being the patch
author.
* To get revisions by the patch author, `Patch::updates` is used.
* `Patch::latest` now only looks at revisions by the patch author.
* Added `Patch::revisions_by`, `Patch::authors` and `Patch::latest_by`.
* The merge behavior on git-push is improved to favor revisions that
merge more recent commits. We also allow for merging the non-latest
revision.
Define types to support Diff of Diffs leaning on the Radicle Surf types.
Use Radicle Surf's Hunk type, but custom Diff, FileDiff, and
Modification types, and avoid Serde serialization as it does not yet
seem necessary.
Parse Git's unified diff format into Radicle Surf's types. Support to
and from the format helps testing and debugging.
Split the UnifiedDiff trait into Decode and Encode traits so we
can offer Decode in cases where no data could be expected..
For example Option<Hunk<_>> and Hunk<_> allowing partial and repeated
decoding on a byte stream.
Avoid decoding `Diff`, `DiffContent::Binary`, `FileDiff`, and `FileHeader`
types. `Diff` keeps fields and methods private which are necessary for
decoding.
Simplify the trait by defining it on the concrete type, which appears to
be the standard rust approach. Remove some oddities in the process (refs
of refs).
We remove the YAML front-matter, since that was annoying to use.
Issues are now edited like patches and commit messages.
Labeling and assigning are done via dedicated commands.
When `rad issue show` is run, the issue comments are shown by default.
This can be tweaked using the `--format` option. A value of "header"
only shows the header, while the default which is "full", shows the
header and comments.
Sets the current branch's upstream to point to the given patch.
This allows for pushes to update the patch.
When opening a patch, if the current branch already has an upstream,
it isn't updated automatically. This is why this command exists.
This allows a user to choose private or public visibility on `rad init`.
It also improves the output to tell the user what happened due to this
choice.
It didn't make sense to get eg. `Patch failed` when listing patches
failed. We change all fatal errors to simply "Error:", giving more
control over the individual commands.
After cloning, we show a cool little summary with some repo stats.
We had to make some adjustments to the way visual width is calculated
due to a bug surfaced around emoji width calculation. Unfortunately
there isn't a perfect solution that works across terminals yet, so the
"variation selector 16" code-point is filtered out for now.
When a fetch is user-requested, a timeout can be supplied that is passed
down to the worker.
When a fetch is service-requested, a default timeout is used.
Private repos are implemented by extending the identity document with a
`visibility` attribute, that can either be `"public"` (default) or
`"private"`.
In case of `private` visibility, only the delegates are allowed to view
the repo, as well as any DIDs added to the allow list.
To implement repo visibility, we simply block fetches from and
announcements to peers for whom the repo should remain invisible.
Private repos are also not announced in the `inventory` message, since
the full list of peers that *may* have the repo is retrievable from the
repo identity. This could cause errors if eg. a peer who is allowed to
view the repo doesn't actually have it. However this is an ok trade-off
for now to keep the complexity low. For repos to truly be private, it's
important that the RIDs don't leak either.
Finally, we modify `radicle-httpd` for now to only list public repos.
Eventually, we would want to change this depending on whether an allowed
peer is authenticated with the service or not.
---
It's also worth mentioning why this approach was taken, vs. end-to-end
encryption. The reasons are as follows:
1. Nodes that do not have access to a private repo will generally not want to
replicate encrypted data that they cannot examine or use.
2. The chosen solution is trivial, while encrypting git objects isn't.
3. Performance of the chosen solution is much better, there is no
overhead.
4. Privacy of the chosen solution is better: RIDs are never leaked, and
neither is the existence of a private repo, nor who has access to it.
There is one downside: Paying for storage of private repos is no better
in terms of privacy than what GitHub offers. Hosting providers will have
access to your private repos, if this solution is used.
Instead of having two types, we simply have one, called `Entry`, which
we rename from `Change`.
There was no real benefit to having two almost identical types, but lots
of added complexity. This patch simplifies the crate by removing one of
the types.
Add `deny.toml` with a few exceptions, and update certain dependencies
to get rid of duplicates.
Running `cargo deny check` will yield some warnings still, but no
errors.
This change allows for files (blobs) to be embedded into COB entries.
This allows for things like image attachments in issue comments for example.
For now, we only enable this in the `issue` COB.
The way it works is that relevant COB actions carry metadata about which
files are attached to them; and we store those files as blobs inside the
COB entry's *tree* object, under an `embeds/` folder.
The `Embed<T>` type is used for the above, and either carries actual
content, or carries a content-id. Retrieving the actual content is as
simple as asking the repository for a blob with that content-id.
As a possible future extension, MIME types could be stored alongside the
files in a "metadata" file. This could help clients display the content
appropriately.
This adds functionality so that on `rad sync` and `rad clone`, we
connect to known seeds if necessary, before attempting to fetch.
In passing, some related changes were made:
* The `rad sync` command's arguments were reworked:
`--replicas <count>` can be used to specify a replica count when
fetching
* The `rad patch` command no longer has a `--fetch` option
* It's now possible to tell the node not to automatically connect to
peers in the background
* `AddressBook` is being used underneath `Seeds` to allow for shuffled
iteration
Only return once the connection is established or failed.
It's still not perfect, as several failure scenarios are not handled,
but it's an improvement.
We move the session address to the top-level struct, since it's needed
in a bunch of places. This change is required for the rate-limiting
code that is coming next.
As a starting point, we populate the address book (if empty) with some
bootstrap nodes which are trusted.
To prevent these nodes being connected to during tests (including e2e
tests), we create a new constructor for `Config` that is used in tests.
Note that a `cfg(test)` check is not enough given that e2e tests don't
have that set.
> I'm going to be making a set of breaking changes to COBs in order to
stabilize the data formats. This is hopefully a one-time change that
bundles various breaking changes.
All COBs have been reworked: issue, patch, id.
The changes included are:
* Revise the assign and tag actions to take a single list of
assignees/tags to set, instead of an "add" and a "remove" list. This
makes API usage simpler when editing issues, and simplifies the apply
function
* Rename "tags" to "labels", and the tag action to label. This is
because tag is confusing in the context of git, as it could mean a git
tag. Using label removes that confusion.
* Use DIDs instead of PublicKeys for assignees -- this is more
future-proof
* Modify the manifest file format in the COB tree. Mainly, remove the
`history_type` key which is redundant, and use camelCase for keys
* Flatten the `Thread` actions into the parent action type
* Ensure that operations on redacted objects do not fail, since
redactions could have happened concurrently
* Use a consistent naming scheme for actions, using `.` as separator
* Consolidate comment types and remove `CodeComment`, by adding an
optional `location` field to `Comment`
* Add many placeholder actions that are not yet implemented
To preserve backwards compatibility, a `legacy` module is created with
the old `apply` function. When loading the manifest, we check whether it
is a legacy COB or a "stable" COB, and in the legacy case, use the
legacy code to materialize the state and then convert the object into
the stable type. Eventually, we'll delete the legacy code.
Some of the old patches had missing objects and that causes problems
during the ref advertisement, as the object is not found.
In this patch, we check that the object exists and also that the patch
is still open. Otherwise a remote tracking branch is created for every
single patch ref.
Move code for writing radicle_surf diff's in git's unified diff format
into its own module. Lean on the type system by defining a
`UnifiedDiff` trait to provide a method `encode` to encode to the
format and another default method to convert to a git 'unified' diff
string.
Additionally a `Header` struct is added to support processing Unified
Diff files. The Header's line numbers must be tracked and modified to
produce legal diff files.
This is in preparation for DDiff support. Upcoming improvements will
include parse unified diff's into these types to support test data.
If you accidently merge updated patch code before updating the patch in
storage, you end up in this weird state where you can't update the patch
any longer. This fixes it.
This commit addresses the inconsistent parsing of the command by fixing the
partial matching behavior for the `--seed` flag. Previously, specifying
the seed value resulted in an invalid option error, as shown in the example below:
```
➜ ~ rad sync --seed z6MksmpU5b1dS7oaqF2bHXhQi1DWy2hB7Mh9CuN7y1DN6QSz
✗ Error: rad sync: invalid option '--seed'
```
With this fix, there are no restrictions on when the seed can be specified.
In a future change, we plan to implement a custom error message when a
match case does not meet specific requirements, such as `rad --fetch --announce`,
which will return a more informative error message. However, this
enhancement is left for a derived solution.
```
➜ ~ rad sync --fetch --announce
✗ Error: rad sync: invalid option '--announce'
```
Fixes: d6cebf613f
Suggested-by: Slack Coder
Signed-off-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>