Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
REVIEW: simplify `run` logic
Fintan Halpenny committed 6 months ago
commit ac0e58037bc447a2f4aa434e23757d40c0b4cb71
parent 34deb75896f4e1ff0bc300193eea7c48f1e67ec7
2 files changed +142 -100
modified crates/radicle-cli/src/commands/cob.rs
@@ -1,7 +1,6 @@
mod args;

-
use std::path::PathBuf;
-
use std::{fs, io};
+
use std::io;

use anyhow::{anyhow, bail};

@@ -33,39 +32,25 @@ pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {
    let storage = &profile.storage;

    match args.command {
-
        Create {
-
            repo,
-
            type_name,
-
            message,
-
            embed_file,
-
            embed_hash,
-
            actions,
-
        } => {
+
        Create(create) => {
            let signer = &profile.signer()?;
-
            let repo = storage.repository_mut(repo)?;
-
            let type_name = FilteredTypeName::from(type_name);
-

-
            let reader = io::BufReader::new(fs::File::open(actions)?);
-

-
            let embed_file = args::parse_many_embeds::<PathBuf>(&embed_file);
-
            let embed_hash = args::parse_many_embeds::<Rev>(&embed_hash);
-

-
            let embeds = embed_file
-
                .chain(embed_hash)
-
                .map(|embed| embed.try_into_bytes(&repo))
-
                .collect::<anyhow::Result<Vec<_>>>()?;
+
            let repo = storage.repository_mut(create.rid())?;
+
            let type_name = create.type_name();
+
            let reader = create.actions_reader()?;
+
            let message = create.message();
+
            let embeds = create.embeds(&repo)?;

            let oid = match type_name {
                Patch => {
                    let store: Store<cob::patch::Patch, _> = Store::open(&repo)?;
                    let actions = read_jsonl_actions(reader)?;
-
                    let (oid, _) = store.create(&message, actions, embeds, signer)?;
+
                    let (oid, _) = store.create(message, actions, embeds, signer)?;
                    oid
                }
                Issue => {
                    let store: Store<cob::issue::Issue, _> = Store::open(&repo)?;
                    let actions = read_jsonl_actions(reader)?;
-
                    let (oid, _) = store.create(&message, actions, embeds, signer)?;
+
                    let (oid, _) = store.create(message, actions, embeds, signer)?;
                    oid
                }
                Identity => anyhow::bail!(
@@ -76,7 +61,7 @@ pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {
                    let store: Store<cob::external::External, _> =
                        Store::open_for(&type_name, &repo)?;
                    let actions = read_jsonl_actions(reader)?;
-
                    let (oid, _) = store.create(&message, actions, embeds, signer)?;
+
                    let (oid, _) = store.create(message, actions, embeds, signer)?;
                    oid
                }
            };
@@ -165,36 +150,21 @@ pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {
                return Err(e);
            }
        }
-
        Update {
-
            repo,
-
            type_name,
-
            object,
-
            message,
-
            actions,
-
            embed_file,
-
            embed_hash,
-
            format: _,
-
        } => {
+
        Update(update) => {
            let signer = &profile.signer()?;
-
            let repo = storage.repository_mut(repo)?;
-
            let reader = io::BufReader::new(fs::File::open(actions)?);
-
            let oid = &object.resolve(&repo.backend)?;
-
            let type_name = FilteredTypeName::from(type_name);
-

-
            let embed_file = args::parse_many_embeds::<PathBuf>(&embed_file);
-
            let embed_hash = args::parse_many_embeds::<Rev>(&embed_hash);
-

-
            let embeds = embed_file
-
                .chain(embed_hash)
-
                .map(|embed| embed.try_into_bytes(&repo))
-
                .collect::<anyhow::Result<Vec<_>>>()?;
+
            let repo = storage.repository_mut(update.rid())?;
+
            let reader = update.actions_reader()?;
+
            let oid = &update.object(&repo)?;
+
            let type_name = update.type_name();
+
            let embeds = update.embeds(&repo)?;
+
            let message = update.message();

            let oid = match type_name {
                Patch => {
                    let actions: Vec<cob::patch::Action> = read_jsonl(reader)?;
                    let mut patches = profile.patches_mut(&repo)?;
                    let mut patch = patches.get_mut(oid)?;
-
                    patch.transaction(&message, &*profile.signer()?, |tx| {
+
                    patch.transaction(message, &*profile.signer()?, |tx| {
                        tx.extend(actions)?;
                        tx.embed(embeds)?;
                        Ok(())
@@ -204,7 +174,7 @@ pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {
                    let actions: Vec<cob::issue::Action> = read_jsonl(reader)?;
                    let mut issues = profile.issues_mut(&repo)?;
                    let mut issue = issues.get_mut(oid)?;
-
                    issue.transaction(&message, &*profile.signer()?, |tx| {
+
                    issue.transaction(message, &*profile.signer()?, |tx| {
                        tx.extend(actions)?;
                        tx.embed(embeds)?;
                        Ok(())
@@ -219,7 +189,7 @@ pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {
                    let actions: Vec<Action> = read_jsonl(reader)?;
                    let mut store: Store<External, _> = Store::open_for(&type_name, &repo)?;
                    let tx = cob::store::Transaction::new(type_name.clone(), actions, embeds);
-
                    let (_, oid) = tx.commit(&message, *oid, &mut store, signer)?;
+
                    let (_, oid) = tx.commit(message, *oid, &mut store, signer)?;
                    oid
                }
            };
modified crates/radicle-cli/src/commands/cob/args.rs
@@ -1,4 +1,6 @@
use std::fmt;
+
use std::fs;
+
use std::io;
use std::path::PathBuf;
use std::str::FromStr;

@@ -25,30 +27,7 @@ pub struct Args {
#[derive(Subcommand, Debug)]
pub(super) enum Command {
    /// Create a new COB of a given type given initial actions
-
    Create {
-
        /// Repository ID of the repository to operate on
-
        #[arg(long, short, value_name = "RID")]
-
        repo: RepoId,
-

-
        /// Typename of the object to create
-
        #[arg(long = "type", short, value_name = "TYPENAME")]
-
        type_name: cob::TypeName,
-

-
        /// Attach a message
-
        #[arg(long, short)]
-
        message: String,
-

-
        /// Supply embed of given name via file at given path
-
        #[arg(long, value_names = ["NAME", "PATH"], num_args = 2)]
-
        embed_file: Vec<String>,
-

-
        /// Supply embed of given name via object ID of blob
-
        #[arg(long, value_names = ["NAME", "OID"], num_args = 2)]
-
        embed_hash: Vec<String>,
-

-
        #[arg(value_name = "FILENAME")]
-
        actions: PathBuf,
-
    },
+
    Create(#[clap(flatten)] Create),

    /// List all COBs of a given type
    List {
@@ -111,38 +90,131 @@ pub(super) enum Command {
    },

    /// Add actions to a COB
-
    Update {
-
        /// Repository ID of the repository to operate on
-
        #[arg(long, short)]
-
        repo: RepoId,
+
    Update(#[clap(flatten)] Update),
+
}

-
        /// Typename of the object to update
-
        #[arg(long = "type", short, value_name = "TYPENAME")]
-
        type_name: cob::TypeName,
+
#[derive(Parser, Debug)]
+
pub(super) struct Create {
+
    /// Repository ID of the repository to operate on
+
    #[arg(long, short, value_name = "RID")]
+
    repo: RepoId,

-
        /// Object ID of the object to update
-
        #[arg(long, short, value_name = "OID")]
-
        object: Rev,
+
    /// Typename of the object to create
+
    #[arg(long = "type", short, value_name = "TYPENAME")]
+
    type_name: cob::TypeName,

-
        /// Attach a message
-
        #[arg(long, short)]
-
        message: String,
+
    /// Attach a message
+
    #[arg(long, short)]
+
    message: String,

-
        /// Supply embed of given name via file at given path
-
        #[arg(long, value_names = ["NAME", "PATH"], num_args = 2)]
-
        embed_file: Vec<String>,
+
    /// Supply embed of given name via file at given path
+
    #[arg(long, value_names = ["NAME", "PATH"], num_args = 2)]
+
    embed_file: Vec<String>,

-
        /// Supply embed of given name via object ID of blob
-
        #[arg(long, value_names = ["NAME", "OID"], num_args = 2)]
-
        embed_hash: Vec<String>,
+
    /// Supply embed of given name via object ID of blob
+
    #[arg(long, value_names = ["NAME", "OID"], num_args = 2)]
+
    embed_hash: Vec<String>,

-
        /// Desired output format
-
        #[arg(long, default_value_t = Format::Json, value_parser = FormatParser)]
-
        format: Format,
+
    #[arg(value_name = "FILENAME")]
+
    actions: PathBuf,
+
}

-
        #[arg(value_name = "FILENAME")]
-
        actions: PathBuf,
-
    },
+
impl Create {
+
    pub(super) fn rid(&self) -> RepoId {
+
        self.repo
+
    }
+

+
    pub(super) fn type_name(&self) -> FilteredTypeName {
+
        FilteredTypeName::from(self.type_name.clone())
+
    }
+

+
    pub(super) fn message(&self) -> &String {
+
        &self.message
+
    }
+

+
    pub(super) fn embeds(
+
        &self,
+
        repo: &storage::git::Repository,
+
    ) -> anyhow::Result<Vec<cob::Embed<cob::Uri>>> {
+
        parse_many_embeds::<PathBuf>(&self.embed_file)
+
            .chain(parse_many_embeds::<Rev>(&self.embed_hash))
+
            .map(|embed| embed.try_into_bytes(repo))
+
            .collect::<anyhow::Result<Vec<_>>>()
+
    }
+

+
    pub fn actions_reader(&self) -> io::Result<io::BufReader<fs::File>> {
+
        Ok(io::BufReader::new(fs::File::open(&self.actions)?))
+
    }
+
}
+

+
#[derive(Parser, Debug)]
+
pub(super) struct Update {
+
    /// Repository ID of the repository to operate on
+
    #[arg(long, short)]
+
    repo: RepoId,
+

+
    /// Typename of the object to update
+
    #[arg(long = "type", short, value_name = "TYPENAME")]
+
    type_name: cob::TypeName,
+

+
    /// Object ID of the object to update
+
    #[arg(long, short, value_name = "OID")]
+
    object: Rev,
+

+
    /// Attach a message
+
    #[arg(long, short)]
+
    message: String,
+

+
    /// Supply embed of given name via file at given path
+
    #[arg(long, value_names = ["NAME", "PATH"], num_args = 2)]
+
    embed_file: Vec<String>,
+

+
    /// Supply embed of given name via object ID of blob
+
    #[arg(long, value_names = ["NAME", "OID"], num_args = 2)]
+
    embed_hash: Vec<String>,
+

+
    // TODO(finto): `Format` is unused and is obsolete for this command
+
    /// Desired output format
+
    #[arg(long, default_value_t = Format::Json, value_parser = FormatParser)]
+
    format: Format,
+

+
    #[arg(value_name = "FILENAME")]
+
    actions: PathBuf,
+
}
+

+
impl Update {
+
    pub(super) fn rid(&self) -> RepoId {
+
        self.repo
+
    }
+

+
    pub(super) fn type_name(&self) -> FilteredTypeName {
+
        FilteredTypeName::from(self.type_name.clone())
+
    }
+

+
    pub(super) fn object(
+
        &self,
+
        repo: &storage::git::Repository,
+
    ) -> Result<cob::ObjectId, radicle::git::raw::Error> {
+
        self.object.resolve(&repo.backend)
+
    }
+

+
    pub(super) fn message(&self) -> &String {
+
        &self.message
+
    }
+

+
    pub(super) fn embeds(
+
        &self,
+
        repo: &storage::git::Repository,
+
    ) -> anyhow::Result<Vec<cob::Embed<cob::Uri>>> {
+
        parse_many_embeds::<PathBuf>(&self.embed_file)
+
            .chain(parse_many_embeds::<Rev>(&self.embed_hash))
+
            .map(|embed| embed.try_into_bytes(repo))
+
            .collect::<anyhow::Result<Vec<_>>>()
+
    }
+

+
    pub fn actions_reader(&self) -> io::Result<io::BufReader<fs::File>> {
+
        Ok(io::BufReader::new(fs::File::open(&self.actions)?))
+
    }
}

/// A precursor to [`cob::Embed`] used for parsing
@@ -164,7 +236,7 @@ impl Embed {
                content: hash.resolve::<git::Oid>(&repo.backend)?.into(),
            },
            EmbedContent::Path(path) => {
-
                cob::Embed::store(self.name, &std::fs::read(path)?, &repo.backend)?
+
                cob::Embed::store(self.name, &fs::read(path)?, &repo.backend)?
            }
        })
    }