diff options
author | Evan Martin <evan.martin@gmail.com> | 2024-01-08 10:57:35 -0800 |
---|---|---|
committer | Evan Martin <evan.martin@gmail.com> | 2024-01-08 11:08:47 -0800 |
commit | 738e5641f169d96ac634c9437373a9ce4f1f6c61 (patch) | |
tree | 9b71e6f1de5a41425d41461be7e351e87d3b163e | |
parent | 81ebd8649dd2fd7de8fa8dd06c13ee5b62efb912 (diff) | |
download | n2-738e5641f169d96ac634c9437373a9ce4f1f6c61.tar.gz |
allow windows drive letters in depfiles
See bug report context in #98.
From a patch from Tobias Hieta <tobias.hieta@ubisoft.com>.
-rw-r--r-- | src/depfile.rs | 46 |
1 files changed, 39 insertions, 7 deletions
diff --git a/src/depfile.rs b/src/depfile.rs index 33144c6..7ee5493 100644 --- a/src/depfile.rs +++ b/src/depfile.rs @@ -31,12 +31,15 @@ fn skip_spaces(scanner: &mut Scanner) -> ParseResult<()> { } /// Read one path from the input scanner. +/// Note: treats colon as a valid character in a path because of Windows-style +/// paths, but this means that the inital `output: ...` path will include the +/// trailing colon. fn read_path<'a>(scanner: &mut Scanner<'a>) -> ParseResult<Option<&'a str>> { skip_spaces(scanner)?; let start = scanner.ofs; loop { match scanner.read() { - '\0' | ' ' | ':' | '\r' | '\n' => { + '\0' | ' ' | '\r' | '\n' => { scanner.back(); break; } @@ -64,7 +67,13 @@ pub fn parse<'a>(scanner: &mut Scanner<'a>) -> ParseResult<Deps<'a>> { Some(o) => o, }; scanner.skip_spaces(); - scanner.expect(':')?; + let target = match target.strip_suffix(':') { + None => { + scanner.expect(':')?; + target + } + Some(target) => target, + }; let mut deps = Vec::new(); while let Some(p) = read_path(scanner)? { deps.push(p); @@ -79,16 +88,19 @@ pub fn parse<'a>(scanner: &mut Scanner<'a>) -> ParseResult<Deps<'a>> { #[cfg(test)] mod tests { - use std::path::Path; - use super::*; + use std::path::Path; - fn must_parse(buf: &mut Vec<u8>) -> Deps { + fn try_parse(buf: &mut Vec<u8>) -> Result<Deps, String> { buf.push(0); let mut scanner = Scanner::new(buf); - match parse(&mut scanner) { + parse(&mut scanner).map_err(|err| scanner.format_parse_error(Path::new("test"), err)) + } + + fn must_parse(buf: &mut Vec<u8>) -> Deps { + match try_parse(buf) { Err(err) => { - println!("{}", scanner.format_parse_error(Path::new("test"), err)); + println!("{}", err); panic!("failed parse"); } Ok(d) => d, @@ -153,4 +165,24 @@ mod tests { assert_eq!(deps.target, "build/browse.o"); assert_eq!(deps.deps.len(), 1); } + + #[test] + fn test_parse_windows_dep_path() { + let mut file = b"odd/path.o: C:/odd\\path.c".to_vec(); + let deps = must_parse(&mut file); + assert_eq!(deps.target, "odd/path.o"); + assert_eq!(deps.deps[0], "C:/odd\\path.c"); + assert_eq!(deps.deps.len(), 1); + } + + #[test] + fn test_parse_missing_colon() { + let mut file = b"foo bar".to_vec(); + let err = try_parse(&mut file).unwrap_err(); + assert!( + err.starts_with("parse error: expected ':'"), + "expected parse error, got {:?}", + err + ); + } } |