ElyMark: dropped and pasted pictures copy into assets and link at the caret (C14.10)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
ZacharyZhang-NYandClaude Opus 5.5 committed 2026-10-12 07:29:57 -04:00
1 parent 72e9441399
commit b74f4e4e72
12 files changed
+357 -63

No files matched your search

+1
View File
@@ -19,6 +19,7 @@ pub use task::RecoveryTask;
pub use save::{
SaveError, Saved, atomic_capable, claim_all, export, import_attachment, same_file, save,
write_attachment,
save_as, save_atomic, save_overwrite, save_with_backup, save_with_probe,
};
pub use session::{Fingerprint, Open, SaveState, SaveTicket, Session, Sessions, StaleTicket};
+25 -16
View File
@@ -212,24 +212,38 @@ pub fn same_file(a: &Path, b: &Path) -> io::Result<bool> {
/// Copies an attachment in; the source is never touched (FILE-07).
pub fn import_attachment(source: &Path, dir: &Path) -> io::Result<PathBuf> {
std::fs::create_dir_all(dir).map_err(|e| with_path(dir, e))?;
let name = source.file_name().ok_or_else(|| {
io::Error::new(
io::ErrorKind::InvalidInput,
format!("{} has no file name", source.display()),
)
})?;
let mut target = dir.join(name);
let stem = Path::new(name)
.file_stem()
.unwrap_or_default()
.to_string_lossy()
.into_owned();
let ext = Path::new(name)
let mut from = std::fs::File::open(source).map_err(|e| with_path(source, e))?;
let target = attach(dir, Path::new(name), |to| io::copy(&mut from, to).map(drop))?;
log::info!("files: imported {} to {}", source.display(), target.display());
Ok(target)
}
/// Writes `bytes` into `dir` as `name`, or a free variant.
pub fn write_attachment(name: &str, bytes: &[u8], dir: &Path) -> io::Result<PathBuf> {
let target = attach(dir, Path::new(name), |to| to.write_all(bytes))?;
log::info!("files: wrote {} bytes to {}", bytes.len(), target.display());
Ok(target)
}
/// Claims a free name like `name`, then fills it.
fn attach(
dir: &Path,
name: &Path,
fill: impl FnOnce(&mut std::fs::File) -> io::Result<()>,
) -> io::Result<PathBuf> {
std::fs::create_dir_all(dir).map_err(|e| with_path(dir, e))?;
let stem = name.file_stem().unwrap_or_default().to_string_lossy().into_owned();
let ext = name
.extension()
.map(|ext| ext.to_string_lossy().into_owned())
.unwrap_or_default();
let mut from = std::fs::File::open(source).map_err(|e| with_path(source, e))?;
let mut target = dir.join(name);
let mut counter = 1;
// Claims the name; another writer's file is never replaced.
let mut to = loop {
@@ -242,17 +256,12 @@ pub fn import_attachment(source: &Path, dir: &Path) -> io::Result<PathBuf> {
Err(e) => return Err(with_path(&target, e)),
}
};
let copied = io::copy(&mut from, &mut to).and_then(|_| to.flush());
if let Err(e) = copied {
let filled = fill(&mut to).and_then(|()| to.flush());
if let Err(e) = filled {
// A half copy is not left behind.
std::fs::remove_file(&target).ok();
return Err(with_path(&target, e));
}
log::info!(
"files: imported {} to {}",
source.display(),
target.display()
);
Ok(target)
}
+9
View File
@@ -180,6 +180,15 @@ fn an_import_copies_and_never_deletes() {
assert_eq!(read(&second), "png-bytes");
}
#[test]
fn written_bytes_take_a_free_name() {
let dir = tempfile::tempdir().expect("a temp dir");
let first = write_attachment("pasted.png", b"one", dir.path()).expect("the first write");
let second = write_attachment("pasted.png", b"two", dir.path()).expect("the second write");
assert_ne!(first, second);
assert_eq!((read(&first), read(&second)), ("one".into(), "two".into()));
}
#[test]
fn a_numbered_import_name_fits_long_file_names() {
let dir = tempfile::tempdir().expect("a temp dir");