Compare commits

..

1 Commits

Author SHA1 Message Date
Andrew Gallant
7bf7ceb5d3 progress 2019-05-29 18:07:03 -04:00
53 changed files with 1381 additions and 1168 deletions

View File

@@ -1,99 +0,0 @@
# test
name: ci
on:
pull_request:
push:
branches:
- master
schedule:
- cron: '00 01 * * *'
jobs:
test:
name: test
runs-on: ${{ matrix.os }}
strategy:
matrix:
# The docs seem to suggest that we can have a matrix with just an
# include directive, but it result in a "matrix must define at least
# one vector" error in the CI system.
build:
- pinned-glibc
- pinned-musl
- stable
- beta
# We test musl with nightly because every once in a while, this will
# catch an upstream regression.
- nightly-glibc
- nightly-musl
- macos
- win-msvc-32
- win-msvc-64
- win-gnu-32
- win-gnu-64
include:
# - build: pinned-glibc
# os: ubuntu-18.04
# rust: 1.34.0
# target: x86_64-unknown-linux-gnu
- build: pinned-musl
os: ubuntu-18.04
rust: 1.34.0
target: x86_64-unknown-linux-musl
- build: stable
os: ubuntu-18.04
rust: stable
target: x86_64-unknown-linux-gnu
# - build: beta
# os: ubuntu-18.04
# rust: beta
# target: x86_64-unknown-linux-gnu
# - build: nightly-glibc
# os: ubuntu-18.04
# rust: nightly
# target: x86_64-unknown-linux-gnu
# - build: nightly-musl
# os: ubuntu-18.04
# rust: nightly
# target: x86_64-unknown-linux-musl
# - build: macos
# os: macOS-10.14
# rust: stable
# target: x86_64-apple-darwin
# - build: win-msvc-32
# os: windows-2019
# rust: stable
# target: i686-pc-windows-msvc
# - build: win-msvc-64
# os: windows-2019
# rust: stable
# target: x86_64-pc-windows-msvc
# - build: win-gnu-32
# os: windows-2019
# rust: stable-i686-gnu
# target: i686-pc-windows-gnu
# - build: win-gnu-64
# os: windows-2019
# rust: stable-x86_64-gnu
# target: x86_64-pc-windows-gnu
steps:
- name: Checkout repository
uses: actions/checkout@v1
with:
fetch-depth: 1
- name: Install Rust
uses: hecrj/setup-rust-action@v1
with:
rust-version: ${{ matrix.rust }}
- name: Install Rust Target
run: rustup target add ${{ matrix.target }}
# - name: Install musl-gcc
# if: contains(matrix.target, 'musl')
# run: |
# apt-get install musl-tools
- name: Build everything
run: cargo build --verbose --target ${{ matrix.target }} --all --features pcre2
- name: Test zsh auto-completions
if: matrix.build == 'stable'
run: ./ci/test_complete.sh
- name: Run tests
run: cargo test --verbose --target ${{ matrix.target }} --all --features pcre2

View File

@@ -1,42 +1,11 @@
TBD
===
TODO
TODO.
Bug fixes:
* [BUG #1335](https://github.com/BurntSushi/ripgrep/issues/1335):
Fixes a performance bug when searching plain text files with very long lines.
11.0.2 (2019-08-01)
===================
ripgrep 11.0.2 is a new patch release that fixes a few bugs, including a
performance regression and a matching bug when using the `-F/--fixed-strings`
flag.
Feature enhancements:
* [FEATURE #1293](https://github.com/BurntSushi/ripgrep/issues/1293):
Added `--glob-case-insensitive` flag that makes `--glob` behave as `--iglob`.
Bug fixes:
* [BUG #1246](https://github.com/BurntSushi/ripgrep/issues/1246):
Add translations to README, starting with an unofficial Chinese translation.
* [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`.
* [BUG #1261](https://github.com/BurntSushi/ripgrep/issues/1261):
Document that no error is reported when searching for `\n` with `-P/--pcre2`.
* [BUG #1284](https://github.com/BurntSushi/ripgrep/issues/1284):
Mention `.ignore` and `.rgignore` more prominently in the README.
* [BUG #1292](https://github.com/BurntSushi/ripgrep/issues/1292):
Fix bug where `--with-filename` was sometimes enabled incorrectly.
* [BUG #1268](https://github.com/BurntSushi/ripgrep/issues/1268):
Fix major performance regression in GitHub `x86_64-linux` binary release.
* [BUG #1302](https://github.com/BurntSushi/ripgrep/issues/1302):
Show better error messages when a non-existent preprocessor command is given.
* [BUG #1334](https://github.com/BurntSushi/ripgrep/issues/1334):
Fix match regression with `-F` flag when patterns contain meta characters.
11.0.1 (2019-04-16)

657
Cargo.lock generated
View File

@@ -2,19 +2,47 @@
# It is not intended for manual editing.
[[package]]
name = "aho-corasick"
version = "0.7.6"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "atty"
version = "0.2.13"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
"termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
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]]
@@ -22,22 +50,22 @@ name = "base64"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "bitflags"
version = "1.1.0"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bstr"
version = "0.2.7"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-automata 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -47,17 +75,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "byteorder"
version = "1.3.2"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cc"
version = "1.0.41"
version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cfg-if"
version = "0.1.9"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -65,27 +93,36 @@ name = "clap"
version = "2.33.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "cloudabi"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crossbeam-channel"
version = "0.3.9"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crossbeam-utils"
version = "0.6.6"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -93,7 +130,7 @@ name = "encoding_rs"
version = "0.8.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"packed_simd 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -115,6 +152,11 @@ 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"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "glob"
version = "0.3.0"
@@ -122,164 +164,166 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "globset"
version = "0.4.4"
version = "0.4.3"
dependencies = [
"aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
"bstr 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
"bstr 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"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.8 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.2.1 (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.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "grep"
version = "0.2.4"
dependencies = [
"grep-cli 0.1.3",
"grep-matcher 0.1.3",
"grep-cli 0.1.2",
"grep-matcher 0.1.2",
"grep-pcre2 0.1.3",
"grep-printer 0.1.3",
"grep-regex 0.1.5",
"grep-searcher 0.1.6",
"termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
"grep-printer 0.1.2",
"grep-regex 0.1.3",
"grep-searcher 0.1.4",
"termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "grep-cli"
version = "0.1.3"
version = "0.1.2"
dependencies = [
"atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
"bstr 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"globset 0.4.4",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"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.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)",
]
[[package]]
name = "grep-matcher"
version = "0.1.3"
version = "0.1.2"
dependencies = [
"memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.2.1 (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.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "grep-pcre2"
version = "0.1.3"
dependencies = [
"grep-matcher 0.1.3",
"pcre2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"grep-matcher 0.1.2",
"pcre2 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "grep-printer"
version = "0.1.3"
version = "0.1.2"
dependencies = [
"base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
"bstr 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"grep-matcher 0.1.3",
"grep-regex 0.1.5",
"grep-searcher 0.1.6",
"serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
"termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"bstr 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"grep-matcher 0.1.2",
"grep-regex 0.1.3",
"grep-searcher 0.1.4",
"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)",
"termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "grep-regex"
version = "0.1.5"
version = "0.1.3"
dependencies = [
"aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
"grep-matcher 0.1.3",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
"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.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)",
]
[[package]]
name = "grep-searcher"
version = "0.1.6"
version = "0.1.4"
dependencies = [
"bstr 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"bstr 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"bytecount 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
"encoding_rs_io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"grep-matcher 0.1.3",
"grep-regex 0.1.5",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"grep-matcher 0.1.2",
"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.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ignore"
version = "0.4.10"
version = "0.4.7"
dependencies = [
"crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"globset 0.4.4",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-channel 0.3.8 (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)",
"memchr 2.2.0 (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)",
"walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
"walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "itoa"
version = "0.4.4"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "jemalloc-sys"
version = "0.3.2"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)",
"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.62 (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.2"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"jemalloc-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"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.4.0"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.2.62"
version = "0.2.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "log"
version = "0.4.8"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "memchr"
version = "2.2.1"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -287,16 +331,16 @@ name = "memmap"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num_cpus"
version = "1.10.1"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -304,102 +348,237 @@ name = "packed_simd"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "pcre2"
version = "0.2.1"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"pcre2-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"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.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.2"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"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)",
"pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "pkg-config"
version = "0.3.15"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "proc-macro2"
version = "1.0.1"
version = "0.4.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "quote"
version = "1.0.2"
version = "0.6.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_chacha"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_core"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_core"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rand_hc"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_isaac"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_jitter"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_os"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_pcg"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_xorshift"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rdrand"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "redox_syscall"
version = "0.1.54"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "redox_termios"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex"
version = "1.2.1"
version = "1.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
"aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.2.0 (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)",
]
[[package]]
name = "regex-automata"
version = "0.1.8"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex-syntax"
version = "0.6.11"
version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "ripgrep"
version = "11.0.2"
dependencies = [
"bstr 0.2.7 (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.4",
"ignore 0.4.10",
"jemallocator 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
"termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "remove_dir_all"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ripgrep"
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.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.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 = "1.0.0"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "same-file"
version = "1.0.5"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -407,27 +586,51 @@ dependencies = [
[[package]]
name = "serde"
version = "1.0.99"
version = "1.0.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde_derive"
version = "1.0.99"
version = "1.0.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"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 = "serde_json"
version = "1.0.40"
version = "1.0.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
"itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
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]]
@@ -437,20 +640,43 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "syn"
version = "1.0.5"
version = "0.15.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"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)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tempfile"
version = "3.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"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)",
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)",
"remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "termcolor"
version = "1.0.5"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "termion"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -458,7 +684,7 @@ name = "textwrap"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -466,32 +692,42 @@ name = "thread_local"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ucd-util"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicode-width"
version = "0.1.6"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicode-xid"
version = "0.2.0"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "utf8-ranges"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "walkdir"
version = "2.2.9"
version = "2.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi"
version = "0.3.8"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -508,7 +744,7 @@ name = "winapi-util"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -518,64 +754,91 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "wincolor"
version = "1.0.2"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[metadata]
"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d"
"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90"
"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.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd"
"checksum bstr 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94cdf78eb7e94c566c1f5dbe2abf8fc70a548fc902942a48c4b3a98b48ca9ade"
"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"
"checksum bytecount 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be0fdd54b507df8f22012890aadd099979befdba27713c767993f8380112ca7c"
"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
"checksum cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "8dae9c4b8fedcae85592ba623c4fd08cfdab3e3b72d6df780c6ead964a69bfff"
"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33"
"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb"
"checksum cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)" = "5e5f3fee5eeb60324c2781f1e41286bdee933850fff9b3c672587fed5ec58c83"
"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4"
"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
"checksum crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa"
"checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6"
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
"checksum crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f0ed1a4de2235cabda8558ff5840bffb97fcb64c97827f354a451307df5f72b"
"checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c"
"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.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f"
"checksum jemalloc-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0d3b9f3f5c9b31aa0f5ed3260385ac205db665baa41d49bb8338008ae94ede45"
"checksum jemallocator 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "43ae63fcfc45e99ab3d1b29a46782ad679e98436c3169d15a167a1108a724b69"
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba"
"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e"
"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"
"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39"
"checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b"
"checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273"
"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.1 (registry+https://github.com/rust-lang/crates.io-index)" = "603da5e101220b9b306bf28e4f1f8703458ce2f64d2787b374e1a19494317180"
"checksum pcre2-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "876c72d05059d23a84bd9fcdc3b1d31c50ea7fe00fe1522b4e68cd3608db8d5b"
"checksum pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c1d2cfa5a714db3b5f24f0915e74fcdf91d09d496ba61329705dda7774d2af"
"checksum proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c5c2380ae88876faae57698be9e9775e3544decad214599c3a6266cca6ac802"
"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
"checksum regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88c3d9193984285d544df4a30c23a4e62ead42edf70a4452ceb76dac1ce05c26"
"checksum regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "92b73c2a1770c255c240eaa4ee600df1704a38dc3feaa6e949e7fcd4f8dc09f9"
"checksum regex-syntax 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b143cceb2ca5e56d5671988ef8b15615733e7ee16cd348e064333b251b89343f"
"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997"
"checksum same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421"
"checksum serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "fec2851eb56d010dc9a21b89ca53ee75e6528bab60c11e89d38390904982da9f"
"checksum serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "cb4dc18c61206b08dc98216c98faa0232f4337e1e1b8574551d5bad29ea1b425"
"checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704"
"checksum pcre2 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a08c8195dd1d8a2a1b5e2af94bf0c4c3c195c2359930442a016bf123196f7155"
"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"
"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0"
"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
"checksum rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9ea758282efe12823e0d952ddb269d2e1897227e464919a554f2a03ef1b832"
"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
"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.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 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf"
"checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e"
"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"
"checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f"
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20"
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
"checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e"
"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86"
"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737"
"checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1"
"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
"checksum wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "96f5016b18804d24db43cebf3c77269e7569b8954a8464501c216cc5e070eaa9"
"checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba"

View File

@@ -1,11 +1,11 @@
[package]
name = "ripgrep"
version = "11.0.2" #: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
directory for a regex pattern while respecting your gitignore rules. ripgrep
has first class support on Windows, macOS and Linux.
has first class support on Windows, macOS and Linux
"""
documentation = "https://github.com/BurntSushi/ripgrep"
homepage = "https://github.com/BurntSushi/ripgrep"
@@ -46,14 +46,15 @@ members = [
]
[dependencies]
bstr = "0.2.0"
bstr = "0.1.2"
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]

View File

@@ -1,2 +0,0 @@
[target.x86_64-unknown-linux-musl]
image = "burntsushi/x86_64-unknown-linux-musl:v0.1.14"

View File

@@ -110,7 +110,7 @@ colors, you'll notice that `faster` will be highlighted instead of just the
It is beyond the scope of this guide to provide a full tutorial on regular
expressions, but ripgrep's specific syntax is documented here:
https://docs.rs/regex/*/regex/#syntax
https://docs.rs/regex/0.2.5/regex/#syntax
### Recursive search

View File

@@ -29,7 +29,6 @@ Please see the [CHANGELOG](CHANGELOG.md) for a release history.
* [Configuration files](GUIDE.md#configuration-file)
* [Shell completions](FAQ.md#complete)
* [Building](#building)
* [Translations](#translations)
### Screenshot of search results
@@ -93,11 +92,11 @@ increases the times to `2.640s` for ripgrep and `10.277s` for GNU grep.
[the FAQ](FAQ.md#posix4ever) for more details on whether ripgrep can truly
replace grep.)
* Like other tools specialized to code search, ripgrep defaults to recursive
directory search and won't search files ignored by your
`.gitignore`/`.ignore`/`.rgignore` files. It also ignores hidden and binary
files by default. ripgrep also implements full support for `.gitignore`,
whereas there are many bugs related to that functionality in other code
search tools claiming to provide the same functionality.
directory search and won't search files ignored by your `.gitignore` files.
It also ignores hidden and binary files by default. ripgrep also implements
full support for `.gitignore`, whereas there are many bugs related to that
functionality in other code search tools claiming to provide the same
functionality.
* ripgrep can search specific types of files. For example, `rg -tpy foo`
limits your search to Python files and `rg -Tjs foo` excludes Javascript
files from your search. ripgrep can be taught about new file types with
@@ -225,7 +224,7 @@ $ choco install ripgrep
```
If you're a **Windows Scoop** user, then you can install ripgrep from the
[official bucket](https://github.com/ScoopInstaller/Main/blob/master/bucket/ripgrep.json):
[official bucket](https://github.com/lukesampson/scoop/blob/master/bucket/ripgrep.json):
```
$ scoop install ripgrep
@@ -288,11 +287,11 @@ 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/11.0.2/ripgrep_11.0.2_amd64.deb
$ sudo dpkg -i ripgrep_11.0.2_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 stable) or Debian sid, ripgrep is
If you run Debian Buster (currently Debian testing) or Debian sid, ripgrep is
[officially maintained by Debian](https://tracker.debian.org/pkg/rust-ripgrep).
```
$ sudo apt-get install ripgrep
@@ -419,11 +418,3 @@ $ cargo test --all
```
from the repository root.
### Translations
The following is a list of known translations of ripgrep's documentation. These
are unofficially maintained and may not be up to date.
* [Chinese](https://github.com/chinanf-boy/ripgrep-zh#%E6%9B%B4%E6%96%B0-)

View File

@@ -1,5 +0,0 @@
FROM japaric/x86_64-unknown-linux-musl:v0.1.14
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
libxslt1-dev asciidoc docbook-xsl xsltproc libxml2-utils

View File

@@ -104,10 +104,6 @@ _rg() {
'*'{-g+,--glob=}'[include/exclude files matching specified glob]:glob'
'*--iglob=[include/exclude files matching specified case-insensitive glob]:glob'
+ '(glob-case-insensitive)' # File-glob case sensitivity options
'--glob-case-insensitive[treat -g/--glob patterns case insensitively]'
$no'--no-glob-case-insensitive[treat -g/--glob patterns case sensitively]'
+ '(heading)' # Heading options
'(pretty-vimgrep)--heading[show matches grouped by file name]'
"(pretty-vimgrep)--no-heading[don't show matches grouped by file name]"

View File

@@ -143,16 +143,16 @@ would behave identically to the following command
same with using globs
--glob=!.git
--glob=!git/*
or
--glob
!.git
!git/*
would behave identically to the following command
rg --glob '!.git' foo
rg --glob '!git/*' foo
ripgrep also provides a flag, *--no-config*, that when present will suppress
any and all support for configuration. This includes any future support

View File

@@ -1,6 +1,6 @@
[package]
name = "globset"
version = "0.4.4" #:version
version = "0.4.3" #:version
authors = ["Andrew Gallant <jamslam@gmail.com>"]
description = """
Cross platform single glob and glob set matching. Glob set matching is the
@@ -20,7 +20,7 @@ bench = false
[dependencies]
aho-corasick = "0.7.3"
bstr = { version = "0.2.0", default-features = false, features = ["std"] }
bstr = { version = "0.1.2", default-features = false, features = ["std"] }
fnv = "1.0.6"
log = "0.4.5"
regex = "1.1.5"

View File

@@ -120,7 +120,7 @@ impl GlobMatcher {
/// Tests whether the given path matches this pattern or not.
pub fn is_match_candidate(&self, path: &Candidate) -> bool {
self.re.is_match(&path.path)
self.re.is_match(path.path.as_bytes())
}
}
@@ -145,7 +145,7 @@ impl GlobStrategic {
/// Tests whether the given path matches this pattern or not.
fn is_match_candidate(&self, candidate: &Candidate) -> bool {
let byte_path = &*candidate.path;
let byte_path = candidate.path.as_bytes();
match self.strategy {
MatchStrategy::Literal(ref lit) => lit.as_bytes() == byte_path,

View File

@@ -119,7 +119,7 @@ use std::path::Path;
use std::str;
use aho_corasick::AhoCorasick;
use bstr::{B, ByteSlice, ByteVec};
use bstr::{B, BStr, BString};
use regex::bytes::{Regex, RegexBuilder, RegexSet};
use pathutil::{file_name, file_name_ext, normalize_path};
@@ -490,15 +490,15 @@ impl GlobSetBuilder {
/// path against multiple globs or sets of globs.
#[derive(Clone, Debug)]
pub struct Candidate<'a> {
path: Cow<'a, [u8]>,
basename: Cow<'a, [u8]>,
ext: Cow<'a, [u8]>,
path: Cow<'a, BStr>,
basename: Cow<'a, BStr>,
ext: Cow<'a, BStr>,
}
impl<'a> Candidate<'a> {
/// Create a new candidate for matching from the given path.
pub fn new<P: AsRef<Path> + ?Sized>(path: &'a P) -> Candidate<'a> {
let path = normalize_path(Vec::from_path_lossy(path.as_ref()));
let path = normalize_path(BString::from_path_lossy(path.as_ref()));
let basename = file_name(&path).unwrap_or(Cow::Borrowed(B("")));
let ext = file_name_ext(&basename).unwrap_or(Cow::Borrowed(B("")));
Candidate {
@@ -508,7 +508,7 @@ impl<'a> Candidate<'a> {
}
}
fn path_prefix(&self, max: usize) -> &[u8] {
fn path_prefix(&self, max: usize) -> &BStr {
if self.path.len() <= max {
&*self.path
} else {
@@ -516,7 +516,7 @@ impl<'a> Candidate<'a> {
}
}
fn path_suffix(&self, max: usize) -> &[u8] {
fn path_suffix(&self, max: usize) -> &BStr {
if self.path.len() <= max {
&*self.path
} else {

View File

@@ -1,15 +1,15 @@
use std::borrow::Cow;
use bstr::{ByteSlice, ByteVec};
use bstr::BStr;
/// The final component of the path, if it is a normal file.
///
/// If the path terminates in ., .., or consists solely of a root of prefix,
/// file_name will return None.
pub fn file_name<'a>(path: &Cow<'a, [u8]>) -> Option<Cow<'a, [u8]>> {
pub fn file_name<'a>(path: &Cow<'a, BStr>) -> Option<Cow<'a, BStr>> {
if path.is_empty() {
return None;
} else if path.last_byte() == Some(b'.') {
} else if path.last() == Some(b'.') {
return None;
}
let last_slash = path.rfind_byte(b'/').map(|i| i + 1).unwrap_or(0);
@@ -39,7 +39,7 @@ pub fn file_name<'a>(path: &Cow<'a, [u8]>) -> Option<Cow<'a, [u8]>> {
/// a pattern like `*.rs` is obviously trying to match files with a `rs`
/// extension, but it also matches files like `.rs`, which doesn't have an
/// extension according to std::path::Path::extension.
pub fn file_name_ext<'a>(name: &Cow<'a, [u8]>) -> Option<Cow<'a, [u8]>> {
pub fn file_name_ext<'a>(name: &Cow<'a, BStr>) -> Option<Cow<'a, BStr>> {
if name.is_empty() {
return None;
}
@@ -60,7 +60,7 @@ pub fn file_name_ext<'a>(name: &Cow<'a, [u8]>) -> Option<Cow<'a, [u8]>> {
/// Normalizes a path to use `/` as a separator everywhere, even on platforms
/// that recognize other characters as separators.
#[cfg(unix)]
pub fn normalize_path(path: Cow<[u8]>) -> Cow<[u8]> {
pub fn normalize_path(path: Cow<BStr>) -> Cow<BStr> {
// UNIX only uses /, so we're good.
path
}
@@ -68,7 +68,7 @@ pub fn normalize_path(path: Cow<[u8]>) -> Cow<[u8]> {
/// Normalizes a path to use `/` as a separator everywhere, even on platforms
/// that recognize other characters as separators.
#[cfg(not(unix))]
pub fn normalize_path(mut path: Cow<[u8]>) -> Cow<[u8]> {
pub fn normalize_path(mut path: Cow<BStr>) -> Cow<BStr> {
use std::path::is_separator;
for i in 0..path.len() {
@@ -84,7 +84,7 @@ pub fn normalize_path(mut path: Cow<[u8]>) -> Cow<[u8]> {
mod tests {
use std::borrow::Cow;
use bstr::{B, ByteVec};
use bstr::{B, BString};
use super::{file_name_ext, normalize_path};
@@ -92,7 +92,7 @@ mod tests {
($name:ident, $file_name:expr, $ext:expr) => {
#[test]
fn $name() {
let bs = Vec::from($file_name);
let bs = BString::from($file_name);
let got = file_name_ext(&Cow::Owned(bs));
assert_eq!($ext.map(|s| Cow::Borrowed(B(s))), got);
}
@@ -109,7 +109,7 @@ mod tests {
($name:ident, $path:expr, $expected:expr) => {
#[test]
fn $name() {
let bs = Vec::from_slice($path);
let bs = BString::from_slice($path);
let got = normalize_path(Cow::Owned(bs));
assert_eq!($expected.to_vec(), got.into_owned());
}

View File

@@ -1,6 +1,6 @@
[package]
name = "grep-cli"
version = "0.1.3" #:version
version = "0.1.2" #:version
authors = ["Andrew Gallant <jamslam@gmail.com>"]
description = """
Utilities for search oriented command line applications.
@@ -14,7 +14,7 @@ license = "Unlicense/MIT"
[dependencies]
atty = "0.2.11"
bstr = "0.2.0"
bstr = "0.1.2"
globset = { version = "0.4.3", path = "../globset" }
lazy_static = "1.1.0"
log = "0.4.5"

View File

@@ -1,7 +1,7 @@
use std::ffi::OsStr;
use std::str;
use bstr::{ByteSlice, ByteVec};
use bstr::{BStr, BString};
/// A single state in the state machine used by `unescape`.
#[derive(Clone, Copy, Eq, PartialEq)]
@@ -38,6 +38,7 @@ enum State {
/// assert_eq!(r"foo\nbar\xFFbaz", escape(b"foo\nbar\xFFbaz"));
/// ```
pub fn escape(bytes: &[u8]) -> String {
let bytes = BStr::new(bytes);
let mut escaped = String::new();
for (s, e, ch) in bytes.char_indices() {
if ch == '\u{FFFD}' {
@@ -55,7 +56,7 @@ pub fn escape(bytes: &[u8]) -> String {
///
/// This is like [`escape`](fn.escape.html), but accepts an OS string.
pub fn escape_os(string: &OsStr) -> String {
escape(Vec::from_os_str_lossy(string).as_bytes())
escape(BString::from_os_str_lossy(string).as_bytes())
}
/// Unescapes a string.
@@ -110,7 +111,7 @@ pub fn unescape(s: &str) -> Vec<u8> {
}
HexFirst => {
match c {
'0'..='9' | 'A'..='F' | 'a'..='f' => {
'0'...'9' | 'A'...'F' | 'a'...'f' => {
state = HexSecond(c);
}
c => {
@@ -121,7 +122,7 @@ pub fn unescape(s: &str) -> Vec<u8> {
}
HexSecond(first) => {
match c {
'0'..='9' | 'A'..='F' | 'a'..='f' => {
'0'...'9' | 'A'...'F' | 'a'...'f' => {
let ordinal = format!("{}{}", first, c);
let byte = u8::from_str_radix(&ordinal, 16).unwrap();
bytes.push(byte);
@@ -173,7 +174,7 @@ fn escape_char(cp: char, into: &mut String) {
/// Adds the given byte to the given string, escaping it if necessary.
fn escape_byte(byte: u8, into: &mut String) {
match byte {
0x21..=0x5B | 0x5D..=0x7D => into.push(byte as char),
0x21...0x5B | 0x5D...0x7D => into.push(byte as char),
b'\n' => into.push_str(r"\n"),
b'\r' => into.push_str(r"\r"),
b'\t' => into.push_str(r"\t"),

View File

@@ -161,7 +161,7 @@ pub fn patterns_from_reader<R: io::Read>(rdr: R) -> io::Result<Vec<String>> {
let mut line_number = 0;
io::BufReader::new(rdr).for_byte_line(|line| {
line_number += 1;
match pattern_from_bytes(line) {
match pattern_from_bytes(line.as_bytes()) {
Ok(pattern) => {
patterns.push(pattern.to_string());
Ok(true)

View File

@@ -1,6 +1,6 @@
[package]
name = "grep-matcher"
version = "0.1.3" #:version
version = "0.1.2" #:version
authors = ["Andrew Gallant <jamslam@gmail.com>"]
description = """
A trait for regular expressions, with a focus on line oriented search.

View File

@@ -134,7 +134,7 @@ fn find_cap_ref(replacement: &[u8]) -> Option<CaptureRef> {
/// Returns true if and only if the given byte is allowed in a capture name.
fn is_valid_cap_letter(b: &u8) -> bool {
match *b {
b'0' ..= b'9' | b'a' ..= b'z' | b'A' ..= b'Z' | b'_' => true,
b'0' ... b'9' | b'a' ... b'z' | b'A' ... b'Z' | b'_' => true,
_ => false,
}
}

View File

@@ -1,6 +1,6 @@
[package]
name = "grep-printer"
version = "0.1.3" #:version
version = "0.1.2" #:version
authors = ["Andrew Gallant <jamslam@gmail.com>"]
description = """
An implementation of the grep crate's Sink trait that provides standard
@@ -19,7 +19,7 @@ serde1 = ["base64", "serde", "serde_derive", "serde_json"]
[dependencies]
base64 = { version = "0.10.0", optional = true }
bstr = "0.2.0"
bstr = "0.1.2"
grep-matcher = { version = "0.1.2", path = "../grep-matcher" }
grep-searcher = { version = "0.1.4", path = "../grep-searcher" }
termcolor = "1.0.4"

View File

@@ -5,7 +5,7 @@ use std::path::Path;
use std::sync::Arc;
use std::time::Instant;
use bstr::ByteSlice;
use bstr::BStr;
use grep_matcher::{Match, Matcher};
use grep_searcher::{
LineStep, Searcher,
@@ -1274,7 +1274,7 @@ impl<'a, M: Matcher, W: WriteColor> StandardImpl<'a, M, W> {
) -> io::Result<()> {
if self.config().max_columns_preview {
let original = line;
let end = bytes[line]
let end = BStr::new(&bytes[line])
.grapheme_indices()
.map(|(_, end, _)| end)
.take(self.config().max_columns.unwrap_or(0) as usize)
@@ -1396,7 +1396,7 @@ impl<'a, M: Matcher, W: WriteColor> StandardImpl<'a, M, W> {
}
let remainder = format!(
"after match (found {:?} byte around offset {})\n",
[byte].as_bstr(), offset,
BStr::new(&[byte]), offset,
);
self.write(remainder.as_bytes())?;
} else if let Some(byte) = bin.convert_byte() {
@@ -1407,7 +1407,7 @@ impl<'a, M: Matcher, W: WriteColor> StandardImpl<'a, M, W> {
}
let remainder = format!(
"matches (found {:?} byte around offset {})\n",
[byte].as_bstr(), offset,
BStr::new(&[byte]), offset,
);
self.write(remainder.as_bytes())?;
}

View File

@@ -4,7 +4,7 @@ use std::io;
use std::path::Path;
use std::time;
use bstr::{ByteSlice, ByteVec};
use bstr::{BStr, BString};
use grep_matcher::{Captures, LineTerminator, Match, Matcher};
use grep_searcher::{
LineIter,
@@ -263,12 +263,12 @@ impl<'a> Sunk<'a> {
/// portability with a small cost: on Windows, paths that are not valid UTF-16
/// will not roundtrip correctly.
#[derive(Clone, Debug)]
pub struct PrinterPath<'a>(Cow<'a, [u8]>);
pub struct PrinterPath<'a>(Cow<'a, BStr>);
impl<'a> PrinterPath<'a> {
/// Create a new path suitable for printing.
pub fn new(path: &'a Path) -> PrinterPath<'a> {
PrinterPath(Vec::from_path_lossy(path))
PrinterPath(BString::from_path_lossy(path))
}
/// Create a new printer path from the given path which can be efficiently
@@ -289,7 +289,7 @@ impl<'a> PrinterPath<'a> {
/// path separators that are both replaced by `new_sep`. In all other
/// environments, only `/` is treated as a path separator.
fn replace_separator(&mut self, new_sep: u8) {
let transformed_path: Vec<u8> = self.0.bytes().map(|b| {
let transformed_path: BString = self.0.bytes().map(|b| {
if b == b'/' || (cfg!(windows) && b == b'\\') {
new_sep
} else {
@@ -301,7 +301,7 @@ impl<'a> PrinterPath<'a> {
/// Return the raw bytes for this path.
pub fn as_bytes(&self) -> &[u8] {
&self.0
self.0.as_bytes()
}
}

View File

@@ -1,6 +1,6 @@
[package]
name = "grep-regex"
version = "0.1.5" #:version
version = "0.1.3" #:version
authors = ["Andrew Gallant <jamslam@gmail.com>"]
description = """
Use Rust's regex library with the 'grep' crate.
@@ -19,3 +19,4 @@ log = "0.4.5"
regex = "1.1"
regex-syntax = "0.6.5"
thread_local = "0.3.6"
utf8-ranges = "1.0.1"

View File

@@ -11,6 +11,7 @@ extern crate log;
extern crate regex;
extern crate regex_syntax;
extern crate thread_local;
extern crate utf8_ranges;
pub use error::{Error, ErrorKind};
pub use matcher::{RegexCaptures, RegexMatcher, RegexMatcherBuilder};

View File

@@ -71,31 +71,10 @@ impl RegexMatcherBuilder {
&self,
literals: &[B],
) -> Result<RegexMatcher, Error> {
let mut has_escape = false;
let mut slices = vec![];
for lit in literals {
slices.push(lit.as_ref());
has_escape = has_escape || lit.as_ref().contains('\\');
}
// Even when we have a fixed set of literals, we might still want to
// use the regex engine. Specifically, if any string has an escape
// in it, then we probably can't feed it to Aho-Corasick without
// removing the escape. Additionally, if there are any particular
// special match semantics we need to honor, that Aho-Corasick isn't
// enough. Finally, the regex engine can do really well with a small
// number of literals (at time of writing, this is changing soon), so
// we use it when there's a small set.
//
// Yes, this is one giant hack. Ideally, this entirely separate literal
// matcher that uses Aho-Corasick would be pushed down into the regex
// engine.
if has_escape
|| !self.config.can_plain_aho_corasick()
|| literals.len() < 40
{
let slices: Vec<_> = literals.iter().map(|s| s.as_ref()).collect();
if !self.config.can_plain_aho_corasick() || literals.len() < 40 {
return self.build(&slices.join("|"));
}
let matcher = MultiLiteralMatcher::new(&slices)?;
let imp = RegexMatcherImpl::MultiLiteral(matcher);
Ok(RegexMatcher {

View File

@@ -1,6 +1,6 @@
use grep_matcher::ByteSet;
use regex_syntax::hir::{self, Hir, HirKind};
use regex_syntax::utf8::Utf8Sequences;
use utf8_ranges::Utf8Sequences;
/// Return a confirmed set of non-matching bytes from the given expression.
pub fn non_matching_bytes(expr: &Hir) -> ByteSet {

View File

@@ -1,6 +1,6 @@
[package]
name = "grep-searcher"
version = "0.1.6" #:version
version = "0.1.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]
bstr = { version = "0.2.0", default-features = false, features = ["std"] }
bstr = { version = "0.1.2", default-features = false, features = ["std"] }
bytecount = "0.5"
encoding_rs = "0.8.14"
encoding_rs_io = "0.1.6"

View File

@@ -17,7 +17,7 @@ fn main() {
}
}
fn example() -> Result<(), Box<dyn Error>> {
fn example() -> Result<(), Box<Error>> {
let pattern = match env::args().nth(1) {
Some(pattern) => pattern,
None => return Err(From::from(format!(

View File

@@ -1,7 +1,7 @@
use std::cmp;
use std::io;
use bstr::ByteSlice;
use bstr::{BStr, BString};
/// The default buffer capacity that we use for the line buffer.
pub(crate) const DEFAULT_BUFFER_CAPACITY: usize = 8 * (1<<10); // 8 KB
@@ -122,7 +122,7 @@ impl LineBufferBuilder {
pub fn build(&self) -> LineBuffer {
LineBuffer {
config: self.config,
buf: vec![0; self.config.capacity],
buf: BString::from(vec![0; self.config.capacity]),
pos: 0,
last_lineterm: 0,
end: 0,
@@ -254,14 +254,13 @@ impl<'b, R: io::Read> LineBufferReader<'b, R> {
/// Return the contents of this buffer.
pub fn buffer(&self) -> &[u8] {
self.line_buffer.buffer()
self.line_buffer.buffer().as_bytes()
}
/// Return the buffer as a BStr, used for convenient equality checking
/// in tests only.
/// Return the underlying buffer as a byte string. Used for tests only.
#[cfg(test)]
fn bstr(&self) -> &::bstr::BStr {
self.buffer().as_bstr()
fn bstr(&self) -> &BStr {
self.line_buffer.buffer()
}
/// Consume the number of bytes provided. This must be less than or equal
@@ -290,7 +289,7 @@ pub struct LineBuffer {
/// The configuration of this buffer.
config: Config,
/// The primary buffer with which to hold data.
buf: Vec<u8>,
buf: BString,
/// The current position of this buffer. This is always a valid sliceable
/// index into `buf`, and its maximum value is the length of `buf`.
pos: usize,
@@ -353,13 +352,13 @@ impl LineBuffer {
}
/// Return the contents of this buffer.
fn buffer(&self) -> &[u8] {
fn buffer(&self) -> &BStr {
&self.buf[self.pos..self.last_lineterm]
}
/// Return the contents of the free space beyond the end of the buffer as
/// a mutable slice.
fn free_buffer(&mut self) -> &mut [u8] {
fn free_buffer(&mut self) -> &mut BStr {
&mut self.buf[self.end..]
}
@@ -482,7 +481,7 @@ impl LineBuffer {
}
let roll_len = self.end - self.pos;
self.buf.copy_within_str(self.pos..self.end, 0);
self.buf.copy_within(self.pos.., 0);
self.pos = 0;
self.last_lineterm = roll_len;
self.end = roll_len;
@@ -520,7 +519,7 @@ impl LineBuffer {
/// Replaces `src` with `replacement` in bytes, and return the offset of the
/// first replacement, if one exists.
fn replace_bytes(bytes: &mut [u8], src: u8, replacement: u8) -> Option<usize> {
fn replace_bytes(bytes: &mut BStr, src: u8, replacement: u8) -> Option<usize> {
if src == replacement {
return None;
}
@@ -543,7 +542,7 @@ fn replace_bytes(bytes: &mut [u8], src: u8, replacement: u8) -> Option<usize> {
#[cfg(test)]
mod tests {
use std::str;
use bstr::{ByteSlice, ByteVec};
use bstr::BString;
use super::*;
const SHERLOCK: &'static str = "\
@@ -564,7 +563,7 @@ and exhibited clearly, with a label attached.\
src: u8,
replacement: u8,
) -> (String, Option<usize>) {
let mut dst = Vec::from(slice);
let mut dst = BString::from(slice);
let result = replace_bytes(&mut dst, src, replacement);
(dst.into_string().unwrap(), result)
}
@@ -678,12 +677,12 @@ and exhibited clearly, with a label attached.\
let mut linebuf = LineBufferBuilder::new().capacity(1).build();
let mut rdr = LineBufferReader::new(bytes.as_bytes(), &mut linebuf);
let mut got = vec![];
let mut got = BString::new();
while rdr.fill().unwrap() {
got.push_str(rdr.buffer());
got.push(rdr.buffer());
rdr.consume_all();
}
assert_eq!(bytes, got.as_bstr());
assert_eq!(bytes, got);
assert_eq!(rdr.absolute_byte_offset(), bytes.len() as u64);
assert_eq!(rdr.binary_byte_offset(), None);
}

View File

@@ -2,7 +2,7 @@
A collection of routines for performing operations on lines.
*/
use bstr::ByteSlice;
use bstr::B;
use bytecount;
use grep_matcher::{LineTerminator, Match};
@@ -85,7 +85,7 @@ impl LineStep {
#[inline(always)]
fn next_impl(&mut self, mut bytes: &[u8]) -> Option<(usize, usize)> {
bytes = &bytes[..self.end];
match bytes[self.pos..].find_byte(self.line_term) {
match B(&bytes[self.pos..]).find_byte(self.line_term) {
None => {
if self.pos < bytes.len() {
let m = (self.pos, bytes.len());
@@ -135,14 +135,14 @@ pub fn locate(
line_term: u8,
range: Match,
) -> Match {
let line_start = bytes[..range.start()]
let line_start = B(&bytes[..range.start()])
.rfind_byte(line_term)
.map_or(0, |i| i + 1);
let line_end =
if range.end() > line_start && bytes[range.end() - 1] == line_term {
range.end()
} else {
bytes[range.end()..]
B(&bytes[range.end()..])
.find_byte(line_term)
.map_or(bytes.len(), |i| range.end() + i + 1)
};
@@ -182,7 +182,7 @@ fn preceding_by_pos(
pos -= 1;
}
loop {
match bytes[..pos].rfind_byte(line_term) {
match B(&bytes[..pos]).rfind_byte(line_term) {
None => {
return 0;
}

View File

@@ -1,6 +1,6 @@
use std::cmp;
use bstr::ByteSlice;
use bstr::B;
use grep_matcher::{LineMatchKind, Matcher};
use lines::{self, LineStep};
@@ -161,7 +161,7 @@ impl<'s, M: Matcher, S: Sink> Core<'s, M, S> {
BinaryDetection::Convert(b) => b,
_ => return Ok(false),
};
if let Some(i) = buf[*range].find_byte(binary_byte) {
if let Some(i) = B(&buf[*range]).find_byte(binary_byte) {
let offset = range.start() + i;
self.binary_byte_offset = Some(offset);
if !self.binary_data(offset as u64)? {

View File

@@ -1,4 +1,3 @@
use std::error;
use std::fmt;
use std::io;
@@ -50,9 +49,9 @@ impl SinkError for io::Error {
/// A `Box<std::error::Error>` can be used as an error for `Sink`
/// implementations out of the box.
impl SinkError for Box<dyn error::Error> {
fn error_message<T: fmt::Display>(message: T) -> Box<dyn error::Error> {
Box::<dyn error::Error>::from(message.to_string())
impl SinkError for Box<::std::error::Error> {
fn error_message<T: fmt::Display>(message: T) -> Box<::std::error::Error> {
Box::<::std::error::Error>::from(message.to_string())
}
}

View File

@@ -1,7 +1,7 @@
use std::io::{self, Write};
use std::str;
use bstr::ByteSlice;
use bstr::B;
use grep_matcher::{
LineMatchKind, LineTerminator, Match, Matcher, NoCaptures, NoError,
};
@@ -94,7 +94,7 @@ impl Matcher for RegexMatcher {
}
// Make it interesting and return the last byte in the current
// line.
let i = haystack
let i = B(haystack)
.find_byte(self.line_term.unwrap().as_byte())
.map(|i| i)
.unwrap_or(haystack.len() - 1);

View File

@@ -21,7 +21,7 @@ fn main() {
}
}
fn try_main() -> Result<(), Box<dyn Error>> {
fn try_main() -> Result<(), Box<Error>> {
let mut args: Vec<OsString> = env::args_os().collect();
if args.len() < 2 {
return Err("Usage: simplegrep <pattern> [<path> ...]".into());
@@ -32,7 +32,7 @@ fn try_main() -> Result<(), Box<dyn Error>> {
search(cli::pattern_from_os(&args[1])?, &args[2..])
}
fn search(pattern: &str, paths: &[OsString]) -> Result<(), Box<dyn Error>> {
fn search(pattern: &str, paths: &[OsString]) -> Result<(), Box<Error>> {
let matcher = RegexMatcher::new_line_matcher(&pattern)?;
let mut searcher = SearcherBuilder::new()
.binary_detection(BinaryDetection::quit(b'\x00'))

View File

@@ -1,6 +1,6 @@
[package]
name = "ignore"
version = "0.4.10" #:version
version = "0.4.7" #:version
authors = ["Andrew Gallant <jamslam@gmail.com>"]
description = """
A fast library for efficiently matching ignore files such as `.gitignore`
@@ -31,5 +31,8 @@ walkdir = "2.2.7"
[target.'cfg(windows)'.dependencies.winapi-util]
version = "0.1.2"
[dev-dependencies]
tempfile = "3.0.5"
[features]
simd-accel = ["globset/simd-accel"]

View File

@@ -14,13 +14,13 @@
// well.
use std::collections::HashMap;
use std::ffi::{OsStr, OsString};
use std::ffi::{OsString, OsStr};
use std::path::{Path, PathBuf};
use std::sync::{Arc, RwLock};
use gitignore::{self, Gitignore, GitignoreBuilder};
use overrides::{self, Override};
use pathutil::{is_hidden, strip_prefix};
use overrides::{self, Override};
use types::{self, Types};
use walk::DirEntry;
use {Error, Match, PartialErrorBuilder};
@@ -152,7 +152,10 @@ impl Ignore {
///
/// Note that this can only be called on an `Ignore` matcher with no
/// parents (i.e., `is_root` returns `true`). This will panic otherwise.
pub fn add_parents<P: AsRef<Path>>(&self, path: P) -> (Ignore, Option<Error>) {
pub fn add_parents<P: AsRef<Path>>(
&self,
path: P,
) -> (Ignore, Option<Error>) {
if !self.0.opts.parents
&& !self.0.opts.git_ignore
&& !self.0.opts.git_exclude
@@ -194,11 +197,12 @@ impl Ignore {
errs.maybe_push(err);
igtmp.is_absolute_parent = true;
igtmp.absolute_base = Some(absolute_base.clone());
igtmp.has_git = if self.0.opts.git_ignore {
parent.join(".git").exists()
} else {
false
};
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());
}
@@ -213,7 +217,10 @@ impl Ignore {
/// returned if it exists.
///
/// Note that all I/O errors are completely ignored.
pub fn add_child<P: AsRef<Path>>(&self, dir: P) -> (Ignore, Option<Error>) {
pub fn add_child<P: AsRef<Path>>(
&self,
dir: P,
) -> (Ignore, Option<Error>) {
let (ig, err) = self.add_child_path(dir.as_ref());
(Ignore(Arc::new(ig)), err)
}
@@ -221,49 +228,64 @@ impl Ignore {
/// Like add_child, but takes a full path and returns an IgnoreInner.
fn add_child_path(&self, dir: &Path) -> (IgnoreInner, Option<Error>) {
let mut errs = PartialErrorBuilder::default();
let custom_ig_matcher = if self.0.custom_ignore_filenames.is_empty() {
Gitignore::empty()
} else {
let (m, err) = create_gitignore(
&dir,
&self.0.custom_ignore_filenames,
self.0.opts.ignore_case_insensitive,
);
errs.maybe_push(err);
m
};
let ig_matcher = if !self.0.opts.ignore {
Gitignore::empty()
} else {
let (m, err) =
create_gitignore(&dir, &[".ignore"], self.0.opts.ignore_case_insensitive);
errs.maybe_push(err);
m
};
let gi_matcher = if !self.0.opts.git_ignore {
Gitignore::empty()
} else {
let (m, err) =
create_gitignore(&dir, &[".gitignore"], self.0.opts.ignore_case_insensitive);
errs.maybe_push(err);
m
};
let gi_exclude_matcher = if !self.0.opts.git_exclude {
Gitignore::empty()
} else {
let (m, err) = create_gitignore(
&dir,
&[".git/info/exclude"],
self.0.opts.ignore_case_insensitive,
);
errs.maybe_push(err);
m
};
let has_git = if self.0.opts.git_ignore {
dir.join(".git").exists()
} else {
false
};
let custom_ig_matcher =
if self.0.custom_ignore_filenames.is_empty() {
Gitignore::empty()
} else {
let (m, err) =
create_gitignore(
&dir,
&self.0.custom_ignore_filenames,
self.0.opts.ignore_case_insensitive,
);
errs.maybe_push(err);
m
};
let ig_matcher =
if !self.0.opts.ignore {
Gitignore::empty()
} else {
let (m, err) =
create_gitignore(
&dir,
&[".ignore"],
self.0.opts.ignore_case_insensitive,
);
errs.maybe_push(err);
m
};
let gi_matcher =
if !self.0.opts.git_ignore {
Gitignore::empty()
} else {
let (m, err) =
create_gitignore(
&dir,
&[".gitignore"],
self.0.opts.ignore_case_insensitive,
);
errs.maybe_push(err);
m
};
let gi_exclude_matcher =
if !self.0.opts.git_exclude {
Gitignore::empty()
} else {
let (m, err) =
create_gitignore(
&dir,
&[".git/info/exclude"],
self.0.opts.ignore_case_insensitive,
);
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(),
@@ -291,16 +313,16 @@ impl Ignore {
let has_custom_ignore_files = !self.0.custom_ignore_filenames.is_empty();
let has_explicit_ignores = !self.0.explicit_ignores.is_empty();
opts.ignore
|| opts.git_global
|| opts.git_ignore
|| opts.git_exclude
|| has_custom_ignore_files
|| has_explicit_ignores
opts.ignore || opts.git_global || opts.git_ignore
|| opts.git_exclude || has_custom_ignore_files
|| has_explicit_ignores
}
/// Like `matched`, but works with a directory entry instead.
pub fn matched_dir_entry<'a>(&'a self, dent: &DirEntry) -> Match<IgnoreMatch<'a>> {
pub fn matched_dir_entry<'a>(
&'a self,
dent: &DirEntry,
) -> Match<IgnoreMatch<'a>> {
let m = self.matched(dent.path(), dent.is_dir());
if m.is_none() && self.0.opts.hidden && is_hidden(dent) {
return Match::Ignore(IgnoreMatch::hidden());
@@ -312,7 +334,11 @@ impl Ignore {
/// ignored or not.
///
/// The match contains information about its origin.
fn matched<'a, P: AsRef<Path>>(&'a self, path: P, is_dir: bool) -> Match<IgnoreMatch<'a>> {
fn matched<'a, P: AsRef<Path>>(
&'a self,
path: P,
is_dir: bool,
) -> Match<IgnoreMatch<'a>> {
// We need to be careful with our path. If it has a leading ./, then
// strip it because it causes nothing but trouble.
let mut path = path.as_ref();
@@ -324,11 +350,9 @@ impl Ignore {
// return that result immediately. Overrides have the highest
// precedence.
if !self.0.overrides.is_empty() {
let mat = self
.0
.overrides
.matched(path, is_dir)
.map(IgnoreMatch::overrides);
let mat =
self.0.overrides.matched(path, is_dir)
.map(IgnoreMatch::overrides);
if !mat.is_none() {
return mat;
}
@@ -343,7 +367,8 @@ impl Ignore {
}
}
if !self.0.types.is_empty() {
let mat = self.0.types.matched(path, is_dir).map(IgnoreMatch::types);
let mat =
self.0.types.matched(path, is_dir).map(IgnoreMatch::types);
if mat.is_ignore() {
return mat;
} else if mat.is_whitelist() {
@@ -355,70 +380,61 @@ impl Ignore {
/// Performs matching only on the ignore files for this directory and
/// all parent directories.
fn matched_ignore<'a>(&'a self, path: &Path, is_dir: bool) -> Match<IgnoreMatch<'a>> {
let (mut m_custom_ignore, mut m_ignore, mut m_gi, mut m_gi_exclude, mut m_explicit) = (
Match::None,
Match::None,
Match::None,
Match::None,
Match::None,
);
fn matched_ignore<'a>(
&'a self,
path: &Path,
is_dir: bool,
) -> Match<IgnoreMatch<'a>> {
let (mut m_custom_ignore, mut m_ignore, mut m_gi, mut m_gi_exclude, mut m_explicit) =
(Match::None, Match::None, Match::None, Match::None, Match::None);
let any_git = self.parents().any(|ig| ig.0.has_git);
let mut saw_git = false;
for ig in self.parents().take_while(|ig| !ig.0.is_absolute_parent) {
if m_custom_ignore.is_none() {
m_custom_ignore =
ig.0.custom_ignore_matcher
.matched(path, is_dir)
.map(IgnoreMatch::gitignore);
ig.0.custom_ignore_matcher.matched(path, is_dir)
.map(IgnoreMatch::gitignore);
}
if m_ignore.is_none() {
m_ignore =
ig.0.ignore_matcher
.matched(path, is_dir)
.map(IgnoreMatch::gitignore);
ig.0.ignore_matcher.matched(path, is_dir)
.map(IgnoreMatch::gitignore);
}
if any_git && !saw_git && m_gi.is_none() {
m_gi =
ig.0.git_ignore_matcher
.matched(path, is_dir)
.map(IgnoreMatch::gitignore);
ig.0.git_ignore_matcher.matched(path, is_dir)
.map(IgnoreMatch::gitignore);
}
if any_git && !saw_git && m_gi_exclude.is_none() {
m_gi_exclude =
ig.0.git_exclude_matcher
.matched(path, is_dir)
.map(IgnoreMatch::gitignore);
ig.0.git_exclude_matcher.matched(path, is_dir)
.map(IgnoreMatch::gitignore);
}
saw_git = saw_git || ig.0.has_git;
}
if self.0.opts.parents {
if let Some(abs_parent_path) = self.absolute_base() {
let path = abs_parent_path.join(path);
for ig in self.parents().skip_while(|ig| !ig.0.is_absolute_parent) {
for ig in self.parents().skip_while(|ig|!ig.0.is_absolute_parent) {
if m_custom_ignore.is_none() {
m_custom_ignore =
ig.0.custom_ignore_matcher
.matched(&path, is_dir)
.map(IgnoreMatch::gitignore);
ig.0.custom_ignore_matcher.matched(&path, is_dir)
.map(IgnoreMatch::gitignore);
}
if m_ignore.is_none() {
m_ignore =
ig.0.ignore_matcher
.matched(&path, is_dir)
.map(IgnoreMatch::gitignore);
ig.0.ignore_matcher.matched(&path, is_dir)
.map(IgnoreMatch::gitignore);
}
if any_git && !saw_git && m_gi.is_none() {
m_gi =
ig.0.git_ignore_matcher
.matched(&path, is_dir)
.map(IgnoreMatch::gitignore);
ig.0.git_ignore_matcher.matched(&path, is_dir)
.map(IgnoreMatch::gitignore);
}
if any_git && !saw_git && m_gi_exclude.is_none() {
m_gi_exclude =
ig.0.git_exclude_matcher
.matched(&path, is_dir)
.map(IgnoreMatch::gitignore);
ig.0.git_exclude_matcher.matched(&path, is_dir)
.map(IgnoreMatch::gitignore);
}
saw_git = saw_git || ig.0.has_git;
}
@@ -430,21 +446,16 @@ impl Ignore {
}
m_explicit = gi.matched(&path, is_dir).map(IgnoreMatch::gitignore);
}
let m_global = if any_git {
self.0
.git_global_matcher
.matched(&path, is_dir)
.map(IgnoreMatch::gitignore)
} else {
Match::None
};
let m_global =
if any_git {
self.0.git_global_matcher
.matched(&path, is_dir)
.map(IgnoreMatch::gitignore)
} else {
Match::None
};
m_custom_ignore
.or(m_ignore)
.or(m_gi)
.or(m_gi_exclude)
.or(m_global)
.or(m_explicit)
m_custom_ignore.or(m_ignore).or(m_gi).or(m_gi_exclude).or(m_global).or(m_explicit)
}
/// Returns an iterator over parent ignore matchers, including this one.
@@ -524,19 +535,20 @@ impl IgnoreBuilder {
/// The matcher returned won't match anything until ignore rules from
/// directories are added to it.
pub fn build(&self) -> Ignore {
let git_global_matcher = if !self.opts.git_global {
Gitignore::empty()
} else {
let mut builder = GitignoreBuilder::new("");
builder
.case_insensitive(self.opts.ignore_case_insensitive)
.unwrap();
let (gi, err) = builder.build_global();
if let Some(err) = err {
debug!("{}", err);
}
gi
};
let git_global_matcher =
if !self.opts.git_global {
Gitignore::empty()
} else {
let mut builder = GitignoreBuilder::new("");
builder
.case_insensitive(self.opts.ignore_case_insensitive)
.unwrap();
let (gi, err) = builder.build_global();
if let Some(err) = err {
debug!("{}", err);
}
gi
};
Ignore(Arc::new(IgnoreInner {
compiled: Arc::new(RwLock::new(HashMap::new())),
@@ -592,10 +604,9 @@ impl IgnoreBuilder {
/// later names.
pub fn add_custom_ignore_filename<S: AsRef<OsStr>>(
&mut self,
file_name: S,
file_name: S
) -> &mut IgnoreBuilder {
self.custom_ignore_filenames
.push(file_name.as_ref().to_os_string());
self.custom_ignore_filenames.push(file_name.as_ref().to_os_string());
self
}
@@ -667,7 +678,10 @@ impl IgnoreBuilder {
/// Process ignore files case insensitively
///
/// This is disabled by default.
pub fn ignore_case_insensitive(&mut self, yes: bool) -> &mut IgnoreBuilder {
pub fn ignore_case_insensitive(
&mut self,
yes: bool,
) -> &mut IgnoreBuilder {
self.opts.ignore_case_insensitive = yes;
self
}
@@ -707,9 +721,10 @@ mod tests {
use std::io::Write;
use std::path::Path;
use tempfile::{self, TempDir};
use dir::IgnoreBuilder;
use gitignore::Gitignore;
use tests::TempDir;
use Error;
fn wfile<P: AsRef<Path>>(path: P, contents: &str) {
@@ -728,21 +743,19 @@ mod tests {
}
}
fn tmpdir() -> TempDir {
TempDir::new().unwrap()
fn tmpdir(prefix: &str) -> TempDir {
tempfile::Builder::new().prefix(prefix).tempdir().unwrap()
}
#[test]
fn explicit_ignore() {
let td = tmpdir();
let td = tmpdir("ignore-test-");
wfile(td.path().join("not-an-ignore"), "foo\n!bar");
let (gi, err) = Gitignore::new(td.path().join("not-an-ignore"));
assert!(err.is_none());
let (ig, err) = IgnoreBuilder::new()
.add_ignore(gi)
.build()
.add_child(td.path());
.add_ignore(gi).build().add_child(td.path());
assert!(err.is_none());
assert!(ig.matched("foo", false).is_ignore());
assert!(ig.matched("bar", false).is_whitelist());
@@ -751,7 +764,7 @@ mod tests {
#[test]
fn git_exclude() {
let td = tmpdir();
let td = tmpdir("ignore-test-");
mkdirp(td.path().join(".git/info"));
wfile(td.path().join(".git/info/exclude"), "foo\n!bar");
@@ -764,7 +777,7 @@ mod tests {
#[test]
fn gitignore() {
let td = tmpdir();
let td = tmpdir("ignore-test-");
mkdirp(td.path().join(".git"));
wfile(td.path().join(".gitignore"), "foo\n!bar");
@@ -777,7 +790,7 @@ mod tests {
#[test]
fn gitignore_no_git() {
let td = tmpdir();
let td = tmpdir("ignore-test-");
wfile(td.path().join(".gitignore"), "foo\n!bar");
let (ig, err) = IgnoreBuilder::new().build().add_child(td.path());
@@ -789,7 +802,7 @@ mod tests {
#[test]
fn ignore() {
let td = tmpdir();
let td = tmpdir("ignore-test-");
wfile(td.path().join(".ignore"), "foo\n!bar");
let (ig, err) = IgnoreBuilder::new().build().add_child(td.path());
@@ -801,14 +814,13 @@ mod tests {
#[test]
fn custom_ignore() {
let td = tmpdir();
let td = tmpdir("ignore-test-");
let custom_ignore = ".customignore";
wfile(td.path().join(custom_ignore), "foo\n!bar");
let (ig, err) = IgnoreBuilder::new()
.add_custom_ignore_filename(custom_ignore)
.build()
.add_child(td.path());
.build().add_child(td.path());
assert!(err.is_none());
assert!(ig.matched("foo", false).is_ignore());
assert!(ig.matched("bar", false).is_whitelist());
@@ -818,15 +830,14 @@ mod tests {
// Tests that a custom ignore file will override an .ignore.
#[test]
fn custom_ignore_over_ignore() {
let td = tmpdir();
let td = tmpdir("ignore-test-");
let custom_ignore = ".customignore";
wfile(td.path().join(".ignore"), "foo");
wfile(td.path().join(custom_ignore), "!foo");
let (ig, err) = IgnoreBuilder::new()
.add_custom_ignore_filename(custom_ignore)
.build()
.add_child(td.path());
.build().add_child(td.path());
assert!(err.is_none());
assert!(ig.matched("foo", false).is_whitelist());
}
@@ -834,7 +845,7 @@ mod tests {
// Tests that earlier custom ignore files have lower precedence than later.
#[test]
fn custom_ignore_precedence() {
let td = tmpdir();
let td = tmpdir("ignore-test-");
let custom_ignore1 = ".customignore1";
let custom_ignore2 = ".customignore2";
wfile(td.path().join(custom_ignore1), "foo");
@@ -843,8 +854,7 @@ mod tests {
let (ig, err) = IgnoreBuilder::new()
.add_custom_ignore_filename(custom_ignore1)
.add_custom_ignore_filename(custom_ignore2)
.build()
.add_child(td.path());
.build().add_child(td.path());
assert!(err.is_none());
assert!(ig.matched("foo", false).is_whitelist());
}
@@ -852,7 +862,7 @@ mod tests {
// Tests that an .ignore will override a .gitignore.
#[test]
fn ignore_over_gitignore() {
let td = tmpdir();
let td = tmpdir("ignore-test-");
wfile(td.path().join(".gitignore"), "foo");
wfile(td.path().join(".ignore"), "!foo");
@@ -864,7 +874,7 @@ mod tests {
// Tests that exclude has lower precedent than both .ignore and .gitignore.
#[test]
fn exclude_lowest() {
let td = tmpdir();
let td = tmpdir("ignore-test-");
wfile(td.path().join(".gitignore"), "!foo");
wfile(td.path().join(".ignore"), "!bar");
mkdirp(td.path().join(".git/info"));
@@ -879,7 +889,7 @@ mod tests {
#[test]
fn errored() {
let td = tmpdir();
let td = tmpdir("ignore-test-");
wfile(td.path().join(".gitignore"), "{foo");
let (_, err) = IgnoreBuilder::new().build().add_child(td.path());
@@ -888,7 +898,7 @@ mod tests {
#[test]
fn errored_both() {
let td = tmpdir();
let td = tmpdir("ignore-test-");
wfile(td.path().join(".gitignore"), "{foo");
wfile(td.path().join(".ignore"), "{bar");
@@ -898,7 +908,7 @@ mod tests {
#[test]
fn errored_partial() {
let td = tmpdir();
let td = tmpdir("ignore-test-");
mkdirp(td.path().join(".git"));
wfile(td.path().join(".gitignore"), "{foo\nbar");
@@ -909,7 +919,7 @@ mod tests {
#[test]
fn errored_partial_and_ignore() {
let td = tmpdir();
let td = tmpdir("ignore-test-");
wfile(td.path().join(".gitignore"), "{foo\nbar");
wfile(td.path().join(".ignore"), "!bar");
@@ -920,7 +930,7 @@ mod tests {
#[test]
fn not_present_empty() {
let td = tmpdir();
let td = tmpdir("ignore-test-");
let (_, err) = IgnoreBuilder::new().build().add_child(td.path());
assert!(err.is_none());
@@ -930,7 +940,7 @@ mod tests {
fn stops_at_git_dir() {
// This tests that .gitignore files beyond a .git barrier aren't
// matched, but .ignore files are.
let td = tmpdir();
let td = tmpdir("ignore-test-");
mkdirp(td.path().join(".git"));
mkdirp(td.path().join("foo/.git"));
wfile(td.path().join(".gitignore"), "foo");
@@ -951,7 +961,7 @@ mod tests {
#[test]
fn absolute_parent() {
let td = tmpdir();
let td = tmpdir("ignore-test-");
mkdirp(td.path().join(".git"));
mkdirp(td.path().join("foo"));
wfile(td.path().join(".gitignore"), "bar");
@@ -974,7 +984,7 @@ mod tests {
#[test]
fn absolute_parent_anchored() {
let td = tmpdir();
let td = tmpdir("ignore-test-");
mkdirp(td.path().join(".git"));
mkdirp(td.path().join("src/llvm"));
wfile(td.path().join(".gitignore"), "/llvm/\nfoo");

View File

@@ -537,7 +537,7 @@ impl GitignoreBuilder {
///
/// Note that the file path returned may not exist.
fn gitconfig_excludes_path() -> Option<PathBuf> {
// git supports $HOME/.gitconfig and $XDG_CONFIG_HOME/git/config. Notably,
// git supports $HOME/.gitconfig and $XDG_CONFIG_DIR/git/config. Notably,
// both can be active at the same time, where $HOME/.gitconfig takes
// precedent. So if $HOME/.gitconfig defines a `core.excludesFile`, then
// we're done.
@@ -568,7 +568,7 @@ fn gitconfig_home_contents() -> Option<Vec<u8>> {
}
/// Returns the file contents of git's global config file, if one exists, in
/// the user's XDG_CONFIG_HOME directory.
/// the user's XDG_CONFIG_DIR directory.
fn gitconfig_xdg_contents() -> Option<Vec<u8>> {
let path = env::var_os("XDG_CONFIG_HOME")
.and_then(|x| if x.is_empty() { None } else { Some(PathBuf::from(x)) })

View File

@@ -55,6 +55,8 @@ extern crate log;
extern crate memchr;
extern crate regex;
extern crate same_file;
#[cfg(test)]
extern crate tempfile;
extern crate thread_local;
extern crate walkdir;
#[cfg(windows)]
@@ -440,66 +442,3 @@ impl<T> Match<T> {
}
}
}
#[cfg(test)]
mod tests {
use std::env;
use std::error;
use std::fs;
use std::path::{Path, PathBuf};
use std::result;
/// A convenient result type alias.
pub type Result<T> =
result::Result<T, Box<dyn error::Error + Send + Sync>>;
macro_rules! err {
($($tt:tt)*) => {
Box::<dyn error::Error + Send + Sync>::from(format!($($tt)*))
}
}
/// A simple wrapper for creating a temporary directory that is
/// automatically deleted when it's dropped.
///
/// We use this in lieu of tempfile because tempfile brings in too many
/// dependencies.
#[derive(Debug)]
pub struct TempDir(PathBuf);
impl Drop for TempDir {
fn drop(&mut self) {
fs::remove_dir_all(&self.0).unwrap();
}
}
impl TempDir {
/// Create a new empty temporary directory under the system's configured
/// temporary directory.
pub fn new() -> Result<TempDir> {
use std::sync::atomic::{AtomicUsize, Ordering};
static TRIES: usize = 100;
static COUNTER: AtomicUsize = AtomicUsize::new(0);
let tmpdir = env::temp_dir();
for _ in 0..TRIES {
let count = COUNTER.fetch_add(1, Ordering::SeqCst);
let path = tmpdir.join("rust-ignore").join(count.to_string());
if path.is_dir() {
continue;
}
fs::create_dir_all(&path).map_err(|e| {
err!("failed to create {}: {}", path.display(), e)
})?;
return Ok(TempDir(path));
}
Err(err!("failed to create temp dir after {} tries", TRIES))
}
/// Return the underlying path to this temporary directory.
pub fn path(&self) -> &Path {
&self.0
}
}
}

View File

@@ -135,7 +135,6 @@ const DEFAULT_TYPES: &'static [(&'static str, &'static [&'static str])] = &[
("d", &["*.d"]),
("dhall", &["*.dhall"]),
("docker", &["*Dockerfile*"]),
("edn", &["*.edn"]),
("elisp", &["*.el"]),
("elixir", &["*.ex", "*.eex", "*.exs"]),
("elm", &["*.elm"]),
@@ -220,7 +219,7 @@ const DEFAULT_TYPES: &'static [(&'static str, &'static [&'static str])] = &[
("msbuild", &[
"*.csproj", "*.fsproj", "*.vcxproj", "*.proj", "*.props", "*.targets"
]),
("nim", &["*.nim", "*.nimf", "*.nimble", "*.nims"]),
("nim", &["*.nim"]),
("nix", &["*.nix"]),
("objc", &["*.h", "*.m"]),
("objcpp", &["*.h", "*.mm"]),
@@ -242,7 +241,6 @@ const DEFAULT_TYPES: &'static [(&'static str, &'static [&'static str])] = &[
("readme", &["README*", "*README"]),
("r", &["*.R", "*.r", "*.Rmd", "*.Rnw"]),
("rdoc", &["*.rdoc"]),
("robot", &["*.robot"]),
("rst", &["*.rst"]),
("ruby", &["Gemfile", "*.gemspec", ".irbrc", "Rakefile", "*.rb"]),
("rust", &["*.rs"]),

View File

@@ -4,8 +4,8 @@ use std::fmt;
use std::fs::{self, FileType, Metadata};
use std::io;
use std::path::{Path, PathBuf};
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::thread;
use std::time::Duration;
use std::vec;
@@ -182,14 +182,14 @@ impl DirEntryInner {
match *self {
Stdin => {
let err = Error::Io(io::Error::new(
io::ErrorKind::Other,
"<stdin> has no metadata",
));
io::ErrorKind::Other, "<stdin> has no metadata"));
Err(err.with_path("<stdin>"))
}
Walkdir(ref x) => x
.metadata()
.map_err(|err| Error::Io(io::Error::from(err)).with_path(x.path())),
Walkdir(ref x) => {
x.metadata().map_err(|err| {
Error::Io(io::Error::from(err)).with_path(x.path())
})
}
Raw(ref x) => x.metadata(),
}
}
@@ -223,8 +223,8 @@ impl DirEntryInner {
#[cfg(unix)]
fn ino(&self) -> Option<u64> {
use self::DirEntryInner::*;
use walkdir::DirEntryExt;
use self::DirEntryInner::*;
match *self {
Stdin => None,
Walkdir(ref x) => Some(x.ino()),
@@ -297,8 +297,7 @@ impl DirEntryRaw {
fs::metadata(&self.path)
} else {
Ok(self.metadata.clone())
}
.map_err(|err| Error::Io(io::Error::from(err)).with_path(&self.path))
}.map_err(|err| Error::Io(io::Error::from(err)).with_path(&self.path))
}
#[cfg(not(windows))]
@@ -307,8 +306,7 @@ impl DirEntryRaw {
fs::metadata(&self.path)
} else {
fs::symlink_metadata(&self.path)
}
.map_err(|err| Error::Io(io::Error::from(err)).with_path(&self.path))
}.map_err(|err| Error::Io(io::Error::from(err)).with_path(&self.path))
}
fn file_type(&self) -> FileType {
@@ -316,9 +314,7 @@ impl DirEntryRaw {
}
fn file_name(&self) -> &OsStr {
self.path
.file_name()
.unwrap_or_else(|| self.path.as_os_str())
self.path.file_name().unwrap_or_else(|| self.path.as_os_str())
}
fn depth(&self) -> usize {
@@ -330,7 +326,10 @@ impl DirEntryRaw {
self.ino
}
fn from_entry(depth: usize, ent: &fs::DirEntry) -> Result<DirEntryRaw, Error> {
fn from_entry(
depth: usize,
ent: &fs::DirEntry,
) -> Result<DirEntryRaw, Error> {
let ty = ent.file_type().map_err(|err| {
let err = Error::Io(io::Error::from(err)).with_path(ent.path());
Error::WithDepth {
@@ -380,22 +379,15 @@ impl DirEntryRaw {
})
}
// Placeholder implementation to allow compiling on non-standard platforms (e.g. wasm32).
#[cfg(not(any(windows, unix)))]
fn from_entry_os(
#[cfg(not(unix))]
fn from_path(
depth: usize,
ent: &fs::DirEntry,
ty: fs::FileType,
pb: PathBuf,
link: bool,
) -> Result<DirEntryRaw, Error> {
Err(Error::Io(io::Error::new(
io::ErrorKind::Other,
"unsupported platform",
)))
}
#[cfg(windows)]
fn from_path(depth: usize, pb: PathBuf, link: bool) -> Result<DirEntryRaw, Error> {
let md = fs::metadata(&pb).map_err(|err| Error::Io(err).with_path(&pb))?;
let md = fs::metadata(&pb).map_err(|err| {
Error::Io(err).with_path(&pb)
})?;
Ok(DirEntryRaw {
path: pb,
ty: md.file_type(),
@@ -406,10 +398,16 @@ impl DirEntryRaw {
}
#[cfg(unix)]
fn from_path(depth: usize, pb: PathBuf, link: bool) -> Result<DirEntryRaw, Error> {
fn from_path(
depth: usize,
pb: PathBuf,
link: bool,
) -> Result<DirEntryRaw, Error> {
use std::os::unix::fs::MetadataExt;
let md = fs::metadata(&pb).map_err(|err| Error::Io(err).with_path(&pb))?;
let md = fs::metadata(&pb).map_err(|err| {
Error::Io(err).with_path(&pb)
})?;
Ok(DirEntryRaw {
path: pb,
ty: md.file_type(),
@@ -418,15 +416,6 @@ impl DirEntryRaw {
ino: md.ino(),
})
}
// Placeholder implementation to allow compiling on non-standard platforms (e.g. wasm32).
#[cfg(not(any(windows, unix)))]
fn from_path(depth: usize, pb: PathBuf, link: bool) -> Result<DirEntryRaw, Error> {
Err(Error::Io(io::Error::new(
io::ErrorKind::Other,
"unsupported platform",
)))
}
}
/// WalkBuilder builds a recursive directory iterator.
@@ -492,8 +481,8 @@ pub struct WalkBuilder {
#[derive(Clone)]
enum Sorter {
ByName(Arc<dyn Fn(&OsStr, &OsStr) -> cmp::Ordering + Send + Sync + 'static>),
ByPath(Arc<dyn Fn(&Path, &Path) -> cmp::Ordering + Send + Sync + 'static>),
ByName(Arc<Fn(&OsStr, &OsStr) -> cmp::Ordering + Send + Sync + 'static>),
ByPath(Arc<Fn(&Path, &Path) -> cmp::Ordering + Send + Sync + 'static>),
}
impl fmt::Debug for WalkBuilder {
@@ -536,34 +525,33 @@ impl WalkBuilder {
let follow_links = self.follow_links;
let max_depth = self.max_depth;
let sorter = self.sorter.clone();
let its = self
.paths
.iter()
.map(move |p| {
if p == Path::new("-") {
(p.to_path_buf(), None)
} else {
let mut wd = WalkDir::new(p);
wd = wd.follow_links(follow_links || p.is_file());
wd = wd.same_file_system(self.same_file_system);
if let Some(max_depth) = max_depth {
wd = wd.max_depth(max_depth);
}
if let Some(ref sorter) = sorter {
match sorter.clone() {
Sorter::ByName(cmp) => {
wd = wd.sort_by(move |a, b| cmp(a.file_name(), b.file_name()));
}
Sorter::ByPath(cmp) => {
wd = wd.sort_by(move |a, b| cmp(a.path(), b.path()));
}
let its = self.paths.iter().map(move |p| {
if p == Path::new("-") {
(p.to_path_buf(), None)
} else {
let mut wd = WalkDir::new(p);
wd = wd.follow_links(follow_links || p.is_file());
wd = wd.same_file_system(self.same_file_system);
if let Some(max_depth) = max_depth {
wd = wd.max_depth(max_depth);
}
if let Some(ref sorter) = sorter {
match sorter.clone() {
Sorter::ByName(cmp) => {
wd = wd.sort_by(move |a, b| {
cmp(a.file_name(), b.file_name())
});
}
Sorter::ByPath(cmp) => {
wd = wd.sort_by(move |a, b| {
cmp(a.path(), b.path())
});
}
}
(p.to_path_buf(), Some(WalkEventIter::from(wd)))
}
})
.collect::<Vec<_>>()
.into_iter();
(p.to_path_buf(), Some(WalkEventIter::from(wd)))
}
}).collect::<Vec<_>>().into_iter();
let ig_root = self.ig_builder.build();
Walk {
its: its,
@@ -647,12 +635,8 @@ impl WalkBuilder {
let mut errs = PartialErrorBuilder::default();
errs.maybe_push(builder.add(path));
match builder.build() {
Ok(gi) => {
self.ig_builder.add_ignore(gi);
}
Err(err) => {
errs.push(err);
}
Ok(gi) => { self.ig_builder.add_ignore(gi); }
Err(err) => { errs.push(err); }
}
errs.into_error_option()
}
@@ -665,7 +649,7 @@ impl WalkBuilder {
/// later names.
pub fn add_custom_ignore_filename<S: AsRef<OsStr>>(
&mut self,
file_name: S,
file_name: S
) -> &mut WalkBuilder {
self.ig_builder.add_custom_ignore_filename(file_name);
self
@@ -802,9 +786,11 @@ impl WalkBuilder {
/// by `sort_by_file_name`.
///
/// Note that this is not used in the parallel iterator.
pub fn sort_by_file_path<F>(&mut self, cmp: F) -> &mut WalkBuilder
where
F: Fn(&Path, &Path) -> cmp::Ordering + Send + Sync + 'static,
pub fn sort_by_file_path<F>(
&mut self,
cmp: F,
) -> &mut WalkBuilder
where F: Fn(&Path, &Path) -> cmp::Ordering + Send + Sync + 'static
{
self.sorter = Some(Sorter::ByPath(Arc::new(cmp)));
self
@@ -822,8 +808,7 @@ impl WalkBuilder {
///
/// Note that this is not used in the parallel iterator.
pub fn sort_by_file_name<F>(&mut self, cmp: F) -> &mut WalkBuilder
where
F: Fn(&OsStr, &OsStr) -> cmp::Ordering + Send + Sync + 'static,
where F: Fn(&OsStr, &OsStr) -> cmp::Ordering + Send + Sync + 'static
{
self.sorter = Some(Sorter::ByName(Arc::new(cmp)));
self
@@ -1004,11 +989,7 @@ enum WalkEvent {
impl From<WalkDir> for WalkEventIter {
fn from(it: WalkDir) -> WalkEventIter {
WalkEventIter {
depth: 0,
it: it.into_iter(),
next: None,
}
WalkEventIter { depth: 0, it: it.into_iter(), next: None }
}
}
@@ -1091,10 +1072,10 @@ impl WalkParallel {
/// Execute the parallel recursive directory iterator. `mkf` is called
/// for each thread used for iteration. The function produced by `mkf`
/// is then in turn called for each visited file path.
pub fn run<F>(self, mut mkf: F)
where
F: FnMut() -> Box<dyn FnMut(Result<DirEntry, Error>) -> WalkState + Send + 'static>,
{
pub fn run<F>(
self,
mut mkf: F,
) where F: FnMut() -> Box<FnMut(Result<DirEntry, Error>) -> WalkState + Send + 'static> {
let mut f = mkf();
let threads = self.threads();
// TODO: Figure out how to use a bounded channel here. With an
@@ -1111,16 +1092,30 @@ impl WalkParallel {
// Note that we only send directories. For files, we send to them the
// callback directly.
for path in self.paths {
let (dent, root_device) = if path == Path::new("-") {
(DirEntry::new_stdin(), None)
} else {
let root_device = if !self.same_file_system {
None
let (dent, root_device) =
if path == Path::new("-") {
(DirEntry::new_stdin(), None)
} else {
match device_num(&path) {
Ok(root_device) => Some(root_device),
let root_device =
if !self.same_file_system {
None
} else {
match device_num(&path) {
Ok(root_device) => Some(root_device),
Err(err) => {
let err = Error::Io(err).with_path(path);
if f(Err(err)).is_quit() {
return;
}
continue;
}
}
};
match DirEntryRaw::from_path(0, path, false) {
Ok(dent) => {
(DirEntry::new_raw(dent, None), root_device)
}
Err(err) => {
let err = Error::Io(err).with_path(path);
if f(Err(err)).is_quit() {
return;
}
@@ -1128,22 +1123,11 @@ impl WalkParallel {
}
}
};
match DirEntryRaw::from_path(0, path, false) {
Ok(dent) => (DirEntry::new_raw(dent, None), root_device),
Err(err) => {
if f(Err(err)).is_quit() {
return;
}
continue;
}
}
};
tx.send(Message::Work(Work {
dent: dent,
ignore: self.ig_root.clone(),
root_device: root_device,
}))
.unwrap();
})).unwrap();
any_work = true;
}
// ... but there's no need to start workers if we don't need them.
@@ -1269,7 +1253,7 @@ impl Work {
/// Note that a worker is *both* a producer and a consumer.
struct Worker {
/// The caller's callback.
f: Box<dyn FnMut(Result<DirEntry, Error>) -> WalkState + Send + 'static>,
f: Box<FnMut(Result<DirEntry, Error>) -> WalkState + Send + 'static>,
/// The push side of our mpmc queue.
tx: channel::Sender<Message>,
/// The receive side of our mpmc queue.
@@ -1335,21 +1319,22 @@ impl Worker {
continue;
}
};
let descend = if let Some(root_device) = work.root_device {
match is_same_file_system(root_device, work.dent.path()) {
Ok(true) => true,
Ok(false) => false,
Err(err) => {
if (self.f)(Err(err)).is_quit() {
self.quit_now();
return;
let descend =
if let Some(root_device) = work.root_device {
match is_same_file_system(root_device, work.dent.path()) {
Ok(true) => true,
Ok(false) => false,
Err(err) => {
if (self.f)(Err(err)).is_quit() {
self.quit_now();
return;
}
false
}
false
}
}
} else {
true
};
} else {
true
};
let depth = work.dent.depth();
match (self.f)(Ok(work.dent)) {
@@ -1367,7 +1352,12 @@ impl Worker {
continue;
}
for result in readdir {
let state = self.run_one(&work.ignore, depth + 1, work.root_device, result);
let state = self.run_one(
&work.ignore,
depth + 1,
work.root_device,
result,
);
if state.is_quit() {
self.quit_now();
return;
@@ -1432,24 +1422,23 @@ impl Worker {
}
}
let should_skip_path = should_skip_entry(ig, &dent);
let should_skip_filesize = if self.max_filesize.is_some() && !dent.is_dir() {
skip_filesize(
self.max_filesize.unwrap(),
dent.path(),
&dent.metadata().ok(),
)
} else {
false
};
let should_skip_filesize =
if self.max_filesize.is_some() && !dent.is_dir() {
skip_filesize(
self.max_filesize.unwrap(),
dent.path(),
&dent.metadata().ok(),
)
} else {
false
};
if !should_skip_path && !should_skip_filesize {
self.tx
.send(Message::Work(Work {
dent: dent,
ignore: ig.clone(),
root_device: root_device,
}))
.unwrap();
self.tx.send(Message::Work(Work {
dent: dent,
ignore: ig.clone(),
root_device: root_device,
})).unwrap();
}
WalkState::Continue
}
@@ -1579,25 +1568,17 @@ fn check_symlink_loop(
child_depth: usize,
) -> Result<(), Error> {
let hchild = Handle::from_path(child_path).map_err(|err| {
Error::from(err)
.with_path(child_path)
.with_depth(child_depth)
Error::from(err).with_path(child_path).with_depth(child_depth)
})?;
for ig in ig_parent
.parents()
.take_while(|ig| !ig.is_absolute_parent())
{
for ig in ig_parent.parents().take_while(|ig| !ig.is_absolute_parent()) {
let h = Handle::from_path(ig.path()).map_err(|err| {
Error::from(err)
.with_path(child_path)
.with_depth(child_depth)
Error::from(err).with_path(child_path).with_depth(child_depth)
})?;
if hchild == h {
return Err(Error::Loop {
ancestor: ig.path().to_path_buf(),
child: child_path.to_path_buf(),
}
.with_depth(child_depth));
}.with_depth(child_depth));
}
}
Ok(())
@@ -1605,10 +1586,14 @@ fn check_symlink_loop(
// Before calling this function, make sure that you ensure that is really
// necessary as the arguments imply a file stat.
fn skip_filesize(max_filesize: u64, path: &Path, ent: &Option<Metadata>) -> bool {
fn skip_filesize(
max_filesize: u64,
path: &Path,
ent: &Option<Metadata>
) -> bool {
let filesize = match *ent {
Some(ref md) => Some(md.len()),
None => None,
None => None
};
if let Some(fs) = filesize {
@@ -1623,7 +1608,10 @@ fn skip_filesize(max_filesize: u64, path: &Path, ent: &Option<Metadata>) -> bool
}
}
fn should_skip_entry(ig: &Ignore, dent: &DirEntry) -> bool {
fn should_skip_entry(
ig: &Ignore,
dent: &DirEntry,
) -> bool {
let m = ig.matched_dir_entry(dent);
if m.is_ignore() {
debug!("ignoring {}: {:?}", dent.path().display(), m);
@@ -1685,27 +1673,28 @@ fn path_equals(dent: &DirEntry, handle: &Handle) -> Result<bool, Error> {
/// Returns true if and only if the given path is on the same device as the
/// given root device.
fn is_same_file_system(root_device: u64, path: &Path) -> Result<bool, Error> {
let dent_device = device_num(path).map_err(|err| Error::Io(err).with_path(path))?;
let dent_device = device_num(path)
.map_err(|err| Error::Io(err).with_path(path))?;
Ok(root_device == dent_device)
}
#[cfg(unix)]
fn device_num<P: AsRef<Path>>(path: P) -> io::Result<u64> {
fn device_num<P: AsRef<Path>>(path: P)-> io::Result<u64> {
use std::os::unix::fs::MetadataExt;
path.as_ref().metadata().map(|md| md.dev())
}
#[cfg(windows)]
#[cfg(windows)]
fn device_num<P: AsRef<Path>>(path: P) -> io::Result<u64> {
use winapi_util::{file, Handle};
use winapi_util::{Handle, file};
let h = Handle::from_path_any(path)?;
file::information(h).map(|info| info.volume_serial_number())
}
#[cfg(not(any(unix, windows)))]
fn device_num<P: AsRef<Path>>(_: P) -> io::Result<u64> {
fn device_num<P: AsRef<Path>>(_: P)-> io::Result<u64> {
Err(io::Error::new(
io::ErrorKind::Other,
"walkdir: same_file_system option not supported on this platform",
@@ -1719,8 +1708,9 @@ mod tests {
use std::path::Path;
use std::sync::{Arc, Mutex};
use tempfile::{self, TempDir};
use super::{DirEntry, WalkBuilder, WalkState};
use tests::TempDir;
fn wfile<P: AsRef<Path>>(path: P, contents: &str) {
let mut file = File::create(path).unwrap();
@@ -1767,7 +1757,10 @@ mod tests {
paths
}
fn walk_collect_parallel(prefix: &Path, builder: &WalkBuilder) -> Vec<String> {
fn walk_collect_parallel(
prefix: &Path,
builder: &WalkBuilder,
) -> Vec<String> {
let mut paths = vec![];
for dent in walk_collect_entries_parallel(builder) {
let path = dent.path().strip_prefix(prefix).unwrap();
@@ -1802,11 +1795,15 @@ mod tests {
paths
}
fn tmpdir() -> TempDir {
TempDir::new().unwrap()
fn tmpdir(prefix: &str) -> TempDir {
tempfile::Builder::new().prefix(prefix).tempdir().unwrap()
}
fn assert_paths(prefix: &Path, builder: &WalkBuilder, expected: &[&str]) {
fn assert_paths(
prefix: &Path,
builder: &WalkBuilder,
expected: &[&str],
) {
let got = walk_collect(prefix, builder);
assert_eq!(got, mkpaths(expected), "single threaded");
let got = walk_collect_parallel(prefix, builder);
@@ -1815,22 +1812,20 @@ mod tests {
#[test]
fn no_ignores() {
let td = tmpdir();
let td = tmpdir("walk-test-");
mkdirp(td.path().join("a/b/c"));
mkdirp(td.path().join("x/y"));
wfile(td.path().join("a/b/foo"), "");
wfile(td.path().join("x/y/foo"), "");
assert_paths(
td.path(),
&WalkBuilder::new(td.path()),
&["x", "x/y", "x/y/foo", "a", "a/b", "a/b/foo", "a/b/c"],
);
assert_paths(td.path(), &WalkBuilder::new(td.path()), &[
"x", "x/y", "x/y/foo", "a", "a/b", "a/b/foo", "a/b/c",
]);
}
#[test]
fn custom_ignore() {
let td = tmpdir();
let td = tmpdir("walk-test-");
let custom_ignore = ".customignore";
mkdirp(td.path().join("a"));
wfile(td.path().join(custom_ignore), "foo");
@@ -1846,7 +1841,7 @@ mod tests {
#[test]
fn custom_ignore_exclusive_use() {
let td = tmpdir();
let td = tmpdir("walk-test-");
let custom_ignore = ".customignore";
mkdirp(td.path().join("a"));
wfile(td.path().join(custom_ignore), "foo");
@@ -1866,7 +1861,7 @@ mod tests {
#[test]
fn gitignore() {
let td = tmpdir();
let td = tmpdir("walk-test-");
mkdirp(td.path().join(".git"));
mkdirp(td.path().join("a"));
wfile(td.path().join(".gitignore"), "foo");
@@ -1875,16 +1870,14 @@ mod tests {
wfile(td.path().join("bar"), "");
wfile(td.path().join("a/bar"), "");
assert_paths(
td.path(),
&WalkBuilder::new(td.path()),
&["bar", "a", "a/bar"],
);
assert_paths(td.path(), &WalkBuilder::new(td.path()), &[
"bar", "a", "a/bar",
]);
}
#[test]
fn explicit_ignore() {
let td = tmpdir();
let td = tmpdir("walk-test-");
let igpath = td.path().join(".not-an-ignore");
mkdirp(td.path().join("a"));
wfile(&igpath, "foo");
@@ -1900,7 +1893,7 @@ mod tests {
#[test]
fn explicit_ignore_exclusive_use() {
let td = tmpdir();
let td = tmpdir("walk-test-");
let igpath = td.path().join(".not-an-ignore");
mkdirp(td.path().join("a"));
wfile(&igpath, "foo");
@@ -1912,16 +1905,13 @@ mod tests {
let mut builder = WalkBuilder::new(td.path());
builder.standard_filters(false);
assert!(builder.add_ignore(&igpath).is_none());
assert_paths(
td.path(),
&builder,
&[".not-an-ignore", "bar", "a", "a/bar"],
);
assert_paths(td.path(), &builder,
&[".not-an-ignore", "bar", "a", "a/bar"]);
}
#[test]
fn gitignore_parent() {
let td = tmpdir();
let td = tmpdir("walk-test-");
mkdirp(td.path().join(".git"));
mkdirp(td.path().join("a"));
wfile(td.path().join(".gitignore"), "foo");
@@ -1934,7 +1924,7 @@ mod tests {
#[test]
fn max_depth() {
let td = tmpdir();
let td = tmpdir("walk-test-");
mkdirp(td.path().join("a/b/c"));
wfile(td.path().join("foo"), "");
wfile(td.path().join("a/foo"), "");
@@ -1942,23 +1932,19 @@ mod tests {
wfile(td.path().join("a/b/c/foo"), "");
let mut builder = WalkBuilder::new(td.path());
assert_paths(
td.path(),
&builder,
&["a", "a/b", "a/b/c", "foo", "a/foo", "a/b/foo", "a/b/c/foo"],
);
assert_paths(td.path(), &builder, &[
"a", "a/b", "a/b/c", "foo", "a/foo", "a/b/foo", "a/b/c/foo",
]);
assert_paths(td.path(), builder.max_depth(Some(0)), &[]);
assert_paths(td.path(), builder.max_depth(Some(1)), &["a", "foo"]);
assert_paths(
td.path(),
builder.max_depth(Some(2)),
&["a", "a/b", "foo", "a/foo"],
);
assert_paths(td.path(), builder.max_depth(Some(2)), &[
"a", "a/b", "foo", "a/foo",
]);
}
#[test]
fn max_filesize() {
let td = tmpdir();
let td = tmpdir("walk-test-");
mkdirp(td.path().join("a/b"));
wfile_size(td.path().join("foo"), 0);
wfile_size(td.path().join("bar"), 400);
@@ -1968,49 +1954,41 @@ mod tests {
wfile_size(td.path().join("a/baz"), 200);
let mut builder = WalkBuilder::new(td.path());
assert_paths(
td.path(),
&builder,
&["a", "a/b", "foo", "bar", "baz", "a/foo", "a/bar", "a/baz"],
);
assert_paths(
td.path(),
builder.max_filesize(Some(0)),
&["a", "a/b", "foo"],
);
assert_paths(
td.path(),
builder.max_filesize(Some(500)),
&["a", "a/b", "foo", "bar", "a/bar", "a/baz"],
);
assert_paths(
td.path(),
builder.max_filesize(Some(50000)),
&["a", "a/b", "foo", "bar", "baz", "a/foo", "a/bar", "a/baz"],
);
assert_paths(td.path(), &builder, &[
"a", "a/b", "foo", "bar", "baz", "a/foo", "a/bar", "a/baz",
]);
assert_paths(td.path(), builder.max_filesize(Some(0)), &[
"a", "a/b", "foo"
]);
assert_paths(td.path(), builder.max_filesize(Some(500)), &[
"a", "a/b", "foo", "bar", "a/bar", "a/baz"
]);
assert_paths(td.path(), builder.max_filesize(Some(50000)), &[
"a", "a/b", "foo", "bar", "baz", "a/foo", "a/bar", "a/baz",
]);
}
#[cfg(unix)] // because symlinks on windows are weird
#[test]
fn symlinks() {
let td = tmpdir();
let td = tmpdir("walk-test-");
mkdirp(td.path().join("a/b"));
symlink(td.path().join("a/b"), td.path().join("z"));
wfile(td.path().join("a/b/foo"), "");
let mut builder = WalkBuilder::new(td.path());
assert_paths(td.path(), &builder, &["a", "a/b", "a/b/foo", "z"]);
assert_paths(
td.path(),
&builder.follow_links(true),
&["a", "a/b", "a/b/foo", "z", "z/foo"],
);
assert_paths(td.path(), &builder, &[
"a", "a/b", "a/b/foo", "z",
]);
assert_paths(td.path(), &builder.follow_links(true), &[
"a", "a/b", "a/b/foo", "z", "z/foo",
]);
}
#[cfg(unix)] // because symlinks on windows are weird
#[test]
fn first_path_not_symlink() {
let td = tmpdir();
let td = tmpdir("walk-test-");
mkdirp(td.path().join("foo"));
let dents = WalkBuilder::new(td.path().join("foo"))
@@ -2021,7 +1999,9 @@ mod tests {
assert_eq!(1, dents.len());
assert!(!dents[0].path_is_symlink());
let dents = walk_collect_entries_parallel(&WalkBuilder::new(td.path().join("foo")));
let dents = walk_collect_entries_parallel(
&WalkBuilder::new(td.path().join("foo")),
);
assert_eq!(1, dents.len());
assert!(!dents[0].path_is_symlink());
}
@@ -2029,13 +2009,17 @@ mod tests {
#[cfg(unix)] // because symlinks on windows are weird
#[test]
fn symlink_loop() {
let td = tmpdir();
let td = tmpdir("walk-test-");
mkdirp(td.path().join("a/b"));
symlink(td.path().join("a"), td.path().join("a/b/c"));
let mut builder = WalkBuilder::new(td.path());
assert_paths(td.path(), &builder, &["a", "a/b", "a/b/c"]);
assert_paths(td.path(), &builder.follow_links(true), &["a", "a/b"]);
assert_paths(td.path(), &builder, &[
"a", "a/b", "a/b/c",
]);
assert_paths(td.path(), &builder.follow_links(true), &[
"a", "a/b",
]);
}
// It's a little tricky to test the 'same_file_system' option since
@@ -2055,7 +2039,7 @@ mod tests {
// If our test directory actually isn't a different volume from /sys,
// then this test is meaningless and we shouldn't run it.
let td = tmpdir();
let td = tmpdir("walk-test-");
if device_num(td.path()).unwrap() == device_num("/sys").unwrap() {
return;
}
@@ -2069,6 +2053,8 @@ mod tests {
// completely.
let mut builder = WalkBuilder::new(td.path());
builder.follow_links(true).same_file_system(true);
assert_paths(td.path(), &builder, &["same_file", "same_file/alink"]);
assert_paths(td.path(), &builder, &[
"same_file", "same_file/alink",
]);
}
}

View File

@@ -1,14 +1,14 @@
class RipgrepBin < Formula
version '11.0.2'
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 "0ba26423691deedf2649b12b1abe3d2be294ee1cb17c40b68fe85efe194f4f57"
sha256 "92446c6b28b6c726f91ad66a03bcd533fc6e1a28ef4b44c27bfe2d49a0f88531"
elsif OS.linux?
url "https://github.com/BurntSushi/ripgrep/releases/download/#{version}/ripgrep-#{version}-x86_64-unknown-linux-musl.tar.gz"
sha256 "2e7978e346553fbc45c0940d9fa11e12f9afbae8213b261aad19b698150e169a"
sha256 "ce74cabac9b39b1ad55837ec01e2c670fa7e965772ac2647b209e31ead19008c"
end
conflicts_with "ripgrep"

View File

@@ -571,7 +571,6 @@ pub fn all_args_and_flags() -> Vec<RGArg> {
flag_fixed_strings(&mut args);
flag_follow(&mut args);
flag_glob(&mut args);
flag_glob_case_insensitive(&mut args);
flag_heading(&mut args);
flag_hidden(&mut args);
flag_iglob(&mut args);
@@ -1219,25 +1218,6 @@ it.
args.push(arg);
}
fn flag_glob_case_insensitive(args: &mut Vec<RGArg>) {
const SHORT: &str = "Process all glob patterns case insensitively.";
const LONG: &str = long!("\
Process glob patterns given with the -g/--glob flag case insensitively. This
effectively treats --glob as --iglob.
This flag can be disabled with the --no-glob-case-insensitive flag.
");
let arg = RGArg::switch("glob-case-insensitive")
.help(SHORT).long_help(LONG)
.overrides("no-glob-case-insensitive");
args.push(arg);
let arg = RGArg::switch("no-glob-case-insensitive")
.hidden()
.overrides("glob-case-insensitive");
args.push(arg);
}
fn flag_heading(args: &mut Vec<RGArg>) {
const SHORT: &str = "Print matches grouped by each file.";
const LONG: &str = long!("\
@@ -1995,12 +1975,7 @@ or backreferences.
Note that PCRE2 is an optional ripgrep feature. If PCRE2 wasn't included in
your build of ripgrep, then using this flag will result in ripgrep printing
an error message and exiting. PCRE2 may also have worse user experience in
some cases, since it has fewer introspection APIs than ripgrep's default regex
engine. For example, if you use a '\n' in a PCRE2 regex without the
'-U/--multiline' flag, then ripgrep will silently fail to match anything
instead of reporting an error immediately (like it does with the default
regex engine).
an error message and exiting.
Related flags: --no-pcre2-unicode
@@ -2196,10 +2171,7 @@ Replace every match with the text given when printing results. Neither this
flag nor any other ripgrep flag will modify your files.
Capture group indices (e.g., $5) and names (e.g., $foo) are supported in the
replacement string. In shells such as Bash and zsh, you should wrap the
pattern in single quotes instead of double quotes. Otherwise, capture group
indices will be replaced by expanded shell variables which will most likely
be empty.
replacement string.
Note that the replacement by default replaces each match, and NOT the entire
line. To replace the entire line, you should match the entire line.

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,20 +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()?);
// Make all globs case insensitive with --glob-case-insensitive.
if self.is_present("glob-case-insensitive") {
builder.case_insensitive(true).unwrap();
}
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.
@@ -1334,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]))
}
}
@@ -1390,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)
@@ -1421,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))
}
@@ -1479,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.
@@ -1565,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);
@@ -1573,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.
@@ -1594,11 +1579,10 @@ impl ArgMatches {
if self.is_present("no-filename") {
false
} else {
let path_stdin = Path::new("-");
self.is_present("with-filename")
|| self.is_present("vimgrep")
|| paths.len() > 1
|| paths.get(0).map_or(false, |p| p != path_stdin && p.is_dir())
|| paths.get(0).map_or(false, |p| p.is_dir())
}
}
}
@@ -1633,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() })
}
}
}
@@ -1641,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()
})
}
}
}
}
@@ -1683,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(
@@ -1721,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
@@ -1773,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,16 +3,16 @@
// 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;
use std::path::{Path, PathBuf};
use bstr::{io::BufReadExt, ByteSlice};
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<dyn 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<dyn 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,12 +1,15 @@
use std::error;
#![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]
@@ -15,6 +18,7 @@ mod messages;
mod app;
mod args;
mod config;
mod err;
mod logger;
mod path_printer;
mod search;
@@ -43,7 +47,8 @@ mod subject;
#[global_allocator]
static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;
type Result<T> = ::std::result::Result<T, Box<dyn error::Error>>;
// 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) {
@@ -214,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)
@@ -240,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())?;
}
@@ -272,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))
@@ -281,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)
}
@@ -304,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();
@@ -319,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

@@ -315,24 +315,7 @@ pub struct SearchWorker<W> {
impl<W: WriteColor> SearchWorker<W> {
/// Execute a search over the given subject.
pub fn search(&mut self, subject: &Subject) -> io::Result<SearchResult> {
let bin =
if subject.is_explicit() {
self.config.binary_explicit.clone()
} else {
self.config.binary_implicit.clone()
};
self.searcher.set_binary_detection(bin);
let path = subject.path();
if subject.is_stdin() {
self.search_reader(path, io::stdin().lock())
} else if self.should_preprocess(path) {
self.search_preprocessor(path)
} else if self.should_decompress(path) {
self.search_decompress(path)
} else {
self.search_path(path)
}
self.search_impl(subject)
}
/// Return a mutable reference to the underlying printer.
@@ -358,6 +341,30 @@ impl<W: WriteColor> SearchWorker<W> {
}
}
/// Search the given subject using the appropriate strategy.
fn search_impl(&mut self, subject: &Subject) -> io::Result<SearchResult> {
let bin =
if subject.is_explicit() {
self.config.binary_explicit.clone()
} else {
self.config.binary_implicit.clone()
};
self.searcher.set_binary_detection(bin);
let path = subject.path();
if subject.is_stdin() {
let stdin = io::stdin();
// A `return` here appeases the borrow checker. NLL will fix this.
return self.search_reader(path, stdin.lock());
} else if self.should_preprocess(path) {
self.search_preprocessor(path)
} else if self.should_decompress(path) {
self.search_decompress(path)
} else {
self.search_path(path)
}
}
/// Returns true if and only if the given file path should be
/// decompressed before searching.
fn should_decompress(&self, path: &Path) -> bool {
@@ -385,23 +392,11 @@ impl<W: WriteColor> SearchWorker<W> {
&mut self,
path: &Path,
) -> io::Result<SearchResult> {
let bin = self.config.preprocessor.as_ref().unwrap();
let mut cmd = Command::new(bin);
let bin = self.config.preprocessor.clone().unwrap();
let mut cmd = Command::new(&bin);
cmd.arg(path).stdin(Stdio::from(File::open(path)?));
let rdr = self
.command_builder
.build(&mut cmd)
.map_err(|err| {
io::Error::new(
io::ErrorKind::Other,
format!(
"preprocessor command could not start: '{:?}': {}",
cmd,
err,
),
)
})?;
let rdr = self.command_builder.build(&mut cmd)?;
self.search_reader(path, rdr).map_err(|err| {
io::Error::new(
io::ErrorKind::Other,

2
termcolor/README.md Normal file
View File

@@ -0,0 +1,2 @@
termcolor has moved to its own repository:
https://github.com/BurntSushi/termcolor

View File

@@ -341,14 +341,6 @@ rgtest!(glob_case_sensitive, |dir: Dir, mut cmd: TestCommand| {
eqnice!("file2.html:Sherlock\n", cmd.stdout());
});
rgtest!(glob_always_case_insensitive, |dir: Dir, mut cmd: TestCommand| {
dir.create("sherlock", SHERLOCK);
dir.create("file.HTML", "Sherlock");
cmd.args(&["--glob-case-insensitive", "--glob", "*.html", "Sherlock"]);
eqnice!("file.HTML:Sherlock\n", cmd.stdout());
});
rgtest!(byte_offset_only_matching, |dir: Dir, mut cmd: TestCommand| {
dir.create("sherlock", SHERLOCK);
cmd.arg("-b").arg("-o").arg("Sherlock");

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);
});
@@ -706,18 +706,6 @@ rgtest!(r1203_reverse_suffix_literal, |dir: Dir, _: TestCommand| {
eqnice!("153.230000\n", cmd.arg(r"\d\d\d000").arg("test").stdout());
});
// See: https://github.com/BurntSushi/ripgrep/issues/1223
rgtest!(r1223_no_dir_check_for_default_path, |dir: Dir, mut cmd: TestCommand| {
dir.create_dir("-");
dir.create("a.json", "{}");
dir.create("a.txt", "some text");
eqnice!(
"a.json\na.txt\n",
sort_lines(&cmd.arg("a").pipe(b"a.json\na.txt"))
);
});
// See: https://github.com/BurntSushi/ripgrep/issues/1259
rgtest!(r1259_drop_last_byte_nonl, |dir: Dir, mut cmd: TestCommand| {
dir.create("patterns-nonl", "[foo]");
@@ -728,13 +716,3 @@ rgtest!(r1259_drop_last_byte_nonl, |dir: Dir, mut cmd: TestCommand| {
cmd = dir.command();
eqnice!("fz\n", cmd.arg("-f").arg("patterns-nl").arg("test").stdout());
});
// See: https://github.com/BurntSushi/ripgrep/issues/1334
rgtest!(r1334_crazy_literals, |dir: Dir, mut cmd: TestCommand| {
dir.create("patterns", &"1.208.0.0/12\n".repeat(40));
dir.create("corpus", "1.208.0.0/12\n");
eqnice!(
"1.208.0.0/12\n",
cmd.arg("-Ff").arg("patterns").arg("corpus").stdout()
);
});

2
wincolor/README.md Normal file
View File

@@ -0,0 +1,2 @@
wincolor has moved to the termcolor repository:
https://github.com/BurntSushi/termcolor