mirror of
https://github.com/BurntSushi/ripgrep.git
synced 2025-08-11 18:21:58 -07:00
Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
7bf7ceb5d3 |
99
.github/workflows/ci.yml
vendored
99
.github/workflows/ci.yml
vendored
@@ -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
|
|
33
CHANGELOG.md
33
CHANGELOG.md
@@ -1,42 +1,11 @@
|
|||||||
TBD
|
TBD
|
||||||
===
|
===
|
||||||
TODO
|
TODO.
|
||||||
|
|
||||||
Bug fixes:
|
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):
|
* [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`.
|
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)
|
11.0.1 (2019-04-16)
|
||||||
|
657
Cargo.lock
generated
657
Cargo.lock
generated
@@ -2,19 +2,47 @@
|
|||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aho-corasick"
|
name = "aho-corasick"
|
||||||
version = "0.7.6"
|
version = "0.7.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
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]]
|
[[package]]
|
||||||
name = "atty"
|
name = "atty"
|
||||||
version = "0.2.13"
|
version = "0.2.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
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)",
|
||||||
"winapi 0.3.8 (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]]
|
[[package]]
|
||||||
@@ -22,22 +50,22 @@ name = "base64"
|
|||||||
version = "0.10.1"
|
version = "0.10.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
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]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.1.0"
|
version = "1.0.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bstr"
|
name = "bstr"
|
||||||
version = "0.2.7"
|
version = "0.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
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)",
|
||||||
"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)",
|
||||||
"regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"regex-automata 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -47,17 +75,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "1.3.2"
|
version = "1.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.41"
|
version = "1.0.35"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "0.1.9"
|
version = "0.1.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -65,27 +93,36 @@ name = "clap"
|
|||||||
version = "2.33.0"
|
version = "2.33.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
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)",
|
"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)",
|
"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]]
|
[[package]]
|
||||||
name = "crossbeam-channel"
|
name = "crossbeam-channel"
|
||||||
version = "0.3.9"
|
version = "0.3.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
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]]
|
[[package]]
|
||||||
name = "crossbeam-utils"
|
name = "crossbeam-utils"
|
||||||
version = "0.6.6"
|
version = "0.6.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
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)",
|
||||||
"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]]
|
[[package]]
|
||||||
@@ -93,7 +130,7 @@ name = "encoding_rs"
|
|||||||
version = "0.8.17"
|
version = "0.8.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
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)",
|
"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"
|
version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
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]]
|
[[package]]
|
||||||
name = "glob"
|
name = "glob"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
@@ -122,164 +164,166 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "globset"
|
name = "globset"
|
||||||
version = "0.4.4"
|
version = "0.4.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick 0.7.6 (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.2.7 (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)",
|
"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)",
|
"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)",
|
"log 0.4.6 (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]]
|
[[package]]
|
||||||
name = "grep"
|
name = "grep"
|
||||||
version = "0.2.4"
|
version = "0.2.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"grep-cli 0.1.3",
|
"grep-cli 0.1.2",
|
||||||
"grep-matcher 0.1.3",
|
"grep-matcher 0.1.2",
|
||||||
"grep-pcre2 0.1.3",
|
"grep-pcre2 0.1.3",
|
||||||
"grep-printer 0.1.3",
|
"grep-printer 0.1.2",
|
||||||
"grep-regex 0.1.5",
|
"grep-regex 0.1.3",
|
||||||
"grep-searcher 0.1.6",
|
"grep-searcher 0.1.4",
|
||||||
"termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"termcolor 1.0.4 (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)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "grep-cli"
|
name = "grep-cli"
|
||||||
version = "0.1.3"
|
version = "0.1.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
"atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"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)",
|
||||||
"globset 0.4.4",
|
"globset 0.4.3",
|
||||||
"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)",
|
||||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.6 (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)",
|
||||||
"same-file 1.0.5 (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.5 (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)",
|
"winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "grep-matcher"
|
name = "grep-matcher"
|
||||||
version = "0.1.3"
|
version = "0.1.2"
|
||||||
dependencies = [
|
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)",
|
||||||
"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]]
|
[[package]]
|
||||||
name = "grep-pcre2"
|
name = "grep-pcre2"
|
||||||
version = "0.1.3"
|
version = "0.1.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"grep-matcher 0.1.3",
|
"grep-matcher 0.1.2",
|
||||||
"pcre2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"pcre2 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "grep-printer"
|
name = "grep-printer"
|
||||||
version = "0.1.3"
|
version = "0.1.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"bstr 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"grep-matcher 0.1.3",
|
"grep-matcher 0.1.2",
|
||||||
"grep-regex 0.1.5",
|
"grep-regex 0.1.3",
|
||||||
"grep-searcher 0.1.6",
|
"grep-searcher 0.1.4",
|
||||||
"serde 1.0.99 (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.99 (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.40 (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.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "grep-regex"
|
name = "grep-regex"
|
||||||
version = "0.1.5"
|
version = "0.1.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick 0.7.6 (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.3",
|
"grep-matcher 0.1.2",
|
||||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.6 (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)",
|
||||||
"regex-syntax 0.6.11 (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)",
|
"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]]
|
[[package]]
|
||||||
name = "grep-searcher"
|
name = "grep-searcher"
|
||||||
version = "0.1.6"
|
version = "0.1.4"
|
||||||
dependencies = [
|
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)",
|
"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 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)",
|
"encoding_rs_io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"grep-matcher 0.1.3",
|
"grep-matcher 0.1.2",
|
||||||
"grep-regex 0.1.5",
|
"grep-regex 0.1.3",
|
||||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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]]
|
[[package]]
|
||||||
name = "ignore"
|
name = "ignore"
|
||||||
version = "0.4.10"
|
version = "0.4.7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossbeam-channel 0.3.9 (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.4",
|
"globset 0.4.3",
|
||||||
"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)",
|
||||||
"log 0.4.8 (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.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.2.1 (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.5 (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)",
|
"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)",
|
"winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "0.4.4"
|
version = "0.4.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jemalloc-sys"
|
name = "jemalloc-sys"
|
||||||
version = "0.3.2"
|
version = "0.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
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)",
|
"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]]
|
[[package]]
|
||||||
name = "jemallocator"
|
name = "jemallocator"
|
||||||
version = "0.3.2"
|
version = "0.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"jemalloc-sys 0.3.2 (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.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lazy_static"
|
name = "lazy_static"
|
||||||
version = "1.4.0"
|
version = "1.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.62"
|
version = "0.2.51"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.8"
|
version = "0.4.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
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]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.2.1"
|
version = "2.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -287,16 +331,16 @@ name = "memmap"
|
|||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
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)",
|
||||||
"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]]
|
[[package]]
|
||||||
name = "num_cpus"
|
name = "num_cpus"
|
||||||
version = "1.10.1"
|
version = "1.10.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
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]]
|
[[package]]
|
||||||
@@ -304,102 +348,237 @@ name = "packed_simd"
|
|||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
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]]
|
[[package]]
|
||||||
name = "pcre2"
|
name = "pcre2"
|
||||||
version = "0.2.1"
|
version = "0.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
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)",
|
||||||
"log 0.4.8 (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.2 (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)",
|
"thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pcre2-sys"
|
name = "pcre2-sys"
|
||||||
version = "0.2.2"
|
version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
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)",
|
||||||
"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)",
|
||||||
"pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
"pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pkg-config"
|
name = "pkg-config"
|
||||||
version = "0.3.15"
|
version = "0.3.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.1"
|
version = "0.4.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
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]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.2"
|
version = "0.6.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
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]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.2.1"
|
version = "1.1.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick 0.7.6 (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.1 (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.11 (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)",
|
"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]]
|
[[package]]
|
||||||
name = "regex-automata"
|
name = "regex-automata"
|
||||||
version = "0.1.8"
|
version = "0.1.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
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]]
|
[[package]]
|
||||||
name = "regex-syntax"
|
name = "regex-syntax"
|
||||||
version = "0.6.11"
|
version = "0.6.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ripgrep"
|
|
||||||
version = "11.0.2"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bstr 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ucd-util 0.1.3 (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)",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[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]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.0"
|
version = "0.2.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "same-file"
|
name = "same-file"
|
||||||
version = "1.0.5"
|
version = "1.0.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@@ -407,27 +586,51 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.99"
|
version = "1.0.90"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.99"
|
version = "1.0.90"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
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)",
|
||||||
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"syn 0.15.31 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.40"
|
version = "1.0.39"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ryu 1.0.0 (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.99 (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]]
|
[[package]]
|
||||||
@@ -437,20 +640,43 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.5"
|
version = "0.15.31"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
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)",
|
||||||
"quote 1.0.2 (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.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 = "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]]
|
[[package]]
|
||||||
name = "termcolor"
|
name = "termcolor"
|
||||||
version = "1.0.5"
|
version = "1.0.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
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]]
|
[[package]]
|
||||||
@@ -458,7 +684,7 @@ name = "textwrap"
|
|||||||
version = "0.11.0"
|
version = "0.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
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]]
|
[[package]]
|
||||||
@@ -466,32 +692,42 @@ name = "thread_local"
|
|||||||
version = "0.3.6"
|
version = "0.3.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
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]]
|
[[package]]
|
||||||
name = "unicode-width"
|
name = "unicode-width"
|
||||||
version = "0.1.6"
|
version = "0.1.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-xid"
|
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"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "walkdir"
|
name = "walkdir"
|
||||||
version = "2.2.9"
|
version = "2.2.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"same-file 1.0.5 (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.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)",
|
"winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.8"
|
version = "0.3.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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"
|
version = "0.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
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]]
|
[[package]]
|
||||||
@@ -518,64 +754,91 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wincolor"
|
name = "wincolor"
|
||||||
version = "1.0.2"
|
version = "1.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
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)",
|
"winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d"
|
"checksum aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e6f484ae0c99fec2e858eb6134949117399f222608d84cadb3f58c1f97c2364c"
|
||||||
"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90"
|
"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 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 bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
|
||||||
"checksum bstr 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94cdf78eb7e94c566c1f5dbe2abf8fc70a548fc902942a48c4b3a98b48ca9ade"
|
"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 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 byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb"
|
||||||
"checksum cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "8dae9c4b8fedcae85592ba623c4fd08cfdab3e3b72d6df780c6ead964a69bfff"
|
"checksum cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)" = "5e5f3fee5eeb60324c2781f1e41286bdee933850fff9b3c672587fed5ec58c83"
|
||||||
"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33"
|
"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 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 cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
||||||
"checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6"
|
"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 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 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 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 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 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 itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b"
|
||||||
"checksum jemalloc-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0d3b9f3f5c9b31aa0f5ed3260385ac205db665baa41d49bb8338008ae94ede45"
|
"checksum jemalloc-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7bef0d4ce37578dfd80b466e3d8324bd9de788e249f1accebb0c472ea4b52bdc"
|
||||||
"checksum jemallocator 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "43ae63fcfc45e99ab3d1b29a46782ad679e98436c3169d15a167a1108a724b69"
|
"checksum jemallocator 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c2b69163a3cf2d0fffcd4e1b57921bc6d8fb97ec27f2aeef00562abdaf4ffe2a"
|
||||||
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
|
||||||
"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba"
|
"checksum libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)" = "bedcc7a809076656486ffe045abeeac163da1b558e963a31e29fbfbeba916917"
|
||||||
"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
|
"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
|
||||||
"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e"
|
"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 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 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 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a08c8195dd1d8a2a1b5e2af94bf0c4c3c195c2359930442a016bf123196f7155"
|
||||||
"checksum pcre2-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "876c72d05059d23a84bd9fcdc3b1d31c50ea7fe00fe1522b4e68cd3608db8d5b"
|
"checksum pcre2-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e9699d43bebf25ee0fdafb9457b9a52da3c57506a3d39a2f9b6498800f032881"
|
||||||
"checksum pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c1d2cfa5a714db3b5f24f0915e74fcdf91d09d496ba61329705dda7774d2af"
|
"checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c"
|
||||||
"checksum proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c5c2380ae88876faae57698be9e9775e3544decad214599c3a6266cca6ac802"
|
"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915"
|
||||||
"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
|
"checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db"
|
||||||
"checksum regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88c3d9193984285d544df4a30c23a4e62ead42edf70a4452ceb76dac1ce05c26"
|
"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
|
||||||
"checksum regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "92b73c2a1770c255c240eaa4ee600df1704a38dc3feaa6e949e7fcd4f8dc09f9"
|
"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
|
||||||
"checksum regex-syntax 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b143cceb2ca5e56d5671988ef8b15615733e7ee16cd348e064333b251b89343f"
|
"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
|
||||||
"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997"
|
"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0"
|
||||||
"checksum same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421"
|
"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
|
||||||
"checksum serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "fec2851eb56d010dc9a21b89ca53ee75e6528bab60c11e89d38390904982da9f"
|
"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
|
||||||
"checksum serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "cb4dc18c61206b08dc98216c98faa0232f4337e1e1b8574551d5bad29ea1b425"
|
"checksum rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9ea758282efe12823e0d952ddb269d2e1897227e464919a554f2a03ef1b832"
|
||||||
"checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704"
|
"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 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 syn 0.15.31 (registry+https://github.com/rust-lang/crates.io-index)" = "d2b4cfac95805274c6afdb12d8f770fa2d27c045953e7b630a81801953699a9a"
|
||||||
"checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e"
|
"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 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 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 ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86"
|
||||||
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
|
||||||
"checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e"
|
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
||||||
"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
|
"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-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-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 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"
|
||||||
|
@@ -1,11 +1,11 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ripgrep"
|
name = "ripgrep"
|
||||||
version = "11.0.2" #:version
|
version = "11.0.1" #:version
|
||||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||||
description = """
|
description = """
|
||||||
ripgrep is a line-oriented search tool that recursively searches your current
|
ripgrep is a line-oriented search tool that recursively searches your current
|
||||||
directory for a regex pattern while respecting your gitignore rules. ripgrep
|
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"
|
documentation = "https://github.com/BurntSushi/ripgrep"
|
||||||
homepage = "https://github.com/BurntSushi/ripgrep"
|
homepage = "https://github.com/BurntSushi/ripgrep"
|
||||||
@@ -46,14 +46,15 @@ members = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bstr = "0.2.0"
|
bstr = "0.1.2"
|
||||||
grep = { version = "0.2.4", path = "grep" }
|
grep = { version = "0.2.4", path = "grep" }
|
||||||
ignore = { version = "0.4.7", path = "ignore" }
|
ignore = { version = "0.4.7", path = "ignore" }
|
||||||
lazy_static = "1.1.0"
|
lazy_static = "1.1.0"
|
||||||
log = "0.4.5"
|
log = { version = "0.4.5", features = ["std"] }
|
||||||
num_cpus = "1.8.0"
|
num_cpus = "1.8.0"
|
||||||
regex = "1.0.5"
|
regex = "1.0.5"
|
||||||
serde_json = "1.0.23"
|
serde_json = "1.0.23"
|
||||||
|
snafu = "0.2.3"
|
||||||
termcolor = "1.0.3"
|
termcolor = "1.0.3"
|
||||||
|
|
||||||
[dependencies.clap]
|
[dependencies.clap]
|
||||||
|
@@ -1,2 +0,0 @@
|
|||||||
[target.x86_64-unknown-linux-musl]
|
|
||||||
image = "burntsushi/x86_64-unknown-linux-musl:v0.1.14"
|
|
2
GUIDE.md
2
GUIDE.md
@@ -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
|
It is beyond the scope of this guide to provide a full tutorial on regular
|
||||||
expressions, but ripgrep's specific syntax is documented here:
|
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
|
### Recursive search
|
||||||
|
27
README.md
27
README.md
@@ -29,7 +29,6 @@ Please see the [CHANGELOG](CHANGELOG.md) for a release history.
|
|||||||
* [Configuration files](GUIDE.md#configuration-file)
|
* [Configuration files](GUIDE.md#configuration-file)
|
||||||
* [Shell completions](FAQ.md#complete)
|
* [Shell completions](FAQ.md#complete)
|
||||||
* [Building](#building)
|
* [Building](#building)
|
||||||
* [Translations](#translations)
|
|
||||||
|
|
||||||
|
|
||||||
### Screenshot of search results
|
### 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
|
[the FAQ](FAQ.md#posix4ever) for more details on whether ripgrep can truly
|
||||||
replace grep.)
|
replace grep.)
|
||||||
* Like other tools specialized to code search, ripgrep defaults to recursive
|
* Like other tools specialized to code search, ripgrep defaults to recursive
|
||||||
directory search and won't search files ignored by your
|
directory search and won't search files ignored by your `.gitignore` files.
|
||||||
`.gitignore`/`.ignore`/`.rgignore` files. It also ignores hidden and binary
|
It also ignores hidden and binary files by default. ripgrep also implements
|
||||||
files by default. ripgrep also implements full support for `.gitignore`,
|
full support for `.gitignore`, whereas there are many bugs related to that
|
||||||
whereas there are many bugs related to that functionality in other code
|
functionality in other code search tools claiming to provide the same
|
||||||
search tools claiming to provide the same functionality.
|
functionality.
|
||||||
* ripgrep can search specific types of files. For example, `rg -tpy foo`
|
* ripgrep can search specific types of files. For example, `rg -tpy foo`
|
||||||
limits your search to Python files and `rg -Tjs foo` excludes Javascript
|
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
|
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
|
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
|
$ 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).
|
[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
|
$ curl -LO https://github.com/BurntSushi/ripgrep/releases/download/11.0.1/ripgrep_11.0.1_amd64.deb
|
||||||
$ sudo dpkg -i ripgrep_11.0.2_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).
|
[officially maintained by Debian](https://tracker.debian.org/pkg/rust-ripgrep).
|
||||||
```
|
```
|
||||||
$ sudo apt-get install ripgrep
|
$ sudo apt-get install ripgrep
|
||||||
@@ -419,11 +418,3 @@ $ cargo test --all
|
|||||||
```
|
```
|
||||||
|
|
||||||
from the repository root.
|
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-)
|
|
||||||
|
@@ -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
|
|
@@ -104,10 +104,6 @@ _rg() {
|
|||||||
'*'{-g+,--glob=}'[include/exclude files matching specified glob]:glob'
|
'*'{-g+,--glob=}'[include/exclude files matching specified glob]:glob'
|
||||||
'*--iglob=[include/exclude files matching specified case-insensitive 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
|
+ '(heading)' # Heading options
|
||||||
'(pretty-vimgrep)--heading[show matches grouped by file name]'
|
'(pretty-vimgrep)--heading[show matches grouped by file name]'
|
||||||
"(pretty-vimgrep)--no-heading[don't show matches grouped by file name]"
|
"(pretty-vimgrep)--no-heading[don't show matches grouped by file name]"
|
||||||
|
@@ -143,16 +143,16 @@ would behave identically to the following command
|
|||||||
|
|
||||||
same with using globs
|
same with using globs
|
||||||
|
|
||||||
--glob=!.git
|
--glob=!git/*
|
||||||
|
|
||||||
or
|
or
|
||||||
|
|
||||||
--glob
|
--glob
|
||||||
!.git
|
!git/*
|
||||||
|
|
||||||
would behave identically to the following command
|
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
|
ripgrep also provides a flag, *--no-config*, that when present will suppress
|
||||||
any and all support for configuration. This includes any future support
|
any and all support for configuration. This includes any future support
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "globset"
|
name = "globset"
|
||||||
version = "0.4.4" #:version
|
version = "0.4.3" #:version
|
||||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||||
description = """
|
description = """
|
||||||
Cross platform single glob and glob set matching. Glob set matching is the
|
Cross platform single glob and glob set matching. Glob set matching is the
|
||||||
@@ -20,7 +20,7 @@ bench = false
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
aho-corasick = "0.7.3"
|
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"
|
fnv = "1.0.6"
|
||||||
log = "0.4.5"
|
log = "0.4.5"
|
||||||
regex = "1.1.5"
|
regex = "1.1.5"
|
||||||
|
@@ -120,7 +120,7 @@ impl GlobMatcher {
|
|||||||
|
|
||||||
/// Tests whether the given path matches this pattern or not.
|
/// Tests whether the given path matches this pattern or not.
|
||||||
pub fn is_match_candidate(&self, path: &Candidate) -> bool {
|
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.
|
/// Tests whether the given path matches this pattern or not.
|
||||||
fn is_match_candidate(&self, candidate: &Candidate) -> bool {
|
fn is_match_candidate(&self, candidate: &Candidate) -> bool {
|
||||||
let byte_path = &*candidate.path;
|
let byte_path = candidate.path.as_bytes();
|
||||||
|
|
||||||
match self.strategy {
|
match self.strategy {
|
||||||
MatchStrategy::Literal(ref lit) => lit.as_bytes() == byte_path,
|
MatchStrategy::Literal(ref lit) => lit.as_bytes() == byte_path,
|
||||||
|
@@ -119,7 +119,7 @@ use std::path::Path;
|
|||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
use aho_corasick::AhoCorasick;
|
use aho_corasick::AhoCorasick;
|
||||||
use bstr::{B, ByteSlice, ByteVec};
|
use bstr::{B, BStr, BString};
|
||||||
use regex::bytes::{Regex, RegexBuilder, RegexSet};
|
use regex::bytes::{Regex, RegexBuilder, RegexSet};
|
||||||
|
|
||||||
use pathutil::{file_name, file_name_ext, normalize_path};
|
use pathutil::{file_name, file_name_ext, normalize_path};
|
||||||
@@ -490,15 +490,15 @@ impl GlobSetBuilder {
|
|||||||
/// path against multiple globs or sets of globs.
|
/// path against multiple globs or sets of globs.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Candidate<'a> {
|
pub struct Candidate<'a> {
|
||||||
path: Cow<'a, [u8]>,
|
path: Cow<'a, BStr>,
|
||||||
basename: Cow<'a, [u8]>,
|
basename: Cow<'a, BStr>,
|
||||||
ext: Cow<'a, [u8]>,
|
ext: Cow<'a, BStr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Candidate<'a> {
|
impl<'a> Candidate<'a> {
|
||||||
/// Create a new candidate for matching from the given path.
|
/// Create a new candidate for matching from the given path.
|
||||||
pub fn new<P: AsRef<Path> + ?Sized>(path: &'a P) -> Candidate<'a> {
|
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 basename = file_name(&path).unwrap_or(Cow::Borrowed(B("")));
|
||||||
let ext = file_name_ext(&basename).unwrap_or(Cow::Borrowed(B("")));
|
let ext = file_name_ext(&basename).unwrap_or(Cow::Borrowed(B("")));
|
||||||
Candidate {
|
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 {
|
if self.path.len() <= max {
|
||||||
&*self.path
|
&*self.path
|
||||||
} else {
|
} 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 {
|
if self.path.len() <= max {
|
||||||
&*self.path
|
&*self.path
|
||||||
} else {
|
} else {
|
||||||
|
@@ -1,15 +1,15 @@
|
|||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use bstr::{ByteSlice, ByteVec};
|
use bstr::BStr;
|
||||||
|
|
||||||
/// The final component of the path, if it is a normal file.
|
/// 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,
|
/// If the path terminates in ., .., or consists solely of a root of prefix,
|
||||||
/// file_name will return None.
|
/// 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() {
|
if path.is_empty() {
|
||||||
return None;
|
return None;
|
||||||
} else if path.last_byte() == Some(b'.') {
|
} else if path.last() == Some(b'.') {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let last_slash = path.rfind_byte(b'/').map(|i| i + 1).unwrap_or(0);
|
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`
|
/// 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, but it also matches files like `.rs`, which doesn't have an
|
||||||
/// extension according to std::path::Path::extension.
|
/// 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() {
|
if name.is_empty() {
|
||||||
return None;
|
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
|
/// Normalizes a path to use `/` as a separator everywhere, even on platforms
|
||||||
/// that recognize other characters as separators.
|
/// that recognize other characters as separators.
|
||||||
#[cfg(unix)]
|
#[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.
|
// UNIX only uses /, so we're good.
|
||||||
path
|
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
|
/// Normalizes a path to use `/` as a separator everywhere, even on platforms
|
||||||
/// that recognize other characters as separators.
|
/// that recognize other characters as separators.
|
||||||
#[cfg(not(unix))]
|
#[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;
|
use std::path::is_separator;
|
||||||
|
|
||||||
for i in 0..path.len() {
|
for i in 0..path.len() {
|
||||||
@@ -84,7 +84,7 @@ pub fn normalize_path(mut path: Cow<[u8]>) -> Cow<[u8]> {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use bstr::{B, ByteVec};
|
use bstr::{B, BString};
|
||||||
|
|
||||||
use super::{file_name_ext, normalize_path};
|
use super::{file_name_ext, normalize_path};
|
||||||
|
|
||||||
@@ -92,7 +92,7 @@ mod tests {
|
|||||||
($name:ident, $file_name:expr, $ext:expr) => {
|
($name:ident, $file_name:expr, $ext:expr) => {
|
||||||
#[test]
|
#[test]
|
||||||
fn $name() {
|
fn $name() {
|
||||||
let bs = Vec::from($file_name);
|
let bs = BString::from($file_name);
|
||||||
let got = file_name_ext(&Cow::Owned(bs));
|
let got = file_name_ext(&Cow::Owned(bs));
|
||||||
assert_eq!($ext.map(|s| Cow::Borrowed(B(s))), got);
|
assert_eq!($ext.map(|s| Cow::Borrowed(B(s))), got);
|
||||||
}
|
}
|
||||||
@@ -109,7 +109,7 @@ mod tests {
|
|||||||
($name:ident, $path:expr, $expected:expr) => {
|
($name:ident, $path:expr, $expected:expr) => {
|
||||||
#[test]
|
#[test]
|
||||||
fn $name() {
|
fn $name() {
|
||||||
let bs = Vec::from_slice($path);
|
let bs = BString::from_slice($path);
|
||||||
let got = normalize_path(Cow::Owned(bs));
|
let got = normalize_path(Cow::Owned(bs));
|
||||||
assert_eq!($expected.to_vec(), got.into_owned());
|
assert_eq!($expected.to_vec(), got.into_owned());
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "grep-cli"
|
name = "grep-cli"
|
||||||
version = "0.1.3" #:version
|
version = "0.1.2" #:version
|
||||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||||
description = """
|
description = """
|
||||||
Utilities for search oriented command line applications.
|
Utilities for search oriented command line applications.
|
||||||
@@ -14,7 +14,7 @@ license = "Unlicense/MIT"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
atty = "0.2.11"
|
atty = "0.2.11"
|
||||||
bstr = "0.2.0"
|
bstr = "0.1.2"
|
||||||
globset = { version = "0.4.3", path = "../globset" }
|
globset = { version = "0.4.3", path = "../globset" }
|
||||||
lazy_static = "1.1.0"
|
lazy_static = "1.1.0"
|
||||||
log = "0.4.5"
|
log = "0.4.5"
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
use bstr::{ByteSlice, ByteVec};
|
use bstr::{BStr, BString};
|
||||||
|
|
||||||
/// A single state in the state machine used by `unescape`.
|
/// A single state in the state machine used by `unescape`.
|
||||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||||
@@ -38,6 +38,7 @@ enum State {
|
|||||||
/// assert_eq!(r"foo\nbar\xFFbaz", escape(b"foo\nbar\xFFbaz"));
|
/// assert_eq!(r"foo\nbar\xFFbaz", escape(b"foo\nbar\xFFbaz"));
|
||||||
/// ```
|
/// ```
|
||||||
pub fn escape(bytes: &[u8]) -> String {
|
pub fn escape(bytes: &[u8]) -> String {
|
||||||
|
let bytes = BStr::new(bytes);
|
||||||
let mut escaped = String::new();
|
let mut escaped = String::new();
|
||||||
for (s, e, ch) in bytes.char_indices() {
|
for (s, e, ch) in bytes.char_indices() {
|
||||||
if ch == '\u{FFFD}' {
|
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.
|
/// This is like [`escape`](fn.escape.html), but accepts an OS string.
|
||||||
pub fn escape_os(string: &OsStr) -> 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.
|
/// Unescapes a string.
|
||||||
@@ -110,7 +111,7 @@ pub fn unescape(s: &str) -> Vec<u8> {
|
|||||||
}
|
}
|
||||||
HexFirst => {
|
HexFirst => {
|
||||||
match c {
|
match c {
|
||||||
'0'..='9' | 'A'..='F' | 'a'..='f' => {
|
'0'...'9' | 'A'...'F' | 'a'...'f' => {
|
||||||
state = HexSecond(c);
|
state = HexSecond(c);
|
||||||
}
|
}
|
||||||
c => {
|
c => {
|
||||||
@@ -121,7 +122,7 @@ pub fn unescape(s: &str) -> Vec<u8> {
|
|||||||
}
|
}
|
||||||
HexSecond(first) => {
|
HexSecond(first) => {
|
||||||
match c {
|
match c {
|
||||||
'0'..='9' | 'A'..='F' | 'a'..='f' => {
|
'0'...'9' | 'A'...'F' | 'a'...'f' => {
|
||||||
let ordinal = format!("{}{}", first, c);
|
let ordinal = format!("{}{}", first, c);
|
||||||
let byte = u8::from_str_radix(&ordinal, 16).unwrap();
|
let byte = u8::from_str_radix(&ordinal, 16).unwrap();
|
||||||
bytes.push(byte);
|
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.
|
/// Adds the given byte to the given string, escaping it if necessary.
|
||||||
fn escape_byte(byte: u8, into: &mut String) {
|
fn escape_byte(byte: u8, into: &mut String) {
|
||||||
match byte {
|
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'\n' => into.push_str(r"\n"),
|
||||||
b'\r' => into.push_str(r"\r"),
|
b'\r' => into.push_str(r"\r"),
|
||||||
b'\t' => into.push_str(r"\t"),
|
b'\t' => into.push_str(r"\t"),
|
||||||
|
@@ -161,7 +161,7 @@ pub fn patterns_from_reader<R: io::Read>(rdr: R) -> io::Result<Vec<String>> {
|
|||||||
let mut line_number = 0;
|
let mut line_number = 0;
|
||||||
io::BufReader::new(rdr).for_byte_line(|line| {
|
io::BufReader::new(rdr).for_byte_line(|line| {
|
||||||
line_number += 1;
|
line_number += 1;
|
||||||
match pattern_from_bytes(line) {
|
match pattern_from_bytes(line.as_bytes()) {
|
||||||
Ok(pattern) => {
|
Ok(pattern) => {
|
||||||
patterns.push(pattern.to_string());
|
patterns.push(pattern.to_string());
|
||||||
Ok(true)
|
Ok(true)
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "grep-matcher"
|
name = "grep-matcher"
|
||||||
version = "0.1.3" #:version
|
version = "0.1.2" #:version
|
||||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||||
description = """
|
description = """
|
||||||
A trait for regular expressions, with a focus on line oriented search.
|
A trait for regular expressions, with a focus on line oriented search.
|
||||||
|
@@ -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.
|
/// Returns true if and only if the given byte is allowed in a capture name.
|
||||||
fn is_valid_cap_letter(b: &u8) -> bool {
|
fn is_valid_cap_letter(b: &u8) -> bool {
|
||||||
match *b {
|
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,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "grep-printer"
|
name = "grep-printer"
|
||||||
version = "0.1.3" #:version
|
version = "0.1.2" #:version
|
||||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||||
description = """
|
description = """
|
||||||
An implementation of the grep crate's Sink trait that provides standard
|
An implementation of the grep crate's Sink trait that provides standard
|
||||||
@@ -19,7 +19,7 @@ serde1 = ["base64", "serde", "serde_derive", "serde_json"]
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
base64 = { version = "0.10.0", optional = true }
|
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-matcher = { version = "0.1.2", path = "../grep-matcher" }
|
||||||
grep-searcher = { version = "0.1.4", path = "../grep-searcher" }
|
grep-searcher = { version = "0.1.4", path = "../grep-searcher" }
|
||||||
termcolor = "1.0.4"
|
termcolor = "1.0.4"
|
||||||
|
@@ -5,7 +5,7 @@ use std::path::Path;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
use bstr::ByteSlice;
|
use bstr::BStr;
|
||||||
use grep_matcher::{Match, Matcher};
|
use grep_matcher::{Match, Matcher};
|
||||||
use grep_searcher::{
|
use grep_searcher::{
|
||||||
LineStep, Searcher,
|
LineStep, Searcher,
|
||||||
@@ -1274,7 +1274,7 @@ impl<'a, M: Matcher, W: WriteColor> StandardImpl<'a, M, W> {
|
|||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
if self.config().max_columns_preview {
|
if self.config().max_columns_preview {
|
||||||
let original = line;
|
let original = line;
|
||||||
let end = bytes[line]
|
let end = BStr::new(&bytes[line])
|
||||||
.grapheme_indices()
|
.grapheme_indices()
|
||||||
.map(|(_, end, _)| end)
|
.map(|(_, end, _)| end)
|
||||||
.take(self.config().max_columns.unwrap_or(0) as usize)
|
.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!(
|
let remainder = format!(
|
||||||
"after match (found {:?} byte around offset {})\n",
|
"after match (found {:?} byte around offset {})\n",
|
||||||
[byte].as_bstr(), offset,
|
BStr::new(&[byte]), offset,
|
||||||
);
|
);
|
||||||
self.write(remainder.as_bytes())?;
|
self.write(remainder.as_bytes())?;
|
||||||
} else if let Some(byte) = bin.convert_byte() {
|
} 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!(
|
let remainder = format!(
|
||||||
"matches (found {:?} byte around offset {})\n",
|
"matches (found {:?} byte around offset {})\n",
|
||||||
[byte].as_bstr(), offset,
|
BStr::new(&[byte]), offset,
|
||||||
);
|
);
|
||||||
self.write(remainder.as_bytes())?;
|
self.write(remainder.as_bytes())?;
|
||||||
}
|
}
|
||||||
|
@@ -4,7 +4,7 @@ use std::io;
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::time;
|
use std::time;
|
||||||
|
|
||||||
use bstr::{ByteSlice, ByteVec};
|
use bstr::{BStr, BString};
|
||||||
use grep_matcher::{Captures, LineTerminator, Match, Matcher};
|
use grep_matcher::{Captures, LineTerminator, Match, Matcher};
|
||||||
use grep_searcher::{
|
use grep_searcher::{
|
||||||
LineIter,
|
LineIter,
|
||||||
@@ -263,12 +263,12 @@ impl<'a> Sunk<'a> {
|
|||||||
/// portability with a small cost: on Windows, paths that are not valid UTF-16
|
/// portability with a small cost: on Windows, paths that are not valid UTF-16
|
||||||
/// will not roundtrip correctly.
|
/// will not roundtrip correctly.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct PrinterPath<'a>(Cow<'a, [u8]>);
|
pub struct PrinterPath<'a>(Cow<'a, BStr>);
|
||||||
|
|
||||||
impl<'a> PrinterPath<'a> {
|
impl<'a> PrinterPath<'a> {
|
||||||
/// Create a new path suitable for printing.
|
/// Create a new path suitable for printing.
|
||||||
pub fn new(path: &'a Path) -> PrinterPath<'a> {
|
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
|
/// 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
|
/// path separators that are both replaced by `new_sep`. In all other
|
||||||
/// environments, only `/` is treated as a path separator.
|
/// environments, only `/` is treated as a path separator.
|
||||||
fn replace_separator(&mut self, new_sep: u8) {
|
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'\\') {
|
if b == b'/' || (cfg!(windows) && b == b'\\') {
|
||||||
new_sep
|
new_sep
|
||||||
} else {
|
} else {
|
||||||
@@ -301,7 +301,7 @@ impl<'a> PrinterPath<'a> {
|
|||||||
|
|
||||||
/// Return the raw bytes for this path.
|
/// Return the raw bytes for this path.
|
||||||
pub fn as_bytes(&self) -> &[u8] {
|
pub fn as_bytes(&self) -> &[u8] {
|
||||||
&self.0
|
self.0.as_bytes()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "grep-regex"
|
name = "grep-regex"
|
||||||
version = "0.1.5" #:version
|
version = "0.1.3" #:version
|
||||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||||
description = """
|
description = """
|
||||||
Use Rust's regex library with the 'grep' crate.
|
Use Rust's regex library with the 'grep' crate.
|
||||||
@@ -19,3 +19,4 @@ log = "0.4.5"
|
|||||||
regex = "1.1"
|
regex = "1.1"
|
||||||
regex-syntax = "0.6.5"
|
regex-syntax = "0.6.5"
|
||||||
thread_local = "0.3.6"
|
thread_local = "0.3.6"
|
||||||
|
utf8-ranges = "1.0.1"
|
||||||
|
@@ -11,6 +11,7 @@ extern crate log;
|
|||||||
extern crate regex;
|
extern crate regex;
|
||||||
extern crate regex_syntax;
|
extern crate regex_syntax;
|
||||||
extern crate thread_local;
|
extern crate thread_local;
|
||||||
|
extern crate utf8_ranges;
|
||||||
|
|
||||||
pub use error::{Error, ErrorKind};
|
pub use error::{Error, ErrorKind};
|
||||||
pub use matcher::{RegexCaptures, RegexMatcher, RegexMatcherBuilder};
|
pub use matcher::{RegexCaptures, RegexMatcher, RegexMatcherBuilder};
|
||||||
|
@@ -71,31 +71,10 @@ impl RegexMatcherBuilder {
|
|||||||
&self,
|
&self,
|
||||||
literals: &[B],
|
literals: &[B],
|
||||||
) -> Result<RegexMatcher, Error> {
|
) -> Result<RegexMatcher, Error> {
|
||||||
let mut has_escape = false;
|
let slices: Vec<_> = literals.iter().map(|s| s.as_ref()).collect();
|
||||||
let mut slices = vec![];
|
if !self.config.can_plain_aho_corasick() || literals.len() < 40 {
|
||||||
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
|
|
||||||
{
|
|
||||||
return self.build(&slices.join("|"));
|
return self.build(&slices.join("|"));
|
||||||
}
|
}
|
||||||
|
|
||||||
let matcher = MultiLiteralMatcher::new(&slices)?;
|
let matcher = MultiLiteralMatcher::new(&slices)?;
|
||||||
let imp = RegexMatcherImpl::MultiLiteral(matcher);
|
let imp = RegexMatcherImpl::MultiLiteral(matcher);
|
||||||
Ok(RegexMatcher {
|
Ok(RegexMatcher {
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
use grep_matcher::ByteSet;
|
use grep_matcher::ByteSet;
|
||||||
use regex_syntax::hir::{self, Hir, HirKind};
|
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.
|
/// Return a confirmed set of non-matching bytes from the given expression.
|
||||||
pub fn non_matching_bytes(expr: &Hir) -> ByteSet {
|
pub fn non_matching_bytes(expr: &Hir) -> ByteSet {
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "grep-searcher"
|
name = "grep-searcher"
|
||||||
version = "0.1.6" #:version
|
version = "0.1.4" #:version
|
||||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||||
description = """
|
description = """
|
||||||
Fast line oriented regex searching as a library.
|
Fast line oriented regex searching as a library.
|
||||||
@@ -13,7 +13,7 @@ keywords = ["regex", "grep", "egrep", "search", "pattern"]
|
|||||||
license = "Unlicense/MIT"
|
license = "Unlicense/MIT"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bstr = { version = "0.2.0", default-features = false, features = ["std"] }
|
bstr = { version = "0.1.2", default-features = false, features = ["std"] }
|
||||||
bytecount = "0.5"
|
bytecount = "0.5"
|
||||||
encoding_rs = "0.8.14"
|
encoding_rs = "0.8.14"
|
||||||
encoding_rs_io = "0.1.6"
|
encoding_rs_io = "0.1.6"
|
||||||
|
@@ -17,7 +17,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn example() -> Result<(), Box<dyn Error>> {
|
fn example() -> Result<(), Box<Error>> {
|
||||||
let pattern = match env::args().nth(1) {
|
let pattern = match env::args().nth(1) {
|
||||||
Some(pattern) => pattern,
|
Some(pattern) => pattern,
|
||||||
None => return Err(From::from(format!(
|
None => return Err(From::from(format!(
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
use bstr::ByteSlice;
|
use bstr::{BStr, BString};
|
||||||
|
|
||||||
/// The default buffer capacity that we use for the line buffer.
|
/// The default buffer capacity that we use for the line buffer.
|
||||||
pub(crate) const DEFAULT_BUFFER_CAPACITY: usize = 8 * (1<<10); // 8 KB
|
pub(crate) const DEFAULT_BUFFER_CAPACITY: usize = 8 * (1<<10); // 8 KB
|
||||||
@@ -122,7 +122,7 @@ impl LineBufferBuilder {
|
|||||||
pub fn build(&self) -> LineBuffer {
|
pub fn build(&self) -> LineBuffer {
|
||||||
LineBuffer {
|
LineBuffer {
|
||||||
config: self.config,
|
config: self.config,
|
||||||
buf: vec![0; self.config.capacity],
|
buf: BString::from(vec![0; self.config.capacity]),
|
||||||
pos: 0,
|
pos: 0,
|
||||||
last_lineterm: 0,
|
last_lineterm: 0,
|
||||||
end: 0,
|
end: 0,
|
||||||
@@ -254,14 +254,13 @@ impl<'b, R: io::Read> LineBufferReader<'b, R> {
|
|||||||
|
|
||||||
/// Return the contents of this buffer.
|
/// Return the contents of this buffer.
|
||||||
pub fn buffer(&self) -> &[u8] {
|
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
|
/// Return the underlying buffer as a byte string. Used for tests only.
|
||||||
/// in tests only.
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
fn bstr(&self) -> &::bstr::BStr {
|
fn bstr(&self) -> &BStr {
|
||||||
self.buffer().as_bstr()
|
self.line_buffer.buffer()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Consume the number of bytes provided. This must be less than or equal
|
/// 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.
|
/// The configuration of this buffer.
|
||||||
config: Config,
|
config: Config,
|
||||||
/// The primary buffer with which to hold data.
|
/// 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
|
/// The current position of this buffer. This is always a valid sliceable
|
||||||
/// index into `buf`, and its maximum value is the length of `buf`.
|
/// index into `buf`, and its maximum value is the length of `buf`.
|
||||||
pos: usize,
|
pos: usize,
|
||||||
@@ -353,13 +352,13 @@ impl LineBuffer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Return the contents of this buffer.
|
/// Return the contents of this buffer.
|
||||||
fn buffer(&self) -> &[u8] {
|
fn buffer(&self) -> &BStr {
|
||||||
&self.buf[self.pos..self.last_lineterm]
|
&self.buf[self.pos..self.last_lineterm]
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the contents of the free space beyond the end of the buffer as
|
/// Return the contents of the free space beyond the end of the buffer as
|
||||||
/// a mutable slice.
|
/// a mutable slice.
|
||||||
fn free_buffer(&mut self) -> &mut [u8] {
|
fn free_buffer(&mut self) -> &mut BStr {
|
||||||
&mut self.buf[self.end..]
|
&mut self.buf[self.end..]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -482,7 +481,7 @@ impl LineBuffer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let roll_len = self.end - self.pos;
|
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.pos = 0;
|
||||||
self.last_lineterm = roll_len;
|
self.last_lineterm = roll_len;
|
||||||
self.end = roll_len;
|
self.end = roll_len;
|
||||||
@@ -520,7 +519,7 @@ impl LineBuffer {
|
|||||||
|
|
||||||
/// Replaces `src` with `replacement` in bytes, and return the offset of the
|
/// Replaces `src` with `replacement` in bytes, and return the offset of the
|
||||||
/// first replacement, if one exists.
|
/// 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 {
|
if src == replacement {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
@@ -543,7 +542,7 @@ fn replace_bytes(bytes: &mut [u8], src: u8, replacement: u8) -> Option<usize> {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::str;
|
use std::str;
|
||||||
use bstr::{ByteSlice, ByteVec};
|
use bstr::BString;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
const SHERLOCK: &'static str = "\
|
const SHERLOCK: &'static str = "\
|
||||||
@@ -564,7 +563,7 @@ and exhibited clearly, with a label attached.\
|
|||||||
src: u8,
|
src: u8,
|
||||||
replacement: u8,
|
replacement: u8,
|
||||||
) -> (String, Option<usize>) {
|
) -> (String, Option<usize>) {
|
||||||
let mut dst = Vec::from(slice);
|
let mut dst = BString::from(slice);
|
||||||
let result = replace_bytes(&mut dst, src, replacement);
|
let result = replace_bytes(&mut dst, src, replacement);
|
||||||
(dst.into_string().unwrap(), result)
|
(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 linebuf = LineBufferBuilder::new().capacity(1).build();
|
||||||
let mut rdr = LineBufferReader::new(bytes.as_bytes(), &mut linebuf);
|
let mut rdr = LineBufferReader::new(bytes.as_bytes(), &mut linebuf);
|
||||||
|
|
||||||
let mut got = vec![];
|
let mut got = BString::new();
|
||||||
while rdr.fill().unwrap() {
|
while rdr.fill().unwrap() {
|
||||||
got.push_str(rdr.buffer());
|
got.push(rdr.buffer());
|
||||||
rdr.consume_all();
|
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.absolute_byte_offset(), bytes.len() as u64);
|
||||||
assert_eq!(rdr.binary_byte_offset(), None);
|
assert_eq!(rdr.binary_byte_offset(), None);
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
A collection of routines for performing operations on lines.
|
A collection of routines for performing operations on lines.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use bstr::ByteSlice;
|
use bstr::B;
|
||||||
use bytecount;
|
use bytecount;
|
||||||
use grep_matcher::{LineTerminator, Match};
|
use grep_matcher::{LineTerminator, Match};
|
||||||
|
|
||||||
@@ -85,7 +85,7 @@ impl LineStep {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn next_impl(&mut self, mut bytes: &[u8]) -> Option<(usize, usize)> {
|
fn next_impl(&mut self, mut bytes: &[u8]) -> Option<(usize, usize)> {
|
||||||
bytes = &bytes[..self.end];
|
bytes = &bytes[..self.end];
|
||||||
match bytes[self.pos..].find_byte(self.line_term) {
|
match B(&bytes[self.pos..]).find_byte(self.line_term) {
|
||||||
None => {
|
None => {
|
||||||
if self.pos < bytes.len() {
|
if self.pos < bytes.len() {
|
||||||
let m = (self.pos, bytes.len());
|
let m = (self.pos, bytes.len());
|
||||||
@@ -135,14 +135,14 @@ pub fn locate(
|
|||||||
line_term: u8,
|
line_term: u8,
|
||||||
range: Match,
|
range: Match,
|
||||||
) -> Match {
|
) -> Match {
|
||||||
let line_start = bytes[..range.start()]
|
let line_start = B(&bytes[..range.start()])
|
||||||
.rfind_byte(line_term)
|
.rfind_byte(line_term)
|
||||||
.map_or(0, |i| i + 1);
|
.map_or(0, |i| i + 1);
|
||||||
let line_end =
|
let line_end =
|
||||||
if range.end() > line_start && bytes[range.end() - 1] == line_term {
|
if range.end() > line_start && bytes[range.end() - 1] == line_term {
|
||||||
range.end()
|
range.end()
|
||||||
} else {
|
} else {
|
||||||
bytes[range.end()..]
|
B(&bytes[range.end()..])
|
||||||
.find_byte(line_term)
|
.find_byte(line_term)
|
||||||
.map_or(bytes.len(), |i| range.end() + i + 1)
|
.map_or(bytes.len(), |i| range.end() + i + 1)
|
||||||
};
|
};
|
||||||
@@ -182,7 +182,7 @@ fn preceding_by_pos(
|
|||||||
pos -= 1;
|
pos -= 1;
|
||||||
}
|
}
|
||||||
loop {
|
loop {
|
||||||
match bytes[..pos].rfind_byte(line_term) {
|
match B(&bytes[..pos]).rfind_byte(line_term) {
|
||||||
None => {
|
None => {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
use std::cmp;
|
use std::cmp;
|
||||||
|
|
||||||
use bstr::ByteSlice;
|
use bstr::B;
|
||||||
|
|
||||||
use grep_matcher::{LineMatchKind, Matcher};
|
use grep_matcher::{LineMatchKind, Matcher};
|
||||||
use lines::{self, LineStep};
|
use lines::{self, LineStep};
|
||||||
@@ -161,7 +161,7 @@ impl<'s, M: Matcher, S: Sink> Core<'s, M, S> {
|
|||||||
BinaryDetection::Convert(b) => b,
|
BinaryDetection::Convert(b) => b,
|
||||||
_ => return Ok(false),
|
_ => 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;
|
let offset = range.start() + i;
|
||||||
self.binary_byte_offset = Some(offset);
|
self.binary_byte_offset = Some(offset);
|
||||||
if !self.binary_data(offset as u64)? {
|
if !self.binary_data(offset as u64)? {
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
use std::error;
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::io;
|
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`
|
/// A `Box<std::error::Error>` can be used as an error for `Sink`
|
||||||
/// implementations out of the box.
|
/// implementations out of the box.
|
||||||
impl SinkError for Box<dyn error::Error> {
|
impl SinkError for Box<::std::error::Error> {
|
||||||
fn error_message<T: fmt::Display>(message: T) -> Box<dyn error::Error> {
|
fn error_message<T: fmt::Display>(message: T) -> Box<::std::error::Error> {
|
||||||
Box::<dyn error::Error>::from(message.to_string())
|
Box::<::std::error::Error>::from(message.to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
use bstr::ByteSlice;
|
use bstr::B;
|
||||||
use grep_matcher::{
|
use grep_matcher::{
|
||||||
LineMatchKind, LineTerminator, Match, Matcher, NoCaptures, NoError,
|
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
|
// Make it interesting and return the last byte in the current
|
||||||
// line.
|
// line.
|
||||||
let i = haystack
|
let i = B(haystack)
|
||||||
.find_byte(self.line_term.unwrap().as_byte())
|
.find_byte(self.line_term.unwrap().as_byte())
|
||||||
.map(|i| i)
|
.map(|i| i)
|
||||||
.unwrap_or(haystack.len() - 1);
|
.unwrap_or(haystack.len() - 1);
|
||||||
|
@@ -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();
|
let mut args: Vec<OsString> = env::args_os().collect();
|
||||||
if args.len() < 2 {
|
if args.len() < 2 {
|
||||||
return Err("Usage: simplegrep <pattern> [<path> ...]".into());
|
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..])
|
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 matcher = RegexMatcher::new_line_matcher(&pattern)?;
|
||||||
let mut searcher = SearcherBuilder::new()
|
let mut searcher = SearcherBuilder::new()
|
||||||
.binary_detection(BinaryDetection::quit(b'\x00'))
|
.binary_detection(BinaryDetection::quit(b'\x00'))
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ignore"
|
name = "ignore"
|
||||||
version = "0.4.10" #:version
|
version = "0.4.7" #:version
|
||||||
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
authors = ["Andrew Gallant <jamslam@gmail.com>"]
|
||||||
description = """
|
description = """
|
||||||
A fast library for efficiently matching ignore files such as `.gitignore`
|
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]
|
[target.'cfg(windows)'.dependencies.winapi-util]
|
||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
tempfile = "3.0.5"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
simd-accel = ["globset/simd-accel"]
|
simd-accel = ["globset/simd-accel"]
|
||||||
|
@@ -14,13 +14,13 @@
|
|||||||
// well.
|
// well.
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::ffi::{OsStr, OsString};
|
use std::ffi::{OsString, OsStr};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
use gitignore::{self, Gitignore, GitignoreBuilder};
|
use gitignore::{self, Gitignore, GitignoreBuilder};
|
||||||
use overrides::{self, Override};
|
|
||||||
use pathutil::{is_hidden, strip_prefix};
|
use pathutil::{is_hidden, strip_prefix};
|
||||||
|
use overrides::{self, Override};
|
||||||
use types::{self, Types};
|
use types::{self, Types};
|
||||||
use walk::DirEntry;
|
use walk::DirEntry;
|
||||||
use {Error, Match, PartialErrorBuilder};
|
use {Error, Match, PartialErrorBuilder};
|
||||||
@@ -152,7 +152,10 @@ impl Ignore {
|
|||||||
///
|
///
|
||||||
/// Note that this can only be called on an `Ignore` matcher with no
|
/// Note that this can only be called on an `Ignore` matcher with no
|
||||||
/// parents (i.e., `is_root` returns `true`). This will panic otherwise.
|
/// 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
|
if !self.0.opts.parents
|
||||||
&& !self.0.opts.git_ignore
|
&& !self.0.opts.git_ignore
|
||||||
&& !self.0.opts.git_exclude
|
&& !self.0.opts.git_exclude
|
||||||
@@ -194,11 +197,12 @@ impl Ignore {
|
|||||||
errs.maybe_push(err);
|
errs.maybe_push(err);
|
||||||
igtmp.is_absolute_parent = true;
|
igtmp.is_absolute_parent = true;
|
||||||
igtmp.absolute_base = Some(absolute_base.clone());
|
igtmp.absolute_base = Some(absolute_base.clone());
|
||||||
igtmp.has_git = if self.0.opts.git_ignore {
|
igtmp.has_git =
|
||||||
parent.join(".git").exists()
|
if self.0.opts.git_ignore {
|
||||||
} else {
|
parent.join(".git").exists()
|
||||||
false
|
} else {
|
||||||
};
|
false
|
||||||
|
};
|
||||||
ig = Ignore(Arc::new(igtmp));
|
ig = Ignore(Arc::new(igtmp));
|
||||||
compiled.insert(parent.as_os_str().to_os_string(), ig.clone());
|
compiled.insert(parent.as_os_str().to_os_string(), ig.clone());
|
||||||
}
|
}
|
||||||
@@ -213,7 +217,10 @@ impl Ignore {
|
|||||||
/// returned if it exists.
|
/// returned if it exists.
|
||||||
///
|
///
|
||||||
/// Note that all I/O errors are completely ignored.
|
/// 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());
|
let (ig, err) = self.add_child_path(dir.as_ref());
|
||||||
(Ignore(Arc::new(ig)), err)
|
(Ignore(Arc::new(ig)), err)
|
||||||
}
|
}
|
||||||
@@ -221,49 +228,64 @@ impl Ignore {
|
|||||||
/// Like add_child, but takes a full path and returns an IgnoreInner.
|
/// Like add_child, but takes a full path and returns an IgnoreInner.
|
||||||
fn add_child_path(&self, dir: &Path) -> (IgnoreInner, Option<Error>) {
|
fn add_child_path(&self, dir: &Path) -> (IgnoreInner, Option<Error>) {
|
||||||
let mut errs = PartialErrorBuilder::default();
|
let mut errs = PartialErrorBuilder::default();
|
||||||
let custom_ig_matcher = if self.0.custom_ignore_filenames.is_empty() {
|
let custom_ig_matcher =
|
||||||
Gitignore::empty()
|
if self.0.custom_ignore_filenames.is_empty() {
|
||||||
} else {
|
Gitignore::empty()
|
||||||
let (m, err) = create_gitignore(
|
} else {
|
||||||
&dir,
|
let (m, err) =
|
||||||
&self.0.custom_ignore_filenames,
|
create_gitignore(
|
||||||
self.0.opts.ignore_case_insensitive,
|
&dir,
|
||||||
);
|
&self.0.custom_ignore_filenames,
|
||||||
errs.maybe_push(err);
|
self.0.opts.ignore_case_insensitive,
|
||||||
m
|
);
|
||||||
};
|
errs.maybe_push(err);
|
||||||
let ig_matcher = if !self.0.opts.ignore {
|
m
|
||||||
Gitignore::empty()
|
};
|
||||||
} else {
|
let ig_matcher =
|
||||||
let (m, err) =
|
if !self.0.opts.ignore {
|
||||||
create_gitignore(&dir, &[".ignore"], self.0.opts.ignore_case_insensitive);
|
Gitignore::empty()
|
||||||
errs.maybe_push(err);
|
} else {
|
||||||
m
|
let (m, err) =
|
||||||
};
|
create_gitignore(
|
||||||
let gi_matcher = if !self.0.opts.git_ignore {
|
&dir,
|
||||||
Gitignore::empty()
|
&[".ignore"],
|
||||||
} else {
|
self.0.opts.ignore_case_insensitive,
|
||||||
let (m, err) =
|
);
|
||||||
create_gitignore(&dir, &[".gitignore"], self.0.opts.ignore_case_insensitive);
|
errs.maybe_push(err);
|
||||||
errs.maybe_push(err);
|
m
|
||||||
m
|
};
|
||||||
};
|
let gi_matcher =
|
||||||
let gi_exclude_matcher = if !self.0.opts.git_exclude {
|
if !self.0.opts.git_ignore {
|
||||||
Gitignore::empty()
|
Gitignore::empty()
|
||||||
} else {
|
} else {
|
||||||
let (m, err) = create_gitignore(
|
let (m, err) =
|
||||||
&dir,
|
create_gitignore(
|
||||||
&[".git/info/exclude"],
|
&dir,
|
||||||
self.0.opts.ignore_case_insensitive,
|
&[".gitignore"],
|
||||||
);
|
self.0.opts.ignore_case_insensitive,
|
||||||
errs.maybe_push(err);
|
);
|
||||||
m
|
errs.maybe_push(err);
|
||||||
};
|
m
|
||||||
let has_git = if self.0.opts.git_ignore {
|
};
|
||||||
dir.join(".git").exists()
|
let gi_exclude_matcher =
|
||||||
} else {
|
if !self.0.opts.git_exclude {
|
||||||
false
|
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 {
|
let ig = IgnoreInner {
|
||||||
compiled: self.0.compiled.clone(),
|
compiled: self.0.compiled.clone(),
|
||||||
dir: dir.to_path_buf(),
|
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_custom_ignore_files = !self.0.custom_ignore_filenames.is_empty();
|
||||||
let has_explicit_ignores = !self.0.explicit_ignores.is_empty();
|
let has_explicit_ignores = !self.0.explicit_ignores.is_empty();
|
||||||
|
|
||||||
opts.ignore
|
opts.ignore || opts.git_global || opts.git_ignore
|
||||||
|| opts.git_global
|
|| opts.git_exclude || has_custom_ignore_files
|
||||||
|| opts.git_ignore
|
|| has_explicit_ignores
|
||||||
|| opts.git_exclude
|
|
||||||
|| has_custom_ignore_files
|
|
||||||
|| has_explicit_ignores
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Like `matched`, but works with a directory entry instead.
|
/// 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());
|
let m = self.matched(dent.path(), dent.is_dir());
|
||||||
if m.is_none() && self.0.opts.hidden && is_hidden(dent) {
|
if m.is_none() && self.0.opts.hidden && is_hidden(dent) {
|
||||||
return Match::Ignore(IgnoreMatch::hidden());
|
return Match::Ignore(IgnoreMatch::hidden());
|
||||||
@@ -312,7 +334,11 @@ impl Ignore {
|
|||||||
/// ignored or not.
|
/// ignored or not.
|
||||||
///
|
///
|
||||||
/// The match contains information about its origin.
|
/// 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
|
// We need to be careful with our path. If it has a leading ./, then
|
||||||
// strip it because it causes nothing but trouble.
|
// strip it because it causes nothing but trouble.
|
||||||
let mut path = path.as_ref();
|
let mut path = path.as_ref();
|
||||||
@@ -324,11 +350,9 @@ impl Ignore {
|
|||||||
// return that result immediately. Overrides have the highest
|
// return that result immediately. Overrides have the highest
|
||||||
// precedence.
|
// precedence.
|
||||||
if !self.0.overrides.is_empty() {
|
if !self.0.overrides.is_empty() {
|
||||||
let mat = self
|
let mat =
|
||||||
.0
|
self.0.overrides.matched(path, is_dir)
|
||||||
.overrides
|
.map(IgnoreMatch::overrides);
|
||||||
.matched(path, is_dir)
|
|
||||||
.map(IgnoreMatch::overrides);
|
|
||||||
if !mat.is_none() {
|
if !mat.is_none() {
|
||||||
return mat;
|
return mat;
|
||||||
}
|
}
|
||||||
@@ -343,7 +367,8 @@ impl Ignore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !self.0.types.is_empty() {
|
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() {
|
if mat.is_ignore() {
|
||||||
return mat;
|
return mat;
|
||||||
} else if mat.is_whitelist() {
|
} else if mat.is_whitelist() {
|
||||||
@@ -355,70 +380,61 @@ impl Ignore {
|
|||||||
|
|
||||||
/// Performs matching only on the ignore files for this directory and
|
/// Performs matching only on the ignore files for this directory and
|
||||||
/// all parent directories.
|
/// all parent directories.
|
||||||
fn matched_ignore<'a>(&'a self, path: &Path, is_dir: bool) -> Match<IgnoreMatch<'a>> {
|
fn matched_ignore<'a>(
|
||||||
let (mut m_custom_ignore, mut m_ignore, mut m_gi, mut m_gi_exclude, mut m_explicit) = (
|
&'a self,
|
||||||
Match::None,
|
path: &Path,
|
||||||
Match::None,
|
is_dir: bool,
|
||||||
Match::None,
|
) -> Match<IgnoreMatch<'a>> {
|
||||||
Match::None,
|
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, Match::None);
|
||||||
);
|
|
||||||
let any_git = self.parents().any(|ig| ig.0.has_git);
|
let any_git = self.parents().any(|ig| ig.0.has_git);
|
||||||
let mut saw_git = false;
|
let mut saw_git = false;
|
||||||
for ig in self.parents().take_while(|ig| !ig.0.is_absolute_parent) {
|
for ig in self.parents().take_while(|ig| !ig.0.is_absolute_parent) {
|
||||||
if m_custom_ignore.is_none() {
|
if m_custom_ignore.is_none() {
|
||||||
m_custom_ignore =
|
m_custom_ignore =
|
||||||
ig.0.custom_ignore_matcher
|
ig.0.custom_ignore_matcher.matched(path, is_dir)
|
||||||
.matched(path, is_dir)
|
.map(IgnoreMatch::gitignore);
|
||||||
.map(IgnoreMatch::gitignore);
|
|
||||||
}
|
}
|
||||||
if m_ignore.is_none() {
|
if m_ignore.is_none() {
|
||||||
m_ignore =
|
m_ignore =
|
||||||
ig.0.ignore_matcher
|
ig.0.ignore_matcher.matched(path, is_dir)
|
||||||
.matched(path, is_dir)
|
.map(IgnoreMatch::gitignore);
|
||||||
.map(IgnoreMatch::gitignore);
|
|
||||||
}
|
}
|
||||||
if any_git && !saw_git && m_gi.is_none() {
|
if any_git && !saw_git && m_gi.is_none() {
|
||||||
m_gi =
|
m_gi =
|
||||||
ig.0.git_ignore_matcher
|
ig.0.git_ignore_matcher.matched(path, is_dir)
|
||||||
.matched(path, is_dir)
|
.map(IgnoreMatch::gitignore);
|
||||||
.map(IgnoreMatch::gitignore);
|
|
||||||
}
|
}
|
||||||
if any_git && !saw_git && m_gi_exclude.is_none() {
|
if any_git && !saw_git && m_gi_exclude.is_none() {
|
||||||
m_gi_exclude =
|
m_gi_exclude =
|
||||||
ig.0.git_exclude_matcher
|
ig.0.git_exclude_matcher.matched(path, is_dir)
|
||||||
.matched(path, is_dir)
|
.map(IgnoreMatch::gitignore);
|
||||||
.map(IgnoreMatch::gitignore);
|
|
||||||
}
|
}
|
||||||
saw_git = saw_git || ig.0.has_git;
|
saw_git = saw_git || ig.0.has_git;
|
||||||
}
|
}
|
||||||
if self.0.opts.parents {
|
if self.0.opts.parents {
|
||||||
if let Some(abs_parent_path) = self.absolute_base() {
|
if let Some(abs_parent_path) = self.absolute_base() {
|
||||||
let path = abs_parent_path.join(path);
|
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() {
|
if m_custom_ignore.is_none() {
|
||||||
m_custom_ignore =
|
m_custom_ignore =
|
||||||
ig.0.custom_ignore_matcher
|
ig.0.custom_ignore_matcher.matched(&path, is_dir)
|
||||||
.matched(&path, is_dir)
|
.map(IgnoreMatch::gitignore);
|
||||||
.map(IgnoreMatch::gitignore);
|
|
||||||
}
|
}
|
||||||
if m_ignore.is_none() {
|
if m_ignore.is_none() {
|
||||||
m_ignore =
|
m_ignore =
|
||||||
ig.0.ignore_matcher
|
ig.0.ignore_matcher.matched(&path, is_dir)
|
||||||
.matched(&path, is_dir)
|
.map(IgnoreMatch::gitignore);
|
||||||
.map(IgnoreMatch::gitignore);
|
|
||||||
}
|
}
|
||||||
if any_git && !saw_git && m_gi.is_none() {
|
if any_git && !saw_git && m_gi.is_none() {
|
||||||
m_gi =
|
m_gi =
|
||||||
ig.0.git_ignore_matcher
|
ig.0.git_ignore_matcher.matched(&path, is_dir)
|
||||||
.matched(&path, is_dir)
|
.map(IgnoreMatch::gitignore);
|
||||||
.map(IgnoreMatch::gitignore);
|
|
||||||
}
|
}
|
||||||
if any_git && !saw_git && m_gi_exclude.is_none() {
|
if any_git && !saw_git && m_gi_exclude.is_none() {
|
||||||
m_gi_exclude =
|
m_gi_exclude =
|
||||||
ig.0.git_exclude_matcher
|
ig.0.git_exclude_matcher.matched(&path, is_dir)
|
||||||
.matched(&path, is_dir)
|
.map(IgnoreMatch::gitignore);
|
||||||
.map(IgnoreMatch::gitignore);
|
|
||||||
}
|
}
|
||||||
saw_git = saw_git || ig.0.has_git;
|
saw_git = saw_git || ig.0.has_git;
|
||||||
}
|
}
|
||||||
@@ -430,21 +446,16 @@ impl Ignore {
|
|||||||
}
|
}
|
||||||
m_explicit = gi.matched(&path, is_dir).map(IgnoreMatch::gitignore);
|
m_explicit = gi.matched(&path, is_dir).map(IgnoreMatch::gitignore);
|
||||||
}
|
}
|
||||||
let m_global = if any_git {
|
let m_global =
|
||||||
self.0
|
if any_git {
|
||||||
.git_global_matcher
|
self.0.git_global_matcher
|
||||||
.matched(&path, is_dir)
|
.matched(&path, is_dir)
|
||||||
.map(IgnoreMatch::gitignore)
|
.map(IgnoreMatch::gitignore)
|
||||||
} else {
|
} else {
|
||||||
Match::None
|
Match::None
|
||||||
};
|
};
|
||||||
|
|
||||||
m_custom_ignore
|
m_custom_ignore.or(m_ignore).or(m_gi).or(m_gi_exclude).or(m_global).or(m_explicit)
|
||||||
.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.
|
/// 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
|
/// The matcher returned won't match anything until ignore rules from
|
||||||
/// directories are added to it.
|
/// directories are added to it.
|
||||||
pub fn build(&self) -> Ignore {
|
pub fn build(&self) -> Ignore {
|
||||||
let git_global_matcher = if !self.opts.git_global {
|
let git_global_matcher =
|
||||||
Gitignore::empty()
|
if !self.opts.git_global {
|
||||||
} else {
|
Gitignore::empty()
|
||||||
let mut builder = GitignoreBuilder::new("");
|
} else {
|
||||||
builder
|
let mut builder = GitignoreBuilder::new("");
|
||||||
.case_insensitive(self.opts.ignore_case_insensitive)
|
builder
|
||||||
.unwrap();
|
.case_insensitive(self.opts.ignore_case_insensitive)
|
||||||
let (gi, err) = builder.build_global();
|
.unwrap();
|
||||||
if let Some(err) = err {
|
let (gi, err) = builder.build_global();
|
||||||
debug!("{}", err);
|
if let Some(err) = err {
|
||||||
}
|
debug!("{}", err);
|
||||||
gi
|
}
|
||||||
};
|
gi
|
||||||
|
};
|
||||||
|
|
||||||
Ignore(Arc::new(IgnoreInner {
|
Ignore(Arc::new(IgnoreInner {
|
||||||
compiled: Arc::new(RwLock::new(HashMap::new())),
|
compiled: Arc::new(RwLock::new(HashMap::new())),
|
||||||
@@ -592,10 +604,9 @@ impl IgnoreBuilder {
|
|||||||
/// later names.
|
/// later names.
|
||||||
pub fn add_custom_ignore_filename<S: AsRef<OsStr>>(
|
pub fn add_custom_ignore_filename<S: AsRef<OsStr>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
file_name: S,
|
file_name: S
|
||||||
) -> &mut IgnoreBuilder {
|
) -> &mut IgnoreBuilder {
|
||||||
self.custom_ignore_filenames
|
self.custom_ignore_filenames.push(file_name.as_ref().to_os_string());
|
||||||
.push(file_name.as_ref().to_os_string());
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -667,7 +678,10 @@ impl IgnoreBuilder {
|
|||||||
/// Process ignore files case insensitively
|
/// Process ignore files case insensitively
|
||||||
///
|
///
|
||||||
/// This is disabled by default.
|
/// 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.opts.ignore_case_insensitive = yes;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@@ -707,9 +721,10 @@ mod tests {
|
|||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
|
use tempfile::{self, TempDir};
|
||||||
|
|
||||||
use dir::IgnoreBuilder;
|
use dir::IgnoreBuilder;
|
||||||
use gitignore::Gitignore;
|
use gitignore::Gitignore;
|
||||||
use tests::TempDir;
|
|
||||||
use Error;
|
use Error;
|
||||||
|
|
||||||
fn wfile<P: AsRef<Path>>(path: P, contents: &str) {
|
fn wfile<P: AsRef<Path>>(path: P, contents: &str) {
|
||||||
@@ -728,21 +743,19 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tmpdir() -> TempDir {
|
fn tmpdir(prefix: &str) -> TempDir {
|
||||||
TempDir::new().unwrap()
|
tempfile::Builder::new().prefix(prefix).tempdir().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn explicit_ignore() {
|
fn explicit_ignore() {
|
||||||
let td = tmpdir();
|
let td = tmpdir("ignore-test-");
|
||||||
wfile(td.path().join("not-an-ignore"), "foo\n!bar");
|
wfile(td.path().join("not-an-ignore"), "foo\n!bar");
|
||||||
|
|
||||||
let (gi, err) = Gitignore::new(td.path().join("not-an-ignore"));
|
let (gi, err) = Gitignore::new(td.path().join("not-an-ignore"));
|
||||||
assert!(err.is_none());
|
assert!(err.is_none());
|
||||||
let (ig, err) = IgnoreBuilder::new()
|
let (ig, err) = IgnoreBuilder::new()
|
||||||
.add_ignore(gi)
|
.add_ignore(gi).build().add_child(td.path());
|
||||||
.build()
|
|
||||||
.add_child(td.path());
|
|
||||||
assert!(err.is_none());
|
assert!(err.is_none());
|
||||||
assert!(ig.matched("foo", false).is_ignore());
|
assert!(ig.matched("foo", false).is_ignore());
|
||||||
assert!(ig.matched("bar", false).is_whitelist());
|
assert!(ig.matched("bar", false).is_whitelist());
|
||||||
@@ -751,7 +764,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn git_exclude() {
|
fn git_exclude() {
|
||||||
let td = tmpdir();
|
let td = tmpdir("ignore-test-");
|
||||||
mkdirp(td.path().join(".git/info"));
|
mkdirp(td.path().join(".git/info"));
|
||||||
wfile(td.path().join(".git/info/exclude"), "foo\n!bar");
|
wfile(td.path().join(".git/info/exclude"), "foo\n!bar");
|
||||||
|
|
||||||
@@ -764,7 +777,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn gitignore() {
|
fn gitignore() {
|
||||||
let td = tmpdir();
|
let td = tmpdir("ignore-test-");
|
||||||
mkdirp(td.path().join(".git"));
|
mkdirp(td.path().join(".git"));
|
||||||
wfile(td.path().join(".gitignore"), "foo\n!bar");
|
wfile(td.path().join(".gitignore"), "foo\n!bar");
|
||||||
|
|
||||||
@@ -777,7 +790,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn gitignore_no_git() {
|
fn gitignore_no_git() {
|
||||||
let td = tmpdir();
|
let td = tmpdir("ignore-test-");
|
||||||
wfile(td.path().join(".gitignore"), "foo\n!bar");
|
wfile(td.path().join(".gitignore"), "foo\n!bar");
|
||||||
|
|
||||||
let (ig, err) = IgnoreBuilder::new().build().add_child(td.path());
|
let (ig, err) = IgnoreBuilder::new().build().add_child(td.path());
|
||||||
@@ -789,7 +802,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ignore() {
|
fn ignore() {
|
||||||
let td = tmpdir();
|
let td = tmpdir("ignore-test-");
|
||||||
wfile(td.path().join(".ignore"), "foo\n!bar");
|
wfile(td.path().join(".ignore"), "foo\n!bar");
|
||||||
|
|
||||||
let (ig, err) = IgnoreBuilder::new().build().add_child(td.path());
|
let (ig, err) = IgnoreBuilder::new().build().add_child(td.path());
|
||||||
@@ -801,14 +814,13 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn custom_ignore() {
|
fn custom_ignore() {
|
||||||
let td = tmpdir();
|
let td = tmpdir("ignore-test-");
|
||||||
let custom_ignore = ".customignore";
|
let custom_ignore = ".customignore";
|
||||||
wfile(td.path().join(custom_ignore), "foo\n!bar");
|
wfile(td.path().join(custom_ignore), "foo\n!bar");
|
||||||
|
|
||||||
let (ig, err) = IgnoreBuilder::new()
|
let (ig, err) = IgnoreBuilder::new()
|
||||||
.add_custom_ignore_filename(custom_ignore)
|
.add_custom_ignore_filename(custom_ignore)
|
||||||
.build()
|
.build().add_child(td.path());
|
||||||
.add_child(td.path());
|
|
||||||
assert!(err.is_none());
|
assert!(err.is_none());
|
||||||
assert!(ig.matched("foo", false).is_ignore());
|
assert!(ig.matched("foo", false).is_ignore());
|
||||||
assert!(ig.matched("bar", false).is_whitelist());
|
assert!(ig.matched("bar", false).is_whitelist());
|
||||||
@@ -818,15 +830,14 @@ mod tests {
|
|||||||
// Tests that a custom ignore file will override an .ignore.
|
// Tests that a custom ignore file will override an .ignore.
|
||||||
#[test]
|
#[test]
|
||||||
fn custom_ignore_over_ignore() {
|
fn custom_ignore_over_ignore() {
|
||||||
let td = tmpdir();
|
let td = tmpdir("ignore-test-");
|
||||||
let custom_ignore = ".customignore";
|
let custom_ignore = ".customignore";
|
||||||
wfile(td.path().join(".ignore"), "foo");
|
wfile(td.path().join(".ignore"), "foo");
|
||||||
wfile(td.path().join(custom_ignore), "!foo");
|
wfile(td.path().join(custom_ignore), "!foo");
|
||||||
|
|
||||||
let (ig, err) = IgnoreBuilder::new()
|
let (ig, err) = IgnoreBuilder::new()
|
||||||
.add_custom_ignore_filename(custom_ignore)
|
.add_custom_ignore_filename(custom_ignore)
|
||||||
.build()
|
.build().add_child(td.path());
|
||||||
.add_child(td.path());
|
|
||||||
assert!(err.is_none());
|
assert!(err.is_none());
|
||||||
assert!(ig.matched("foo", false).is_whitelist());
|
assert!(ig.matched("foo", false).is_whitelist());
|
||||||
}
|
}
|
||||||
@@ -834,7 +845,7 @@ mod tests {
|
|||||||
// Tests that earlier custom ignore files have lower precedence than later.
|
// Tests that earlier custom ignore files have lower precedence than later.
|
||||||
#[test]
|
#[test]
|
||||||
fn custom_ignore_precedence() {
|
fn custom_ignore_precedence() {
|
||||||
let td = tmpdir();
|
let td = tmpdir("ignore-test-");
|
||||||
let custom_ignore1 = ".customignore1";
|
let custom_ignore1 = ".customignore1";
|
||||||
let custom_ignore2 = ".customignore2";
|
let custom_ignore2 = ".customignore2";
|
||||||
wfile(td.path().join(custom_ignore1), "foo");
|
wfile(td.path().join(custom_ignore1), "foo");
|
||||||
@@ -843,8 +854,7 @@ mod tests {
|
|||||||
let (ig, err) = IgnoreBuilder::new()
|
let (ig, err) = IgnoreBuilder::new()
|
||||||
.add_custom_ignore_filename(custom_ignore1)
|
.add_custom_ignore_filename(custom_ignore1)
|
||||||
.add_custom_ignore_filename(custom_ignore2)
|
.add_custom_ignore_filename(custom_ignore2)
|
||||||
.build()
|
.build().add_child(td.path());
|
||||||
.add_child(td.path());
|
|
||||||
assert!(err.is_none());
|
assert!(err.is_none());
|
||||||
assert!(ig.matched("foo", false).is_whitelist());
|
assert!(ig.matched("foo", false).is_whitelist());
|
||||||
}
|
}
|
||||||
@@ -852,7 +862,7 @@ mod tests {
|
|||||||
// Tests that an .ignore will override a .gitignore.
|
// Tests that an .ignore will override a .gitignore.
|
||||||
#[test]
|
#[test]
|
||||||
fn ignore_over_gitignore() {
|
fn ignore_over_gitignore() {
|
||||||
let td = tmpdir();
|
let td = tmpdir("ignore-test-");
|
||||||
wfile(td.path().join(".gitignore"), "foo");
|
wfile(td.path().join(".gitignore"), "foo");
|
||||||
wfile(td.path().join(".ignore"), "!foo");
|
wfile(td.path().join(".ignore"), "!foo");
|
||||||
|
|
||||||
@@ -864,7 +874,7 @@ mod tests {
|
|||||||
// Tests that exclude has lower precedent than both .ignore and .gitignore.
|
// Tests that exclude has lower precedent than both .ignore and .gitignore.
|
||||||
#[test]
|
#[test]
|
||||||
fn exclude_lowest() {
|
fn exclude_lowest() {
|
||||||
let td = tmpdir();
|
let td = tmpdir("ignore-test-");
|
||||||
wfile(td.path().join(".gitignore"), "!foo");
|
wfile(td.path().join(".gitignore"), "!foo");
|
||||||
wfile(td.path().join(".ignore"), "!bar");
|
wfile(td.path().join(".ignore"), "!bar");
|
||||||
mkdirp(td.path().join(".git/info"));
|
mkdirp(td.path().join(".git/info"));
|
||||||
@@ -879,7 +889,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn errored() {
|
fn errored() {
|
||||||
let td = tmpdir();
|
let td = tmpdir("ignore-test-");
|
||||||
wfile(td.path().join(".gitignore"), "{foo");
|
wfile(td.path().join(".gitignore"), "{foo");
|
||||||
|
|
||||||
let (_, err) = IgnoreBuilder::new().build().add_child(td.path());
|
let (_, err) = IgnoreBuilder::new().build().add_child(td.path());
|
||||||
@@ -888,7 +898,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn errored_both() {
|
fn errored_both() {
|
||||||
let td = tmpdir();
|
let td = tmpdir("ignore-test-");
|
||||||
wfile(td.path().join(".gitignore"), "{foo");
|
wfile(td.path().join(".gitignore"), "{foo");
|
||||||
wfile(td.path().join(".ignore"), "{bar");
|
wfile(td.path().join(".ignore"), "{bar");
|
||||||
|
|
||||||
@@ -898,7 +908,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn errored_partial() {
|
fn errored_partial() {
|
||||||
let td = tmpdir();
|
let td = tmpdir("ignore-test-");
|
||||||
mkdirp(td.path().join(".git"));
|
mkdirp(td.path().join(".git"));
|
||||||
wfile(td.path().join(".gitignore"), "{foo\nbar");
|
wfile(td.path().join(".gitignore"), "{foo\nbar");
|
||||||
|
|
||||||
@@ -909,7 +919,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn errored_partial_and_ignore() {
|
fn errored_partial_and_ignore() {
|
||||||
let td = tmpdir();
|
let td = tmpdir("ignore-test-");
|
||||||
wfile(td.path().join(".gitignore"), "{foo\nbar");
|
wfile(td.path().join(".gitignore"), "{foo\nbar");
|
||||||
wfile(td.path().join(".ignore"), "!bar");
|
wfile(td.path().join(".ignore"), "!bar");
|
||||||
|
|
||||||
@@ -920,7 +930,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn not_present_empty() {
|
fn not_present_empty() {
|
||||||
let td = tmpdir();
|
let td = tmpdir("ignore-test-");
|
||||||
|
|
||||||
let (_, err) = IgnoreBuilder::new().build().add_child(td.path());
|
let (_, err) = IgnoreBuilder::new().build().add_child(td.path());
|
||||||
assert!(err.is_none());
|
assert!(err.is_none());
|
||||||
@@ -930,7 +940,7 @@ mod tests {
|
|||||||
fn stops_at_git_dir() {
|
fn stops_at_git_dir() {
|
||||||
// This tests that .gitignore files beyond a .git barrier aren't
|
// This tests that .gitignore files beyond a .git barrier aren't
|
||||||
// matched, but .ignore files are.
|
// matched, but .ignore files are.
|
||||||
let td = tmpdir();
|
let td = tmpdir("ignore-test-");
|
||||||
mkdirp(td.path().join(".git"));
|
mkdirp(td.path().join(".git"));
|
||||||
mkdirp(td.path().join("foo/.git"));
|
mkdirp(td.path().join("foo/.git"));
|
||||||
wfile(td.path().join(".gitignore"), "foo");
|
wfile(td.path().join(".gitignore"), "foo");
|
||||||
@@ -951,7 +961,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn absolute_parent() {
|
fn absolute_parent() {
|
||||||
let td = tmpdir();
|
let td = tmpdir("ignore-test-");
|
||||||
mkdirp(td.path().join(".git"));
|
mkdirp(td.path().join(".git"));
|
||||||
mkdirp(td.path().join("foo"));
|
mkdirp(td.path().join("foo"));
|
||||||
wfile(td.path().join(".gitignore"), "bar");
|
wfile(td.path().join(".gitignore"), "bar");
|
||||||
@@ -974,7 +984,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn absolute_parent_anchored() {
|
fn absolute_parent_anchored() {
|
||||||
let td = tmpdir();
|
let td = tmpdir("ignore-test-");
|
||||||
mkdirp(td.path().join(".git"));
|
mkdirp(td.path().join(".git"));
|
||||||
mkdirp(td.path().join("src/llvm"));
|
mkdirp(td.path().join("src/llvm"));
|
||||||
wfile(td.path().join(".gitignore"), "/llvm/\nfoo");
|
wfile(td.path().join(".gitignore"), "/llvm/\nfoo");
|
||||||
|
@@ -537,7 +537,7 @@ impl GitignoreBuilder {
|
|||||||
///
|
///
|
||||||
/// Note that the file path returned may not exist.
|
/// Note that the file path returned may not exist.
|
||||||
fn gitconfig_excludes_path() -> Option<PathBuf> {
|
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
|
// both can be active at the same time, where $HOME/.gitconfig takes
|
||||||
// precedent. So if $HOME/.gitconfig defines a `core.excludesFile`, then
|
// precedent. So if $HOME/.gitconfig defines a `core.excludesFile`, then
|
||||||
// we're done.
|
// 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
|
/// 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>> {
|
fn gitconfig_xdg_contents() -> Option<Vec<u8>> {
|
||||||
let path = env::var_os("XDG_CONFIG_HOME")
|
let path = env::var_os("XDG_CONFIG_HOME")
|
||||||
.and_then(|x| if x.is_empty() { None } else { Some(PathBuf::from(x)) })
|
.and_then(|x| if x.is_empty() { None } else { Some(PathBuf::from(x)) })
|
||||||
|
@@ -55,6 +55,8 @@ extern crate log;
|
|||||||
extern crate memchr;
|
extern crate memchr;
|
||||||
extern crate regex;
|
extern crate regex;
|
||||||
extern crate same_file;
|
extern crate same_file;
|
||||||
|
#[cfg(test)]
|
||||||
|
extern crate tempfile;
|
||||||
extern crate thread_local;
|
extern crate thread_local;
|
||||||
extern crate walkdir;
|
extern crate walkdir;
|
||||||
#[cfg(windows)]
|
#[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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@@ -135,7 +135,6 @@ const DEFAULT_TYPES: &'static [(&'static str, &'static [&'static str])] = &[
|
|||||||
("d", &["*.d"]),
|
("d", &["*.d"]),
|
||||||
("dhall", &["*.dhall"]),
|
("dhall", &["*.dhall"]),
|
||||||
("docker", &["*Dockerfile*"]),
|
("docker", &["*Dockerfile*"]),
|
||||||
("edn", &["*.edn"]),
|
|
||||||
("elisp", &["*.el"]),
|
("elisp", &["*.el"]),
|
||||||
("elixir", &["*.ex", "*.eex", "*.exs"]),
|
("elixir", &["*.ex", "*.eex", "*.exs"]),
|
||||||
("elm", &["*.elm"]),
|
("elm", &["*.elm"]),
|
||||||
@@ -220,7 +219,7 @@ const DEFAULT_TYPES: &'static [(&'static str, &'static [&'static str])] = &[
|
|||||||
("msbuild", &[
|
("msbuild", &[
|
||||||
"*.csproj", "*.fsproj", "*.vcxproj", "*.proj", "*.props", "*.targets"
|
"*.csproj", "*.fsproj", "*.vcxproj", "*.proj", "*.props", "*.targets"
|
||||||
]),
|
]),
|
||||||
("nim", &["*.nim", "*.nimf", "*.nimble", "*.nims"]),
|
("nim", &["*.nim"]),
|
||||||
("nix", &["*.nix"]),
|
("nix", &["*.nix"]),
|
||||||
("objc", &["*.h", "*.m"]),
|
("objc", &["*.h", "*.m"]),
|
||||||
("objcpp", &["*.h", "*.mm"]),
|
("objcpp", &["*.h", "*.mm"]),
|
||||||
@@ -242,7 +241,6 @@ const DEFAULT_TYPES: &'static [(&'static str, &'static [&'static str])] = &[
|
|||||||
("readme", &["README*", "*README"]),
|
("readme", &["README*", "*README"]),
|
||||||
("r", &["*.R", "*.r", "*.Rmd", "*.Rnw"]),
|
("r", &["*.R", "*.r", "*.Rmd", "*.Rnw"]),
|
||||||
("rdoc", &["*.rdoc"]),
|
("rdoc", &["*.rdoc"]),
|
||||||
("robot", &["*.robot"]),
|
|
||||||
("rst", &["*.rst"]),
|
("rst", &["*.rst"]),
|
||||||
("ruby", &["Gemfile", "*.gemspec", ".irbrc", "Rakefile", "*.rb"]),
|
("ruby", &["Gemfile", "*.gemspec", ".irbrc", "Rakefile", "*.rb"]),
|
||||||
("rust", &["*.rs"]),
|
("rust", &["*.rs"]),
|
||||||
|
@@ -4,8 +4,8 @@ use std::fmt;
|
|||||||
use std::fs::{self, FileType, Metadata};
|
use std::fs::{self, FileType, Metadata};
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::vec;
|
use std::vec;
|
||||||
@@ -182,14 +182,14 @@ impl DirEntryInner {
|
|||||||
match *self {
|
match *self {
|
||||||
Stdin => {
|
Stdin => {
|
||||||
let err = Error::Io(io::Error::new(
|
let err = Error::Io(io::Error::new(
|
||||||
io::ErrorKind::Other,
|
io::ErrorKind::Other, "<stdin> has no metadata"));
|
||||||
"<stdin> has no metadata",
|
|
||||||
));
|
|
||||||
Err(err.with_path("<stdin>"))
|
Err(err.with_path("<stdin>"))
|
||||||
}
|
}
|
||||||
Walkdir(ref x) => x
|
Walkdir(ref x) => {
|
||||||
.metadata()
|
x.metadata().map_err(|err| {
|
||||||
.map_err(|err| Error::Io(io::Error::from(err)).with_path(x.path())),
|
Error::Io(io::Error::from(err)).with_path(x.path())
|
||||||
|
})
|
||||||
|
}
|
||||||
Raw(ref x) => x.metadata(),
|
Raw(ref x) => x.metadata(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -223,8 +223,8 @@ impl DirEntryInner {
|
|||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
fn ino(&self) -> Option<u64> {
|
fn ino(&self) -> Option<u64> {
|
||||||
use self::DirEntryInner::*;
|
|
||||||
use walkdir::DirEntryExt;
|
use walkdir::DirEntryExt;
|
||||||
|
use self::DirEntryInner::*;
|
||||||
match *self {
|
match *self {
|
||||||
Stdin => None,
|
Stdin => None,
|
||||||
Walkdir(ref x) => Some(x.ino()),
|
Walkdir(ref x) => Some(x.ino()),
|
||||||
@@ -297,8 +297,7 @@ impl DirEntryRaw {
|
|||||||
fs::metadata(&self.path)
|
fs::metadata(&self.path)
|
||||||
} else {
|
} else {
|
||||||
Ok(self.metadata.clone())
|
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))]
|
#[cfg(not(windows))]
|
||||||
@@ -307,8 +306,7 @@ impl DirEntryRaw {
|
|||||||
fs::metadata(&self.path)
|
fs::metadata(&self.path)
|
||||||
} else {
|
} else {
|
||||||
fs::symlink_metadata(&self.path)
|
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 {
|
fn file_type(&self) -> FileType {
|
||||||
@@ -316,9 +314,7 @@ impl DirEntryRaw {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn file_name(&self) -> &OsStr {
|
fn file_name(&self) -> &OsStr {
|
||||||
self.path
|
self.path.file_name().unwrap_or_else(|| self.path.as_os_str())
|
||||||
.file_name()
|
|
||||||
.unwrap_or_else(|| self.path.as_os_str())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn depth(&self) -> usize {
|
fn depth(&self) -> usize {
|
||||||
@@ -330,7 +326,10 @@ impl DirEntryRaw {
|
|||||||
self.ino
|
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 ty = ent.file_type().map_err(|err| {
|
||||||
let err = Error::Io(io::Error::from(err)).with_path(ent.path());
|
let err = Error::Io(io::Error::from(err)).with_path(ent.path());
|
||||||
Error::WithDepth {
|
Error::WithDepth {
|
||||||
@@ -380,22 +379,15 @@ impl DirEntryRaw {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Placeholder implementation to allow compiling on non-standard platforms (e.g. wasm32).
|
#[cfg(not(unix))]
|
||||||
#[cfg(not(any(windows, unix)))]
|
fn from_path(
|
||||||
fn from_entry_os(
|
|
||||||
depth: usize,
|
depth: usize,
|
||||||
ent: &fs::DirEntry,
|
pb: PathBuf,
|
||||||
ty: fs::FileType,
|
link: bool,
|
||||||
) -> Result<DirEntryRaw, Error> {
|
) -> Result<DirEntryRaw, Error> {
|
||||||
Err(Error::Io(io::Error::new(
|
let md = fs::metadata(&pb).map_err(|err| {
|
||||||
io::ErrorKind::Other,
|
Error::Io(err).with_path(&pb)
|
||||||
"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))?;
|
|
||||||
Ok(DirEntryRaw {
|
Ok(DirEntryRaw {
|
||||||
path: pb,
|
path: pb,
|
||||||
ty: md.file_type(),
|
ty: md.file_type(),
|
||||||
@@ -406,10 +398,16 @@ impl DirEntryRaw {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[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;
|
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 {
|
Ok(DirEntryRaw {
|
||||||
path: pb,
|
path: pb,
|
||||||
ty: md.file_type(),
|
ty: md.file_type(),
|
||||||
@@ -418,15 +416,6 @@ impl DirEntryRaw {
|
|||||||
ino: md.ino(),
|
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.
|
/// WalkBuilder builds a recursive directory iterator.
|
||||||
@@ -492,8 +481,8 @@ pub struct WalkBuilder {
|
|||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
enum Sorter {
|
enum Sorter {
|
||||||
ByName(Arc<dyn Fn(&OsStr, &OsStr) -> cmp::Ordering + Send + Sync + 'static>),
|
ByName(Arc<Fn(&OsStr, &OsStr) -> cmp::Ordering + Send + Sync + 'static>),
|
||||||
ByPath(Arc<dyn Fn(&Path, &Path) -> cmp::Ordering + Send + Sync + 'static>),
|
ByPath(Arc<Fn(&Path, &Path) -> cmp::Ordering + Send + Sync + 'static>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for WalkBuilder {
|
impl fmt::Debug for WalkBuilder {
|
||||||
@@ -536,34 +525,33 @@ impl WalkBuilder {
|
|||||||
let follow_links = self.follow_links;
|
let follow_links = self.follow_links;
|
||||||
let max_depth = self.max_depth;
|
let max_depth = self.max_depth;
|
||||||
let sorter = self.sorter.clone();
|
let sorter = self.sorter.clone();
|
||||||
let its = self
|
let its = self.paths.iter().map(move |p| {
|
||||||
.paths
|
if p == Path::new("-") {
|
||||||
.iter()
|
(p.to_path_buf(), None)
|
||||||
.map(move |p| {
|
} else {
|
||||||
if p == Path::new("-") {
|
let mut wd = WalkDir::new(p);
|
||||||
(p.to_path_buf(), None)
|
wd = wd.follow_links(follow_links || p.is_file());
|
||||||
} else {
|
wd = wd.same_file_system(self.same_file_system);
|
||||||
let mut wd = WalkDir::new(p);
|
if let Some(max_depth) = max_depth {
|
||||||
wd = wd.follow_links(follow_links || p.is_file());
|
wd = wd.max_depth(max_depth);
|
||||||
wd = wd.same_file_system(self.same_file_system);
|
}
|
||||||
if let Some(max_depth) = max_depth {
|
if let Some(ref sorter) = sorter {
|
||||||
wd = wd.max_depth(max_depth);
|
match sorter.clone() {
|
||||||
}
|
Sorter::ByName(cmp) => {
|
||||||
if let Some(ref sorter) = sorter {
|
wd = wd.sort_by(move |a, b| {
|
||||||
match sorter.clone() {
|
cmp(a.file_name(), b.file_name())
|
||||||
Sorter::ByName(cmp) => {
|
});
|
||||||
wd = wd.sort_by(move |a, b| cmp(a.file_name(), b.file_name()));
|
}
|
||||||
}
|
Sorter::ByPath(cmp) => {
|
||||||
Sorter::ByPath(cmp) => {
|
wd = wd.sort_by(move |a, b| {
|
||||||
wd = wd.sort_by(move |a, b| cmp(a.path(), b.path()));
|
cmp(a.path(), b.path())
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(p.to_path_buf(), Some(WalkEventIter::from(wd)))
|
|
||||||
}
|
}
|
||||||
})
|
(p.to_path_buf(), Some(WalkEventIter::from(wd)))
|
||||||
.collect::<Vec<_>>()
|
}
|
||||||
.into_iter();
|
}).collect::<Vec<_>>().into_iter();
|
||||||
let ig_root = self.ig_builder.build();
|
let ig_root = self.ig_builder.build();
|
||||||
Walk {
|
Walk {
|
||||||
its: its,
|
its: its,
|
||||||
@@ -647,12 +635,8 @@ impl WalkBuilder {
|
|||||||
let mut errs = PartialErrorBuilder::default();
|
let mut errs = PartialErrorBuilder::default();
|
||||||
errs.maybe_push(builder.add(path));
|
errs.maybe_push(builder.add(path));
|
||||||
match builder.build() {
|
match builder.build() {
|
||||||
Ok(gi) => {
|
Ok(gi) => { self.ig_builder.add_ignore(gi); }
|
||||||
self.ig_builder.add_ignore(gi);
|
Err(err) => { errs.push(err); }
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
errs.push(err);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
errs.into_error_option()
|
errs.into_error_option()
|
||||||
}
|
}
|
||||||
@@ -665,7 +649,7 @@ impl WalkBuilder {
|
|||||||
/// later names.
|
/// later names.
|
||||||
pub fn add_custom_ignore_filename<S: AsRef<OsStr>>(
|
pub fn add_custom_ignore_filename<S: AsRef<OsStr>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
file_name: S,
|
file_name: S
|
||||||
) -> &mut WalkBuilder {
|
) -> &mut WalkBuilder {
|
||||||
self.ig_builder.add_custom_ignore_filename(file_name);
|
self.ig_builder.add_custom_ignore_filename(file_name);
|
||||||
self
|
self
|
||||||
@@ -802,9 +786,11 @@ impl WalkBuilder {
|
|||||||
/// by `sort_by_file_name`.
|
/// by `sort_by_file_name`.
|
||||||
///
|
///
|
||||||
/// Note that this is not used in the parallel iterator.
|
/// Note that this is not used in the parallel iterator.
|
||||||
pub fn sort_by_file_path<F>(&mut self, cmp: F) -> &mut WalkBuilder
|
pub fn sort_by_file_path<F>(
|
||||||
where
|
&mut self,
|
||||||
F: Fn(&Path, &Path) -> cmp::Ordering + Send + Sync + 'static,
|
cmp: F,
|
||||||
|
) -> &mut WalkBuilder
|
||||||
|
where F: Fn(&Path, &Path) -> cmp::Ordering + Send + Sync + 'static
|
||||||
{
|
{
|
||||||
self.sorter = Some(Sorter::ByPath(Arc::new(cmp)));
|
self.sorter = Some(Sorter::ByPath(Arc::new(cmp)));
|
||||||
self
|
self
|
||||||
@@ -822,8 +808,7 @@ impl WalkBuilder {
|
|||||||
///
|
///
|
||||||
/// Note that this is not used in the parallel iterator.
|
/// Note that this is not used in the parallel iterator.
|
||||||
pub fn sort_by_file_name<F>(&mut self, cmp: F) -> &mut WalkBuilder
|
pub fn sort_by_file_name<F>(&mut self, cmp: F) -> &mut WalkBuilder
|
||||||
where
|
where F: Fn(&OsStr, &OsStr) -> cmp::Ordering + Send + Sync + 'static
|
||||||
F: Fn(&OsStr, &OsStr) -> cmp::Ordering + Send + Sync + 'static,
|
|
||||||
{
|
{
|
||||||
self.sorter = Some(Sorter::ByName(Arc::new(cmp)));
|
self.sorter = Some(Sorter::ByName(Arc::new(cmp)));
|
||||||
self
|
self
|
||||||
@@ -1004,11 +989,7 @@ enum WalkEvent {
|
|||||||
|
|
||||||
impl From<WalkDir> for WalkEventIter {
|
impl From<WalkDir> for WalkEventIter {
|
||||||
fn from(it: WalkDir) -> WalkEventIter {
|
fn from(it: WalkDir) -> WalkEventIter {
|
||||||
WalkEventIter {
|
WalkEventIter { depth: 0, it: it.into_iter(), next: None }
|
||||||
depth: 0,
|
|
||||||
it: it.into_iter(),
|
|
||||||
next: None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1091,10 +1072,10 @@ impl WalkParallel {
|
|||||||
/// Execute the parallel recursive directory iterator. `mkf` is called
|
/// Execute the parallel recursive directory iterator. `mkf` is called
|
||||||
/// for each thread used for iteration. The function produced by `mkf`
|
/// for each thread used for iteration. The function produced by `mkf`
|
||||||
/// is then in turn called for each visited file path.
|
/// is then in turn called for each visited file path.
|
||||||
pub fn run<F>(self, mut mkf: F)
|
pub fn run<F>(
|
||||||
where
|
self,
|
||||||
F: FnMut() -> Box<dyn FnMut(Result<DirEntry, Error>) -> WalkState + Send + 'static>,
|
mut mkf: F,
|
||||||
{
|
) where F: FnMut() -> Box<FnMut(Result<DirEntry, Error>) -> WalkState + Send + 'static> {
|
||||||
let mut f = mkf();
|
let mut f = mkf();
|
||||||
let threads = self.threads();
|
let threads = self.threads();
|
||||||
// TODO: Figure out how to use a bounded channel here. With an
|
// 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
|
// Note that we only send directories. For files, we send to them the
|
||||||
// callback directly.
|
// callback directly.
|
||||||
for path in self.paths {
|
for path in self.paths {
|
||||||
let (dent, root_device) = if path == Path::new("-") {
|
let (dent, root_device) =
|
||||||
(DirEntry::new_stdin(), None)
|
if path == Path::new("-") {
|
||||||
} else {
|
(DirEntry::new_stdin(), None)
|
||||||
let root_device = if !self.same_file_system {
|
|
||||||
None
|
|
||||||
} else {
|
} else {
|
||||||
match device_num(&path) {
|
let root_device =
|
||||||
Ok(root_device) => Some(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) => {
|
Err(err) => {
|
||||||
let err = Error::Io(err).with_path(path);
|
|
||||||
if f(Err(err)).is_quit() {
|
if f(Err(err)).is_quit() {
|
||||||
return;
|
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 {
|
tx.send(Message::Work(Work {
|
||||||
dent: dent,
|
dent: dent,
|
||||||
ignore: self.ig_root.clone(),
|
ignore: self.ig_root.clone(),
|
||||||
root_device: root_device,
|
root_device: root_device,
|
||||||
}))
|
})).unwrap();
|
||||||
.unwrap();
|
|
||||||
any_work = true;
|
any_work = true;
|
||||||
}
|
}
|
||||||
// ... but there's no need to start workers if we don't need them.
|
// ... 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.
|
/// Note that a worker is *both* a producer and a consumer.
|
||||||
struct Worker {
|
struct Worker {
|
||||||
/// The caller's callback.
|
/// 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.
|
/// The push side of our mpmc queue.
|
||||||
tx: channel::Sender<Message>,
|
tx: channel::Sender<Message>,
|
||||||
/// The receive side of our mpmc queue.
|
/// The receive side of our mpmc queue.
|
||||||
@@ -1335,21 +1319,22 @@ impl Worker {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let descend = if let Some(root_device) = work.root_device {
|
let descend =
|
||||||
match is_same_file_system(root_device, work.dent.path()) {
|
if let Some(root_device) = work.root_device {
|
||||||
Ok(true) => true,
|
match is_same_file_system(root_device, work.dent.path()) {
|
||||||
Ok(false) => false,
|
Ok(true) => true,
|
||||||
Err(err) => {
|
Ok(false) => false,
|
||||||
if (self.f)(Err(err)).is_quit() {
|
Err(err) => {
|
||||||
self.quit_now();
|
if (self.f)(Err(err)).is_quit() {
|
||||||
return;
|
self.quit_now();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
false
|
||||||
}
|
}
|
||||||
false
|
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
} else {
|
true
|
||||||
true
|
};
|
||||||
};
|
|
||||||
|
|
||||||
let depth = work.dent.depth();
|
let depth = work.dent.depth();
|
||||||
match (self.f)(Ok(work.dent)) {
|
match (self.f)(Ok(work.dent)) {
|
||||||
@@ -1367,7 +1352,12 @@ impl Worker {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for result in readdir {
|
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() {
|
if state.is_quit() {
|
||||||
self.quit_now();
|
self.quit_now();
|
||||||
return;
|
return;
|
||||||
@@ -1432,24 +1422,23 @@ impl Worker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let should_skip_path = should_skip_entry(ig, &dent);
|
let should_skip_path = should_skip_entry(ig, &dent);
|
||||||
let should_skip_filesize = if self.max_filesize.is_some() && !dent.is_dir() {
|
let should_skip_filesize =
|
||||||
skip_filesize(
|
if self.max_filesize.is_some() && !dent.is_dir() {
|
||||||
self.max_filesize.unwrap(),
|
skip_filesize(
|
||||||
dent.path(),
|
self.max_filesize.unwrap(),
|
||||||
&dent.metadata().ok(),
|
dent.path(),
|
||||||
)
|
&dent.metadata().ok(),
|
||||||
} else {
|
)
|
||||||
false
|
} else {
|
||||||
};
|
false
|
||||||
|
};
|
||||||
|
|
||||||
if !should_skip_path && !should_skip_filesize {
|
if !should_skip_path && !should_skip_filesize {
|
||||||
self.tx
|
self.tx.send(Message::Work(Work {
|
||||||
.send(Message::Work(Work {
|
dent: dent,
|
||||||
dent: dent,
|
ignore: ig.clone(),
|
||||||
ignore: ig.clone(),
|
root_device: root_device,
|
||||||
root_device: root_device,
|
})).unwrap();
|
||||||
}))
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
WalkState::Continue
|
WalkState::Continue
|
||||||
}
|
}
|
||||||
@@ -1579,25 +1568,17 @@ fn check_symlink_loop(
|
|||||||
child_depth: usize,
|
child_depth: usize,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let hchild = Handle::from_path(child_path).map_err(|err| {
|
let hchild = Handle::from_path(child_path).map_err(|err| {
|
||||||
Error::from(err)
|
Error::from(err).with_path(child_path).with_depth(child_depth)
|
||||||
.with_path(child_path)
|
|
||||||
.with_depth(child_depth)
|
|
||||||
})?;
|
})?;
|
||||||
for ig in ig_parent
|
for ig in ig_parent.parents().take_while(|ig| !ig.is_absolute_parent()) {
|
||||||
.parents()
|
|
||||||
.take_while(|ig| !ig.is_absolute_parent())
|
|
||||||
{
|
|
||||||
let h = Handle::from_path(ig.path()).map_err(|err| {
|
let h = Handle::from_path(ig.path()).map_err(|err| {
|
||||||
Error::from(err)
|
Error::from(err).with_path(child_path).with_depth(child_depth)
|
||||||
.with_path(child_path)
|
|
||||||
.with_depth(child_depth)
|
|
||||||
})?;
|
})?;
|
||||||
if hchild == h {
|
if hchild == h {
|
||||||
return Err(Error::Loop {
|
return Err(Error::Loop {
|
||||||
ancestor: ig.path().to_path_buf(),
|
ancestor: ig.path().to_path_buf(),
|
||||||
child: child_path.to_path_buf(),
|
child: child_path.to_path_buf(),
|
||||||
}
|
}.with_depth(child_depth));
|
||||||
.with_depth(child_depth));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -1605,10 +1586,14 @@ fn check_symlink_loop(
|
|||||||
|
|
||||||
// Before calling this function, make sure that you ensure that is really
|
// Before calling this function, make sure that you ensure that is really
|
||||||
// necessary as the arguments imply a file stat.
|
// 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 {
|
let filesize = match *ent {
|
||||||
Some(ref md) => Some(md.len()),
|
Some(ref md) => Some(md.len()),
|
||||||
None => None,
|
None => None
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(fs) = filesize {
|
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);
|
let m = ig.matched_dir_entry(dent);
|
||||||
if m.is_ignore() {
|
if m.is_ignore() {
|
||||||
debug!("ignoring {}: {:?}", dent.path().display(), m);
|
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
|
/// Returns true if and only if the given path is on the same device as the
|
||||||
/// given root device.
|
/// given root device.
|
||||||
fn is_same_file_system(root_device: u64, path: &Path) -> Result<bool, Error> {
|
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)
|
Ok(root_device == dent_device)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[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;
|
use std::os::unix::fs::MetadataExt;
|
||||||
|
|
||||||
path.as_ref().metadata().map(|md| md.dev())
|
path.as_ref().metadata().map(|md| md.dev())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
fn device_num<P: AsRef<Path>>(path: P) -> io::Result<u64> {
|
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)?;
|
let h = Handle::from_path_any(path)?;
|
||||||
file::information(h).map(|info| info.volume_serial_number())
|
file::information(h).map(|info| info.volume_serial_number())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(any(unix, windows)))]
|
#[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(
|
Err(io::Error::new(
|
||||||
io::ErrorKind::Other,
|
io::ErrorKind::Other,
|
||||||
"walkdir: same_file_system option not supported on this platform",
|
"walkdir: same_file_system option not supported on this platform",
|
||||||
@@ -1719,8 +1708,9 @@ mod tests {
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
|
use tempfile::{self, TempDir};
|
||||||
|
|
||||||
use super::{DirEntry, WalkBuilder, WalkState};
|
use super::{DirEntry, WalkBuilder, WalkState};
|
||||||
use tests::TempDir;
|
|
||||||
|
|
||||||
fn wfile<P: AsRef<Path>>(path: P, contents: &str) {
|
fn wfile<P: AsRef<Path>>(path: P, contents: &str) {
|
||||||
let mut file = File::create(path).unwrap();
|
let mut file = File::create(path).unwrap();
|
||||||
@@ -1767,7 +1757,10 @@ mod tests {
|
|||||||
paths
|
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![];
|
let mut paths = vec![];
|
||||||
for dent in walk_collect_entries_parallel(builder) {
|
for dent in walk_collect_entries_parallel(builder) {
|
||||||
let path = dent.path().strip_prefix(prefix).unwrap();
|
let path = dent.path().strip_prefix(prefix).unwrap();
|
||||||
@@ -1802,11 +1795,15 @@ mod tests {
|
|||||||
paths
|
paths
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tmpdir() -> TempDir {
|
fn tmpdir(prefix: &str) -> TempDir {
|
||||||
TempDir::new().unwrap()
|
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);
|
let got = walk_collect(prefix, builder);
|
||||||
assert_eq!(got, mkpaths(expected), "single threaded");
|
assert_eq!(got, mkpaths(expected), "single threaded");
|
||||||
let got = walk_collect_parallel(prefix, builder);
|
let got = walk_collect_parallel(prefix, builder);
|
||||||
@@ -1815,22 +1812,20 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn no_ignores() {
|
fn no_ignores() {
|
||||||
let td = tmpdir();
|
let td = tmpdir("walk-test-");
|
||||||
mkdirp(td.path().join("a/b/c"));
|
mkdirp(td.path().join("a/b/c"));
|
||||||
mkdirp(td.path().join("x/y"));
|
mkdirp(td.path().join("x/y"));
|
||||||
wfile(td.path().join("a/b/foo"), "");
|
wfile(td.path().join("a/b/foo"), "");
|
||||||
wfile(td.path().join("x/y/foo"), "");
|
wfile(td.path().join("x/y/foo"), "");
|
||||||
|
|
||||||
assert_paths(
|
assert_paths(td.path(), &WalkBuilder::new(td.path()), &[
|
||||||
td.path(),
|
"x", "x/y", "x/y/foo", "a", "a/b", "a/b/foo", "a/b/c",
|
||||||
&WalkBuilder::new(td.path()),
|
]);
|
||||||
&["x", "x/y", "x/y/foo", "a", "a/b", "a/b/foo", "a/b/c"],
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn custom_ignore() {
|
fn custom_ignore() {
|
||||||
let td = tmpdir();
|
let td = tmpdir("walk-test-");
|
||||||
let custom_ignore = ".customignore";
|
let custom_ignore = ".customignore";
|
||||||
mkdirp(td.path().join("a"));
|
mkdirp(td.path().join("a"));
|
||||||
wfile(td.path().join(custom_ignore), "foo");
|
wfile(td.path().join(custom_ignore), "foo");
|
||||||
@@ -1846,7 +1841,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn custom_ignore_exclusive_use() {
|
fn custom_ignore_exclusive_use() {
|
||||||
let td = tmpdir();
|
let td = tmpdir("walk-test-");
|
||||||
let custom_ignore = ".customignore";
|
let custom_ignore = ".customignore";
|
||||||
mkdirp(td.path().join("a"));
|
mkdirp(td.path().join("a"));
|
||||||
wfile(td.path().join(custom_ignore), "foo");
|
wfile(td.path().join(custom_ignore), "foo");
|
||||||
@@ -1866,7 +1861,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn gitignore() {
|
fn gitignore() {
|
||||||
let td = tmpdir();
|
let td = tmpdir("walk-test-");
|
||||||
mkdirp(td.path().join(".git"));
|
mkdirp(td.path().join(".git"));
|
||||||
mkdirp(td.path().join("a"));
|
mkdirp(td.path().join("a"));
|
||||||
wfile(td.path().join(".gitignore"), "foo");
|
wfile(td.path().join(".gitignore"), "foo");
|
||||||
@@ -1875,16 +1870,14 @@ mod tests {
|
|||||||
wfile(td.path().join("bar"), "");
|
wfile(td.path().join("bar"), "");
|
||||||
wfile(td.path().join("a/bar"), "");
|
wfile(td.path().join("a/bar"), "");
|
||||||
|
|
||||||
assert_paths(
|
assert_paths(td.path(), &WalkBuilder::new(td.path()), &[
|
||||||
td.path(),
|
"bar", "a", "a/bar",
|
||||||
&WalkBuilder::new(td.path()),
|
]);
|
||||||
&["bar", "a", "a/bar"],
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn explicit_ignore() {
|
fn explicit_ignore() {
|
||||||
let td = tmpdir();
|
let td = tmpdir("walk-test-");
|
||||||
let igpath = td.path().join(".not-an-ignore");
|
let igpath = td.path().join(".not-an-ignore");
|
||||||
mkdirp(td.path().join("a"));
|
mkdirp(td.path().join("a"));
|
||||||
wfile(&igpath, "foo");
|
wfile(&igpath, "foo");
|
||||||
@@ -1900,7 +1893,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn explicit_ignore_exclusive_use() {
|
fn explicit_ignore_exclusive_use() {
|
||||||
let td = tmpdir();
|
let td = tmpdir("walk-test-");
|
||||||
let igpath = td.path().join(".not-an-ignore");
|
let igpath = td.path().join(".not-an-ignore");
|
||||||
mkdirp(td.path().join("a"));
|
mkdirp(td.path().join("a"));
|
||||||
wfile(&igpath, "foo");
|
wfile(&igpath, "foo");
|
||||||
@@ -1912,16 +1905,13 @@ mod tests {
|
|||||||
let mut builder = WalkBuilder::new(td.path());
|
let mut builder = WalkBuilder::new(td.path());
|
||||||
builder.standard_filters(false);
|
builder.standard_filters(false);
|
||||||
assert!(builder.add_ignore(&igpath).is_none());
|
assert!(builder.add_ignore(&igpath).is_none());
|
||||||
assert_paths(
|
assert_paths(td.path(), &builder,
|
||||||
td.path(),
|
&[".not-an-ignore", "bar", "a", "a/bar"]);
|
||||||
&builder,
|
|
||||||
&[".not-an-ignore", "bar", "a", "a/bar"],
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn gitignore_parent() {
|
fn gitignore_parent() {
|
||||||
let td = tmpdir();
|
let td = tmpdir("walk-test-");
|
||||||
mkdirp(td.path().join(".git"));
|
mkdirp(td.path().join(".git"));
|
||||||
mkdirp(td.path().join("a"));
|
mkdirp(td.path().join("a"));
|
||||||
wfile(td.path().join(".gitignore"), "foo");
|
wfile(td.path().join(".gitignore"), "foo");
|
||||||
@@ -1934,7 +1924,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn max_depth() {
|
fn max_depth() {
|
||||||
let td = tmpdir();
|
let td = tmpdir("walk-test-");
|
||||||
mkdirp(td.path().join("a/b/c"));
|
mkdirp(td.path().join("a/b/c"));
|
||||||
wfile(td.path().join("foo"), "");
|
wfile(td.path().join("foo"), "");
|
||||||
wfile(td.path().join("a/foo"), "");
|
wfile(td.path().join("a/foo"), "");
|
||||||
@@ -1942,23 +1932,19 @@ mod tests {
|
|||||||
wfile(td.path().join("a/b/c/foo"), "");
|
wfile(td.path().join("a/b/c/foo"), "");
|
||||||
|
|
||||||
let mut builder = WalkBuilder::new(td.path());
|
let mut builder = WalkBuilder::new(td.path());
|
||||||
assert_paths(
|
assert_paths(td.path(), &builder, &[
|
||||||
td.path(),
|
"a", "a/b", "a/b/c", "foo", "a/foo", "a/b/foo", "a/b/c/foo",
|
||||||
&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(0)), &[]);
|
||||||
assert_paths(td.path(), builder.max_depth(Some(1)), &["a", "foo"]);
|
assert_paths(td.path(), builder.max_depth(Some(1)), &["a", "foo"]);
|
||||||
assert_paths(
|
assert_paths(td.path(), builder.max_depth(Some(2)), &[
|
||||||
td.path(),
|
"a", "a/b", "foo", "a/foo",
|
||||||
builder.max_depth(Some(2)),
|
]);
|
||||||
&["a", "a/b", "foo", "a/foo"],
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn max_filesize() {
|
fn max_filesize() {
|
||||||
let td = tmpdir();
|
let td = tmpdir("walk-test-");
|
||||||
mkdirp(td.path().join("a/b"));
|
mkdirp(td.path().join("a/b"));
|
||||||
wfile_size(td.path().join("foo"), 0);
|
wfile_size(td.path().join("foo"), 0);
|
||||||
wfile_size(td.path().join("bar"), 400);
|
wfile_size(td.path().join("bar"), 400);
|
||||||
@@ -1968,49 +1954,41 @@ mod tests {
|
|||||||
wfile_size(td.path().join("a/baz"), 200);
|
wfile_size(td.path().join("a/baz"), 200);
|
||||||
|
|
||||||
let mut builder = WalkBuilder::new(td.path());
|
let mut builder = WalkBuilder::new(td.path());
|
||||||
assert_paths(
|
assert_paths(td.path(), &builder, &[
|
||||||
td.path(),
|
"a", "a/b", "foo", "bar", "baz", "a/foo", "a/bar", "a/baz",
|
||||||
&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(),
|
assert_paths(td.path(), builder.max_filesize(Some(500)), &[
|
||||||
builder.max_filesize(Some(0)),
|
"a", "a/b", "foo", "bar", "a/bar", "a/baz"
|
||||||
&["a", "a/b", "foo"],
|
]);
|
||||||
);
|
assert_paths(td.path(), builder.max_filesize(Some(50000)), &[
|
||||||
assert_paths(
|
"a", "a/b", "foo", "bar", "baz", "a/foo", "a/bar", "a/baz",
|
||||||
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
|
#[cfg(unix)] // because symlinks on windows are weird
|
||||||
#[test]
|
#[test]
|
||||||
fn symlinks() {
|
fn symlinks() {
|
||||||
let td = tmpdir();
|
let td = tmpdir("walk-test-");
|
||||||
mkdirp(td.path().join("a/b"));
|
mkdirp(td.path().join("a/b"));
|
||||||
symlink(td.path().join("a/b"), td.path().join("z"));
|
symlink(td.path().join("a/b"), td.path().join("z"));
|
||||||
wfile(td.path().join("a/b/foo"), "");
|
wfile(td.path().join("a/b/foo"), "");
|
||||||
|
|
||||||
let mut builder = WalkBuilder::new(td.path());
|
let mut builder = WalkBuilder::new(td.path());
|
||||||
assert_paths(td.path(), &builder, &["a", "a/b", "a/b/foo", "z"]);
|
assert_paths(td.path(), &builder, &[
|
||||||
assert_paths(
|
"a", "a/b", "a/b/foo", "z",
|
||||||
td.path(),
|
]);
|
||||||
&builder.follow_links(true),
|
assert_paths(td.path(), &builder.follow_links(true), &[
|
||||||
&["a", "a/b", "a/b/foo", "z", "z/foo"],
|
"a", "a/b", "a/b/foo", "z", "z/foo",
|
||||||
);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(unix)] // because symlinks on windows are weird
|
#[cfg(unix)] // because symlinks on windows are weird
|
||||||
#[test]
|
#[test]
|
||||||
fn first_path_not_symlink() {
|
fn first_path_not_symlink() {
|
||||||
let td = tmpdir();
|
let td = tmpdir("walk-test-");
|
||||||
mkdirp(td.path().join("foo"));
|
mkdirp(td.path().join("foo"));
|
||||||
|
|
||||||
let dents = WalkBuilder::new(td.path().join("foo"))
|
let dents = WalkBuilder::new(td.path().join("foo"))
|
||||||
@@ -2021,7 +1999,9 @@ mod tests {
|
|||||||
assert_eq!(1, dents.len());
|
assert_eq!(1, dents.len());
|
||||||
assert!(!dents[0].path_is_symlink());
|
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_eq!(1, dents.len());
|
||||||
assert!(!dents[0].path_is_symlink());
|
assert!(!dents[0].path_is_symlink());
|
||||||
}
|
}
|
||||||
@@ -2029,13 +2009,17 @@ mod tests {
|
|||||||
#[cfg(unix)] // because symlinks on windows are weird
|
#[cfg(unix)] // because symlinks on windows are weird
|
||||||
#[test]
|
#[test]
|
||||||
fn symlink_loop() {
|
fn symlink_loop() {
|
||||||
let td = tmpdir();
|
let td = tmpdir("walk-test-");
|
||||||
mkdirp(td.path().join("a/b"));
|
mkdirp(td.path().join("a/b"));
|
||||||
symlink(td.path().join("a"), td.path().join("a/b/c"));
|
symlink(td.path().join("a"), td.path().join("a/b/c"));
|
||||||
|
|
||||||
let mut builder = WalkBuilder::new(td.path());
|
let mut builder = WalkBuilder::new(td.path());
|
||||||
assert_paths(td.path(), &builder, &["a", "a/b", "a/b/c"]);
|
assert_paths(td.path(), &builder, &[
|
||||||
assert_paths(td.path(), &builder.follow_links(true), &["a", "a/b"]);
|
"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
|
// 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,
|
// If our test directory actually isn't a different volume from /sys,
|
||||||
// then this test is meaningless and we shouldn't run it.
|
// 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() {
|
if device_num(td.path()).unwrap() == device_num("/sys").unwrap() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2069,6 +2053,8 @@ mod tests {
|
|||||||
// completely.
|
// completely.
|
||||||
let mut builder = WalkBuilder::new(td.path());
|
let mut builder = WalkBuilder::new(td.path());
|
||||||
builder.follow_links(true).same_file_system(true);
|
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",
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,14 +1,14 @@
|
|||||||
class RipgrepBin < Formula
|
class RipgrepBin < Formula
|
||||||
version '11.0.2'
|
version '11.0.1'
|
||||||
desc "Recursively search directories for a regex pattern."
|
desc "Recursively search directories for a regex pattern."
|
||||||
homepage "https://github.com/BurntSushi/ripgrep"
|
homepage "https://github.com/BurntSushi/ripgrep"
|
||||||
|
|
||||||
if OS.mac?
|
if OS.mac?
|
||||||
url "https://github.com/BurntSushi/ripgrep/releases/download/#{version}/ripgrep-#{version}-x86_64-apple-darwin.tar.gz"
|
url "https://github.com/BurntSushi/ripgrep/releases/download/#{version}/ripgrep-#{version}-x86_64-apple-darwin.tar.gz"
|
||||||
sha256 "0ba26423691deedf2649b12b1abe3d2be294ee1cb17c40b68fe85efe194f4f57"
|
sha256 "92446c6b28b6c726f91ad66a03bcd533fc6e1a28ef4b44c27bfe2d49a0f88531"
|
||||||
elsif OS.linux?
|
elsif OS.linux?
|
||||||
url "https://github.com/BurntSushi/ripgrep/releases/download/#{version}/ripgrep-#{version}-x86_64-unknown-linux-musl.tar.gz"
|
url "https://github.com/BurntSushi/ripgrep/releases/download/#{version}/ripgrep-#{version}-x86_64-unknown-linux-musl.tar.gz"
|
||||||
sha256 "2e7978e346553fbc45c0940d9fa11e12f9afbae8213b261aad19b698150e169a"
|
sha256 "ce74cabac9b39b1ad55837ec01e2c670fa7e965772ac2647b209e31ead19008c"
|
||||||
end
|
end
|
||||||
|
|
||||||
conflicts_with "ripgrep"
|
conflicts_with "ripgrep"
|
||||||
|
32
src/app.rs
32
src/app.rs
@@ -571,7 +571,6 @@ pub fn all_args_and_flags() -> Vec<RGArg> {
|
|||||||
flag_fixed_strings(&mut args);
|
flag_fixed_strings(&mut args);
|
||||||
flag_follow(&mut args);
|
flag_follow(&mut args);
|
||||||
flag_glob(&mut args);
|
flag_glob(&mut args);
|
||||||
flag_glob_case_insensitive(&mut args);
|
|
||||||
flag_heading(&mut args);
|
flag_heading(&mut args);
|
||||||
flag_hidden(&mut args);
|
flag_hidden(&mut args);
|
||||||
flag_iglob(&mut args);
|
flag_iglob(&mut args);
|
||||||
@@ -1219,25 +1218,6 @@ it.
|
|||||||
args.push(arg);
|
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>) {
|
fn flag_heading(args: &mut Vec<RGArg>) {
|
||||||
const SHORT: &str = "Print matches grouped by each file.";
|
const SHORT: &str = "Print matches grouped by each file.";
|
||||||
const LONG: &str = long!("\
|
const LONG: &str = long!("\
|
||||||
@@ -1995,12 +1975,7 @@ or backreferences.
|
|||||||
|
|
||||||
Note that PCRE2 is an optional ripgrep feature. If PCRE2 wasn't included in
|
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
|
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
|
an error message and exiting.
|
||||||
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).
|
|
||||||
|
|
||||||
Related flags: --no-pcre2-unicode
|
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.
|
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
|
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
|
replacement string.
|
||||||
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.
|
|
||||||
|
|
||||||
Note that the replacement by default replaces each match, and NOT the entire
|
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.
|
line. To replace the entire line, you should match the entire line.
|
||||||
|
189
src/args.rs
189
src/args.rs
@@ -36,6 +36,7 @@ use ignore::{Walk, WalkBuilder, WalkParallel};
|
|||||||
use log;
|
use log;
|
||||||
use num_cpus;
|
use num_cpus;
|
||||||
use regex;
|
use regex;
|
||||||
|
use snafu::{self, ResultExt};
|
||||||
use termcolor::{
|
use termcolor::{
|
||||||
WriteColor,
|
WriteColor,
|
||||||
BufferWriter, ColorChoice,
|
BufferWriter, ColorChoice,
|
||||||
@@ -43,6 +44,7 @@ use termcolor::{
|
|||||||
|
|
||||||
use crate::app;
|
use crate::app;
|
||||||
use crate::config;
|
use crate::config;
|
||||||
|
use crate::err::{self, Result};
|
||||||
use crate::logger::Logger;
|
use crate::logger::Logger;
|
||||||
use crate::messages::{set_messages, set_ignore_messages};
|
use crate::messages::{set_messages, set_ignore_messages};
|
||||||
use crate::path_printer::{PathPrinter, PathPrinterBuilder};
|
use crate::path_printer::{PathPrinter, PathPrinterBuilder};
|
||||||
@@ -50,7 +52,6 @@ use crate::search::{
|
|||||||
PatternMatcher, Printer, SearchWorker, SearchWorkerBuilder,
|
PatternMatcher, Printer, SearchWorker, SearchWorkerBuilder,
|
||||||
};
|
};
|
||||||
use crate::subject::SubjectBuilder;
|
use crate::subject::SubjectBuilder;
|
||||||
use crate::Result;
|
|
||||||
|
|
||||||
/// The command that ripgrep should execute based on the command line
|
/// The command that ripgrep should execute based on the command line
|
||||||
/// configuration.
|
/// configuration.
|
||||||
@@ -141,9 +142,7 @@ impl Args {
|
|||||||
set_messages(!early_matches.is_present("no-messages"));
|
set_messages(!early_matches.is_present("no-messages"));
|
||||||
set_ignore_messages(!early_matches.is_present("no-ignore-messages"));
|
set_ignore_messages(!early_matches.is_present("no-ignore-messages"));
|
||||||
|
|
||||||
if let Err(err) = Logger::init() {
|
Logger::init()?;
|
||||||
return Err(format!("failed to initialize logger: {}", err).into());
|
|
||||||
}
|
|
||||||
if early_matches.is_present("trace") {
|
if early_matches.is_present("trace") {
|
||||||
log::set_max_level(log::LevelFilter::Trace);
|
log::set_max_level(log::LevelFilter::Trace);
|
||||||
} else if early_matches.is_present("debug") {
|
} else if early_matches.is_present("debug") {
|
||||||
@@ -422,13 +421,22 @@ impl SortBy {
|
|||||||
match self.kind {
|
match self.kind {
|
||||||
SortByKind::None | SortByKind::Path => {}
|
SortByKind::None | SortByKind::Path => {}
|
||||||
SortByKind::LastModified => {
|
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 => {
|
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 => {
|
SortByKind::Created => {
|
||||||
env::current_exe()?.metadata()?.created()?;
|
env::current_exe()
|
||||||
|
.and_then(|x| x.metadata())
|
||||||
|
.and_then(|x| x.created())
|
||||||
|
.context(err::UnsupportedSortCreation)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -611,21 +619,12 @@ impl ArgMatches {
|
|||||||
Ok(matcher) => return Ok(PatternMatcher::PCRE2(matcher)),
|
Ok(matcher) => return Ok(PatternMatcher::PCRE2(matcher)),
|
||||||
Err(err) => err,
|
Err(err) => err,
|
||||||
};
|
};
|
||||||
Err(From::from(format!(
|
err::Hybrid {
|
||||||
"regex could not be compiled with either the default regex \
|
rust_err: Box::new(rust_err),
|
||||||
engine or with PCRE2.\n\n\
|
pcre_err: Box::new(pcre_err),
|
||||||
default regex engine error:\n{}\n{}\n{}\n\n\
|
}.fail()
|
||||||
PCRE2 regex engine error:\n{}",
|
|
||||||
"~".repeat(79), rust_err, "~".repeat(79), pcre_err,
|
|
||||||
)))
|
|
||||||
} else {
|
} else {
|
||||||
let matcher = match self.matcher_rust(patterns) {
|
Ok(PatternMatcher::RustRegex(self.matcher_rust(patterns)?))
|
||||||
Ok(matcher) => matcher,
|
|
||||||
Err(err) => {
|
|
||||||
return Err(From::from(suggest_pcre2(err.to_string())));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Ok(PatternMatcher::RustRegex(matcher))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -635,11 +634,7 @@ impl ArgMatches {
|
|||||||
/// then this returns an error.
|
/// then this returns an error.
|
||||||
#[cfg(not(feature = "pcre2"))]
|
#[cfg(not(feature = "pcre2"))]
|
||||||
fn matcher(&self, patterns: &[String]) -> Result<PatternMatcher> {
|
fn matcher(&self, patterns: &[String]) -> Result<PatternMatcher> {
|
||||||
if self.is_present("pcre2") {
|
snafu::ensure!(!self.is_present("pcre2"), err::PCRE2Unavailable);
|
||||||
return Err(From::from(
|
|
||||||
"PCRE2 is not available in this build of ripgrep",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
let matcher = self.matcher_rust(patterns)?;
|
let matcher = self.matcher_rust(patterns)?;
|
||||||
Ok(PatternMatcher::RustRegex(matcher))
|
Ok(PatternMatcher::RustRegex(matcher))
|
||||||
}
|
}
|
||||||
@@ -692,10 +687,7 @@ impl ArgMatches {
|
|||||||
} else {
|
} else {
|
||||||
builder.build(&patterns.join("|"))
|
builder.build(&patterns.join("|"))
|
||||||
};
|
};
|
||||||
match res {
|
res.eager_context(err::RustRegex)
|
||||||
Ok(m) => Ok(m),
|
|
||||||
Err(err) => Err(From::from(suggest_multiline(err.to_string()))),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Build a matcher using PCRE2.
|
/// Build a matcher using PCRE2.
|
||||||
@@ -737,7 +729,7 @@ impl ArgMatches {
|
|||||||
if self.is_present("crlf") {
|
if self.is_present("crlf") {
|
||||||
builder.crlf(true);
|
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.
|
/// 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.
|
// Start with a default set of color specs.
|
||||||
let mut specs = default_color_specs();
|
let mut specs = default_color_specs();
|
||||||
for spec_str in self.values_of_lossy_vec("colors") {
|
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))
|
Ok(ColorSpecs::new(&specs))
|
||||||
}
|
}
|
||||||
@@ -1078,7 +1070,8 @@ impl ArgMatches {
|
|||||||
return Ok(EncodingMode::Disabled);
|
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.
|
/// 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.
|
/// Builds the set of glob overrides from the command line flags.
|
||||||
fn overrides(&self) -> Result<Override> {
|
fn overrides(&self) -> Result<Override> {
|
||||||
let mut builder = OverrideBuilder::new(env::current_dir()?);
|
let cwd = env::current_dir().context(err::CurrentDir)?;
|
||||||
// Make all globs case insensitive with --glob-case-insensitive.
|
let mut builder = OverrideBuilder::new(cwd);
|
||||||
if self.is_present("glob-case-insensitive") {
|
|
||||||
builder.case_insensitive(true).unwrap();
|
|
||||||
}
|
|
||||||
for glob in self.values_of_lossy_vec("glob") {
|
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.
|
// This only enables case insensitivity for subsequent globs.
|
||||||
builder.case_insensitive(true).unwrap();
|
builder.case_insensitive(true).unwrap();
|
||||||
for glob in self.values_of_lossy_vec("iglob") {
|
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.
|
/// Return all file paths that ripgrep should search.
|
||||||
@@ -1334,16 +1324,10 @@ impl ArgMatches {
|
|||||||
};
|
};
|
||||||
if sep.is_empty() {
|
if sep.is_empty() {
|
||||||
Ok(None)
|
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 {
|
} else {
|
||||||
|
snafu::ensure!(sep.len() == 1, err::InvalidPathSeparator {
|
||||||
|
separator: sep.clone(),
|
||||||
|
});
|
||||||
Ok(Some(sep[0]))
|
Ok(Some(sep[0]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1390,17 +1374,17 @@ impl ArgMatches {
|
|||||||
}
|
}
|
||||||
if let Some(paths) = self.values_of_os("file") {
|
if let Some(paths) = self.values_of_os("file") {
|
||||||
for path in paths {
|
for path in paths {
|
||||||
if path == "-" {
|
let some_pats =
|
||||||
pats.extend(cli::patterns_from_stdin()?
|
if path == "-" {
|
||||||
.into_iter()
|
cli::patterns_from_stdin()
|
||||||
.map(|p| self.pattern_from_string(p))
|
.context(err::ReadManyPatterns)?
|
||||||
);
|
} else {
|
||||||
} else {
|
cli::patterns_from_path(path)
|
||||||
pats.extend(cli::patterns_from_path(path)?
|
.context(err::ReadManyPatterns)?
|
||||||
.into_iter()
|
};
|
||||||
.map(|p| self.pattern_from_string(p))
|
pats.extend(
|
||||||
);
|
some_pats.into_iter().map(|p| self.pattern_from_string(p))
|
||||||
}
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(pats)
|
Ok(pats)
|
||||||
@@ -1421,7 +1405,7 @@ impl ArgMatches {
|
|||||||
///
|
///
|
||||||
/// If the pattern is not valid UTF-8, then an error is returned.
|
/// If the pattern is not valid UTF-8, then an error is returned.
|
||||||
fn pattern_from_os_str(&self, pat: &OsStr) -> Result<String> {
|
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))
|
Ok(self.pattern_from_str(s))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1479,11 +1463,12 @@ impl ArgMatches {
|
|||||||
/// flag. If no --pre-globs are available, then this always returns an
|
/// flag. If no --pre-globs are available, then this always returns an
|
||||||
/// empty set of globs.
|
/// empty set of globs.
|
||||||
fn preprocessor_globs(&self) -> Result<Override> {
|
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") {
|
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.
|
/// Parse the regex-size-limit argument option into a byte count.
|
||||||
@@ -1565,7 +1550,7 @@ impl ArgMatches {
|
|||||||
builder.clear(&ty);
|
builder.clear(&ty);
|
||||||
}
|
}
|
||||||
for def in self.values_of_lossy_vec("type-add") {
|
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") {
|
for ty in self.values_of_lossy_vec("type") {
|
||||||
builder.select(&ty);
|
builder.select(&ty);
|
||||||
@@ -1573,7 +1558,7 @@ impl ArgMatches {
|
|||||||
for ty in self.values_of_lossy_vec("type-not") {
|
for ty in self.values_of_lossy_vec("type-not") {
|
||||||
builder.negate(&ty);
|
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.
|
/// Returns the number of times the `unrestricted` flag is provided.
|
||||||
@@ -1594,11 +1579,10 @@ impl ArgMatches {
|
|||||||
if self.is_present("no-filename") {
|
if self.is_present("no-filename") {
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
let path_stdin = Path::new("-");
|
|
||||||
self.is_present("with-filename")
|
self.is_present("with-filename")
|
||||||
|| self.is_present("vimgrep")
|
|| self.is_present("vimgrep")
|
||||||
|| paths.len() > 1
|
|| 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>> {
|
fn usize_of(&self, name: &str) -> Result<Option<usize>> {
|
||||||
match self.value_of_lossy(name) {
|
match self.value_of_lossy(name) {
|
||||||
None => Ok(None),
|
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
|
/// If the aforementioned format is not recognized, then this returns an
|
||||||
/// error.
|
/// error.
|
||||||
fn parse_human_readable_size(
|
fn parse_human_readable_size(&self, name: &str) -> Result<Option<u64>> {
|
||||||
&self,
|
match self.value_of_lossy(name) {
|
||||||
arg_name: &str,
|
None => Ok(None),
|
||||||
) -> Result<Option<u64>> {
|
Some(size) => {
|
||||||
let size = match self.value_of_lossy(arg_name) {
|
cli::parse_human_readable_size(&size)
|
||||||
None => return Ok(None),
|
.map(Some)
|
||||||
Some(size) => size,
|
.eager_context(err::InvalidHumanSize {
|
||||||
};
|
flag: name.to_string()
|
||||||
Ok(Some(cli::parse_human_readable_size(&size)?))
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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`,
|
/// Convert the result of parsing a human readable file size to a `usize`,
|
||||||
/// failing if the type does not fit.
|
/// failing if the type does not fit.
|
||||||
fn u64_to_usize(
|
fn u64_to_usize(
|
||||||
@@ -1721,11 +1685,14 @@ fn u64_to_usize(
|
|||||||
None => return Ok(None),
|
None => return Ok(None),
|
||||||
Some(value) => value,
|
Some(value) => value,
|
||||||
};
|
};
|
||||||
if value <= usize::MAX as u64 {
|
snafu::ensure!(
|
||||||
Ok(Some(value as usize))
|
value <= usize::MAX as u64,
|
||||||
} else {
|
err::NumberTooBig {
|
||||||
Err(From::from(format!("number too large for {}", arg_name)))
|
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
|
/// Builds a comparator for sorting two files according to a system time
|
||||||
@@ -1773,7 +1740,7 @@ where I: IntoIterator<Item=T>,
|
|||||||
Err(err) => err,
|
Err(err) => err,
|
||||||
};
|
};
|
||||||
if err.use_stderr() {
|
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
|
// 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
|
// at this point is a broken pipe error, in which case, we want to ignore
|
||||||
|
@@ -3,16 +3,16 @@
|
|||||||
// argument corresponds precisely to one shell argument.
|
// argument corresponds precisely to one shell argument.
|
||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::error::Error;
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use bstr::{io::BufReadExt, ByteSlice};
|
use bstr::io::BufReadExt;
|
||||||
use log;
|
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.
|
/// Return a sequence of arguments derived from ripgrep rc configuration files.
|
||||||
pub fn args() -> Vec<OsString> {
|
pub fn args() -> Vec<OsString> {
|
||||||
@@ -55,12 +55,11 @@ pub fn args() -> Vec<OsString> {
|
|||||||
/// for each line in addition to successfully parsed arguments.
|
/// for each line in addition to successfully parsed arguments.
|
||||||
fn parse<P: AsRef<Path>>(
|
fn parse<P: AsRef<Path>>(
|
||||||
path: P,
|
path: P,
|
||||||
) -> Result<(Vec<OsString>, Vec<Box<dyn Error>>)> {
|
) -> Result<(Vec<OsString>, Vec<Error>)> {
|
||||||
let path = path.as_ref();
|
let path = path.as_ref();
|
||||||
match File::open(&path) {
|
let file = File::open(&path).context(err::ConfigIO { path })?;
|
||||||
Ok(file) => parse_reader(file),
|
let res = parse_reader(file).context(err::ConfigIO { path })?;
|
||||||
Err(err) => Err(From::from(format!("{}: {}", path.display(), err))),
|
Ok(res)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a single ripgrep rc file from the given reader.
|
/// 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.
|
/// in addition to successfully parsed arguments.
|
||||||
fn parse_reader<R: io::Read>(
|
fn parse_reader<R: io::Read>(
|
||||||
rdr: R,
|
rdr: R,
|
||||||
) -> Result<(Vec<OsString>, Vec<Box<dyn Error>>)> {
|
) -> io::Result<(Vec<OsString>, Vec<Error>)> {
|
||||||
let bufrdr = io::BufReader::new(rdr);
|
let bufrdr = io::BufReader::new(rdr);
|
||||||
let (mut args, mut errs) = (vec![], vec![]);
|
let (mut args, mut errs) = (vec![], vec![]);
|
||||||
let mut line_number = 0;
|
let mut line_number = 0u64;
|
||||||
bufrdr.for_byte_line_with_terminator(|line| {
|
bufrdr.for_byte_line_with_terminator(|line| {
|
||||||
line_number += 1;
|
line_number += 1;
|
||||||
|
|
||||||
@@ -92,7 +91,11 @@ fn parse_reader<R: io::Read>(
|
|||||||
args.push(osstr.to_os_string());
|
args.push(osstr.to_os_string());
|
||||||
}
|
}
|
||||||
Err(err) => {
|
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)
|
Ok(true)
|
||||||
|
250
src/err.rs
Normal file
250
src/err.rs
Normal 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
|
||||||
|
}
|
||||||
|
}
|
@@ -4,6 +4,9 @@
|
|||||||
// for this functionality.
|
// for this functionality.
|
||||||
|
|
||||||
use log::{self, Log};
|
use log::{self, Log};
|
||||||
|
use snafu::ResultExt;
|
||||||
|
|
||||||
|
use crate::err::{self, Result};
|
||||||
|
|
||||||
/// The simplest possible logger that logs to stderr.
|
/// 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
|
/// 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
|
/// global logger. If there was a problem setting the logger, then an
|
||||||
/// error is returned.
|
/// error is returned.
|
||||||
pub fn init() -> Result<(), log::SetLoggerError> {
|
pub fn init() -> Result<()> {
|
||||||
log::set_logger(LOGGER)
|
log::set_logger(LOGGER).eager_context(err::LoggerInit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
46
src/main.rs
46
src/main.rs
@@ -1,12 +1,15 @@
|
|||||||
use std::error;
|
#![allow(warnings)]
|
||||||
|
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
use std::process;
|
use std::process;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
use ignore::WalkState;
|
use ignore::WalkState;
|
||||||
|
use snafu::ResultExt;
|
||||||
|
|
||||||
use args::Args;
|
use args::Args;
|
||||||
|
use err::Result;
|
||||||
use subject::Subject;
|
use subject::Subject;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
@@ -15,6 +18,7 @@ mod messages;
|
|||||||
mod app;
|
mod app;
|
||||||
mod args;
|
mod args;
|
||||||
mod config;
|
mod config;
|
||||||
|
mod err;
|
||||||
mod logger;
|
mod logger;
|
||||||
mod path_printer;
|
mod path_printer;
|
||||||
mod search;
|
mod search;
|
||||||
@@ -43,7 +47,8 @@ mod subject;
|
|||||||
#[global_allocator]
|
#[global_allocator]
|
||||||
static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;
|
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() {
|
fn main() {
|
||||||
if let Err(err) = Args::parse().and_then(try_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()) {
|
if let Err(err) = path_printer.write_path(subject.path()) {
|
||||||
// A broken pipe means graceful termination.
|
// A broken pipe means graceful termination.
|
||||||
if err.kind() == io::ErrorKind::BrokenPipe {
|
if err.is_broken_pipe() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Otherwise, we have some other error that's preventing us from
|
// Otherwise, we have some other error that's preventing us from
|
||||||
// writing to stdout, so we should bubble it up.
|
// writing to stdout, so we should bubble it up.
|
||||||
return Err(err.into());
|
return Err(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(matched)
|
Ok(matched)
|
||||||
@@ -240,7 +245,7 @@ fn files_parallel(args: &Args) -> Result<bool> {
|
|||||||
let matched = Arc::new(AtomicBool::new(false));
|
let matched = Arc::new(AtomicBool::new(false));
|
||||||
let (tx, rx) = mpsc::channel::<Subject>();
|
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() {
|
for subject in rx.iter() {
|
||||||
path_printer.write_path(subject.path())?;
|
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.
|
// A broken pipe means graceful termination, so fall through.
|
||||||
// Otherwise, something bad happened while writing to stdout, so bubble
|
// Otherwise, something bad happened while writing to stdout, so bubble
|
||||||
// it up.
|
// it up.
|
||||||
if err.kind() != io::ErrorKind::BrokenPipe {
|
if !err.is_broken_pipe() {
|
||||||
return Err(err.into());
|
return Err(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(matched.load(SeqCst))
|
Ok(matched.load(SeqCst))
|
||||||
@@ -281,22 +286,29 @@ fn files_parallel(args: &Args) -> Result<bool> {
|
|||||||
|
|
||||||
/// The top-level entry point for --type-list.
|
/// The top-level entry point for --type-list.
|
||||||
fn types(args: &Args) -> Result<bool> {
|
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 count = 0;
|
||||||
let mut stdout = args.stdout();
|
for def in defs {
|
||||||
for def in args.type_defs()? {
|
|
||||||
count += 1;
|
count += 1;
|
||||||
stdout.write_all(def.name().as_bytes())?;
|
wtr.write_all(def.name().as_bytes())?;
|
||||||
stdout.write_all(b": ")?;
|
wtr.write_all(b": ")?;
|
||||||
|
|
||||||
let mut first = true;
|
let mut first = true;
|
||||||
for glob in def.globs() {
|
for glob in def.globs() {
|
||||||
if !first {
|
if !first {
|
||||||
stdout.write_all(b", ")?;
|
wtr.write_all(b", ")?;
|
||||||
}
|
}
|
||||||
stdout.write_all(glob.as_bytes())?;
|
wtr.write_all(glob.as_bytes())?;
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
stdout.write_all(b"\n")?;
|
wtr.write_all(b"\n")?;
|
||||||
}
|
}
|
||||||
Ok(count > 0)
|
Ok(count > 0)
|
||||||
}
|
}
|
||||||
@@ -304,7 +316,7 @@ fn types(args: &Args) -> Result<bool> {
|
|||||||
/// The top-level entry point for --pcre2-version.
|
/// The top-level entry point for --pcre2-version.
|
||||||
fn pcre2_version(args: &Args) -> Result<bool> {
|
fn pcre2_version(args: &Args) -> Result<bool> {
|
||||||
#[cfg(feature = "pcre2")]
|
#[cfg(feature = "pcre2")]
|
||||||
fn imp(args: &Args) -> Result<bool> {
|
fn imp(args: &Args) -> io::Result<bool> {
|
||||||
use grep::pcre2;
|
use grep::pcre2;
|
||||||
|
|
||||||
let mut stdout = args.stdout();
|
let mut stdout = args.stdout();
|
||||||
@@ -319,11 +331,11 @@ fn pcre2_version(args: &Args) -> Result<bool> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "pcre2"))]
|
#[cfg(not(feature = "pcre2"))]
|
||||||
fn imp(args: &Args) -> Result<bool> {
|
fn imp(args: &Args) -> io::Result<bool> {
|
||||||
let mut stdout = args.stdout();
|
let mut stdout = args.stdout();
|
||||||
writeln!(stdout, "PCRE2 is not available in this build of ripgrep.")?;
|
writeln!(stdout, "PCRE2 is not available in this build of ripgrep.")?;
|
||||||
Ok(false)
|
Ok(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
imp(args)
|
imp(args).eager_context(err::PCRE2Version)
|
||||||
}
|
}
|
||||||
|
@@ -2,8 +2,11 @@ use std::io;
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use grep::printer::{ColorSpecs, PrinterPath};
|
use grep::printer::{ColorSpecs, PrinterPath};
|
||||||
|
use snafu::ResultExt;
|
||||||
use termcolor::WriteColor;
|
use termcolor::WriteColor;
|
||||||
|
|
||||||
|
use crate::err::{self, Result};
|
||||||
|
|
||||||
/// A configuration for describing how paths should be written.
|
/// A configuration for describing how paths should be written.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
struct Config {
|
struct Config {
|
||||||
@@ -87,7 +90,11 @@ pub struct PathPrinter<W> {
|
|||||||
|
|
||||||
impl<W: WriteColor> PathPrinter<W> {
|
impl<W: WriteColor> PathPrinter<W> {
|
||||||
/// Write the given path to the underlying writer.
|
/// 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);
|
let ppath = PrinterPath::with_separator(path, self.config.separator);
|
||||||
if !self.wtr.supports_color() {
|
if !self.wtr.supports_color() {
|
||||||
self.wtr.write_all(ppath.as_bytes())?;
|
self.wtr.write_all(ppath.as_bytes())?;
|
||||||
|
@@ -315,24 +315,7 @@ pub struct SearchWorker<W> {
|
|||||||
impl<W: WriteColor> SearchWorker<W> {
|
impl<W: WriteColor> SearchWorker<W> {
|
||||||
/// Execute a search over the given subject.
|
/// Execute a search over the given subject.
|
||||||
pub fn search(&mut self, subject: &Subject) -> io::Result<SearchResult> {
|
pub fn search(&mut self, subject: &Subject) -> io::Result<SearchResult> {
|
||||||
let bin =
|
self.search_impl(subject)
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a mutable reference to the underlying printer.
|
/// 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
|
/// Returns true if and only if the given file path should be
|
||||||
/// decompressed before searching.
|
/// decompressed before searching.
|
||||||
fn should_decompress(&self, path: &Path) -> bool {
|
fn should_decompress(&self, path: &Path) -> bool {
|
||||||
@@ -385,23 +392,11 @@ impl<W: WriteColor> SearchWorker<W> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
path: &Path,
|
path: &Path,
|
||||||
) -> io::Result<SearchResult> {
|
) -> io::Result<SearchResult> {
|
||||||
let bin = self.config.preprocessor.as_ref().unwrap();
|
let bin = self.config.preprocessor.clone().unwrap();
|
||||||
let mut cmd = Command::new(bin);
|
let mut cmd = Command::new(&bin);
|
||||||
cmd.arg(path).stdin(Stdio::from(File::open(path)?));
|
cmd.arg(path).stdin(Stdio::from(File::open(path)?));
|
||||||
|
|
||||||
let rdr = self
|
let rdr = self.command_builder.build(&mut cmd)?;
|
||||||
.command_builder
|
|
||||||
.build(&mut cmd)
|
|
||||||
.map_err(|err| {
|
|
||||||
io::Error::new(
|
|
||||||
io::ErrorKind::Other,
|
|
||||||
format!(
|
|
||||||
"preprocessor command could not start: '{:?}': {}",
|
|
||||||
cmd,
|
|
||||||
err,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
self.search_reader(path, rdr).map_err(|err| {
|
self.search_reader(path, rdr).map_err(|err| {
|
||||||
io::Error::new(
|
io::Error::new(
|
||||||
io::ErrorKind::Other,
|
io::ErrorKind::Other,
|
||||||
|
2
termcolor/README.md
Normal file
2
termcolor/README.md
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
termcolor has moved to its own repository:
|
||||||
|
https://github.com/BurntSushi/termcolor
|
@@ -341,14 +341,6 @@ rgtest!(glob_case_sensitive, |dir: Dir, mut cmd: TestCommand| {
|
|||||||
eqnice!("file2.html:Sherlock\n", cmd.stdout());
|
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| {
|
rgtest!(byte_offset_only_matching, |dir: Dir, mut cmd: TestCommand| {
|
||||||
dir.create("sherlock", SHERLOCK);
|
dir.create("sherlock", SHERLOCK);
|
||||||
cmd.arg("-b").arg("-o").arg("Sherlock");
|
cmd.arg("-b").arg("-o").arg("Sherlock");
|
||||||
|
@@ -392,8 +392,8 @@ rgtest!(r428_unrecognized_style, |_: Dir, mut cmd: TestCommand| {
|
|||||||
let output = cmd.cmd().output().unwrap();
|
let output = cmd.cmd().output().unwrap();
|
||||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||||
let expected = "\
|
let expected = "\
|
||||||
unrecognized style attribute ''. Choose from: nobold, bold, nointense, \
|
invalid --colors spec: unrecognized style attribute ''. \
|
||||||
intense, nounderline, underline.
|
Choose from: nobold, bold, nointense, intense, nounderline, underline.
|
||||||
";
|
";
|
||||||
eqnice!(expected, stderr);
|
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());
|
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
|
// See: https://github.com/BurntSushi/ripgrep/issues/1259
|
||||||
rgtest!(r1259_drop_last_byte_nonl, |dir: Dir, mut cmd: TestCommand| {
|
rgtest!(r1259_drop_last_byte_nonl, |dir: Dir, mut cmd: TestCommand| {
|
||||||
dir.create("patterns-nonl", "[foo]");
|
dir.create("patterns-nonl", "[foo]");
|
||||||
@@ -728,13 +716,3 @@ rgtest!(r1259_drop_last_byte_nonl, |dir: Dir, mut cmd: TestCommand| {
|
|||||||
cmd = dir.command();
|
cmd = dir.command();
|
||||||
eqnice!("fz\n", cmd.arg("-f").arg("patterns-nl").arg("test").stdout());
|
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
2
wincolor/README.md
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
wincolor has moved to the termcolor repository:
|
||||||
|
https://github.com/BurntSushi/termcolor
|
Reference in New Issue
Block a user