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:
parent
0a0e70b1d1
commit
9ea040ccd0
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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 }
|
||||||
|
|
|
||||||
|
|
@ -209,12 +209,12 @@ 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) => {
|
||||||
log::error!(target: "test", "Error building package `{package}`: {e}");
|
log::error!(target: "test", "Error building package `{package}`: {e}");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,11 +38,11 @@ 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 {
|
||||||
init_existing(repo, rid, args, &profile)
|
init_existing(repo, rid, args, &profile)
|
||||||
|
|
|
||||||
|
|
@ -261,17 +261,17 @@ 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))
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -148,11 +148,11 @@ 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()
|
||||||
.write(true)
|
.write(true)
|
||||||
|
|
|
||||||
|
|
@ -679,11 +679,11 @@ 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() {
|
||||||
Some(fr) => fr.set_item(&item),
|
Some(fr) => fr.set_item(&item),
|
||||||
|
|
|
||||||
|
|
@ -27,14 +27,15 @@ 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()
|
||||||
|
&& let Err(e) = sync::fetch(rid, settings.clone(), &mut node, &profile)
|
||||||
|
{
|
||||||
term::error(e);
|
term::error(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -57,12 +58,12 @@ 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)?;
|
profile.add_inventory(rid, node)?;
|
||||||
term::success!("Inventory updated with {}", term::format::tertiary(rid));
|
term::success!("Inventory updated with {}", term::format::tertiary(rid));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
term::success!(
|
term::success!(
|
||||||
"Seeding policy {outcome} for {} with scope '{scope}'",
|
"Seeding policy {outcome} for {} with scope '{scope}'",
|
||||||
|
|
|
||||||
|
|
@ -381,11 +381,11 @@ 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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -65,11 +65,11 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,13 +39,13 @@ 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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Migrate functions.
|
/// Migrate functions.
|
||||||
pub mod migrate {
|
pub mod migrate {
|
||||||
|
|
|
||||||
|
|
@ -89,11 +89,11 @@ 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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -119,13 +119,13 @@ 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 {
|
return Err(Error::AlreadyInitialized {
|
||||||
exists: path_public.to_path_buf(),
|
exists: path_public.to_path_buf(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: If [`PathBuf::parent`] returns `None`,
|
// NOTE: If [`PathBuf::parent`] returns `None`,
|
||||||
// then the path is at root or empty, so don't
|
// then the path is at root or empty, so don't
|
||||||
|
|
|
||||||
|
|
@ -330,8 +330,9 @@ 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 {
|
||||||
|
|
@ -339,7 +340,6 @@ impl<K: Ord + Copy, V> Dag<K, V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
nodes
|
nodes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -351,8 +351,9 @@ 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 {
|
||||||
|
|
@ -360,7 +361,6 @@ impl<K: Ord + Copy, V> Dag<K, V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
nodes
|
nodes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -155,12 +155,12 @@ 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
(body.to_string(), Vec::new())
|
(body.to_string(), Vec::new())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -301,16 +301,16 @@ 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() {
|
&& let Some(event) = self.handle_io(Interest::READABLE)
|
||||||
if let Some(event) = self.handle_io(Interest::READABLE) {
|
{
|
||||||
events.push(event);
|
events.push(event);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
events
|
events
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -174,11 +174,11 @@ 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))?;
|
||||||
|
|
||||||
events
|
events
|
||||||
|
|
|
||||||
|
|
@ -249,12 +249,12 @@ 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);
|
log::debug!(target: "test", "Node {} has {rid}/{nid}", self.id);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
events
|
events
|
||||||
.wait(
|
.wait(
|
||||||
|e| matches!(e, Event::RefsFetched { .. }).then_some(()),
|
|e| matches!(e, Event::RefsFetched { .. }).then_some(()),
|
||||||
|
|
|
||||||
|
|
@ -329,9 +329,10 @@ 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() {
|
for (remote_id, _) in remotes.into_iter() {
|
||||||
match RefsAt::new(&repo, remote_id) {
|
match RefsAt::new(&repo, remote_id) {
|
||||||
Ok(refs_at) => {
|
Ok(refs_at) => {
|
||||||
|
|
@ -346,8 +347,6 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.announcement(RefsAnnouncement {
|
self.announcement(RefsAnnouncement {
|
||||||
rid,
|
rid,
|
||||||
|
|
|
||||||
|
|
@ -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() {
|
||||||
|
|
|
||||||
|
|
@ -186,14 +186,14 @@ 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
|
// Don't notify about patch branches, since we already get
|
||||||
// notifications about patch updates.
|
// notifications about patch updates.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if let RefUpdate::Skipped { .. } = update {
|
if let RefUpdate::Skipped { .. } = update {
|
||||||
// Don't notify about skipped refs.
|
// Don't notify about skipped refs.
|
||||||
} else if let Err(e) = store.insert(rid, update, now) {
|
} else if let Err(e) = store.insert(rid, update, now) {
|
||||||
|
|
|
||||||
|
|
@ -464,11 +464,11 @@ 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(
|
||||||
&rid,
|
&rid,
|
||||||
|
|
@ -1300,17 +1300,15 @@ 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,
|
||||||
addr,
|
addr,
|
||||||
|
|
@ -1811,8 +1809,9 @@ 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 AnnouncementMessage::Inventory(_) = ann.message {
|
||||||
if let Err(e) = self
|
if let Err(e) = self
|
||||||
.database_mut()
|
.database_mut()
|
||||||
|
|
@ -1827,7 +1826,6 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Message::Subscribe(subscribe) => {
|
Message::Subscribe(subscribe) => {
|
||||||
// Filter announcements by interest.
|
// Filter announcements by interest.
|
||||||
match self
|
match self
|
||||||
|
|
@ -1876,13 +1874,13 @@ 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);
|
||||||
|
|
@ -1892,8 +1890,6 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1929,13 +1925,13 @@ 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 });
|
self.emitter.emit(Event::SeedDiscovered { rid, nid });
|
||||||
debug!(target: "service", "Routing table updated for {rid} with seed {nid}");
|
debug!(target: "service", "Routing table updated for {rid} with seed {nid}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Set of initial messages to send to a peer.
|
/// Set of initial messages to send to a peer.
|
||||||
fn initial(&mut self, _link: Link) -> Vec<Message> {
|
fn initial(&mut self, _link: Link) -> Vec<Message> {
|
||||||
|
|
|
||||||
|
|
@ -36,11 +36,11 @@ 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.
|
||||||
if !address::is_routable(&ip) {
|
if !address::is_routable(&ip) {
|
||||||
|
|
|
||||||
|
|
@ -218,14 +218,14 @@ 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_attempted(&mut self) {
|
pub fn to_attempted(&mut self) {
|
||||||
assert!(
|
assert!(
|
||||||
|
|
|
||||||
|
|
@ -245,11 +245,11 @@ 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(
|
||||||
stdin.lock(),
|
stdin.lock(),
|
||||||
|
|
|
||||||
|
|
@ -662,9 +662,9 @@ 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()? {
|
|
||||||
if profile.hints() {
|
|
||||||
// Remove the remote portion of the name, i.e.
|
// Remove the remote portion of the name, i.e.
|
||||||
// rad/patches/deadbeef -> patches/deadbeef
|
// rad/patches/deadbeef -> patches/deadbeef
|
||||||
let name = name.split_once('/').unwrap_or_default().1;
|
let name = name.split_once('/').unwrap_or_default().1;
|
||||||
|
|
@ -673,8 +673,6 @@ where
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Some(ExplorerResource::Patch { id: patch }))
|
Ok(Some(ExplorerResource::Patch { id: patch }))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -204,16 +204,16 @@ 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") {
|
&& !editor.is_empty()
|
||||||
if !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.
|
||||||
// On Windows, custom editors configured via Git are not supported,
|
// On Windows, custom editors configured via Git are not supported,
|
||||||
|
|
|
||||||
|
|
@ -59,11 +59,11 @@ 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) }
|
||||||
.join()
|
.join()
|
||||||
|
|
|
||||||
|
|
@ -48,14 +48,14 @@ 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;
|
*review = last;
|
||||||
transformed = true;
|
transformed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if transformed {
|
if transformed {
|
||||||
let obj = json::to_string(&patch).map_err(Error::MalformedJson)?;
|
let obj = json::to_string(&patch).map_err(Error::MalformedJson)?;
|
||||||
|
|
|
||||||
|
|
@ -726,11 +726,11 @@ 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,15 +739,15 @@ 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(
|
return Ok(Authorization::from(
|
||||||
actor == &comment.author()
|
actor == &comment.author()
|
||||||
|| actor == review.author.public_key()
|
|| actor == review.author.public_key()
|
||||||
|| actor == revision.author.public_key(),
|
|| actor == revision.author.public_key(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// Redacted.
|
// Redacted.
|
||||||
Authorization::Unknown
|
Authorization::Unknown
|
||||||
}
|
}
|
||||||
|
|
@ -773,11 +773,11 @@ 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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -399,11 +399,11 @@ 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,11 +503,11 @@ 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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -347,20 +347,20 @@ 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 {
|
return Err(InsertionError::TargetNotQualified {
|
||||||
name: name.into_inner(),
|
name: name.into_inner(),
|
||||||
target: target_str,
|
target: target_str,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
self.reclassify_targets(&name);
|
self.reclassify_targets(&name);
|
||||||
self.0.insert(name, target);
|
self.0.insert(name, target);
|
||||||
|
|
@ -373,14 +373,14 @@ 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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<IndexMap<Name, Unprotected<RefString>>> for SymbolicRefs {
|
impl TryFrom<IndexMap<Name, Unprotected<RefString>>> for SymbolicRefs {
|
||||||
type Error = InsertionError;
|
type Error = InsertionError;
|
||||||
|
|
|
||||||
|
|
@ -91,11 +91,11 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -187,11 +187,12 @@ 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");
|
log::warn!(target: "radicle", "Overwriting `seedingPolicy` configuration");
|
||||||
cfg.node.seeding_policy = match policy {
|
cfg.node.seeding_policy = match policy {
|
||||||
Policy::Allow => DefaultSeedingPolicy::Allow {
|
Policy::Allow => DefaultSeedingPolicy::Allow {
|
||||||
|
|
@ -200,7 +201,6 @@ impl Config {
|
||||||
Policy::Block => DefaultSeedingPolicy::Block,
|
Policy::Block => DefaultSeedingPolicy::Block,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Ok(cfg)
|
Ok(cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -85,11 +85,11 @@ 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,11 +497,11 @@ 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)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -842,11 +842,11 @@ 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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,13 +34,13 @@ 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));
|
updates.push(RefUpdate::from(name, old, new));
|
||||||
// Returning `true` ensures the process is not aborted.
|
// Returning `true` ensures the process is not aborted.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
false
|
false
|
||||||
});
|
});
|
||||||
opts.remote_callbacks(callbacks);
|
opts.remote_callbacks(callbacks);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue