cli: Give more control over `init` announcement
Instead of always announcing the inventory, by default we don't. Users can run `rad push` to trigger an announcement.
This commit is contained in:
parent
8c22012d61
commit
e69be6051d
|
|
@ -3,7 +3,7 @@ To create your first radicle project, navigate to a git repository, and run
|
||||||
the `init` command:
|
the `init` command:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ rad init --name heartwood --description "Radicle Heartwood Protocol & Stack" --no-confirm
|
$ rad init --name heartwood --description "Radicle Heartwood Protocol & Stack" --no-confirm --announce
|
||||||
|
|
||||||
Initializing local 🌱 project in .
|
Initializing local 🌱 project in .
|
||||||
|
|
||||||
|
|
@ -14,11 +14,9 @@ Initializing local 🌱 project in .
|
||||||
"defaultBranch": "master"
|
"defaultBranch": "master"
|
||||||
}
|
}
|
||||||
✓ Syncing inventory..
|
✓ Syncing inventory..
|
||||||
|
✓ Announcing inventory..
|
||||||
|
|
||||||
Your project id is rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji. You can show it any time by running:
|
Your project id is rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji. You can show it any time by running:
|
||||||
rad .
|
rad .
|
||||||
|
|
||||||
To publish your project to the network, run:
|
|
||||||
rad push
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ To create your first radicle project, navigate to a git repository, and run
|
||||||
the `init` command:
|
the `init` command:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ rad init --name heartwood --description "Radicle Heartwood Protocol & Stack" --no-confirm --no-sync --no-track
|
$ rad init --name heartwood --description "Radicle Heartwood Protocol & Stack" --no-confirm --no-track
|
||||||
|
|
||||||
Initializing local 🌱 project in .
|
Initializing local 🌱 project in .
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,8 +33,8 @@ Options
|
||||||
--default-branch The default branch of the project
|
--default-branch The default branch of the project
|
||||||
--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
|
||||||
|
--announce Announce the new project to the network
|
||||||
--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
|
||||||
"#,
|
"#,
|
||||||
};
|
};
|
||||||
|
|
@ -48,7 +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,
|
pub announce: bool,
|
||||||
pub track: bool,
|
pub track: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -65,7 +65,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;
|
let mut announce = false;
|
||||||
let mut track = true;
|
let mut track = true;
|
||||||
|
|
||||||
while let Some(arg) = parser.next()? {
|
while let Some(arg) = parser.next()? {
|
||||||
|
|
@ -108,15 +108,12 @@ impl Args for Options {
|
||||||
Long("setup-signing") => {
|
Long("setup-signing") => {
|
||||||
setup_signing = true;
|
setup_signing = true;
|
||||||
}
|
}
|
||||||
|
Long("announce") => {
|
||||||
|
announce = true;
|
||||||
|
}
|
||||||
Long("no-confirm") => {
|
Long("no-confirm") => {
|
||||||
interactive = Interactive::No;
|
interactive = Interactive::No;
|
||||||
}
|
}
|
||||||
Long("sync") => {
|
|
||||||
sync = true;
|
|
||||||
}
|
|
||||||
Long("no-sync") => {
|
|
||||||
sync = false;
|
|
||||||
}
|
|
||||||
Long("no-track") => {
|
Long("no-track") => {
|
||||||
track = false;
|
track = false;
|
||||||
}
|
}
|
||||||
|
|
@ -139,7 +136,7 @@ impl Args for Options {
|
||||||
interactive,
|
interactive,
|
||||||
set_upstream,
|
set_upstream,
|
||||||
setup_signing,
|
setup_signing,
|
||||||
sync,
|
announce,
|
||||||
track,
|
track,
|
||||||
},
|
},
|
||||||
vec![],
|
vec![],
|
||||||
|
|
@ -241,7 +238,8 @@ 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 {
|
|
||||||
|
if node.is_running() {
|
||||||
let spinner = term::spinner("Syncing inventory..");
|
let spinner = term::spinner("Syncing inventory..");
|
||||||
if let Err(e) = node.sync_inventory() {
|
if let Err(e) = node.sync_inventory() {
|
||||||
spinner.error(e);
|
spinner.error(e);
|
||||||
|
|
@ -250,6 +248,15 @@ pub fn init(options: Options, profile: &profile::Profile) -> anyhow::Result<()>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if options.announce {
|
||||||
|
let spinner = term::spinner("Announcing inventory..");
|
||||||
|
if let Err(e) = node.announce_inventory() {
|
||||||
|
spinner.error(e);
|
||||||
|
} else {
|
||||||
|
spinner.finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
term::blank();
|
term::blank();
|
||||||
term::info!(
|
term::info!(
|
||||||
"Your project id is {}. You can show it any time by running:",
|
"Your project id is {}. You can show it any time by running:",
|
||||||
|
|
@ -257,9 +264,11 @@ pub fn init(options: Options, profile: &profile::Profile) -> anyhow::Result<()>
|
||||||
);
|
);
|
||||||
term::indented(term::format::secondary("rad ."));
|
term::indented(term::format::secondary("rad ."));
|
||||||
|
|
||||||
term::blank();
|
if !options.announce {
|
||||||
term::info!("To publish your project to the network, run:");
|
term::blank();
|
||||||
term::indented(term::format::secondary("rad push"));
|
term::info!("To publish your project to the network, run:");
|
||||||
|
term::indented(term::format::secondary("rad push"));
|
||||||
|
}
|
||||||
term::blank();
|
term::blank();
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
|
|
||||||
|
|
@ -15,15 +15,13 @@ pub const HELP: Help = Help {
|
||||||
usage: r#"
|
usage: r#"
|
||||||
Usage
|
Usage
|
||||||
|
|
||||||
rad push [--all] [--[no-]sync] [<option>...]
|
rad push [--all] [<option>...]
|
||||||
|
|
||||||
By default, only the current branch is synced.
|
By default, only the current branch is pushed.
|
||||||
|
|
||||||
Options
|
Options
|
||||||
|
|
||||||
--all Push all branches (default: false)
|
--all Push all branches (default: false)
|
||||||
--sync Sync after pushing to the "rad" remote (default: false)
|
|
||||||
--no-sync Do not sync after pushing to the "rad" remote
|
|
||||||
--help Print help
|
--help Print help
|
||||||
|
|
||||||
Git options
|
Git options
|
||||||
|
|
@ -40,7 +38,6 @@ pub struct Options {
|
||||||
pub force: bool,
|
pub force: bool,
|
||||||
pub all: bool,
|
pub all: bool,
|
||||||
pub set_upstream: bool,
|
pub set_upstream: bool,
|
||||||
pub sync: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Args for Options {
|
impl Args for Options {
|
||||||
|
|
@ -51,7 +48,6 @@ impl Args for Options {
|
||||||
let mut verbose = false;
|
let mut verbose = false;
|
||||||
let mut force = false;
|
let mut force = false;
|
||||||
let mut all = false;
|
let mut all = false;
|
||||||
let mut sync = None;
|
|
||||||
let mut set_upstream = false;
|
let mut set_upstream = false;
|
||||||
|
|
||||||
while let Some(arg) = parser.next()? {
|
while let Some(arg) = parser.next()? {
|
||||||
|
|
@ -68,16 +64,6 @@ impl Args for Options {
|
||||||
Long("set-upstream") | Short('u') => {
|
Long("set-upstream") | Short('u') => {
|
||||||
set_upstream = true;
|
set_upstream = true;
|
||||||
}
|
}
|
||||||
Long("sync") => {
|
|
||||||
// Falls back to `--no-sync` in case of ambiguity.
|
|
||||||
// eg. `rad push --no-sync --sync`
|
|
||||||
if sync.is_none() {
|
|
||||||
sync = Some(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Long("no-sync") => {
|
|
||||||
sync = Some(false);
|
|
||||||
}
|
|
||||||
Long("force") | Short('f') => {
|
Long("force") | Short('f') => {
|
||||||
force = true;
|
force = true;
|
||||||
}
|
}
|
||||||
|
|
@ -92,7 +78,6 @@ impl Args for Options {
|
||||||
force,
|
force,
|
||||||
all,
|
all,
|
||||||
set_upstream,
|
set_upstream,
|
||||||
sync: sync.unwrap_or_default(),
|
|
||||||
verbose,
|
verbose,
|
||||||
},
|
},
|
||||||
vec![],
|
vec![],
|
||||||
|
|
@ -130,9 +115,5 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
|
||||||
Err(err) => return Err(err.into()),
|
Err(err) => return Err(err.into()),
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.sync {
|
|
||||||
term::warning("the `--sync` option is not yet supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -388,6 +388,7 @@ fn test_replication_via_seed() {
|
||||||
"Radicle Heartwood Protocol & Stack",
|
"Radicle Heartwood Protocol & Stack",
|
||||||
"--default-branch",
|
"--default-branch",
|
||||||
"master",
|
"master",
|
||||||
|
"--announce",
|
||||||
],
|
],
|
||||||
working.join("alice"),
|
working.join("alice"),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,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,
|
announce: false,
|
||||||
track: false,
|
track: false,
|
||||||
},
|
},
|
||||||
&profile,
|
&profile,
|
||||||
|
|
|
||||||
|
|
@ -165,6 +165,12 @@ fn command<H: Handle<Error = runtime::HandleError>>(
|
||||||
}
|
}
|
||||||
CommandResult::ok().to_writer(writer).ok();
|
CommandResult::ok().to_writer(writer).ok();
|
||||||
}
|
}
|
||||||
|
CommandName::AnnounceInventory => {
|
||||||
|
if let Err(e) = handle.announce_inventory() {
|
||||||
|
return Err(CommandError::Runtime(e));
|
||||||
|
}
|
||||||
|
CommandResult::ok().to_writer(writer).ok();
|
||||||
|
}
|
||||||
CommandName::SyncInventory => match handle.sync_inventory() {
|
CommandName::SyncInventory => match handle.sync_inventory() {
|
||||||
Ok(updated) => {
|
Ok(updated) => {
|
||||||
CommandResult::Okay { updated }.to_writer(writer)?;
|
CommandResult::Okay { updated }.to_writer(writer)?;
|
||||||
|
|
|
||||||
|
|
@ -159,6 +159,10 @@ impl<G: Signer + Ecdh + 'static> radicle::node::Handle for Handle<G> {
|
||||||
self.command(service::Command::AnnounceRefs(id))
|
self.command(service::Command::AnnounceRefs(id))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn announce_inventory(&mut self) -> Result<(), Error> {
|
||||||
|
self.command(service::Command::AnnounceInventory)
|
||||||
|
}
|
||||||
|
|
||||||
fn sync_inventory(&mut self) -> Result<bool, Error> {
|
fn sync_inventory(&mut self) -> Result<bool, Error> {
|
||||||
let (sender, receiver) = chan::bounded(1);
|
let (sender, receiver) = chan::bounded(1);
|
||||||
self.command(service::Command::SyncInventory(sender))?;
|
self.command(service::Command::SyncInventory(sender))?;
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,8 @@ pub type QueryState = dyn Fn(&dyn ServiceState) -> Result<(), CommandError> + Se
|
||||||
pub enum Command {
|
pub enum Command {
|
||||||
/// Announce repository references for given repository to peers.
|
/// Announce repository references for given repository to peers.
|
||||||
AnnounceRefs(Id),
|
AnnounceRefs(Id),
|
||||||
|
/// Announce local repositories to peers.
|
||||||
|
AnnounceInventory,
|
||||||
/// Announce local inventory to peers.
|
/// Announce local inventory to peers.
|
||||||
SyncInventory(chan::Sender<bool>),
|
SyncInventory(chan::Sender<bool>),
|
||||||
/// Connect to node with the given address.
|
/// Connect to node with the given address.
|
||||||
|
|
@ -128,6 +130,7 @@ impl fmt::Debug for Command {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Self::AnnounceRefs(id) => write!(f, "AnnounceRefs({id})"),
|
Self::AnnounceRefs(id) => write!(f, "AnnounceRefs({id})"),
|
||||||
|
Self::AnnounceInventory => write!(f, "AnnounceInventory"),
|
||||||
Self::SyncInventory(_) => write!(f, "SyncInventory(..)"),
|
Self::SyncInventory(_) => write!(f, "SyncInventory(..)"),
|
||||||
Self::Connect(id, addr) => write!(f, "Connect({id}, {addr})"),
|
Self::Connect(id, addr) => write!(f, "Connect({id}, {addr})"),
|
||||||
Self::Seeds(id, _) => write!(f, "Seeds({id})"),
|
Self::Seeds(id, _) => write!(f, "Seeds({id})"),
|
||||||
|
|
@ -516,10 +519,19 @@ where
|
||||||
error!("Error announcing refs: {}", err);
|
error!("Error announcing refs: {}", err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Command::AnnounceInventory => {
|
||||||
|
if let Err(err) = self
|
||||||
|
.storage
|
||||||
|
.inventory()
|
||||||
|
.and_then(|i| self.announce_inventory(i))
|
||||||
|
{
|
||||||
|
error!("Error announcing inventory: {}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
Command::SyncInventory(resp) => {
|
Command::SyncInventory(resp) => {
|
||||||
let updated = self
|
let updated = self
|
||||||
.sync_and_announce_inventory()
|
.sync_inventory()
|
||||||
.expect("Service::command: error syncing and announcing inventory");
|
.expect("Service::command: error syncing inventory");
|
||||||
resp.send(!updated.is_empty()).ok();
|
resp.send(!updated.is_empty()).ok();
|
||||||
}
|
}
|
||||||
Command::QueryState(query, sender) => {
|
Command::QueryState(query, sender) => {
|
||||||
|
|
@ -620,8 +632,21 @@ where
|
||||||
// cases.
|
// cases.
|
||||||
|
|
||||||
// Announce the newly fetched repository to the network, if necessary.
|
// Announce the newly fetched repository to the network, if necessary.
|
||||||
if let Err(e) = self.sync_and_announce_inventory() {
|
match self.sync_inventory() {
|
||||||
error!(target: "service", "Failed to sync announce new inventory: {e}");
|
Ok(updated) => {
|
||||||
|
if !updated.is_empty() {
|
||||||
|
if let Err(e) = self
|
||||||
|
.storage
|
||||||
|
.inventory()
|
||||||
|
.and_then(|i| self.announce_inventory(i))
|
||||||
|
{
|
||||||
|
error!(target: "service", "Failed to announce inventory: {e}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error!(target: "service", "Failed to sync inventory: {e}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1073,13 +1098,10 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sync, and if needed, announce our local inventory.
|
/// Sync, and if needed, announce our local inventory.
|
||||||
fn sync_and_announce_inventory(&mut self) -> Result<Vec<Id>, Error> {
|
fn sync_inventory(&mut self) -> Result<Vec<Id>, Error> {
|
||||||
let inventory = self.storage.inventory()?;
|
let inventory = self.storage.inventory()?;
|
||||||
let updated = self.sync_routing(&inventory, self.node_id(), self.time())?;
|
let updated = self.sync_routing(&inventory, self.node_id(), self.time())?;
|
||||||
|
|
||||||
if !updated.is_empty() {
|
|
||||||
self.announce_inventory(inventory)?;
|
|
||||||
}
|
|
||||||
Ok(updated)
|
Ok(updated)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,10 @@ impl radicle::node::Handle for Handle {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn announce_inventory(&mut self) -> Result<(), Self::Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn sync_inventory(&mut self) -> Result<bool, Self::Error> {
|
fn sync_inventory(&mut self) -> Result<bool, Self::Error> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -110,6 +110,8 @@ impl From<net::SocketAddr> for Address {
|
||||||
pub enum CommandName {
|
pub enum CommandName {
|
||||||
/// Announce repository references for given repository to peers.
|
/// Announce repository references for given repository to peers.
|
||||||
AnnounceRefs,
|
AnnounceRefs,
|
||||||
|
/// Announce local repositories to peers.
|
||||||
|
AnnounceInventory,
|
||||||
/// Sync local inventory with node.
|
/// Sync local inventory with node.
|
||||||
SyncInventory,
|
SyncInventory,
|
||||||
/// Connect to node with the given address.
|
/// Connect to node with the given address.
|
||||||
|
|
@ -382,8 +384,10 @@ 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>;
|
||||||
/// Notify the service that a project has been updated.
|
/// 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.
|
||||||
|
fn announce_inventory(&mut self) -> Result<(), Self::Error>;
|
||||||
/// Notify the service that our inventory was updated.
|
/// Notify the service that our inventory was updated.
|
||||||
fn sync_inventory(&mut self) -> Result<bool, Self::Error>;
|
fn sync_inventory(&mut self) -> Result<bool, Self::Error>;
|
||||||
/// Ask the service to shutdown.
|
/// Ask the service to shutdown.
|
||||||
|
|
@ -525,6 +529,13 @@ impl Handle for Node {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn announce_inventory(&mut self) -> Result<(), Error> {
|
||||||
|
for line in self.call::<&str, CommandResult>(CommandName::AnnounceInventory, [])? {
|
||||||
|
line?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn sync_inventory(&mut self) -> Result<bool, Error> {
|
fn sync_inventory(&mut self) -> Result<bool, Error> {
|
||||||
let mut line = self.call::<&str, _>(CommandName::SyncInventory, [])?;
|
let mut line = self.call::<&str, _>(CommandName::SyncInventory, [])?;
|
||||||
let response: CommandResult = line.next().ok_or(Error::EmptyResponse {
|
let response: CommandResult = line.next().ok_or(Error::EmptyResponse {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue