Compare commits

..

22 Commits

Author SHA1 Message Date
Andrew Gallant
7bf7ceb5d3 progress 2019-05-29 18:07:03 -04:00
Andrew Gallant
7d3f794588 ignore: remove .git check in some cases
When we know we aren't going to process gitignores, we shouldn't waste
the syscall in every directory to check for a git repo.
2019-05-29 18:06:11 -04:00
bruce-one
290fd2a7b6 readme: mention Zstandard and Brotli
Also alphabetise the list.

PR #1288
2019-05-29 13:37:31 -04:00
Fabian Würfl
d1e4d28f30 readme: remove outdated statement
Issue #10 already states that "ripgrep is now in most or all of the major
package repositories."

PR #1280
2019-05-14 18:44:50 -04:00
Andrew Gallant
5ce2d7351d ci: use cross for musl x86_64 builds
This is necessary because jemalloc + musl + Ubuntu 16.04 is apparently
broken.

Moreover, jemalloc doesn't support i686, so we accept the performance
regression there.

See also: https://github.com/gnzlbg/jemallocator/issues/124
2019-04-25 11:12:14 -04:00
Andrew Gallant
9dcfd9a205 deps: bump pcre2-sys to 0.2.1
This brings in a bug fix that no longer tries to run `git` to update the
submodule if the `git` command doesn't exist.

This is useful is more restricted build contexts where `git` isn't
installed. Such as in the docker image used for running `cross`.
2019-04-25 11:12:14 -04:00
Andrew Gallant
36b276c6d0 printer: remove unnecessary mut 2019-04-24 17:22:27 -04:00
Andrew Gallant
03bf37ff4a alloc: use jemalloc when building with musl
It turns out that musl's allocator is slow enough to cause a fairly
noticeable performance regression when ripgrep is built as a static
binary with musl. We fix this by using jemalloc when building with musl.

We continue to use the default system allocator in all other scenarios.
Namely, glibc's allocator doesn't noticeably regress performance compared
to jemalloc. But we could add more targets to this logic if other
system allocators (macOS, Windows) prove to be slow.

This wasn't necessary before because rustc recently stopped using jemalloc
by default.

Fixes #1268
2019-04-24 17:21:38 -04:00
Andrew Gallant
e7829c05d3 cli: fix bug where last byte was stripped
In an effort to strip line terminators, we assumed their existence. But
a pattern file may not end with a line terminator, so we shouldn't
unconditionally strip them.

We fix this by moving to bstr's line handling, which does this for us
automatically.
2019-04-19 07:11:44 -04:00
Rory O’Kane
a6222939f9 readme: mention --pcre2 as long form of -P
This is for consistency with the short and long flags given in other
bullet points. I originally assumed there was no long flag for `-P`
because none was given here.

PR #1254
2019-04-16 21:22:48 -04:00
Rory O’Kane
6ffd434232 readme: mention --auto-hybrid-regex in advantages
This feature solves a major reason I was skeptical of using ripgrep, so
I think it’s good to mention it in the section about why one should use
it.

I use backreferences a lot, so I had previously thought that ripgrep
would provide no speed advantage over ag, since I would always have
`-P` enabled. But when I saw `--auto-hybrid-regex` in the 11.0.0
changelog, I learned that ripgrep can use it to speed up simple queries
while still allowing me to write backreferences.

PR #1253
2019-04-16 17:21:40 -04:00
Andrew Gallant
1f1cd9b467 pkg: update brew tap to 11.0.1 2019-04-16 13:39:56 -04:00
Andrew Gallant
973de50c9e ripgrep: release 11.0.1, take 2 2019-04-16 13:11:28 -04:00
Andrew Gallant
5f8805a496 ripgrep: release 11.0.1 2019-04-16 13:10:29 -04:00
Andrew Gallant
fdde2bcd38 deps: update regex to 1.1.6
This brings in a fix for a regression introduced in ripgrep 11.

Fixes #1247
2019-04-16 08:34:30 -04:00
Gerard de Melo
7b3fe6b325 doc: fix typo in FAQ
PR #1248
2019-04-16 08:32:30 -04:00
Max Horn
b3dd3ae203 ignore/types: add GAP
Add support for file types used by the GAP language, a research system
computational discrete algebra, see <https://www.gap-system.org>

PR #1249
2019-04-16 08:31:58 -04:00
Andrew Gallant
f3083e4574 readme: remove brew tap instructions
The brew tap isn't really needed any more, since SIMD is now
automatically enabled in all binaries.
2019-04-15 18:32:33 -04:00
Andrew Gallant
d03e30707e pkg: update brew tap to 11.0.0 2019-04-15 18:32:10 -04:00
Andrew Gallant
d7f57d9aab ripgrep: release 11.0.0 2019-04-15 18:09:40 -04:00
Andrew Gallant
1a2a24ea74 grep: release 0.2.4 2019-04-15 18:03:46 -04:00
Andrew Gallant
d66610b295 grep-cli: release 0.1.2 2019-04-15 18:02:44 -04:00
22 changed files with 620 additions and 209 deletions

View File

@@ -1,5 +1,27 @@
11.0.0 (TBD)
============
TBD
===
TODO.
Bug fixes:
* [BUG #1259](https://github.com/BurntSushi/ripgrep/issues/1259):
Fix bug where the last byte of a `-f file` was stripped if it wasn't a `\n`.
11.0.1 (2019-04-16)
===================
ripgrep 11.0.1 is a new patch release that fixes a search regression introduced
in the previous 11.0.0 release. In particular, ripgrep can enter an infinite
loop for some search patterns when searching invalid UTF-8.
Bug fixes:
* [BUG #1247](https://github.com/BurntSushi/ripgrep/issues/1247):
Fix search bug that can cause ripgrep to enter an infinite loop.
11.0.0 (2019-04-15)
===================
ripgrep 11 is a new major version release of ripgrep that contains many bug
fixes, some performance improvements and a few feature enhancements. Notably,
ripgrep's user experience for binary file filtering has been improved. See the
@@ -32,9 +54,9 @@ This release increases the **minimum supported Rust version** from 1.28.0 to
terminal. That is, `rg -uuu foo` should now be equivalent to `grep -r foo`.
* The `avx-accel` feature of ripgrep has been removed since it is no longer
necessary. All uses of AVX in ripgrep are now enabled automatically via
runtime CPU feature detection. The `simd-accel` feature does remain
available, however, it does increase compilation times substantially at the
moment.
runtime CPU feature detection. The `simd-accel` feature does remain available
(only for enabling SIMD for transcoding), however, it does increase
compilation times substantially at the moment.
Performance improvements:

114
Cargo.lock generated
View File

@@ -23,6 +23,28 @@ name = "autocfg"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "backtrace"
version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "backtrace-sys"
version = "0.1.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "base64"
version = "0.10.1"
@@ -125,6 +147,11 @@ name = "fnv"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "fs_extra"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "fuchsia-cprng"
version = "0.1.1"
@@ -144,14 +171,14 @@ dependencies = [
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
"glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "grep"
version = "0.2.3"
version = "0.2.4"
dependencies = [
"grep-cli 0.1.1",
"grep-cli 0.1.2",
"grep-matcher 0.1.2",
"grep-pcre2 0.1.3",
"grep-printer 0.1.2",
@@ -163,14 +190,14 @@ dependencies = [
[[package]]
name = "grep-cli"
version = "0.1.1"
version = "0.1.2"
dependencies = [
"atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"bstr 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"globset 0.4.3",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -181,7 +208,7 @@ name = "grep-matcher"
version = "0.1.2"
dependencies = [
"memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -214,7 +241,7 @@ dependencies = [
"aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
"grep-matcher 0.1.2",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -232,7 +259,7 @@ dependencies = [
"grep-regex 0.1.3",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -244,7 +271,7 @@ dependencies = [
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -257,6 +284,25 @@ name = "itoa"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "jemalloc-sys"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
"fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "jemallocator"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"jemalloc-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "lazy_static"
version = "1.3.0"
@@ -312,13 +358,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"pcre2-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pcre2-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "pcre2-sys"
version = "0.2.0"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -466,7 +512,7 @@ dependencies = [
[[package]]
name = "regex"
version = "1.1.5"
version = "1.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -502,22 +548,29 @@ dependencies = [
[[package]]
name = "ripgrep"
version = "0.10.0"
version = "11.0.1"
dependencies = [
"bstr 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
"grep 0.2.3",
"grep 0.2.4",
"ignore 0.4.7",
"jemallocator 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)",
"snafu 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc-demangle"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "ryu"
version = "0.2.7"
@@ -561,6 +614,25 @@ name = "smallvec"
version = "0.6.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "snafu"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"snafu-derive 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "snafu-derive"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.31 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "strsim"
version = "0.8.0"
@@ -693,6 +765,8 @@ dependencies = [
"checksum aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e6f484ae0c99fec2e858eb6134949117399f222608d84cadb3f58c1f97c2364c"
"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799"
"checksum backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f106c02a3604afcdc0df5d36cc47b44b55917dbaf3d808f71c163a0ddba64637"
"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6"
"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
"checksum bstr 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6c8203ca06c502958719dae5f653a79e0cc6ba808ed02beffbf27d09610f2143"
@@ -707,9 +781,12 @@ dependencies = [
"checksum encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4155785c79f2f6701f185eb2e6b4caf0555ec03477cb4c70db67b465311620ed"
"checksum encoding_rs_io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9619ee7a2bf4e777e020b95c1439abaf008f8ea8041b78a0552c4f1bcf4df32c"
"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
"checksum fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5f2a4a2034423744d2cc7ca2068453168dcdb82c438419e639a26bd87839c674"
"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
"checksum glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b"
"checksum jemalloc-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7bef0d4ce37578dfd80b466e3d8324bd9de788e249f1accebb0c472ea4b52bdc"
"checksum jemallocator 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c2b69163a3cf2d0fffcd4e1b57921bc6d8fb97ec27f2aeef00562abdaf4ffe2a"
"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
"checksum libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)" = "bedcc7a809076656486ffe045abeeac163da1b558e963a31e29fbfbeba916917"
"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
@@ -718,7 +795,7 @@ dependencies = [
"checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba"
"checksum packed_simd 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a85ea9fc0d4ac0deb6fe7911d38786b32fc11119afd9e9d38b84ff691ce64220"
"checksum pcre2 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a08c8195dd1d8a2a1b5e2af94bf0c4c3c195c2359930442a016bf123196f7155"
"checksum pcre2-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1e0092a7eae1c569cf7dbec61eef956516df93eb4afda8f600ccb16980aca849"
"checksum pcre2-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e9699d43bebf25ee0fdafb9457b9a52da3c57506a3d39a2f9b6498800f032881"
"checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c"
"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915"
"checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db"
@@ -735,16 +812,19 @@ dependencies = [
"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
"checksum redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)" = "12229c14a0f65c4f1cb046a3b52047cdd9da1f4b30f8a39c5063c8bae515e252"
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
"checksum regex 1.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "559008764a17de49a3146b234641644ed37d118d1ef641a0bb573d146edc6ce0"
"checksum regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8f0a0bcab2fd7d1d7c54fa9eae6f43eddeb9ce2e7352f8518a814a4f65d60c58"
"checksum regex-automata 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a25a7daa2eea48550e9946133d6cc9621020d29cc7069089617234bf8b6a8693"
"checksum regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfd8681eebe297b81d98498869d4aae052137651ad7b96822f09ceb690d0a96"
"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5"
"checksum rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ccc78bfd5acd7bf3e89cffcf899e5cb1a52d6fafa8dec2739ad70c9577a57288"
"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7"
"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267"
"checksum serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)" = "aa5f7c20820475babd2c077c3ab5f8c77a31c15e16ea38687b4c02d3e48680f4"
"checksum serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)" = "58fc82bec244f168b23d1963b45c8bf5726e9a15a9d146a067f9081aeed2de79"
"checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d"
"checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be"
"checksum snafu 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "67a2e16c9b74a09d4bc84ea6e5eb68fef70b4cb14e8ccd26f2de76af2e9c2e8a"
"checksum snafu-derive 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bf96650c2b31fa949780f792025f4ca79fbe87bd723a8b3573dce37be7193b08"
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
"checksum syn 0.15.31 (registry+https://github.com/rust-lang/crates.io-index)" = "d2b4cfac95805274c6afdb12d8f770fa2d27c045953e7b630a81801953699a9a"
"checksum tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b86c784c88d98c801132806dadd3819ed29d8600836c4088e855cdf3e178ed8a"

View File

@@ -1,6 +1,6 @@
[package]
name = "ripgrep"
version = "0.10.0" #:version
version = "11.0.1" #:version
authors = ["Andrew Gallant <jamslam@gmail.com>"]
description = """
ripgrep is a line-oriented search tool that recursively searches your current
@@ -47,13 +47,14 @@ members = [
[dependencies]
bstr = "0.1.2"
grep = { version = "0.2.3", path = "grep" }
grep = { version = "0.2.4", path = "grep" }
ignore = { version = "0.4.7", path = "ignore" }
lazy_static = "1.1.0"
log = "0.4.5"
log = { version = "0.4.5", features = ["std"] }
num_cpus = "1.8.0"
regex = "1.0.5"
serde_json = "1.0.23"
snafu = "0.2.3"
termcolor = "1.0.3"
[dependencies.clap]
@@ -61,6 +62,9 @@ version = "2.32.0"
default-features = false
features = ["suggestions"]
[target.'cfg(all(target_env = "musl", target_pointer_width = "64"))'.dependencies.jemallocator]
version = "0.3.0"
[build-dependencies]
lazy_static = "1.1.0"

2
FAQ.md
View File

@@ -935,7 +935,7 @@ for the previous section apply.
* Are you writing portable shell scripts intended to work in a variety of
environments? Great, probably not a good idea to use ripgrep! ripgrep is has
nowhere near the ubquity of grep, so if you do use ripgrep, you might need
nowhere near the ubiquity of grep, so if you do use ripgrep, you might need
to futz with the installation process more than you would with grep.
* Do you care about POSIX compatibility? If so, then you can't use ripgrep
because it never was, isn't and never will be POSIX compatible.

View File

@@ -108,13 +108,14 @@ increases the times to `2.640s` for ripgrep and `10.277s` for GNU grep.
* ripgrep has optional support for switching its regex engine to use PCRE2.
Among other things, this makes it possible to use look-around and
backreferences in your patterns, which are not supported in ripgrep's default
regex engine. PCRE2 support is enabled with `-P`.
regex engine. PCRE2 support can be enabled with `-P/--pcre2` (use PCRE2
always) or `--auto-hybrid-regex` (use PCRE2 only if needed).
* ripgrep supports searching files in text encodings other than UTF-8, such
as UTF-16, latin-1, GBK, EUC-JP, Shift_JIS and more. (Some support for
automatically detecting UTF-16 is provided. Other text encodings must be
specifically specified with the `-E/--encoding` flag.)
* ripgrep supports searching files compressed in a common format (gzip, xz,
lzma, bzip2 or lz4) with the `-z/--search-zip` flag.
* ripgrep supports searching files compressed in a common format (brotli,
bzip2, gzip, lz4, lzma, xz, or zstandard) with the `-z/--search-zip` flag.
* ripgrep supports arbitrary input preprocessing filters which could be PDF
text extraction, less supported decompression, decrypting, automatic encoding
detection and so on.
@@ -208,14 +209,6 @@ from homebrew-core, (compiled with rust stable, no SIMD):
$ brew install ripgrep
```
or you can install a binary compiled with rust nightly (including SIMD and all
optimizations) by utilizing a custom tap:
```
$ brew tap burntsushi/ripgrep https://github.com/BurntSushi/ripgrep.git
$ brew install ripgrep-bin
```
If you're a **MacPorts** user, then you can install ripgrep from the
[official ports](https://www.macports.org/ports.php?by=name&substr=ripgrep):
@@ -294,8 +287,8 @@ then ripgrep can be installed using a binary `.deb` file provided in each
[ripgrep release](https://github.com/BurntSushi/ripgrep/releases).
```
$ curl -LO https://github.com/BurntSushi/ripgrep/releases/download/0.10.0/ripgrep_0.10.0_amd64.deb
$ sudo dpkg -i ripgrep_0.10.0_amd64.deb
$ curl -LO https://github.com/BurntSushi/ripgrep/releases/download/11.0.1/ripgrep_11.0.1_amd64.deb
$ sudo dpkg -i ripgrep_11.0.1_amd64.deb
```
If you run Debian Buster (currently Debian testing) or Debian sid, ripgrep is
@@ -350,9 +343,6 @@ If you're a **Rust programmer**, ripgrep can be installed with `cargo`.
$ cargo install ripgrep
```
ripgrep isn't currently in any other package repositories.
[I'd like to change that](https://github.com/BurntSushi/ripgrep/issues/10).
### Building

View File

@@ -8,12 +8,13 @@ set -ex
# Generate artifacts for release
mk_artifacts() {
CARGO="$(builder)"
if is_arm; then
cargo build --target "$TARGET" --release
"$CARGO" build --target "$TARGET" --release
else
# Technically, MUSL builds will force PCRE2 to get statically compiled,
# but we also want PCRE2 statically build for macOS binaries.
PCRE2_SYS_STATIC=1 cargo build --target "$TARGET" --release --features 'pcre2'
PCRE2_SYS_STATIC=1 "$CARGO" build --target "$TARGET" --release --features 'pcre2'
fi
}

View File

@@ -7,11 +7,13 @@ set -ex
. "$(dirname $0)/utils.sh"
main() {
CARGO="$(builder)"
# Test a normal debug build.
if is_arm; then
cargo build --target "$TARGET" --verbose
"$CARGO" build --target "$TARGET" --verbose
else
cargo build --target "$TARGET" --verbose --all --features 'pcre2'
"$CARGO" build --target "$TARGET" --verbose --all --features 'pcre2'
fi
# Show the output of the most recent build.rs stderr.
@@ -44,7 +46,7 @@ main() {
"$(dirname "${0}")/test_complete.sh"
# Run tests for ripgrep and all sub-crates.
cargo test --target "$TARGET" --verbose --all --features 'pcre2'
"$CARGO" test --target "$TARGET" --verbose --all --features 'pcre2'
}
main

View File

@@ -55,6 +55,13 @@ gcc_prefix() {
esac
}
is_musl() {
case "$TARGET" in
*-musl) return 0 ;;
*) return 1 ;;
esac
}
is_x86() {
case "$(architecture)" in
amd64|i386) return 0 ;;
@@ -62,6 +69,13 @@ is_x86() {
esac
}
is_x86_64() {
case "$(architecture)" in
amd64) return 0 ;;
*) return 1 ;;
esac
}
is_arm() {
case "$(architecture)" in
armhf) return 0 ;;
@@ -82,3 +96,12 @@ is_osx() {
*) return 1 ;;
esac
}
builder() {
if is_musl && is_x86_64; then
cargo install cross
echo "cross"
else
echo "cargo"
fi
}

View File

@@ -1,6 +1,6 @@
[package]
name = "grep-cli"
version = "0.1.1" #:version
version = "0.1.2" #:version
authors = ["Andrew Gallant <jamslam@gmail.com>"]
description = """
Utilities for search oriented command line applications.

View File

@@ -2,10 +2,12 @@ use std::error;
use std::ffi::OsStr;
use std::fmt;
use std::fs::File;
use std::io::{self, BufRead};
use std::io;
use std::path::Path;
use std::str;
use bstr::io::BufReadExt;
use escape::{escape, escape_os};
/// An error that occurs when a pattern could not be converted to valid UTF-8.
@@ -156,28 +158,22 @@ pub fn patterns_from_stdin() -> io::Result<Vec<String>> {
/// ```
pub fn patterns_from_reader<R: io::Read>(rdr: R) -> io::Result<Vec<String>> {
let mut patterns = vec![];
let mut bufrdr = io::BufReader::new(rdr);
let mut line = vec![];
let mut line_number = 0;
while {
line.clear();
io::BufReader::new(rdr).for_byte_line(|line| {
line_number += 1;
bufrdr.read_until(b'\n', &mut line)? > 0
} {
line.pop().unwrap(); // remove trailing '\n'
if line.last() == Some(&b'\r') {
line.pop().unwrap();
}
match pattern_from_bytes(&line) {
Ok(pattern) => patterns.push(pattern.to_string()),
match pattern_from_bytes(line.as_bytes()) {
Ok(pattern) => {
patterns.push(pattern.to_string());
Ok(true)
}
Err(err) => {
return Err(io::Error::new(
Err(io::Error::new(
io::ErrorKind::Other,
format!("{}: {}", line_number, err),
));
))
}
}
}
})?;
Ok(patterns)
}

View File

@@ -1029,7 +1029,7 @@ impl<'a, M: Matcher, W: WriteColor> StandardImpl<'a, M, W> {
let mut count = 0;
let mut stepper = LineStep::new(line_term, 0, bytes.len());
while let Some((start, end)) = stepper.next(bytes) {
let mut line = Match::new(start, end);
let line = Match::new(start, end);
self.write_prelude(
self.sunk.absolute_byte_offset() + line.start() as u64,
self.sunk.line_number().map(|n| n + count),
@@ -1105,7 +1105,6 @@ impl<'a, M: Matcher, W: WriteColor> StandardImpl<'a, M, W> {
let spec = self.config().colors.matched();
let bytes = self.sunk.bytes();
for &m in self.sunk.matches() {
let mut m = m;
let mut count = 0;
let mut stepper = LineStep::new(line_term, 0, bytes.len());
while let Some((start, end)) = stepper.next(bytes) {

View File

@@ -1,6 +1,6 @@
[package]
name = "grep"
version = "0.2.3" #:version
version = "0.2.4" #:version
authors = ["Andrew Gallant <jamslam@gmail.com>"]
description = """
Fast line oriented regex searching as a library.
@@ -13,7 +13,7 @@ keywords = ["regex", "grep", "egrep", "search", "pattern"]
license = "Unlicense/MIT"
[dependencies]
grep-cli = { version = "0.1.1", path = "../grep-cli" }
grep-cli = { version = "0.1.2", path = "../grep-cli" }
grep-matcher = { version = "0.1.2", path = "../grep-matcher" }
grep-pcre2 = { version = "0.1.3", path = "../grep-pcre2", optional = true }
grep-printer = { version = "0.1.2", path = "../grep-printer" }

View File

@@ -197,7 +197,12 @@ impl Ignore {
errs.maybe_push(err);
igtmp.is_absolute_parent = true;
igtmp.absolute_base = Some(absolute_base.clone());
igtmp.has_git = parent.join(".git").exists();
igtmp.has_git =
if self.0.opts.git_ignore {
parent.join(".git").exists()
} else {
false
};
ig = Ignore(Arc::new(igtmp));
compiled.insert(parent.as_os_str().to_os_string(), ig.clone());
}
@@ -275,6 +280,12 @@ impl Ignore {
errs.maybe_push(err);
m
};
let has_git =
if self.0.opts.git_ignore {
dir.join(".git").exists()
} else {
false
};
let ig = IgnoreInner {
compiled: self.0.compiled.clone(),
dir: dir.to_path_buf(),
@@ -290,7 +301,7 @@ impl Ignore {
git_global_matcher: self.0.git_global_matcher.clone(),
git_ignore_matcher: gi_matcher,
git_exclude_matcher: gi_exclude_matcher,
has_git: dir.join(".git").exists(),
has_git: has_git,
opts: self.0.opts,
};
(ig, errs.into_error_option())

View File

@@ -146,6 +146,7 @@ const DEFAULT_TYPES: &'static [(&'static str, &'static [&'static str])] = &[
"*.f90", "*.F90", "*.f95", "*.F95",
]),
("fsharp", &["*.fs", "*.fsx", "*.fsi"]),
("gap", &["*.g", "*.gap", "*.gi", "*.gd", "*.tst"]),
("gn", &["*.gn", "*.gni"]),
("go", &["*.go"]),
("gzip", &["*.gz", "*.tgz"]),

View File

@@ -1,14 +1,14 @@
class RipgrepBin < Formula
version '0.10.0'
version '11.0.1'
desc "Recursively search directories for a regex pattern."
homepage "https://github.com/BurntSushi/ripgrep"
if OS.mac?
url "https://github.com/BurntSushi/ripgrep/releases/download/#{version}/ripgrep-#{version}-x86_64-apple-darwin.tar.gz"
sha256 "32754b4173ac87a7bfffd436d601a49362676eb1841ab33440f2f49c002c8967"
sha256 "92446c6b28b6c726f91ad66a03bcd533fc6e1a28ef4b44c27bfe2d49a0f88531"
elsif OS.linux?
url "https://github.com/BurntSushi/ripgrep/releases/download/#{version}/ripgrep-#{version}-x86_64-unknown-linux-musl.tar.gz"
sha256 "c76080aa807a339b44139885d77d15ad60ab8cdd2c2fdaf345d0985625bc0f97"
sha256 "ce74cabac9b39b1ad55837ec01e2c670fa7e965772ac2647b209e31ead19008c"
end
conflicts_with "ripgrep"

View File

@@ -36,6 +36,7 @@ use ignore::{Walk, WalkBuilder, WalkParallel};
use log;
use num_cpus;
use regex;
use snafu::{self, ResultExt};
use termcolor::{
WriteColor,
BufferWriter, ColorChoice,
@@ -43,6 +44,7 @@ use termcolor::{
use crate::app;
use crate::config;
use crate::err::{self, Result};
use crate::logger::Logger;
use crate::messages::{set_messages, set_ignore_messages};
use crate::path_printer::{PathPrinter, PathPrinterBuilder};
@@ -50,7 +52,6 @@ use crate::search::{
PatternMatcher, Printer, SearchWorker, SearchWorkerBuilder,
};
use crate::subject::SubjectBuilder;
use crate::Result;
/// The command that ripgrep should execute based on the command line
/// configuration.
@@ -141,9 +142,7 @@ impl Args {
set_messages(!early_matches.is_present("no-messages"));
set_ignore_messages(!early_matches.is_present("no-ignore-messages"));
if let Err(err) = Logger::init() {
return Err(format!("failed to initialize logger: {}", err).into());
}
Logger::init()?;
if early_matches.is_present("trace") {
log::set_max_level(log::LevelFilter::Trace);
} else if early_matches.is_present("debug") {
@@ -422,13 +421,22 @@ impl SortBy {
match self.kind {
SortByKind::None | SortByKind::Path => {}
SortByKind::LastModified => {
env::current_exe()?.metadata()?.modified()?;
env::current_exe()
.and_then(|x| x.metadata())
.and_then(|x| x.modified())
.context(err::UnsupportedSortModified)?;
}
SortByKind::LastAccessed => {
env::current_exe()?.metadata()?.accessed()?;
env::current_exe()
.and_then(|x| x.metadata())
.and_then(|x| x.accessed())
.context(err::UnsupportedSortAccess)?;
}
SortByKind::Created => {
env::current_exe()?.metadata()?.created()?;
env::current_exe()
.and_then(|x| x.metadata())
.and_then(|x| x.created())
.context(err::UnsupportedSortCreation)?;
}
}
Ok(())
@@ -611,21 +619,12 @@ impl ArgMatches {
Ok(matcher) => return Ok(PatternMatcher::PCRE2(matcher)),
Err(err) => err,
};
Err(From::from(format!(
"regex could not be compiled with either the default regex \
engine or with PCRE2.\n\n\
default regex engine error:\n{}\n{}\n{}\n\n\
PCRE2 regex engine error:\n{}",
"~".repeat(79), rust_err, "~".repeat(79), pcre_err,
)))
err::Hybrid {
rust_err: Box::new(rust_err),
pcre_err: Box::new(pcre_err),
}.fail()
} else {
let matcher = match self.matcher_rust(patterns) {
Ok(matcher) => matcher,
Err(err) => {
return Err(From::from(suggest_pcre2(err.to_string())));
}
};
Ok(PatternMatcher::RustRegex(matcher))
Ok(PatternMatcher::RustRegex(self.matcher_rust(patterns)?))
}
}
@@ -635,11 +634,7 @@ impl ArgMatches {
/// then this returns an error.
#[cfg(not(feature = "pcre2"))]
fn matcher(&self, patterns: &[String]) -> Result<PatternMatcher> {
if self.is_present("pcre2") {
return Err(From::from(
"PCRE2 is not available in this build of ripgrep",
));
}
snafu::ensure!(!self.is_present("pcre2"), err::PCRE2Unavailable);
let matcher = self.matcher_rust(patterns)?;
Ok(PatternMatcher::RustRegex(matcher))
}
@@ -692,10 +687,7 @@ impl ArgMatches {
} else {
builder.build(&patterns.join("|"))
};
match res {
Ok(m) => Ok(m),
Err(err) => Err(From::from(suggest_multiline(err.to_string()))),
}
res.eager_context(err::RustRegex)
}
/// Build a matcher using PCRE2.
@@ -737,7 +729,7 @@ impl ArgMatches {
if self.is_present("crlf") {
builder.crlf(true);
}
Ok(builder.build(&patterns.join("|"))?)
Ok(builder.build(&patterns.join("|")).context(err::PCRE2Regex)?)
}
/// Build a JSON printer that writes results to the given writer.
@@ -987,7 +979,7 @@ impl ArgMatches {
// Start with a default set of color specs.
let mut specs = default_color_specs();
for spec_str in self.values_of_lossy_vec("colors") {
specs.push(spec_str.parse()?);
specs.push(spec_str.parse().context(err::InvalidColorSpec)?);
}
Ok(ColorSpecs::new(&specs))
}
@@ -1078,7 +1070,8 @@ impl ArgMatches {
return Ok(EncodingMode::Disabled);
}
Ok(EncodingMode::Some(Encoding::new(&label)?))
let enc = Encoding::new(&label).context(err::SearchConfig)?;
Ok(EncodingMode::Some(enc))
}
/// Return the file separator to use based on the CLI configuration.
@@ -1267,16 +1260,17 @@ impl ArgMatches {
/// Builds the set of glob overrides from the command line flags.
fn overrides(&self) -> Result<Override> {
let mut builder = OverrideBuilder::new(env::current_dir()?);
let cwd = env::current_dir().context(err::CurrentDir)?;
let mut builder = OverrideBuilder::new(cwd);
for glob in self.values_of_lossy_vec("glob") {
builder.add(&glob)?;
builder.add(&glob).context(err::InvalidGlobFlag)?;
}
// This only enables case insensitivity for subsequent globs.
builder.case_insensitive(true).unwrap();
for glob in self.values_of_lossy_vec("iglob") {
builder.add(&glob)?;
builder.add(&glob).context(err::InvalidIGlobFlag)?;
}
Ok(builder.build()?)
Ok(builder.build().context(err::GlobBuild)?)
}
/// Return all file paths that ripgrep should search.
@@ -1330,16 +1324,10 @@ impl ArgMatches {
};
if sep.is_empty() {
Ok(None)
} else if sep.len() > 1 {
Err(From::from(format!(
"A path separator must be exactly one byte, but \
the given separator is {} bytes: {}\n\
In some shells on Windows '/' is automatically \
expanded. Use '//' instead.",
sep.len(),
cli::escape(&sep),
)))
} else {
snafu::ensure!(sep.len() == 1, err::InvalidPathSeparator {
separator: sep.clone(),
});
Ok(Some(sep[0]))
}
}
@@ -1386,17 +1374,17 @@ impl ArgMatches {
}
if let Some(paths) = self.values_of_os("file") {
for path in paths {
if path == "-" {
pats.extend(cli::patterns_from_stdin()?
.into_iter()
.map(|p| self.pattern_from_string(p))
);
} else {
pats.extend(cli::patterns_from_path(path)?
.into_iter()
.map(|p| self.pattern_from_string(p))
);
}
let some_pats =
if path == "-" {
cli::patterns_from_stdin()
.context(err::ReadManyPatterns)?
} else {
cli::patterns_from_path(path)
.context(err::ReadManyPatterns)?
};
pats.extend(
some_pats.into_iter().map(|p| self.pattern_from_string(p))
);
}
}
Ok(pats)
@@ -1417,7 +1405,7 @@ impl ArgMatches {
///
/// If the pattern is not valid UTF-8, then an error is returned.
fn pattern_from_os_str(&self, pat: &OsStr) -> Result<String> {
let s = cli::pattern_from_os(pat)?;
let s = cli::pattern_from_os(pat).context(err::ReadOSPattern)?;
Ok(self.pattern_from_str(s))
}
@@ -1475,11 +1463,12 @@ impl ArgMatches {
/// flag. If no --pre-globs are available, then this always returns an
/// empty set of globs.
fn preprocessor_globs(&self) -> Result<Override> {
let mut builder = OverrideBuilder::new(env::current_dir()?);
let cwd = env::current_dir().context(err::CurrentDir)?;
let mut builder = OverrideBuilder::new(cwd);
for glob in self.values_of_lossy_vec("pre-glob") {
builder.add(&glob)?;
builder.add(&glob).context(err::InvalidPreGlob)?;
}
Ok(builder.build()?)
Ok(builder.build().context(err::PreGlobBuild)?)
}
/// Parse the regex-size-limit argument option into a byte count.
@@ -1561,7 +1550,7 @@ impl ArgMatches {
builder.clear(&ty);
}
for def in self.values_of_lossy_vec("type-add") {
builder.add_def(&def)?;
builder.add_def(&def).context(err::InvalidTypeDefinition)?;
}
for ty in self.values_of_lossy_vec("type") {
builder.select(&ty);
@@ -1569,7 +1558,7 @@ impl ArgMatches {
for ty in self.values_of_lossy_vec("type-not") {
builder.negate(&ty);
}
builder.build().map_err(From::from)
builder.build().eager_context(err::TypeDefinitionBuild)
}
/// Returns the number of times the `unrestricted` flag is provided.
@@ -1628,7 +1617,11 @@ impl ArgMatches {
fn usize_of(&self, name: &str) -> Result<Option<usize>> {
match self.value_of_lossy(name) {
None => Ok(None),
Some(v) => v.parse().map(Some).map_err(From::from),
Some(v) => {
v.parse()
.map(Some)
.eager_context(err::InvalidNumber { flag: name.to_string() })
}
}
}
@@ -1636,15 +1629,17 @@ impl ArgMatches {
///
/// If the aforementioned format is not recognized, then this returns an
/// error.
fn parse_human_readable_size(
&self,
arg_name: &str,
) -> Result<Option<u64>> {
let size = match self.value_of_lossy(arg_name) {
None => return Ok(None),
Some(size) => size,
};
Ok(Some(cli::parse_human_readable_size(&size)?))
fn parse_human_readable_size(&self, name: &str) -> Result<Option<u64>> {
match self.value_of_lossy(name) {
None => Ok(None),
Some(size) => {
cli::parse_human_readable_size(&size)
.map(Some)
.eager_context(err::InvalidHumanSize {
flag: name.to_string()
})
}
}
}
}
@@ -1678,32 +1673,6 @@ impl ArgMatches {
}
}
/// Inspect an error resulting from building a Rust regex matcher, and if it's
/// believed to correspond to a syntax error that PCRE2 could handle, then
/// add a message to suggest the use of -P/--pcre2.
#[cfg(feature = "pcre2")]
fn suggest_pcre2(msg: String) -> String {
if !msg.contains("backreferences") && !msg.contains("look-around") {
msg
} else {
format!("{}
Consider enabling PCRE2 with the --pcre2 flag, which can handle backreferences
and look-around.", msg)
}
}
fn suggest_multiline(msg: String) -> String {
if msg.contains("the literal") && msg.contains("not allowed") {
format!("{}
Consider enabling multiline mode with the --multiline flag (or -U for short).
When multiline mode is enabled, new line characters can be matched.", msg)
} else {
msg
}
}
/// Convert the result of parsing a human readable file size to a `usize`,
/// failing if the type does not fit.
fn u64_to_usize(
@@ -1716,11 +1685,14 @@ fn u64_to_usize(
None => return Ok(None),
Some(value) => value,
};
if value <= usize::MAX as u64 {
Ok(Some(value as usize))
} else {
Err(From::from(format!("number too large for {}", arg_name)))
}
snafu::ensure!(
value <= usize::MAX as u64,
err::NumberTooBig {
flag: arg_name.to_string(),
limit: usize::MAX as u64,
}
);
Ok(Some(value as usize))
}
/// Builds a comparator for sorting two files according to a system time
@@ -1768,7 +1740,7 @@ where I: IntoIterator<Item=T>,
Err(err) => err,
};
if err.use_stderr() {
return Err(err.into());
return Err(snafu::Context { error: err, context: err::Clap }.into());
}
// Explicitly ignore any error returned by write!. The most likely error
// at this point is a broken pipe error, in which case, we want to ignore

View File

@@ -3,7 +3,6 @@
// argument corresponds precisely to one shell argument.
use std::env;
use std::error::Error;
use std::fs::File;
use std::io;
use std::ffi::OsString;
@@ -11,8 +10,9 @@ use std::path::{Path, PathBuf};
use bstr::io::BufReadExt;
use log;
use snafu::{self, ResultExt};
use crate::Result;
use crate::err::{self, Error, Result};
/// Return a sequence of arguments derived from ripgrep rc configuration files.
pub fn args() -> Vec<OsString> {
@@ -55,12 +55,11 @@ pub fn args() -> Vec<OsString> {
/// for each line in addition to successfully parsed arguments.
fn parse<P: AsRef<Path>>(
path: P,
) -> Result<(Vec<OsString>, Vec<Box<Error>>)> {
) -> Result<(Vec<OsString>, Vec<Error>)> {
let path = path.as_ref();
match File::open(&path) {
Ok(file) => parse_reader(file),
Err(err) => Err(From::from(format!("{}: {}", path.display(), err))),
}
let file = File::open(&path).context(err::ConfigIO { path })?;
let res = parse_reader(file).context(err::ConfigIO { path })?;
Ok(res)
}
/// Parse a single ripgrep rc file from the given reader.
@@ -76,10 +75,10 @@ fn parse<P: AsRef<Path>>(
/// in addition to successfully parsed arguments.
fn parse_reader<R: io::Read>(
rdr: R,
) -> Result<(Vec<OsString>, Vec<Box<Error>>)> {
) -> io::Result<(Vec<OsString>, Vec<Error>)> {
let bufrdr = io::BufReader::new(rdr);
let (mut args, mut errs) = (vec![], vec![]);
let mut line_number = 0;
let mut line_number = 0u64;
bufrdr.for_byte_line_with_terminator(|line| {
line_number += 1;
@@ -92,7 +91,11 @@ fn parse_reader<R: io::Read>(
args.push(osstr.to_os_string());
}
Err(err) => {
errs.push(format!("{}: {}", line_number, err).into());
let ctx = snafu::Context {
error: err,
context: err::ConfigInvalidUTF8 { line_number },
};
errs.push(ctx.into());
}
}
Ok(true)

250
src/err.rs Normal file
View File

@@ -0,0 +1,250 @@
use std::io;
use std::path::{Path, PathBuf};
use std::result;
use snafu::{Backtrace, Context, Snafu};
pub type Result<T> = result::Result<T, Error>;
#[derive(Debug, Snafu)]
#[snafu(visibility(pub(crate)))]
pub enum Error {
#[snafu(display("I/O error: {}", source))]
IO {
backtrace: Backtrace,
source: io::Error,
},
#[snafu(display(
"failed to retrieve current working directory: {}", source,
))]
CurrentDir {
backtrace: Backtrace,
source: io::Error,
},
#[snafu(display("sorting by modified time is unsupported: {}", source))]
UnsupportedSortModified {
backtrace: Backtrace,
source: io::Error,
},
#[snafu(display("sorting by access time is unsupported: {}", source))]
UnsupportedSortAccess {
backtrace: Backtrace,
source: io::Error,
},
#[snafu(display("sorting by creation time is unsupported: {}", source))]
UnsupportedSortCreation {
backtrace: Backtrace,
source: io::Error,
},
#[snafu(display(
"I/O error parsing config in {}: {}",
path.display(),
source,
))]
ConfigIO {
backtrace: Backtrace,
source: io::Error,
path: PathBuf,
},
#[snafu(display(
"config parse error on line {}: {}",
line_number,
source,
))]
ConfigInvalidUTF8 {
backtrace: Backtrace,
source: bstr::Utf8Error,
line_number: u64,
},
#[snafu(display("failed to initialize logger: {}", source))]
LoggerInit {
backtrace: Backtrace,
source: log::SetLoggerError,
},
#[snafu(display("{}", source))]
Clap {
backtrace: Backtrace,
source: clap::Error,
},
#[snafu(display("{}", source))]
ReadManyPatterns {
backtrace: Backtrace,
source: io::Error,
},
#[snafu(display("{}", source))]
ReadOSPattern {
backtrace: Backtrace,
source: grep::cli::InvalidPatternError,
},
#[snafu(display(
"A path separator must be exactly one byte, but \
the given separator is {} bytes: {}\n\
In some shells on Windows '/' is automatically \
expanded. Use '//' instead.",
separator.len(), grep::cli::escape(&separator),
))]
InvalidPathSeparator {
backtrace: Backtrace,
separator: Vec<u8>,
},
#[snafu(display("error parsing -g/--glob: {}", source))]
InvalidGlobFlag {
backtrace: Backtrace,
source: ignore::Error,
},
#[snafu(display("error parsing --iglob: {}", source))]
InvalidIGlobFlag {
backtrace: Backtrace,
source: ignore::Error,
},
#[snafu(display("error building --glob matcher: {}", source))]
GlobBuild {
backtrace: Backtrace,
source: ignore::Error,
},
#[snafu(display("error parsing --pre-glob: {}", source))]
InvalidPreGlob {
backtrace: Backtrace,
source: ignore::Error,
},
#[snafu(display("error building --pre-glob matcher: {}", source))]
PreGlobBuild {
backtrace: Backtrace,
source: ignore::Error,
},
#[snafu(display("error parsing --type-add value: {}", source))]
InvalidTypeDefinition {
backtrace: Backtrace,
source: ignore::Error,
},
#[snafu(display("error building type matcher: {}", source))]
TypeDefinitionBuild {
backtrace: Backtrace,
source: ignore::Error,
},
#[snafu(display("failed to parse {} value as a number: {}", flag, source))]
InvalidNumber {
backtrace: Backtrace,
source: std::num::ParseIntError,
flag: String,
},
#[snafu(display(
"failed to parse {} value as a file size: {}", flag, source,
))]
InvalidHumanSize {
backtrace: Backtrace,
source: grep::cli::ParseSizeError,
flag: String,
},
#[snafu(display(
"number given to {} is too large (limit is {})",
flag, limit,
))]
NumberTooBig {
backtrace: Backtrace,
flag: String,
limit: u64,
},
#[snafu(display("{}", source))]
SearchConfig {
backtrace: Backtrace,
source: grep::searcher::ConfigError,
},
#[snafu(display("invalid --colors spec: {}", source))]
InvalidColorSpec {
backtrace: Backtrace,
source: grep::printer::ColorError,
},
#[snafu(display("{}", suggest(source)))]
RustRegex {
backtrace: Backtrace,
source: grep::regex::Error,
},
#[snafu(display(
"regex could not be compiled with either the default regex \
engine or with PCRE2.\n\n\
default regex engine error:\n{}\n{}\n{}\n\n\
PCRE2 regex engine error:\n{}",
"~".repeat(79),
rust_err,
"~".repeat(79),
pcre_err,
))]
Hybrid {
backtrace: Backtrace,
rust_err: Box<Error>,
pcre_err: Box<Error>,
},
#[snafu(display("failed to write type definitions to stdout: {}", source))]
WriteTypes {
backtrace: Backtrace,
source: io::Error,
},
#[cfg(feature = "pcre2")]
#[snafu(display("{}", suggest(source)))]
PCRE2Regex {
backtrace: Backtrace,
source: grep::pcre2::Error,
},
#[snafu(display("PCRE2 is not available in this build of ripgrep"))]
PCRE2Unavailable {
backtrace: Backtrace,
},
#[snafu(display("failed to write PCRE2 version to stdout: {}", source))]
PCRE2Version {
backtrace: Backtrace,
source: io::Error,
},
}
impl Error {
/// Return true if and only if this corresponds to an I/O error generated
/// by a broken pipe.
pub fn is_broken_pipe(&self) -> bool {
self.io_err().map_or(false, |e| e.kind() == io::ErrorKind::BrokenPipe)
}
/// Return a reference to this error's underlying I/O error, if one exists.
pub fn io_err(&self) -> Option<&io::Error> {
match *self {
Error::IO { ref source, .. } => Some(source),
Error::CurrentDir { ref source, .. } => Some(source),
Error::UnsupportedSortModified { ref source, .. } => Some(source),
Error::UnsupportedSortAccess { ref source, .. } => Some(source),
Error::UnsupportedSortCreation { ref source, .. } => Some(source),
Error::ConfigIO { ref source, .. } => Some(source),
Error::ReadManyPatterns { ref source, .. } => Some(source),
Error::WriteTypes { ref source, .. } => Some(source),
Error::PCRE2Version { ref source, .. } => Some(source),
_ => None,
}
}
}
/// Inspect an error's display string and look for potentially suggestions
/// to give to an end user.
///
/// These include:
///
/// 1. If the error results from the use of a new line literal, then return a
/// new message suggesting the use of the -U/--multiline flag.
/// 2. If the error correspond to a syntax error that PCRE2 could handle, then
/// add a message to suggest the use of -P/--pcre2.
fn suggest<E: std::error::Error>(err: &E) -> String {
let msg = err.to_string();
if msg.contains("the literal") && msg.contains("not allowed") {
format!("{}
Consider enabling multiline mode with the --multiline flag (or -U for short).
When multiline mode is enabled, new line characters can be matched.", msg)
} else if cfg!(feature = "pcre2") &&
(msg.contains("backreferences") || msg.contains("look-around"))
{
format!("{}
Consider enabling PCRE2 with the --pcre2 flag, which can handle backreferences
and look-around.", msg)
} else {
msg
}
}

View File

@@ -4,6 +4,9 @@
// for this functionality.
use log::{self, Log};
use snafu::ResultExt;
use crate::err::{self, Result};
/// The simplest possible logger that logs to stderr.
///
@@ -18,8 +21,8 @@ impl Logger {
/// Create a new logger that logs to stderr and initialize it as the
/// global logger. If there was a problem setting the logger, then an
/// error is returned.
pub fn init() -> Result<(), log::SetLoggerError> {
log::set_logger(LOGGER)
pub fn init() -> Result<()> {
log::set_logger(LOGGER).eager_context(err::LoggerInit)
}
}

View File

@@ -1,11 +1,15 @@
#![allow(warnings)]
use std::io::{self, Write};
use std::process;
use std::sync::{Arc, Mutex};
use std::time::Instant;
use ignore::WalkState;
use snafu::ResultExt;
use args::Args;
use err::Result;
use subject::Subject;
#[macro_use]
@@ -14,12 +18,37 @@ mod messages;
mod app;
mod args;
mod config;
mod err;
mod logger;
mod path_printer;
mod search;
mod subject;
type Result<T> = ::std::result::Result<T, Box<::std::error::Error>>;
// Since Rust no longer uses jemalloc by default, ripgrep will, by default,
// use the system allocator. On Linux, this would normally be glibc's
// allocator, which is pretty good. In particular, ripgrep does not have a
// particularly allocation heavy workload, so there really isn't much
// difference (for ripgrep's purposes) between glibc's allocator and jemalloc.
//
// However, when ripgrep is built with musl, this means ripgrep will use musl's
// allocator, which appears to be substantially worse. (musl's goal is not to
// have the fastest version of everything. Its goal is to be small and amenable
// to static compilation.) Even though ripgrep isn't particularly allocation
// heavy, musl's allocator appears to slow down ripgrep quite a bit. Therefore,
// when building with musl, we use jemalloc.
//
// We don't unconditionally use jemalloc because it can be nice to use the
// system's default allocator by default. Moreover, jemalloc seems to increase
// compilation times by a bit.
//
// Moreover, we only do this on 64-bit systems since jemalloc doesn't support
// i686.
#[cfg(all(target_env = "musl", target_pointer_width = "64"))]
#[global_allocator]
static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;
// type Result<T> = ::std::result::Result<T, Box<::std::error::Error>>;
// type Result<T> =
fn main() {
if let Err(err) = Args::parse().and_then(try_main) {
@@ -190,12 +219,12 @@ fn files(args: &Args) -> Result<bool> {
}
if let Err(err) = path_printer.write_path(subject.path()) {
// A broken pipe means graceful termination.
if err.kind() == io::ErrorKind::BrokenPipe {
if err.is_broken_pipe() {
break;
}
// Otherwise, we have some other error that's preventing us from
// writing to stdout, so we should bubble it up.
return Err(err.into());
return Err(err);
}
}
Ok(matched)
@@ -216,7 +245,7 @@ fn files_parallel(args: &Args) -> Result<bool> {
let matched = Arc::new(AtomicBool::new(false));
let (tx, rx) = mpsc::channel::<Subject>();
let print_thread = thread::spawn(move || -> io::Result<()> {
let print_thread = thread::spawn(move || -> Result<()> {
for subject in rx.iter() {
path_printer.write_path(subject.path())?;
}
@@ -248,8 +277,8 @@ fn files_parallel(args: &Args) -> Result<bool> {
// A broken pipe means graceful termination, so fall through.
// Otherwise, something bad happened while writing to stdout, so bubble
// it up.
if err.kind() != io::ErrorKind::BrokenPipe {
return Err(err.into());
if !err.is_broken_pipe() {
return Err(err);
}
}
Ok(matched.load(SeqCst))
@@ -257,22 +286,29 @@ fn files_parallel(args: &Args) -> Result<bool> {
/// The top-level entry point for --type-list.
fn types(args: &Args) -> Result<bool> {
write_types(args.stdout(), &args.type_defs()?)
.eager_context(err::WriteTypes)
}
fn write_types<W: io::Write>(
mut wtr: W,
defs: &[ignore::types::FileTypeDef],
) -> io::Result<bool> {
let mut count = 0;
let mut stdout = args.stdout();
for def in args.type_defs()? {
for def in defs {
count += 1;
stdout.write_all(def.name().as_bytes())?;
stdout.write_all(b": ")?;
wtr.write_all(def.name().as_bytes())?;
wtr.write_all(b": ")?;
let mut first = true;
for glob in def.globs() {
if !first {
stdout.write_all(b", ")?;
wtr.write_all(b", ")?;
}
stdout.write_all(glob.as_bytes())?;
wtr.write_all(glob.as_bytes())?;
first = false;
}
stdout.write_all(b"\n")?;
wtr.write_all(b"\n")?;
}
Ok(count > 0)
}
@@ -280,7 +316,7 @@ fn types(args: &Args) -> Result<bool> {
/// The top-level entry point for --pcre2-version.
fn pcre2_version(args: &Args) -> Result<bool> {
#[cfg(feature = "pcre2")]
fn imp(args: &Args) -> Result<bool> {
fn imp(args: &Args) -> io::Result<bool> {
use grep::pcre2;
let mut stdout = args.stdout();
@@ -295,11 +331,11 @@ fn pcre2_version(args: &Args) -> Result<bool> {
}
#[cfg(not(feature = "pcre2"))]
fn imp(args: &Args) -> Result<bool> {
fn imp(args: &Args) -> io::Result<bool> {
let mut stdout = args.stdout();
writeln!(stdout, "PCRE2 is not available in this build of ripgrep.")?;
Ok(false)
}
imp(args)
imp(args).eager_context(err::PCRE2Version)
}

View File

@@ -2,8 +2,11 @@ use std::io;
use std::path::Path;
use grep::printer::{ColorSpecs, PrinterPath};
use snafu::ResultExt;
use termcolor::WriteColor;
use crate::err::{self, Result};
/// A configuration for describing how paths should be written.
#[derive(Clone, Debug)]
struct Config {
@@ -87,7 +90,11 @@ pub struct PathPrinter<W> {
impl<W: WriteColor> PathPrinter<W> {
/// Write the given path to the underlying writer.
pub fn write_path(&mut self, path: &Path) -> io::Result<()> {
pub fn write_path(&mut self, path: &Path) -> Result<()> {
self.write(path).eager_context(err::IO)
}
fn write(&mut self, path: &Path) -> io::Result<()> {
let ppath = PrinterPath::with_separator(path, self.config.separator);
if !self.wtr.supports_color() {
self.wtr.write_all(ppath.as_bytes())?;

View File

@@ -392,8 +392,8 @@ rgtest!(r428_unrecognized_style, |_: Dir, mut cmd: TestCommand| {
let output = cmd.cmd().output().unwrap();
let stderr = String::from_utf8_lossy(&output.stderr);
let expected = "\
unrecognized style attribute ''. Choose from: nobold, bold, nointense, \
intense, nounderline, underline.
invalid --colors spec: unrecognized style attribute ''. \
Choose from: nobold, bold, nointense, intense, nounderline, underline.
";
eqnice!(expected, stderr);
});
@@ -705,3 +705,14 @@ rgtest!(r1203_reverse_suffix_literal, |dir: Dir, _: TestCommand| {
let mut cmd = dir.command();
eqnice!("153.230000\n", cmd.arg(r"\d\d\d000").arg("test").stdout());
});
// See: https://github.com/BurntSushi/ripgrep/issues/1259
rgtest!(r1259_drop_last_byte_nonl, |dir: Dir, mut cmd: TestCommand| {
dir.create("patterns-nonl", "[foo]");
dir.create("patterns-nl", "[foo]\n");
dir.create("test", "fz");
eqnice!("fz\n", cmd.arg("-f").arg("patterns-nonl").arg("test").stdout());
cmd = dir.command();
eqnice!("fz\n", cmd.arg("-f").arg("patterns-nl").arg("test").stdout());
});