From e0415e5d32c7006a8f78d5bd9228adc68d980df4 Mon Sep 17 00:00:00 2001 From: Sergio Triana Escobedo Date: Mon, 12 Jan 2026 14:38:52 -0600 Subject: [PATCH 1/3] feat: create parent directories when saving new file (fixes #737) --- crates/edit/src/bin/edit/documents.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/crates/edit/src/bin/edit/documents.rs b/crates/edit/src/bin/edit/documents.rs index 33fc8cf5a76d..7e386f1d5eb5 100644 --- a/crates/edit/src/bin/edit/documents.rs +++ b/crates/edit/src/bin/edit/documents.rs @@ -4,6 +4,7 @@ use std::collections::LinkedList; use std::ffi::OsStr; use std::fs::File; +use std::fs; use std::path::{Path, PathBuf}; use edit::buffer::{RcTextBuffer, TextBuffer}; @@ -210,6 +211,12 @@ impl DocumentManager { } pub fn open_for_writing(path: &Path) -> apperr::Result { + // Crear directorios padres si no existen + if let Some(parent) = path.parent() { + if !parent.exists() { + fs::create_dir_all(parent).map_err(apperr::Error::from)?; + } + } File::create(path).map_err(apperr::Error::from) } From ab80cdc7e61e8dfaf70535d009be5a21d370a26b Mon Sep 17 00:00:00 2001 From: Sergio Triana Escobedo Date: Mon, 12 Jan 2026 15:33:07 -0600 Subject: [PATCH 2/3] feat: improve error handling for directory creation and file writing --- crates/edit/src/bin/edit/documents.rs | 40 +++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/crates/edit/src/bin/edit/documents.rs b/crates/edit/src/bin/edit/documents.rs index 7e386f1d5eb5..97b7269996d7 100644 --- a/crates/edit/src/bin/edit/documents.rs +++ b/crates/edit/src/bin/edit/documents.rs @@ -211,13 +211,26 @@ impl DocumentManager { } pub fn open_for_writing(path: &Path) -> apperr::Result { - // Crear directorios padres si no existen + // Error handling for directory creation and file writing if let Some(parent) = path.parent() { if !parent.exists() { - fs::create_dir_all(parent).map_err(apperr::Error::from)?; + match fs::create_dir_all(parent) { + Ok(_) => {}, + Err(e) => { + // Log or handle the error as needed + eprintln!("[Error] Failed to create parent directories for {:?}: {}", parent, e); + return Err(apperr::Error::from(e)); + } + } + } + } + match File::create(path) { + Ok(f) => Ok(f), + Err(e) => { + eprintln!("[Error] Failed to create file {:?}: {}", path, e); + Err(apperr::Error::from(e)) } } - File::create(path).map_err(apperr::Error::from) } fn create_buffer() -> apperr::Result { @@ -319,4 +332,25 @@ mod tests { assert_eq!(parse("file.txt:10"), ("file.txt", Some(Point { x: 0, y: 9 }))); assert_eq!(parse("file.txt:10:5"), ("file.txt", Some(Point { x: 4, y: 9 }))); } + + #[test] + fn test_open_for_writing_error() { + // It is not possible to reliably trigger a file creation error on all systems/environments. + // Instead, we check that the function works for a valid temp path. + use std::env; + use std::fs; + use std::path::PathBuf; + + let mut temp_path = env::temp_dir(); + temp_path.push("test_open_for_writing_should_succeed.txt"); + + // Clean up before test + let _ = fs::remove_file(&temp_path); + + let result = DocumentManager::open_for_writing(&temp_path); + assert!(result.is_ok(), "Expected to be able to create a file in temp dir"); + + // Clean up after test + let _ = fs::remove_file(&temp_path); + } } From 668c10bc73c901b981a30a1d53cf485cef5a0d6d Mon Sep 17 00:00:00 2001 From: Leonard Hecker Date: Mon, 19 Jan 2026 19:39:46 +0100 Subject: [PATCH 3/3] Simplify, Improve Windows support --- crates/edit/src/bin/edit/documents.rs | 50 ++++++--------------------- crates/edit/src/sys/windows.rs | 4 ++- 2 files changed, 13 insertions(+), 41 deletions(-) diff --git a/crates/edit/src/bin/edit/documents.rs b/crates/edit/src/bin/edit/documents.rs index 97b7269996d7..4366417af624 100644 --- a/crates/edit/src/bin/edit/documents.rs +++ b/crates/edit/src/bin/edit/documents.rs @@ -3,8 +3,8 @@ use std::collections::LinkedList; use std::ffi::OsStr; -use std::fs::File; use std::fs; +use std::fs::File; use std::path::{Path, PathBuf}; use edit::buffer::{RcTextBuffer, TextBuffer}; @@ -212,25 +212,16 @@ impl DocumentManager { pub fn open_for_writing(path: &Path) -> apperr::Result { // Error handling for directory creation and file writing - if let Some(parent) = path.parent() { - if !parent.exists() { - match fs::create_dir_all(parent) { - Ok(_) => {}, - Err(e) => { - // Log or handle the error as needed - eprintln!("[Error] Failed to create parent directories for {:?}: {}", parent, e); - return Err(apperr::Error::from(e)); - } - } - } - } - match File::create(path) { - Ok(f) => Ok(f), - Err(e) => { - eprintln!("[Error] Failed to create file {:?}: {}", path, e); - Err(apperr::Error::from(e)) - } + + // It is worth doing an existence check because it is significantly + // faster than calling mkdir() and letting it fail (at least on Windows). + if let Some(parent) = path.parent() + && !parent.exists() + { + fs::create_dir_all(parent)?; } + + File::create(path).map_err(apperr::Error::from) } fn create_buffer() -> apperr::Result { @@ -332,25 +323,4 @@ mod tests { assert_eq!(parse("file.txt:10"), ("file.txt", Some(Point { x: 0, y: 9 }))); assert_eq!(parse("file.txt:10:5"), ("file.txt", Some(Point { x: 4, y: 9 }))); } - - #[test] - fn test_open_for_writing_error() { - // It is not possible to reliably trigger a file creation error on all systems/environments. - // Instead, we check that the function works for a valid temp path. - use std::env; - use std::fs; - use std::path::PathBuf; - - let mut temp_path = env::temp_dir(); - temp_path.push("test_open_for_writing_should_succeed.txt"); - - // Clean up before test - let _ = fs::remove_file(&temp_path); - - let result = DocumentManager::open_for_writing(&temp_path); - assert!(result.is_ok(), "Expected to be able to create a file in temp dir"); - - // Clean up after test - let _ = fs::remove_file(&temp_path); - } } diff --git a/crates/edit/src/sys/windows.rs b/crates/edit/src/sys/windows.rs index 03e9ca7da1bf..380153b407e7 100644 --- a/crates/edit/src/sys/windows.rs +++ b/crates/edit/src/sys/windows.rs @@ -706,7 +706,9 @@ pub fn apperr_format(f: &mut std::fmt::Formatter<'_>, code: u32) -> std::fmt::Re /// Checks if the given error is a "file not found" error. pub fn apperr_is_not_found(err: apperr::Error) -> bool { - err == gle_to_apperr(Foundation::ERROR_FILE_NOT_FOUND) + const FNF: apperr::Error = gle_to_apperr(Foundation::ERROR_FILE_NOT_FOUND); + const PNF: apperr::Error = gle_to_apperr(Foundation::ERROR_PATH_NOT_FOUND); + err == FNF || err == PNF } fn check_bool_return(ret: BOOL) -> apperr::Result<()> {