rust/msrv: 1.85.0 → 1.88.0

`cargo check` fails because `human-panic` and `sysinfo` require at least
1.88.0.

    +++ command cargo check --release --locked --all-targets
    error: rustc 1.85.0 is not supported by the following packages:
      human-panic@2.0.6 requires rustc 1.88
      sysinfo@0.37.2 requires rustc 1.88

Bump MSRV to fix this.

1.88.0 introduced [let chains], which in turn has `clippy` warn about
nested if statements. All of these sites are fixed in this change.

1.87.0 introduced [`is_multiple_of`], which is a more readable version
of `x % y == 0`.

[let chains]: https://blog.rust-lang.org/2025/06/26/Rust-1.88.0/#let-chains
[`is_multiple_of`]: https://doc.rust-lang.org/std/primitive.usize.html#method.is_multiple_of
This commit is contained in:
Lorenz Leutgeb 2026-05-07 22:31:10 +02:00 committed by Fintan Halpenny
parent 0a0e70b1d1
commit 9ea040ccd0
37 changed files with 263 additions and 264 deletions

View File

@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
## Minimum Supported Rust Version (MSRV)
The MSRV is updated to `1.88.0` due to dependencies requiring a higher bound.
This effectively puts all published crates in `heartwood` to an MSRV of `1.88.0`.
## Domain Name Migration ## Domain Name Migration
Following a domain move of the project, the names of the bootstrap nodes change: Following a domain move of the project, the names of the bootstrap nodes change:

View File

@ -16,7 +16,7 @@ version = "0.9.0"
# *per crate*. If anyone ever wants to set it to a different # *per crate*. If anyone ever wants to set it to a different
# value per crate, this is of course possible. We're waiting # value per crate, this is of course possible. We're waiting
# for the day it makes a difference… # for the day it makes a difference…
rust-version = "1.85.0" rust-version = "1.88.0"
[workspace.dependencies] [workspace.dependencies]
amplify = { version = "4.0.0", default-features = false } amplify = { version = "4.0.0", default-features = false }

View File

@ -209,10 +209,10 @@ impl TestFormula {
for result in results { for result in results {
match result { match result {
Ok(msg) => { Ok(msg) => {
if let Ok(Message::CompilerArtifact(a)) = msg.decode() { if let Ok(Message::CompilerArtifact(a)) = msg.decode()
if let Some(e) = a.executable { && let Some(e) = a.executable
log::debug!(target: "test", "Built {}", e.display()); {
} log::debug!(target: "test", "Built {}", e.display());
} }
} }
Err(e) => { Err(e) => {

View File

@ -38,10 +38,10 @@ pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {
} }
Err(e) => return Err(e.into()), Err(e) => return Err(e.into()),
}; };
if let Ok((remote, _)) = git::rad_remote(&repo) { if let Ok((remote, _)) = git::rad_remote(&repo)
if let Some(remote) = remote.url() { && let Some(remote) = remote.url()
bail!("repository is already initialized with remote {remote}"); {
} bail!("repository is already initialized with remote {remote}");
} }
if let Some(rid) = args.existing { if let Some(rid) = args.existing {

View File

@ -261,16 +261,16 @@ where
} }
}; };
if let Some(a) = assignee { if let Some(a) = assignee
if !issue.assignees().any(|v| v == &Did::from(a)) { && !issue.assignees().any(|v| v == &Did::from(a))
return None; {
} return None;
} }
if let Some(s) = state { if let Some(s) = state
if s != issue.state() { && s != issue.state()
return None; {
} return None;
} }
Some((id, issue)) Some((id, issue))

View File

@ -148,10 +148,10 @@ impl Rotate {
/// Remove the existing file, if it exists. Then create the next log, and /// Remove the existing file, if it exists. Then create the next log, and
/// create a hard link to it. /// create a hard link to it.
pub fn execute(self) -> io::Result<Rotated> { pub fn execute(self) -> io::Result<Rotated> {
if let Some(to_remove) = self.remove { if let Some(to_remove) = self.remove
if let Err(err) = to_remove.execute() { && let Err(err) = to_remove.execute()
log::warn!(target: "cli", "Failed to remove current log file: {err}"); {
} log::warn!(target: "cli", "Failed to remove current log file: {err}");
} }
let log = OpenOptions::new() let log = OpenOptions::new()

View File

@ -679,10 +679,10 @@ impl<'a> ReviewBuilder<'a> {
let total = queue.len(); let total = queue.len();
while let Some((ix, item)) = queue.next() { while let Some((ix, item)) = queue.next() {
if let Some(hunk) = self.hunk { if let Some(hunk) = self.hunk
if hunk != ix + 1 { && hunk != ix + 1
continue; {
} continue;
} }
let progress = term::format::secondary(format!("({}/{total})", ix + 1)); let progress = term::format::secondary(format!("({}/{total})", ix + 1));
let file = match file.as_mut() { let file = match file.as_mut() {

View File

@ -27,10 +27,11 @@ pub fn run(args: Args, ctx: impl term::Context) -> anyhow::Result<()> {
for rid in rids { for rid in rids {
update(rid, scope, &mut node, &profile)?; update(rid, scope, &mut node, &profile)?;
if should_fetch && node.is_running() { if should_fetch
if let Err(e) = sync::fetch(rid, settings.clone(), &mut node, &profile) { && node.is_running()
term::error(e); && let Err(e) = sync::fetch(rid, settings.clone(), &mut node, &profile)
} {
term::error(e);
} }
} }
} }
@ -57,11 +58,11 @@ pub fn update(
let updated = profile.seed(rid, scope, node)?; let updated = profile.seed(rid, scope, node)?;
let outcome = if updated { "updated" } else { "exists" }; let outcome = if updated { "updated" } else { "exists" };
if let Ok(repo) = profile.storage.repository(rid) { if let Ok(repo) = profile.storage.repository(rid)
if repo.identity_doc()?.is_public() { && repo.identity_doc()?.is_public()
profile.add_inventory(rid, node)?; {
term::success!("Inventory updated with {}", term::format::tertiary(rid)); profile.add_inventory(rid, node)?;
} term::success!("Inventory updated with {}", term::format::tertiary(rid));
} }
term::success!( term::success!(

View File

@ -381,10 +381,10 @@ pub fn commit_ssh_fingerprint(path: &Path, sha1: &str) -> Result<Option<String>,
.transpose()?; .transpose()?;
// We only return a fingerprint if it's not an empty string // We only return a fingerprint if it's not an empty string
if let Some(s) = string { if let Some(s) = string
if !s.is_empty() { && !s.is_empty()
return Ok(Some(s)); {
} return Ok(Some(s));
} }
Ok(None) Ok(None)

View File

@ -65,10 +65,10 @@ pub fn fail(error: &anyhow::Error) {
} }
// Catch common node errors, and offer a hint. // Catch common node errors, and offer a hint.
if let Some(e) = error.downcast_ref::<radicle::node::Error>() { if let Some(e) = error.downcast_ref::<radicle::node::Error>()
if e.is_connection_err() { && e.is_connection_err()
io::hint("to start your node, run `rad node start`."); {
} io::hint("to start your node, run `rad node start`.");
} }
if let Some(Error::WithHint { hint, .. }) = error.downcast_ref::<Error>() { if let Some(Error::WithHint { hint, .. }) = error.downcast_ref::<Error>() {
io::hint(hint); io::hint(hint);

View File

@ -39,10 +39,10 @@ impl MigrateCallback for MigrateSpinner {
progress.rows.percentage() progress.rows.percentage()
)); ));
if progress.is_done() { if progress.is_done()
if let Some(spinner) = self.spinner.take() { && let Some(spinner) = self.spinner.take()
spinner.finish() {
} spinner.finish()
} }
} }
} }

View File

@ -89,10 +89,10 @@ pub fn branches(target: &Oid, repo: &git::raw::Repository) -> anyhow::Result<Vec
if !r.is_branch() { if !r.is_branch() {
continue; continue;
} }
if let (Some(oid), Some(name)) = (&r.target(), &r.shorthand()) { if let (Some(oid), Some(name)) = (&r.target(), &r.shorthand())
if target == oid { && target == oid
branches.push(name.to_string()); {
}; branches.push(name.to_string());
}; };
} }
Ok(branches) Ok(branches)

View File

@ -119,12 +119,12 @@ impl Keystore {
}); });
} }
if let Some(path_public) = &self.path_public { if let Some(path_public) = &self.path_public
if path_public.exists() { && path_public.exists()
return Err(Error::AlreadyInitialized { {
exists: path_public.to_path_buf(), return Err(Error::AlreadyInitialized {
}); exists: path_public.to_path_buf(),
} });
} }
// NOTE: If [`PathBuf::parent`] returns `None`, // NOTE: If [`PathBuf::parent`] returns `None`,

View File

@ -330,13 +330,13 @@ impl<K: Ord + Copy, V> Dag<K, V> {
stack.extend(from.dependents.iter()); stack.extend(from.dependents.iter());
while let Some(key) = stack.pop_front() { while let Some(key) = stack.pop_front() {
if let Some(node) = self.graph.get(&key) { if let Some(node) = self.graph.get(&key)
if visited.insert(key) { && visited.insert(key)
nodes.push(key); {
nodes.push(key);
for &neighbour in &node.dependents { for &neighbour in &node.dependents {
stack.push_back(neighbour); stack.push_back(neighbour);
}
} }
} }
} }
@ -351,13 +351,13 @@ impl<K: Ord + Copy, V> Dag<K, V> {
stack.extend(from.dependencies.iter()); stack.extend(from.dependencies.iter());
while let Some(key) = stack.pop_front() { while let Some(key) = stack.pop_front() {
if let Some(node) = self.graph.get(&key) { if let Some(node) = self.graph.get(&key)
if visited.insert(key) { && visited.insert(key)
nodes.push(key); {
nodes.push(key);
for &neighbour in &node.dependencies { for &neighbour in &node.dependencies {
stack.push_back(neighbour); stack.push_back(neighbour);
}
} }
} }
} }

View File

@ -155,10 +155,10 @@ fn parse_body(body: &str) -> (String, Vec<OwnedTrailer>) {
if let Some(split) = body.rfind("\n\n") { if let Some(split) = body.rfind("\n\n") {
let candidate = &body[split + 2..]; let candidate = &body[split + 2..];
// Only treat non-empty paragraphs as trailers. // Only treat non-empty paragraphs as trailers.
if !candidate.trim().is_empty() { if !candidate.trim().is_empty()
if let Some(trailers) = try_parse_trailers(candidate) { && let Some(trailers) = try_parse_trailers(candidate)
return (body[..split].to_string(), trailers); {
} return (body[..split].to_string(), trailers);
} }
} }

View File

@ -301,15 +301,15 @@ impl<S: Session + Source> EventHandler for Transport<S> {
fn handle(&mut self, event: &Event) -> Vec<Self::Reaction> { fn handle(&mut self, event: &Event) -> Vec<Self::Reaction> {
let mut events = Vec::with_capacity(2); let mut events = Vec::with_capacity(2);
if event.is_writable() { if event.is_writable()
if let Some(event) = self.handle_io(Interest::WRITABLE) { && let Some(event) = self.handle_io(Interest::WRITABLE)
events.push(event); {
} events.push(event);
} }
if event.is_readable() { if event.is_readable()
if let Some(event) = self.handle_io(Interest::READABLE) { && let Some(event) = self.handle_io(Interest::READABLE)
events.push(event); {
} events.push(event);
} }
events events
} }

View File

@ -174,10 +174,10 @@ impl radicle::node::Handle for Handle {
let sessions = self.sessions()?; let sessions = self.sessions()?;
let session = sessions.iter().find(|s| s.nid == node); let session = sessions.iter().find(|s| s.nid == node);
if let Some(s) = session { if let Some(s) = session
if s.state.is_connected() { && s.state.is_connected()
return Ok(ConnectResult::Connected); {
} return Ok(ConnectResult::Connected);
} }
self.command(service::Command::Connect(node, addr, opts))?; self.command(service::Command::Connect(node, addr, opts))?;

View File

@ -249,11 +249,11 @@ impl<G: Signer<Signature> + cyphernet::Ecdh> NodeHandle<G> {
let events = self.handle.events(); let events = self.handle.events();
loop { loop {
if let Ok(repo) = self.storage.repository(*rid) { if let Ok(repo) = self.storage.repository(*rid)
if repo.remote(nid).is_ok() { && repo.remote(nid).is_ok()
log::debug!(target: "test", "Node {} has {rid}/{nid}", self.id); {
break; log::debug!(target: "test", "Node {} has {rid}/{nid}", self.id);
} break;
} }
events events
.wait( .wait(

View File

@ -329,22 +329,21 @@ where
pub fn refs_announcement(&self, rid: RepoId) -> Message { pub fn refs_announcement(&self, rid: RepoId) -> Message {
let mut refs = BoundedVec::new(); let mut refs = BoundedVec::new();
if let Ok(repo) = self.storage().repository(rid) { if let Ok(repo) = self.storage().repository(rid)
if let Ok(false) = repo.is_empty() { && let Ok(false) = repo.is_empty()
if let Ok(remotes) = repo.remotes() { && let Ok(remotes) = repo.remotes()
for (remote_id, _) in remotes.into_iter() { {
match RefsAt::new(&repo, remote_id) { for (remote_id, _) in remotes.into_iter() {
Ok(refs_at) => { match RefsAt::new(&repo, remote_id) {
if let Err(e) = refs.push(refs_at) { Ok(refs_at) => {
debug!(target: "test", "Failed to push {remote_id} to refs: {e}"); if let Err(e) = refs.push(refs_at) {
break; debug!(target: "test", "Failed to push {remote_id} to refs: {e}");
} break;
}
Err(e) => {
debug!(target: "test", "Failed to get `rad/sigrefs` for {remote_id}: {e}")
}
} }
} }
Err(e) => {
debug!(target: "test", "Failed to get `rad/sigrefs` for {remote_id}: {e}")
}
} }
} }
} }

View File

@ -331,7 +331,7 @@ where
// between individual nodes. We need to think about more realistic // between individual nodes. We need to think about more realistic
// scenarios. We should also think about creating various network // scenarios. We should also think about creating various network
// topologies. // topologies.
if self.time.as_secs() % 10 == 0 { if self.time.as_secs().is_multiple_of(10) {
for (i, x) in nodes.keys().enumerate() { for (i, x) in nodes.keys().enumerate() {
for y in nodes.keys().skip(i + 1) { for y in nodes.keys().skip(i + 1) {
if self.is_fallible() { if self.is_fallible() {

View File

@ -186,12 +186,12 @@ fn notify(
// for sigref verification. // for sigref verification.
continue; continue;
} }
if let Some(rest) = r.strip_prefix(git::fmt::refname!("refs/heads/patches")) { if let Some(rest) = r.strip_prefix(git::fmt::refname!("refs/heads/patches"))
if radicle::cob::ObjectId::from_str(rest.as_str()).is_ok() { && radicle::cob::ObjectId::from_str(rest.as_str()).is_ok()
// Don't notify about patch branches, since we already get {
// notifications about patch updates. // Don't notify about patch branches, since we already get
continue; // notifications about patch updates.
} continue;
} }
} }
if let RefUpdate::Skipped { .. } = update { if let RefUpdate::Skipped { .. } = update {

View File

@ -464,10 +464,10 @@ where
continue; continue;
}; };
// Skip this repo if the sync status matches what we have in storage. // Skip this repo if the sync status matches what we have in storage.
if let Some(announced) = announced.get(&rid) { if let Some(announced) = announced.get(&rid)
if updated_at.oid == announced.oid { && updated_at.oid == announced.oid
continue; {
} continue;
} }
// Make sure our local node's sync status is up to date with storage. // Make sure our local node's sync status is up to date with storage.
if self.db.seeds_mut().synced( if self.db.seeds_mut().synced(
@ -1300,16 +1300,14 @@ where
self.outbox.write_all(peer, msgs); self.outbox.write_all(peer, msgs);
} }
Entry::Vacant(e) => { Entry::Vacant(e) => {
if let HostName::Ip(ip) = addr.host { if let HostName::Ip(ip) = addr.host
if !address::is_local(&ip) { && !address::is_local(&ip)
if let Err(e) = && let Err(e) =
self.db self.db
.addresses_mut() .addresses_mut()
.record_ip(&remote, ip, self.clock.into()) .record_ip(&remote, ip, self.clock.into())
{ {
log::debug!(target: "service", "Failed to record IP address for {remote}: {e}"); log::debug!(target: "service", "Failed to record IP address for {remote}: {e}");
}
}
} }
let peer = e.insert(Session::inbound( let peer = e.insert(Session::inbound(
remote, remote,
@ -1811,20 +1809,20 @@ where
let relayer = remote; let relayer = remote;
let relayer_addr = peer.addr.clone(); let relayer_addr = peer.addr.clone();
if let Some(id) = self.handle_announcement(relayer, &relayer_addr, &ann)? { if let Some(id) = self.handle_announcement(relayer, &relayer_addr, &ann)?
if self.config.is_relay() { && self.config.is_relay()
if let AnnouncementMessage::Inventory(_) = ann.message { {
if let Err(e) = self if let AnnouncementMessage::Inventory(_) = ann.message {
.database_mut() if let Err(e) = self
.gossip_mut() .database_mut()
.set_relay(id, gossip::RelayStatus::Relay) .gossip_mut()
{ .set_relay(id, gossip::RelayStatus::Relay)
warn!(target: "service", "Failed to set relay flag for message: {e}"); {
return Ok(()); warn!(target: "service", "Failed to set relay flag for message: {e}");
} return Ok(());
} else {
self.relay(id, ann);
} }
} else {
self.relay(id, ann);
} }
} }
} }
@ -1876,20 +1874,18 @@ where
); );
} }
Message::Pong { zeroes } => { Message::Pong { zeroes } => {
if let Some((ping, latencies)) = connected { if let Some((ping, latencies)) = connected
if let session::PingState::AwaitingResponse { && let session::PingState::AwaitingResponse {
len: ponglen, len: ponglen,
since, since,
} = *ping } = *ping
{ && (ponglen as usize) == zeroes.len()
if (ponglen as usize) == zeroes.len() { {
*ping = session::PingState::Ok; *ping = session::PingState::Ok;
// Keep track of peer latency. // Keep track of peer latency.
latencies.push_back(self.clock - since); latencies.push_back(self.clock - since);
if latencies.len() > MAX_LATENCIES { if latencies.len() > MAX_LATENCIES {
latencies.pop_front(); latencies.pop_front();
}
}
} }
} }
} }
@ -1929,11 +1925,11 @@ where
/// Add a seed to our routing table. /// Add a seed to our routing table.
fn seed_discovered(&mut self, rid: RepoId, nid: NodeId, time: Timestamp) { fn seed_discovered(&mut self, rid: RepoId, nid: NodeId, time: Timestamp) {
if let Ok(result) = self.db.routing_mut().add_inventory([&rid], nid, time) { if let Ok(result) = self.db.routing_mut().add_inventory([&rid], nid, time)
if let &[(_, InsertResult::SeedAdded)] = result.as_slice() { && let &[(_, InsertResult::SeedAdded)] = result.as_slice()
self.emitter.emit(Event::SeedDiscovered { rid, nid }); {
debug!(target: "service", "Routing table updated for {rid} with seed {nid}"); self.emitter.emit(Event::SeedDiscovered { rid, nid });
} debug!(target: "service", "Routing table updated for {rid} with seed {nid}");
} }
} }

View File

@ -36,10 +36,10 @@ impl RateLimiter {
tokens: &T, tokens: &T,
now: LocalTime, now: LocalTime,
) -> bool { ) -> bool {
if let Some(nid) = nid { if let Some(nid) = nid
if self.bypass.contains(nid) { && self.bypass.contains(nid)
return false; {
} return false;
} }
if let HostName::Ip(ip) = addr { if let HostName::Ip(ip) = addr {
// Don't limit LAN addresses. // Don't limit LAN addresses.

View File

@ -218,12 +218,12 @@ impl Session {
ref mut stable, ref mut stable,
.. ..
} = self.state } = self.state
&& now >= since
&& now.duration_since(since) >= CONNECTION_STABLE_THRESHOLD
{ {
if now >= since && now.duration_since(since) >= CONNECTION_STABLE_THRESHOLD { *stable = true;
*stable = true; // Reset number of attempts for stable connections.
// Reset number of attempts for stable connections. self.attempts = 0;
self.attempts = 0;
}
} }
} }

View File

@ -245,10 +245,10 @@ fn run(profile: radicle::Profile) -> Result<(), Error> {
let git = service::RealGitService; let git = service::RealGitService;
let mut node = service::RealNodeSession::new(&profile); 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 { && debug
eprintln!("{}: unable to set open file limit: {e}", VERSION.name); {
} eprintln!("{}: unable to set open file limit: {e}", VERSION.name);
} }
run_loop( run_loop(

View File

@ -662,17 +662,15 @@ where
// Set up current branch so that pushing updates the patch. // Set up current branch so that pushing updates the patch.
else if let Some(branch) = else if let Some(branch) =
rad::setup_patch_upstream(&patch, *head, working, upstream, false)? rad::setup_patch_upstream(&patch, *head, working, upstream, false)?
&& let Some(name) = branch.name()?
&& profile.hints()
{ {
if let Some(name) = branch.name()? { // Remove the remote portion of the name, i.e.
if profile.hints() { // rad/patches/deadbeef -> patches/deadbeef
// Remove the remote portion of the name, i.e. let name = name.split_once('/').unwrap_or_default().1;
// rad/patches/deadbeef -> patches/deadbeef hint(format!(
let name = name.split_once('/').unwrap_or_default().1; "to update, run `git push` or `git push {upstream} --force-with-lease HEAD:{name}`"
hint(format!( ));
"to update, run `git push` or `git push {upstream} --force-with-lease HEAD:{name}`"
));
}
}
} }
} }

View File

@ -204,15 +204,15 @@ impl Editor {
/// Get the default editor command. /// Get the default editor command.
fn default_editor() -> Option<OsString> { fn default_editor() -> Option<OsString> {
// First check the standard environment variables. // First check the standard environment variables.
if let Ok(visual) = env::var("VISUAL") { if let Ok(visual) = env::var("VISUAL")
if !visual.is_empty() { && !visual.is_empty()
return Some(visual.into()); {
} return Some(visual.into());
} }
if let Ok(editor) = env::var("EDITOR") { if let Ok(editor) = env::var("EDITOR")
if !editor.is_empty() { && !editor.is_empty()
return Some(editor.into()); {
} return Some(editor.into());
} }
// Check Git. The user might have configured their editor there. // Check Git. The user might have configured their editor there.

View File

@ -59,10 +59,10 @@ pub struct Spinner {
impl Drop for Spinner { impl Drop for Spinner {
fn drop(&mut self) { fn drop(&mut self) {
if let Ok(mut progress) = self.progress.lock() { if let Ok(mut progress) = self.progress.lock()
if let State::Running = progress.state { && let State::Running = progress.state
progress.state = State::Canceled; {
} progress.state = State::Canceled;
} }
unsafe { ManuallyDrop::take(&mut self.handle) } unsafe { ManuallyDrop::take(&mut self.handle) }

View File

@ -48,11 +48,11 @@ pub fn run(
.ok_or(Error::MalformedJsonSchema)?; .ok_or(Error::MalformedJsonSchema)?;
for (_, review) in reviews.iter_mut() { for (_, review) in reviews.iter_mut() {
if let Some(list) = review.as_array_mut() { if let Some(list) = review.as_array_mut()
if let Some(last) = list.pop() { && let Some(last) = list.pop()
*review = last; {
transformed = true; *review = last;
} transformed = true;
} }
} }
} }

View File

@ -726,10 +726,10 @@ impl Patch {
review, comment, .. review, comment, ..
} }
| Action::ReviewCommentRedact { review, comment } => { | Action::ReviewCommentRedact { review, comment } => {
if let Some((_, review)) = lookup::review(self, review)? { if let Some((_, review)) = lookup::review(self, review)?
if let Some(comment) = review.comments.comment(comment) { && let Some(comment) = review.comments.comment(comment)
return Ok(Authorization::from(*actor == comment.author())); {
} return Ok(Authorization::from(*actor == comment.author()));
} }
// Redacted. // Redacted.
Authorization::Unknown Authorization::Unknown
@ -739,14 +739,14 @@ impl Patch {
// The reviewer, commenter or revision author can resolve and unresolve review comments. // The reviewer, commenter or revision author can resolve and unresolve review comments.
Action::ReviewCommentResolve { review, comment } Action::ReviewCommentResolve { review, comment }
| Action::ReviewCommentUnresolve { review, comment } => { | Action::ReviewCommentUnresolve { review, comment } => {
if let Some((revision, review)) = lookup::review(self, review)? { if let Some((revision, review)) = lookup::review(self, review)?
if let Some(comment) = review.comments.comment(comment) { && let Some(comment) = review.comments.comment(comment)
return Ok(Authorization::from( {
actor == &comment.author() return Ok(Authorization::from(
|| actor == review.author.public_key() actor == &comment.author()
|| actor == revision.author.public_key(), || actor == review.author.public_key()
)); || actor == revision.author.public_key(),
} ));
} }
// Redacted. // Redacted.
Authorization::Unknown Authorization::Unknown
@ -773,10 +773,10 @@ impl Patch {
| Action::RevisionCommentRedact { | Action::RevisionCommentRedact {
revision, comment, .. revision, comment, ..
} => { } => {
if let Some(revision) = lookup::revision(self, revision)? { if let Some(revision) = lookup::revision(self, revision)?
if let Some(comment) = revision.discussion.comment(comment) { && let Some(comment) = revision.discussion.comment(comment)
return Ok(Authorization::from(actor == &comment.author())); {
} return Ok(Authorization::from(actor == &comment.author()));
} }
// Redacted. // Redacted.
Authorization::Unknown Authorization::Unknown

View File

@ -399,10 +399,10 @@ impl<L> Thread<Comment<L>> {
to: &'a CommentId, to: &'a CommentId,
) -> impl Iterator<Item = (&'a CommentId, &'a Comment<L>)> { ) -> impl Iterator<Item = (&'a CommentId, &'a Comment<L>)> {
self.comments().filter_map(move |(id, c)| { self.comments().filter_map(move |(id, c)| {
if let Some(reply_to) = c.reply_to { if let Some(reply_to) = c.reply_to
if &reply_to == to { && &reply_to == to
return Some((id, c)); {
} return Some((id, c));
} }
None None
}) })
@ -503,10 +503,10 @@ pub fn comment<L>(
if body.is_empty() { if body.is_empty() {
return Err(Error::Comment(id)); return Err(Error::Comment(id));
} }
if let Some(id) = reply_to { if let Some(id) = reply_to
if !thread.comments.contains_key(&id) { && !thread.comments.contains_key(&id)
return Err(Error::Missing(id)); {
} return Err(Error::Missing(id));
} }
debug_assert!(!thread.timeline.contains(&id)); debug_assert!(!thread.timeline.contains(&id));
thread.timeline.push(id); thread.timeline.push(id);

View File

@ -347,19 +347,19 @@ impl SymbolicRefs {
// A [`Target::Direct`] whose string is already a key is actually // A [`Target::Direct`] whose string is already a key is actually
// an intermediate link — downgrade to [`Target::Symbolic`]. // an intermediate link — downgrade to [`Target::Symbolic`].
if let Target::Direct(q) = &target { if let Target::Direct(q) = &target
if self.0.contains_key(&q.as_ref().to_ref_string()) { && self.0.contains_key(&q.as_ref().to_ref_string())
target = Target::symbolic(q.to_ref_string()); {
} target = Target::symbolic(q.to_ref_string());
} }
if let Target::Symbolic(s) = &target { if let Target::Symbolic(s) = &target
if self.resolve(s.as_ref()).is_none() { && self.resolve(s.as_ref()).is_none()
return Err(InsertionError::TargetNotQualified { {
name: name.into_inner(), return Err(InsertionError::TargetNotQualified {
target: target_str, name: name.into_inner(),
}); target: target_str,
} });
} }
self.reclassify_targets(&name); self.reclassify_targets(&name);
@ -373,10 +373,10 @@ impl SymbolicRefs {
fn reclassify_targets(&mut self, new_key: &Name) { fn reclassify_targets(&mut self, new_key: &Name) {
let key = new_key.as_ref(); let key = new_key.as_ref();
for existing in self.0.values_mut() { for existing in self.0.values_mut() {
if let Target::Direct(q) = existing { if let Target::Direct(q) = existing
if q == key { && q == key
*existing = Target::symbolic(q.to_ref_string()); {
} *existing = Target::symbolic(q.to_ref_string());
} }
} }
} }

View File

@ -91,10 +91,10 @@ pub mod env {
// because of the complexity surrounding how the pager command is // because of the complexity surrounding how the pager command is
// parsed and executed. See also <https://stackoverflow.com/a/773973/1835188>. // parsed and executed. See also <https://stackoverflow.com/a/773973/1835188>.
#[cfg(not(windows))] #[cfg(not(windows))]
if let Ok(cfg) = crate::git::raw::Config::open_default() { if let Ok(cfg) = crate::git::raw::Config::open_default()
if let Ok(pager) = cfg.get_string("core.pager") { && let Ok(pager) = cfg.get_string("core.pager")
return Some(pager); {
} return Some(pager);
} }
if let Ok(pager) = var("PAGER") { if let Ok(pager) = var("PAGER") {
return Some(pager); return Some(pager);

View File

@ -187,18 +187,18 @@ impl Config {
// Handle deprecated policy configuration. // Handle deprecated policy configuration.
// Nb. This will override "seedingPolicy" if set! This code should be removed after 1.0. // Nb. This will override "seedingPolicy" if set! This code should be removed after 1.0.
if let (Some(p), Some(s)) = (cfg.node.extra.get("policy"), cfg.node.extra.get("scope")) { if let (Some(p), Some(s)) = (cfg.node.extra.get("policy"), cfg.node.extra.get("scope"))
if let (Ok(policy), Ok(scope)) = ( && let (Ok(policy), Ok(scope)) = (
json::from_value::<Policy>(p.clone()), json::from_value::<Policy>(p.clone()),
json::from_value::<Scope>(s.clone()), json::from_value::<Scope>(s.clone()),
) { )
log::warn!(target: "radicle", "Overwriting `seedingPolicy` configuration"); {
cfg.node.seeding_policy = match policy { log::warn!(target: "radicle", "Overwriting `seedingPolicy` configuration");
Policy::Allow => DefaultSeedingPolicy::Allow { cfg.node.seeding_policy = match policy {
scope: node::config::Scope::explicit(scope), Policy::Allow => DefaultSeedingPolicy::Allow {
}, scope: node::config::Scope::explicit(scope),
Policy::Block => DefaultSeedingPolicy::Block, },
} Policy::Block => DefaultSeedingPolicy::Block,
} }
} }
Ok(cfg) Ok(cfg)

View File

@ -85,10 +85,10 @@ where
if let Err(e) = project.remove() { if let Err(e) = project.remove() {
log::warn!(target: "radicle", "Failed to remove project during `rad::init` cleanup: {e}"); log::warn!(target: "radicle", "Failed to remove project during `rad::init` cleanup: {e}");
} }
if repo.find_remote(&REMOTE_NAME).is_ok() { if repo.find_remote(&REMOTE_NAME).is_ok()
if let Err(e) = repo.remote_delete(&REMOTE_NAME) { && let Err(e) = repo.remote_delete(&REMOTE_NAME)
log::warn!(target: "radicle", "Failed to remove remote during `rad::init` cleanup: {e}"); {
} log::warn!(target: "radicle", "Failed to remove remote during `rad::init` cleanup: {e}");
} }
Err(err) Err(err)
} }
@ -497,10 +497,10 @@ pub fn setup_patch_upstream<'a>(
)?; )?;
assert!(remote_branch.is_remote()); assert!(remote_branch.is_remote());
if let Some(name) = name { if let Some(name) = name
if force || branch.upstream().is_err() { && (force || branch.upstream().is_err())
git::set_upstream(working, remote, name.as_str(), git::refs::patch(patch))?; {
} git::set_upstream(working, remote, name.as_str(), git::refs::patch(patch))?;
} }
Ok(Some(crate::git::raw::Branch::wrap(remote_branch))) Ok(Some(crate::git::raw::Branch::wrap(remote_branch)))
} }

View File

@ -842,10 +842,10 @@ impl ReadRepository for Repository {
fn head(&self) -> Result<(Qualified<'_>, Oid), RepositoryError> { fn head(&self) -> Result<(Qualified<'_>, Oid), RepositoryError> {
// If `HEAD` is already set locally, just return that. // If `HEAD` is already set locally, just return that.
if let Ok(head) = self.backend.head() { if let Ok(head) = self.backend.head()
if let Ok((name, oid)) = git::refs::qualified_from(&head) { && let Ok((name, oid)) = git::refs::qualified_from(&head)
return Ok((name.to_owned(), oid)); {
} return Ok((name.to_owned(), oid));
} }
self.canonical_head() self.canonical_head()
} }

View File

@ -34,12 +34,12 @@ pub fn fetch<W: WriteRepository>(
}; };
callbacks.update_tips(|name, old, new| { callbacks.update_tips(|name, old, new| {
if let Ok(name) = git::fmt::RefString::try_from(name) { if let Ok(name) = git::fmt::RefString::try_from(name)
if name.to_namespaced().is_some() { && name.to_namespaced().is_some()
updates.push(RefUpdate::from(name, old, new)); {
// Returning `true` ensures the process is not aborted. updates.push(RefUpdate::from(name, old, new));
return true; // Returning `true` ensures the process is not aborted.
} return true;
} }
false false
}); });