Radish alpha
h
rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5
Radicle Heartwood Protocol & Stack
Radicle
Git
remote-helper/service: Introduce `NodeSession`
Adrian Duke committed 2 months ago
commit 27493c2229766fc14268dc619fbec0e83e4f835d
parent 56253b5
3 files changed +100 -61
modified crates/radicle-remote-helper/src/main.rs
@@ -243,6 +243,7 @@ pub fn run(profile: radicle::Profile) -> Result<(), Error> {
    let mut opts = Options::default();
    let mut expected_refs = Vec::new();
    let git = service::RealGitService;
+
    let mut node = service::RealNodeSession::new(&profile);

    if let Err(e) = radicle::io::set_file_limit(4096) {
        if debug {
@@ -310,6 +311,7 @@ pub fn run(profile: radicle::Profile) -> Result<(), Error> {
                    opts,
                    &expected_refs,
                    &git,
+
                    &mut node,
                )?;

                for line in output {
modified crates/radicle-remote-helper/src/push.rs
@@ -4,7 +4,6 @@ mod canonical;
mod error;

use std::collections::HashMap;
-
use std::io::IsTerminal;
use std::process::ExitStatus;
use std::str::FromStr;
use std::{assert_eq, io};
@@ -22,16 +21,16 @@ use radicle::crypto;
use radicle::explorer::ExplorerResource;
use radicle::identity::{CanonicalRefs, Did};
use radicle::node;
-
use radicle::node::{Handle, NodeId};
+
use radicle::node::NodeId;
use radicle::storage;
use radicle::storage::git::transport::local::Url;
use radicle::storage::{ReadRepository, SignRepository as _, WriteRepository};
use radicle::Profile;
use radicle::{git, rad};
-
use radicle_cli as cli;
use radicle_cli::terminal as term;

use crate::service::GitService;
+
use crate::service::NodeSession;
use crate::{hint, read_line, warn, Options, Verbosity};

#[derive(Debug, Error)]
@@ -254,6 +253,7 @@ pub fn run(
    opts: Options,
    expected_refs: &[String],
    git: &impl GitService,
+
    node: &mut impl NodeSession,
) -> Result<Vec<String>, Error> {
    // 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.
                // If our node is not running, we simply skip this step, as the
                // refs will be announced eventually, when the node restarts.
-
                let node = radicle::Node::new(profile.socket());
                if node.is_running() {
                    // 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 {
                    hint("offline push, your node is not running");
                    hint("to sync with the network, run `rad node start`");
@@ -1038,59 +1038,3 @@ fn push_ref(

    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(())
-
}
modified crates/radicle-remote-helper/src/service.rs
@@ -1,9 +1,15 @@
use std::io;
+
use std::io::IsTerminal;
use std::path::Path;
use std::process;

+
use radicle::explorer::ExplorerResource;
use radicle::git;
+
use radicle::node::Handle;
use radicle::storage;
+
use radicle::Profile;
+
use radicle_cli::node::{SyncError, SyncReporting, SyncSettings};
+
use radicle_cli::terminal as term;

/// Abstraction for Git subprocess calls.
pub(super) trait GitService {
@@ -38,3 +44,90 @@ impl GitService for RealGitService {
        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(())
+
    }
+
}