remote-helper/service: Introduce `NodeSession`
Prefactor to add a trait capturing behaviour of the node.
This commit is contained in:
parent
56253b529e
commit
27493c2229
|
|
@ -243,6 +243,7 @@ pub fn run(profile: radicle::Profile) -> Result<(), Error> {
|
||||||
let mut opts = Options::default();
|
let mut opts = Options::default();
|
||||||
let mut expected_refs = Vec::new();
|
let mut expected_refs = Vec::new();
|
||||||
let git = service::RealGitService;
|
let git = service::RealGitService;
|
||||||
|
let mut node = service::RealNodeSession::new(&profile);
|
||||||
|
|
||||||
if let Err(e) = radicle::io::set_file_limit(4096) {
|
if let Err(e) = radicle::io::set_file_limit(4096) {
|
||||||
if debug {
|
if debug {
|
||||||
|
|
@ -310,6 +311,7 @@ pub fn run(profile: radicle::Profile) -> Result<(), Error> {
|
||||||
opts,
|
opts,
|
||||||
&expected_refs,
|
&expected_refs,
|
||||||
&git,
|
&git,
|
||||||
|
&mut node,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
for line in output {
|
for line in output {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ mod canonical;
|
||||||
mod error;
|
mod error;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::io::IsTerminal;
|
|
||||||
use std::process::ExitStatus;
|
use std::process::ExitStatus;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::{assert_eq, io};
|
use std::{assert_eq, io};
|
||||||
|
|
@ -22,16 +21,16 @@ use radicle::crypto;
|
||||||
use radicle::explorer::ExplorerResource;
|
use radicle::explorer::ExplorerResource;
|
||||||
use radicle::identity::{CanonicalRefs, Did};
|
use radicle::identity::{CanonicalRefs, Did};
|
||||||
use radicle::node;
|
use radicle::node;
|
||||||
use radicle::node::{Handle, NodeId};
|
use radicle::node::NodeId;
|
||||||
use radicle::storage;
|
use radicle::storage;
|
||||||
use radicle::storage::git::transport::local::Url;
|
use radicle::storage::git::transport::local::Url;
|
||||||
use radicle::storage::{ReadRepository, SignRepository as _, WriteRepository};
|
use radicle::storage::{ReadRepository, SignRepository as _, WriteRepository};
|
||||||
use radicle::Profile;
|
use radicle::Profile;
|
||||||
use radicle::{git, rad};
|
use radicle::{git, rad};
|
||||||
use radicle_cli as cli;
|
|
||||||
use radicle_cli::terminal as term;
|
use radicle_cli::terminal as term;
|
||||||
|
|
||||||
use crate::service::GitService;
|
use crate::service::GitService;
|
||||||
|
use crate::service::NodeSession;
|
||||||
use crate::{hint, read_line, warn, Options, Verbosity};
|
use crate::{hint, read_line, warn, Options, Verbosity};
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
|
|
@ -254,6 +253,7 @@ pub fn run(
|
||||||
opts: Options,
|
opts: Options,
|
||||||
expected_refs: &[String],
|
expected_refs: &[String],
|
||||||
git: &impl GitService,
|
git: &impl GitService,
|
||||||
|
node: &mut impl NodeSession,
|
||||||
) -> Result<Vec<String>, Error> {
|
) -> Result<Vec<String>, Error> {
|
||||||
// Don't allow push if either of these conditions is true:
|
// Don't allow push if either of these conditions is true:
|
||||||
//
|
//
|
||||||
|
|
@ -462,10 +462,10 @@ pub fn run(
|
||||||
// Connect to local node and announce refs to the network.
|
// Connect to local node and announce refs to the network.
|
||||||
// If our node is not running, we simply skip this step, as the
|
// If our node is not running, we simply skip this step, as the
|
||||||
// refs will be announced eventually, when the node restarts.
|
// refs will be announced eventually, when the node restarts.
|
||||||
let node = radicle::Node::new(profile.socket());
|
|
||||||
if node.is_running() {
|
if node.is_running() {
|
||||||
// Nb. allow this to fail. The push to local storage was still successful.
|
// Nb. allow this to fail. The push to local storage was still successful.
|
||||||
sync(stored, ok.into_values().flatten(), opts, node, profile).ok();
|
node.sync(stored, ok.into_values().flatten().collect(), opts, profile)
|
||||||
|
.ok();
|
||||||
} else if hints {
|
} else if hints {
|
||||||
hint("offline push, your node is not running");
|
hint("offline push, your node is not running");
|
||||||
hint("to sync with the network, run `rad node start`");
|
hint("to sync with the network, run `rad node start`");
|
||||||
|
|
@ -1038,59 +1038,3 @@ fn push_ref(
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sync with the network.
|
|
||||||
fn sync(
|
|
||||||
repo: &storage::git::Repository,
|
|
||||||
updated: impl Iterator<Item = ExplorerResource>,
|
|
||||||
opts: Options,
|
|
||||||
mut node: radicle::Node,
|
|
||||||
profile: &Profile,
|
|
||||||
) -> Result<(), cli::node::SyncError> {
|
|
||||||
let progress = if io::stderr().is_terminal() {
|
|
||||||
term::PaintTarget::Stderr
|
|
||||||
} else {
|
|
||||||
term::PaintTarget::Hidden
|
|
||||||
};
|
|
||||||
let result = cli::node::announce(
|
|
||||||
repo,
|
|
||||||
cli::node::SyncSettings::default().with_profile(profile),
|
|
||||||
cli::node::SyncReporting {
|
|
||||||
progress,
|
|
||||||
completion: term::PaintTarget::Stderr,
|
|
||||||
debug: opts.sync_debug,
|
|
||||||
},
|
|
||||||
&mut node,
|
|
||||||
profile,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let mut urls = Vec::new();
|
|
||||||
|
|
||||||
if let Some(result) = result {
|
|
||||||
for seed in profile.config.preferred_seeds.iter() {
|
|
||||||
if result.is_synced(&seed.id) {
|
|
||||||
for resource in updated {
|
|
||||||
let url = profile
|
|
||||||
.config
|
|
||||||
.public_explorer
|
|
||||||
.url(seed.addr.host.clone(), repo.id)
|
|
||||||
.resource(resource);
|
|
||||||
|
|
||||||
urls.push(url);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print URLs to the updated resources.
|
|
||||||
if !urls.is_empty() {
|
|
||||||
eprintln!();
|
|
||||||
for url in urls {
|
|
||||||
eprintln!(" {}", term::format::dim(url));
|
|
||||||
}
|
|
||||||
eprintln!();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,15 @@
|
||||||
use std::io;
|
use std::io;
|
||||||
|
use std::io::IsTerminal;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::process;
|
use std::process;
|
||||||
|
|
||||||
|
use radicle::explorer::ExplorerResource;
|
||||||
use radicle::git;
|
use radicle::git;
|
||||||
|
use radicle::node::Handle;
|
||||||
use radicle::storage;
|
use radicle::storage;
|
||||||
|
use radicle::Profile;
|
||||||
|
use radicle_cli::node::{SyncError, SyncReporting, SyncSettings};
|
||||||
|
use radicle_cli::terminal as term;
|
||||||
|
|
||||||
/// Abstraction for Git subprocess calls.
|
/// Abstraction for Git subprocess calls.
|
||||||
pub(super) trait GitService {
|
pub(super) trait GitService {
|
||||||
|
|
@ -38,3 +44,90 @@ impl GitService for RealGitService {
|
||||||
git::run(working, args)
|
git::run(working, args)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Abstraction for Node interaction.
|
||||||
|
pub(super) trait NodeSession {
|
||||||
|
fn is_running(&self) -> bool;
|
||||||
|
|
||||||
|
fn sync(
|
||||||
|
&mut self,
|
||||||
|
repo: &storage::git::Repository,
|
||||||
|
updated: Vec<ExplorerResource>,
|
||||||
|
opts: crate::Options,
|
||||||
|
profile: &Profile,
|
||||||
|
) -> Result<(), SyncError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) struct RealNodeSession {
|
||||||
|
node: radicle::Node,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RealNodeSession {
|
||||||
|
pub(super) fn new(profile: &Profile) -> Self {
|
||||||
|
Self {
|
||||||
|
node: radicle::Node::new(profile.socket()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NodeSession for RealNodeSession {
|
||||||
|
fn is_running(&self) -> bool {
|
||||||
|
self.node.is_running()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sync(
|
||||||
|
&mut self,
|
||||||
|
repo: &storage::git::Repository,
|
||||||
|
updated: Vec<ExplorerResource>,
|
||||||
|
opts: crate::Options,
|
||||||
|
profile: &Profile,
|
||||||
|
) -> Result<(), SyncError> {
|
||||||
|
let progress = if io::stderr().is_terminal() {
|
||||||
|
term::PaintTarget::Stderr
|
||||||
|
} else {
|
||||||
|
term::PaintTarget::Hidden
|
||||||
|
};
|
||||||
|
|
||||||
|
let result = radicle_cli::node::announce(
|
||||||
|
repo,
|
||||||
|
SyncSettings::default().with_profile(profile),
|
||||||
|
SyncReporting {
|
||||||
|
progress,
|
||||||
|
completion: term::PaintTarget::Stderr,
|
||||||
|
debug: opts.sync_debug,
|
||||||
|
},
|
||||||
|
&mut self.node,
|
||||||
|
profile,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let mut urls = Vec::new();
|
||||||
|
|
||||||
|
if let Some(result) = result {
|
||||||
|
for seed in profile.config.preferred_seeds.iter() {
|
||||||
|
if result.is_synced(&seed.id) {
|
||||||
|
for resource in updated {
|
||||||
|
let url = profile
|
||||||
|
.config
|
||||||
|
.public_explorer
|
||||||
|
.url(seed.addr.host.clone(), repo.id)
|
||||||
|
.resource(resource);
|
||||||
|
|
||||||
|
urls.push(url);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print URLs to the updated resources.
|
||||||
|
if !urls.is_empty() {
|
||||||
|
eprintln!();
|
||||||
|
for url in urls {
|
||||||
|
eprintln!(" {}", term::format::dim(url));
|
||||||
|
}
|
||||||
|
eprintln!();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue