Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mktemp: add func to expose functionality (for use in nushell) #5479

Merged
merged 2 commits into from
Nov 7, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 40 additions & 18 deletions src/uu/mktemp/src/mktemp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,29 +115,30 @@ impl Display for MkTempError {
/// This provides a layer of indirection between the application logic
/// and the argument parsing library `clap`, allowing each to vary
/// independently.
struct Options {
#[derive(Clone)]
pub struct Options {
/// Whether to create a temporary directory instead of a file.
directory: bool,
pub directory: bool,

/// Whether to just print the name of a file that would have been created.
dry_run: bool,
pub dry_run: bool,

/// Whether to suppress file creation error messages.
quiet: bool,
pub quiet: bool,

/// The directory in which to create the temporary file.
///
/// If `None`, the file will be created in the current directory.
tmpdir: Option<PathBuf>,
pub tmpdir: Option<PathBuf>,

/// The suffix to append to the temporary file, if any.
suffix: Option<String>,
pub suffix: Option<String>,

/// Whether to treat the template argument as a single file path component.
treat_as_template: bool,
pub treat_as_template: bool,

/// The template to use for the name of the temporary file.
template: String,
pub template: String,
}

impl Options {
Expand Down Expand Up @@ -192,7 +193,7 @@ impl Options {
/// `num_rand_chars`.
struct Params {
/// The directory that will contain the temporary file.
directory: String,
directory: PathBuf,

/// The (non-random) prefix of the temporary file.
prefix: String,
Expand Down Expand Up @@ -297,7 +298,7 @@ impl Params {
let num_rand_chars = j - i;

Ok(Self {
directory,
directory: directory.into(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool that we indeed already get the PathBuf from clap! However, we still need to fix this conversion from String inbetween, but I'll open an issue for that.

prefix,
num_rand_chars,
suffix,
Expand Down Expand Up @@ -357,12 +358,13 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
exec(&tmpdir, &prefix, rand, &suffix, make_dir)
};

if suppress_file_err {
let res = if suppress_file_err {
// Mapping all UErrors to ExitCodes prevents the errors from being printed
res.map_err(|e| e.code().into())
} else {
res
}
};
println_verbatim(res?).map_err_context(|| "failed to print directory name".to_owned())
}

pub fn uu_app() -> Command {
Expand Down Expand Up @@ -441,7 +443,7 @@ pub fn uu_app() -> Command {
.arg(Arg::new(ARG_TEMPLATE).num_args(..=1))
}

pub fn dry_exec(tmpdir: &str, prefix: &str, rand: usize, suffix: &str) -> UResult<()> {
fn dry_exec(tmpdir: &Path, prefix: &str, rand: usize, suffix: &str) -> UResult<PathBuf> {
let len = prefix.len() + suffix.len() + rand;
let mut buf = Vec::with_capacity(len);
buf.extend(prefix.as_bytes());
Expand All @@ -462,7 +464,7 @@ pub fn dry_exec(tmpdir: &str, prefix: &str, rand: usize, suffix: &str) -> UResul
// We guarantee utf8.
let buf = String::from_utf8(buf).unwrap();
let tmpdir = Path::new(tmpdir).join(buf);
println_verbatim(tmpdir).map_err_context(|| "failed to print directory name".to_owned())
Ok(tmpdir)
}

/// Create a temporary directory with the given parameters.
Expand All @@ -476,7 +478,7 @@ pub fn dry_exec(tmpdir: &str, prefix: &str, rand: usize, suffix: &str) -> UResul
///
/// If the temporary directory could not be written to disk or if the
/// given directory `dir` does not exist.
fn make_temp_dir(dir: &str, prefix: &str, rand: usize, suffix: &str) -> UResult<PathBuf> {
fn make_temp_dir(dir: &Path, prefix: &str, rand: usize, suffix: &str) -> UResult<PathBuf> {
let mut builder = Builder::new();
builder.prefix(prefix).rand_bytes(rand).suffix(suffix);
match builder.tempdir_in(dir) {
Expand Down Expand Up @@ -508,7 +510,7 @@ fn make_temp_dir(dir: &str, prefix: &str, rand: usize, suffix: &str) -> UResult<
///
/// If the file could not be written to disk or if the directory does
/// not exist.
fn make_temp_file(dir: &str, prefix: &str, rand: usize, suffix: &str) -> UResult<PathBuf> {
fn make_temp_file(dir: &Path, prefix: &str, rand: usize, suffix: &str) -> UResult<PathBuf> {
let mut builder = Builder::new();
builder.prefix(prefix).rand_bytes(rand).suffix(suffix);
match builder.tempfile_in(dir) {
Expand All @@ -527,7 +529,7 @@ fn make_temp_file(dir: &str, prefix: &str, rand: usize, suffix: &str) -> UResult
}
}

fn exec(dir: &str, prefix: &str, rand: usize, suffix: &str, make_dir: bool) -> UResult<()> {
fn exec(dir: &Path, prefix: &str, rand: usize, suffix: &str, make_dir: bool) -> UResult<PathBuf> {
let path = if make_dir {
make_temp_dir(dir, prefix, rand, suffix)?
} else {
Expand All @@ -546,7 +548,27 @@ fn exec(dir: &str, prefix: &str, rand: usize, suffix: &str, make_dir: bool) -> U
// relative path.
let path = Path::new(dir).join(filename);

println_verbatim(path).map_err_context(|| "failed to print directory name".to_owned())
Ok(path)
}

/// Create a temporary file or directory
///
/// Behavior is determined by the `options` parameter, see [`Options`] for details.
pub fn mktemp(options: &Options) -> UResult<PathBuf> {
// Parse file path parameters from the command-line options.
let Params {
directory: tmpdir,
prefix,
num_rand_chars: rand,
suffix,
} = Params::from(options.clone())?;

// Create the temporary file or directory, or simulate creating it.
if options.dry_run {
dry_exec(&tmpdir, &prefix, rand, &suffix)
} else {
exec(&tmpdir, &prefix, rand, &suffix, options.directory)
}
}

#[cfg(test)]
Expand Down