mod mark_path { use git_tempfile::{AutoRemove, ContainingDirectory}; #[test] fn it_persists_markers_along_with_newly_created_directories() -> crate::Result { let dir = tempfile::tempdir()?; let target = dir.path().join("a").join("b").join("file.tmp"); let new_filename = target.parent().unwrap().join("file.ext"); let handle = git_tempfile::mark_at( &target, ContainingDirectory::CreateAllRaceProof(Default::default()), AutoRemove::TempfileAndEmptyParentDirectoriesUntil { boundary_directory: dir.path().into(), }, )?; std::fs::create_dir(&new_filename)?; let err = handle .persist(&new_filename) .expect_err("cannot persist onto directory"); let handle = err.handle; std::fs::remove_dir(&new_filename)?; handle.take().expect("still there").persist(&new_filename)?; assert!(!target.exists(), "tempfile was renamed"); assert!( new_filename.is_file(), "new file was placed (and parent directories still exist)" ); Ok(()) } #[test] fn it_can_create_the_containing_directory_and_remove_it_on_drop() -> crate::Result { let dir = tempfile::tempdir()?; let first_dir = "dir"; let filename = dir.path().join(first_dir).join("subdir").join("file.tmp"); let tempfile = git_tempfile::mark_at( &filename, ContainingDirectory::CreateAllRaceProof(Default::default()), AutoRemove::TempfileAndEmptyParentDirectoriesUntil { boundary_directory: dir.path().into(), }, )?; assert!(filename.is_file(), "specified file should exist precisely"); drop(tempfile); assert!( !filename.is_file(), "after drop named files are deleted as well as extra directories" ); assert!( !dir.path().join(first_dir).is_dir(), "previously created and now empty directories are deleted, too" ); Ok(()) }}mod at_path { use git_tempfile::{AutoRemove, ContainingDirectory}; #[test] fn reduce_resource_usage_by_converting_files_to_markers_and_persist_them() -> crate::Result { let dir = tempfile::tempdir()?; let target = dir.path().join("a").join("file.tmp"); let new_filename = target.parent().unwrap().join("file.ext"); let mut file = git_tempfile::writable_at( &target, ContainingDirectory::CreateAllRaceProof(Default::default()), AutoRemove::TempfileAndEmptyParentDirectoriesUntil { boundary_directory: dir.path().into(), }, )?; file.with_mut(|f| f.as_file_mut().write_all(b"hello world"))??; let mark = file.close()?; mark.take().expect("still there").persist(&new_filename)?; assert!(!target.exists(), "tempfile was renamed"); assert!( new_filename.is_file(), "new file was placed (and parent directories still exist)" ); assert_eq!( std::fs::read(new_filename)?, &b"hello world"[..], "written content is persisted, too" ); Ok(()) } use std::io::{ErrorKind, Write}; #[test] fn it_persists_tempfiles_along_with_newly_created_directories() -> crate::Result { let dir = tempfile::tempdir()?; let target = dir.path().join("a").join("b").join("file.tmp"); let new_filename = target.parent().unwrap().join("file.ext"); assert!( !new_filename.is_file(), "the filename for persistence doesn't exist yet" ); let handle = git_tempfile::writable_at( &target, ContainingDirectory::CreateAllRaceProof(Default::default()), AutoRemove::TempfileAndEmptyParentDirectoriesUntil { boundary_directory: dir.path().into(), }, )?; std::fs::create_dir(&new_filename)?; let err = handle .persist(&new_filename) .expect_err("cannot persist onto directory"); let handle = err.handle; std::fs::remove_dir(&new_filename)?; let mut file = handle.take().expect("still there"); file.write_all(b"hello world")?; drop(file.persist(&new_filename)?); assert!(!target.exists(), "tempfile was renamed"); assert!( new_filename.is_file(), "new file was placed (and parent directories still exist)" ); assert_eq!( std::fs::read(new_filename)?, &b"hello world"[..], "written content is persisted, too" ); Ok(()) } #[test] fn it_can_create_the_containing_directory_and_remove_it_on_drop() -> crate::Result { let dir = tempfile::tempdir()?; let first_dir = "dir"; let filename = dir.path().join(first_dir).join("subdir").join("file.tmp"); let tempfile = git_tempfile::writable_at( &filename, ContainingDirectory::CreateAllRaceProof(Default::default()), AutoRemove::TempfileAndEmptyParentDirectoriesUntil { boundary_directory: dir.path().into(), }, )?; assert!(filename.is_file(), "specified file should exist precisely"); drop(tempfile); assert!( !filename.is_file(), "after drop named files are deleted as well as extra directories" ); assert!( !dir.path().join(first_dir).is_dir(), "previously created and now empty directories are deleted, too" ); assert!(dir.path().is_dir(), "it won't touch the containing directory"); Ok(()) } #[test] fn it_names_files_correctly_and_similarly_named_tempfiles_cannot_be_created() -> crate::Result { let dir = tempfile::tempdir()?; let filename = dir.path().join("something-specific.ext"); let tempfile = git_tempfile::writable_at(&filename, ContainingDirectory::Exists, AutoRemove::Tempfile)?; let res = git_tempfile::writable_at(&filename, ContainingDirectory::Exists, AutoRemove::Tempfile); assert!( matches!(res, Err(err) if err.kind() == ErrorKind::AlreadyExists), "only one tempfile can be created at a time, they are exclusive" ); assert!(filename.is_file(), "specified file should exist precisely"); drop(tempfile); assert!(!filename.is_file(), "after drop named files are deleted as well"); assert!(dir.path().is_dir(), "it won't touch the containing directory"); Ok(()) }} mod new { use std::{ io::{ErrorKind, Write}, path::Path, }; use git_tempfile::{AutoRemove, ContainingDirectory}; fn filecount_in(path: impl AsRef<Path>) -> usize { std::fs::read_dir(path).expect("valid dir").count() } #[test] fn it_can_be_kept() -> crate::Result { let dir = tempfile::tempdir()?; drop( git_tempfile::new(dir.path(), ContainingDirectory::Exists, AutoRemove::Tempfile)? .take() .expect("not taken yet") .keep()?, ); assert_eq!(filecount_in(&dir), 1, "a temp file and persisted"); Ok(()) } #[test] fn it_is_removed_if_it_goes_out_of_scope() -> crate::Result { let dir = tempfile::tempdir()?; { let _keep = git_tempfile::new(dir.path(), ContainingDirectory::Exists, AutoRemove::Tempfile)?; assert_eq!(filecount_in(&dir), 1, "a temp file was created"); } assert_eq!(filecount_in(&dir), 0, "lock was automatically removed"); Ok(()) } #[test] fn it_can_create_the_containing_directory_and_remove_it_when_dropped() -> crate::Result { let dir = tempfile::tempdir()?; let containing_dir = dir.path().join("dir"); assert!(!containing_dir.exists()); { let mut writable = git_tempfile::new( &containing_dir, ContainingDirectory::CreateAllRaceProof(Default::default()), AutoRemove::TempfileAndEmptyParentDirectoriesUntil { boundary_directory: dir.path().into(), }, )?; assert_eq!( filecount_in(&dir), 1, "a temp file was created, as well as the directory" ); writable.with_mut(|tf| tf.write_all(b"hello world"))??; assert_eq!( writable .with_mut(|_tf| Err::<(), std::io::Error>(ErrorKind::Other.into()))? .unwrap_err() .kind(), ErrorKind::Other, "errors are propagated" ); writable .with_mut(|tf| assert!(tf.path().is_file())) .expect("after seeing an error before the file still exists"); } assert!(!containing_dir.is_dir(), "the now empty directory was deleted as well"); assert!(dir.path().is_dir(), "it won't touch the containing directory"); Ok(()) }}
mod mark_path {
use git_tempfile::{AutoRemove, ContainingDirectory};
#[test]
fn it_persists_markers_along_with_newly_created_directories() -> crate::Result {
let dir = tempfile::tempdir()?;
let target = dir.path().join("a").join("b").join("file.tmp");
let new_filename = target.parent().unwrap().join("file.ext");
let handle = git_tempfile::mark_at(
&target,
ContainingDirectory::CreateAllRaceProof(Default::default()),
AutoRemove::TempfileAndEmptyParentDirectoriesUntil {
boundary_directory: dir.path().into(),
},
)?;
std::fs::create_dir(&new_filename)?;
let err = handle
.persist(&new_filename)
.expect_err("cannot persist onto directory");
let handle = err.handle;
std::fs::remove_dir(&new_filename)?;
handle.take().expect("still there").persist(&new_filename)?;
assert!(!target.exists(), "tempfile was renamed");
assert!(
new_filename.is_file(),
"new file was placed (and parent directories still exist)"
);
Ok(())
}
#[test]
fn it_can_create_the_containing_directory_and_remove_it_on_drop() -> crate::Result {
let dir = tempfile::tempdir()?;
let first_dir = "dir";
let filename = dir.path().join(first_dir).join("subdir").join("file.tmp");
let tempfile = git_tempfile::mark_at(
&filename,
ContainingDirectory::CreateAllRaceProof(Default::default()),
AutoRemove::TempfileAndEmptyParentDirectoriesUntil {
boundary_directory: dir.path().into(),
},
)?;
assert!(filename.is_file(), "specified file should exist precisely");
drop(tempfile);
assert!(
!filename.is_file(),
"after drop named files are deleted as well as extra directories"
);
assert!(
!dir.path().join(first_dir).is_dir(),
"previously created and now empty directories are deleted, too"
);
Ok(())
}
}
mod at_path {
use git_tempfile::{AutoRemove, ContainingDirectory};
#[test]
fn reduce_resource_usage_by_converting_files_to_markers_and_persist_them() -> crate::Result {
let dir = tempfile::tempdir()?;
let target = dir.path().join("a").join("file.tmp");
let new_filename = target.parent().unwrap().join("file.ext");
let mut file = git_tempfile::writable_at(
&target,
ContainingDirectory::CreateAllRaceProof(Default::default()),
AutoRemove::TempfileAndEmptyParentDirectoriesUntil {
boundary_directory: dir.path().into(),
},
)?;
file.with_mut(|f| f.as_file_mut().write_all(b"hello world"))??;
let mark = file.close()?;
mark.take().expect("still there").persist(&new_filename)?;
assert!(!target.exists(), "tempfile was renamed");
assert!(
new_filename.is_file(),
"new file was placed (and parent directories still exist)"
);
assert_eq!(
std::fs::read(new_filename)?,
&b"hello world"[..],
"written content is persisted, too"
);
Ok(())
}
use std::io::{ErrorKind, Write};
#[test]
fn it_persists_tempfiles_along_with_newly_created_directories() -> crate::Result {
let dir = tempfile::tempdir()?;
let target = dir.path().join("a").join("b").join("file.tmp");
let new_filename = target.parent().unwrap().join("file.ext");
assert!(
!new_filename.is_file(),
"the filename for persistence doesn't exist yet"
);
let handle = git_tempfile::writable_at(
&target,
ContainingDirectory::CreateAllRaceProof(Default::default()),
AutoRemove::TempfileAndEmptyParentDirectoriesUntil {
boundary_directory: dir.path().into(),
},
)?;
std::fs::create_dir(&new_filename)?;
let err = handle
.persist(&new_filename)
.expect_err("cannot persist onto directory");
let handle = err.handle;
std::fs::remove_dir(&new_filename)?;
let mut file = handle.take().expect("still there");
file.write_all(b"hello world")?;
drop(file.persist(&new_filename)?);
assert!(!target.exists(), "tempfile was renamed");
assert!(
new_filename.is_file(),
"new file was placed (and parent directories still exist)"
);
assert_eq!(
std::fs::read(new_filename)?,
&b"hello world"[..],
"written content is persisted, too"
);
Ok(())
}
#[test]
fn it_can_create_the_containing_directory_and_remove_it_on_drop() -> crate::Result {
let dir = tempfile::tempdir()?;
let first_dir = "dir";
let filename = dir.path().join(first_dir).join("subdir").join("file.tmp");
let tempfile = git_tempfile::writable_at(
&filename,
ContainingDirectory::CreateAllRaceProof(Default::default()),
AutoRemove::TempfileAndEmptyParentDirectoriesUntil {
boundary_directory: dir.path().into(),
},
)?;
assert!(filename.is_file(), "specified file should exist precisely");
drop(tempfile);
assert!(
!filename.is_file(),
"after drop named files are deleted as well as extra directories"
);
assert!(
!dir.path().join(first_dir).is_dir(),
"previously created and now empty directories are deleted, too"
);
assert!(dir.path().is_dir(), "it won't touch the containing directory");
Ok(())
}
#[test]
fn it_names_files_correctly_and_similarly_named_tempfiles_cannot_be_created() -> crate::Result {
let dir = tempfile::tempdir()?;
let filename = dir.path().join("something-specific.ext");
let tempfile = git_tempfile::writable_at(&filename, ContainingDirectory::Exists, AutoRemove::Tempfile)?;
let res = git_tempfile::writable_at(&filename, ContainingDirectory::Exists, AutoRemove::Tempfile);
assert!(
matches!(res, Err(err) if err.kind() == ErrorKind::AlreadyExists),
"only one tempfile can be created at a time, they are exclusive"
);
assert!(filename.is_file(), "specified file should exist precisely");
drop(tempfile);
assert!(!filename.is_file(), "after drop named files are deleted as well");
assert!(dir.path().is_dir(), "it won't touch the containing directory");
Ok(())
}
}
mod new {
use std::{
io::{ErrorKind, Write},
path::Path,
};
use git_tempfile::{AutoRemove, ContainingDirectory};
fn filecount_in(path: impl AsRef<Path>) -> usize {
std::fs::read_dir(path).expect("valid dir").count()
}
#[test]
fn it_can_be_kept() -> crate::Result {
let dir = tempfile::tempdir()?;
drop(
git_tempfile::new(dir.path(), ContainingDirectory::Exists, AutoRemove::Tempfile)?
.take()
.expect("not taken yet")
.keep()?,
);
assert_eq!(filecount_in(&dir), 1, "a temp file and persisted");
Ok(())
}
#[test]
fn it_is_removed_if_it_goes_out_of_scope() -> crate::Result {
let dir = tempfile::tempdir()?;
{
let _keep = git_tempfile::new(dir.path(), ContainingDirectory::Exists, AutoRemove::Tempfile)?;
assert_eq!(filecount_in(&dir), 1, "a temp file was created");
}
assert_eq!(filecount_in(&dir), 0, "lock was automatically removed");
Ok(())
}
#[test]
fn it_can_create_the_containing_directory_and_remove_it_when_dropped() -> crate::Result {
let dir = tempfile::tempdir()?;
let containing_dir = dir.path().join("dir");
assert!(!containing_dir.exists());
{
let mut writable = git_tempfile::new(
&containing_dir,
ContainingDirectory::CreateAllRaceProof(Default::default()),
AutoRemove::TempfileAndEmptyParentDirectoriesUntil {
boundary_directory: dir.path().into(),
},
)?;
assert_eq!(
filecount_in(&dir),
1,
"a temp file was created, as well as the directory"
);
writable.with_mut(|tf| tf.write_all(b"hello world"))??;
assert_eq!(
writable
.with_mut(|_tf| Err::<(), std::io::Error>(ErrorKind::Other.into()))?
.unwrap_err()
.kind(),
ErrorKind::Other,
"errors are propagated"
);
writable
.with_mut(|tf| assert!(tf.path().is_file()))
.expect("after seeing an error before the file still exists");
}
assert!(!containing_dir.is_dir(), "the now empty directory was deleted as well");
assert!(dir.path().is_dir(), "it won't touch the containing directory");
Ok(())
}
}