Collapse if-let nests into let-chains (MSRV-1.95 collapsible_if sweep)
Root cause of the CI Lint regression: commit 6113c53 bumped
rust-version 1.85 -> 1.95. clippy::collapsible_if is MSRV-gated —
collapsing `if let { if let }` needs let-chains, stabilized in Rust
1.95. At MSRV 1.85 clippy suppressed these; at 1.95 it emits them.
The patterns were pre-existing; the MSRV bump surfaced 47 of them
and turned `Lint (luajit)` / `Lint (lua54)` red at HEAD (was green
through PR #7; red from PR #8 = the release-prep MSRV bump).
Resolution (operator-chosen: autofix into let-chains): applied
`cargo clippy --fix` across the luajit, lua54, and crdt lanes
(--all-targets). The fix only applied with the lint at warn level;
`-- -D warnings` turns it into an error and blocks --fix.
Verified on the pinned 1.95.0, all three lanes:
clippy --all-targets -D warnings clean (luajit / lua54 / crdt);
fmt 0 diffs; lib tests 1223/0.
Note: the prior #6 "quiescent audit, clippy clean" was inaccurate —
clippy was not actually re-run there (build/version/fmt only), so
this MSRV-gated regression went uncaught until the live attach-debug
investigation surfaced it. This commit restores genuine clippy
cleanliness at MSRV 1.95.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
46aed3f393
commit
d3fa63290a
|
|
@ -669,11 +669,11 @@ impl AsyncRuntime {
|
||||||
// a time keeps RefCell happy across re-entrant pending
|
// a time keeps RefCell happy across re-entrant pending
|
||||||
// borrows.
|
// borrows.
|
||||||
let prior_id = self.supersede.borrow().get(key).copied();
|
let prior_id = self.supersede.borrow().get(key).copied();
|
||||||
if let Some(prior) = prior_id {
|
if let Some(prior) = prior_id
|
||||||
if let Some(job) = self.pending.borrow().get(&prior) {
|
&& let Some(job) = self.pending.borrow().get(&prior)
|
||||||
|
{
|
||||||
job.cancel.cancel();
|
job.cancel.cancel();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
self.supersede.borrow_mut().insert(key.to_owned(), id);
|
self.supersede.borrow_mut().insert(key.to_owned(), id);
|
||||||
}
|
}
|
||||||
self.pending.borrow_mut().insert(
|
self.pending.borrow_mut().insert(
|
||||||
|
|
@ -1043,11 +1043,11 @@ impl AsyncRuntime {
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
for id in &newly_settled {
|
for id in &newly_settled {
|
||||||
if let Some(job) = pending.get(id) {
|
if let Some(job) = pending.get(id) {
|
||||||
if let Some(key) = &job.supersede_key {
|
if let Some(key) = &job.supersede_key
|
||||||
if sup.get(key) == Some(id) {
|
&& sup.get(key) == Some(id)
|
||||||
|
{
|
||||||
sup.remove(key);
|
sup.remove(key);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// T M3.7: record the settle in the completion
|
// T M3.7: record the settle in the completion
|
||||||
// ring. We push the front and trim the back so
|
// ring. We push the front and trim the back so
|
||||||
// the newest completions are always at index 0.
|
// the newest completions are always at index 0.
|
||||||
|
|
@ -1548,16 +1548,15 @@ fn walk_dir(root: &Path, tx: &cb_channel::Sender<PathBuf>, cancel: &Cancellation
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if file_type.is_dir() {
|
if file_type.is_dir() {
|
||||||
if let Some(name) = path.file_name().and_then(|n| n.to_str()) {
|
if let Some(name) = path.file_name().and_then(|n| n.to_str())
|
||||||
if name.starts_with('.')
|
&& (name.starts_with('.')
|
||||||
|| matches!(
|
|| matches!(
|
||||||
name,
|
name,
|
||||||
"node_modules" | "target" | "build" | "dist" | "__pycache__"
|
"node_modules" | "target" | "build" | "dist" | "__pycache__"
|
||||||
)
|
))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
stack.push(path);
|
stack.push(path);
|
||||||
} else if file_type.is_file() && tx.send(path).is_err() {
|
} else if file_type.is_file() && tx.send(path).is_err() {
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -859,11 +859,11 @@ pub(crate) fn run_attach_pair(
|
||||||
// active buffer's cursor stale so subsequent
|
// active buffer's cursor stale so subsequent
|
||||||
// keystrokes round-trip too until the daemon's
|
// keystrokes round-trip too until the daemon's
|
||||||
// next `CursorByte` re-grounds the mirror cursor.
|
// next `CursorByte` re-grounds the mirror cursor.
|
||||||
if matches!(frontend_event, FrontendEvent::Key(_)) {
|
if matches!(frontend_event, FrontendEvent::Key(_))
|
||||||
if let Some(active_buf) = buffer_mirror.active_buffer() {
|
&& let Some(active_buf) = buffer_mirror.active_buffer()
|
||||||
|
{
|
||||||
buffer_mirror.mark_cursor_stale(active_buf);
|
buffer_mirror.mark_cursor_stale(active_buf);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Visual optimistic paint (Path β). Fires only when
|
// Visual optimistic paint (Path β). Fires only when
|
||||||
// the orchestrator landed a CrdtOp (mirror was
|
// the orchestrator landed a CrdtOp (mirror was
|
||||||
|
|
@ -906,8 +906,9 @@ pub(crate) fn run_attach_pair(
|
||||||
#[cfg(not(feature = "crdt"))]
|
#[cfg(not(feature = "crdt"))]
|
||||||
let optimistic_handled = false;
|
let optimistic_handled = false;
|
||||||
|
|
||||||
if !optimistic_handled {
|
if !optimistic_handled
|
||||||
if let Err(e) = forward_event(&mut writer, &ev, assigned_id, frontend.size()) {
|
&& let Err(e) = forward_event(&mut writer, &ev, assigned_id, frontend.size())
|
||||||
|
{
|
||||||
// Likely a broken pipe — instance went away.
|
// Likely a broken pipe — instance went away.
|
||||||
eprintln!("pmacs: {e}");
|
eprintln!("pmacs: {e}");
|
||||||
return Err(e);
|
return Err(e);
|
||||||
|
|
@ -928,7 +929,6 @@ pub(crate) fn run_attach_pair(
|
||||||
buffer_mirror.mark_cursor_stale(active_buf);
|
buffer_mirror.mark_cursor_stale(active_buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
// Wind down. The order matters:
|
// Wind down. The order matters:
|
||||||
|
|
|
||||||
|
|
@ -321,12 +321,12 @@ fn read_frame<R: Read>(r: &mut R) -> io::Result<Option<Vec<u8>>> {
|
||||||
if line.is_empty() {
|
if line.is_empty() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if let Some((k, v)) = line.split_once(':') {
|
if let Some((k, v)) = line.split_once(':')
|
||||||
if k.trim().eq_ignore_ascii_case("content-length") {
|
&& k.trim().eq_ignore_ascii_case("content-length")
|
||||||
|
{
|
||||||
content_length = v.trim().parse().ok();
|
content_length = v.trim().parse().ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
let n = content_length
|
let n = content_length
|
||||||
.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "missing Content-Length"))?;
|
.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "missing Content-Length"))?;
|
||||||
let mut body = vec![0u8; n];
|
let mut body = vec![0u8; n];
|
||||||
|
|
|
||||||
|
|
@ -1034,8 +1034,9 @@ fn main() {
|
||||||
// notification by writing a sentinel file. Tests
|
// notification by writing a sentinel file. Tests
|
||||||
// that drove an `invoke_tool` cancellation poll for
|
// that drove an `invoke_tool` cancellation poll for
|
||||||
// the file as proof the server actually got it.
|
// the file as proof the server actually got it.
|
||||||
if let Some(dir) = std::env::var_os("PMACS_FAKE_MCP_CANCEL_DIR") {
|
if let Some(dir) = std::env::var_os("PMACS_FAKE_MCP_CANCEL_DIR")
|
||||||
if let Some(req_id) = params.get("requestId") {
|
&& let Some(req_id) = params.get("requestId")
|
||||||
|
{
|
||||||
// requestId is whatever the client sent —
|
// requestId is whatever the client sent —
|
||||||
// typically a u64, but per the spec it can
|
// typically a u64, but per the spec it can
|
||||||
// be any JSON value. Use its string form.
|
// be any JSON value. Use its string form.
|
||||||
|
|
@ -1044,12 +1045,10 @@ fn main() {
|
||||||
serde_json::Value::String(s) => s.clone(),
|
serde_json::Value::String(s) => s.clone(),
|
||||||
other => other.to_string(),
|
other => other.to_string(),
|
||||||
};
|
};
|
||||||
let path =
|
let path = std::path::PathBuf::from(&dir).join(format!("cancelled-{id_str}"));
|
||||||
std::path::PathBuf::from(&dir).join(format!("cancelled-{id_str}"));
|
|
||||||
let _ = std::fs::write(&path, b"");
|
let _ = std::fs::write(&path, b"");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
("prompts/get", Some(idv)) => {
|
("prompts/get", Some(idv)) => {
|
||||||
request_counter += 1;
|
request_counter += 1;
|
||||||
let prompt_name = params.get("name").and_then(|v| v.as_str()).unwrap_or("");
|
let prompt_name = params.get("name").and_then(|v| v.as_str()).unwrap_or("");
|
||||||
|
|
@ -1817,7 +1816,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
if mode == "ignore_eof_sleep" {
|
if mode == "ignore_eof_sleep" {
|
||||||
loop {
|
loop {
|
||||||
std::thread::sleep(std::time::Duration::from_secs(60));
|
std::thread::sleep(std::time::Duration::from_mins(1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2560,8 +2560,8 @@ mod tests {
|
||||||
for op in ops {
|
for op in ops {
|
||||||
let op_repr = format!("{op:?}");
|
let op_repr = format!("{op:?}");
|
||||||
let edit = apply_capturing(&mut a, op);
|
let edit = apply_capturing(&mut a, op);
|
||||||
if let Some(edit) = edit {
|
if let Some(edit) = edit
|
||||||
if let Some(crdt_op) = edit.crdt_op.as_ref() {
|
&& let Some(crdt_op) = edit.crdt_op.as_ref() {
|
||||||
// Apply the wire-format bytes to the
|
// Apply the wire-format bytes to the
|
||||||
// receiver. Receiver projection must match
|
// receiver. Receiver projection must match
|
||||||
// A's projection after this.
|
// A's projection after this.
|
||||||
|
|
@ -2583,7 +2583,6 @@ mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// T M10.3 generator: forward-only ops (no Undo/Redo). The
|
/// T M10.3 generator: forward-only ops (no Undo/Redo). The
|
||||||
/// round-trip proptest excludes history-nav because the
|
/// round-trip proptest excludes history-nav because the
|
||||||
|
|
|
||||||
|
|
@ -127,14 +127,14 @@ impl BufferRegistry {
|
||||||
pub fn remove(&mut self, id: BufferId) -> Result<Buffer, RegistryError> {
|
pub fn remove(&mut self, id: BufferId) -> Result<Buffer, RegistryError> {
|
||||||
// Peek without taking ownership: if the buffer is mid-edit we
|
// Peek without taking ownership: if the buffer is mid-edit we
|
||||||
// surface a typed error and leave the registry untouched.
|
// surface a typed error and leave the registry untouched.
|
||||||
if let Some(buf) = self.buffers.get(&id) {
|
if let Some(buf) = self.buffers.get(&id)
|
||||||
if buf.editing_in_progress() {
|
&& buf.editing_in_progress()
|
||||||
|
{
|
||||||
return Err(RegistryError::ConcurrentEdit {
|
return Err(RegistryError::ConcurrentEdit {
|
||||||
id,
|
id,
|
||||||
name: buf.name().to_string(),
|
name: buf.name().to_string(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
let buf = self
|
let buf = self
|
||||||
.buffers
|
.buffers
|
||||||
.remove(&id)
|
.remove(&id)
|
||||||
|
|
|
||||||
|
|
@ -214,11 +214,11 @@ fn extract_markup_text(v: &Value) -> Option<String> {
|
||||||
if let Some(s) = v.as_str() {
|
if let Some(s) = v.as_str() {
|
||||||
return Some(s.to_owned());
|
return Some(s.to_owned());
|
||||||
}
|
}
|
||||||
if let Some(obj) = v.as_object() {
|
if let Some(obj) = v.as_object()
|
||||||
if let Some(s) = obj.get("value").and_then(Value::as_str) {
|
&& let Some(s) = obj.get("value").and_then(Value::as_str)
|
||||||
|
{
|
||||||
return Some(s.to_owned());
|
return Some(s.to_owned());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -431,12 +431,12 @@ impl CompletionTriggers {
|
||||||
};
|
};
|
||||||
let mut chars = Vec::with_capacity(arr.len());
|
let mut chars = Vec::with_capacity(arr.len());
|
||||||
for v in arr {
|
for v in arr {
|
||||||
if let Some(s) = v.as_str() {
|
if let Some(s) = v.as_str()
|
||||||
if let Some(ch) = s.chars().next() {
|
&& let Some(ch) = s.chars().next()
|
||||||
|
{
|
||||||
chars.push(ch);
|
chars.push(ch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Self { chars }
|
Self { chars }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,11 +58,11 @@ pub fn resolve_config_dir(
|
||||||
xdg: Option<&std::ffi::OsStr>,
|
xdg: Option<&std::ffi::OsStr>,
|
||||||
home: Option<&std::ffi::OsStr>,
|
home: Option<&std::ffi::OsStr>,
|
||||||
) -> Option<PathBuf> {
|
) -> Option<PathBuf> {
|
||||||
if let Some(xdg) = xdg {
|
if let Some(xdg) = xdg
|
||||||
if !xdg.is_empty() {
|
&& !xdg.is_empty()
|
||||||
|
{
|
||||||
return Some(PathBuf::from(xdg).join(CONFIG_SUBDIR));
|
return Some(PathBuf::from(xdg).join(CONFIG_SUBDIR));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
let home = home?;
|
let home = home?;
|
||||||
Some(PathBuf::from(home).join(".config").join(CONFIG_SUBDIR))
|
Some(PathBuf::from(home).join(".config").join(CONFIG_SUBDIR))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1276,12 +1276,12 @@ fn send_buffer_snapshots(editor: &EditorState, write_stream: &mut UnixStream) {
|
||||||
// Upgrade non-CRDT buffers to CRDT-backed in place. The
|
// Upgrade non-CRDT buffers to CRDT-backed in place. The
|
||||||
// upgrade preserves the buffer's id, name, and content; only
|
// upgrade preserves the buffer's id, name, and content; only
|
||||||
// the CRDT machinery is added.
|
// the CRDT machinery is added.
|
||||||
if !buf.is_crdt_backed() {
|
if !buf.is_crdt_backed()
|
||||||
if let Err(e) = buf.upgrade_to_crdt(instance_peer_id) {
|
&& let Err(e) = buf.upgrade_to_crdt(instance_peer_id)
|
||||||
|
{
|
||||||
eprintln!("pmacs: upgrade_to_crdt for {buffer_id:?} failed: {e:?}");
|
eprintln!("pmacs: upgrade_to_crdt for {buffer_id:?} failed: {e:?}");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
let Some(crdt) = buf.crdt_state() else {
|
let Some(crdt) = buf.crdt_state() else {
|
||||||
// Upgrade succeeded but somehow crdt is still None —
|
// Upgrade succeeded but somehow crdt is still None —
|
||||||
// shouldn't happen; defensive skip.
|
// shouldn't happen; defensive skip.
|
||||||
|
|
@ -1516,8 +1516,8 @@ fn validate_remote_crdt_op(
|
||||||
let expected_peer_id = crate::crdt::peer_id_from_frontend(source);
|
let expected_peer_id = crate::crdt::peer_id_from_frontend(source);
|
||||||
let registry_handle = editor.core.borrow().registry.clone();
|
let registry_handle = editor.core.borrow().registry.clone();
|
||||||
let registry = registry_handle.borrow();
|
let registry = registry_handle.borrow();
|
||||||
if let Ok(buf) = registry.get(buffer_id) {
|
if let Ok(buf) = registry.get(buffer_id)
|
||||||
if buf
|
&& buf
|
||||||
.validate_remote_op_peer_ids(expected_peer_id, &op.bytes)
|
.validate_remote_op_peer_ids(expected_peer_id, &op.bytes)
|
||||||
.is_err()
|
.is_err()
|
||||||
{
|
{
|
||||||
|
|
@ -1525,7 +1525,6 @@ fn validate_remote_crdt_op(
|
||||||
"op.bytes carry CRDT ops attributed to a peer other than the authenticated source",
|
"op.bytes carry CRDT ops attributed to a peer other than the authenticated source",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -307,14 +307,14 @@ fn replace_help_buffer(
|
||||||
edits.push(edit);
|
edits.push(edit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !text.is_empty() {
|
if !text.is_empty()
|
||||||
if let Ok(edit) = buf.apply_edit(EditOp::Insert {
|
&& let Ok(edit) = buf.apply_edit(EditOp::Insert {
|
||||||
pos: 0,
|
pos: 0,
|
||||||
bytes: text.as_bytes(),
|
bytes: text.as_bytes(),
|
||||||
}) {
|
})
|
||||||
|
{
|
||||||
edits.push(edit);
|
edits.push(edit);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// The help buffer is regenerated content; mark it clean so the
|
// The help buffer is regenerated content; mark it clean so the
|
||||||
// modeline doesn't claim it has unsaved changes.
|
// modeline doesn't claim it has unsaved changes.
|
||||||
buf.mark_clean();
|
buf.mark_clean();
|
||||||
|
|
|
||||||
|
|
@ -94,11 +94,11 @@ fn collapse_contents(v: &Value) -> Option<String> {
|
||||||
}
|
}
|
||||||
return Some(out);
|
return Some(out);
|
||||||
}
|
}
|
||||||
if let Some(obj) = v.as_object() {
|
if let Some(obj) = v.as_object()
|
||||||
if let Some(s) = obj.get("value").and_then(Value::as_str) {
|
&& let Some(s) = obj.get("value").and_then(Value::as_str)
|
||||||
|
{
|
||||||
return Some(s.to_owned());
|
return Some(s.to_owned());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -103,14 +103,14 @@ pub fn render(
|
||||||
edits.push(edit);
|
edits.push(edit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !text.is_empty() {
|
if !text.is_empty()
|
||||||
if let Ok(edit) = buf.apply_edit(EditOp::Insert {
|
&& let Ok(edit) = buf.apply_edit(EditOp::Insert {
|
||||||
pos: 0,
|
pos: 0,
|
||||||
bytes: text.as_bytes(),
|
bytes: text.as_bytes(),
|
||||||
}) {
|
})
|
||||||
|
{
|
||||||
edits.push(edit);
|
edits.push(edit);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
buf.mark_clean();
|
buf.mark_clean();
|
||||||
(id, edits)
|
(id, edits)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -245,8 +245,9 @@ impl KeymapStack {
|
||||||
let mut any_pending = false;
|
let mut any_pending = false;
|
||||||
|
|
||||||
// 1) Buffer-local --- highest priority.
|
// 1) Buffer-local --- highest priority.
|
||||||
if let Some(id) = active_buffer {
|
if let Some(id) = active_buffer
|
||||||
if let Some(map) = self.buffers.get(&id) {
|
&& let Some(map) = self.buffers.get(&id)
|
||||||
|
{
|
||||||
match map.lookup(sequence) {
|
match map.lookup(sequence) {
|
||||||
Resolution::Bound(b) => {
|
Resolution::Bound(b) => {
|
||||||
return StackResolution::Bound(ResolvedBinding {
|
return StackResolution::Bound(ResolvedBinding {
|
||||||
|
|
@ -258,7 +259,6 @@ impl KeymapStack {
|
||||||
Resolution::Unbound => {}
|
Resolution::Unbound => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// 2) Modes --- ordered by `active_modes`.
|
// 2) Modes --- ordered by `active_modes`.
|
||||||
for mode_name in active_modes {
|
for mode_name in active_modes {
|
||||||
|
|
|
||||||
|
|
@ -282,11 +282,11 @@ fn bind_recursive(map: &mut Keymap, sequence: &[Chord], command: String, source:
|
||||||
fn unbind_recursive(map: &mut Keymap, sequence: &[Chord]) -> Option<Binding> {
|
fn unbind_recursive(map: &mut Keymap, sequence: &[Chord]) -> Option<Binding> {
|
||||||
let (head, tail) = sequence.split_first()?;
|
let (head, tail) = sequence.split_first()?;
|
||||||
if tail.is_empty() {
|
if tail.is_empty() {
|
||||||
if let Some(Branch::Leaf(_)) = map.branches.get(head) {
|
if let Some(Branch::Leaf(_)) = map.branches.get(head)
|
||||||
if let Some(Branch::Leaf(b)) = map.branches.remove(head) {
|
&& let Some(Branch::Leaf(b)) = map.branches.remove(head)
|
||||||
|
{
|
||||||
return Some(b);
|
return Some(b);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let removed = match map.branches.get_mut(head) {
|
let removed = match map.branches.get_mut(head) {
|
||||||
|
|
@ -294,11 +294,11 @@ fn unbind_recursive(map: &mut Keymap, sequence: &[Chord]) -> Option<Binding> {
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
// Prune empty submaps so the tree doesn't grow stalactites.
|
// Prune empty submaps so the tree doesn't grow stalactites.
|
||||||
if let Some(Branch::Submap(sub)) = map.branches.get(head) {
|
if let Some(Branch::Submap(sub)) = map.branches.get(head)
|
||||||
if sub.is_empty() {
|
&& sub.is_empty()
|
||||||
|
{
|
||||||
map.branches.remove(head);
|
map.branches.remove(head);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Some(removed)
|
Some(removed)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
25
src/lsp.rs
25
src/lsp.rs
|
|
@ -1137,8 +1137,9 @@ impl LspManager {
|
||||||
};
|
};
|
||||||
// Build the initialize request payload.
|
// Build the initialize request payload.
|
||||||
let body = self.build_initialize(sid, init_request_id);
|
let body = self.build_initialize(sid, init_request_id);
|
||||||
if let Some(client) = self.clients.get(&sid) {
|
if let Some(client) = self.clients.get(&sid)
|
||||||
if let Err(e) = send_frame_to(&self.supervisor, client, &body) {
|
&& let Err(e) = send_frame_to(&self.supervisor, client, &body)
|
||||||
|
{
|
||||||
self.push_event(
|
self.push_event(
|
||||||
sid,
|
sid,
|
||||||
at,
|
at,
|
||||||
|
|
@ -1147,7 +1148,6 @@ impl LspManager {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
self.push_event(sid, at, LspEventKind::Started { pid });
|
self.push_event(sid, at, LspEventKind::Started { pid });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1233,12 +1233,10 @@ impl LspManager {
|
||||||
} else {
|
} else {
|
||||||
self.push_event(sid, at, LspEventKind::Crashed { reason });
|
self.push_event(sid, at, LspEventKind::Crashed { reason });
|
||||||
}
|
}
|
||||||
if restart {
|
if restart && let Some(client) = self.clients.get_mut(&sid) {
|
||||||
if let Some(client) = self.clients.get_mut(&sid) {
|
|
||||||
client.next_restart_at = Some(at + self.restart_backoff);
|
client.next_restart_at = Some(at + self.restart_backoff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_frames(&mut self, sid: LspServerId) {
|
fn parse_frames(&mut self, sid: LspServerId) {
|
||||||
loop {
|
loop {
|
||||||
|
|
@ -1263,11 +1261,11 @@ impl LspManager {
|
||||||
// Frame violations are unrecoverable on the same
|
// Frame violations are unrecoverable on the same
|
||||||
// byte stream; terminate and let the restart
|
// byte stream; terminate and let the restart
|
||||||
// policy bring things back if configured.
|
// policy bring things back if configured.
|
||||||
if let Some(client) = self.clients.get_mut(&sid) {
|
if let Some(client) = self.clients.get_mut(&sid)
|
||||||
if let Some(pid) = client.process {
|
&& let Some(pid) = client.process
|
||||||
|
{
|
||||||
let _ = self.supervisor.borrow_mut().terminate(pid);
|
let _ = self.supervisor.borrow_mut().terminate(pid);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1419,13 +1417,12 @@ impl LspManager {
|
||||||
// help) get absorbed into the matching shared store before
|
// help) get absorbed into the matching shared store before
|
||||||
// surfacing as a generic `Response` event. Consumers
|
// surfacing as a generic `Response` event. Consumers
|
||||||
// observing the event in the same tick see the fresh data.
|
// observing the event in the same tick see the fresh data.
|
||||||
if let Some(route) = self.pending_routes.remove(&(sid, rid)) {
|
if let Some(route) = self.pending_routes.remove(&(sid, rid))
|
||||||
if error.is_none() {
|
&& error.is_none()
|
||||||
if let Some(value) = result.as_ref() {
|
&& let Some(value) = result.as_ref()
|
||||||
|
{
|
||||||
self.absorb_routed_response(sid, &route, value);
|
self.absorb_routed_response(sid, &route, value);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
// Generic response.
|
// Generic response.
|
||||||
self.push_event(
|
self.push_event(
|
||||||
sid,
|
sid,
|
||||||
|
|
|
||||||
16
src/mcp.rs
16
src/mcp.rs
|
|
@ -1524,8 +1524,9 @@ impl McpManager {
|
||||||
req_id
|
req_id
|
||||||
};
|
};
|
||||||
let body = build_initialize(init_request_id);
|
let body = build_initialize(init_request_id);
|
||||||
if let Some(client) = self.clients.get(&sid) {
|
if let Some(client) = self.clients.get(&sid)
|
||||||
if let Err(e) = send_frame_to(&self.supervisor, client, &body) {
|
&& let Err(e) = send_frame_to(&self.supervisor, client, &body)
|
||||||
|
{
|
||||||
self.push_event(
|
self.push_event(
|
||||||
sid,
|
sid,
|
||||||
at,
|
at,
|
||||||
|
|
@ -1534,7 +1535,6 @@ impl McpManager {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
self.push_event(sid, at, McpEventKind::Started { pid });
|
self.push_event(sid, at, McpEventKind::Started { pid });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1597,12 +1597,10 @@ impl McpManager {
|
||||||
TerminalKind::Stopped => self.push_event(sid, at, McpEventKind::Stopped),
|
TerminalKind::Stopped => self.push_event(sid, at, McpEventKind::Stopped),
|
||||||
TerminalKind::Crashed => self.push_event(sid, at, McpEventKind::Crashed { reason }),
|
TerminalKind::Crashed => self.push_event(sid, at, McpEventKind::Crashed { reason }),
|
||||||
}
|
}
|
||||||
if restart {
|
if restart && let Some(client) = self.clients.get_mut(&sid) {
|
||||||
if let Some(client) = self.clients.get_mut(&sid) {
|
|
||||||
client.next_restart_at = Some(at + self.restart_backoff);
|
client.next_restart_at = Some(at + self.restart_backoff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_frames(&mut self, sid: McpServerId) {
|
fn parse_frames(&mut self, sid: McpServerId) {
|
||||||
loop {
|
loop {
|
||||||
|
|
@ -1911,12 +1909,12 @@ impl McpManager {
|
||||||
/// of the LSP layer's "frame violations are unrecoverable on the
|
/// of the LSP layer's "frame violations are unrecoverable on the
|
||||||
/// same byte stream" path.
|
/// same byte stream" path.
|
||||||
fn terminate_after_protocol_error(&mut self, sid: McpServerId) {
|
fn terminate_after_protocol_error(&mut self, sid: McpServerId) {
|
||||||
if let Some(client) = self.clients.get(&sid) {
|
if let Some(client) = self.clients.get(&sid)
|
||||||
if let Some(pid) = client.process {
|
&& let Some(pid) = client.process
|
||||||
|
{
|
||||||
let _ = self.supervisor.borrow_mut().terminate(pid);
|
let _ = self.supervisor.borrow_mut().terminate(pid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_request(
|
fn handle_request(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
|
||||||
|
|
@ -494,15 +494,16 @@ impl MinibufferAction {
|
||||||
}
|
}
|
||||||
return Self::Ignore;
|
return Self::Ignore;
|
||||||
}
|
}
|
||||||
if alt && !ctrl {
|
if alt
|
||||||
if let KeyCode::Char(c) = chord.code {
|
&& !ctrl
|
||||||
|
&& let KeyCode::Char(c) = chord.code
|
||||||
|
{
|
||||||
return match c {
|
return match c {
|
||||||
'n' => Self::ScrollNext,
|
'n' => Self::ScrollNext,
|
||||||
'p' => Self::ScrollPrev,
|
'p' => Self::ScrollPrev,
|
||||||
_ => Self::Ignore,
|
_ => Self::Ignore,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Self::Ignore
|
Self::Ignore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -631,11 +632,11 @@ pub fn fuzzy_score(needle: &str, haystack: &str) -> Option<i32> {
|
||||||
if n[i] == hc {
|
if n[i] == hc {
|
||||||
if j == 0 {
|
if j == 0 {
|
||||||
score += 10;
|
score += 10;
|
||||||
} else if let Some(prev_h) = h.get(j - 1) {
|
} else if let Some(prev_h) = h.get(j - 1)
|
||||||
if matches!(*prev_h, '.' | '-' | '_' | ' ') {
|
&& matches!(*prev_h, '.' | '-' | '_' | ' ')
|
||||||
|
{
|
||||||
score += 5;
|
score += 5;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if let Some(p) = prev_match {
|
if let Some(p) = prev_match {
|
||||||
if p + 1 == j {
|
if p + 1 == j {
|
||||||
score += 3;
|
score += 3;
|
||||||
|
|
|
||||||
|
|
@ -119,7 +119,7 @@ pub struct Fetcher {
|
||||||
timeout: Duration,
|
timeout: Duration,
|
||||||
}
|
}
|
||||||
|
|
||||||
const DEFAULT_TIMEOUT: Duration = Duration::from_secs(60);
|
const DEFAULT_TIMEOUT: Duration = Duration::from_mins(1);
|
||||||
|
|
||||||
impl Fetcher {
|
impl Fetcher {
|
||||||
/// Construct a fetcher with an explicit cache directory. The
|
/// Construct a fetcher with an explicit cache directory. The
|
||||||
|
|
@ -472,11 +472,11 @@ fn xdg_cache_root() -> Result<PathBuf, FetchError> {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn normalize_url(url: &str) -> String {
|
pub fn normalize_url(url: &str) -> String {
|
||||||
let mut u = url.trim_end_matches('/').to_string();
|
let mut u = url.trim_end_matches('/').to_string();
|
||||||
if dot_git_strip_applies(&u) {
|
if dot_git_strip_applies(&u)
|
||||||
if let Some(s) = u.strip_suffix(".git") {
|
&& let Some(s) = u.strip_suffix(".git")
|
||||||
|
{
|
||||||
u = s.to_string();
|
u = s.to_string();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if let Some(scheme_end) = u.find("://") {
|
if let Some(scheme_end) = u.find("://") {
|
||||||
let host_start = scheme_end + 3;
|
let host_start = scheme_end + 3;
|
||||||
let after_host = u[host_start..]
|
let after_host = u[host_start..]
|
||||||
|
|
@ -497,15 +497,13 @@ fn dot_git_strip_applies(u: &str) -> bool {
|
||||||
}
|
}
|
||||||
// SSH shorthand: `user@host:path`. Distinguished from URL forms
|
// SSH shorthand: `user@host:path`. Distinguished from URL forms
|
||||||
// by the `@` appearing before any `:` and no `://` prefix.
|
// by the `@` appearing before any `:` and no `://` prefix.
|
||||||
if !u.contains("://") {
|
if !u.contains("://")
|
||||||
if let Some(at) = u.find('@') {
|
&& let Some(at) = u.find('@')
|
||||||
if let Some(colon) = u.find(':') {
|
&& let Some(colon) = u.find(':')
|
||||||
if at < colon {
|
&& at < colon
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -657,14 +657,14 @@ impl Installer {
|
||||||
let staging_path = plan
|
let staging_path = plan
|
||||||
.install_path
|
.install_path
|
||||||
.with_file_name(format!(".{}.swap.tmp", plan.basename));
|
.with_file_name(format!(".{}.swap.tmp", plan.basename));
|
||||||
if let Err(e) = std::fs::remove_file(&staging_path) {
|
if let Err(e) = std::fs::remove_file(&staging_path)
|
||||||
if e.kind() != io::ErrorKind::NotFound {
|
&& e.kind() != io::ErrorKind::NotFound
|
||||||
|
{
|
||||||
return Err(InstallError::Io {
|
return Err(InstallError::Io {
|
||||||
path: staging_path,
|
path: staging_path,
|
||||||
source: e,
|
source: e,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
symlink_create(&plan.canonical_source, &staging_path)?;
|
symlink_create(&plan.canonical_source, &staging_path)?;
|
||||||
|
|
||||||
Ok(StagedLocalInstall { plan, staging_path })
|
Ok(StagedLocalInstall { plan, staging_path })
|
||||||
|
|
@ -846,8 +846,9 @@ impl Installer {
|
||||||
// and pmacs.toml version disagree. Branch and commit pins
|
// and pmacs.toml version disagree. Branch and commit pins
|
||||||
// skip this check --- the user explicitly asked for that
|
// skip this check --- the user explicitly asked for that
|
||||||
// revision regardless of what the manifest says.
|
// revision regardless of what the manifest says.
|
||||||
if let InstallPin::Version(req) = &spec.pin {
|
if let InstallPin::Version(req) = &spec.pin
|
||||||
if !req.matches(&manifest.version) {
|
&& !req.matches(&manifest.version)
|
||||||
|
{
|
||||||
return Err(InstallError::ManifestVersionMismatch {
|
return Err(InstallError::ManifestVersionMismatch {
|
||||||
address: url.clone(),
|
address: url.clone(),
|
||||||
tag: tag_descriptor.clone(),
|
tag: tag_descriptor.clone(),
|
||||||
|
|
@ -855,7 +856,6 @@ impl Installer {
|
||||||
req: req.to_string(),
|
req: req.to_string(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Archive + extract.
|
// Archive + extract.
|
||||||
let install_root = self.install_root()?;
|
let install_root = self.install_root()?;
|
||||||
|
|
|
||||||
|
|
@ -408,14 +408,14 @@ impl Lockfile {
|
||||||
|
|
||||||
/// Write pre-serialized lockfile bytes to disk atomically.
|
/// Write pre-serialized lockfile bytes to disk atomically.
|
||||||
pub fn write_bytes_to(path: &Path, bytes: &[u8]) -> Result<(), LockfileError> {
|
pub fn write_bytes_to(path: &Path, bytes: &[u8]) -> Result<(), LockfileError> {
|
||||||
if let Some(parent) = path.parent() {
|
if let Some(parent) = path.parent()
|
||||||
if !parent.as_os_str().is_empty() {
|
&& !parent.as_os_str().is_empty()
|
||||||
|
{
|
||||||
fs::create_dir_all(parent).map_err(|source| LockfileError::Io {
|
fs::create_dir_all(parent).map_err(|source| LockfileError::Io {
|
||||||
path: parent.to_path_buf(),
|
path: parent.to_path_buf(),
|
||||||
source,
|
source,
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
crate::file_io::save_atomic(path, bytes)
|
crate::file_io::save_atomic(path, bytes)
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
.map_err(|err| lockfile_save_error(path, err))?;
|
.map_err(|err| lockfile_save_error(path, err))?;
|
||||||
|
|
|
||||||
|
|
@ -890,8 +890,9 @@ impl<'a> ResolverState<'a> {
|
||||||
// selection. This is the `UpdatePolicy::UpdateOne` cascade
|
// selection. This is the `UpdatePolicy::UpdateOne` cascade
|
||||||
// brake — non-target packages stay at lockfile versions
|
// brake — non-target packages stay at lockfile versions
|
||||||
// unless current constraints force them to move.
|
// unless current constraints force them to move.
|
||||||
if let Some(hint) = self.prefer_versions.get(url).cloned() {
|
if let Some(hint) = self.prefer_versions.get(url).cloned()
|
||||||
if let Some(cand) = after_user.iter().find(|c| c.version == hint) {
|
&& let Some(cand) = after_user.iter().find(|c| c.version == hint)
|
||||||
|
{
|
||||||
let manifest = self
|
let manifest = self
|
||||||
.read_manifest(url, repo, &cand.commit_for_tag())?
|
.read_manifest(url, repo, &cand.commit_for_tag())?
|
||||||
.clone();
|
.clone();
|
||||||
|
|
@ -907,7 +908,6 @@ impl<'a> ResolverState<'a> {
|
||||||
// an older one). Fall through to highest-version
|
// an older one). Fall through to highest-version
|
||||||
// selection.
|
// selection.
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Phase 2b: walk highest-first, fetch manifest lazily, return
|
// Phase 2b: walk highest-first, fetch manifest lazily, return
|
||||||
// first that satisfies pmacs_required. Lazy fetch matters: in
|
// first that satisfies pmacs_required. Lazy fetch matters: in
|
||||||
|
|
|
||||||
|
|
@ -945,8 +945,8 @@ impl ProcessSupervisor {
|
||||||
} else {
|
} else {
|
||||||
// Schedule a restart attempt for `restart_backoff` from
|
// Schedule a restart attempt for `restart_backoff` from
|
||||||
// now if not yet scheduled.
|
// now if not yet scheduled.
|
||||||
if let Some(proc) = self.processes.get_mut(&id) {
|
if let Some(proc) = self.processes.get_mut(&id)
|
||||||
if matches!(proc.state, ProcessState::Terminated(_))
|
&& matches!(proc.state, ProcessState::Terminated(_))
|
||||||
&& !matches!(proc.spec.restart, RestartPolicy::Never)
|
&& !matches!(proc.spec.restart, RestartPolicy::Never)
|
||||||
&& proc.next_restart_at.is_none()
|
&& proc.next_restart_at.is_none()
|
||||||
{
|
{
|
||||||
|
|
@ -954,7 +954,6 @@ impl ProcessSupervisor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Drain and return all events queued for `id` since the last
|
/// Drain and return all events queued for `id` since the last
|
||||||
/// call. Returns an empty vec for unknown ids and for known ids
|
/// call. Returns an empty vec for unknown ids and for known ids
|
||||||
|
|
@ -1032,15 +1031,15 @@ impl ProcessSupervisor {
|
||||||
}
|
}
|
||||||
// SIGKILL anything left.
|
// SIGKILL anything left.
|
||||||
for id in &ids {
|
for id in &ids {
|
||||||
if let Some(proc) = self.processes.get(id) {
|
if let Some(proc) = self.processes.get(id)
|
||||||
if matches!(
|
&& matches!(
|
||||||
proc.state,
|
proc.state,
|
||||||
ProcessState::Running { .. } | ProcessState::Exiting { .. }
|
ProcessState::Running { .. } | ProcessState::Exiting { .. }
|
||||||
) {
|
)
|
||||||
|
{
|
||||||
let _ = self.signal(*id, Signal::SIGKILL);
|
let _ = self.signal(*id, Signal::SIGKILL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// Final reap loop. SIGKILL is delivered immediately by the
|
// Final reap loop. SIGKILL is delivered immediately by the
|
||||||
// kernel; the child becomes a zombie until we reap. Bound
|
// kernel; the child becomes a zombie until we reap. Bound
|
||||||
// the wait so a pathological case can't hang the editor
|
// the wait so a pathological case can't hang the editor
|
||||||
|
|
|
||||||
|
|
@ -232,12 +232,12 @@ fn walk_for_marker(
|
||||||
if let Some(kind) = match_marker(ancestor, markers) {
|
if let Some(kind) = match_marker(ancestor, markers) {
|
||||||
return Some((ancestor.to_path_buf(), kind));
|
return Some((ancestor.to_path_buf(), kind));
|
||||||
}
|
}
|
||||||
if let Some(stop) = stop_root {
|
if let Some(stop) = stop_root
|
||||||
if ancestor == stop {
|
&& ancestor == stop
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -344,11 +344,11 @@ impl ProjectIndex {
|
||||||
/// Save the index to `dest` as JSON, creating parent directories
|
/// Save the index to `dest` as JSON, creating parent directories
|
||||||
/// as needed.
|
/// as needed.
|
||||||
pub fn save(&self, dest: &Path) -> io::Result<()> {
|
pub fn save(&self, dest: &Path) -> io::Result<()> {
|
||||||
if let Some(parent) = dest.parent() {
|
if let Some(parent) = dest.parent()
|
||||||
if !parent.as_os_str().is_empty() {
|
&& !parent.as_os_str().is_empty()
|
||||||
|
{
|
||||||
fs::create_dir_all(parent)?;
|
fs::create_dir_all(parent)?;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
let bytes = serde_json::to_vec(self).map_err(io::Error::other)?;
|
let bytes = serde_json::to_vec(self).map_err(io::Error::other)?;
|
||||||
fs::write(dest, bytes)
|
fs::write(dest, bytes)
|
||||||
}
|
}
|
||||||
|
|
@ -729,11 +729,11 @@ fn extract_rust_heuristic(source: &str) -> Vec<Symbol> {
|
||||||
|
|
||||||
fn strip_rust_visibility(s: &str) -> &str {
|
fn strip_rust_visibility(s: &str) -> &str {
|
||||||
let trimmed = s.trim_start();
|
let trimmed = s.trim_start();
|
||||||
if let Some(rest) = trimmed.strip_prefix("pub(") {
|
if let Some(rest) = trimmed.strip_prefix("pub(")
|
||||||
if let Some(close) = rest.find(')') {
|
&& let Some(close) = rest.find(')')
|
||||||
|
{
|
||||||
return rest[close + 1..].trim_start();
|
return rest[close + 1..].trim_start();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if let Some(rest) = trimmed.strip_prefix("pub ") {
|
if let Some(rest) = trimmed.strip_prefix("pub ") {
|
||||||
return rest.trim_start();
|
return rest.trim_start();
|
||||||
}
|
}
|
||||||
|
|
@ -771,8 +771,9 @@ fn extract_lua_heuristic(source: &str) -> Vec<Symbol> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// local NAME = function(...
|
// local NAME = function(...
|
||||||
if let Some(rest) = line.strip_prefix("local ") {
|
if let Some(rest) = line.strip_prefix("local ")
|
||||||
if let Some(eq) = rest.find('=') {
|
&& let Some(eq) = rest.find('=')
|
||||||
|
{
|
||||||
let name = rest[..eq].trim();
|
let name = rest[..eq].trim();
|
||||||
let value = rest[eq + 1..].trim_start();
|
let value = rest[eq + 1..].trim_start();
|
||||||
if is_identifier(name) {
|
if is_identifier(name) {
|
||||||
|
|
@ -785,7 +786,6 @@ fn extract_lua_heuristic(source: &str) -> Vec<Symbol> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
out
|
out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -917,8 +917,9 @@ pub fn extract_treesitter(
|
||||||
|
|
||||||
fn walk_treesitter(node: tree_sitter::Node<'_>, bytes: &[u8], out: &mut Vec<Symbol>) {
|
fn walk_treesitter(node: tree_sitter::Node<'_>, bytes: &[u8], out: &mut Vec<Symbol>) {
|
||||||
let kind_name = node.kind();
|
let kind_name = node.kind();
|
||||||
if let Some(sym_kind) = treesitter_kind(kind_name) {
|
if let Some(sym_kind) = treesitter_kind(kind_name)
|
||||||
if let Some(name_node) = node.child_by_field_name("name") {
|
&& let Some(name_node) = node.child_by_field_name("name")
|
||||||
|
{
|
||||||
let start = name_node.start_byte();
|
let start = name_node.start_byte();
|
||||||
let end = name_node.end_byte();
|
let end = name_node.end_byte();
|
||||||
if let Ok(name) = std::str::from_utf8(&bytes[start..end]) {
|
if let Ok(name) = std::str::from_utf8(&bytes[start..end]) {
|
||||||
|
|
@ -933,7 +934,6 @@ fn walk_treesitter(node: tree_sitter::Node<'_>, bytes: &[u8], out: &mut Vec<Symb
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
let mut cursor = node.walk();
|
let mut cursor = node.walk();
|
||||||
for child in node.children(&mut cursor) {
|
for child in node.children(&mut cursor) {
|
||||||
walk_treesitter(child, bytes, out);
|
walk_treesitter(child, bytes, out);
|
||||||
|
|
@ -1027,9 +1027,10 @@ fn ingest_lsp_one(
|
||||||
(parent_uri.map(str::to_owned), 0, 0)
|
(parent_uri.map(str::to_owned), 0, 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
if !name.is_empty() {
|
if !name.is_empty()
|
||||||
if let Some(uri) = uri.as_deref() {
|
&& let Some(uri) = uri.as_deref()
|
||||||
if let Some(path) = uri_to_path(uri) {
|
&& let Some(path) = uri_to_path(uri)
|
||||||
|
{
|
||||||
let kind = kind_code.map_or(SymbolKind::Other("unknown".into()), |code| {
|
let kind = kind_code.map_or(SymbolKind::Other("unknown".into()), |code| {
|
||||||
SymbolKind::from_lsp_code(code)
|
SymbolKind::from_lsp_code(code)
|
||||||
});
|
});
|
||||||
|
|
@ -1046,8 +1047,6 @@ fn ingest_lsp_one(
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DocumentSymbol form: recurse into children with the same uri.
|
// DocumentSymbol form: recurse into children with the same uri.
|
||||||
if let Some(children) = entry.get("children").and_then(|v| v.as_array()) {
|
if let Some(children) = entry.get("children").and_then(|v| v.as_array()) {
|
||||||
|
|
@ -1089,13 +1088,14 @@ fn percent_decode(s: &str) -> String {
|
||||||
let mut out = Vec::with_capacity(bytes.len());
|
let mut out = Vec::with_capacity(bytes.len());
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while i < bytes.len() {
|
while i < bytes.len() {
|
||||||
if bytes[i] == b'%' && i + 2 < bytes.len() {
|
if bytes[i] == b'%'
|
||||||
if let (Some(h), Some(l)) = (hex_val(bytes[i + 1]), hex_val(bytes[i + 2])) {
|
&& i + 2 < bytes.len()
|
||||||
|
&& let (Some(h), Some(l)) = (hex_val(bytes[i + 1]), hex_val(bytes[i + 2]))
|
||||||
|
{
|
||||||
out.push((h << 4) | l);
|
out.push((h << 4) | l);
|
||||||
i += 3;
|
i += 3;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
out.push(bytes[i]);
|
out.push(bytes[i]);
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -149,8 +149,9 @@ fn parse_parameter(v: &Value, parent_label: &str) -> Option<SignatureParameter>
|
||||||
documentation,
|
documentation,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if let Some(arr) = label_field.as_array() {
|
if let Some(arr) = label_field.as_array()
|
||||||
if arr.len() == 2 {
|
&& arr.len() == 2
|
||||||
|
{
|
||||||
let start = arr[0].as_u64()? as u32;
|
let start = arr[0].as_u64()? as u32;
|
||||||
let end = arr[1].as_u64()? as u32;
|
let end = arr[1].as_u64()? as u32;
|
||||||
let s = parent_label
|
let s = parent_label
|
||||||
|
|
@ -163,7 +164,6 @@ fn parse_parameter(v: &Value, parent_label: &str) -> Option<SignatureParameter>
|
||||||
documentation,
|
documentation,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -171,11 +171,11 @@ fn extract_markup_text(v: &Value) -> Option<String> {
|
||||||
if let Some(s) = v.as_str() {
|
if let Some(s) = v.as_str() {
|
||||||
return Some(s.to_owned());
|
return Some(s.to_owned());
|
||||||
}
|
}
|
||||||
if let Some(obj) = v.as_object() {
|
if let Some(obj) = v.as_object()
|
||||||
if let Some(s) = obj.get("value").and_then(Value::as_str) {
|
&& let Some(s) = obj.get("value").and_then(Value::as_str)
|
||||||
|
{
|
||||||
return Some(s.to_owned());
|
return Some(s.to_owned());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -383,8 +383,9 @@ impl View for SignatureView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if max_rows > 1 {
|
if max_rows > 1
|
||||||
if let Some(doc) = snap.documentation.as_deref() {
|
&& let Some(doc) = snap.documentation.as_deref()
|
||||||
|
{
|
||||||
for (i, line) in doc.lines().enumerate() {
|
for (i, line) in doc.lines().enumerate() {
|
||||||
let row_idx = i as u32 + 1;
|
let row_idx = i as u32 + 1;
|
||||||
if row_idx >= max_rows {
|
if row_idx >= max_rows {
|
||||||
|
|
@ -405,8 +406,7 @@ impl View for SignatureView {
|
||||||
cell.attachment = None;
|
cell.attachment = None;
|
||||||
col += 1;
|
col += 1;
|
||||||
if width == 2 && col < max_cols {
|
if width == 2 && col < max_cols {
|
||||||
let cont =
|
let cont = cells.at(CellCoord::new(origin.row + row_idx, origin.col + col));
|
||||||
cells.at(CellCoord::new(origin.row + row_idx, origin.col + col));
|
|
||||||
cont.glyph = Glyph::Continuation;
|
cont.glyph = Glyph::Continuation;
|
||||||
cont.style = Style::default();
|
cont.style = Style::default();
|
||||||
cont.attachment = None;
|
cont.attachment = None;
|
||||||
|
|
@ -417,7 +417,6 @@ impl View for SignatureView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn char_display_width(ch: char) -> u32 {
|
fn char_display_width(ch: char) -> u32 {
|
||||||
UnicodeWidthChar::width(ch).unwrap_or(0) as u32
|
UnicodeWidthChar::width(ch).unwrap_or(0) as u32
|
||||||
|
|
|
||||||
|
|
@ -102,11 +102,11 @@ pub fn resolve_socket_path_with_runtime(arg: Option<&str>, runtime: &Path) -> Pa
|
||||||
/// non-empty, else `/tmp/pmacs-<uid>`.
|
/// non-empty, else `/tmp/pmacs-<uid>`.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn runtime_dir() -> PathBuf {
|
pub fn runtime_dir() -> PathBuf {
|
||||||
if let Some(xdg) = env::var_os("XDG_RUNTIME_DIR") {
|
if let Some(xdg) = env::var_os("XDG_RUNTIME_DIR")
|
||||||
if !xdg.is_empty() {
|
&& !xdg.is_empty()
|
||||||
|
{
|
||||||
return PathBuf::from(xdg);
|
return PathBuf::from(xdg);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
PathBuf::from(format!("/tmp/pmacs-{}", current_uid()))
|
PathBuf::from(format!("/tmp/pmacs-{}", current_uid()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -84,14 +84,14 @@ pub fn render(
|
||||||
edits.push(edit);
|
edits.push(edit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !text.is_empty() {
|
if !text.is_empty()
|
||||||
if let Ok(edit) = buf.apply_edit(EditOp::Insert {
|
&& let Ok(edit) = buf.apply_edit(EditOp::Insert {
|
||||||
pos: 0,
|
pos: 0,
|
||||||
bytes: text.as_bytes(),
|
bytes: text.as_bytes(),
|
||||||
}) {
|
})
|
||||||
|
{
|
||||||
edits.push(edit);
|
edits.push(edit);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
buf.mark_clean();
|
buf.mark_clean();
|
||||||
(id, edits)
|
(id, edits)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -356,7 +356,7 @@ mod soak_helpers {
|
||||||
1 => rt.dispatch_compute_sum((u64::from(rng()) % 1_000) + 1, None),
|
1 => rt.dispatch_compute_sum((u64::from(rng()) % 1_000) + 1, None),
|
||||||
_ => rt.dispatch_emit_n((u64::from(rng()) % 32) + 1, None, Some(8)),
|
_ => rt.dispatch_emit_n((u64::from(rng()) % 32) + 1, None, Some(8)),
|
||||||
};
|
};
|
||||||
if rng() % 4 == 0 {
|
if rng().is_multiple_of(4) {
|
||||||
rt.cancel(id);
|
rt.cancel(id);
|
||||||
}
|
}
|
||||||
let inner_deadline = Instant::now() + Duration::from_secs(2);
|
let inner_deadline = Instant::now() + Duration::from_secs(2);
|
||||||
|
|
|
||||||
|
|
@ -269,14 +269,14 @@ impl Observer {
|
||||||
// reconstruct here. In M10.11's smoke / scenario
|
// reconstruct here. In M10.11's smoke / scenario
|
||||||
// tests, the observer attaches before any edit
|
// tests, the observer attaches before any edit
|
||||||
// activity, so this branch shouldn't fire.
|
// activity, so this branch shouldn't fire.
|
||||||
if let Some(r) = self.replicas.get(&buffer_id) {
|
if let Some(r) = self.replicas.get(&buffer_id)
|
||||||
if let Err(e) = r.import_updates(&op.bytes) {
|
&& let Err(e) = r.import_updates(&op.bytes)
|
||||||
|
{
|
||||||
self.import_errors
|
self.import_errors
|
||||||
.entry(buffer_id)
|
.entry(buffer_id)
|
||||||
.or_insert_with(|| format!("{e:?}"));
|
.or_insert_with(|| format!("{e:?}"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
InstanceMessage::PresenceUpdate { frontend_id, .. }
|
InstanceMessage::PresenceUpdate { frontend_id, .. }
|
||||||
if frontend_id != self.frontend_id =>
|
if frontend_id != self.frontend_id =>
|
||||||
{
|
{
|
||||||
|
|
@ -349,11 +349,11 @@ impl Observer {
|
||||||
let deadline = Instant::now() + timeout;
|
let deadline = Instant::now() + timeout;
|
||||||
loop {
|
loop {
|
||||||
self.pump(Duration::from_millis(100));
|
self.pump(Duration::from_millis(100));
|
||||||
if let Some(text) = self.materialized(buffer_id) {
|
if let Some(text) = self.materialized(buffer_id)
|
||||||
if text == expected {
|
&& text == expected
|
||||||
|
{
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if Instant::now() >= deadline {
|
if Instant::now() >= deadline {
|
||||||
let observed = self
|
let observed = self
|
||||||
.materialized(buffer_id)
|
.materialized(buffer_id)
|
||||||
|
|
@ -375,11 +375,11 @@ impl Observer {
|
||||||
let deadline = Instant::now() + timeout;
|
let deadline = Instant::now() + timeout;
|
||||||
loop {
|
loop {
|
||||||
self.pump(Duration::from_millis(100));
|
self.pump(Duration::from_millis(100));
|
||||||
if let Some(text) = self.materialized(buffer_id) {
|
if let Some(text) = self.materialized(buffer_id)
|
||||||
if substrings.iter().all(|s| text.contains(s)) {
|
&& substrings.iter().all(|s| text.contains(s))
|
||||||
|
{
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if Instant::now() >= deadline {
|
if Instant::now() >= deadline {
|
||||||
let observed = self
|
let observed = self
|
||||||
.materialized(buffer_id)
|
.materialized(buffer_id)
|
||||||
|
|
|
||||||
|
|
@ -3002,12 +3002,12 @@ fn m4_12_definition_response_lands_in_store() {
|
||||||
mgr.borrow_mut().tick();
|
mgr.borrow_mut().tick();
|
||||||
let store = mgr.borrow().definition_store();
|
let store = mgr.borrow().definition_store();
|
||||||
let guard = store.lock().expect("lock");
|
let guard = store.lock().expect("lock");
|
||||||
if let Some(r) = guard.get(&key) {
|
if let Some(r) = guard.get(&key)
|
||||||
if let Some(loc) = r.locations.first() {
|
&& let Some(loc) = r.locations.first()
|
||||||
|
{
|
||||||
got = Some((loc.line, loc.col));
|
got = Some((loc.line, loc.col));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
drop(guard);
|
drop(guard);
|
||||||
std::thread::sleep(Duration::from_millis(15));
|
std::thread::sleep(Duration::from_millis(15));
|
||||||
}
|
}
|
||||||
|
|
@ -3043,12 +3043,12 @@ fn m4_12_formatting_response_lands_in_store() {
|
||||||
mgr.borrow_mut().tick();
|
mgr.borrow_mut().tick();
|
||||||
let store = mgr.borrow().formatting_store();
|
let store = mgr.borrow().formatting_store();
|
||||||
let guard = store.lock().expect("lock");
|
let guard = store.lock().expect("lock");
|
||||||
if let Some(r) = guard.get(&key) {
|
if let Some(r) = guard.get(&key)
|
||||||
if !r.edits.is_empty() {
|
&& !r.edits.is_empty()
|
||||||
|
{
|
||||||
got = r.edits.clone();
|
got = r.edits.clone();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
drop(guard);
|
drop(guard);
|
||||||
std::thread::sleep(Duration::from_millis(15));
|
std::thread::sleep(Duration::from_millis(15));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -142,16 +142,16 @@ fn attach_send_key_receive_cell_response() {
|
||||||
stream
|
stream
|
||||||
.set_read_timeout(Some(Duration::from_millis(200)))
|
.set_read_timeout(Some(Duration::from_millis(200)))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
if let Ok(msg) = read_message::<InstanceMessage>(&mut stream) {
|
if let Ok(msg) = read_message::<InstanceMessage>(&mut stream)
|
||||||
if matches!(
|
&& matches!(
|
||||||
msg,
|
msg,
|
||||||
InstanceMessage::CellDelta { .. } | InstanceMessage::Cursor(_)
|
InstanceMessage::CellDelta { .. } | InstanceMessage::Cursor(_)
|
||||||
) {
|
)
|
||||||
|
{
|
||||||
got_response = true;
|
got_response = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
assert!(got_response, "expected render response after key");
|
assert!(got_response, "expected render response after key");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -830,13 +830,13 @@ fn m10_9_other_frontend_cursor_appears_in_recipient_cell_delta_with_color() {
|
||||||
for cell in &span.cells {
|
for cell in &span.cells {
|
||||||
// The palette uses Color::Rgb(...). Any cell whose
|
// The palette uses Color::Rgb(...). Any cell whose
|
||||||
// fg is a palette entry is an overlay cell.
|
// fg is a palette entry is an overlay cell.
|
||||||
if let Color::Rgb(_, _, _) = cell.style.fg {
|
if let Color::Rgb(_, _, _) = cell.style.fg
|
||||||
if is_palette_color(cell.style.fg) {
|
&& is_palette_color(cell.style.fg)
|
||||||
|
{
|
||||||
saw_palette_cell = true;
|
saw_palette_cell = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if saw_palette_cell {
|
if saw_palette_cell {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -937,15 +937,15 @@ fn wait_for_palette_color_in_b(stream: &mut UnixStream, timeout: Duration) -> Op
|
||||||
{
|
{
|
||||||
for span in &spans {
|
for span in &spans {
|
||||||
for cell in &span.cells {
|
for cell in &span.cells {
|
||||||
if let Color::Rgb(_, _, _) = cell.style.fg {
|
if let Color::Rgb(_, _, _) = cell.style.fg
|
||||||
if is_palette_color(cell.style.fg) {
|
&& is_palette_color(cell.style.fg)
|
||||||
|
{
|
||||||
return Some(cell.style.fg);
|
return Some(cell.style.fg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1554,31 +1554,27 @@ fn m10_10_criterion_3_two_frontend_conflict_converges() {
|
||||||
let mut a_received_b_op = false;
|
let mut a_received_b_op = false;
|
||||||
let mut b_received_a_op = false;
|
let mut b_received_a_op = false;
|
||||||
while Instant::now() < deadline && !(a_received_b_op && b_received_a_op) {
|
while Instant::now() < deadline && !(a_received_b_op && b_received_a_op) {
|
||||||
if !a_received_b_op {
|
if !a_received_b_op
|
||||||
if let Ok(InstanceMessage::CrdtOp { op, .. }) =
|
&& let Ok(InstanceMessage::CrdtOp { op, .. }) =
|
||||||
read_message::<InstanceMessage>(&mut stream_a)
|
read_message::<InstanceMessage>(&mut stream_a)
|
||||||
|
&& op.peer_id == hello_b.assigned_frontend_id.0
|
||||||
{
|
{
|
||||||
if op.peer_id == hello_b.assigned_frontend_id.0 {
|
|
||||||
replica_a
|
replica_a
|
||||||
.import_updates(&op.bytes)
|
.import_updates(&op.bytes)
|
||||||
.expect("a import B's op");
|
.expect("a import B's op");
|
||||||
a_received_b_op = true;
|
a_received_b_op = true;
|
||||||
}
|
}
|
||||||
}
|
if !b_received_a_op
|
||||||
}
|
&& let Ok(InstanceMessage::CrdtOp { op, .. }) =
|
||||||
if !b_received_a_op {
|
|
||||||
if let Ok(InstanceMessage::CrdtOp { op, .. }) =
|
|
||||||
read_message::<InstanceMessage>(&mut stream_b)
|
read_message::<InstanceMessage>(&mut stream_b)
|
||||||
|
&& op.peer_id == hello_a.assigned_frontend_id.0
|
||||||
{
|
{
|
||||||
if op.peer_id == hello_a.assigned_frontend_id.0 {
|
|
||||||
replica_b
|
replica_b
|
||||||
.import_updates(&op.bytes)
|
.import_updates(&op.bytes)
|
||||||
.expect("b import A's op");
|
.expect("b import A's op");
|
||||||
b_received_a_op = true;
|
b_received_a_op = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
assert!(
|
assert!(
|
||||||
a_received_b_op,
|
a_received_b_op,
|
||||||
"criterion 3: A must receive B's CrdtOp via daemon broadcast"
|
"criterion 3: A must receive B's CrdtOp via daemon broadcast"
|
||||||
|
|
@ -2008,13 +2004,12 @@ fn m10_10_f26_spoofed_loro_internal_peer_id_is_rejected() {
|
||||||
while Instant::now() < deadline {
|
while Instant::now() < deadline {
|
||||||
if let Ok(InstanceMessage::CrdtOp { op, .. }) =
|
if let Ok(InstanceMessage::CrdtOp { op, .. }) =
|
||||||
read_message::<InstanceMessage>(&mut stream_b)
|
read_message::<InstanceMessage>(&mut stream_b)
|
||||||
|
&& op.bytes == spoofed_bytes
|
||||||
{
|
{
|
||||||
if op.bytes == spoofed_bytes {
|
|
||||||
saw_spoofed_broadcast = true;
|
saw_spoofed_broadcast = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
assert!(
|
assert!(
|
||||||
!saw_spoofed_broadcast,
|
!saw_spoofed_broadcast,
|
||||||
"F26: daemon must reject ops whose loro-internal peer attribution \
|
"F26: daemon must reject ops whose loro-internal peer attribution \
|
||||||
|
|
|
||||||
|
|
@ -84,17 +84,16 @@ fn locate_lua() -> Option<PathBuf> {
|
||||||
return Some(p);
|
return Some(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Ok(out) = std::process::Command::new("which").arg(name).output() {
|
if let Ok(out) = std::process::Command::new("which").arg(name).output()
|
||||||
if out.status.success() {
|
&& out.status.success()
|
||||||
if let Ok(path) = String::from_utf8(out.stdout) {
|
&& let Ok(path) = String::from_utf8(out.stdout)
|
||||||
|
{
|
||||||
let path = path.trim();
|
let path = path.trim();
|
||||||
if !path.is_empty() {
|
if !path.is_empty() {
|
||||||
return Some(PathBuf::from(path));
|
return Some(PathBuf::from(path));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"skipping: lua/luajit not on PATH (set PMACS_TEST_LUA or PMACS_TEST_LUAJIT to override)"
|
"skipping: lua/luajit not on PATH (set PMACS_TEST_LUA or PMACS_TEST_LUAJIT to override)"
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -396,7 +396,7 @@ fn m6_6_buffer_memory_stays_under_200mb_during_run() {
|
||||||
let reached_target = pump_until(
|
let reached_target = pump_until(
|
||||||
&mut editor,
|
&mut editor,
|
||||||
|e| history_bytes(e) >= TARGET_HISTORY_BYTES,
|
|e| history_bytes(e) >= TARGET_HISTORY_BYTES,
|
||||||
Duration::from_secs(60),
|
Duration::from_mins(1),
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
reached_target,
|
reached_target,
|
||||||
|
|
|
||||||
|
|
@ -1012,13 +1012,13 @@ fn dired_sort_mtime_orders_newest_first() {
|
||||||
.write(true)
|
.write(true)
|
||||||
.open(&oldest)
|
.open(&oldest)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.set_modified(now - Duration::from_secs(120))
|
.set_modified(now - Duration::from_mins(2))
|
||||||
.expect("set mtime oldest");
|
.expect("set mtime oldest");
|
||||||
std::fs::File::options()
|
std::fs::File::options()
|
||||||
.write(true)
|
.write(true)
|
||||||
.open(&middle)
|
.open(&middle)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.set_modified(now - Duration::from_secs(60))
|
.set_modified(now - Duration::from_mins(1))
|
||||||
.expect("set mtime middle");
|
.expect("set mtime middle");
|
||||||
std::fs::File::options()
|
std::fs::File::options()
|
||||||
.write(true)
|
.write(true)
|
||||||
|
|
|
||||||
|
|
@ -288,14 +288,14 @@ fn m9_3_cancellation_reaches_server() {
|
||||||
// file.
|
// file.
|
||||||
if let Ok(entries) = std::fs::read_dir(&cancel_dir) {
|
if let Ok(entries) = std::fs::read_dir(&cancel_dir) {
|
||||||
for entry in entries.flatten() {
|
for entry in entries.flatten() {
|
||||||
if let Some(name) = entry.file_name().to_str() {
|
if let Some(name) = entry.file_name().to_str()
|
||||||
if name.starts_with("cancelled-") {
|
&& name.starts_with("cancelled-")
|
||||||
|
{
|
||||||
sentinel_seen = true;
|
sentinel_seen = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if sentinel_seen && runtime.is_complete(job) {
|
if sentinel_seen && runtime.is_complete(job) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue