aboutsummaryrefslogtreecommitdiff
path: root/b3sum/src
diff options
context:
space:
mode:
authorJack O'Connor <[email protected]>2024-11-25 13:37:52 -0800
committerJack O'Connor <[email protected]>2024-11-25 13:50:46 -0800
commit1170f023bf459ea3d0bedd285d6ae32309ee348c (patch)
treeae9a3eaf8463565ea087f51cee79264ad6c6e7e6 /b3sum/src
parentaa3e8ec32a389461babde3789d6ac50ee3c38662 (diff)
add support for windows newlines in b3sum --check
Fixes #222.
Diffstat (limited to 'b3sum/src')
-rw-r--r--b3sum/src/main.rs16
-rw-r--r--b3sum/src/unit_tests.rs30
2 files changed, 32 insertions, 14 deletions
diff --git a/b3sum/src/main.rs b/b3sum/src/main.rs
index a55d910..baa6b6c 100644
--- a/b3sum/src/main.rs
+++ b/b3sum/src/main.rs
@@ -244,8 +244,11 @@ fn filepath_to_string(filepath: &Path) -> FilepathString {
filepath_string = filepath_string.replace('\\', "/");
}
let mut is_escaped = false;
- if filepath_string.contains('\\') || filepath_string.contains('\n') {
- filepath_string = filepath_string.replace('\\', "\\\\").replace('\n', "\\n");
+ if filepath_string.contains(['\\', '\n', '\r']) {
+ filepath_string = filepath_string
+ .replace('\\', "\\\\")
+ .replace('\n', "\\n")
+ .replace('\r', "\\r");
is_escaped = true;
}
FilepathString {
@@ -303,6 +306,7 @@ fn unescape(mut path: &str) -> Result<String> {
match path[i + 1..].chars().next().unwrap() {
// Anything other than a recognized escape sequence is an error.
'n' => unescaped.push_str("\n"),
+ 'r' => unescaped.push_str("\r"),
'\\' => unescaped.push_str("\\"),
_ => bail!("Invalid backslash escape"),
}
@@ -321,13 +325,11 @@ struct ParsedCheckLine {
}
fn parse_check_line(mut line: &str) -> Result<ParsedCheckLine> {
- // Trim off the trailing newline, if any.
- line = line.trim_end_matches('\n');
+ // Trim off the trailing newlines, if any.
+ line = line.trim_end_matches(['\r', '\n']);
// If there's a backslash at the front of the line, that means we need to
// unescape the path below. This matches the behavior of e.g. md5sum.
- let first = if let Some(c) = line.chars().next() {
- c
- } else {
+ let Some(first) = line.chars().next() else {
bail!("Empty line");
};
let mut is_escaped = false;
diff --git a/b3sum/src/unit_tests.rs b/b3sum/src/unit_tests.rs
index 1fa1a17..b95c4a2 100644
--- a/b3sum/src/unit_tests.rs
+++ b/b3sum/src/unit_tests.rs
@@ -28,13 +28,13 @@ fn test_parse_check_line() {
file_path,
expected_hash,
} = crate::parse_check_line(
- "fafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafa fo \to\n\n\n",
+ "fafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafafa \t\r\n\n\r \t\r\n\n\r",
)
.unwrap();
assert_eq!(expected_hash, blake3::Hash::from([0xfa; 32]));
assert!(!is_escaped);
- assert_eq!(file_string, "fo \to");
- assert_eq!(file_path, Path::new("fo \to"));
+ assert_eq!(file_string, " \t\r\n\n\r \t");
+ assert_eq!(file_path, Path::new(" \t\r\n\n\r \t"));
// path is one space
let crate::ParsedCheckLine {
@@ -71,20 +71,20 @@ fn test_parse_check_line() {
assert_eq!(file_path, Path::new("fo\\a\\no"));
}
- // escaped newline
+ // escaped newlines
let crate::ParsedCheckLine {
file_string,
is_escaped,
file_path,
expected_hash,
} = crate::parse_check_line(
- "\\4444444444444444444444444444444444444444444444444444444444444444 fo\\n\\no",
+ "\\4444444444444444444444444444444444444444444444444444444444444444 fo\\r\\n\\n\\ro",
)
.unwrap();
assert_eq!(expected_hash, blake3::Hash::from([0x44; 32]));
assert!(is_escaped);
- assert_eq!(file_string, "fo\\n\\no");
- assert_eq!(file_path, Path::new("fo\n\no"));
+ assert_eq!(file_string, "fo\\r\\n\\n\\ro");
+ assert_eq!(file_path, Path::new("fo\r\n\n\ro"));
// Escaped newline and backslash. Again because backslash is not allowed on
// Windows, this test is Unix-only.
@@ -187,3 +187,19 @@ fn test_parse_check_line() {
.unwrap_err();
}
}
+
+#[test]
+fn test_filepath_to_string() {
+ let output = crate::filepath_to_string(Path::new("foo"));
+ assert_eq!(output.filepath_string, "foo");
+ assert!(!output.is_escaped);
+
+ let output = crate::filepath_to_string(Path::new("f\\ \t\r\noo"));
+ if cfg!(windows) {
+ // We normalize backslashes to forward slashes on Windows.
+ assert_eq!(output.filepath_string, "f/ \t\\r\\noo");
+ } else {
+ assert_eq!(output.filepath_string, "f\\\\ \t\\r\\noo");
+ }
+ assert!(output.is_escaped);
+}