The `refs/tmp` namespace is used by Git for the purpose of storing
temporary refs. We use it here instead of `refs/patch` to indicate
that the refs can be safely deleted.
This adds the ability to the git-remote-helper to open and update
patches via a `git push` to the magic ref `refs/patches` and
`refs/heads/patches/<patch-id>`.
The main change is that we had to move away from offering the `connect`
capability in the remote helper, to offering `push` and `fetch`
individually.
To get a feel for how this works, see the `rad-patch-via-push.md`
example.
This commit addresses the issue of recursion in the TryFrom
call of Reference by resolving the parent in a lazy way.
Due to constraints posed by the need to access `git2::Repository`
or `git2::Commit` to resolve the parent, this commit decides to
pull out the parent resolution logic from the `cob::object::Commit`
module and move it inside the `cob::store::Store` implementation by adding
a new method `parents_of`.
Suggested-by: Fintan Halpenny <fintan.halpenny@gmail.com>
Tested-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
Signed-off-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
This change updates to the latest radicle-git-ext, which required a
few changes within the radicle family of crates.
One set of changes is that the radicle-git-ext crate subsumes
git-commit, git-trailers, and git-ref-format -- so all those imports
go through radicle-git-ext.
The commit code requires that parent `Oid`s point to commits, which
made some tests fail. One of the reasons for these failures is that
the patch tests used fabricated `Oid`s and so the verification would
fail. This is fixed by allowing the test context code to create
`PatchRequest`s that create valid commits.
The other reason for failure was that the identity `Action` passed an
`Oid` that pointed to a blob. This is fixed by removing that code and
making a note of it in documentation.
The final major change was moving the Refspec type into git-ref-format
and removing the AsRefspecs trait. The trait was not required and
could its usage could be replaced by simpler code.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
If the 'rad' remote is still in the git config, then some of the CLI
tooling will think the project exists -- even after running `rad rm`.
For example, in the current state, if `rad rm` is followed by `rad
init` then the operation will fail.
During `rad rm`, attempt to delete the 'rad' remote.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
When attempting to connect to a peer, and when succeeding, write the timestamp
to the database.
This will allow us to better select addresses and not retry peers to
soon.
This change ensures that we include as a parent to the initial commit
of a patch COB, the head of the branch we are proposing as a patch.
This was already happening for patch updates, but we forgot to also
include it for the initial patch revision.
This ensures that the code is always fetched alongside the patch.
If the reference did not exist it is not necessary to create a new
`sigrefs` entry. Check that the reference exists before removing from
the cob store and only sign if it did.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
It wasn't being set correctly, and it's not the place for it,
so we remove it and set it in `httpd`.
Note that `Remote` is now simply a wrapper around `SignedRefs`.
If we want to remove the type or turn it into an alias, it will
require touching lots of different parts of the codebase. I opted
not to do that here as it's lower priority.
We were allowing remotes to be constructed via a function that didn't
check its inputs.
This is now fixed by moving the public key into the `SignedRefs` struct.
This commit fixes the inconsistency with the `rad patch` command,
which previously displayed an empty table when there were no issues. Now,
the CLI will display a message indicating that there are no issues to display.
Signed-off-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
This command announces refs to peers and waits for them to be
in sync.
Adds a subscribe method to `Handle` so that we can get the events
from the seed to allow us to confirm that the configured seeds fetched
from us.
This commit adds the cob state of either patches or issues to the
corresponding endpoint.
So we can either query a cob listing with the required state or expect
the default state.
And once filtered by cob state we paginate.
Signed-off-by: Sebastian Martinez <me@sebastinez.dev>
Fetch project information using the delegates fork of the project. This
avoids expecting a user's fork to exist locally.
Delegate project information is expected to remain in sync.
Add a test case showing that when a review is made with a None value
to an already set field, it will remove the original value.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
Instead of returning the namespaces that we fetched with,
we return the remotes that were actually fetched from.
This can differ if some trusted peers were not available
on the remote node.
Previously, if that was the case, it would cause errors
since the remotes were looked up and that lookup failed.
With this change, we not only verify the signed refs before
the repository "transfer", but also validate that all refs in the
repo are signed and there is no discrepancy with the signed refs
file.
This allows change commits to have more than one parent that isn't
part of the DAG.
We can use this to create dependencies towards git objects such as
commits, in the case of patch actions.
Previously we were announcing inventories all the time, due to
relying on the timestamp changing on insertion.
We change this to only announce our inventory when it actually changes.
When a merge is applied to a patch, we check whether the threshold
of delegates has been reached, at which point we set the patch status
to `merged`.
This requires threading the identity document oid through the "apply"
process.
Revision IDs are globally unique. Users will be able to use the
Revision ID in place of its patch ID.
Make `rad merge` refuse to merge an older revision unless the `--force`
option is given.
Using LWWReg::from will always set the clock value to the default,
which can end up being used wrong.
Instead, introduce a constructor method `initial` to indicate that it
should be used on initial construction, while `new` should be used for
newer values of the register.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
This fixes an issue that came up in tests where we would be reading
and writing to the database at the same time, and it would fail with
an error due to the lock being contended on.
Replaces pub accessors to struct fields with methods
Also creates some methods to compute necessary information
Signed-off-by: Sebastian Martinez <me@sebastinez.dev>
The One variant caused many paint points for fetching logic, where it
was not necessary. It was only constructed in one place, which could
be replaced by using the variant that holds a set of keys.
Remove the Namespaces::One variant and rename Namespaces::Many to
Namespaces::Trusted.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
When a repository does not yet exist during a fetch, i.e. a clone,
then only delegates are being fetched.
Augment Namespaces::Many to hold the trusted and optional delegate peers
separately. Doing so allows the construction of the variant without
the repository existing, but tracking relationships existing.
This variant can then be used to build refspecs for both the trusted
peers and delegates when doing a cloning fetch.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
The previous fetching logic had some pitfalls regarding its logic:
* Fetched 'rad' references could end up not being verifiable and leaving
the storage in a corrupt state
* Forced pushes would be prohibited, since they would be rejected by
the client side due to the refspecs being used.
The new approach is to stage a fetch in 2 steps. The first step is to
fetch the relevant `rad/id` and `rad/sigrefs` for verification. For
all remotes that are verified, fetch all references listed in their
respective `rad/sigrefs`, using the `+` marker in the refspec,
allowing to update for any force pushes -- note that this becomes a
safe operation since the `sigrefs` are signed by the remote that
created them.
To prevent unverifiable 'rad' references from polluting storage, all
fetch negotiations are done in a staging repository set up in a
temporary directory. All successful fetches are then transferred,
using the 'file://' protocol, from the temporary directory into the
radicle storage.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
To be able to change the description of a patch revision, without the
need to create a new revision.
Signed-off-by: Sebastian Martinez <me@sebastinez.dev>
Using LWWReg::from was giving subsequent actions
the same clock value as their predecessors.
This resulted in a Reject not being able
to turn into an Accept on a second review of a patch.
The solution is to use the clock value that was produced for the Op
and pass that into new, avoiding the call to from.
Co-authored-by: Fintan Halpenny <fintan.halpenny@gmail.com>
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
Signed-off-by: Sebastian Martinez <me@sebastinez.dev>
Introduce a canonical reference for refs/rad/id to aid in discovering
information about a repository without knowing a peer -- e.g. if a
peer wants to clone a new repository it needs to find out which peers
are delegates for that project, but does not know what their NIDs are
up front.
The approach mirrors the canonical `head` for a repository and
introduces useful constructors for `Doc`/`DocAt`.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
The tracked nodes include nodes marked tracked in the db, and
the delegates and `Namespaces::All` if it is a new repo.
Signed-off-by: Han Xu <keepsimple@gmail.com>
We implement a new `Element` trait which allows for more complex output
to be drawn, such as vertical and horizontal stacks.
We adapt `Table` to work within this system.
We refresh the output of `rad patch show` to use these new tools.
For display purposes in the web client, we add with this commit the
some needed properties to the revisions in the patch endpoint.
Signed-off-by: Sebastian Martinez <me@sebastinez.dev>
It's not a good idea to have fallible operations run after `FetchOk`
is received, since there's no easy way to communicate the error
to the remote at that point. What would then happen is that the fetch
just "hangs", since nothing is there to cancel it.
Hence, we compute namespaces earlier in the process, and store the
namespaces in the session. If there is a failure, the fetch is
never initiated.
The Reaction type needs to ensure that the `char` stored for its value
meets certain requirements -- via its `new` constructor.
To ensure Reaction is always constructed correctly, the `pub` accessor
is removed, and the Deserialize implementation is implemented by hand
-- as opposed to using derive.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
If Ops::try_from fails in from_history then it means that some
operations failed to be parsed.
If this happens, then a warning should be logged so that these failure
cases can be more easily traced.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
Periodically, make sure we try to fetch inventory that is tracked
but missing from local storage.
We decide not to fetch immediately on `TrackRepo`, as this limits
the command's flexibility. For example, when `rad clone` is used,
we want to be able to fetch manually after tracking.
By introducing a small limitation: only allowing entries in the change
graph to be addressable, instead of individual operations; we
drastically simplify the CRDT implementation.
There are four advantages:
1. Op ids are just regular SHA-1s
2. There's no need for relative IDs, ops never refer to other ops within the
same commit
3. There's no need for a nonce, since commits can't collide, and neither can op IDs
4. `OpId` can just be an alias of `EntryId`
The disadvantage of course, is that we have to be mindful of how we
create op transactions, since each transaction creates an addressable
unit. For example, we must not include multiple patch revisions in the
same transaction.
The fetch implementation will potentially fetch the local operator's
remote, which is unnecessary and could result in deleted data.
Fix this by threading the local operator's public key and add an
ignore refspec to the fetch arguments, i.e.
^refs/namespaces/<local>/*
The implementation also strictly fetches all or one namespace. This is
improved upon by introducing a new variant for specifying a set of
namespaces.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
The method `track_repo` only accepted the RID as the argument for
tracking.
Instead, allow passing Scope as an argument for tracking a
repository.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
The tracking configuration has no way of consulting for a configured
scope.
This change allows the storing of this scope inside the tracking
`Config` -- currently unused.
The default Scope is chosen as Trusted, so that nodes do not
implicitly track any other node. If this behaviour is desired -- for
example, for seed nodes -- then All should be chosen.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
The DelegatesOnly scope is very limited and causes more confusion than
it solves.
The Trusted scope subsumes DelegatesOnly since it implies delegates
along with any tracked nodes. This feels more natural to use and so
DelegatesOnly is removed -- leaving only Trusted and All.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
Previously the alias field was simply a string which could possibly be
empty. Some checks were made to see if this string was empty.
Instead, make the logic more obvious by making the alias field
optional.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
The MockStorage holds an inventory of repositories and their
identities but when asking for a MockRepository, none of this
information is transferred.
Add `id` and `doc` fields to MockRepository for defining some of its
functionality.
In addition, add a generator for a nonempty MockStorage to use in
tests that will expect the storage to be populated.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
Getting delegates for a repository is a common task. A method is added
to ReadRepository for this, which default to fetching the identity
document, verifying it, and return the delegates for that identity.
The connect command was unimplemented for both Node and the control
socket.
This wires up the connect functionality in both places.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
The routing function for Node was not implemented and there were no
functions for getting any tracking information.
This implements routing, tracked_repos, and tracked_nodes. To
accomplish this it was necessary to add associated types to the
Handler trait so that implementations could differ in the types they
use for returning this data, i.e. the control socket needs to use a
channel while the Node needs to return serializable data.
Currently, the Node uses a `Vec` but it would be more beneficial to
return an Iterator directly to ensure we are not always hitting the
heap.
To allow for the tracking types to be used across radicle-node (the
crate) and in radicle::node (the module), it was necessary to move
the types to the common place, i.e. radicle::node. At the same time,
new structs were added to make it easier to refer to tracked repos vs
tracked nodes.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
Before this change, the identity document would be loaded for the
COB signer. This meant that a fork would be needed for that signer.
After this change, it's no longer necessary, since the identity doc
head is computed from available remotes.
While making those changes, it was also apparent that some of the
identity-related functions had bad names and error types, this
was fixed as well.
Previously, the seeds information would only consist of the connected
NodeIds.
Improve on this by adding any disconnected and fetching seeds as
well. A seed can either be disconnected, connected, or fetching --
where fetching implies connected.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
The Handle trait defines a FetchResult associated type. This type is
always instantiated to be the FetchResult enum in radicle::node.
Remove the associated type to simplify the trait.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
It's fairly easy for a user to (by mistake or intentionally) create two
operations with the same OpId. This patch makes it much less likely,
and ensures that if the OpId is equal, it's because the operations
are identical.
Improvements to the CLI output as well as converging towards
`termion` as a backend.
The crates we were using for prompting and spinners were based on
a terminal backend called `console`, which is not really used
anywhere else. There were also limitations in terms of the output
of these crates.
Therefore, we switched to the `inquire` crate for prompting, using
the `termion` backend, which is very standard.
Additionally, we simplify the terminal output to use symbols:
! for Warning
✓ for Success
✗ for Error
... Instead of a mix of words and symbols.
We also include a modified version of the `yansi` crate which plays
well with our table formatting functions by automatically truncating
and padding output in a unicode-aware way.
The olpc-json crate's CanonicalFormatter does not escape certain
control characters, including new lines. This means that when a COB
gets serialized that includes new lines, those new lines are
serialized verbatim. Upon deserialization `serde_json` -- and any
other JSON deserializer -- will fail due to the encounter of these
control characters.
This behaviour was prevented in radicle-link with the definition of
its own CanoncialFormatter that encodes the control characters
correctly.
Inline this definition of the formatter, under MIT license, to ensure
the correct and remove oplc-cjson.
The behaviour is checked using a multiline test in the issue COB.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
The `From` implementation would allow someone to create a `Home` in an
incorrect fashion, for example the path is not canonical.
Exchange `From` for a `TryFrom` implementation.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
Instead of showing just public keys we need to show the fully qualified
spec for a NID which is prefixed by `did🔑` While we want to maintain
`Author` and `ActorId` for internal use.
Signed-off-by: Sebastian Martinez <me@sebastinez.dev>
The CLI commands and output use PublicKey, ActorId, and NodeId for
peer identifiers.
Instead Did should be standardised for use in CLI arguments and
outputs.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
Add conversion from Did to PublicKey through a From implementation.
Add FromStr implementation.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
If a path was passed to `Home` in non-canonical form it would not use
the right path for any initialisation or use.
The aim is to use the `canonicalize` function for paths. However, this
may return an error if none of the paths exist. To ensure that the
path exists the `new` constructor for `Home` creates the directory and
canonicalizes the path.
Since `new` now initialises the home directory, it would be useful if
it also initialised all the necessary subdirectories -- which removes
the need for the `init` method.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
`Doc::commit` used `git2::Signature::now` when committing the document
to the repository. This results in the commits always changing and not
allowing us to test outputs of our CLI commands that would wish to
output the SHA.
Make `Doc::commit` reproducible in debug mode using `debug_assertions`
and checking the `RAD_COMMIT_TIME` environment variable.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
In order to make identity changes where the threshold is higher than
1, it is necessary to gather signatures of delegates to surpass that
threshold.
To achieve this the Proposal cob is introduced for proposing changes
and gathering the signatures over those changes.
Once a quorum is reached the Proposal can be published, committing the
new identity document to storage.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
The signatures for Radicle identities were using the documents
content.
It is standard to use the hash of the content instead, since signing
and verification is faster on a smaller set of data.
Use the resulting Git blob's object id, i.e. `git hash-object`, as the
signing and verifying payload.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
Rust 1.67 was announced[0]. Update the necessary files for running
1.67 and fix the clippy suggestions for string interpolation.
[0]: https://blog.rust-lang.org/2023/01/26/Rust-1.67.0.html
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
By allowing the node to run using a `MockSigner`, we speed up tests
significantly, since PBKDF2 doesn't need to run.
Signed-off-by: Alexis Sellier <self@cloudhead.io>
There are few unrelated changes in this commit that I wasn't able to
split out, mostly due to laziness, so I'll list them here:
* The node startup logic is moved out of the main function, and into a
dedicated functionin `client.rs`.
* There is a tentative worker implementation that is untested, and
handles git replication both ways. It's likely lacking in various ways
but I wanted to get it in there anyway.
* `Address` was moved from `radicle-node` to `radicle`, because it's
needed to send `Connect` commands from the node handle.
* The `netservices` dependency was updated.
* Finally, there is a first end-to-end node test, which currently
doesn't use NoiseXK, but uses the new reactor in `netservices`.
Signed-off-by: Alexis Sellier <self@cloudhead.io>
Make testing more convenient by reducing rad-remote-helper's dependency
on SSH Agent. It may be opted out of by setting the `RAD_PASSPHRASE`
environment variable.
Signed-off-by: Slack Coder <slackcoder@server.ky>
By using `0` as the clock value for an empty state (without operations),
we simplify transaction code. Previously, there was no clock value for
empty states, which meant that we had to sometimes use an `Option`.
* Move storage impl into `storage::cob`
* Rename `change::Create` to `change::Template`
* Rename `change::Storage::create` to `change::Storage::store`
Some of the renames are to further distinguish COBs from Changes, and
the different types of "create" operations within cobs.
Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
* Use the correct passphrase type everywhere
* Allow conversion of secret key
* Extract logic for storing a key in keystore
Signed-off-by: Alexis Sellier <self@cloudhead.io>
Adds a `rad delegate` CLI command.
The command consists of three subcommands:
* `add` -- add a new delegate to the set of delegates of a project
* `remove` -- remove an existing delegate from the set of delegates of a
project
* `list` -- list the delegates of a project
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
To ensure that signatures are unique for verifying an identity a
HashMap is used in place of a Vec of tuples.
This prevents any double counting for quorum checks.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
The `validate` method of `Project` was unused, which is problematic if
the attributes are supposed to be validated based on some
constraints. The issue is that `Project` provided public construction
of its fields with enforcing validation.
This change makes `Project`'s attributes private and introduces a
smart constructor `new` which is fallible if any of the constraints
are not met. The error type was changed to be a vector of errors since
all of these errors can be collected for better error reporting.
Deserialization also provided a way of constructing a `Project`
without ensuring any of the constraints were checked. To prevent this
a hand-rolled `Deserialize` is provided that goes through
`Project::new`.
To access the fields of `Project`, accessor functions are added and
all call sites are updated to use them.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
Allow assigning an issue to one or more people via a new subcommand.
rad assign <issue> <peer>
To unassign:
rad unassign <issue> <peer>
To support testing and documentation, create an example for maintaining
issues for a project.
Signed-off-by: Slack Coder <slackcoder@server.ky>
This implementation intentionally preserves all edits such that
they may be displayed in an application as an edit history.
Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
This makes a change to comments, such that all comments require a
parent, except the "root" comment, which is created with the COB.
Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
This is a large change that introduces transport encryption via
a Noise_XK handshake. The inner `Service` now works directly
with `NodeId` and doesn't need to interact with socket addresses.
The transport logic takes place in `wire::transport`, and the
established sessions are passed down to `Service`.
Note that the i/o implementation in the `poll-reactor` crate still
needs testing, and there is still work to be done to integrate the
Git transport as part of this architecture.
Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
In RIP-2, we specify that identity document root commits must include
the signature of all founding delegates.
This commit adds the required signatures during document creation
and verifies them on load.
Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
The new hierarchy should be much more correct, and cleaner:
* `identity` (`Identity`)
* `identity::did` (`Did`)
* `identity::doc` (`Doc`, `Payload`)
* `identity::doc::id` (`Id`)
* `identity::project` (`Project`)
Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
Use the BoundedVec to limit the supported number of refs in
RefAnnouncement messages. The size (235) is the maximum supported by
message wire size.
To reduce the complexity of the changes, BoundedVec is used again
instead of using a new bounded Refs or BTreeMap. This requires
defining new Decode/Encode logic for Ref's element types, and
workarounds for arbitrary instances.
Signed-off-by: Slack Coder <slackcoder@server.ky>
The tracking command was tracking a project when it should
have been tracking peers.
We also add the ability to pass an alias when tracking from
the CLI.
Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
This reverts to the previous naming, since after serialization
we would otherwise end up with `{ status: { status: closed } }`.
Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
These instances were not safe to have around, as they allow
removal of items in a non-commutative way.
Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
This was changed by mistake from the previous format used in radicle
link. We restore all keys to camel-case.
Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
Sometimes it is more efficient to perform multiple operations at once
and store those in the collaborative object graph together.
Change the contents to be a non-empty sequence of byte sequences,
i.e. NonEmpty<Vec<u8>>. These are stored as blobs in a git tree in
order by their index in the non-empty sequence. They are, in turn,
retrieved in order of their original index.
Change the conversion of an `EntryWithClock` to return a non-empty
sequence of `Op`s, which are in turn used to apply many changes in
each `from_history` implementation.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
We are working on other mechanisms to help identify keys, and this
is just redundant.
Also update some of the CLI examples to create a canonical example
for documentation.
Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
This will allow us to run commands other than `rad`
and to have tests that switch between different users.
Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
The latter is a fork of the former, which adds const generics
and a bunch of other quality of life improvements that aren't
in the original crate due to it being unmaintained.
Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
Helps with the confusion with `radicle_cob::Change` and matches the
name for this object in common literature.
Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
Since the underlying DAG guarantees causal event delivery,
we can rely on this to simplify the code.
Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
This was causing an issue in rust-analyzer, and probably would fail
in other ways via cargo. In any case it wasn't a good idea.
Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
Added the `parse_refname` function for parsing a reference into its
`TypeName` and `ObjectId`, if possible.
This replaces the `cob_suffix` function in `radicle`.
This change also fixes the `FromStr` instance of `ObjectId` to use
`from_str` instead of `TryFrom` for bytes.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
* Use the existing conventions for passing a signer to functions.
* Allow replacing git refs when updating cobs.
* Fix the parsing of a cob id.
Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
To wire up radicle-cob, it is necessary to implement the traits for
the following types:
* `Repository`: `change::Storage`, `object::Storage`, and `Store`
* `project::Identity`: `identity::Identity`
For `Repository`, the `change::Storage` implementation is trivial, as
it uses the underlying `git2::Repository` implementation. Then
`object::Storage` simply defines the required references names and
does lookups or updates.
The aforementioned reference naming scheme is:
refs/namespaces/<ns>/refs/cobs/<typename>/<object_id>
For `project::Identity`, the `identity::Identity` implementation is
straight-forward.
To finalise the work, a simplified API is exposed as `radicle::cob`
where the `create`, `update`, `get`, and `list` functions are
redefined in terms of `radicle` specific types.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
In interactive (user) contexts, use `try_sign` instead of `sign`.
We also revisit the `Profile` by adding a `signer` method that can
fail, eg. if we couldn't connect to ssh-agent.
Finally, we replace `UnsafeSigner` with `MemorySigner`, which makes
use of `ssh::Keystore`.
Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
To support ssh-agent, add a signing method that can fail.
Also cleanup usage so that we always accept signer references.
Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
We move the identity branch out of `heads/` and to the old location:
refs/rad/id
We move the signed refs branch to:
refs/rad/sigrefs
Keeping both "special" branches under the same hierarchy makes things a
bit easier to work with, and tells the user that they should be updated
with special tooling.
We also revert to `rad/` because we no longer have the issue of having
`rad/rad/id` when doing a checkout of the remote branch in a working
copy.
Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
Be careful about when to attempt creating a profile. Errors could
trigger creating a profile even when unrelated to it not existing.
Profile::load(..) is altered to distinguish between these cases.
Signed-off-by: Slack Coder <slackcoder@server.ky>
The crypto types are useful to use in other components that are
separate from the radicle crate, e.g. the incoming radicle-cobs
crate.
Separate out the types into a radicle-crypto crate. This crate defines
the usual PublicKey, SecretKey, and Signature types. It also provides
the ssh functionality, under the `ssh` feature. It is also necessary
to provide the `From` impl for `Component` here, which again is
guarded by the `git-ref-format` feature.
The `Arbitrary` implementation are moved. The arbitrary decision of
redefining `ByteArray` in both radicle-crypto and radicle was made.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
The changes in this commit are all intertwined and it was hard to
split them into smaller commits:
* Use custom transports everywhere
Instead of `file://` and instead of using a child process for fetching
and pushing; we go through our custom transports, which use the `rad://`
and `heartwood://` schemes.
* Introduce a 'mock' remote transport
To test the remote transport without needing to spawn TCP streams,
we add a mock transport that works between storages on the file
system.
* Get rid of node's `git-url`
Instead of git urls, nodes simply use their node-ids to replicate.
To distinguish between working-copy-to-storage (local) and
storage-to-storage (remote) replication, we create two new
URL types: a `remote::Url` (`heartwood://`) and a `local::Url`
(`rad://`).
These schemes are to be used for the remote and local transports,
respectively.
The difference between the two schemes is that remote replication
requires a node id.
Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
Since the `HEAD` reference is trusted (we set it locally), use that
when possible, instead of re-computing it.
Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
We set the `HEAD` and eg. `refs/heads/master` refs when updating
repositories, which allows users to easily clone with git.
For now, `HEAD` is chosen based on a unanimity quorum of delegates.
This can be made more sophisticated in the future.
We've also had to ignore some refs during verification, since these
have cropped in for eg. due to the staging copy clone and the
changes included here.
Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
We weren't including the *multicodec* bytes previously.
This is now tested against some test vectors from the spec.
Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
The `git-ref-format`[0] and `radicle-git-ext`[1] crates are now
published to crates.io.
Switch the dependency to rely on them. This also required to update
the `git2` dependency to `0.15.0` as well as using the
`vendored-libgit2` feature -- avoiding the openssl dependency too.
[0]: https://crates.io/crates/git-ref-format
[1]: https://crates.io/crates/radicle-git-ext
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
To build an address book, peers communicate via gossip, sending
`NodeAnnouncement` messages.
These need to be handled by storing the addresses in an address book
and the addresses need to be persisted to disk.
Node announcement messages should also be relayed to peers like other
gossip messages.
Armored signatures are used by Git for signing commits. Support reading
writing these signatures by implementing a new trait to read and write
to the SSH formmat.
Signed-off-by: Slack Coder <slackcoder@server.ky>
The `V` parameter of `Remote` is already determined by the `refs`
field. The `verified: PhantomData<V>` field is not required.
Remove the `verified` field to simplify the `Remote` struct.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
The previous iteration of the storage layout for projects organised
peer's subtrees by the `refs/remotes` category. This layout leads to
problems when linking a working copy to the storage project. The fetch
refspec would look something like:
fetch = +refs/remotes/abc/heads/*:refs/remotes/rad/*
This works perfectly fine when running:
git fetch rad
but will fail when one tries to specify:
git fetch rad main
Instead, the command would need to be:
git fetch remotes/abc/heads/main
This patch proposes to move the use of `refs/namespaces` for each
peer. The layout looks similar in that each peer has a subtree, but
instead it is under `refs/namespaces/<peer>/refs/...`.
The previous refspec would look more familiar in its new form:
fetch = +refs/heads/*:refs/remotes/rad/*
With this in place running:
git --namespace=abc rad main
Will work as expected and place the reference under
`refs/remotes/rad/main`. Similary, `git --namespace=abc push` will
work as expected.
Another benefit of this approach is that the use of namespacing means
that a tag is pushed it will be placed under the respective namespace
rather than in the global `refs/tags` category.
The actual implementation needed to work around the fact that
`git2`/`libgit2` does not have any options for fetching or pushing
using namespaces. The working copy code uses processes to shell out to
`git` for namespacing needs.
Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
To be able to support git commits with multiple signature
headers, we have to implement our own parsing and formatting.
Signed-off-by: Alexis Sellier <alexis@radicle.xyz>