cli: Move common functionality out of the CLI

This commit is contained in:
cloudhead 2024-06-08 21:43:52 +02:00
parent a6b5c723c8
commit 81f94d0cff
No known key found for this signature in database
5 changed files with 72 additions and 86 deletions

View File

@ -20,7 +20,6 @@ use radicle::node::{Event, Handle, NodeId, DEFAULT_SUBSCRIBE_TIMEOUT};
use radicle::prelude::Doc;
use radicle::{profile, Node};
use crate as cli;
use crate::commands;
use crate::git;
use crate::terminal as term;
@ -290,10 +289,10 @@ pub fn init(options: Options, profile: &profile::Profile) -> anyhow::Result<()>
// It's important to seed our own repositories to make sure that our node signals
// interest for them. This ensures that messages relating to them are relayed to us.
if options.seed {
cli::project::seed(rid, options.scope, &mut node, profile)?;
profile.seed(rid, options.scope, &mut node)?;
if doc.visibility.is_public() {
cli::project::add_inventory(rid, &mut node, profile)?;
profile.add_inventory(rid, &mut node)?;
}
}

View File

@ -10,8 +10,8 @@ use radicle_term::Element as _;
use crate::commands::rad_sync as sync;
use crate::node::SyncSettings;
use crate::terminal as term;
use crate::terminal::args::{Args, Error, Help};
use crate::{project, terminal as term};
pub const HELP: Help = Help {
name: "seed",
@ -134,7 +134,7 @@ pub fn update(
node: &mut Node,
profile: &Profile,
) -> Result<(), anyhow::Error> {
let updated = project::seed(rid, scope, node, profile)?;
let updated = profile.seed(rid, scope, node)?;
let outcome = if updated { "updated" } else { "exists" };
term::success!(
@ -145,17 +145,11 @@ pub fn update(
Ok(())
}
pub fn delete(rid: RepoId, node: &mut Node, profile: &Profile) -> anyhow::Result<()> {
if project::unseed(rid, node, profile)? {
term::success!("Seeding policy for {} removed", term::format::tertiary(rid));
}
Ok(())
}
pub fn seeding(profile: &Profile) -> anyhow::Result<()> {
let store = profile.policies()?;
let storage = &profile.storage;
let mut t = term::Table::new(term::table::TableOptions::bordered());
t.header([
term::format::default(String::from("Repository")),
term::format::default(String::from("Name")),

View File

@ -4,8 +4,8 @@ use anyhow::anyhow;
use radicle::{prelude::*, Node};
use crate::terminal as term;
use crate::terminal::args::{Args, Error, Help};
use crate::{project, terminal as term};
pub const HELP: Help = Help {
name: "unseed",
@ -72,7 +72,7 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
}
pub fn delete(rid: RepoId, node: &mut Node, profile: &Profile) -> anyhow::Result<()> {
if project::unseed(rid, node, profile)? {
if profile.unseed(rid, node)? {
term::success!("Seeding policy for {} removed", term::format::tertiary(rid));
}
Ok(())

View File

@ -1,11 +1,8 @@
use localtime::LocalTime;
use radicle::prelude::*;
use crate::git;
use radicle::git::RefStr;
use radicle::node::policy::Scope;
use radicle::node::{routing, Handle, NodeId};
use radicle::Node;
use radicle::node::NodeId;
/// Setup a repository remote and tracking branch.
pub struct SetupRemote<'a> {
@ -52,68 +49,3 @@ impl<'a> SetupRemote<'a> {
Ok((remote, None))
}
}
/// Add the repo to our inventory.
pub fn add_inventory(
rid: RepoId,
node: &mut Node,
profile: &Profile,
) -> Result<bool, anyhow::Error> {
match node.add_inventory(rid) {
Ok(updated) => Ok(updated),
Err(e) if e.is_connection_err() => {
let now = LocalTime::now();
let mut db = profile.database_mut()?;
let updates =
routing::Store::add_inventory(&mut db, [&rid], *profile.id(), now.into())?;
Ok(!updates.is_empty())
}
Err(e) => Err(e.into()),
}
}
/// Seed a repository by first trying to seed through the node, and if the node isn't running, by
/// updating the policy database directly. If the repo is available locally, we also add it to our
/// inventory.
pub fn seed(
rid: RepoId,
scope: Scope,
node: &mut Node,
profile: &Profile,
) -> Result<bool, anyhow::Error> {
match node.seed(rid, scope) {
Ok(updated) => Ok(updated),
Err(e) if e.is_connection_err() => {
let mut config = profile.policies_mut()?;
let result = config.seed(&rid, scope)?;
if result && profile.storage.contains(&rid)? {
let now = LocalTime::now();
let mut db = profile.database_mut()?;
routing::Store::add_inventory(&mut db, [&rid], *profile.id(), now.into())?;
}
Ok(result)
}
Err(e) => Err(e.into()),
}
}
/// Unseed a repository by first trying to unseed through the node, and if the node isn't running,
/// by updating the policy database directly.
pub fn unseed(rid: RepoId, node: &mut Node, profile: &Profile) -> Result<bool, anyhow::Error> {
match node.unseed(rid) {
Ok(updated) => Ok(updated),
Err(e) if e.is_connection_err() => {
let mut config = profile.policies_mut()?;
let result = config.unseed(&rid)?;
let mut db = profile.database_mut()?;
radicle::node::routing::Store::remove_inventory(&mut db, &rid, profile.id())?;
Ok(result)
}
Err(e) => Err(e.into()),
}
}

View File

@ -27,12 +27,12 @@ use crate::node::policy::config::store::Read;
use crate::node::{
notifications, policy,
policy::{Policy, Scope, SeedingPolicy},
Alias, AliasStore,
Alias, AliasStore, Handle as _, Node,
};
use crate::prelude::{Did, NodeId};
use crate::prelude::{Did, NodeId, RepoId};
use crate::storage::git::transport;
use crate::storage::git::Storage;
use crate::storage::ReadRepository;
use crate::storage::{ReadRepository, ReadStorage};
use crate::{cli, cob, git, node, storage, web};
/// Environment variables used by radicle.
@ -158,6 +158,10 @@ pub enum Error {
#[error(transparent)]
Config(#[from] ConfigError),
#[error(transparent)]
Node(#[from] node::Error),
#[error(transparent)]
Routing(#[from] node::routing::Error),
#[error(transparent)]
Keystore(#[from] keystore::Error),
#[error(transparent)]
MemorySigner(#[from] keystore::MemorySignerError),
@ -423,6 +427,63 @@ impl Profile {
Aliases { policies, db }
}
/// Add the repo to our inventory.
/// If the node is offline, adds it directly to the database.
pub fn add_inventory(&self, rid: RepoId, node: &mut Node) -> Result<bool, Error> {
match node.add_inventory(rid) {
Ok(updated) => Ok(updated),
Err(e) if e.is_connection_err() => {
let now = LocalTime::now();
let mut db = self.database_mut()?;
let updates =
node::routing::Store::add_inventory(&mut db, [&rid], *self.id(), now.into())?;
Ok(!updates.is_empty())
}
Err(e) => Err(e.into()),
}
}
/// Seed a repository by first trying to seed through the node, and if the node isn't running,
/// by updating the policy database directly. If the repo is available locally, we also add it
/// to our inventory.
pub fn seed(&self, rid: RepoId, scope: Scope, node: &mut Node) -> Result<bool, Error> {
match node.seed(rid, scope) {
Ok(updated) => Ok(updated),
Err(e) if e.is_connection_err() => {
let mut config = self.policies_mut()?;
let result = config.seed(&rid, scope)?;
if result && self.storage.contains(&rid)? {
let now = LocalTime::now();
let mut db = self.database_mut()?;
node::routing::Store::add_inventory(&mut db, [&rid], *self.id(), now.into())?;
}
Ok(result)
}
Err(e) => Err(e.into()),
}
}
/// Unseed a repository by first trying to unseed through the node, and if the node isn't
/// running, by updating the policy database directly.
pub fn unseed(&self, rid: RepoId, node: &mut Node) -> Result<bool, Error> {
match node.unseed(rid) {
Ok(updated) => Ok(updated),
Err(e) if e.is_connection_err() => {
let mut config = self.policies_mut()?;
let result = config.unseed(&rid)?;
let mut db = self.database_mut()?;
node::routing::Store::remove_inventory(&mut db, &rid, self.id())?;
Ok(result)
}
Err(e) => Err(e.into()),
}
}
}
impl std::ops::Deref for Profile {