remote-helper: Don't use external command for sync

We use the library function which gives us more control over the output
and removes the need to create a sub-process.
This commit is contained in:
Alexis Sellier 2023-05-22 11:38:59 +02:00
parent cfc386ed0e
commit 4bf15bf7ca
No known key found for this signature in database
1 changed files with 36 additions and 35 deletions

View File

@ -1,15 +1,16 @@
use std::collections::HashSet; use std::collections::HashSet;
use std::ffi::OsStr;
use std::os::fd::{AsRawFd, FromRawFd};
use std::path::Path; use std::path::Path;
use std::str::FromStr; use std::str::FromStr;
use std::{assert_eq, io, process}; use std::time;
use std::{assert_eq, io};
use thiserror::Error; use thiserror::Error;
use radicle::cob::patch; use radicle::cob::patch;
use radicle::crypto::{PublicKey, Signer}; use radicle::crypto::{PublicKey, Signer};
use radicle::node;
use radicle::node::{Handle, NodeId}; use radicle::node::{Handle, NodeId};
use radicle::prelude::Id;
use radicle::storage::git::cob::object::ParseObjectId; use radicle::storage::git::cob::object::ParseObjectId;
use radicle::storage::git::transport::local::Url; use radicle::storage::git::transport::local::Url;
use radicle::storage::WriteRepository; use radicle::storage::WriteRepository;
@ -20,6 +21,9 @@ use radicle_cli::terminal as cli;
use crate::read_line; use crate::read_line;
/// Default timeout for syncing to the network after a push.
const DEFAULT_SYNC_TIMEOUT: time::Duration = time::Duration::from_secs(9);
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum Error { pub enum Error {
/// Public key doesn't match the remote namespace we're pushing to. /// Public key doesn't match the remote namespace we're pushing to.
@ -194,14 +198,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.
if radicle::Node::new(profile.socket()).is_running() { let node = radicle::Node::new(profile.socket());
let rid = stored.id.to_string(); if node.is_running() {
let stderr = io::stderr().as_raw_fd();
// 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.
execute("rad", ["sync", &rid, "--announce", "--verbose"], unsafe { sync(stored.id, node).ok();
process::Stdio::from_raw_fd(stderr)
})
.ok();
} }
} }
@ -446,31 +446,32 @@ fn push_ref(
Ok(()) Ok(())
} }
/// Execute a command as a child process, redirecting its stdout to the given `Stdio`. /// Sync with the network.
fn execute<S: AsRef<std::ffi::OsStr>>( fn sync(rid: Id, mut node: radicle::Node) -> Result<(), radicle::node::Error> {
name: &str, let seeds = node.seeds(rid)?;
args: impl IntoIterator<Item = S>, let connected = seeds.connected().cloned().collect::<Vec<_>>();
stdout: process::Stdio,
) -> Result<String, Error> {
let mut cmd = process::Command::new(name);
cmd.args(args)
.stdout(stdout)
.stderr(process::Stdio::inherit());
let child = cmd.spawn()?; if connected.is_empty() {
let output = child.wait_with_output()?; eprintln!("Not connected to any seeds.");
let status = output.status; return Ok(());
}
if !status.success() { let mut spinner = cli::spinner_to(
let cmd = format!( format!("Syncing with {} node(s)..", connected.len()),
"{} {}", io::stderr(),
cmd.get_program().to_string_lossy(), io::stderr(),
cmd.get_args()
.collect::<Vec<_>>()
.join(OsStr::new(" "))
.to_string_lossy()
); );
return Err(Error::CommandFailed(cmd, status.code().unwrap_or(-1))); let result = node.announce(rid, connected, DEFAULT_SYNC_TIMEOUT, |event| match event {
node::AnnounceEvent::Announced => {}
node::AnnounceEvent::RefsSynced { remote } => {
spinner.message(format!("Synced with {remote}.."));
} }
Ok(String::from_utf8_lossy(&output.stdout).to_string()) })?;
if result.synced.is_empty() {
spinner.failed();
} else {
spinner.message(format!("Synced with {} node(s)", result.synced.len()));
spinner.finish();
}
Ok(())
} }