Skip to content

Commit d852b52

Browse files
authored
refactor: divide pacquet-fs into multiple files (#214)
1 parent 96ab1de commit d852b52

File tree

5 files changed

+115
-108
lines changed

5 files changed

+115
-108
lines changed

crates/fs/src/ensure_file.rs

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
use derive_more::{Display, Error};
2+
use miette::Diagnostic;
3+
use std::{
4+
fs::{self, OpenOptions},
5+
io::{self, Write},
6+
path::{Path, PathBuf},
7+
};
8+
9+
/// Error type of [`ensure_file`].
10+
#[derive(Debug, Display, Error, Diagnostic)]
11+
pub enum EnsureFileError {
12+
#[display("Failed to create the parent directory at {parent_dir:?}: {error}")]
13+
CreateDir {
14+
parent_dir: PathBuf,
15+
#[error(source)]
16+
error: io::Error,
17+
},
18+
#[display("Failed to create file at {file_path:?}: {error}")]
19+
CreateFile {
20+
file_path: PathBuf,
21+
#[error(source)]
22+
error: io::Error,
23+
},
24+
#[display("Failed to write to file at {file_path:?}: {error}")]
25+
WriteFile {
26+
file_path: PathBuf,
27+
#[error(source)]
28+
error: io::Error,
29+
},
30+
}
31+
32+
/// Write `content` to `file_path` unless it already exists.
33+
///
34+
/// Ancestor directories will be created if they don't already exist.
35+
pub fn ensure_file(
36+
file_path: &Path,
37+
content: &[u8],
38+
#[cfg_attr(windows, allow(unused))] mode: Option<u32>,
39+
) -> Result<(), EnsureFileError> {
40+
if file_path.exists() {
41+
return Ok(());
42+
}
43+
44+
let parent_dir = file_path.parent().unwrap();
45+
fs::create_dir_all(parent_dir).map_err(|error| EnsureFileError::CreateDir {
46+
parent_dir: parent_dir.to_path_buf(),
47+
error,
48+
})?;
49+
50+
let mut options = OpenOptions::new();
51+
options.write(true).create(true);
52+
53+
#[cfg(unix)]
54+
{
55+
use std::os::unix::fs::OpenOptionsExt;
56+
if let Some(mode) = mode {
57+
options.mode(mode);
58+
}
59+
}
60+
61+
options
62+
.open(file_path)
63+
.map_err(|error| EnsureFileError::CreateFile { file_path: file_path.to_path_buf(), error })?
64+
.write_all(content)
65+
.map_err(|error| EnsureFileError::WriteFile { file_path: file_path.to_path_buf(), error })
66+
}

crates/fs/src/file_mode.rs

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
use std::io;
2+
3+
/// Bit mask to filter executable bits (`--x--x--x`).
4+
pub const EXEC_MASK: u32 = 0b001_001_001;
5+
6+
/// All can read and execute, but only owner can write (`rwxr-xr-x`).
7+
pub const EXEC_MODE: u32 = 0b111_101_101;
8+
9+
/// Whether a file mode has all executable bits.
10+
pub fn is_all_exec(mode: u32) -> bool {
11+
mode & EXEC_MASK == EXEC_MASK
12+
}
13+
14+
/// Set file mode to 777 on POSIX platforms such as Linux or macOS,
15+
/// or do nothing on Windows.
16+
#[cfg_attr(windows, allow(unused))]
17+
pub fn make_file_executable(file: &std::fs::File) -> io::Result<()> {
18+
#[cfg(unix)]
19+
return {
20+
use std::{
21+
fs::Permissions,
22+
os::unix::fs::{MetadataExt, PermissionsExt},
23+
};
24+
let mode = file.metadata()?.mode();
25+
let mode = mode | EXEC_MASK;
26+
let permissions = Permissions::from_mode(mode);
27+
file.set_permissions(permissions)
28+
};
29+
30+
#[cfg(windows)]
31+
return Ok(());
32+
}

crates/fs/src/lib.rs

+5-107
Original file line numberDiff line numberDiff line change
@@ -1,109 +1,7 @@
1-
use derive_more::{Display, Error};
2-
use miette::Diagnostic;
3-
use std::{
4-
fs::{self, OpenOptions},
5-
io::{self, Write},
6-
path::{Path, PathBuf},
7-
};
1+
mod ensure_file;
2+
mod symlink_dir;
83

9-
pub mod file_mode {
10-
/// Bit mask to filter executable bits (`--x--x--x`).
11-
pub const EXEC_MASK: u32 = 0b001_001_001;
4+
pub use ensure_file::*;
5+
pub use symlink_dir::*;
126

13-
/// All can read and execute, but only owner can write (`rwxr-xr-x`).
14-
pub const EXEC_MODE: u32 = 0b111_101_101;
15-
16-
/// Whether a file mode has all executable bits.
17-
pub fn is_all_exec(mode: u32) -> bool {
18-
mode & EXEC_MASK == EXEC_MASK
19-
}
20-
}
21-
22-
/// Create a symlink to a directory.
23-
///
24-
/// The `link` path will be a symbolic link pointing to `original`.
25-
pub fn symlink_dir(original: &Path, link: &Path) -> io::Result<()> {
26-
#[cfg(unix)]
27-
return std::os::unix::fs::symlink(original, link);
28-
#[cfg(windows)]
29-
return junction::create(original, link); // junctions instead of symlinks because symlinks may require elevated privileges.
30-
}
31-
32-
/// Error type of [`ensure_file`].
33-
#[derive(Debug, Display, Error, Diagnostic)]
34-
pub enum EnsureFileError {
35-
#[display("Failed to create the parent directory at {parent_dir:?}: {error}")]
36-
CreateDir {
37-
parent_dir: PathBuf,
38-
#[error(source)]
39-
error: io::Error,
40-
},
41-
#[display("Failed to create file at {file_path:?}: {error}")]
42-
CreateFile {
43-
file_path: PathBuf,
44-
#[error(source)]
45-
error: io::Error,
46-
},
47-
#[display("Failed to write to file at {file_path:?}: {error}")]
48-
WriteFile {
49-
file_path: PathBuf,
50-
#[error(source)]
51-
error: io::Error,
52-
},
53-
}
54-
55-
/// Write `content` to `file_path` unless it already exists.
56-
///
57-
/// Ancestor directories will be created if they don't already exist.
58-
pub fn ensure_file(
59-
file_path: &Path,
60-
content: &[u8],
61-
#[cfg_attr(windows, allow(unused))] mode: Option<u32>,
62-
) -> Result<(), EnsureFileError> {
63-
if file_path.exists() {
64-
return Ok(());
65-
}
66-
67-
let parent_dir = file_path.parent().unwrap();
68-
fs::create_dir_all(parent_dir).map_err(|error| EnsureFileError::CreateDir {
69-
parent_dir: parent_dir.to_path_buf(),
70-
error,
71-
})?;
72-
73-
let mut options = OpenOptions::new();
74-
options.write(true).create(true);
75-
76-
#[cfg(unix)]
77-
{
78-
use std::os::unix::fs::OpenOptionsExt;
79-
if let Some(mode) = mode {
80-
options.mode(mode);
81-
}
82-
}
83-
84-
options
85-
.open(file_path)
86-
.map_err(|error| EnsureFileError::CreateFile { file_path: file_path.to_path_buf(), error })?
87-
.write_all(content)
88-
.map_err(|error| EnsureFileError::WriteFile { file_path: file_path.to_path_buf(), error })
89-
}
90-
91-
/// Set file mode to 777 on POSIX platforms such as Linux or macOS,
92-
/// or do nothing on Windows.
93-
#[cfg_attr(windows, allow(unused))]
94-
pub fn make_file_executable(file: &std::fs::File) -> io::Result<()> {
95-
#[cfg(unix)]
96-
return {
97-
use std::{
98-
fs::Permissions,
99-
os::unix::fs::{MetadataExt, PermissionsExt},
100-
};
101-
let mode = file.metadata()?.mode();
102-
let mode = mode | file_mode::EXEC_MASK;
103-
let permissions = Permissions::from_mode(mode);
104-
file.set_permissions(permissions)
105-
};
106-
107-
#[cfg(windows)]
108-
return Ok(());
109-
}
7+
pub mod file_mode;

crates/fs/src/symlink_dir.rs

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
use std::{io, path::Path};
2+
3+
/// Create a symlink to a directory.
4+
///
5+
/// The `link` path will be a symbolic link pointing to `original`.
6+
pub fn symlink_dir(original: &Path, link: &Path) -> io::Result<()> {
7+
#[cfg(unix)]
8+
return std::os::unix::fs::symlink(original, link);
9+
#[cfg(windows)]
10+
return junction::create(original, link); // junctions instead of symlinks because symlinks may require elevated privileges.
11+
}

tasks/integrated-benchmark/src/work_env.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::{
55
};
66
use itertools::Itertools;
77
use os_display::Quotable;
8-
use pacquet_fs::make_file_executable;
8+
use pacquet_fs::file_mode::make_file_executable;
99
use pipe_trait::Pipe;
1010
use std::{
1111
borrow::Cow,

0 commit comments

Comments
 (0)