cli: Move common functionality out of the CLI
This commit is contained in:
parent
a6b5c723c8
commit
81f94d0cff
|
|
@ -20,7 +20,6 @@ use radicle::node::{Event, Handle, NodeId, DEFAULT_SUBSCRIBE_TIMEOUT};
|
||||||
use radicle::prelude::Doc;
|
use radicle::prelude::Doc;
|
||||||
use radicle::{profile, Node};
|
use radicle::{profile, Node};
|
||||||
|
|
||||||
use crate as cli;
|
|
||||||
use crate::commands;
|
use crate::commands;
|
||||||
use crate::git;
|
use crate::git;
|
||||||
use crate::terminal as term;
|
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
|
// 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.
|
// interest for them. This ensures that messages relating to them are relayed to us.
|
||||||
if options.seed {
|
if options.seed {
|
||||||
cli::project::seed(rid, options.scope, &mut node, profile)?;
|
profile.seed(rid, options.scope, &mut node)?;
|
||||||
|
|
||||||
if doc.visibility.is_public() {
|
if doc.visibility.is_public() {
|
||||||
cli::project::add_inventory(rid, &mut node, profile)?;
|
profile.add_inventory(rid, &mut node)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,8 @@ use radicle_term::Element as _;
|
||||||
|
|
||||||
use crate::commands::rad_sync as sync;
|
use crate::commands::rad_sync as sync;
|
||||||
use crate::node::SyncSettings;
|
use crate::node::SyncSettings;
|
||||||
|
use crate::terminal as term;
|
||||||
use crate::terminal::args::{Args, Error, Help};
|
use crate::terminal::args::{Args, Error, Help};
|
||||||
use crate::{project, terminal as term};
|
|
||||||
|
|
||||||
pub const HELP: Help = Help {
|
pub const HELP: Help = Help {
|
||||||
name: "seed",
|
name: "seed",
|
||||||
|
|
@ -134,7 +134,7 @@ pub fn update(
|
||||||
node: &mut Node,
|
node: &mut Node,
|
||||||
profile: &Profile,
|
profile: &Profile,
|
||||||
) -> Result<(), anyhow::Error> {
|
) -> 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" };
|
let outcome = if updated { "updated" } else { "exists" };
|
||||||
|
|
||||||
term::success!(
|
term::success!(
|
||||||
|
|
@ -145,17 +145,11 @@ pub fn update(
|
||||||
Ok(())
|
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<()> {
|
pub fn seeding(profile: &Profile) -> anyhow::Result<()> {
|
||||||
let store = profile.policies()?;
|
let store = profile.policies()?;
|
||||||
let storage = &profile.storage;
|
let storage = &profile.storage;
|
||||||
let mut t = term::Table::new(term::table::TableOptions::bordered());
|
let mut t = term::Table::new(term::table::TableOptions::bordered());
|
||||||
|
|
||||||
t.header([
|
t.header([
|
||||||
term::format::default(String::from("Repository")),
|
term::format::default(String::from("Repository")),
|
||||||
term::format::default(String::from("Name")),
|
term::format::default(String::from("Name")),
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@ use anyhow::anyhow;
|
||||||
|
|
||||||
use radicle::{prelude::*, Node};
|
use radicle::{prelude::*, Node};
|
||||||
|
|
||||||
|
use crate::terminal as term;
|
||||||
use crate::terminal::args::{Args, Error, Help};
|
use crate::terminal::args::{Args, Error, Help};
|
||||||
use crate::{project, terminal as term};
|
|
||||||
|
|
||||||
pub const HELP: Help = Help {
|
pub const HELP: Help = Help {
|
||||||
name: "unseed",
|
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<()> {
|
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));
|
term::success!("Seeding policy for {} removed", term::format::tertiary(rid));
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,8 @@
|
||||||
use localtime::LocalTime;
|
|
||||||
use radicle::prelude::*;
|
use radicle::prelude::*;
|
||||||
|
|
||||||
use crate::git;
|
use crate::git;
|
||||||
use radicle::git::RefStr;
|
use radicle::git::RefStr;
|
||||||
use radicle::node::policy::Scope;
|
use radicle::node::NodeId;
|
||||||
use radicle::node::{routing, Handle, NodeId};
|
|
||||||
use radicle::Node;
|
|
||||||
|
|
||||||
/// Setup a repository remote and tracking branch.
|
/// Setup a repository remote and tracking branch.
|
||||||
pub struct SetupRemote<'a> {
|
pub struct SetupRemote<'a> {
|
||||||
|
|
@ -52,68 +49,3 @@ impl<'a> SetupRemote<'a> {
|
||||||
Ok((remote, None))
|
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()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -27,12 +27,12 @@ use crate::node::policy::config::store::Read;
|
||||||
use crate::node::{
|
use crate::node::{
|
||||||
notifications, policy,
|
notifications, policy,
|
||||||
policy::{Policy, Scope, SeedingPolicy},
|
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::transport;
|
||||||
use crate::storage::git::Storage;
|
use crate::storage::git::Storage;
|
||||||
use crate::storage::ReadRepository;
|
use crate::storage::{ReadRepository, ReadStorage};
|
||||||
use crate::{cli, cob, git, node, storage, web};
|
use crate::{cli, cob, git, node, storage, web};
|
||||||
|
|
||||||
/// Environment variables used by radicle.
|
/// Environment variables used by radicle.
|
||||||
|
|
@ -158,6 +158,10 @@ pub enum Error {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Config(#[from] ConfigError),
|
Config(#[from] ConfigError),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
|
Node(#[from] node::Error),
|
||||||
|
#[error(transparent)]
|
||||||
|
Routing(#[from] node::routing::Error),
|
||||||
|
#[error(transparent)]
|
||||||
Keystore(#[from] keystore::Error),
|
Keystore(#[from] keystore::Error),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
MemorySigner(#[from] keystore::MemorySignerError),
|
MemorySigner(#[from] keystore::MemorySignerError),
|
||||||
|
|
@ -423,6 +427,63 @@ impl Profile {
|
||||||
|
|
||||||
Aliases { policies, db }
|
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 {
|
impl std::ops::Deref for Profile {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue