cli: Use tracking DB access for `node` command
This commit is contained in:
parent
cf8113765c
commit
9b6ede8fc5
|
|
@ -1,7 +1,7 @@
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
|
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use radicle::node::{Address, Node, NodeId};
|
use radicle::node::{Address, Node, NodeId, TRACKING_DB_FILE};
|
||||||
|
|
||||||
use crate::terminal as term;
|
use crate::terminal as term;
|
||||||
use crate::terminal::args::{Args, Error, Help};
|
use crate::terminal::args::{Args, Error, Help};
|
||||||
|
|
@ -152,8 +152,10 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
|
||||||
control::stop(node)?;
|
control::stop(node)?;
|
||||||
}
|
}
|
||||||
Operation::Tracking { mode } => {
|
Operation::Tracking { mode } => {
|
||||||
let node = Node::new(profile.socket());
|
let store = radicle::node::tracking::store::Config::open(
|
||||||
tracking::run(&node, mode)?
|
profile.home.node().join(TRACKING_DB_FILE),
|
||||||
|
)?;
|
||||||
|
tracking::run(&store, mode)?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,23 @@
|
||||||
use radicle::node::{tracking, Handle as _};
|
use radicle::node::tracking;
|
||||||
use radicle::prelude::Did;
|
use radicle::prelude::Did;
|
||||||
use radicle::Node;
|
|
||||||
|
|
||||||
use crate::terminal as term;
|
use crate::terminal as term;
|
||||||
|
|
||||||
use super::TrackingMode;
|
use super::TrackingMode;
|
||||||
|
|
||||||
pub fn run(node: &Node, mode: TrackingMode) -> anyhow::Result<()> {
|
pub fn run(store: &tracking::store::Config, mode: TrackingMode) -> anyhow::Result<()> {
|
||||||
match mode {
|
match mode {
|
||||||
TrackingMode::Repos => print_repos(node)?,
|
TrackingMode::Repos => print_repos(store)?,
|
||||||
TrackingMode::Nodes => print_nodes(node)?,
|
TrackingMode::Nodes => print_nodes(store)?,
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_repos(node: &Node) -> anyhow::Result<()> {
|
fn print_repos(store: &tracking::store::Config) -> anyhow::Result<()> {
|
||||||
let mut t = term::Table::new(term::table::TableOptions::default());
|
let mut t = term::Table::new(term::table::TableOptions::default());
|
||||||
t.push(["RID", "Scope", "Policy"]);
|
t.push(["RID", "Scope", "Policy"]);
|
||||||
t.push(["---", "-----", "------"]);
|
t.push(["---", "-----", "------"]);
|
||||||
for tracking::Repo { id, scope, policy } in node.repo_policies()? {
|
for tracking::Repo { id, scope, policy } in store.repo_entries()? {
|
||||||
t.push([
|
t.push([
|
||||||
term::format::highlight(id.to_string()),
|
term::format::highlight(id.to_string()),
|
||||||
term::format::secondary(scope.to_string()),
|
term::format::secondary(scope.to_string()),
|
||||||
|
|
@ -29,11 +28,11 @@ fn print_repos(node: &Node) -> anyhow::Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_nodes(node: &Node) -> anyhow::Result<()> {
|
fn print_nodes(store: &tracking::store::Config) -> anyhow::Result<()> {
|
||||||
let mut t = term::Table::new(term::table::TableOptions::default());
|
let mut t = term::Table::new(term::table::TableOptions::default());
|
||||||
t.push(["DID", "Alias", "Policy"]);
|
t.push(["DID", "Alias", "Policy"]);
|
||||||
t.push(["---", "-----", "------"]);
|
t.push(["---", "-----", "------"]);
|
||||||
for tracking::Node { id, alias, policy } in node.node_policies()? {
|
for tracking::Node { id, alias, policy } in store.node_entries()? {
|
||||||
t.push([
|
t.push([
|
||||||
term::format::highlight(Did::from(id).to_string()),
|
term::format::highlight(Did::from(id).to_string()),
|
||||||
match alias {
|
match alias {
|
||||||
|
|
|
||||||
|
|
@ -131,15 +131,6 @@ fn command<H: Handle<Error = runtime::HandleError>>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CommandName::RepoPolicies => match handle.repo_policies() {
|
|
||||||
Ok(ts) => {
|
|
||||||
for t in ts.into_iter() {
|
|
||||||
serde_json::to_writer(&mut writer, &t)?;
|
|
||||||
writeln!(writer)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(e) => return Err(CommandError::Runtime(e)),
|
|
||||||
},
|
|
||||||
CommandName::TrackNode => {
|
CommandName::TrackNode => {
|
||||||
let (node, alias) = match cmd.args.as_slice() {
|
let (node, alias) = match cmd.args.as_slice() {
|
||||||
[node] => (node.as_str(), None),
|
[node] => (node.as_str(), None),
|
||||||
|
|
@ -171,15 +162,6 @@ fn command<H: Handle<Error = runtime::HandleError>>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CommandName::NodePolicies => match handle.node_policies() {
|
|
||||||
Ok(ts) => {
|
|
||||||
for t in ts.into_iter() {
|
|
||||||
serde_json::to_writer(&mut writer, &t)?;
|
|
||||||
writeln!(writer)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(e) => return Err(CommandError::Runtime(e)),
|
|
||||||
},
|
|
||||||
CommandName::AnnounceRefs => {
|
CommandName::AnnounceRefs => {
|
||||||
let rid: Id = parse::arg(cmd)?;
|
let rid: Id = parse::arg(cmd)?;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ use thiserror::Error;
|
||||||
|
|
||||||
use radicle::git;
|
use radicle::git;
|
||||||
use radicle::node::Handle as _;
|
use radicle::node::Handle as _;
|
||||||
|
use radicle::node::{ADDRESS_DB_FILE, ROUTING_DB_FILE, TRACKING_DB_FILE};
|
||||||
use radicle::profile::Home;
|
use radicle::profile::Home;
|
||||||
use radicle::Storage;
|
use radicle::Storage;
|
||||||
|
|
||||||
|
|
@ -30,15 +31,6 @@ use crate::{service, LocalTime};
|
||||||
pub use handle::Error as HandleError;
|
pub use handle::Error as HandleError;
|
||||||
pub use handle::Handle;
|
pub use handle::Handle;
|
||||||
|
|
||||||
/// Directory in `$RAD_HOME` under which node-specific files are stored.
|
|
||||||
pub const NODE_DIR: &str = "node";
|
|
||||||
/// Filename of routing table database under [`NODE_DIR`].
|
|
||||||
pub const ROUTING_DB_FILE: &str = "routing.db";
|
|
||||||
/// Filename of address database under [`NODE_DIR`].
|
|
||||||
pub const ADDRESS_DB_FILE: &str = "addresses.db";
|
|
||||||
/// Filename of tracking table database under [`NODE_DIR`].
|
|
||||||
pub const TRACKING_DB_FILE: &str = "tracking.db";
|
|
||||||
|
|
||||||
/// A client error.
|
/// A client error.
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
|
|
||||||
|
|
@ -109,10 +109,7 @@ impl<G: Signer + Ecdh + 'static> Handle<G> {
|
||||||
impl<G: Signer + Ecdh + 'static> radicle::node::Handle for Handle<G> {
|
impl<G: Signer + Ecdh + 'static> radicle::node::Handle for Handle<G> {
|
||||||
type Sessions = Sessions;
|
type Sessions = Sessions;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
type Routing = chan::Receiver<(Id, NodeId)>;
|
type Routing = chan::Receiver<(Id, NodeId)>;
|
||||||
type RepoPolicies = chan::Receiver<tracking::Repo>;
|
|
||||||
type NodePolicies = chan::Receiver<tracking::Node>;
|
|
||||||
|
|
||||||
fn is_running(&self) -> bool {
|
fn is_running(&self) -> bool {
|
||||||
true
|
true
|
||||||
|
|
@ -136,40 +133,6 @@ impl<G: Signer + Ecdh + 'static> radicle::node::Handle for Handle<G> {
|
||||||
receiver.recv().map_err(Error::from)
|
receiver.recv().map_err(Error::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn repo_policies(&self) -> Result<Self::RepoPolicies, Self::Error> {
|
|
||||||
let (sender, receiver) = chan::unbounded();
|
|
||||||
let query: Arc<QueryState> = Arc::new(move |state| {
|
|
||||||
for t in state.repo_policies()? {
|
|
||||||
if sender.send(t).is_err() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
});
|
|
||||||
let (err_sender, err_receiver) = chan::bounded(1);
|
|
||||||
self.command(service::Command::QueryState(query, err_sender))?;
|
|
||||||
err_receiver.recv()??;
|
|
||||||
|
|
||||||
Ok(receiver)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn node_policies(&self) -> Result<Self::NodePolicies, Self::Error> {
|
|
||||||
let (sender, receiver) = chan::unbounded();
|
|
||||||
let query: Arc<QueryState> = Arc::new(move |state| {
|
|
||||||
for t in state.node_policies()? {
|
|
||||||
if sender.send(t).is_err() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
});
|
|
||||||
let (err_sender, err_receiver) = chan::bounded(1);
|
|
||||||
self.command(service::Command::QueryState(query, err_sender))?;
|
|
||||||
err_receiver.recv()??;
|
|
||||||
|
|
||||||
Ok(receiver)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn track_node(&mut self, id: NodeId, alias: Option<String>) -> Result<bool, Error> {
|
fn track_node(&mut self, id: NodeId, alias: Option<String>) -> Result<bool, Error> {
|
||||||
let (sender, receiver) = chan::bounded(1);
|
let (sender, receiver) = chan::bounded(1);
|
||||||
self.command(service::Command::TrackNode(id, alias, sender))?;
|
self.command(service::Command::TrackNode(id, alias, sender))?;
|
||||||
|
|
|
||||||
|
|
@ -1501,10 +1501,6 @@ pub trait ServiceState {
|
||||||
fn config(&self) -> &Config;
|
fn config(&self) -> &Config;
|
||||||
/// Get reference to routing table.
|
/// Get reference to routing table.
|
||||||
fn routing(&self) -> &dyn routing::Store;
|
fn routing(&self) -> &dyn routing::Store;
|
||||||
/// Get the tracked repos.
|
|
||||||
fn repo_policies(&self) -> Result<Vec<tracking::Repo>, tracking::Error>;
|
|
||||||
/// Get the tracked nodes.
|
|
||||||
fn node_policies(&self) -> Result<Vec<tracking::Node>, tracking::Error>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R, A, S, G> ServiceState for Service<R, A, S, G>
|
impl<R, A, S, G> ServiceState for Service<R, A, S, G>
|
||||||
|
|
@ -1540,14 +1536,6 @@ where
|
||||||
fn routing(&self) -> &dyn routing::Store {
|
fn routing(&self) -> &dyn routing::Store {
|
||||||
&self.routing
|
&self.routing
|
||||||
}
|
}
|
||||||
|
|
||||||
fn repo_policies(&self) -> Result<Vec<tracking::Repo>, tracking::Error> {
|
|
||||||
Ok(self.tracking.repo_entries()?.collect())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn node_policies(&self) -> Result<Vec<tracking::Node>, tracking::Error> {
|
|
||||||
Ok(self.tracking.node_entries()?.collect())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Disconnect reason.
|
/// Disconnect reason.
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,6 @@ impl radicle::node::Handle for Handle {
|
||||||
type Error = HandleError;
|
type Error = HandleError;
|
||||||
type Sessions = service::Sessions;
|
type Sessions = service::Sessions;
|
||||||
type Routing = Vec<(Id, NodeId)>;
|
type Routing = Vec<(Id, NodeId)>;
|
||||||
type RepoPolicies = Vec<tracking::Repo>;
|
|
||||||
type NodePolicies = Vec<tracking::Node>;
|
|
||||||
|
|
||||||
fn is_running(&self) -> bool {
|
fn is_running(&self) -> bool {
|
||||||
true
|
true
|
||||||
|
|
@ -40,32 +38,6 @@ impl radicle::node::Handle for Handle {
|
||||||
Ok(FetchResult::from(Ok::<Vec<RefUpdate>, Self::Error>(vec![])))
|
Ok(FetchResult::from(Ok::<Vec<RefUpdate>, Self::Error>(vec![])))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn repo_policies(&self) -> Result<Self::RepoPolicies, Self::Error> {
|
|
||||||
Ok(self
|
|
||||||
.tracking_repos
|
|
||||||
.iter()
|
|
||||||
.copied()
|
|
||||||
.map(|id| tracking::Repo {
|
|
||||||
id,
|
|
||||||
scope: tracking::Scope::All,
|
|
||||||
policy: tracking::Policy::Track,
|
|
||||||
})
|
|
||||||
.collect())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn node_policies(&self) -> Result<Self::NodePolicies, Self::Error> {
|
|
||||||
Ok(self
|
|
||||||
.tracking_nodes
|
|
||||||
.iter()
|
|
||||||
.copied()
|
|
||||||
.map(|id| tracking::Node {
|
|
||||||
id,
|
|
||||||
alias: None,
|
|
||||||
policy: tracking::Policy::Track,
|
|
||||||
})
|
|
||||||
.collect())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn track_repo(&mut self, id: Id, _scope: tracking::Scope) -> Result<bool, Self::Error> {
|
fn track_repo(&mut self, id: Id, _scope: tracking::Scope) -> Result<bool, Self::Error> {
|
||||||
Ok(self.tracking_repos.insert(id))
|
Ok(self.tracking_repos.insert(id))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,12 @@ pub use features::Features;
|
||||||
pub const DEFAULT_SOCKET_NAME: &str = "radicle.sock";
|
pub const DEFAULT_SOCKET_NAME: &str = "radicle.sock";
|
||||||
/// Default radicle protocol port.
|
/// Default radicle protocol port.
|
||||||
pub const DEFAULT_PORT: u16 = 8776;
|
pub const DEFAULT_PORT: u16 = 8776;
|
||||||
|
/// Filename of routing table database under the node directory.
|
||||||
|
pub const ROUTING_DB_FILE: &str = "routing.db";
|
||||||
|
/// Filename of address database under the node directory.
|
||||||
|
pub const ADDRESS_DB_FILE: &str = "addresses.db";
|
||||||
|
/// Filename of tracking table database under the node directory.
|
||||||
|
pub const TRACKING_DB_FILE: &str = "tracking.db";
|
||||||
|
|
||||||
/// Result of a command, on the node control socket.
|
/// Result of a command, on the node control socket.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
|
@ -125,14 +131,10 @@ pub enum CommandName {
|
||||||
TrackRepo,
|
TrackRepo,
|
||||||
/// Untrack the given repository.
|
/// Untrack the given repository.
|
||||||
UntrackRepo,
|
UntrackRepo,
|
||||||
/// Get the repository tracking policies.
|
|
||||||
RepoPolicies,
|
|
||||||
/// Track the given node.
|
/// Track the given node.
|
||||||
TrackNode,
|
TrackNode,
|
||||||
/// Untrack the given node.
|
/// Untrack the given node.
|
||||||
UntrackNode,
|
UntrackNode,
|
||||||
/// Get the node tracking policies.
|
|
||||||
NodePolicies,
|
|
||||||
/// Get the node's inventory.
|
/// Get the node's inventory.
|
||||||
Inventory,
|
Inventory,
|
||||||
/// Get the node's routing table.
|
/// Get the node's routing table.
|
||||||
|
|
@ -380,8 +382,6 @@ pub trait Handle {
|
||||||
type Error: std::error::Error + Send + Sync + 'static;
|
type Error: std::error::Error + Send + Sync + 'static;
|
||||||
|
|
||||||
type Routing: IntoIterator<Item = (Id, NodeId)>;
|
type Routing: IntoIterator<Item = (Id, NodeId)>;
|
||||||
type RepoPolicies: IntoIterator<Item = tracking::Repo>;
|
|
||||||
type NodePolicies: IntoIterator<Item = tracking::Node>;
|
|
||||||
|
|
||||||
/// Check if the node is running. to a peer.
|
/// Check if the node is running. to a peer.
|
||||||
fn is_running(&self) -> bool;
|
fn is_running(&self) -> bool;
|
||||||
|
|
@ -400,10 +400,6 @@ pub trait Handle {
|
||||||
fn untrack_repo(&mut self, id: Id) -> Result<bool, Self::Error>;
|
fn untrack_repo(&mut self, id: Id) -> Result<bool, Self::Error>;
|
||||||
/// Untrack the given node.
|
/// Untrack the given node.
|
||||||
fn untrack_node(&mut self, id: NodeId) -> Result<bool, Self::Error>;
|
fn untrack_node(&mut self, id: NodeId) -> Result<bool, Self::Error>;
|
||||||
/// Get the tracking information for all tracked or blocked repos in storage.
|
|
||||||
fn repo_policies(&self) -> Result<Self::RepoPolicies, Self::Error>;
|
|
||||||
/// Get the tracking information for all tracked or blocked nodes in storage.
|
|
||||||
fn node_policies(&self) -> Result<Self::NodePolicies, Self::Error>;
|
|
||||||
/// Notify the service that a project has been updated, and announce local refs.
|
/// Notify the service that a project has been updated, and announce local refs.
|
||||||
fn announce_refs(&mut self, id: Id) -> Result<(), Self::Error>;
|
fn announce_refs(&mut self, id: Id) -> Result<(), Self::Error>;
|
||||||
/// Announce local inventory.
|
/// Announce local inventory.
|
||||||
|
|
@ -464,9 +460,6 @@ impl Node {
|
||||||
impl Handle for Node {
|
impl Handle for Node {
|
||||||
type Sessions = ();
|
type Sessions = ();
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
type RepoPolicies = Vec<tracking::Repo>;
|
|
||||||
type NodePolicies = Vec<tracking::Node>;
|
|
||||||
type Routing = Vec<(Id, NodeId)>;
|
type Routing = Vec<(Id, NodeId)>;
|
||||||
|
|
||||||
fn is_running(&self) -> bool {
|
fn is_running(&self) -> bool {
|
||||||
|
|
@ -510,24 +503,6 @@ impl Handle for Node {
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn repo_policies(&self) -> Result<Vec<tracking::Repo>, Self::Error> {
|
|
||||||
let mut repos = Vec::new();
|
|
||||||
for result in self.call::<&str, _>(CommandName::RepoPolicies, [])? {
|
|
||||||
let repo = result?;
|
|
||||||
repos.push(repo);
|
|
||||||
}
|
|
||||||
Ok(repos)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn node_policies(&self) -> Result<Vec<tracking::Node>, Self::Error> {
|
|
||||||
let mut repos = Vec::new();
|
|
||||||
for result in self.call::<&str, _>(CommandName::NodePolicies, [])? {
|
|
||||||
let repo = result?;
|
|
||||||
repos.push(repo);
|
|
||||||
}
|
|
||||||
Ok(repos)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn track_node(&mut self, id: NodeId, alias: Option<String>) -> Result<bool, Error> {
|
fn track_node(&mut self, id: NodeId, alias: Option<String>) -> Result<bool, Error> {
|
||||||
let id = id.to_human();
|
let id = id.to_human();
|
||||||
let args = if let Some(alias) = alias.as_deref() {
|
let args = if let Some(alias) = alias.as_deref() {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue