Fix saving files as *.sql on macOS Sequoia (#20195)

Closes #16969

Release Notes:

- Fixed a bug in macOS Sequoia where you can't save a new file as
`*.sql`, it would rename to `.sql.s`. As a side effect you can no longer
save a new file as `*sql.s`. We hope to remove this workaround when the
operating system fixes its bug; in the meantime you can either set
`"use_system_path_prompts": false` in your settings file to skip the
macOS dialogues, or create new files by right clicking in the project
panel.
This commit is contained in:
Conrad Irwin 2024-11-04 13:23:59 -07:00 committed by GitHub
parent c9ec235b12
commit cfcbfc1d82
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -391,7 +391,7 @@ impl MacPlatform {
}
}
fn os_version(&self) -> Result<SemanticVersion> {
fn os_version() -> Result<SemanticVersion> {
unsafe {
let process_info = NSProcessInfo::processInfo(nil);
let version = process_info.operatingSystemVersion();
@ -585,7 +585,7 @@ impl Platform for MacPlatform {
// API only available post Monterey
// https://developer.apple.com/documentation/appkit/nsworkspace/3753004-setdefaultapplicationaturl
let (done_tx, done_rx) = oneshot::channel();
if self.os_version().ok() < Some(SemanticVersion::new(12, 0, 0)) {
if Self::os_version().ok() < Some(SemanticVersion::new(12, 0, 0)) {
return Task::ready(Err(anyhow!(
"macOS 12.0 or later is required to register URL schemes"
)));
@ -695,7 +695,36 @@ impl Platform for MacPlatform {
if response == NSModalResponse::NSModalResponseOk {
let url = panel.URL();
if url.isFileURL() == YES {
result = ns_url_to_path(panel.URL()).ok()
result = ns_url_to_path(panel.URL()).ok().map(|mut result| {
let Some(filename) = result.file_name() else {
return result;
};
let chunks = filename
.as_bytes()
.split(|&b| b == b'.')
.collect::<Vec<_>>();
// https://github.com/zed-industries/zed/issues/16969
// Workaround a bug in macOS Sequoia that adds an extra file-extension
// sometimes. e.g. `a.sql` becomes `a.sql.s` or `a.txtx` becomes `a.txtx.txt`
//
// This is conditional on OS version because I'd like to get rid of it, so that
// you can manually create a file called `a.sql.s`. That said it seems better
// to break that use-case than breaking `a.sql`.
if chunks.len() == 3 && chunks[1].starts_with(chunks[2]) {
if Self::os_version()
.is_ok_and(|v| v >= SemanticVersion::new(15, 0, 0))
{
let new_filename = OsStr::from_bytes(
&filename.as_bytes()
[..chunks[0].len() + 1 + chunks[1].len()],
)
.to_owned();
result.set_file_name(&new_filename);
}
}
return result;
})
}
}