Move `radicle/id` and `radicle/signature`
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>
This commit is contained in:
parent
25c982cd8c
commit
16b22d9178
|
|
@ -19,7 +19,7 @@ pub use ext::Oid;
|
||||||
pub use git2 as raw;
|
pub use git2 as raw;
|
||||||
pub use git_ref_format as fmt;
|
pub use git_ref_format as fmt;
|
||||||
pub use git_ref_format::{
|
pub use git_ref_format::{
|
||||||
lit, name, qualified, refname, Component, Namespaced, Qualified, RefStr, RefString,
|
component, lit, name, qualified, refname, Component, Namespaced, Qualified, RefStr, RefString,
|
||||||
};
|
};
|
||||||
pub use radicle_git_ext as ext;
|
pub use radicle_git_ext as ext;
|
||||||
pub use storage::git::transport::local::Url;
|
pub use storage::git::transport::local::Url;
|
||||||
|
|
@ -59,9 +59,6 @@ pub enum ListRefsError {
|
||||||
pub mod refs {
|
pub mod refs {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
/// Where project information is kept.
|
|
||||||
pub static IDENTITY_BRANCH: Lazy<RefString> = Lazy::new(|| refname!("radicle/id"));
|
|
||||||
|
|
||||||
/// Try to get a qualified reference from a generic reference.
|
/// Try to get a qualified reference from a generic reference.
|
||||||
pub fn qualified_from<'a>(r: &'a git2::Reference) -> Result<(Qualified<'a>, Oid), RefError> {
|
pub fn qualified_from<'a>(r: &'a git2::Reference) -> Result<(Qualified<'a>, Oid), RefError> {
|
||||||
let name = r.name().ok_or(RefError::InvalidName)?;
|
let name = r.name().ok_or(RefError::InvalidName)?;
|
||||||
|
|
@ -78,17 +75,36 @@ pub mod refs {
|
||||||
pub mod storage {
|
pub mod storage {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
/// Where the project's identity document is stored.
|
||||||
|
///
|
||||||
|
/// `refs/rad/id`
|
||||||
|
///
|
||||||
|
pub static IDENTITY_BRANCH: Lazy<Qualified> = Lazy::new(|| {
|
||||||
|
Qualified::from_components(name::component!("rad"), name::component!("id"), None)
|
||||||
|
});
|
||||||
|
|
||||||
|
/// Where the project's signed references are stored.
|
||||||
|
///
|
||||||
|
/// `refs/rad/sigrefs`
|
||||||
|
///
|
||||||
|
pub static SIGREFS_BRANCH: Lazy<Qualified> = Lazy::new(|| {
|
||||||
|
Qualified::from_components(name::component!("rad"), name::component!("sigrefs"), None)
|
||||||
|
});
|
||||||
|
|
||||||
/// Create the [`Namespaced`] `branch` under the `remote` namespace, i.e.
|
/// Create the [`Namespaced`] `branch` under the `remote` namespace, i.e.
|
||||||
|
///
|
||||||
/// `refs/namespaces/<remote>/refs/heads/<branch>`
|
/// `refs/namespaces/<remote>/refs/heads/<branch>`
|
||||||
|
///
|
||||||
pub fn branch<'a>(remote: &RemoteId, branch: &RefStr) -> Namespaced<'a> {
|
pub fn branch<'a>(remote: &RemoteId, branch: &RefStr) -> Namespaced<'a> {
|
||||||
Qualified::from(git_ref_format::lit::refs_heads(branch)).with_namespace(remote.into())
|
Qualified::from(git_ref_format::lit::refs_heads(branch)).with_namespace(remote.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the branch used to track project information.
|
/// Get the branch where the project's identity document is stored.
|
||||||
|
///
|
||||||
|
/// `refs/namespaces/<remote>/refs/rad/id`
|
||||||
///
|
///
|
||||||
/// `refs/namespaces/<remote>/refs/heads/radicle/id`
|
|
||||||
pub fn id(remote: &RemoteId) -> Namespaced {
|
pub fn id(remote: &RemoteId) -> Namespaced {
|
||||||
branch(remote, &IDENTITY_BRANCH)
|
IDENTITY_BRANCH.with_namespace(remote.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,9 +31,11 @@ pub struct Untrusted;
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct Trusted;
|
pub struct Trusted;
|
||||||
|
|
||||||
|
/// Path to the identity document in the identity branch.
|
||||||
pub static PATH: Lazy<&Path> = Lazy::new(|| Path::new("radicle.json"));
|
pub static PATH: Lazy<&Path> = Lazy::new(|| Path::new("radicle.json"));
|
||||||
|
/// Maximum length of a string in the identity document.
|
||||||
pub const MAX_STRING_LENGTH: usize = 255;
|
pub const MAX_STRING_LENGTH: usize = 255;
|
||||||
|
/// Maximum number of a delegates in the identity document.
|
||||||
pub const MAX_DELEGATES: usize = 255;
|
pub const MAX_DELEGATES: usize = 255;
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
|
|
@ -148,11 +150,6 @@ impl Doc<Verified> {
|
||||||
msg: &str,
|
msg: &str,
|
||||||
storage: &S,
|
storage: &S,
|
||||||
) -> Result<(Id, git::Oid, S::Repository), DocError> {
|
) -> Result<(Id, git::Oid, S::Repository), DocError> {
|
||||||
// You can checkout this branch in your working copy with:
|
|
||||||
//
|
|
||||||
// git fetch rad
|
|
||||||
// git checkout -b radicle/id remotes/rad/radicle/id
|
|
||||||
//
|
|
||||||
let (doc_oid, doc) = self.encode()?;
|
let (doc_oid, doc) = self.encode()?;
|
||||||
let id = Id::from(doc_oid);
|
let id = Id::from(doc_oid);
|
||||||
let repo = storage.repository(id)?;
|
let repo = storage.repository(id)?;
|
||||||
|
|
@ -358,8 +355,8 @@ impl Doc<Unverified> {
|
||||||
|
|
||||||
impl<V> Doc<V> {
|
impl<V> Doc<V> {
|
||||||
pub fn head<R: ReadRepository>(remote: &RemoteId, repo: &R) -> Result<Oid, DocError> {
|
pub fn head<R: ReadRepository>(remote: &RemoteId, repo: &R) -> Result<Oid, DocError> {
|
||||||
let head = git::Qualified::from(git::lit::refs_heads(&*git::refs::IDENTITY_BRANCH));
|
repo.reference_oid(remote, &git::refs::storage::IDENTITY_BRANCH)
|
||||||
repo.reference_oid(remote, &head).map_err(DocError::from)
|
.map_err(DocError::from)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -122,7 +122,7 @@ pub fn fork_remote<G: Signer, S: storage::WriteStorage>(
|
||||||
// Creates or copies the following references:
|
// Creates or copies the following references:
|
||||||
//
|
//
|
||||||
// refs/remotes/<pk>/heads/master
|
// refs/remotes/<pk>/heads/master
|
||||||
// refs/remotes/<pk>/heads/radicle/id
|
// refs/remotes/<pk>/rad/id
|
||||||
// refs/remotes/<pk>/tags/*
|
// refs/remotes/<pk>/tags/*
|
||||||
// refs/remotes/<pk>/rad/signature
|
// refs/remotes/<pk>/rad/signature
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,10 +24,10 @@ pub use crate::git::*;
|
||||||
use super::{Namespaces, RefUpdate, RemoteId};
|
use super::{Namespaces, RefUpdate, RemoteId};
|
||||||
use transport::remote;
|
use transport::remote;
|
||||||
|
|
||||||
pub static REMOTES_GLOB: Lazy<refspec::PatternString> =
|
pub static NAMESPACES_GLOB: Lazy<refspec::PatternString> =
|
||||||
Lazy::new(|| refspec::pattern!("refs/namespaces/*"));
|
Lazy::new(|| refspec::pattern!("refs/namespaces/*"));
|
||||||
pub static SIGNATURES_GLOB: Lazy<refspec::PatternString> =
|
pub static SIGREFS_GLOB: Lazy<refspec::PatternString> =
|
||||||
Lazy::new(|| refspec::pattern!("refs/namespaces/*/radicle/signature"));
|
Lazy::new(|| refspec::pattern!("refs/namespaces/*/rad/sigrefs"));
|
||||||
|
|
||||||
// TODO: Is this is the wrong place for this type?
|
// TODO: Is this is the wrong place for this type?
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
|
|
@ -309,7 +309,7 @@ impl Repository {
|
||||||
pub fn remote_ids(
|
pub fn remote_ids(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<impl Iterator<Item = Result<RemoteId, refs::Error>> + '_, git2::Error> {
|
) -> Result<impl Iterator<Item = Result<RemoteId, refs::Error>> + '_, git2::Error> {
|
||||||
let iter = self.backend.references_glob(SIGNATURES_GLOB.as_str())?.map(
|
let iter = self.backend.references_glob(SIGREFS_GLOB.as_str())?.map(
|
||||||
|reference| -> Result<RemoteId, refs::Error> {
|
|reference| -> Result<RemoteId, refs::Error> {
|
||||||
let r = reference?;
|
let r = reference?;
|
||||||
let name = r.name().ok_or(refs::Error::InvalidRef)?;
|
let name = r.name().ok_or(refs::Error::InvalidRef)?;
|
||||||
|
|
@ -327,16 +327,17 @@ impl Repository {
|
||||||
impl Iterator<Item = Result<(RemoteId, Remote<Verified>), refs::Error>> + '_,
|
impl Iterator<Item = Result<(RemoteId, Remote<Verified>), refs::Error>> + '_,
|
||||||
git2::Error,
|
git2::Error,
|
||||||
> {
|
> {
|
||||||
let remotes = self.backend.references_glob(SIGNATURES_GLOB.as_str())?.map(
|
let remotes =
|
||||||
|reference| -> Result<_, _> {
|
self.backend
|
||||||
let r = reference?;
|
.references_glob(SIGREFS_GLOB.as_str())?
|
||||||
let name = r.name().ok_or(refs::Error::InvalidRef)?;
|
.map(|reference| -> Result<_, _> {
|
||||||
let (id, _) = git::parse_ref_namespaced::<RemoteId>(name)?;
|
let r = reference?;
|
||||||
let remote = self.remote(&id)?;
|
let name = r.name().ok_or(refs::Error::InvalidRef)?;
|
||||||
|
let (id, _) = git::parse_ref_namespaced::<RemoteId>(name)?;
|
||||||
|
let remote = self.remote(&id)?;
|
||||||
|
|
||||||
Ok((id, remote))
|
Ok((id, remote))
|
||||||
},
|
});
|
||||||
);
|
|
||||||
Ok(remotes)
|
Ok(remotes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -358,7 +359,7 @@ impl Repository {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
|
|
||||||
if refname == *refs::SIGNATURE_REF {
|
if refname == *refs::SIGREFS_BRANCH {
|
||||||
// Ignore the signed-refs reference, as this is what we're verifying.
|
// Ignore the signed-refs reference, as this is what we're verifying.
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
|
@ -714,7 +715,7 @@ mod tests {
|
||||||
use crate::assert_matches;
|
use crate::assert_matches;
|
||||||
use crate::git;
|
use crate::git;
|
||||||
use crate::rad;
|
use crate::rad;
|
||||||
use crate::storage::refs::SIGNATURE_REF;
|
use crate::storage::refs::SIGREFS_BRANCH;
|
||||||
use crate::storage::{ReadRepository, ReadStorage, RefUpdate, WriteRepository};
|
use crate::storage::{ReadRepository, ReadStorage, RefUpdate, WriteRepository};
|
||||||
use crate::test::arbitrary;
|
use crate::test::arbitrary;
|
||||||
use crate::test::fixtures;
|
use crate::test::fixtures;
|
||||||
|
|
@ -733,7 +734,7 @@ mod tests {
|
||||||
|
|
||||||
// Strip the remote refs of sigrefs so we can compare them.
|
// Strip the remote refs of sigrefs so we can compare them.
|
||||||
for remote in refs.values_mut() {
|
for remote in refs.values_mut() {
|
||||||
let sigref = (*SIGNATURE_REF).to_ref_string();
|
let sigref = (*SIGREFS_BRANCH).to_ref_string();
|
||||||
remote.remove(&sigref).unwrap();
|
remote.remove(&sigref).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -866,7 +867,7 @@ mod tests {
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
refs.sort();
|
refs.sort();
|
||||||
|
|
||||||
assert_eq!(refs, vec!["refs/heads/master", "refs/heads/radicle/id"]);
|
assert_eq!(refs, vec!["refs/heads/master", "refs/rad/id"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -972,8 +973,8 @@ mod tests {
|
||||||
updates,
|
updates,
|
||||||
vec![
|
vec![
|
||||||
format!("refs/namespaces/{remote}/refs/heads/master"),
|
format!("refs/namespaces/{remote}/refs/heads/master"),
|
||||||
format!("refs/namespaces/{remote}/refs/heads/radicle/id"),
|
format!("refs/namespaces/{remote}/refs/rad/id"),
|
||||||
format!("refs/namespaces/{remote}/refs/radicle/signature")
|
format!("refs/namespaces/{remote}/refs/rad/sigrefs")
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -1005,7 +1006,7 @@ mod tests {
|
||||||
let mut unsigned = project.references(&alice).unwrap();
|
let mut unsigned = project.references(&alice).unwrap();
|
||||||
|
|
||||||
// The signed refs doesn't contain the signature ref itself.
|
// The signed refs doesn't contain the signature ref itself.
|
||||||
let sigref = (*SIGNATURE_REF).to_ref_string();
|
let sigref = (*SIGREFS_BRANCH).to_ref_string();
|
||||||
unsigned.remove(&sigref).unwrap();
|
unsigned.remove(&sigref).unwrap();
|
||||||
|
|
||||||
assert_eq!(remote.refs, signed);
|
assert_eq!(remote.refs, signed);
|
||||||
|
|
|
||||||
|
|
@ -8,23 +8,19 @@ use std::path::Path;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use crypto::{PublicKey, Signature, Signer, Unverified, Verified};
|
use crypto::{PublicKey, Signature, Signer, Unverified, Verified};
|
||||||
use once_cell::sync::Lazy;
|
|
||||||
use radicle_git_ext as git_ext;
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::git;
|
use crate::git;
|
||||||
|
use crate::git::ext as git_ext;
|
||||||
use crate::git::Oid;
|
use crate::git::Oid;
|
||||||
use crate::storage;
|
use crate::storage;
|
||||||
use crate::storage::{ReadRepository, RemoteId, WriteRepository};
|
use crate::storage::{ReadRepository, RemoteId, WriteRepository};
|
||||||
|
|
||||||
pub static SIGNATURE_REF: Lazy<git::Qualified> = Lazy::new(|| {
|
pub use crate::git::refs::storage::*;
|
||||||
git::Qualified::from_components(
|
|
||||||
git::name::component!("radicle"),
|
/// File in which the signed references are stored, in the `refs/rad/sigrefs` branch.
|
||||||
git::name::component!("signature"),
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
});
|
|
||||||
pub const REFS_BLOB_PATH: &str = "refs";
|
pub const REFS_BLOB_PATH: &str = "refs";
|
||||||
|
/// File in which the signature over the references is stored in the `refs/rad/sigrefs` branch.
|
||||||
pub const SIGNATURE_BLOB_PATH: &str = "signature";
|
pub const SIGNATURE_BLOB_PATH: &str = "signature";
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
@ -129,7 +125,7 @@ impl Refs {
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
let refs = self
|
let refs = self
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(name, oid)| name.as_refstr() != (*SIGNATURE_REF).as_ref() && !oid.is_zero());
|
.filter(|(name, oid)| name.as_refstr() != SIGREFS_BRANCH.as_ref() && !oid.is_zero());
|
||||||
|
|
||||||
for (name, oid) in refs {
|
for (name, oid) in refs {
|
||||||
buf.push_str(&oid.to_string());
|
buf.push_str(&oid.to_string());
|
||||||
|
|
@ -231,7 +227,7 @@ impl SignedRefs<Verified> {
|
||||||
where
|
where
|
||||||
S: ReadRepository,
|
S: ReadRepository,
|
||||||
{
|
{
|
||||||
let oid = repo.reference_oid(remote, &SIGNATURE_REF)?;
|
let oid = repo.reference_oid(remote, &SIGREFS_BRANCH)?;
|
||||||
|
|
||||||
SignedRefs::load_at(oid, remote, repo)
|
SignedRefs::load_at(oid, remote, repo)
|
||||||
}
|
}
|
||||||
|
|
@ -266,7 +262,7 @@ impl SignedRefs<Verified> {
|
||||||
remote: &RemoteId,
|
remote: &RemoteId,
|
||||||
repo: &S,
|
repo: &S,
|
||||||
) -> Result<Updated, Error> {
|
) -> Result<Updated, Error> {
|
||||||
let sigref = &*SIGNATURE_REF;
|
let sigref = &SIGREFS_BRANCH;
|
||||||
let parent = match repo.reference(remote, sigref) {
|
let parent = match repo.reference(remote, sigref) {
|
||||||
Ok(r) => Some(r.peel_to_commit()?),
|
Ok(r) => Some(r.peel_to_commit()?),
|
||||||
Err(git_ext::Error::Git(e)) if git_ext::is_not_found_err(&e) => None,
|
Err(git_ext::Error::Git(e)) if git_ext::is_not_found_err(&e) => None,
|
||||||
|
|
|
||||||
|
|
@ -152,7 +152,7 @@ impl Arbitrary for Refs {
|
||||||
"heads/feature/1",
|
"heads/feature/1",
|
||||||
"heads/feature/2",
|
"heads/feature/2",
|
||||||
"heads/feature/3",
|
"heads/feature/3",
|
||||||
"heads/radicle/id",
|
"rad/id",
|
||||||
"tags/v1.0",
|
"tags/v1.0",
|
||||||
"tags/v2.0",
|
"tags/v2.0",
|
||||||
"notes/1",
|
"notes/1",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue