Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
git: Use RefString types for git::refs
Slack Coder committed 3 years ago
commit f9ad3ac155e4428986b1cd4689807fd8c3288ae3
parent 48a5c75ae3257a830d43e2b845076557b2b07df1
12 files changed +67 -46
modified Cargo.lock
@@ -815,6 +815,7 @@ dependencies = [
 "colored",
 "crossbeam-channel",
 "fastrand",
+
 "git-ref-format",
 "lexopt",
 "log",
 "nakamoto-net",
@@ -839,6 +840,7 @@ name = "radicle-tools"
version = "0.2.0"
dependencies = [
 "anyhow",
+
 "git-ref-format",
 "radicle",
]

modified radicle-node/Cargo.toml
@@ -7,19 +7,20 @@ edition = "2021"

[dependencies]
anyhow = { version = "1" }
-
byteorder = { version = "1" }
bloomy = { version = "1.2" }
+
byteorder = { version = "1" }
chrono = { version = "0.4.0" }
colored = { version = "1.9.0" }
crossbeam-channel = { version = "0.5.6" }
fastrand = { version = "1.8.0" }
+
git-ref-format = { version = "0", features = ["serde", "macro"] }
lexopt = { version = "0.2.1" }
log = { version = "0.4.17", features = ["std"] }
-
serde = { version = "1", features = ["derive"] }
-
serde_json = { version = "1", features = ["preserve_order"] }
-
nonempty = { version = "0.8.0", features = ["serialize"] }
nakamoto-net = { version = "0.3.0" }
nakamoto-net-poll = { version = "0.3.0" }
+
nonempty = { version = "0.8.0", features = ["serialize"] }
+
serde = { version = "1", features = ["derive"] }
+
serde_json = { version = "1", features = ["preserve_order"] }
tempfile = { version = "3.3.0" }
thiserror = { version = "1" }

modified radicle-node/src/test/tests.rs
@@ -22,7 +22,7 @@ use crate::test::simulator;
use crate::test::simulator::{Peer as _, Simulation};
use crate::test::storage::MockStorage;
use crate::LocalTime;
-
use crate::{client, identity, rad, service, storage, test};
+
use crate::{client, git, identity, rad, service, test};

// NOTE
//
@@ -397,7 +397,7 @@ fn test_push_and_pull() {
        &repo,
        "alice",
        "alice's repo",
-
        storage::BranchName::from("master"),
+
        git::refname!("master"),
        alice.signer(),
        alice.storage(),
    )
modified radicle-tools/Cargo.toml
@@ -7,6 +7,7 @@ edition = "2021"

[dependencies]
anyhow = { version = "1" }
+
git-ref-format = { version = "0", features = ["serde", "macro"] }

[dependencies.radicle]
version = "0"
modified radicle-tools/src/rad-init.rs
@@ -1,5 +1,7 @@
use std::path::Path;

+
use radicle::git;
+

fn main() -> anyhow::Result<()> {
    let cwd = Path::new(".").canonicalize()?;
    let name = cwd.file_name().unwrap().to_string_lossy().to_string();
@@ -9,7 +11,7 @@ fn main() -> anyhow::Result<()> {
        &repo,
        &name,
        "",
-
        radicle::git::BranchName::from("master"),
+
        git::refname!("master"),
        &profile.signer,
        &profile.storage,
    )?;
modified radicle/src/git.rs
@@ -16,7 +16,7 @@ pub use ext::Error;
pub use ext::Oid;
pub use git2 as raw;
pub use git_ref_format as fmt;
-
pub use git_ref_format::{refname, RefStr, RefString};
+
pub use git_ref_format::{refname, Component, Qualified, RefStr, RefString};
pub use git_url as url;
pub use git_url::Url;
pub use radicle_git_ext as ext;
@@ -41,6 +41,13 @@ pub enum ListRefsError {
    InvalidRef(#[from] RefError),
}

+
impl From<&RemoteId> for RefString {
+
    fn from(id: &RemoteId) -> Self {
+
        // PublicKey strings contain only legal characters.
+
        RefString::try_from(id.to_string()).unwrap()
+
    }
+
}
+

pub mod refs {
    use super::*;

@@ -50,31 +57,36 @@ pub mod refs {
    pub mod storage {
        use super::*;

-
        pub fn branch(remote: &RemoteId, branch: &str) -> String {
-
            format!("refs/remotes/{remote}/heads/{branch}")
+
        pub fn branch(remote: &RemoteId, branch: &RefStr) -> RefString {
+
            refname!("refs/remotes")
+
                .and::<RefString>(remote.into())
+
                .and(refname!("heads"))
+
                .and(branch)
        }

        /// Get the branch used to track project information.
-
        pub fn id(remote: &RemoteId) -> String {
+
        pub fn id(remote: &RemoteId) -> RefString {
            branch(remote, &IDENTITY_BRANCH)
        }
    }

    pub mod workdir {
-
        pub fn branch(branch: &str) -> String {
-
            format!("refs/heads/{branch}")
+
        use super::*;
+

+
        pub fn branch(branch: &RefStr) -> RefString {
+
            refname!("refs/heads").join(branch)
        }

-
        pub fn note(name: &str) -> String {
-
            format!("refs/notes/{name}")
+
        pub fn note(name: &RefStr) -> RefString {
+
            refname!("refs/notes").join(name)
        }

-
        pub fn remote_branch(remote: &str, branch: &str) -> String {
-
            format!("refs/remotes/{remote}/{branch}")
+
        pub fn remote_branch(remote: &RefStr, branch: &RefStr) -> RefString {
+
            refname!("refs/remotes").and(remote).and(branch)
        }

-
        pub fn tag(name: &str) -> String {
-
            format!("refs/tags/{name}")
+
        pub fn tag(name: &RefStr) -> RefString {
+
            refname!("refs/tags").join(name)
        }
    }
}
modified radicle/src/identity/project.rs
@@ -71,8 +71,8 @@ impl From<Delegate> for PublicKey {
#[serde(rename_all = "kebab-case")]
pub struct Payload {
    pub name: String,
-
    pub description: String,    // TODO: Make optional.
-
    pub default_branch: String, // TODO: Make optional.
+
    pub description: String,            // TODO: Make optional.
+
    pub default_branch: git::RefString, // TODO: Make optional.
}

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
modified radicle/src/rad.rs
@@ -3,6 +3,7 @@ use std::io;
use std::path::Path;
use std::str::FromStr;

+
use once_cell::sync::Lazy;
use thiserror::Error;

use crate::crypto::{Signer, Verified};
@@ -13,7 +14,7 @@ use crate::storage::refs::SignedRefs;
use crate::storage::{BranchName, ReadRepository as _, RemoteId, WriteRepository as _};
use crate::{identity, storage};

-
pub const REMOTE_NAME: &str = "rad";
+
pub static REMOTE_NAME: Lazy<git::RefString> = Lazy::new(|| git::refname!("rad"));

#[derive(Error, Debug)]
pub enum InitError {
@@ -63,7 +64,7 @@ pub fn init<G: Signer, S: storage::WriteStorage>(

    git::set_upstream(
        repo,
-
        REMOTE_NAME,
+
        &REMOTE_NAME,
        &default_branch,
        &git::refs::storage::branch(pk, &default_branch),
    )?;
@@ -71,7 +72,7 @@ pub fn init<G: Signer, S: storage::WriteStorage>(
    // TODO: Note that you'll likely want to use `RemoteCallbacks` and set
    // `push_update_reference` to test whether all the references were pushed
    // successfully.
-
    git::configure_remote(repo, REMOTE_NAME, pk, &url)?.push::<&str>(
+
    git::configure_remote(repo, &REMOTE_NAME, pk, &url)?.push::<&str>(
        &[&format!(
            "{}:{}",
            &git::refs::workdir::branch(&default_branch),
@@ -276,24 +277,24 @@ pub fn checkout<P: AsRef<Path>, S: storage::ReadStorage>(
    opts.no_reinit(true).description(&project.description);

    let repo = git2::Repository::init_opts(path, &opts)?;
-
    let default_branch = project.default_branch.as_str();
    let url = storage.url(&proj);

    // Configure and fetch all refs from remote.
-
    git::configure_remote(&repo, REMOTE_NAME, remote, &url)?.fetch::<&str>(&[], None, None)?;
+
    git::configure_remote(&repo, &REMOTE_NAME, remote, &url)?.fetch::<&str>(&[], None, None)?;

    {
        // Setup default branch.
-
        let remote_head_ref = git::refs::workdir::remote_branch(REMOTE_NAME, default_branch);
+
        let remote_head_ref =
+
            git::refs::workdir::remote_branch(&REMOTE_NAME, &project.default_branch);
        let remote_head_commit = repo.find_reference(&remote_head_ref)?.peel_to_commit()?;
-
        let _ = repo.branch(default_branch, &remote_head_commit, true)?;
+
        let _ = repo.branch(&project.default_branch, &remote_head_commit, true)?;

        // Setup remote tracking for default branch.
        git::set_upstream(
            &repo,
-
            REMOTE_NAME,
-
            default_branch,
-
            &git::refs::storage::branch(remote, default_branch),
+
            &REMOTE_NAME,
+
            &project.default_branch,
+
            &git::refs::storage::branch(remote, &project.default_branch),
        )?;
    }

@@ -302,7 +303,7 @@ pub fn checkout<P: AsRef<Path>, S: storage::ReadStorage>(

/// Get the radicle ("rad") remote of a repository, and return the associated project id.
pub fn remote(repo: &git2::Repository) -> Result<(git2::Remote<'_>, Id), git2::Error> {
-
    let remote = repo.find_remote(REMOTE_NAME)?;
+
    let remote = repo.find_remote(&REMOTE_NAME)?;
    let url = remote.url_bytes();
    let url = git::Url::from_bytes(url).unwrap();
    let path = url.path.to_string();
@@ -335,7 +336,7 @@ mod tests {
            &repo,
            "acme",
            "Acme's repo",
-
            BranchName::from("master"),
+
            git::refname!("master"),
            &signer,
            &storage,
        )
@@ -353,7 +354,7 @@ mod tests {
        assert_eq!(remotes[&public_key].refs, refs);
        assert_eq!(project.name, "acme");
        assert_eq!(project.description, "Acme's repo");
-
        assert_eq!(project.default_branch, BranchName::from("master"));
+
        assert_eq!(project.default_branch, git::refname!("master"));
        assert_eq!(
            project.delegates.first(),
            &Delegate {
@@ -378,7 +379,7 @@ mod tests {
            &original,
            "acme",
            "Acme's repo",
-
            BranchName::from("master"),
+
            git::refname!("master"),
            &alice,
            &storage,
        )
@@ -408,7 +409,7 @@ mod tests {
            &original,
            "acme",
            "Acme's repo",
-
            BranchName::from("master"),
+
            git::refname!("master"),
            &signer,
            &storage,
        )
@@ -430,14 +431,14 @@ mod tests {
                .to_vec()
        );
        assert_eq!(
-
            copy.find_remote(REMOTE_NAME)
+
            copy.find_remote(&REMOTE_NAME)
                .unwrap()
                .refspecs()
                .into_iter()
                .map(|r| r.bytes().to_vec())
                .collect::<Vec<_>>(),
            original
-
                .find_remote(REMOTE_NAME)
+
                .find_remote(&REMOTE_NAME)
                .unwrap()
                .refspecs()
                .into_iter()
modified radicle/src/storage.rs
@@ -24,7 +24,7 @@ use crate::storage::refs::Refs;

use self::refs::SignedRefs;

-
pub type BranchName = String;
+
pub type BranchName = git::RefString;
pub type Inventory = Vec<Id>;

/// Storage error.
modified radicle/src/storage/git.rs
@@ -810,7 +810,7 @@ mod tests {
            &source,
            "radicle",
            "radicle",
-
            BranchName::from("master"),
+
            git::refname!("master"),
            signer,
            &storage,
        )
modified radicle/src/test/arbitrary.rs
@@ -85,7 +85,7 @@ impl Arbitrary for Doc<Unverified> {
    fn arbitrary(g: &mut quickcheck::Gen) -> Self {
        let name = String::arbitrary(g);
        let description = String::arbitrary(g);
-
        let default_branch = String::arbitrary(g);
+
        let default_branch = git::RefString::try_from(String::arbitrary(g)).unwrap();
        let delegate = Delegate::arbitrary(g);

        Self::initial(name, description, default_branch, delegate)
@@ -101,9 +101,11 @@ impl Arbitrary for Doc<Verified> {
        let description = iter::repeat_with(|| rng.alphanumeric())
            .take(rng.usize(0..32))
            .collect();
-
        let default_branch = iter::repeat_with(|| rng.alphanumeric())
+
        let default_branch: git::RefString = iter::repeat_with(|| rng.alphanumeric())
            .take(rng.usize(1..16))
-
            .collect();
+
            .collect::<String>()
+
            .try_into()
+
            .unwrap();
        let delegates: NonEmpty<_> = iter::repeat_with(|| Delegate {
            name: iter::repeat_with(|| rng.alphanumeric())
                .take(rng.usize(1..16))
modified radicle/src/test/fixtures.rs
@@ -6,7 +6,7 @@ use crate::identity::Id;
use crate::rad;
use crate::storage::git::Storage;
use crate::storage::refs::SignedRefs;
-
use crate::storage::{BranchName, WriteStorage};
+
use crate::storage::WriteStorage;

/// Create a new storage with a project.
pub fn storage<P: AsRef<Path>, G: Signer>(path: P, signer: G) -> Result<Storage, rad::InitError> {
@@ -23,7 +23,7 @@ pub fn storage<P: AsRef<Path>, G: Signer>(path: P, signer: G) -> Result<Storage,
            &repo,
            name,
            desc,
-
            BranchName::from("master"),
+
            git::refname!("master"),
            &signer,
            &storage,
        )?;
@@ -43,7 +43,7 @@ pub fn project<P: AsRef<Path>, S: WriteStorage, G: Signer>(
        &repo,
        "acme",
        "Acme's repository",
-
        BranchName::from("master"),
+
        git::refname!("master"),
        signer,
        storage,
    )?;