166 Commits

Author SHA1 Message Date
Sylvestre Ledru 0e4517b8c9 version 0.4.0 2023-04-02 19:20:22 +02:00
Sylvestre Ledru 671916f718 Merge pull request #222 from sylvestre/fix-release
Various clippy fixes + precommit
2023-04-02 19:13:13 +02:00
Sylvestre Ledru e4121cc988 Fix more clippy warnings 2023-04-02 18:56:31 +02:00
Sylvestre Ledru d7bb67e53d Fix more clippy warnings 2023-04-02 18:53:40 +02:00
Sylvestre Ledru 3e96a14d1f add a pre commit configuration - just like coreutils 2023-04-02 18:52:18 +02:00
Sylvestre Ledru 3f6ac572e1 fix some clippy warnings 2023-04-02 18:51:29 +02:00
Sylvestre Ledru 8f2409742d Merge pull request #220 from uutils/dependabot/cargo/predicates-3.0.2
build(deps): bump predicates from 2.1.5 to 3.0.2
2023-04-02 18:47:01 +02:00
dependabot[bot] 7469db2027 build(deps): bump predicates from 2.1.5 to 3.0.2
Bumps [predicates](https://github.com/assert-rs/predicates-rs) from 2.1.5 to 3.0.2.
- [Release notes](https://github.com/assert-rs/predicates-rs/releases)
- [Changelog](https://github.com/assert-rs/predicates-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/assert-rs/predicates-rs/compare/v2.1.5...v3.0.2)

---
updated-dependencies:
- dependency-name: predicates
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-27 03:59:28 +00:00
Sylvestre Ledru 5659812641 Merge pull request #213 from int3/embedded
Add support for embedded "{}"
2023-03-13 08:34:09 +01:00
Jez Ng 30a22453d6 Add support for embedded "{}"
Given

  find . -exec foo{}bar \;

GNU find will replace `{}` by the filename. This commit matches that
behavior.

Note that this is not required by the POSIX spec.

The GNU testsuite doesn't cover this case, so I've added a test in this
repo.
2023-02-23 23:38:40 +01:00
Sylvestre Ledru a3287a978f Merge pull request #211 from sylvestre/ci-warnings
fix the ci warnings
2023-02-23 23:38:28 +01:00
Sylvestre Ledru 238100bc67 fix the ci warnings 2023-02-23 23:09:54 +01:00
Sylvestre Ledru 59301c788a Merge pull request #209 from uutils/dependabot/cargo/once_cell-1.17.1
build(deps): bump once_cell from 1.17.0 to 1.17.1
2023-02-15 14:54:48 +01:00
dependabot[bot] 5b907e2ea8 build(deps): bump once_cell from 1.17.0 to 1.17.1
Bumps [once_cell](https://github.com/matklad/once_cell) from 1.17.0 to 1.17.1.
- [Release notes](https://github.com/matklad/once_cell/releases)
- [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md)
- [Commits](https://github.com/matklad/once_cell/compare/v1.17.0...v1.17.1)

---
updated-dependencies:
- dependency-name: once_cell
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-15 03:57:59 +00:00
Sylvestre Ledru 31d3ae2cd1 Merge pull request #207 from uutils/dependabot/cargo/bumpalo-3.12.0
build(deps): bump bumpalo from 3.10.0 to 3.12.0
2023-01-21 09:20:28 +01:00
dependabot[bot] f5f1aac007 build(deps): bump bumpalo from 3.10.0 to 3.12.0
Bumps [bumpalo](https://github.com/fitzgen/bumpalo) from 3.10.0 to 3.12.0.
- [Release notes](https://github.com/fitzgen/bumpalo/releases)
- [Changelog](https://github.com/fitzgen/bumpalo/blob/main/CHANGELOG.md)
- [Commits](https://github.com/fitzgen/bumpalo/compare/3.10.0...3.12.0)

---
updated-dependencies:
- dependency-name: bumpalo
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-20 22:14:12 +00:00
Sylvestre Ledru f044f44cf4 Merge pull request #206 from uutils/dependabot/cargo/serial_test-1.0.0
build(deps): bump serial_test from 0.10.0 to 1.0.0
2023-01-18 08:50:59 +01:00
Sylvestre Ledru cbd2849546 Merge pull request #205 from uutils/dependabot/cargo/nix-0.26.2
build(deps): bump nix from 0.26.1 to 0.26.2
2023-01-18 08:50:51 +01:00
dependabot[bot] 0cbeae5a21 build(deps): bump serial_test from 0.10.0 to 1.0.0
Bumps [serial_test](https://github.com/palfrey/serial_test) from 0.10.0 to 1.0.0.
- [Release notes](https://github.com/palfrey/serial_test/releases)
- [Commits](https://github.com/palfrey/serial_test/compare/v0.10.0...v1.0.0)

---
updated-dependencies:
- dependency-name: serial_test
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-18 03:02:13 +00:00
dependabot[bot] bd0ab84fd5 build(deps): bump nix from 0.26.1 to 0.26.2
Bumps [nix](https://github.com/nix-rust/nix) from 0.26.1 to 0.26.2.
- [Release notes](https://github.com/nix-rust/nix/releases)
- [Changelog](https://github.com/nix-rust/nix/blob/v0.26.2/CHANGELOG.md)
- [Commits](https://github.com/nix-rust/nix/compare/v0.26.1...v0.26.2)

---
updated-dependencies:
- dependency-name: nix
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-18 03:02:06 +00:00
Sylvestre Ledru 78865ea683 Merge pull request #203 from uutils/dependabot/cargo/regex-1.7.1
build(deps): bump regex from 1.7.0 to 1.7.1
2023-01-10 09:50:04 +01:00
Sylvestre Ledru 65c29e0d71 Merge pull request #204 from uutils/dependabot/cargo/assert_cmd-2.0.8
build(deps): bump assert_cmd from 2.0.7 to 2.0.8
2023-01-10 09:49:57 +01:00
dependabot[bot] e523ea125a build(deps): bump assert_cmd from 2.0.7 to 2.0.8
Bumps [assert_cmd](https://github.com/assert-rs/assert_cmd) from 2.0.7 to 2.0.8.
- [Release notes](https://github.com/assert-rs/assert_cmd/releases)
- [Changelog](https://github.com/assert-rs/assert_cmd/blob/master/CHANGELOG.md)
- [Commits](https://github.com/assert-rs/assert_cmd/compare/v2.0.7...v2.0.8)

---
updated-dependencies:
- dependency-name: assert_cmd
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-10 03:02:19 +00:00
dependabot[bot] 7af32c58e9 build(deps): bump regex from 1.7.0 to 1.7.1
Bumps [regex](https://github.com/rust-lang/regex) from 1.7.0 to 1.7.1.
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.7.0...1.7.1)

---
updated-dependencies:
- dependency-name: regex
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-10 03:02:16 +00:00
Sylvestre Ledru 1fbf4775cd Merge pull request #201 from uutils/dependabot/cargo/once_cell-1.17.0
build(deps): bump once_cell from 1.16.0 to 1.17.0
2022-12-30 08:49:18 +01:00
Sylvestre Ledru 624e7b6c3a Merge pull request #202 from uutils/dependabot/cargo/predicates-2.1.5
build(deps): bump predicates from 2.1.4 to 2.1.5
2022-12-30 08:49:07 +01:00
dependabot[bot] 147a62d2d6 build(deps): bump predicates from 2.1.4 to 2.1.5
Bumps [predicates](https://github.com/assert-rs/predicates-rs) from 2.1.4 to 2.1.5.
- [Release notes](https://github.com/assert-rs/predicates-rs/releases)
- [Changelog](https://github.com/assert-rs/predicates-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/assert-rs/predicates-rs/compare/v2.1.4...v2.1.5)

---
updated-dependencies:
- dependency-name: predicates
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-30 03:01:56 +00:00
dependabot[bot] 2933d89c28 build(deps): bump once_cell from 1.16.0 to 1.17.0
Bumps [once_cell](https://github.com/matklad/once_cell) from 1.16.0 to 1.17.0.
- [Release notes](https://github.com/matklad/once_cell/releases)
- [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md)
- [Commits](https://github.com/matklad/once_cell/compare/v1.16.0...v1.17.0)

---
updated-dependencies:
- dependency-name: once_cell
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-30 03:01:51 +00:00
Sylvestre Ledru 327898dcd9 Merge pull request #200 from uutils/dependabot/cargo/serial_test-0.10.0
build(deps): bump serial_test from 0.9.0 to 0.10.0
2022-12-19 09:00:25 +01:00
dependabot[bot] a83ce989c5 build(deps): bump serial_test from 0.9.0 to 0.10.0
Bumps [serial_test](https://github.com/palfrey/serial_test) from 0.9.0 to 0.10.0.
- [Release notes](https://github.com/palfrey/serial_test/releases)
- [Commits](https://github.com/palfrey/serial_test/compare/v0.9.0...v0.10.0)

---
updated-dependencies:
- dependency-name: serial_test
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-19 03:04:46 +00:00
Sylvestre Ledru b028814190 Merge pull request #197 from uutils/dependabot/cargo/predicates-2.1.4
build(deps): bump predicates from 2.1.3 to 2.1.4
2022-12-08 08:45:18 +01:00
Sylvestre Ledru 6e0b4da8ce Merge pull request #198 from uutils/dependabot/cargo/assert_cmd-2.0.7
build(deps): bump assert_cmd from 2.0.6 to 2.0.7
2022-12-08 08:45:05 +01:00
Sylvestre Ledru 233ae30477 Merge pull request #199 from uutils/dependabot/cargo/filetime-0.2.19
build(deps): bump filetime from 0.2.18 to 0.2.19
2022-12-08 08:44:54 +01:00
dependabot[bot] cb1ea61de5 build(deps): bump filetime from 0.2.18 to 0.2.19
Bumps [filetime](https://github.com/alexcrichton/filetime) from 0.2.18 to 0.2.19.
- [Release notes](https://github.com/alexcrichton/filetime/releases)
- [Commits](https://github.com/alexcrichton/filetime/compare/0.2.18...0.2.19)

---
updated-dependencies:
- dependency-name: filetime
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-08 03:03:07 +00:00
dependabot[bot] 28628f0e86 build(deps): bump assert_cmd from 2.0.6 to 2.0.7
Bumps [assert_cmd](https://github.com/assert-rs/assert_cmd) from 2.0.6 to 2.0.7.
- [Release notes](https://github.com/assert-rs/assert_cmd/releases)
- [Changelog](https://github.com/assert-rs/assert_cmd/blob/master/CHANGELOG.md)
- [Commits](https://github.com/assert-rs/assert_cmd/compare/v2.0.6...v2.0.7)

---
updated-dependencies:
- dependency-name: assert_cmd
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-02 03:03:41 +00:00
dependabot[bot] e6c3e5e7cf build(deps): bump predicates from 2.1.3 to 2.1.4
Bumps [predicates](https://github.com/assert-rs/predicates-rs) from 2.1.3 to 2.1.4.
- [Release notes](https://github.com/assert-rs/predicates-rs/releases)
- [Changelog](https://github.com/assert-rs/predicates-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/assert-rs/predicates-rs/compare/v2.1.3...v2.1.4)

---
updated-dependencies:
- dependency-name: predicates
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-02 03:03:37 +00:00
Sylvestre Ledru 992bad1f40 Merge pull request #196 from uutils/dependabot/cargo/nix-0.26.1
build(deps): bump nix from 0.25.0 to 0.26.1
2022-11-30 10:50:39 +01:00
dependabot[bot] 7869e09f4a build(deps): bump nix from 0.25.0 to 0.26.1
Bumps [nix](https://github.com/nix-rust/nix) from 0.25.0 to 0.26.1.
- [Release notes](https://github.com/nix-rust/nix/releases)
- [Changelog](https://github.com/nix-rust/nix/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nix-rust/nix/compare/v0.25.0...v0.26.1)

---
updated-dependencies:
- dependency-name: nix
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-30 03:03:38 +00:00
Sylvestre Ledru 620ae272ad Merge pull request #195 from uutils/dependabot/cargo/chrono-0.4.23
build(deps): bump chrono from 0.4.22 to 0.4.23
2022-11-14 08:44:28 +01:00
Sylvestre Ledru b06e8d36cf Merge pull request #194 from uutils/dependabot/cargo/predicates-2.1.3
build(deps): bump predicates from 2.1.2 to 2.1.3
2022-11-14 08:44:02 +01:00
dependabot[bot] b74e6b403f build(deps): bump chrono from 0.4.22 to 0.4.23
Bumps [chrono](https://github.com/chronotope/chrono) from 0.4.22 to 0.4.23.
- [Release notes](https://github.com/chronotope/chrono/releases)
- [Changelog](https://github.com/chronotope/chrono/blob/main/CHANGELOG.md)
- [Commits](https://github.com/chronotope/chrono/compare/v0.4.22...v0.4.23)

---
updated-dependencies:
- dependency-name: chrono
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-14 03:07:01 +00:00
dependabot[bot] 85014b0218 build(deps): bump predicates from 2.1.2 to 2.1.3
Bumps [predicates](https://github.com/assert-rs/predicates-rs) from 2.1.2 to 2.1.3.
- [Release notes](https://github.com/assert-rs/predicates-rs/releases)
- [Changelog](https://github.com/assert-rs/predicates-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/assert-rs/predicates-rs/compare/v2.1.2...v2.1.3)

---
updated-dependencies:
- dependency-name: predicates
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-14 03:06:49 +00:00
Sylvestre Ledru 232a301525 Merge pull request #192 from uutils/dependabot/cargo/regex-1.7.0
build(deps): bump regex from 1.6.0 to 1.7.0
2022-11-08 08:45:42 +01:00
Sylvestre Ledru fa552493ba Merge pull request #193 from uutils/dependabot/cargo/assert_cmd-2.0.6
build(deps): bump assert_cmd from 2.0.5 to 2.0.6
2022-11-08 08:44:31 +01:00
Sylvestre Ledru f0b8792cfd Merge pull request #191 from uutils/dependabot/cargo/predicates-2.1.2
build(deps): bump predicates from 2.1.1 to 2.1.2
2022-11-08 08:44:19 +01:00
dependabot[bot] c561643aa8 build(deps): bump assert_cmd from 2.0.5 to 2.0.6
Bumps [assert_cmd](https://github.com/assert-rs/assert_cmd) from 2.0.5 to 2.0.6.
- [Release notes](https://github.com/assert-rs/assert_cmd/releases)
- [Changelog](https://github.com/assert-rs/assert_cmd/blob/master/CHANGELOG.md)
- [Commits](https://github.com/assert-rs/assert_cmd/compare/v2.0.5...v2.0.6)

---
updated-dependencies:
- dependency-name: assert_cmd
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-08 03:06:26 +00:00
dependabot[bot] 7e1fb57ede build(deps): bump regex from 1.6.0 to 1.7.0
Bumps [regex](https://github.com/rust-lang/regex) from 1.6.0 to 1.7.0.
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.6.0...1.7.0)

---
updated-dependencies:
- dependency-name: regex
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-08 03:06:21 +00:00
dependabot[bot] be420a911b build(deps): bump predicates from 2.1.1 to 2.1.2
Bumps [predicates](https://github.com/assert-rs/predicates-rs) from 2.1.1 to 2.1.2.
- [Release notes](https://github.com/assert-rs/predicates-rs/releases)
- [Changelog](https://github.com/assert-rs/predicates-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/assert-rs/predicates-rs/compare/v2.1.1...v2.1.2)

---
updated-dependencies:
- dependency-name: predicates
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-08 03:06:15 +00:00
Sylvestre Ledru 47274c6784 Merge pull request #190 from uutils/dependabot/cargo/once_cell-1.16.0
build(deps): bump once_cell from 1.15.0 to 1.16.0
2022-10-31 07:53:52 +01:00
dependabot[bot] 46f280e838 build(deps): bump once_cell from 1.15.0 to 1.16.0
Bumps [once_cell](https://github.com/matklad/once_cell) from 1.15.0 to 1.16.0.
- [Release notes](https://github.com/matklad/once_cell/releases)
- [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md)
- [Commits](https://github.com/matklad/once_cell/compare/v1.15.0...v1.16.0)

---
updated-dependencies:
- dependency-name: once_cell
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-31 03:10:23 +00:00
Sylvestre Ledru 931b6e6d54 Merge pull request #189 from tavianator/bfs-2.6.2
ci: Update bfs to 2.6.2
2022-10-23 18:05:07 +02:00
Sylvestre Ledru bfc246b564 Merge pull request #186 from uutils/dependabot/cargo/filetime-0.2.18
build(deps): bump filetime from 0.2.17 to 0.2.18
2022-10-23 17:33:36 +02:00
Tavian Barnes 366c8b019f ci: Update bfs to 2.6.2 2022-10-21 12:04:44 -04:00
Sylvestre Ledru 7581c68813 Merge branch 'main' into dependabot/cargo/filetime-0.2.18 2022-10-21 09:15:45 +02:00
Sylvestre Ledru 0b02baf61b Merge pull request #188 from uutils/sylvestre-patch-1
Fix a clippy warning
2022-10-21 09:15:17 +02:00
Sylvestre Ledru 2a13f16446 Merge pull request #187 from uutils/dependabot/cargo/assert_cmd-2.0.5
build(deps): bump assert_cmd from 2.0.4 to 2.0.5
2022-10-21 09:14:57 +02:00
Sylvestre Ledru b95879684a Fix a clippy warning
`this expression borrows a value the compiler would automatically borrow`
2022-10-21 08:58:10 +02:00
dependabot[bot] f61a57ce6f build(deps): bump assert_cmd from 2.0.4 to 2.0.5
Bumps [assert_cmd](https://github.com/assert-rs/assert_cmd) from 2.0.4 to 2.0.5.
- [Release notes](https://github.com/assert-rs/assert_cmd/releases)
- [Changelog](https://github.com/assert-rs/assert_cmd/blob/master/CHANGELOG.md)
- [Commits](https://github.com/assert-rs/assert_cmd/compare/v2.0.4...v2.0.5)

---
updated-dependencies:
- dependency-name: assert_cmd
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-21 03:17:10 +00:00
dependabot[bot] 5d7966f654 build(deps): bump filetime from 0.2.17 to 0.2.18
Bumps [filetime](https://github.com/alexcrichton/filetime) from 0.2.17 to 0.2.18.
- [Release notes](https://github.com/alexcrichton/filetime/releases)
- [Commits](https://github.com/alexcrichton/filetime/compare/0.2.17...0.2.18)

---
updated-dependencies:
- dependency-name: filetime
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-21 03:17:05 +00:00
Sylvestre Ledru e785397880 Merge pull request #185 from uutils/dependabot/cargo/once_cell-1.15.0
build(deps): bump once_cell from 1.13.1 to 1.15.0
2022-09-21 09:28:08 +02:00
dependabot[bot] 3d10d81356 build(deps): bump once_cell from 1.13.1 to 1.15.0
Bumps [once_cell](https://github.com/matklad/once_cell) from 1.13.1 to 1.15.0.
- [Release notes](https://github.com/matklad/once_cell/releases)
- [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md)
- [Commits](https://github.com/matklad/once_cell/compare/v1.13.1...v1.15.0)

---
updated-dependencies:
- dependency-name: once_cell
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-21 03:15:45 +00:00
Sylvestre Ledru fa8e118a30 Merge pull request #183 from uutils/dependabot/cargo/iana-time-zone-0.1.47
build(deps): bump iana-time-zone from 0.1.44 to 0.1.47
2022-08-30 23:34:19 +02:00
dependabot[bot] 25c1b5084d build(deps): bump iana-time-zone from 0.1.44 to 0.1.47
Bumps [iana-time-zone](https://github.com/strawlab/iana-time-zone) from 0.1.44 to 0.1.47.
- [Release notes](https://github.com/strawlab/iana-time-zone/releases)
- [Changelog](https://github.com/strawlab/iana-time-zone/blob/main/CHANGELOG.md)
- [Commits](https://github.com/strawlab/iana-time-zone/compare/0.1.44...v0.1.47)

---
updated-dependencies:
- dependency-name: iana-time-zone
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-30 19:57:29 +00:00
Sylvestre Ledru 4563289689 Merge pull request #181 from uutils/dependabot/cargo/chrono-0.4.22
build(deps): bump chrono from 0.4.20 to 0.4.22
2022-08-17 08:59:18 +02:00
Sylvestre Ledru c7f5ed7760 Merge pull request #182 from uutils/dependabot/cargo/once_cell-1.13.1
build(deps): bump once_cell from 1.13.0 to 1.13.1
2022-08-17 08:58:53 +02:00
dependabot[bot] cb9771e694 build(deps): bump once_cell from 1.13.0 to 1.13.1
Bumps [once_cell](https://github.com/matklad/once_cell) from 1.13.0 to 1.13.1.
- [Release notes](https://github.com/matklad/once_cell/releases)
- [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md)
- [Commits](https://github.com/matklad/once_cell/compare/v1.13.0...v1.13.1)

---
updated-dependencies:
- dependency-name: once_cell
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-17 03:10:10 +00:00
dependabot[bot] e3f9fc4e90 build(deps): bump chrono from 0.4.20 to 0.4.22
Bumps [chrono](https://github.com/chronotope/chrono) from 0.4.20 to 0.4.22.
- [Release notes](https://github.com/chronotope/chrono/releases)
- [Changelog](https://github.com/chronotope/chrono/blob/main/CHANGELOG.md)
- [Commits](https://github.com/chronotope/chrono/compare/v0.4.20...v0.4.22)

---
updated-dependencies:
- dependency-name: chrono
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-16 03:15:26 +00:00
Sylvestre Ledru c21a0110cd Merge pull request #175 from uutils/dependabot/cargo/chrono-0.4.20
build(deps): bump chrono from 0.4.19 to 0.4.20
2022-08-15 09:14:15 +02:00
Sylvestre Ledru 497d655661 Merge pull request #180 from uutils/dependabot/cargo/nix-0.25.0
build(deps): bump nix from 0.24.2 to 0.25.0
2022-08-15 09:13:58 +02:00
dependabot[bot] f9d0fc2e36 build(deps): bump nix from 0.24.2 to 0.25.0
Bumps [nix](https://github.com/nix-rust/nix) from 0.24.2 to 0.25.0.
- [Release notes](https://github.com/nix-rust/nix/releases)
- [Changelog](https://github.com/nix-rust/nix/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nix-rust/nix/compare/v0.24.2...v0.25.0)

---
updated-dependencies:
- dependency-name: nix
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-15 03:10:04 +00:00
dependabot[bot] 5c5d4d9543 build(deps): bump chrono from 0.4.19 to 0.4.20
Bumps [chrono](https://github.com/chronotope/chrono) from 0.4.19 to 0.4.20.
- [Release notes](https://github.com/chronotope/chrono/releases)
- [Changelog](https://github.com/chronotope/chrono/blob/main/CHANGELOG.md)
- [Commits](https://github.com/chronotope/chrono/compare/v0.4.19...v0.4.20)

---
updated-dependencies:
- dependency-name: chrono
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-12 17:42:00 +02:00
Sylvestre Ledru 32318b77aa Merge pull request #178 from uutils/dependabot/cargo/serial_test-0.9.0
build(deps): bump serial_test from 0.8.0 to 0.9.0
2022-08-12 17:41:49 +02:00
Sylvestre Ledru 0d20a3d5cd Merge pull request #179 from refi64/wip/refi64/mkfifo-errors
find: Don't swallow mkfifo errors in the tests
2022-08-12 17:41:27 +02:00
Ryan Gonzalez 07916e1c23 find: Don't swallow mkfifo errors in the tests
Use nix's version of mkfifo instead, which lets us easily access the
errors and then fail with more information than the FIFO mysteriously
not appearing.

Ref. #177.

Signed-off-by: Ryan Gonzalez <ryan.gonzalez@collabora.com>
2022-08-12 10:26:15 -05:00
dependabot[bot] 43d725275b build(deps): bump serial_test from 0.8.0 to 0.9.0
Bumps [serial_test](https://github.com/palfrey/serial_test) from 0.8.0 to 0.9.0.
- [Release notes](https://github.com/palfrey/serial_test/releases)
- [Commits](https://github.com/palfrey/serial_test/compare/v0.8.0...v0.9.0)

---
updated-dependencies:
- dependency-name: serial_test
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-11 03:08:25 +00:00
Sylvestre Ledru 96de758f19 Merge pull request #176 from uutils/dependabot/cargo/onig-6.4.0
build(deps): bump onig from 6.3.2 to 6.4.0
2022-08-10 14:34:28 +02:00
dependabot[bot] 60f554c699 build(deps): bump onig from 6.3.2 to 6.4.0
Bumps [onig](https://github.com/iwillspeak/rust-onig) from 6.3.2 to 6.4.0.
- [Release notes](https://github.com/iwillspeak/rust-onig/releases)
- [Changelog](https://github.com/rust-onig/rust-onig/blob/main/CHANGELOG.md)
- [Commits](https://github.com/iwillspeak/rust-onig/compare/v6.3.2...v6.4.0)

---
updated-dependencies:
- dependency-name: onig
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-10 03:10:13 +00:00
Sylvestre Ledru a66f38bf1c Merge pull request #174 from uutils/dependabot/cargo/regex-1.6.0
build(deps): bump regex from 1.5.6 to 1.6.0
2022-07-06 09:10:55 +02:00
dependabot[bot] 8b05a3f5e4 build(deps): bump regex from 1.5.6 to 1.6.0
Bumps [regex](https://github.com/rust-lang/regex) from 1.5.6 to 1.6.0.
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.5.6...1.6.0)

---
updated-dependencies:
- dependency-name: regex
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-06 03:11:38 +00:00
Sylvestre Ledru 1c1f6fc6e6 Merge pull request #173 from uutils/dependabot/cargo/once_cell-1.13.0
build(deps): bump once_cell from 1.12.0 to 1.13.0
2022-07-05 07:48:43 +02:00
dependabot[bot] ddbe013d05 build(deps): bump once_cell from 1.12.0 to 1.13.0
Bumps [once_cell](https://github.com/matklad/once_cell) from 1.12.0 to 1.13.0.
- [Release notes](https://github.com/matklad/once_cell/releases)
- [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md)
- [Commits](https://github.com/matklad/once_cell/compare/v1.12.0...v1.13.0)

---
updated-dependencies:
- dependency-name: once_cell
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-05 03:21:12 +00:00
Sylvestre Ledru 2418d11397 Merge pull request #171 from uutils/dependabot/cargo/onig-6.3.2
build(deps): bump onig from 6.3.1 to 6.3.2
2022-07-04 08:34:02 +02:00
Sylvestre Ledru 67c3193446 Merge pull request #172 from uutils/dependabot/cargo/filetime-0.2.17
build(deps): bump filetime from 0.2.16 to 0.2.17
2022-07-04 08:33:45 +02:00
dependabot[bot] a41537a803 build(deps): bump filetime from 0.2.16 to 0.2.17
Bumps [filetime](https://github.com/alexcrichton/filetime) from 0.2.16 to 0.2.17.
- [Release notes](https://github.com/alexcrichton/filetime/releases)
- [Commits](https://github.com/alexcrichton/filetime/commits/0.2.17)

---
updated-dependencies:
- dependency-name: filetime
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-04 03:26:15 +00:00
dependabot[bot] 8f673c5899 build(deps): bump onig from 6.3.1 to 6.3.2
Bumps [onig](https://github.com/iwillspeak/rust-onig) from 6.3.1 to 6.3.2.
- [Release notes](https://github.com/iwillspeak/rust-onig/releases)
- [Commits](https://github.com/iwillspeak/rust-onig/commits/v6.3.2)

---
updated-dependencies:
- dependency-name: onig
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-04 03:26:13 +00:00
Sylvestre Ledru 4aab22af08 Link to the tracking page 2022-06-27 08:57:17 +02:00
Sylvestre Ledru da45c3b424 Merge pull request #167 from tavianator/stat
find/matchers: Implement -inum and -links
2022-06-27 08:53:01 +02:00
Sylvestre Ledru 1a4cb25c5c Merge pull request #170 from uutils/dependabot/cargo/serial_test-0.8.0
build(deps): bump serial_test from 0.7.0 to 0.8.0
2022-06-27 08:51:42 +02:00
dependabot[bot] 2a8636162f build(deps): bump serial_test from 0.7.0 to 0.8.0
Bumps [serial_test](https://github.com/palfrey/serial_test) from 0.7.0 to 0.8.0.
- [Release notes](https://github.com/palfrey/serial_test/releases)
- [Commits](https://github.com/palfrey/serial_test/compare/v0.7.0...v0.8.0)

---
updated-dependencies:
- dependency-name: serial_test
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-27 03:12:03 +00:00
Sylvestre Ledru 6bad054a5e Merge branch 'main' into stat 2022-06-06 09:43:46 +02:00
Sylvestre Ledru 4a47054ffc Merge pull request #168 from tavianator/access
find/matchers: Implement the -{read,writ,execut}able access checks
2022-06-06 09:43:06 +02:00
Sylvestre Ledru a6b1827ee0 Merge pull request #169 from uutils/dependabot/cargo/serial_test-0.7.0
build(deps): bump serial_test from 0.6.0 to 0.7.0
2022-06-06 09:42:31 +02:00
dependabot[bot] f05c2f1b61 build(deps): bump serial_test from 0.6.0 to 0.7.0
Bumps [serial_test](https://github.com/palfrey/serial_test) from 0.6.0 to 0.7.0.
- [Release notes](https://github.com/palfrey/serial_test/releases)
- [Commits](https://github.com/palfrey/serial_test/compare/v0.6.0...v0.7.0)

---
updated-dependencies:
- dependency-name: serial_test
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-06 03:17:56 +00:00
Tavian Barnes f967b29735 find/matchers: Implement the -{read,writ,execut}able access checks 2022-06-01 11:22:12 -04:00
Sylvestre Ledru dbde7abdc2 Merge branch 'main' into stat 2022-06-01 08:42:44 +01:00
Sylvestre Ledru a9241678e5 Merge pull request #166 from tavianator/right-sed-ed
find/matchers: Add the `ed` and `sed` regex types
2022-06-01 08:40:06 +01:00
Sylvestre Ledru 37547b00be Merge pull request #165 from tavianator/mount
find/matchers: Implement -mount as an alias for -xdev
2022-06-01 08:39:26 +01:00
Tavian Barnes 7c3268d9ef tests: Add integration tests for find -inum and -links 2022-05-31 17:09:43 -04:00
Tavian Barnes 972ac0bbff tests: Add integration tests for find -regextype ed/sed 2022-05-31 17:02:59 -04:00
Tavian Barnes 1bfbe7623e tests: Add a simple integration test for find -mount/-xdev 2022-05-31 17:01:35 -04:00
Tavian Barnes 08c22e6e33 find/matchers: Implement -inum and -links 2022-05-30 12:12:35 -04:00
Tavian Barnes 7855d08379 find/matchers: Add the ed and sed regex types 2022-05-30 11:53:39 -04:00
Tavian Barnes 80bfec17eb find/matchers: Implement -mount as an alias for -xdev 2022-05-30 11:52:40 -04:00
Sylvestre Ledru 75de125d45 Merge pull request #163 from tavianator/bfs-2.6
ci: Update bfs testsuite to version 2.6
2022-05-30 09:08:04 +01:00
Tavian Barnes e04cd34384 ci: Update bfs testsuite to version 2.6
The latest bfs properly groups the --sudo tests, so we can test things
that require root like -xdev.
2022-05-25 13:23:55 -04:00
Sylvestre Ledru 36e3229537 Merge pull request #162 from uutils/dependabot/cargo/once_cell-1.12.0
build(deps): bump once_cell from 1.11.0 to 1.12.0
2022-05-24 08:13:45 +02:00
dependabot[bot] eff4c5d38a build(deps): bump once_cell from 1.11.0 to 1.12.0
Bumps [once_cell](https://github.com/matklad/once_cell) from 1.11.0 to 1.12.0.
- [Release notes](https://github.com/matklad/once_cell/releases)
- [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md)
- [Commits](https://github.com/matklad/once_cell/compare/v1.11.0...v1.12.0)

---
updated-dependencies:
- dependency-name: once_cell
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-24 03:11:37 +00:00
Sylvestre Ledru 2defcbeacc Merge pull request #161 from uutils/dependabot/cargo/regex-1.5.6
Bump regex from 1.5.5 to 1.5.6
2022-05-23 08:36:06 +02:00
dependabot[bot] 301b495097 Bump regex from 1.5.5 to 1.5.6
Bumps [regex](https://github.com/rust-lang/regex) from 1.5.5 to 1.5.6.
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.5.5...1.5.6)

---
updated-dependencies:
- dependency-name: regex
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-23 03:21:30 +00:00
Sylvestre Ledru f3ecd5b424 Merge pull request #160 from uutils/dependabot/github_actions/codecov/codecov-action-3
Bump codecov/codecov-action from 1 to 3
2022-05-20 11:51:40 +02:00
Sylvestre Ledru a44b981812 Merge pull request #159 from uutils/dependabot/github_actions/actions/checkout-3
Bump actions/checkout from 2 to 3
2022-05-20 10:03:56 +02:00
Sylvestre Ledru 3466eabfc7 Merge pull request #158 from uutils/dependabot/github_actions/actions/upload-artifact-3
Bump actions/upload-artifact from 2 to 3
2022-05-20 09:57:25 +02:00
dependabot[bot] 283082a36d Bump codecov/codecov-action from 1 to 3
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 1 to 3.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/master/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v1...v3)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-20 07:29:37 +00:00
dependabot[bot] 5741479e2f Bump actions/checkout from 2 to 3
Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-20 07:29:34 +00:00
dependabot[bot] 9e434052e5 Bump actions/upload-artifact from 2 to 3
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 2 to 3.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-20 07:29:30 +00:00
Sylvestre Ledru 92a24ecad0 Enable dependabot for github actions 2022-05-20 09:29:07 +02:00
Sylvestre Ledru 0ec8d472d1 Merge pull request #157 from uutils/dependabot/cargo/once_cell-1.11.0
Bump once_cell from 1.10.0 to 1.11.0
2022-05-20 09:25:23 +02:00
dependabot[bot] 6050706bfd Bump once_cell from 1.10.0 to 1.11.0
Bumps [once_cell](https://github.com/matklad/once_cell) from 1.10.0 to 1.11.0.
- [Release notes](https://github.com/matklad/once_cell/releases)
- [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md)
- [Commits](https://github.com/matklad/once_cell/compare/v1.10.0...v1.11.0)

---
updated-dependencies:
- dependency-name: once_cell
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-20 07:10:21 +00:00
Sylvestre Ledru 946544eec9 Merge pull request #156 from uutils/dependabot/cargo/filetime-0.2.16
Bump filetime from 0.2.15 to 0.2.16
2022-04-18 14:41:03 +02:00
dependabot[bot] 5e32ed0381 Bump filetime from 0.2.15 to 0.2.16
Bumps [filetime](https://github.com/alexcrichton/filetime) from 0.2.15 to 0.2.16.
- [Release notes](https://github.com/alexcrichton/filetime/releases)
- [Commits](https://github.com/alexcrichton/filetime/commits)

---
updated-dependencies:
- dependency-name: filetime
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-18 07:10:52 +00:00
Sylvestre Ledru b111e50fa9 Merge pull request #153 from uutils/dependabot/cargo/regex-1.5.5
Bump regex from 1.5.4 to 1.5.5
2022-03-25 09:02:28 +01:00
dependabot[bot] d58fb523b1 Bump regex from 1.5.4 to 1.5.5
Bumps [regex](https://github.com/rust-lang/regex) from 1.5.4 to 1.5.5.
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.5.4...1.5.5)

---
updated-dependencies:
- dependency-name: regex
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-25 07:20:20 +00:00
Sylvestre Ledru fcb89d2156 Merge pull request #154 from tavianator/perm-uucore
find: Use the uucore mode parsing implementation for -perm
2022-03-25 08:19:09 +01:00
Tavian Barnes 0b23d9b202 find: Add integration tests for -perm 2022-03-23 13:34:09 -04:00
Tavian Barnes 13bc54f7ae find: Use the uucore mode parsing implementation for -perm
Fixes #26.
2022-03-16 16:37:31 -04:00
Sylvestre Ledru 4cd4e4fb79 Merge pull request #151 from tavianator/globs
POSIX compliant globs
2022-03-05 21:01:56 +01:00
Sylvestre Ledru 27bfbdc906 Merge pull request #152 from uutils/dependabot/cargo/once_cell-1.10.0
Bump once_cell from 1.9.0 to 1.10.0
2022-03-04 09:28:18 +01:00
dependabot[bot] 1faeef0ab2 Bump once_cell from 1.9.0 to 1.10.0
Bumps [once_cell](https://github.com/matklad/once_cell) from 1.9.0 to 1.10.0.
- [Release notes](https://github.com/matklad/once_cell/releases)
- [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md)
- [Commits](https://github.com/matklad/once_cell/compare/v1.9.0...v1.10.0)

---
updated-dependencies:
- dependency-name: once_cell
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-04 07:11:08 +00:00
Tavian Barnes ce375a71b0 ci: Fix BFS tests comparison with zero skipped tests
Now that -path/-ipath is implemented, no tests are skipped any more.
Fix CI by using zero instead of the empty string, which breaks the
compare_bfs_result.py script.
2022-02-23 21:33:32 -05:00
Tavian Barnes 016995fa4a find/matchers: Implement -[i]path, -[i]wholename 2022-02-23 21:33:32 -05:00
Tavian Barnes 36cc88e159 find/matchers: Implement POSIX-compliant globs
The glob crate exposes .gitignore style globs with recursive (**)
matching and other features.  find should implement globs exactly as
specified by POSIX.  Do this by translating them to POSIX Basic Regular
Expressions.

Fixes #140.
2022-02-23 21:08:04 -05:00
Tavian Barnes 22cbd8e467 find/matchers: Use the same type for case-[in]sensitive matchers 2022-02-23 20:34:03 -05:00
Tavian Barnes a9ad63838f find/matchers: Split lname matchers into separate types 2022-02-23 20:20:25 -05:00
Sylvestre Ledru e18c369b33 Merge pull request #150 from tavianator/bfs-2.4
ci: Update BFS testsuite to version 2.4
2022-02-22 21:47:15 +01:00
Tavian Barnes cead712118 ci: Fix GNU testsuite comparison
The uploaded log artifact maintains the directory structure, so just
compare it directly to the GNU find directory.
2022-02-22 14:30:56 -05:00
Tavian Barnes 193aaf2aa0 ci: Don't run the GNU/bfs testsuites twice 2022-02-22 13:42:39 -05:00
Tavian Barnes 7be2715f07 ci: Update BFS testsuite to version 2.4 2022-02-22 13:41:43 -05:00
Sylvestre Ledru a3501a267a Merge pull request #149 from uutils/dependabot/cargo/serial_test-0.6.0
Bump serial_test from 0.5.1 to 0.6.0
2022-02-21 08:29:44 +01:00
dependabot[bot] a3928291f8 Bump serial_test from 0.5.1 to 0.6.0
Bumps [serial_test](https://github.com/palfrey/serial_test) from 0.5.1 to 0.6.0.
- [Release notes](https://github.com/palfrey/serial_test/releases)
- [Commits](https://github.com/palfrey/serial_test/compare/v0.5.1...v0.6.0)

---
updated-dependencies:
- dependency-name: serial_test
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-21 07:16:47 +00:00
Sylvestre Ledru 493a1e9998 Merge pull request #147 from tavianator/quit
Implement -quit
2022-02-11 09:37:53 +01:00
Sylvestre Ledru d26cdf3010 Merge pull request #148 from tavianator/easy-flags
Implement -P and --
2022-02-10 22:37:11 +01:00
Sylvestre Ledru eddfddf217 Merge pull request #145 from tavianator/dash-and
Support -and as a synonym for -a
2022-02-10 22:35:52 +01:00
Sylvestre Ledru f2c808c3cf Merge pull request #146 from tavianator/printf-times
printf: Fix some time formatting to match GNU find
2022-02-10 22:34:52 +01:00
Tavian Barnes d16305d5fd Implement -quit 2022-02-10 15:29:50 -05:00
Tavian Barnes 1f3b2094a5 Implement -P and -- 2022-02-10 15:24:54 -05:00
Tavian Barnes b16a05f260 printf: Fix some time formatting to match GNU find
GNU find uses 10 digits for nanoseconds for some reason, and %S includes
them.
2022-02-10 13:50:40 -05:00
Tavian Barnes f04d297372 Support -and as a synonym for -a 2022-02-10 13:23:51 -05:00
Sylvestre Ledru 7ffd5f8424 Merge pull request #141 from tavianator/into-box
matchers: Replace new_box() with an into_box() trait method
2022-02-08 20:31:53 +01:00
Sylvestre Ledru 48d6f63fc8 Merge pull request #144 from tavianator/dejagnu
ci: Also run the dejagnu tests from GNU findutils
2022-02-08 20:31:19 +01:00
Tavian Barnes 979a442443 matchers: Replace new_box() with an into_box() trait method
This lets us get rid of the boilerplate new_box() inherent method on
most Matcher impls.  It also removes the need for explicit boxing before
passing Matchers to a few functions like new_and_matcher().
2022-02-08 13:20:26 -05:00
Tavian Barnes 43027d0808 ci: Also run the dejagnu tests from GNU findutils 2022-02-08 12:05:00 -05:00
Tavian Barnes 5c45b30427 Parse and ignore GNU find optimization levels (-On)
This makes us compatible with the GNU find testsuite.
2022-02-08 12:05:00 -05:00
Sylvestre Ledru a7af22724b Merge pull request #143 from sylvestre/clippy
Various Clippy fixes
2022-02-05 20:52:55 +01:00
Sylvestre Ledru 4eb943fea2 rustfmt recent changes 2022-02-05 15:16:36 +01:00
Sylvestre Ledru f399291533 fix clippy warning: Fix the needless_pass_by_value 2022-02-05 15:09:29 +01:00
Sylvestre Ledru 59be8d5ce7 refresh cargo.lock with recent updates 2022-02-05 15:06:18 +01:00
Sylvestre Ledru 384aa23e74 fix clippy warning: use Self when possible 2022-02-05 15:06:18 +01:00
Sylvestre Ledru 58070d6a00 Merge pull request #139 from refi64/prune-dirs-only
Avoid skipping the entire directory if a file hits -prune
2022-01-31 20:28:22 +01:00
Ryan Gonzalez 5f054351d4 Avoid skipping the entire directory if a file hits -prune
This matches up with the behavior of GNU findutils, as documented in its
man page:

> **if the file is a directory**, do not descend into it

Signed-off-by: Ryan Gonzalez <ryan.gonzalez@collabora.com>
2022-01-31 13:00:51 -06:00
Sylvestre Ledru 78eba7efbc Merge pull request #136 from refi64/xdev
Add support for -xdev
2022-01-27 09:15:25 +01:00
Sylvestre Ledru d6433f9f54 Merge pull request #137 from refi64/empty
Add support for -empty
2022-01-27 09:12:43 +01:00
Sylvestre Ledru 1bf7ff7e13 Merge pull request #138 from refi64/lname
Add support for -lname / -ilname
2022-01-27 09:07:19 +01:00
Ryan Gonzalez 162d5f3822 Add support for -lname / -ilname
Signed-off-by: Ryan Gonzalez <ryan.gonzalez@collabora.com>
2022-01-26 20:28:21 -06:00
Ryan Gonzalez efa2a4b553 Add support for -empty
Signed-off-by: Ryan Gonzalez <ryan.gonzalez@collabora.com>
2022-01-26 19:17:46 -06:00
Ryan Gonzalez 0a8b72fdbc Add support for -xdev
Unfortunately, the nature of this makes it incredibly hard to test for
in CI; not even BFS's massive test suite covers it. That being said,
it's a simple enough addition that the risk it incurs hopefully
shouldn't be too large.

Signed-off-by: Ryan Gonzalez <ryan.gonzalez@collabora.com>
2022-01-26 17:42:15 -06:00
Sylvestre Ledru 1517cc0e84 Update 0.3.0 2022-01-26 23:41:02 +01:00
43 changed files with 2514 additions and 1108 deletions
+10 -6
View File
@@ -1,8 +1,12 @@
version: 2
updates:
- package-ecosystem: cargo
directory: "/"
schedule:
interval: daily
time: "07:00"
open-pull-requests-limit: 10
- package-ecosystem: "cargo"
directory: "/"
schedule:
interval: "daily"
open-pull-requests-limit: 5
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 5
+50 -95
View File
@@ -10,12 +10,12 @@ jobs:
matrix:
os: [ubuntu-latest, macOS-latest, windows-latest]
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- uses: actions/checkout@v3
- name: Install `rust` toolchain
run: |
## Install `rust` toolchain
rustup toolchain install stable --no-self-update -c rustfmt --profile minimal
rustup default stable
# For bindgen: https://github.com/rust-lang/rust-bindgen/issues/1797
- uses: KyleMayes/install-llvm-action@v1
@@ -26,9 +26,9 @@ jobs:
- run: echo "LIBCLANG_PATH=$((gcm clang).source -replace "clang.exe")" >> $env:GITHUB_ENV
if: matrix.os == 'windows-latest'
- uses: actions-rs/cargo@v1
with:
command: check
- name: Check
run: |
cargo check
test:
name: cargo test
@@ -37,12 +37,12 @@ jobs:
matrix:
os: [ubuntu-latest, macOS-latest, windows-latest]
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- uses: actions/checkout@v3
- name: Install `rust` toolchain
run: |
## Install `rust` toolchain
rustup toolchain install stable --no-self-update -c rustfmt --profile minimal
rustup default stable
# For bindgen: https://github.com/rust-lang/rust-bindgen/issues/1797
- uses: KyleMayes/install-llvm-action@v1
@@ -53,41 +53,40 @@ jobs:
- run: echo "LIBCLANG_PATH=$((gcm clang).source -replace "clang.exe")" >> $env:GITHUB_ENV
if: matrix.os == 'windows-latest'
- uses: actions-rs/cargo@v1
with:
command: test
- name: Check
run: |
cargo check
fmt:
name: cargo fmt --all -- --check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- uses: actions/checkout@v3
- name: Install `rust` toolchain
run: |
## Install `rust` toolchain
rustup toolchain install stable --no-self-update -c rustfmt --profile minimal
rustup default stable
- run: rustup component add rustfmt
- uses: actions-rs/cargo@v1
with:
command: fmt
args: --all -- --check
- name: cargo fmt
run: |
cargo fmt --all -- --check
clippy:
name: cargo clippy -- -D warnings
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- uses: actions/checkout@v3
- name: Install `rust` toolchain
run: |
## Install `rust` toolchain
rustup toolchain install stable --no-self-update -c rustfmt --profile minimal
rustup default stable
- run: rustup component add clippy
- uses: actions-rs/cargo@v1
with:
command: clippy
args: -- -D warnings
- name: cargo clippy
run: |
cargo clippy -- -D warnings
grcov:
name: Code coverage
@@ -102,27 +101,20 @@ jobs:
- "--all-features"
steps:
- name: Checkout source code
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: ${{ matrix.toolchain }}
override: true
- name: Install `rust` toolchain
run: |
## Install `rust` toolchain
rustup toolchain install nightly --no-self-update -c rustfmt --profile minimal
rustup default nightly
- name: Install grcov
uses: actions-rs/install@v0.1
with:
crate: grcov
version: latest
use-tool-cache: true
- name: "`grcov` ~ install"
run: cargo install grcov
- name: Test
uses: actions-rs/cargo@v1
with:
command: test
args: --all --no-fail-fast ${{ matrix.cargo_flags }}
- name: cargo test
run: |
cargo test --all --no-fail-fast ${{ matrix.cargo_flags }}
env:
CARGO_INCREMENTAL: "0"
RUSTFLAGS: '-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort -Cdebug-assertions=off'
@@ -130,7 +122,6 @@ jobs:
- name: Generate coverage data
id: grcov
# uses: actions-rs/grcov@v0.1
run: |
grcov target/debug/ \
--branch \
@@ -147,51 +138,15 @@ jobs:
--service-name "GitHub Actions" \
--service-number ${{ github.run_id }}
- name: Upload coverage as artifact
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: lcov.info
# path: ${{ steps.grcov.outputs.report }}
path: lcov.info
- name: Upload coverage to codecov.io
uses: codecov/codecov-action@v1
uses: codecov/codecov-action@v3
with:
# file: ${{ steps.grcov.outputs.report }}
file: lcov.info
fail_ci_if_error: true
external:
name: External testsuites
runs-on: ${{ matrix.os }}
strategy:
matrix:
os:
- ubuntu-latest
toolchain:
- nightly
cargo_flags:
- "--all-features"
steps:
- name: Checkout source code
uses: actions/checkout@v2
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: ${{ matrix.toolchain }}
override: true
- name: Run the gnu testsuite
id: gnu
run: |
sudo apt install autopoint
git clone https://git.savannah.gnu.org/git/findutils.git ../findutils.gnu
bash util/build-gnu.sh || true
- name: Run the bfs testsuite
id: bfs
run: |
sudo apt install acl libacl1-dev attr libattr1-dev libcap2-bin libcap-dev
git clone https://github.com/tavianator/bfs.git ../bfs
bash util/build-bfs.sh || true
+26 -98
View File
@@ -1,6 +1,6 @@
on: [push, pull_request]
name: GNU findutils compatibility tests
name: External testsuites
jobs:
gnu-tests:
@@ -8,21 +8,21 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout findutils
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
path: findutils
- name: Checkout GNU findutils
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
repository: gnu-mirror-unofficial/findutils
path: findutils.gnu
ref: 5768a03ddfb5e18b1682e339d6cdd24ff721c510
submodules: true
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- name: Install `rust` toolchain
run: |
## Install `rust` toolchain
rustup toolchain install stable --no-self-update -c rustfmt --profile minimal
rustup default stable
- name: Install dependencies
shell: bash
run: |
@@ -38,39 +38,14 @@ jobs:
- name: Extract testing info
shell: bash
run: |
LOG_FILE=findutils.gnu/tests/test-suite.log
if test -f "$LOG_FILE"; then
TOTAL=$(sed -n "s/.*# TOTAL: \(.*\)/\1/p" "$LOG_FILE"|tr -d '\r'|head -n1)
PASS=$(sed -n "s/.*# PASS: \(.*\)/\1/p" "$LOG_FILE"|tr -d '\r'|head -n1)
SKIP=$(sed -n "s/.*# SKIP: \(.*\)/\1/p" "$LOG_FILE"|tr -d '\r'|head -n1)
FAIL=$(sed -n "s/.*# FAIL: \(.*\)/\1/p" "$LOG_FILE"|tr -d '\r'|head -n1)
XPASS=$(sed -n "s/.*# XPASS: \(.*\)/\1/p" "$LOG_FILE"|tr -d '\r'|head -n1)
ERROR=$(sed -n "s/.*# ERROR: \(.*\)/\1/p" "$LOG_FILE"|tr -d '\r'|head -n1)
if [[ "$TOTAL" -eq 0 || "$TOTAL" -eq 1 ]]; then
echo "Error in the execution, failing early"
exit 1
fi
output="GNU tests summary = TOTAL: $TOTAL / PASS: $PASS / FAIL: $FAIL / ERROR: $ERROR"
echo "${output}"
if [[ "$FAIL" -gt 0 || "$ERROR" -gt 0 ]]; then echo "::warning ::${output}" ; fi
jq -n \
--arg date "$(date --rfc-email)" \
--arg sha "$GITHUB_SHA" \
--arg total "$TOTAL" \
--arg pass "$PASS" \
--arg skip "$SKIP" \
--arg fail "$FAIL" \
--arg xpass "$XPASS" \
--arg error "$ERROR" \
'{($date): { sha: $sha, total: $total, pass: $pass, skip: $skip, fail: $fail, xpass: $xpass, error: $error, }}' > gnu-result.json
else
echo "::error ::Failed to get summary of test results"
fi
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
with:
name: gnu-test-report
path: findutils.gnu/tests/**/*.log
- uses: actions/upload-artifact@v2
path: |
findutils.gnu/find/testsuite/*.log
findutils.gnu/xargs/testsuite/*.log
findutils.gnu/tests/**/*.log
- uses: actions/upload-artifact@v3
with:
name: gnu-result
path: gnu-result.json
@@ -95,18 +70,7 @@ jobs:
- name: Compare failing tests against master
shell: bash
run: |
OLD_FAILING=$(sed -n "s/^FAIL: \([[:print:]]\+\).*/\1/p" dl/test-suite.log | sort)
NEW_FAILING=$(sed -n "s/^FAIL: \([[:print:]]\+\).*/\1/p" findutils.gnu/tests/test-suite.log | sort)
for LINE in $OLD_FAILING; do
if ! grep -Fxq $LINE<<<"$NEW_FAILING"; then
echo "::warning ::Congrats! The gnu test $LINE is now passing!"
fi
done
for LINE in $NEW_FAILING; do
if ! grep -Fxq $LINE<<<"$OLD_FAILING"; then
echo "::error ::gnu test failed: $LINE. $LINE is passing on 'main'. Maybe you have to rebase?"
fi
done
./findutils/util/diff-gnu.sh ./dl ./findutils.gnu
- name: Compare against main results
shell: bash
run: |
@@ -118,20 +82,20 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout findutils
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
path: findutils
- name: Checkout BFS
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
repository: tavianator/bfs
path: bfs
ref: '2.3.1'
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
ref: '2.6.2'
- name: Install `rust` toolchain
run: |
## Install `rust` toolchain
rustup toolchain install stable --no-self-update -c rustfmt --profile minimal
rustup default stable
- name: Install dependencies
shell: bash
run: |
@@ -144,36 +108,11 @@ jobs:
run: |
cd findutils
bash util/build-bfs.sh ||:
- name: Extract testing info
shell: bash
run: |
LOG_FILE=bfs/tests.log
if test -f "$LOG_FILE"; then
PASS=$(sed -n "s/^tests passed: \(.*\)/\1/p" "$LOG_FILE"|head -n1)
FAIL=$(sed -n "s/^tests failed: \(.*\)/\1/p" "$LOG_FILE"|head -n1)
TOTAL=$(($PASS + $FAIL))
if [[ "$TOTAL" -eq 0 || "$TOTAL" -eq 1 ]]; then
echo "Error in the execution, failing early"
exit 1
fi
output="BFS tests summary = TOTAL: $TOTAL / PASS: $PASS / FAIL: $FAIL"
echo "${output}"
if [[ "$FAIL" -gt 0 || "$ERROR" -gt 0 ]]; then echo "::warning ::${output}" ; fi
jq -n \
--arg date "$(date --rfc-email)" \
--arg sha "$GITHUB_SHA" \
--arg total "$TOTAL" \
--arg pass "$PASS" \
--arg fail "$FAIL" \
'{($date): { sha: $sha, total: $total, pass: $pass, fail: $fail, }}' > bfs-result.json
else
echo "::error ::Failed to get summary of test results"
fi
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
with:
name: bfs-test-report
path: bfs/tests.log
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
with:
name: bfs-result
path: bfs-result.json
@@ -198,18 +137,7 @@ jobs:
- name: Compare failing tests against main
shell: bash
run: |
OLD_FAILING=$(sed -n "s/^\([[:print:]]\+\) failed\!/\1/p" dl/tests.log | sort)
NEW_FAILING=$(sed -n "s/^\([[:print:]]\+\) failed\!/\1/p" bfs/tests.log | sort)
for LINE in $OLD_FAILING; do
if ! grep -Fxq $LINE<<<"$NEW_FAILING"; then
echo "::warning ::Congrats! The bfs test $LINE is now passing!"
fi
done
for LINE in $NEW_FAILING; do
if ! grep -Fxq $LINE<<<"$OLD_FAILING"; then
echo "::error ::bfs test failed: $LINE. $LINE is passing on 'main'. Maybe you have to rebase?"
fi
done
./findutils/util/diff-bfs.sh dl/tests.log bfs/tests.log
- name: Compare against main results
shell: bash
run: |
+17
View File
@@ -0,0 +1,17 @@
repos:
- repo: local
hooks:
- id: rust-linting
name: Rust linting
description: Run cargo fmt on files included in the commit.
entry: cargo +nightly fmt --
pass_filenames: true
types: [file, rust]
language: system
- id: rust-clippy
name: Rust clippy
description: Run cargo clippy on files included in the commit.
entry: cargo +nightly clippy --workspace --all-targets --all-features --
pass_filenames: false
types: [file, rust]
language: system
Generated
+461 -84
View File
File diff suppressed because it is too large Load Diff
+9 -8
View File
@@ -1,6 +1,6 @@
[package]
name = "findutils"
version = "0.3.0"
version = "0.4.0"
homepage = "https://github.com/uutils/findutils"
repository = "https://github.com/uutils/findutils"
edition = "2018"
@@ -12,18 +12,19 @@ authors = ["uutils developers"]
[dependencies]
chrono = "0.4"
clap = "2.34"
glob = "0.3"
faccess = "0.2.4"
walkdir = "2.3"
regex = "1.5"
once_cell = "1.9"
onig = "6.3"
uucore = { version = "0.0.12", features = ["entries", "fs", "fsext"] }
regex = "1.7"
once_cell = "1.17"
onig = "6.4"
uucore = { version = "0.0.12", features = ["entries", "fs", "fsext", "mode"] }
[dev-dependencies]
assert_cmd = "2"
filetime = "0.2"
predicates = "2"
serial_test = "0.5"
nix = "0.26"
predicates = "3"
serial_test = "1.0"
tempfile = "3"
[[bin]]
+2
View File
@@ -19,3 +19,5 @@ bash util/build-gnu.sh tests/misc/help-version.sh
![Evolution over time - GNU testsuite](https://github.com/uutils/findutils-tracking/blob/main/gnu-results.png?raw=true)
![Evolution over time - BFS testsuite](https://github.com/uutils/findutils-tracking/blob/main/bfs-results.png?raw=true)
For more details, see https://github.com/uutils/findutils-tracking/
+1 -4
View File
@@ -4,12 +4,9 @@
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.
extern crate findutils;
extern crate glob;
fn main() {
let args = std::env::args().collect::<Vec<String>>();
let strs: Vec<&str> = args.iter().map(|s| s.as_ref()).collect();
let strs: Vec<&str> = args.iter().map(std::convert::AsRef::as_ref).collect();
let deps = findutils::find::StandardDependencies::new();
std::process::exit(findutils::find::find_main(&strs, &deps));
}
+60
View File
@@ -0,0 +1,60 @@
// Copyright 2022 Tavian Barnes
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.
use faccess::PathExt;
use walkdir::DirEntry;
use super::{Matcher, MatcherIO};
/// Matcher for -{read,writ,execut}able.
pub enum AccessMatcher {
Readable,
Writable,
Executable,
}
impl Matcher for AccessMatcher {
fn matches(&self, file_info: &DirEntry, _: &mut MatcherIO) -> bool {
let path = file_info.path();
match self {
Self::Readable => path.readable(),
Self::Writable => path.writable(),
Self::Executable => path.executable(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::find::matchers::tests::get_dir_entry_for;
use crate::find::matchers::Matcher;
use crate::find::tests::FakeDependencies;
#[test]
fn access_matcher() {
let file_info = get_dir_entry_for("test_data/simple", "abbbc");
let deps = FakeDependencies::new();
assert!(
AccessMatcher::Readable.matches(&file_info, &mut deps.new_matcher_io()),
"file should be readable"
);
assert!(
AccessMatcher::Writable.matches(&file_info, &mut deps.new_matcher_io()),
"file should be writable"
);
#[cfg(unix)]
assert!(
!AccessMatcher::Executable.matches(&file_info, &mut deps.new_matcher_io()),
"file should not be executable"
);
}
}
+1 -5
View File
@@ -18,14 +18,10 @@ use super::{Matcher, MatcherIO};
pub struct DeleteMatcher;
impl DeleteMatcher {
pub fn new() -> DeleteMatcher {
pub fn new() -> Self {
DeleteMatcher
}
pub fn new_box() -> io::Result<Box<dyn Matcher>> {
Ok(Box::new(DeleteMatcher::new()))
}
fn delete(&self, file_path: &Path, file_type: FileType) -> io::Result<()> {
if file_type.is_dir() {
fs::remove_dir(file_path)
+100
View File
@@ -0,0 +1,100 @@
// Copyright 2021 Collabora, Ltd.
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.
use std::{
fs::read_dir,
io::{stderr, Write},
};
use super::Matcher;
pub struct EmptyMatcher;
impl EmptyMatcher {
pub fn new() -> EmptyMatcher {
EmptyMatcher
}
}
impl Matcher for EmptyMatcher {
fn matches(&self, file_info: &walkdir::DirEntry, _: &mut super::MatcherIO) -> bool {
if file_info.file_type().is_file() {
match file_info.metadata() {
Ok(meta) => meta.len() == 0,
Err(err) => {
writeln!(
&mut stderr(),
"Error getting size for {}: {}",
file_info.path().display(),
err
)
.unwrap();
false
}
}
} else if file_info.file_type().is_dir() {
match read_dir(file_info.path()) {
Ok(mut it) => it.next().is_none(),
Err(err) => {
writeln!(
&mut stderr(),
"Error getting contents of {}: {}",
file_info.path().display(),
err
)
.unwrap();
false
}
}
} else {
false
}
}
}
#[cfg(test)]
mod tests {
use tempfile::Builder;
use super::*;
use crate::find::matchers::tests::get_dir_entry_for;
use crate::find::matchers::Matcher;
use crate::find::tests::FakeDependencies;
#[test]
fn empty_files() {
let empty_file_info = get_dir_entry_for("test_data/simple", "abbbc");
let nonempty_file_info = get_dir_entry_for("test_data/size", "512bytes");
let matcher = EmptyMatcher::new();
let deps = FakeDependencies::new();
assert!(matcher.matches(&empty_file_info, &mut deps.new_matcher_io()));
assert!(!matcher.matches(&nonempty_file_info, &mut deps.new_matcher_io()));
}
#[test]
fn empty_directories() {
let temp_dir = Builder::new()
.prefix("empty_directories")
.tempdir()
.unwrap();
let temp_dir_path = temp_dir.path().to_string_lossy();
let subdir_name = "subdir";
std::fs::create_dir(temp_dir.path().join(subdir_name)).unwrap();
let matcher = EmptyMatcher::new();
let deps = FakeDependencies::new();
let file_info = get_dir_entry_for(&temp_dir_path, subdir_name);
assert!(matcher.matches(&file_info, &mut deps.new_matcher_io()));
std::fs::File::create(temp_dir.path().join(subdir_name).join("a")).unwrap();
let file_info = get_dir_entry_for(&temp_dir_path, subdir_name);
assert!(!matcher.matches(&file_info, &mut deps.new_matcher_io()));
}
}
+15 -22
View File
@@ -14,7 +14,7 @@ use walkdir::DirEntry;
use super::{Matcher, MatcherIO};
enum Arg {
Filename,
FileArg(Vec<OsString>),
LiteralArg(OsString),
}
@@ -29,33 +29,26 @@ impl SingleExecMatcher {
executable: &str,
args: &[&str],
exec_in_parent_dir: bool,
) -> Result<SingleExecMatcher, Box<dyn Error>> {
) -> Result<Self, Box<dyn Error>> {
let transformed_args = args
.iter()
.map(|&a| match a {
"{}" => Arg::Filename,
_ => Arg::LiteralArg(OsString::from(a)),
.map(|&a| {
let parts = a.split("{}").collect::<Vec<_>>();
if parts.len() == 1 {
// No {} present
Arg::LiteralArg(OsString::from(a))
} else {
Arg::FileArg(parts.iter().map(OsString::from).collect())
}
})
.collect();
Ok(SingleExecMatcher {
Ok(Self {
executable: executable.to_string(),
args: transformed_args,
exec_in_parent_dir,
})
}
pub fn new_box(
executable: &str,
args: &[&str],
exec_in_parent_dir: bool,
) -> Result<Box<dyn Matcher>, Box<dyn Error>> {
Ok(Box::new(SingleExecMatcher::new(
executable,
args,
exec_in_parent_dir,
)?))
}
}
impl Matcher for SingleExecMatcher {
@@ -72,10 +65,10 @@ impl Matcher for SingleExecMatcher {
};
for arg in &self.args {
command.arg(match *arg {
Arg::LiteralArg(ref a) => a.as_os_str(),
Arg::Filename => path_to_file.as_os_str(),
});
match *arg {
Arg::LiteralArg(ref a) => command.arg(a.as_os_str()),
Arg::FileArg(ref parts) => command.arg(&parts.join(path_to_file.as_os_str())),
};
}
if self.exec_in_parent_dir {
match file_info.path().parent() {
+238
View File
@@ -0,0 +1,238 @@
// Copyright 2022 Tavian Barnes
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.
use onig::{self, Regex, RegexOptions, Syntax};
/// Parse a string as a POSIX Basic Regular Expression.
fn parse_bre(expr: &str, options: RegexOptions) -> Result<Regex, onig::Error> {
let bre = Syntax::posix_basic();
Regex::with_options(expr, bre.options() | options, bre)
}
/// Push a literal character onto a regex, escaping it if necessary.
fn regex_push_literal(regex: &mut String, ch: char) {
// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_03_03
if matches!(ch, '.' | '[' | '\\' | '*' | '^' | '$') {
regex.push('\\');
}
regex.push(ch);
}
/// Extracts a bracket expression from a glob.
fn extract_bracket_expr(pattern: &str) -> Option<(String, &str)> {
// https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_13_01
//
// If an open bracket introduces a bracket expression as in XBD RE Bracket Expression,
// except that the <exclamation-mark> character ( '!' ) shall replace the <circumflex>
// character ( '^' ) in its role in a non-matching list in the regular expression notation,
// it shall introduce a pattern bracket expression. A bracket expression starting with an
// unquoted <circumflex> character produces unspecified results. Otherwise, '[' shall match
// the character itself.
//
// To check for valid bracket expressions, we scan for the closing bracket and
// attempt to parse that segment as a regex. If that fails, we treat the '['
// literally.
let mut expr = "[".to_string();
let mut chars = pattern.chars();
let mut next = chars.next();
// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_03_05
//
// 3. A non-matching list expression begins with a <circumflex> ( '^' ) ...
//
// (but in a glob, '!' is used instead of '^')
if next == Some('!') {
expr.push('^');
next = chars.next();
}
// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_03_05
//
// 1. ... The <right-square-bracket> ( ']' ) shall lose its special meaning and represent
// itself in a bracket expression if it occurs first in the list (after an initial
// <circumflex> ( '^' ), if any).
if next == Some(']') {
expr.push(']');
next = chars.next();
}
while let Some(ch) = next {
expr.push(ch);
match ch {
'[' => {
// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_03_05
//
// 4. A collating symbol is a collating element enclosed within bracket-period
// ( "[." and ".]" ) delimiters. ...
//
// 5. An equivalence class expression shall ... be expressed by enclosing any
// one of the collating elements in the equivalence class within bracket-
// equal ( "[=" and "=]" ) delimiters.
//
// 6. ... A character class expression is expressed as a character class name
// enclosed within bracket- <colon> ( "[:" and ":]" ) delimiters.
next = chars.next();
if let Some(delim) = next {
expr.push(delim);
if matches!(delim, '.' | '=' | ':') {
let rest = chars.as_str();
let end = rest.find([delim, ']'])? + 2;
expr.push_str(&rest[..end]);
chars = rest[end..].chars();
}
}
}
']' => {
// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_03_05
//
// 1. ... The <right-square-bracket> ( ']' ) shall ... terminate the bracket
// expression, unless it appears in a collating symbol (such as "[.].]" ) or is
// the ending <right-square-bracket> for a collating symbol, equivalence class,
// or character class.
break;
}
_ => {}
}
next = chars.next();
}
if parse_bre(&expr, RegexOptions::REGEX_OPTION_NONE).is_ok() {
Some((expr, chars.as_str()))
} else {
None
}
}
/// Converts a POSIX glob into a POSIX Basic Regular Expression
fn glob_to_regex(pattern: &str) -> String {
let mut regex = String::new();
let mut chars = pattern.chars();
while let Some(ch) = chars.next() {
// https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_13
match ch {
'?' => regex.push('.'),
'*' => regex.push_str(".*"),
'\\' => {
if let Some(ch) = chars.next() {
regex_push_literal(&mut regex, ch);
} else {
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/fnmatch.html
//
// If pattern ends with an unescaped <backslash>, fnmatch() shall return a
// non-zero value (indicating either no match or an error).
//
// Most implementations return FNM_NOMATCH in this case, so return a regex that
// never matches.
return "$.".to_string();
}
}
'[' => {
if let Some((expr, rest)) = extract_bracket_expr(chars.as_str()) {
regex.push_str(&expr);
chars = rest.chars();
} else {
regex_push_literal(&mut regex, ch);
}
}
_ => regex_push_literal(&mut regex, ch),
}
}
regex
}
/// An fnmatch()-style glob matcher.
pub struct Pattern {
regex: Regex,
}
impl Pattern {
/// Parse an fnmatch()-style glob.
pub fn new(pattern: &str, caseless: bool) -> Self {
let options = if caseless {
RegexOptions::REGEX_OPTION_IGNORECASE
} else {
RegexOptions::REGEX_OPTION_NONE
};
// As long as glob_to_regex() is correct, this should never fail
let regex = parse_bre(&glob_to_regex(pattern), options).unwrap();
Self { regex }
}
/// Test if this patern matches a string.
pub fn matches(&self, string: &str) -> bool {
self.regex.is_match(string)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn literals() {
assert_eq!(glob_to_regex(r"foo.bar"), r"foo\.bar");
}
#[test]
fn regex_special() {
assert_eq!(glob_to_regex(r"^foo.bar$"), r"\^foo\.bar\$");
}
#[test]
fn wildcards() {
assert_eq!(glob_to_regex(r"foo?bar*baz"), r"foo.bar.*baz");
}
#[test]
fn escapes() {
assert_eq!(glob_to_regex(r"fo\o\?bar\*baz\\"), r"foo?bar\*baz\\");
}
#[test]
fn incomplete_escape() {
assert_eq!(glob_to_regex(r"foo\"), r"$.")
}
#[test]
fn valid_brackets() {
assert_eq!(glob_to_regex(r"foo[bar][!baz]"), r"foo[bar][^baz]");
}
#[test]
fn complex_brackets() {
assert_eq!(
glob_to_regex(r"[!]!.*[\[.].][=]=][:space:]-]"),
r"[^]!.*[\[.].][=]=][:space:]-]"
);
}
#[test]
fn invalid_brackets() {
assert_eq!(glob_to_regex(r"foo[bar[!baz"), r"foo\[bar\[!baz");
}
#[test]
fn pattern_matches() {
assert!(Pattern::new(r"foo*bar", false).matches("foo--bar"));
assert!(!Pattern::new(r"foo*bar", false).matches("bar--foo"));
}
#[test]
fn caseless_matches() {
assert!(Pattern::new(r"foo*BAR", true).matches("FOO--bar"));
assert!(!Pattern::new(r"foo*BAR", true).matches("BAR--foo"));
}
}
+107
View File
@@ -0,0 +1,107 @@
// Copyright 2017 Google Inc.
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.
use std::io::{stderr, Write};
use std::path::PathBuf;
use walkdir::DirEntry;
use super::glob::Pattern;
use super::{Matcher, MatcherIO};
fn read_link_target(file_info: &DirEntry) -> Option<PathBuf> {
match file_info.path().read_link() {
Ok(target) => Some(target),
Err(err) => {
// If it's not a symlink, then it's not an error that should be
// shown.
if err.kind() != std::io::ErrorKind::InvalidInput {
writeln!(
&mut stderr(),
"Error reading target of {}: {}",
file_info.path().display(),
err
)
.unwrap();
}
None
}
}
}
/// This matcher makes a comparison of the link target against a shell wildcard
/// pattern. See `glob::Pattern` for details on the exact syntax.
pub struct LinkNameMatcher {
pattern: Pattern,
}
impl LinkNameMatcher {
pub fn new(pattern_string: &str, caseless: bool) -> LinkNameMatcher {
let pattern = Pattern::new(pattern_string, caseless);
Self { pattern }
}
}
impl Matcher for LinkNameMatcher {
fn matches(&self, file_info: &DirEntry, _: &mut MatcherIO) -> bool {
if let Some(target) = read_link_target(file_info) {
self.pattern.matches(&target.to_string_lossy())
} else {
false
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::find::matchers::tests::get_dir_entry_for;
use crate::find::matchers::Matcher;
use crate::find::tests::FakeDependencies;
use std::io::ErrorKind;
#[cfg(unix)]
use std::os::unix::fs::symlink;
#[cfg(windows)]
use std::os::windows::fs::symlink_file;
fn create_file_link() {
#[cfg(unix)]
if let Err(e) = symlink("abbbc", "test_data/links/link-f") {
if e.kind() != ErrorKind::AlreadyExists {
panic!("Failed to create sym link: {:?}", e);
}
}
#[cfg(windows)]
if let Err(e) = symlink_file("abbbc", "test_data/links/link-f") {
if e.kind() != ErrorKind::AlreadyExists {
panic!("Failed to create sym link: {:?}", e);
}
}
}
#[test]
fn matches_against_link_target() {
create_file_link();
let link_f = get_dir_entry_for("test_data/links", "link-f");
let matcher = LinkNameMatcher::new("ab?bc", false);
let deps = FakeDependencies::new();
assert!(matcher.matches(&link_f, &mut deps.new_matcher_io()));
}
#[test]
fn caseless_matches_against_link_target() {
create_file_link();
let link_f = get_dir_entry_for("test_data/links", "link-f");
let matcher = LinkNameMatcher::new("AbB?c", true);
let deps = FakeDependencies::new();
assert!(matcher.matches(&link_f, &mut deps.new_matcher_io()));
}
}
+136 -73
View File
@@ -25,8 +25,8 @@ pub struct AndMatcher {
}
impl AndMatcher {
pub fn new(submatchers: Vec<Box<dyn Matcher>>) -> AndMatcher {
AndMatcher { submatchers }
pub fn new(submatchers: Vec<Box<dyn Matcher>>) -> Self {
Self { submatchers }
}
}
@@ -35,9 +35,16 @@ impl Matcher for AndMatcher {
/// place. If the nth sub-matcher returns false, then we immediately return
/// and don't make any further calls.
fn matches(&self, dir_entry: &DirEntry, matcher_io: &mut MatcherIO) -> bool {
self.submatchers
.iter()
.all(|x| x.matches(dir_entry, matcher_io))
for matcher in &self.submatchers {
if !matcher.matches(dir_entry, matcher_io) {
return false;
}
if matcher_io.should_quit() {
break;
}
}
true
}
fn has_side_effects(&self) -> bool {
@@ -62,14 +69,14 @@ pub struct AndMatcherBuilder {
}
impl AndMatcherBuilder {
pub fn new() -> AndMatcherBuilder {
AndMatcherBuilder {
pub fn new() -> Self {
Self {
submatchers: Vec::new(),
}
}
pub fn new_and_condition(&mut self, matcher: Box<dyn Matcher>) {
self.submatchers.push(matcher);
pub fn new_and_condition(&mut self, matcher: impl Matcher) {
self.submatchers.push(matcher.into_box());
}
/// Builds a Matcher: consuming the builder in the process.
@@ -79,9 +86,7 @@ impl AndMatcherBuilder {
// safe to unwrap: we've just checked the size
return self.submatchers.pop().unwrap();
}
let matcher = Box::new(AndMatcher::new(self.submatchers));
self.submatchers = Vec::new();
matcher
AndMatcher::new(self.submatchers).into_box()
}
}
@@ -94,8 +99,8 @@ pub struct OrMatcher {
}
impl OrMatcher {
pub fn new(submatchers: Vec<Box<dyn Matcher>>) -> OrMatcher {
OrMatcher { submatchers }
pub fn new(submatchers: Vec<Box<dyn Matcher>>) -> Self {
Self { submatchers }
}
}
@@ -104,9 +109,16 @@ impl Matcher for OrMatcher {
/// place. If the nth sub-matcher returns true, then we immediately return
/// and don't make any further calls.
fn matches(&self, dir_entry: &DirEntry, matcher_io: &mut MatcherIO) -> bool {
self.submatchers
.iter()
.any(|x| x.matches(dir_entry, matcher_io))
for matcher in &self.submatchers {
if matcher.matches(dir_entry, matcher_io) {
return true;
}
if matcher_io.should_quit() {
break;
}
}
false
}
fn has_side_effects(&self) -> bool {
@@ -131,7 +143,7 @@ pub struct OrMatcherBuilder {
}
impl OrMatcherBuilder {
pub fn new_and_condition(&mut self, matcher: Box<dyn Matcher>) {
pub fn new_and_condition(&mut self, matcher: impl Matcher) {
// safe to unwrap. submatchers always has at least one member
self.submatchers
.last_mut()
@@ -151,8 +163,8 @@ impl OrMatcherBuilder {
Ok(())
}
pub fn new() -> OrMatcherBuilder {
let mut o = OrMatcherBuilder {
pub fn new() -> Self {
let mut o = Self {
submatchers: Vec::new(),
};
o.submatchers.push(AndMatcherBuilder::new());
@@ -170,7 +182,7 @@ impl OrMatcherBuilder {
for x in self.submatchers {
submatchers.push(x.build());
}
Box::new(OrMatcher::new(submatchers))
OrMatcher::new(submatchers).into_box()
}
}
@@ -184,8 +196,8 @@ pub struct ListMatcher {
}
impl ListMatcher {
pub fn new(submatchers: Vec<Box<dyn Matcher>>) -> ListMatcher {
ListMatcher { submatchers }
pub fn new(submatchers: Vec<Box<dyn Matcher>>) -> Self {
Self { submatchers }
}
}
@@ -196,6 +208,9 @@ impl Matcher for ListMatcher {
let mut rc = false;
for matcher in &self.submatchers {
rc = matcher.matches(dir_entry, matcher_io);
if matcher_io.should_quit() {
break;
}
}
rc
}
@@ -222,7 +237,7 @@ pub struct ListMatcherBuilder {
}
impl ListMatcherBuilder {
pub fn new_and_condition(&mut self, matcher: Box<dyn Matcher>) {
pub fn new_and_condition(&mut self, matcher: impl Matcher) {
// safe to unwrap. submatchers always has at least one member
self.submatchers
.last_mut()
@@ -265,8 +280,8 @@ impl ListMatcherBuilder {
Ok(())
}
pub fn new() -> ListMatcherBuilder {
let mut o = ListMatcherBuilder {
pub fn new() -> Self {
let mut o = Self {
submatchers: Vec::new(),
};
o.submatchers.push(OrMatcherBuilder::new());
@@ -291,12 +306,6 @@ impl ListMatcherBuilder {
/// A simple matcher that always matches.
pub struct TrueMatcher;
impl TrueMatcher {
pub fn new_box() -> Box<dyn Matcher> {
Box::new(TrueMatcher {})
}
}
impl Matcher for TrueMatcher {
fn matches(&self, _dir_entry: &DirEntry, _: &mut MatcherIO) -> bool {
true
@@ -312,24 +321,16 @@ impl Matcher for FalseMatcher {
}
}
impl FalseMatcher {
pub fn new_box() -> Box<dyn Matcher> {
Box::new(FalseMatcher {})
}
}
/// Matcher that wraps another matcher and inverts matching criteria.
pub struct NotMatcher {
submatcher: Box<dyn Matcher>,
}
impl NotMatcher {
pub fn new(submatcher: Box<dyn Matcher>) -> NotMatcher {
NotMatcher { submatcher }
}
pub fn new_box(submatcher: Box<dyn Matcher>) -> Box<NotMatcher> {
Box::new(NotMatcher::new(submatcher))
pub fn new(submatcher: impl Matcher) -> Self {
Self {
submatcher: submatcher.into_box(),
}
}
}
@@ -355,13 +356,16 @@ impl Matcher for NotMatcher {
mod tests {
use super::*;
use crate::find::matchers::quit::QuitMatcher;
use crate::find::matchers::tests::get_dir_entry_for;
use crate::find::matchers::{Matcher, MatcherIO};
use crate::find::tests::FakeDependencies;
use std::cell::RefCell;
use std::rc::Rc;
use walkdir::DirEntry;
/// Simple Matcher impl that has side effects
pub struct HasSideEffects {}
pub struct HasSideEffects;
impl Matcher for HasSideEffects {
fn matches(&self, _: &DirEntry, _: &mut MatcherIO) -> bool {
@@ -373,9 +377,13 @@ mod tests {
}
}
impl HasSideEffects {
pub fn new_box() -> Box<dyn Matcher> {
Box::new(HasSideEffects {})
/// Matcher that counts its invocations
struct Counter(Rc<RefCell<u32>>);
impl Matcher for Counter {
fn matches(&self, _: &DirEntry, _: &mut MatcherIO) -> bool {
*self.0.borrow_mut() += 1;
true
}
}
@@ -386,12 +394,12 @@ mod tests {
let deps = FakeDependencies::new();
// start with one matcher returning true
builder.new_and_condition(TrueMatcher::new_box());
builder.new_and_condition(TrueMatcher);
assert!(builder.build().matches(&abbbc, &mut deps.new_matcher_io()));
builder = AndMatcherBuilder::new();
builder.new_and_condition(TrueMatcher::new_box());
builder.new_and_condition(FalseMatcher::new_box());
builder.new_and_condition(TrueMatcher);
builder.new_and_condition(FalseMatcher);
assert!(!builder.build().matches(&abbbc, &mut deps.new_matcher_io()));
}
@@ -402,13 +410,13 @@ mod tests {
let deps = FakeDependencies::new();
// start with one matcher returning false
builder.new_and_condition(FalseMatcher::new_box());
builder.new_and_condition(FalseMatcher);
assert!(!builder.build().matches(&abbbc, &mut deps.new_matcher_io()));
let mut builder = OrMatcherBuilder::new();
builder.new_and_condition(FalseMatcher::new_box());
builder.new_and_condition(FalseMatcher);
builder.new_or_condition("-o").unwrap();
builder.new_and_condition(TrueMatcher::new_box());
builder.new_and_condition(TrueMatcher);
assert!(builder.build().matches(&abbbc, &mut deps.new_matcher_io()));
}
@@ -419,21 +427,21 @@ mod tests {
let deps = FakeDependencies::new();
// result should always match that of the last pushed submatcher
builder.new_and_condition(FalseMatcher::new_box());
builder.new_and_condition(FalseMatcher);
assert!(!builder.build().matches(&abbbc, &mut deps.new_matcher_io()));
builder = ListMatcherBuilder::new();
builder.new_and_condition(FalseMatcher::new_box());
builder.new_and_condition(FalseMatcher);
builder.new_list_condition().unwrap();
builder.new_and_condition(TrueMatcher::new_box());
builder.new_and_condition(TrueMatcher);
assert!(builder.build().matches(&abbbc, &mut deps.new_matcher_io()));
builder = ListMatcherBuilder::new();
builder.new_and_condition(FalseMatcher::new_box());
builder.new_and_condition(FalseMatcher);
builder.new_list_condition().unwrap();
builder.new_and_condition(TrueMatcher::new_box());
builder.new_and_condition(TrueMatcher);
builder.new_list_condition().unwrap();
builder.new_and_condition(FalseMatcher::new_box());
builder.new_and_condition(FalseMatcher);
assert!(!builder.build().matches(&abbbc, &mut deps.new_matcher_io()));
}
@@ -460,12 +468,12 @@ mod tests {
let mut builder = AndMatcherBuilder::new();
// start with one matcher with no side effects false
builder.new_and_condition(TrueMatcher::new_box());
builder.new_and_condition(TrueMatcher);
assert!(!builder.build().has_side_effects());
builder = AndMatcherBuilder::new();
builder.new_and_condition(TrueMatcher::new_box());
builder.new_and_condition(HasSideEffects::new_box());
builder.new_and_condition(TrueMatcher);
builder.new_and_condition(HasSideEffects);
assert!(builder.build().has_side_effects());
}
@@ -474,12 +482,12 @@ mod tests {
let mut builder = OrMatcherBuilder::new();
// start with one matcher with no side effects false
builder.new_and_condition(TrueMatcher::new_box());
builder.new_and_condition(TrueMatcher);
assert!(!builder.build().has_side_effects());
builder = OrMatcherBuilder::new();
builder.new_and_condition(TrueMatcher::new_box());
builder.new_and_condition(HasSideEffects::new_box());
builder.new_and_condition(TrueMatcher);
builder.new_and_condition(HasSideEffects);
assert!(builder.build().has_side_effects());
}
@@ -488,12 +496,12 @@ mod tests {
let mut builder = ListMatcherBuilder::new();
// start with one matcher with no side effects false
builder.new_and_condition(TrueMatcher::new_box());
builder.new_and_condition(TrueMatcher);
assert!(!builder.build().has_side_effects());
builder = ListMatcherBuilder::new();
builder.new_and_condition(TrueMatcher::new_box());
builder.new_and_condition(HasSideEffects::new_box());
builder.new_and_condition(TrueMatcher);
builder.new_and_condition(HasSideEffects);
assert!(builder.build().has_side_effects());
}
@@ -512,8 +520,8 @@ mod tests {
#[test]
fn not_matches_works() {
let abbbc = get_dir_entry_for("test_data/simple", "abbbc");
let not_true = NotMatcher::new(TrueMatcher::new_box());
let not_false = NotMatcher::new(FalseMatcher::new_box());
let not_true = NotMatcher::new(TrueMatcher);
let not_false = NotMatcher::new(FalseMatcher);
let deps = FakeDependencies::new();
assert!(!not_true.matches(&abbbc, &mut deps.new_matcher_io()));
assert!(not_false.matches(&abbbc, &mut deps.new_matcher_io()));
@@ -521,9 +529,64 @@ mod tests {
#[test]
fn not_has_side_effects_works() {
let has_fx = NotMatcher::new(HasSideEffects::new_box());
let hasnt_fx = NotMatcher::new(FalseMatcher::new_box());
let has_fx = NotMatcher::new(HasSideEffects);
let hasnt_fx = NotMatcher::new(FalseMatcher);
assert!(has_fx.has_side_effects());
assert!(!hasnt_fx.has_side_effects());
}
#[test]
fn and_quit_works() {
let abbbc = get_dir_entry_for("test_data/simple", "abbbc");
let mut builder = AndMatcherBuilder::new();
let deps = FakeDependencies::new();
let before = Rc::new(RefCell::new(0));
let after = Rc::new(RefCell::new(0));
builder.new_and_condition(Counter(before.clone()));
builder.new_and_condition(QuitMatcher);
builder.new_and_condition(Counter(after.clone()));
builder.build().matches(&abbbc, &mut deps.new_matcher_io());
assert_eq!(*before.borrow(), 1);
assert_eq!(*after.borrow(), 0);
}
#[test]
fn or_quit_works() {
let abbbc = get_dir_entry_for("test_data/simple", "abbbc");
let mut builder = OrMatcherBuilder::new();
let deps = FakeDependencies::new();
let before = Rc::new(RefCell::new(0));
let after = Rc::new(RefCell::new(0));
builder.new_and_condition(Counter(before.clone()));
builder.new_or_condition("-o").unwrap();
builder.new_and_condition(QuitMatcher);
builder.new_or_condition("-o").unwrap();
builder.new_and_condition(Counter(after.clone()));
builder.build().matches(&abbbc, &mut deps.new_matcher_io());
assert_eq!(*before.borrow(), 1);
assert_eq!(*after.borrow(), 0);
}
#[test]
fn list_quit_works() {
let abbbc = get_dir_entry_for("test_data/simple", "abbbc");
let mut builder = ListMatcherBuilder::new();
let deps = FakeDependencies::new();
let before = Rc::new(RefCell::new(0));
let after = Rc::new(RefCell::new(0));
builder.new_and_condition(Counter(before.clone()));
builder.new_list_condition().unwrap();
builder.new_and_condition(QuitMatcher);
builder.new_list_condition().unwrap();
builder.new_and_condition(Counter(after.clone()));
builder.build().matches(&abbbc, &mut deps.new_matcher_io());
assert_eq!(*before.borrow(), 1);
assert_eq!(*after.borrow(), 0);
}
}
+145 -45
View File
@@ -4,16 +4,23 @@
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.
mod access;
mod delete;
mod empty;
pub mod exec;
mod glob;
mod lname;
mod logical_matchers;
mod name;
mod path;
mod perm;
mod printer;
mod printf;
mod prune;
mod quit;
mod regex;
mod size;
mod stat;
mod time;
mod type_matcher;
@@ -23,12 +30,34 @@ use std::time::SystemTime;
use std::{error::Error, str::FromStr};
use walkdir::DirEntry;
use self::access::AccessMatcher;
use self::delete::DeleteMatcher;
use self::empty::EmptyMatcher;
use self::exec::SingleExecMatcher;
use self::lname::LinkNameMatcher;
use self::logical_matchers::{
AndMatcherBuilder, FalseMatcher, ListMatcherBuilder, NotMatcher, TrueMatcher,
};
use self::name::NameMatcher;
use self::path::PathMatcher;
use self::perm::PermMatcher;
use self::printer::{PrintDelimiter, Printer};
use self::printf::Printf;
use self::prune::PruneMatcher;
use self::quit::QuitMatcher;
use self::regex::RegexMatcher;
use self::size::SizeMatcher;
use self::stat::{InodeMatcher, LinksMatcher};
use self::time::{FileTimeMatcher, FileTimeType, NewerMatcher};
use self::type_matcher::TypeMatcher;
use super::{Config, Dependencies};
/// Struct holding references to outputs and any inputs that can't be derived
/// from the file/directory info.
pub struct MatcherIO<'a> {
should_skip_dir: bool,
quit: bool,
deps: &'a dyn Dependencies<'a>,
}
@@ -37,6 +66,7 @@ impl<'a> MatcherIO<'a> {
MatcherIO {
deps,
should_skip_dir: false,
quit: false,
}
}
@@ -48,6 +78,14 @@ impl<'a> MatcherIO<'a> {
self.should_skip_dir
}
pub fn quit(&mut self) {
self.quit = true;
}
pub fn should_quit(&self) -> bool {
self.quit
}
pub fn now(&self) -> SystemTime {
self.deps.now()
}
@@ -57,7 +95,15 @@ impl<'a> MatcherIO<'a> {
/// is what's being searched for. To a first order approximation, find consists
/// of building a chain of Matcher objects, and then walking a directory tree,
/// passing each entry to the chain of Matchers.
pub trait Matcher {
pub trait Matcher: 'static {
/// Boxes this matcher as a trait object.
fn into_box(self) -> Box<dyn Matcher>
where
Self: Sized,
{
Box::new(self)
}
/// Returns whether the given file matches the object's predicate.
fn matches(&self, file_info: &DirEntry, matcher_io: &mut MatcherIO) -> bool;
@@ -80,6 +126,28 @@ pub trait Matcher {
fn finished(&self) {}
}
impl Matcher for Box<dyn Matcher> {
fn into_box(self) -> Box<dyn Matcher> {
self
}
fn matches(&self, file_info: &DirEntry, matcher_io: &mut MatcherIO) -> bool {
(**self).matches(file_info, matcher_io)
}
fn has_side_effects(&self) -> bool {
(**self).has_side_effects()
}
fn finished_dir(&self, finished_directory: &Path) {
(**self).finished_dir(finished_directory)
}
fn finished(&self) {
(**self).finished()
}
}
pub enum ComparableValue {
MoreThan(u64),
EqualTo(u64),
@@ -115,10 +183,9 @@ pub fn build_top_level_matcher(
// if the matcher doesn't have any side-effects, then we default to printing
if !top_level_matcher.has_side_effects() {
let mut new_and_matcher = logical_matchers::AndMatcherBuilder::new();
let mut new_and_matcher = AndMatcherBuilder::new();
new_and_matcher.new_and_condition(top_level_matcher);
new_and_matcher
.new_and_condition(printer::Printer::new_box(printer::PrintDelimiter::Newline));
new_and_matcher.new_and_condition(Printer::new(PrintDelimiter::Newline));
return Ok(new_and_matcher.build());
}
Ok(top_level_matcher)
@@ -198,7 +265,7 @@ fn build_matcher_tree(
arg_index: usize,
expecting_bracket: bool,
) -> Result<(usize, Box<dyn Matcher>), Box<dyn Error>> {
let mut top_level_matcher = logical_matchers::ListMatcherBuilder::new();
let mut top_level_matcher = ListMatcherBuilder::new();
let mut regex_type = regex::RegexType::default();
@@ -210,31 +277,39 @@ fn build_matcher_tree(
let mut invert_next_matcher = false;
while i < args.len() {
let possible_submatcher = match args[i] {
"-print" => Some(printer::Printer::new_box(printer::PrintDelimiter::Newline)),
"-print0" => Some(printer::Printer::new_box(printer::PrintDelimiter::Null)),
"-print" => Some(Printer::new(PrintDelimiter::Newline).into_box()),
"-print0" => Some(Printer::new(PrintDelimiter::Null).into_box()),
"-printf" => {
if i >= args.len() - 1 {
return Err(From::from(format!("missing argument to {}", args[i])));
}
i += 1;
Some(printf::Printf::new_box(args[i])?)
Some(Printf::new(args[i])?.into_box())
}
"-true" => Some(logical_matchers::TrueMatcher::new_box()),
"-false" => Some(logical_matchers::FalseMatcher::new_box()),
"-name" => {
"-true" => Some(TrueMatcher.into_box()),
"-false" => Some(FalseMatcher.into_box()),
"-lname" | "-ilname" => {
if i >= args.len() - 1 {
return Err(From::from(format!("missing argument to {}", args[i])));
}
i += 1;
Some(name::NameMatcher::new_box(args[i])?)
Some(LinkNameMatcher::new(args[i], args[i - 1].starts_with("-i")).into_box())
}
"-iname" => {
"-name" | "-iname" => {
if i >= args.len() - 1 {
return Err(From::from(format!("missing argument to {}", args[i])));
}
i += 1;
Some(name::CaselessNameMatcher::new_box(args[i])?)
Some(NameMatcher::new(args[i], args[i - 1].starts_with("-i")).into_box())
}
"-path" | "-ipath" | "-wholename" | "-iwholename" => {
if i >= args.len() - 1 {
return Err(From::from(format!("missing argument to {}", args[i])));
}
i += 1;
Some(PathMatcher::new(args[i], args[i - 1].starts_with("-i")).into_box())
}
"-readable" => Some(AccessMatcher::Readable.into_box()),
"-regextype" => {
if i >= args.len() - 1 {
return Err(From::from(format!("missing argument to {}", args[i])));
@@ -248,49 +323,49 @@ fn build_matcher_tree(
return Err(From::from(format!("missing argument to {}", args[i])));
}
i += 1;
Some(regex::RegexMatcher::new_box(regex_type, args[i], false)?)
Some(RegexMatcher::new(regex_type, args[i], false)?.into_box())
}
"-iregex" => {
if i >= args.len() - 1 {
return Err(From::from(format!("missing argument to {}", args[i])));
}
i += 1;
Some(regex::RegexMatcher::new_box(regex_type, args[i], true)?)
Some(RegexMatcher::new(regex_type, args[i], true)?.into_box())
}
"-type" => {
if i >= args.len() - 1 {
return Err(From::from(format!("missing argument to {}", args[i])));
}
i += 1;
Some(type_matcher::TypeMatcher::new_box(args[i])?)
Some(TypeMatcher::new(args[i])?.into_box())
}
"-delete" => {
// -delete implicitly requires -depth
config.depth_first = true;
Some(delete::DeleteMatcher::new_box()?)
Some(DeleteMatcher::new().into_box())
}
"-newer" => {
if i >= args.len() - 1 {
return Err(From::from(format!("missing argument to {}", args[i])));
}
i += 1;
Some(time::NewerMatcher::new_box(args[i])?)
Some(NewerMatcher::new(args[i])?.into_box())
}
"-mtime" | "-atime" | "-ctime" => {
if i >= args.len() - 1 {
return Err(From::from(format!("missing argument to {}", args[i])));
}
let file_time_type = match args[i] {
"-atime" => time::FileTimeType::Accessed,
"-ctime" => time::FileTimeType::Created,
"-mtime" => time::FileTimeType::Modified,
"-atime" => FileTimeType::Accessed,
"-ctime" => FileTimeType::Created,
"-mtime" => FileTimeType::Modified,
// This shouldn't be possible. We've already checked the value
// is one of those three values.
_ => unreachable!("Encountered unexpected value {}", args[i]),
};
let days = convert_arg_to_comparable_value(args[i], args[i + 1])?;
i += 1;
Some(time::FileTimeMatcher::new_box(file_time_type, days))
Some(FileTimeMatcher::new(file_time_type, days).into_box())
}
"-size" => {
if i >= args.len() - 1 {
@@ -299,8 +374,9 @@ fn build_matcher_tree(
let (size, unit) =
convert_arg_to_comparable_value_and_suffix(args[i], args[i + 1])?;
i += 1;
Some(size::SizeMatcher::new_box(size, &unit)?)
Some(SizeMatcher::new(size, &unit)?.into_box())
}
"-empty" => Some(EmptyMatcher::new().into_box()),
"-exec" | "-execdir" => {
let mut arg_index = i + 1;
while arg_index < args.len() && args[arg_index] != ";" {
@@ -322,20 +398,38 @@ fn build_matcher_tree(
let executable = args[i + 1];
let exec_args = &args[i + 2..arg_index];
i = arg_index;
Some(exec::SingleExecMatcher::new_box(
executable,
exec_args,
expression == "-execdir",
)?)
Some(
SingleExecMatcher::new(executable, exec_args, expression == "-execdir")?
.into_box(),
)
}
"-inum" => {
if i >= args.len() - 1 {
return Err(From::from(format!("missing argument to {}", args[i])));
}
let inum = convert_arg_to_comparable_value(args[i], args[i + 1])?;
i += 1;
Some(InodeMatcher::new(inum)?.into_box())
}
"-links" => {
if i >= args.len() - 1 {
return Err(From::from(format!("missing argument to {}", args[i])));
}
let inum = convert_arg_to_comparable_value(args[i], args[i + 1])?;
i += 1;
Some(LinksMatcher::new(inum)?.into_box())
}
"-executable" => Some(AccessMatcher::Executable.into_box()),
"-perm" => {
if i >= args.len() - 1 {
return Err(From::from(format!("missing argument to {}", args[i])));
}
i += 1;
Some(perm::PermMatcher::new_box(args[i])?)
Some(PermMatcher::new(args[i])?.into_box())
}
"-prune" => Some(prune::PruneMatcher::new_box()),
"-prune" => Some(PruneMatcher::new().into_box()),
"-quit" => Some(QuitMatcher.into_box()),
"-writable" => Some(AccessMatcher::Writable.into_box()),
"-not" | "!" => {
if !are_more_expressions(args, i) {
return Err(From::from(format!(
@@ -346,7 +440,7 @@ fn build_matcher_tree(
invert_next_matcher = !invert_next_matcher;
None
}
"-a" => {
"-and" | "-a" => {
if !are_more_expressions(args, i) {
return Err(From::from(format!(
"expected an expression after {}",
@@ -392,6 +486,11 @@ fn build_matcher_tree(
config.depth_first = true;
None
}
"-mount" | "-xdev" => {
// TODO add warning if it appears after actual testing criterion
config.same_file_system = true;
None
}
"-sorted" => {
// TODO add warning if it appears after actual testing criterion
config.sorted_output = true;
@@ -426,8 +525,7 @@ fn build_matcher_tree(
};
if let Some(submatcher) = possible_submatcher {
if invert_next_matcher {
top_level_matcher
.new_and_condition(logical_matchers::NotMatcher::new_box(submatcher));
top_level_matcher.new_and_condition(NotMatcher::new(submatcher));
invert_next_matcher = false;
} else {
top_level_matcher.new_and_condition(submatcher);
@@ -624,17 +722,19 @@ mod tests {
#[test]
fn build_top_level_matcher_dash_a_works() {
let abbbc = get_dir_entry_for("./test_data/simple", "abbbc");
let mut config = Config::default();
let deps = FakeDependencies::new();
for arg in &["-a", "-and"] {
let abbbc = get_dir_entry_for("./test_data/simple", "abbbc");
let mut config = Config::default();
let deps = FakeDependencies::new();
// build a matcher using an explicit -a argument
let matcher = build_top_level_matcher(&["-true", "-a", "-true"], &mut config).unwrap();
assert!(matcher.matches(&abbbc, &mut deps.new_matcher_io()));
assert_eq!(
deps.get_output_as_string(),
fix_up_slashes("./test_data/simple/abbbc\n")
);
// build a matcher using an explicit -a argument
let matcher = build_top_level_matcher(&["-true", arg, "-true"], &mut config).unwrap();
assert!(matcher.matches(&abbbc, &mut deps.new_matcher_io()));
assert_eq!(
deps.get_output_as_string(),
fix_up_slashes("./test_data/simple/abbbc\n")
);
}
}
#[test]
@@ -1025,7 +1125,7 @@ mod tests {
fn build_top_level_matcher_perm_bad() {
let mut config = Config::default();
if let Err(e) = build_top_level_matcher(&["-perm", "foo"], &mut config) {
assert!(e.to_string().contains("invalid mode"));
assert!(e.to_string().contains("invalid operator"));
} else {
panic!("-perm with bad mode pattern should fail");
}
+51 -57
View File
@@ -4,79 +4,65 @@
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.
use glob::Pattern;
use glob::PatternError;
use walkdir::DirEntry;
use super::glob::Pattern;
use super::{Matcher, MatcherIO};
/// This matcher makes a case-sensitive comparison of the name against a
/// shell wildcard pattern. See `glob::Pattern` for details on the exact
/// syntax.
/// This matcher makes a comparison of the name against a shell wildcard
/// pattern. See `glob::Pattern` for details on the exact syntax.
pub struct NameMatcher {
pattern: Pattern,
}
impl NameMatcher {
pub fn new(pattern_string: &str) -> Result<NameMatcher, PatternError> {
let p = Pattern::new(pattern_string)?;
Ok(NameMatcher { pattern: p })
}
pub fn new_box(pattern_string: &str) -> Result<Box<dyn Matcher>, PatternError> {
Ok(Box::new(NameMatcher::new(pattern_string)?))
pub fn new(pattern_string: &str, caseless: bool) -> Self {
let pattern = Pattern::new(pattern_string, caseless);
Self { pattern }
}
}
impl Matcher for NameMatcher {
fn matches(&self, file_info: &DirEntry, _: &mut MatcherIO) -> bool {
self.pattern
.matches(file_info.file_name().to_string_lossy().as_ref())
}
}
/// This matcher makes a case-insensitive comparison of the name against a
/// shell wildcard pattern. See `glob::Pattern` for details on the exact
/// syntax.
pub struct CaselessNameMatcher {
pattern: Pattern,
}
impl CaselessNameMatcher {
pub fn new(pattern_string: &str) -> Result<CaselessNameMatcher, PatternError> {
let p = Pattern::new(&pattern_string.to_lowercase())?;
Ok(CaselessNameMatcher { pattern: p })
}
pub fn new_box(pattern_string: &str) -> Result<Box<dyn Matcher>, PatternError> {
Ok(Box::new(CaselessNameMatcher::new(pattern_string)?))
}
}
impl super::Matcher for CaselessNameMatcher {
fn matches(&self, file_info: &DirEntry, _: &mut MatcherIO) -> bool {
self.pattern.matches(
file_info
.file_name()
.to_string_lossy()
.to_lowercase()
.as_ref(),
)
let name = file_info.file_name().to_string_lossy();
self.pattern.matches(&name)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::find::matchers::tests::get_dir_entry_for;
use crate::find::matchers::Matcher;
use crate::find::tests::FakeDependencies;
use std::io::ErrorKind;
#[cfg(unix)]
use std::os::unix::fs::symlink;
#[cfg(windows)]
use std::os::windows::fs::symlink_file;
fn create_file_link() {
#[cfg(unix)]
if let Err(e) = symlink("abbbc", "test_data/links/link-f") {
if e.kind() != ErrorKind::AlreadyExists {
panic!("Failed to create sym link: {:?}", e);
}
}
#[cfg(windows)]
if let Err(e) = symlink_file("abbbc", "test_data/links/link-f") {
if e.kind() != ErrorKind::AlreadyExists {
panic!("Failed to create sym link: {:?}", e);
}
}
}
#[test]
fn matching_with_wrong_case_returns_false() {
let abbbc = get_dir_entry_for("test_data/simple", "abbbc");
let matcher = NameMatcher::new(&"A*C".to_string()).unwrap();
let matcher = NameMatcher::new("A*C", false);
let deps = FakeDependencies::new();
assert!(!matcher.matches(&abbbc, &mut deps.new_matcher_io()));
}
@@ -84,7 +70,7 @@ mod tests {
#[test]
fn matching_with_right_case_returns_true() {
let abbbc = get_dir_entry_for("test_data/simple", "abbbc");
let matcher = NameMatcher::new(&"abb?c".to_string()).unwrap();
let matcher = NameMatcher::new("abb?c", false);
let deps = FakeDependencies::new();
assert!(matcher.matches(&abbbc, &mut deps.new_matcher_io()));
}
@@ -92,21 +78,25 @@ mod tests {
#[test]
fn not_matching_returns_false() {
let abbbc = get_dir_entry_for("test_data/simple", "abbbc");
let matcher = NameMatcher::new(&"shouldn't match".to_string()).unwrap();
let matcher = NameMatcher::new("shouldn't match", false);
let deps = FakeDependencies::new();
assert!(!matcher.matches(&abbbc, &mut deps.new_matcher_io()));
}
#[test]
fn cant_create_with_invalid_pattern() {
let result = NameMatcher::new(&"a**c".to_string());
assert!(result.is_err());
fn matches_against_link_file_name() {
create_file_link();
let link_f = get_dir_entry_for("test_data/links", "link-f");
let matcher = NameMatcher::new("link?f", false);
let deps = FakeDependencies::new();
assert!(matcher.matches(&link_f, &mut deps.new_matcher_io()));
}
#[test]
fn caseless_matching_with_wrong_case_returns_true() {
let abbbc = get_dir_entry_for("test_data/simple", "abbbc");
let matcher = CaselessNameMatcher::new(&"A*C".to_string()).unwrap();
let matcher = NameMatcher::new("A*C", true);
let deps = FakeDependencies::new();
assert!(matcher.matches(&abbbc, &mut deps.new_matcher_io()));
}
@@ -114,7 +104,7 @@ mod tests {
#[test]
fn caseless_matching_with_right_case_returns_true() {
let abbbc = get_dir_entry_for("test_data/simple", "abbbc");
let matcher = CaselessNameMatcher::new(&"abb?c".to_string()).unwrap();
let matcher = NameMatcher::new("abb?c", true);
let deps = FakeDependencies::new();
assert!(matcher.matches(&abbbc, &mut deps.new_matcher_io()));
}
@@ -122,14 +112,18 @@ mod tests {
#[test]
fn caseless_not_matching_returns_false() {
let abbbc = get_dir_entry_for("test_data/simple", "abbbc");
let matcher = CaselessNameMatcher::new(&"shouldn't match".to_string()).unwrap();
let matcher = NameMatcher::new("shouldn't match", true);
let deps = FakeDependencies::new();
assert!(!matcher.matches(&abbbc, &mut deps.new_matcher_io()));
}
#[test]
fn caseless_cant_create_with_invalid_pattern() {
let result = CaselessNameMatcher::new(&"a**c".to_string());
assert!(result.is_err());
fn caseless_matches_against_link_file_name() {
create_file_link();
let link_f = get_dir_entry_for("test_data/links", "link-f");
let matcher = NameMatcher::new("linK?f", true);
let deps = FakeDependencies::new();
assert!(matcher.matches(&link_f, &mut deps.new_matcher_io()));
}
}
+82
View File
@@ -0,0 +1,82 @@
// Copyright 2017 Google Inc.
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.
use walkdir::DirEntry;
use super::glob::Pattern;
use super::{Matcher, MatcherIO};
/// This matcher makes a comparison of the path against a shell wildcard
/// pattern. See `glob::Pattern` for details on the exact syntax.
pub struct PathMatcher {
pattern: Pattern,
}
impl PathMatcher {
pub fn new(pattern_string: &str, caseless: bool) -> Self {
let pattern = Pattern::new(pattern_string, caseless);
Self { pattern }
}
}
impl Matcher for PathMatcher {
fn matches(&self, file_info: &DirEntry, _: &mut MatcherIO) -> bool {
let path = file_info.path().to_string_lossy();
self.pattern.matches(&path)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::find::matchers::tests::get_dir_entry_for;
use crate::find::matchers::Matcher;
use crate::find::tests::FakeDependencies;
// Variants of fix_up_slashes that properly escape the forward slashes for
// being in a glob.
#[cfg(windows)]
fn fix_up_glob_slashes(re: &str) -> String {
re.replace("/", "\\\\")
}
#[cfg(not(windows))]
fn fix_up_glob_slashes(re: &str) -> String {
re.to_owned()
}
#[test]
fn matching_against_whole_path() {
let abbbc = get_dir_entry_for("test_data/simple", "abbbc");
let matcher = PathMatcher::new(&fix_up_glob_slashes("test_*/*/a*c"), false);
let deps = FakeDependencies::new();
assert!(matcher.matches(&abbbc, &mut deps.new_matcher_io()));
}
#[test]
fn not_matching_against_just_name() {
let abbbc = get_dir_entry_for("test_data/simple", "abbbc");
let matcher = PathMatcher::new("a*c", false);
let deps = FakeDependencies::new();
assert!(!matcher.matches(&abbbc, &mut deps.new_matcher_io()));
}
#[test]
fn not_matching_against_wrong_case() {
let abbbc = get_dir_entry_for("test_data/simple", "abbbc");
let matcher = PathMatcher::new(&fix_up_glob_slashes("test_*/*/A*C"), false);
let deps = FakeDependencies::new();
assert!(!matcher.matches(&abbbc, &mut deps.new_matcher_io()));
}
#[test]
fn caseless_matching() {
let abbbc = get_dir_entry_for("test_data/simple", "abbbc");
let matcher = PathMatcher::new(&fix_up_glob_slashes("test_*/*/A*C"), true);
let deps = FakeDependencies::new();
assert!(matcher.matches(&abbbc, &mut deps.new_matcher_io()));
}
}
+91 -378
View File
File diff suppressed because it is too large Load Diff
+2 -6
View File
@@ -28,12 +28,8 @@ pub struct Printer {
}
impl Printer {
pub fn new(delimiter: PrintDelimiter) -> Printer {
Printer { delimiter }
}
pub fn new_box(delimiter: PrintDelimiter) -> Box<dyn Matcher> {
Box::new(Printer::new(delimiter))
pub fn new(delimiter: PrintDelimiter) -> Self {
Self { delimiter }
}
}

Some files were not shown because too many files have changed in this diff Show More