mirror of
https://github.com/uutils/findutils.git
synced 2026-06-10 15:48:30 -07:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| efe6dc05f9 | |||
| 53980035af | |||
| e2d84e98d5 | |||
| 865ab0991e | |||
| 8add685cc6 | |||
| c4afeab1bc |
@@ -92,7 +92,7 @@ jobs:
|
||||
path: lcov.info
|
||||
|
||||
- name: Upload coverage to codecov.io
|
||||
uses: codecov/codecov-action@v6
|
||||
uses: codecov/codecov-action@v7
|
||||
with:
|
||||
files: lcov.info
|
||||
fail_ci_if_error: true
|
||||
|
||||
@@ -18,10 +18,10 @@ jobs:
|
||||
name: Run benchmarks
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Setup Rust toolchain, cache and cargo-codspeed binary
|
||||
uses: moonrepo/setup-rust@v0
|
||||
uses: moonrepo/setup-rust@v1
|
||||
with:
|
||||
channel: stable
|
||||
cache-target: release
|
||||
|
||||
@@ -975,7 +975,7 @@ fn build_matcher_tree(
|
||||
)
|
||||
}
|
||||
}
|
||||
None => return Err(From::from(format!("Unrecognized flag: '{}'", args[i]))),
|
||||
None => return Err(From::from(format!("unknown predicate '{}'", args[i]))),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
+40
-10
@@ -167,16 +167,21 @@ impl FormatStringParser<'_> {
|
||||
// Try parsing an octal sequence first.
|
||||
let first = self.front()?;
|
||||
if first.is_digit(OCTAL_RADIX) {
|
||||
if let Ok(code) = self.peek(OCTAL_LEN).and_then(|octal| {
|
||||
u32::from_str_radix(octal, OCTAL_RADIX).map_err(std::convert::Into::into)
|
||||
}) {
|
||||
// safe to unwrap: .peek() already succeeded above.
|
||||
let octal = self.advance_by(OCTAL_LEN).unwrap();
|
||||
return match char::from_u32(code) {
|
||||
Some(c) => Ok(FormatComponent::Literal(c.to_string())),
|
||||
None => Err(format!("Invalid character value: \\{octal}").into()),
|
||||
};
|
||||
}
|
||||
// A GNU octal escape is 1 to 3 octal digits. Consume only the leading
|
||||
// octal digits (which are ASCII), rather than slicing a fixed 3 bytes
|
||||
// that can land inside a following multibyte char.
|
||||
let octal: String = self
|
||||
.string
|
||||
.chars()
|
||||
.take(OCTAL_LEN)
|
||||
.take_while(|c| c.is_digit(OCTAL_RADIX))
|
||||
.collect();
|
||||
let code = u32::from_str_radix(&octal, OCTAL_RADIX)?;
|
||||
self.advance_by(octal.len())?;
|
||||
return match char::from_u32(code) {
|
||||
Some(c) => Ok(FormatComponent::Literal(c.to_string())),
|
||||
None => Err(format!("Invalid character value: \\{octal}").into()),
|
||||
};
|
||||
}
|
||||
|
||||
self.advance_one()?;
|
||||
@@ -688,6 +693,31 @@ mod tests {
|
||||
assert!(FormatString::parse("\\").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_octal_escape_before_multibyte_char() {
|
||||
assert_eq!(
|
||||
FormatString::parse("\\0€").unwrap().components,
|
||||
vec![
|
||||
FormatComponent::Literal("\0".to_owned()),
|
||||
FormatComponent::Literal("€".to_owned()),
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
FormatString::parse("\\1😀").unwrap().components,
|
||||
vec![
|
||||
FormatComponent::Literal("\u{1}".to_owned()),
|
||||
FormatComponent::Literal("😀".to_owned()),
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
FormatString::parse("\\00é").unwrap().components,
|
||||
vec![
|
||||
FormatComponent::Literal("\0".to_owned()),
|
||||
FormatComponent::Literal("é".to_owned()),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_formatting() {
|
||||
fn unaligned_directive(directive: FormatDirective) -> FormatComponent {
|
||||
|
||||
+1
-1
@@ -546,7 +546,7 @@ mod tests {
|
||||
//
|
||||
let result = super::parse_args(&["-asdadsafsfsadcs"]);
|
||||
if let Err(e) = result {
|
||||
assert_eq!(e.to_string(), "Unrecognized flag: '-asdadsafsfsadcs'");
|
||||
assert_eq!(e.to_string(), "unknown predicate '-asdadsafsfsadcs'");
|
||||
} else {
|
||||
panic!("parse_args should have returned an error");
|
||||
}
|
||||
|
||||
+4
-2
@@ -490,8 +490,10 @@ impl DbReader {
|
||||
return None;
|
||||
};
|
||||
|
||||
// drop nul byte when matching
|
||||
match String::from_utf8_lossy(&buf[..buf.len() - 1]).as_ref() {
|
||||
// drop the trailing nul byte when matching. `read_until` may stop at EOF
|
||||
// without one (e.g. a too-short file), so strip it only if present rather
|
||||
// than slicing `buf.len() - 1`, which underflows when `buf` is empty.
|
||||
match String::from_utf8_lossy(buf.strip_suffix(b"\0").unwrap_or(&buf)).as_ref() {
|
||||
"LOCATE02" => Some(DbFormat::Locate02),
|
||||
_ => None,
|
||||
}
|
||||
|
||||
@@ -253,3 +253,16 @@ fn test_updatedb_locate_roundtrip() {
|
||||
"locate output did not contain the indexed file: {stdout:?}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_locate_one_byte_db() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let db = dir.path().join("db_1byte");
|
||||
std::fs::write(&db, b"X").unwrap();
|
||||
Command::cargo_bin("locate")
|
||||
.expect("couldn't find locate binary")
|
||||
.arg(format!("--database={}", db.display()))
|
||||
.arg("foo")
|
||||
.assert()
|
||||
.code(1);
|
||||
}
|
||||
|
||||
@@ -82,6 +82,24 @@ fn multiple_matcher_success() {
|
||||
.stdout_contains("abbbc");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unknown_predicate_is_rejected() {
|
||||
// GNU find rejects an unrecognized predicate with
|
||||
// "find: unknown predicate '<arg>'" and exit code 1 (see the GNU
|
||||
// testsuite's tests/find/refuse-noop test).
|
||||
ucmd()
|
||||
.arg("-noop")
|
||||
.fails()
|
||||
.stderr_contains("unknown predicate '-noop'")
|
||||
.no_stdout();
|
||||
|
||||
ucmd()
|
||||
.arg("---noop")
|
||||
.fails()
|
||||
.stderr_contains("unknown predicate '---noop'")
|
||||
.no_stdout();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_matcher_failure() {
|
||||
ucmd()
|
||||
|
||||
Reference in New Issue
Block a user