cli: Have `init` trigger routing table updates

Before this change, nodes had to be restarted to announce newly
initialized projects.
This commit is contained in:
Alexis Sellier 2023-02-08 16:29:42 +01:00
parent c138cd062c
commit f01735bef6
No known key found for this signature in database
4 changed files with 34 additions and 13 deletions

View File

@ -8,7 +8,7 @@ use anyhow::{anyhow, bail, Context as _};
use radicle::crypto::ssh; use radicle::crypto::ssh;
use radicle::git::RefString; use radicle::git::RefString;
use radicle::node::NodeId; use radicle::node::{Handle, NodeId};
use crate::git; use crate::git;
use crate::terminal as term; use crate::terminal as term;
@ -34,6 +34,7 @@ Options
--set-upstream, -u Setup the upstream of the default branch --set-upstream, -u Setup the upstream of the default branch
--setup-signing Setup the radicle key as a signing key for this repository --setup-signing Setup the radicle key as a signing key for this repository
--no-confirm Don't ask for confirmation during setup --no-confirm Don't ask for confirmation during setup
--no-sync Don't announce the new project to the network
--help Print help --help Print help
"#, "#,
}; };
@ -47,6 +48,7 @@ pub struct Options {
pub interactive: Interactive, pub interactive: Interactive,
pub setup_signing: bool, pub setup_signing: bool,
pub set_upstream: bool, pub set_upstream: bool,
pub sync: bool,
} }
impl Args for Options { impl Args for Options {
@ -62,6 +64,7 @@ impl Args for Options {
let mut interactive = Interactive::Yes; let mut interactive = Interactive::Yes;
let mut set_upstream = false; let mut set_upstream = false;
let mut setup_signing = false; let mut setup_signing = false;
let mut sync = true;
while let Some(arg) = parser.next()? { while let Some(arg) = parser.next()? {
match arg { match arg {
@ -106,6 +109,12 @@ impl Args for Options {
Long("no-confirm") => { Long("no-confirm") => {
interactive = Interactive::No; interactive = Interactive::No;
} }
Long("sync") => {
sync = true;
}
Long("no-sync") => {
sync = false;
}
Long("help") => { Long("help") => {
return Err(Error::Help.into()); return Err(Error::Help.into());
} }
@ -125,6 +134,7 @@ impl Args for Options {
interactive, interactive,
set_upstream, set_upstream,
setup_signing, setup_signing,
sync,
}, },
vec![], vec![],
)) ))
@ -221,6 +231,14 @@ pub fn init(options: Options, profile: &profile::Profile) -> anyhow::Result<()>
// Setup radicle signing key. // Setup radicle signing key.
self::setup_signing(profile.id(), &repo, interactive)?; self::setup_signing(profile.id(), &repo, interactive)?;
} }
if options.sync {
let spinner = term::spinner("Announcing refs..");
if let Err(e) = radicle::Node::new(profile.socket()).announce_refs(id) {
spinner.error(e);
} else {
spinner.finish();
}
}
term::blank(); term::blank();
term::info!( term::info!(

View File

@ -35,7 +35,7 @@ impl Spinner {
pub fn error(mut self, msg: impl ToString) { pub fn error(mut self, msg: impl ToString) {
let msg = msg.to_string(); let msg = msg.to_string();
self.message = format!("{} ({})", self.message, msg); self.message = format!("{} (error: {})", self.message, msg);
self.set_failed(); self.set_failed();
} }

View File

@ -90,6 +90,7 @@ pub fn seed(dir: &Path) -> Context {
interactive: false.into(), interactive: false.into(),
setup_signing: false, setup_signing: false,
set_upstream: false, set_upstream: false,
sync: false,
}, },
&profile, &profile,
) )

View File

@ -91,8 +91,6 @@ pub enum Error {
#[error(transparent)] #[error(transparent)]
Storage(#[from] storage::Error), Storage(#[from] storage::Error),
#[error(transparent)] #[error(transparent)]
Fetch(#[from] storage::FetchError),
#[error(transparent)]
Routing(#[from] routing::Error), Routing(#[from] routing::Error),
} }
@ -701,19 +699,13 @@ where
return Ok(false); return Ok(false);
} }
if let Err(err) = self.process_inventory( if let Err(err) = self.sync_inventory(
message.inventory.as_slice(), message.inventory.as_slice(),
*announcer, *announcer,
&message.timestamp, &message.timestamp,
) { ) {
error!("Error processing inventory from {}: {}", announcer, err); error!("Error processing inventory from {}: {}", announcer, err);
if let Error::Fetch(storage::FetchError::Verify(err)) = err {
// Disconnect the peer if it is the signer of this message.
if announcer == relayer {
return Err(session::Error::VerificationFailed(err));
}
}
// There's not much we can do if the peer sending us this message isn't the // There's not much we can do if the peer sending us this message isn't the
// origin of it. // origin of it.
return Ok(false); return Ok(false);
@ -722,6 +714,13 @@ where
} }
// Process a peer inventory update announcement by (maybe) fetching. // Process a peer inventory update announcement by (maybe) fetching.
AnnouncementMessage::Refs(message) => { AnnouncementMessage::Refs(message) => {
// We update inventories when receiving ref announcements, as these could come
// from a new repository being initialized.
if let Ok(updated) = self.routing.insert(message.id, *relayer, message.timestamp) {
if updated {
info!(target: "service", "Routing table updated for {} with seed {relayer}", message.id);
}
}
// TODO: Buffer/throttle fetches. // TODO: Buffer/throttle fetches.
// TODO: Check that we're tracking this user as well. // TODO: Check that we're tracking this user as well.
if self if self
@ -743,7 +742,8 @@ where
return Ok(true); return Ok(true);
} else { } else {
debug!(target: "service", debug!(
target: "service",
"Ignoring refs announcement from {announcer}: repository {} isn't tracked", "Ignoring refs announcement from {announcer}: repository {} isn't tracked",
message.id message.id
); );
@ -959,7 +959,9 @@ where
} }
/// Process a peer inventory announcement by updating our routing table. /// Process a peer inventory announcement by updating our routing table.
fn process_inventory( /// This function expects the peer's full inventory, and prunes entries that are not in the
/// given inventory.
fn sync_inventory(
&mut self, &mut self,
inventory: &[Id], inventory: &[Id],
from: NodeId, from: NodeId,