diff options
| author | Jack O'Connor <[email protected]> | 2024-11-25 13:37:52 -0800 |
|---|---|---|
| committer | Jack O'Connor <[email protected]> | 2024-11-25 13:50:46 -0800 |
| commit | 1170f023bf459ea3d0bedd285d6ae32309ee348c (patch) | |
| tree | ae9a3eaf8463565ea087f51cee79264ad6c6e7e6 /b3sum/src | |
| parent | aa3e8ec32a389461babde3789d6ac50ee3c38662 (diff) | |
add support for windows newlines in b3sum --check
Fixes #222.
Diffstat (limited to 'b3sum/src')
| -rw-r--r-- | b3sum/src/main.rs | 16 | ||||
| -rw-r--r-- | b3sum/src/unit_tests.rs | 30 |
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); +} |
