Fixes for M-02 to M-14, G-01 to G-14, K-02 to K-04, X-04 to X-14, not yet reviewed

Committed before review so Windows and WSL builds can start.
Each fix was tested and mutation-checked here; the codex review
of each item is still to come, so tasks/BUGS.md stays unticked.

M-02 is mid-review: round 1 findings are fixed (apps/ely-mark/src/tally.rs).
K-01 stays deferred. The ElyMark window test mark-outside.sh failed
once at its crash-recovery step in the last run; not yet looked into.
This commit is contained in:
ZacharyZhang-NY committed 2026-10-10 02:29:19 -04:00
1 parent 6505f35669
commit d59159cea2
75 files changed
+1482 -354

No files matched your search

+24 -9
View File
@@ -30,16 +30,27 @@ fn identity(path: &Path) -> io::Result<PathBuf> {
pub trait Saving: Host {
/// The tab whose source file is `target`.
fn holder(&self, target: &Path) -> io::Result<Option<u64>> {
// Target errors stand; a tab's gone volume does not.
let target = identity(target)?;
for tab in &self.core().tabs {
if let Some(open) = tab.session.path()
&& ely_files::same_file(open, target)?
{
return Ok(Some(tab.id));
let Some(open) = tab.session.path() else { continue };
match ely_files::same_file(open, &target) {
Ok(true) => return Ok(Some(tab.id)),
Ok(false) => {}
Err(error) => log::warn!("office: tab {} has no file to compare: {error}", tab.id),
}
}
Ok(None)
}
/// A save as refused unwritten; a waiting close stops.
fn refuse_save(&mut self, then: &Option<After>, words: gpui::SharedString, cx: &mut Context<Self>) {
self.toast(words, Severity::Danger, cx);
if then.is_some() {
self.close_stopped(cx);
}
}
/// Saves in place in its own format.
fn save(&mut self, id: u64, then: Option<After>, window: &mut Window, cx: &mut Context<Self>) {
if !self.settled(id, cx) {
@@ -216,25 +227,29 @@ pub trait Saving: Host {
host.write_as(id, path, then, window, cx)
});
}
let name = self.tab(id).map(|tab| tab.name.clone()).unwrap_or_default();
let unsaved = |error: io::Error, cx: &mut Context<Self>| {
text(cx, "office.error.save", &[("name", &name), ("error", &error.to_string())])
};
let target = match identity(&path) {
Ok(target) => target,
Err(error) => return self.report(id, Err(SaveError::Io(error)), cx),
Err(error) => return self.refuse_save(&then, unsaved(error, cx), cx),
};
let Some(format) = files::save_as_format(&Self::KIND, &target) else {
let formats = Self::KIND.save_as.join(", .");
let text = text(cx, "office.error.format", &[("formats", &formats)]);
return self.toast(text, Severity::Danger, cx);
return self.refuse_save(&then, text, cx);
};
let Some(tab) = self.tab(id) else {
return log::info!("office: tab {id} closed before its save");
};
let holder = match self.holder(&target) {
Ok(holder) => holder,
Err(error) => return self.report(id, Err(SaveError::Io(error)), cx),
Err(error) => return self.refuse_save(&then, unsaved(error, cx), cx),
};
if holder.is_some_and(|other| other != id) {
let text = text(cx, "office.error.taken", &[("name", &file_name(&target))]);
return self.toast(text, Severity::Danger, cx);
return self.refuse_save(&then, text, cx);
}
let own_format = tab
.session
@@ -242,7 +257,7 @@ pub trait Saving: Host {
.and_then(|open| files::kept_format(&Self::KIND, open).ok());
if holder == Some(id) && (tab.risk.is_some() || own_format != Some(format)) {
let text = text(cx, "office.error.convert", &[]);
return self.toast(text, Severity::Danger, cx);
return self.refuse_save(&then, text, cx);
}
// The written file differs from the open one; reopen it.
let reopen =