diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..8617b72 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,127 @@ +# adapted from https://github.com/BurntSushi/ripgrep/blob/master/.github/workflows/ci.yml +name: ci +on: + pull_request: + push: + # schedule: + # - cron: '00 01 * * *' +jobs: + test: + name: test + env: + # For some builds, we use cross to test on 32-bit and big-endian + # systems. + CARGO: cargo + # When CARGO is set to CROSS, this is set to `--target matrix.target`. + TARGET_FLAGS: + # When CARGO is set to CROSS, TARGET_DIR includes matrix.target. + TARGET_DIR: ./target + # Emit backtraces on panics. + RUST_BACKTRACE: 1 + runs-on: ${{ matrix.os }} + strategy: + matrix: + build: + - nightly + - nightly-musl + - nightly-arm + - macos + - win-msvc + #- win-gnu + include: + #- build: stable + # os: ubuntu-18.04 + # rust: stable + - build: nightly + os: ubuntu-18.04 + rust: nightly + - build: nightly-musl + os: ubuntu-18.04 + rust: nightly + target: x86_64-unknown-linux-musl + - build: nightly-arm + os: ubuntu-18.04 + rust: nightly + target: arm-unknown-linux-gnueabihf + - build: macos + os: macos-latest + rust: nightly + - build: win-msvc + os: windows-2019 + rust: nightly + #- build: win-gnu + # os: windows-2019 + # rust: nightly-x86_64-gnu + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Install packages (Ubuntu) + if: matrix.os == 'ubuntu-18.04' + run: | + ci/ubuntu-install-packages + + - name: Install packages (macOS) + if: matrix.os == 'macos-latest' + run: | + ci/macos-install-packages + + - name: Install Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: ${{ matrix.rust }} + profile: minimal + override: true + + - name: Use Cross + if: matrix.target != '' + run: | + # FIXME: to work around bugs in latest cross release, install master. + # See: https://github.com/rust-embedded/cross/issues/357 + cargo install --git https://github.com/rust-embedded/cross + echo "::set-env name=CARGO::cross" + echo "::set-env name=TARGET_FLAGS::--target ${{ matrix.target }}" + echo "::set-env name=TARGET_DIR::./target/${{ matrix.target }}" + + - name: Show command used for Cargo + run: | + echo "cargo command is: ${{ env.CARGO }}" + echo "target flag is: ${{ env.TARGET_FLAGS }}" + + - name: Build ripgrep-all and all crates + run: ${{ env.CARGO }} build --verbose --all ${{ env.TARGET_FLAGS }} + + # This is useful for debugging problems when the expected build artifacts + # (like shell completions and man pages) aren't generated. + - name: Show build.rs stderr + shell: bash + run: | + set +x + stderr="$(find "${{ env.TARGET_DIR }}/debug" -name stderr -print0 | xargs -0 ls -t | head -n1)" + if [ -s "$stderr" ]; then + echo "===== $stderr ===== " + cat "$stderr" + echo "=====" + fi + set -x + + - name: Run tests (sans cross) + if: matrix.target == '' + run: ${{ env.CARGO }} test --verbose --all ${{ env.TARGET_FLAGS }} + + rustfmt: + name: rustfmt + runs-on: ubuntu-18.04 + steps: + - name: Checkout repository + uses: actions/checkout@v2 + - name: Install Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + profile: minimal + components: rustfmt + - name: Check formatting + run: | + cargo fmt --all -- --check diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..dbb358b --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,205 @@ +# adapted from https://github.com/BurntSushi/ripgrep/blob/master/.github/workflows/release.yml +# The way this works is a little weird. But basically, the create-release job +# runs purely to initialize the GitHub release itself. Once done, the upload +# URL of the release is saved as an artifact. +# +# The build-release job runs only once create-release is finished. It gets +# the release upload URL by downloading the corresponding artifact (which was +# uploaded by create-release). It then builds the release executables for each +# supported platform and attaches them as release assets to the previously +# created release. +# +# The key here is that we create the release only once. + +name: release +on: + push: + # Enable when testing release infrastructure on a branch. + # branches: + # - ag/release + tags: + - 'v[0-9]+.[0-9]+.[0-9]+' +jobs: + create-release: + name: create-release + runs-on: ubuntu-latest + # env: + # Set to force version number, e.g., when no tag exists. + # RG_VERSION: TEST-0.0.0 + steps: + - name: Create artifacts directory + run: mkdir artifacts + + - name: Get the release version from the tag + if: env.RG_VERSION == '' + run: | + # Apparently, this is the right way to get a tag name. Really? + # + # See: https://github.community/t5/GitHub-Actions/How-to-get-just-the-tag-name/m-p/32167/highlight/true#M1027 + echo "::set-env name=RG_VERSION::${GITHUB_REF#refs/tags/}" + echo "version is: ${{ env.RG_VERSION }}" + + - name: Create GitHub release + id: release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ env.RG_VERSION }} + release_name: ${{ env.RG_VERSION }} + + - name: Save release upload URL to artifact + run: echo "${{ steps.release.outputs.upload_url }}" > artifacts/release-upload-url + + - name: Save version number to artifact + run: echo "${{ env.RG_VERSION }}" > artifacts/release-version + + - name: Upload artifacts + uses: actions/upload-artifact@v1 + with: + name: artifacts + path: artifacts + + build-release: + name: build-release + needs: ['create-release'] + runs-on: ${{ matrix.os }} + env: + # For some builds, we use cross to test on 32-bit and big-endian + # systems. + CARGO: cargo + # When CARGO is set to CROSS, this is set to `--target matrix.target`. + TARGET_FLAGS: + # When CARGO is set to CROSS, TARGET_DIR includes matrix.target. + TARGET_DIR: ./target + # Emit backtraces on panics. + RUST_BACKTRACE: 1 + strategy: + matrix: + build: [linux, linux-arm, macos, win-msvc] + include: + - build: linux + os: ubuntu-18.04 + rust: nightly + target: x86_64-unknown-linux-musl + - build: linux-arm + os: ubuntu-18.04 + rust: nightly + target: arm-unknown-linux-gnueabihf + - build: macos + os: macos-latest + rust: nightly + target: x86_64-apple-darwin + - build: win-msvc + os: windows-2019 + rust: nightly + target: x86_64-pc-windows-msvc + #- build: win-gnu + # os: windows-2019 + # rust: nightly-x86_64-gnu + # target: x86_64-pc-windows-gnu + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + with: + fetch-depth: 1 + + - name: Install packages (Ubuntu) + if: matrix.os == 'ubuntu-18.04' + run: | + ci/ubuntu-install-packages + + - name: Install packages (macOS) + if: matrix.os == 'macos-latest' + run: | + ci/macos-install-packages + + - name: Install Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: ${{ matrix.rust }} + profile: minimal + override: true + target: ${{ matrix.target }} + + - name: Use Cross + # if: matrix.os != 'windows-2019' + run: | + # FIXME: to work around bugs in latest cross release, install master. + # See: https://github.com/rust-embedded/cross/issues/357 + cargo install --git https://github.com/rust-embedded/cross + echo "::set-env name=CARGO::cross" + echo "::set-env name=TARGET_FLAGS::--target ${{ matrix.target }}" + echo "::set-env name=TARGET_DIR::./target/${{ matrix.target }}" + + - name: Show command used for Cargo + run: | + echo "cargo command is: ${{ env.CARGO }}" + echo "target flag is: ${{ env.TARGET_FLAGS }}" + echo "target dir is: ${{ env.TARGET_DIR }}" + + - name: Get release download URL + uses: actions/download-artifact@v1 + with: + name: artifacts + path: artifacts + + - name: Set release upload URL and release version + shell: bash + run: | + release_upload_url="$(cat artifacts/release-upload-url)" + echo "::set-env name=RELEASE_UPLOAD_URL::$release_upload_url" + echo "release upload url: $RELEASE_UPLOAD_URL" + release_version="$(cat artifacts/release-version)" + echo "::set-env name=RELEASE_VERSION::$release_version" + echo "release version: $RELEASE_VERSION" + + - name: Build release binary + run: ${{ env.CARGO }} build --verbose --release ${{ env.TARGET_FLAGS }} + + - name: Strip release binary (linux and macos) + if: matrix.build == 'linux' || matrix.build == 'macos' + run: | + strip "target/${{ matrix.target }}/release/rga" "target/${{ matrix.target }}/release/rga-preproc" + + - name: Strip release binary (arm) + if: matrix.build == 'linux-arm' + run: | + docker run --rm -v \ + "$PWD/target:/target:Z" \ + rustembedded/cross:arm-unknown-linux-gnueabihf \ + arm-linux-gnueabihf-strip \ + /target/arm-unknown-linux-gnueabihf/release/rga \ + /target/arm-unknown-linux-gnueabihf/release/rga-preproc + + - name: Build archive + shell: bash + run: | + staging="ripgrep_all-${{ env.RELEASE_VERSION }}-${{ matrix.target }}" + mkdir -p "$staging"/doc + + cp {README.md,LICENSE.md} "$staging/" + cp CHANGELOG.md "$staging/doc/" + + if [ "${{ matrix.os }}" = "windows-2019" ]; then + cp "target/${{ matrix.target }}/release/rga.exe" "$staging/" + cp "target/${{ matrix.target }}/release/rga-preproc.exe" "$staging/" + 7z a "$staging.zip" "$staging" + echo "::set-env name=ASSET::$staging.zip" + else + cp "target/${{ matrix.target }}/release/rga" "$staging/" + cp "target/${{ matrix.target }}/release/rga-preproc" "$staging/" + tar czf "$staging.tar.gz" "$staging" + echo "::set-env name=ASSET::$staging.tar.gz" + fi + + - name: Upload release archive + uses: actions/upload-release-asset@v1.0.1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ env.RELEASE_UPLOAD_URL }} + asset_path: ${{ env.ASSET }} + asset_name: ${{ env.ASSET }} + asset_content_type: application/octet-stream diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 99efa21..0000000 --- a/.travis.yml +++ /dev/null @@ -1,87 +0,0 @@ -language: rust -dist: xenial -env: - global: - - PROJECT_NAME: ripgrep_all - - RUST_BACKTRACE: full -addons: - apt: - packages: - # For generating man page. - - libxslt1-dev - - asciidoc - - docbook-xsl - - xsltproc - - libxml2-utils - # Needed for completion-function test. - - zsh - # Needed for testing decompression search. - - xz-utils - - liblz4-tool - # For building MUSL static builds on Linux. - - musl-tools - # rga specific - - pandoc - - poppler-utils -matrix: - fast_finish: true - include: - # Nightly channel. - # All *nix releases are done on the nightly channel to take advantage - # of the regex library's multiple pattern SIMD search. - - os: linux - rust: nightly - env: TARGET=x86_64-unknown-linux-musl - - os: osx - rust: nightly - # XML_CATALOG_FILES is apparently necessary for asciidoc on macOS. - env: TARGET=x86_64-apple-darwin XML_CATALOG_FILES=/usr/local/etc/xml/catalog - - os: linux - rust: stable - env: TARGET=x86_64-unknown-linux-gnu - - os: linux - rust: stable - env: TARGET=x86_64-unknown-linux-musl - #- os: linux - # rust: 1.35.0 - # env: TARGET=arm-unknown-linux-gnueabihf GCC_VERSION=4.8 - # addons: - # apt: - # packages: - # - gcc-4.8-arm-linux-gnueabihf - # - binutils-arm-linux-gnueabihf - # - libc6-armhf-cross - # - libc6-dev-armhf-cross - # # For generating man page. - # - libxslt1-dev - # - asciidoc - # - docbook-xsl - # - xsltproc - # - libxml2-utils - - os: windows - rust: nightly-x86_64-pc-windows-gnu - env: TARGET=x86_64-pc-windows-gnu -install: ci/install.sh -script: ci/script.sh -before_deploy: ci/before_deploy.sh -deploy: - provider: releases - file_glob: true - file: deployment/${PROJECT_NAME}-${TRAVIS_TAG}-${TARGET}.* - skip_cleanup: true - on: - condition: $TRAVIS_RUST_VERSION = nightly - tags: true - api_key: - secure: BACN/S5fv590pb0bq7rUNX553yxrUDk3ZDcQ9JcG0DXFkv3/XIRzoc88YbDAp065Yk9DJ8SrT9X/Al9l8/MKoLfVmcz3jdFUJAsppkO4fouOxdtiufYq5MFFlrP6SYMHy7Gx95lZsh++NSwbq+1fjMkESOTWqz1ptUmAa7ERecGuX4t/4QoPfyTYNWb84LLDqeD9Geabj7HuCsjsa4gdJUFew13zvE1SFRUkVPVGo09j/+fYVZRoY0ObqHVYQEOlj4HtHHjaYnsLgKHcGGigc252N15sm7zFM0+/lRMYIx7LLv6SmFc/eHqHy8D9gHzUx1tEYnScuNEDDHSS7hXfKGyTrOPfENAqzWCIAftveUVI/+rWmMIOWDxzxt5s9P9k9c93GP7L2L/HJlEZfr0UKQhHfcv/uOaS48vhh4WyzybgBRLFcNwrGKSoHgJhGRHdnQbTc8JMNPBEoJKdtSosQk56ZievMg2rDxF/GArpLTTe58+kMrhFbK9bGBP0YcZjaLnIZuuRf2LZQFtT9gSPFuvXjhwDaz/5a3Gp+9ZIEF50Ad/nf2xKf/rwFaFFJ0RkPdw20TCuerasQUnbpDmZRYnJNrdVlYKIIxQ6dF+PqO8/4RJ1tRYaWk79G8fDVRWp/IfvtduLKqgh/mjNgefOc9qf0DoBVxK7LJx5CHHomkE= -branches: - only: - # Pushes and PR to the master branch - - master - - windows - # Ruby regex to match tags. Required, or travis won't trigger deploys when - # a new tag is pushed. - - /^v\d+\.\d+\.\d+.*$/ -notifications: - email: - on_success: never diff --git a/CHANGELOG.md b/CHANGELOG.md index 186b0f1..b863b09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# 0.9.6 (2020-05-18) + +- Fix windows builds +- Move to Github Actions instead of Travis + # 0.9.5 (2020-04-08) - Allow search in pdf files without extension (https://github.com/phiresky/ripgrep-all/issues/39) diff --git a/Cargo.lock b/Cargo.lock index 764fbc9..468ea77 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,14 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "addr2line" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456d75cbb82da1ad150c8a9d97285ffcd21c9931dcb11e995903e7d75141b38b" +dependencies = [ + "gimli", +] + [[package]] name = "adler32" version = "1.0.4" @@ -21,7 +30,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" dependencies = [ - "winapi 0.3.8", + "winapi", ] [[package]] @@ -38,7 +47,7 @@ checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ "hermit-abi", "libc", - "winapi 0.3.8", + "winapi", ] [[package]] @@ -55,26 +64,17 @@ checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" [[package]] name = "backtrace" -version = "0.3.46" +version = "0.3.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e692897359247cc6bb902933361652380af0f1b7651ae5c5013407f30e109e" +checksum = "0df2f85c8a2abbe3b7d7e748052fdd9b76a0458fdeb16ad4223f5eca78c7c130" dependencies = [ - "backtrace-sys", + "addr2line", "cfg-if", "libc", + "object", "rustc-demangle", ] -[[package]] -name = "backtrace-sys" -version = "0.1.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7de8aba10a69c8e8d7622c5710229485ec32e9d55fdad160ea559c086fdcd118" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "bincode" version = "1.2.1" @@ -125,9 +125,9 @@ checksum = "c06509d1f4ffa658939bd23f076cd929ef218241363796551528e7eec69128c8" [[package]] name = "cc" -version = "1.0.50" +version = "1.0.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd" +checksum = "404b1fe4f65288577753b17e3b36a04596ee784493ec249bf81c7f2d2acd751c" dependencies = [ "jobserver", ] @@ -151,9 +151,9 @@ dependencies = [ [[package]] name = "clap" -version = "2.33.0" +version = "2.33.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" +checksum = "bdfa80d47f954d53a35a64987ca1422f495b8d6483c0fe9f7117b36c2a792129" dependencies = [ "ansi_term", "atty", @@ -256,9 +256,9 @@ dependencies = [ [[package]] name = "encoding_rs" -version = "0.8.22" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd8d03faa7fe0c1431609dfad7bbe827af30f82e1e2ae6f7ee4fca6bd764bc28" +checksum = "e8ac63f94732332f44fe654443c46f6375d1939684c17b0afb6cb56b0456e171" dependencies = [ "cfg-if", ] @@ -296,9 +296,9 @@ dependencies = [ [[package]] name = "failure" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8529c2421efa3066a5cbd8063d2244603824daccb6936b079010bb2aa89464b" +checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" dependencies = [ "backtrace", "failure_derive", @@ -306,9 +306,9 @@ dependencies = [ [[package]] name = "failure_derive" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "030a733c8287d6213886dd487564ff5c8f6aae10278b3588ed177f9d18f8d231" +checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ "proc-macro2", "quote", @@ -330,14 +330,14 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" [[package]] name = "filetime" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f59efc38004c988e4201d11d263b8171f49a2e7ec0bdbb71773433f271504a5e" +checksum = "affc17579b132fc2461adf7c575cc6e8b134ebca52c51f5411388965227dc695" dependencies = [ "cfg-if", "libc", "redox_syscall", - "winapi 0.3.8", + "winapi", ] [[package]] @@ -360,9 +360,9 @@ dependencies = [ [[package]] name = "fnv" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "fuchsia-cprng" @@ -390,6 +390,12 @@ dependencies = [ "wasi", ] +[[package]] +name = "gimli" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcc8e0c9bce37868955864dbecd2b1ab2bdf967e6f28066d65aaac620444b65c" + [[package]] name = "glob" version = "0.3.0" @@ -407,9 +413,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.1.10" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "725cf19794cf90aa94e65050cb4191ff5d8fa87a498383774c47b332e3af952e" +checksum = "91780f809e750b0a89f5544be56617ff6b1227ee485bcb06ebe10cdf89bd3b71" dependencies = [ "libc", ] @@ -449,16 +455,6 @@ dependencies = [ "libc", ] -[[package]] -name = "kernel32-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - [[package]] name = "lazy_static" version = "1.4.0" @@ -467,15 +463,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.68" +version = "0.2.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0" +checksum = "3baa92041a6fec78c687fa0cc2b3fae8884f743d672cf551bed1d6dac6988d0f" [[package]] name = "libsqlite3-sys" -version = "0.17.2" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38c4446f020dfbfab9f8a1ab605c15e6c03a8924c08522dcb67314acc8d2b523" +checksum = "1e704a02bcaecd4a08b93a23f6be59d0bd79cd161e0963e9499165a0a35df7bd" dependencies = [ "cc", "pkg-config", @@ -484,9 +480,9 @@ dependencies = [ [[package]] name = "linked-hash-map" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" +checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a" [[package]] name = "lmdb-rkv" @@ -540,9 +536,9 @@ dependencies = [ [[package]] name = "lzma-sys" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e48818fd597d46155132bbbb9505d6d1b3d360b4ee25cfa91c406f8a90fe91" +checksum = "f24f76ec44a8ac23a31915d6e326bca17ce88da03096f1ff194925dc714dac99" dependencies = [ "cc", "libc", @@ -655,6 +651,12 @@ dependencies = [ "autocfg 1.0.0", ] +[[package]] +name = "object" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cbca9424c482ee628fa549d9c812e2cd22f1180b9222c9200fdfa6eb31aecb2" + [[package]] name = "ordered-float" version = "1.0.2" @@ -694,14 +696,14 @@ dependencies = [ "redox_syscall", "rustc_version", "smallvec 0.6.13", - "winapi 0.3.8", + "winapi", ] [[package]] name = "paste" -version = "0.1.10" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab4fb1930692d1b6a9cfabdde3d06ea0a7d186518e2f4d67660d8970e2fa647a" +checksum = "0a229b1c58c692edcaa5b9b0948084f130f55d2dcc15b02fcc5340b2b4521476" dependencies = [ "paste-impl", "proc-macro-hack", @@ -709,9 +711,9 @@ dependencies = [ [[package]] name = "paste-impl" -version = "0.1.10" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62486e111e571b1e93b710b61e8f493c0013be39629b714cb166bdb06aa5a8a" +checksum = "2e0bf239e447e67ff6d16a8bb5e4d4bd2343acf5066061c0e8e06ac5ba8ca68c" dependencies = [ "proc-macro-hack", "proc-macro2", @@ -755,15 +757,15 @@ checksum = "780fb4b6698bbf9cf2444ea5d22411cef2953f0824b98f33cf454ec5615645bd" [[package]] name = "ppv-lite86" -version = "0.2.6" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" +checksum = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea" [[package]] name = "proc-macro-error" -version = "0.4.12" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18f33027081eba0a6d8aba6d1b1c3a3be58cbb12106341c2d5759fcd9b5277e7" +checksum = "98e9e4b82e0ef281812565ea4751049f1bdcdfccda7d3f459f2e138a40c08678" dependencies = [ "proc-macro-error-attr", "proc-macro2", @@ -774,9 +776,9 @@ dependencies = [ [[package]] name = "proc-macro-error-attr" -version = "0.4.12" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a5b4b77fdb63c1eca72173d68d24501c54ab1269409f6b672c85deb18af69de" +checksum = "4f5444ead4e9935abd7f27dc51f7e852a0569ac888096d5ec2499470794e2e53" dependencies = [ "proc-macro2", "quote", @@ -793,9 +795,9 @@ checksum = "0d659fe7c6d27f25e9d80a1a094c223f5246f6a6596453e09d7229bf42750b63" [[package]] name = "proc-macro2" -version = "1.0.10" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df246d292ff63439fea9bc8c0a270bed0e390d5ebd4db4ba15aba81111b5abe3" +checksum = "53f5ffe53a6b28e37c9c1ce74893477864d64f74778a93a4beb43c8fa167f639" dependencies = [ "unicode-xid", ] @@ -808,9 +810,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.3" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" +checksum = "54a21852a652ad6f610c9510194f398ff6f8692e334fd1145fed931f7fbe44ea" dependencies = [ "proc-macro2", ] @@ -831,7 +833,7 @@ dependencies = [ "rand_os", "rand_pcg", "rand_xorshift", - "winapi 0.3.8", + "winapi", ] [[package]] @@ -926,7 +928,7 @@ checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" dependencies = [ "libc", "rand_core 0.4.2", - "winapi 0.3.8", + "winapi", ] [[package]] @@ -940,7 +942,7 @@ dependencies = [ "libc", "rand_core 0.4.2", "rdrand", - "winapi 0.3.8", + "winapi", ] [[package]] @@ -979,9 +981,9 @@ checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" [[package]] name = "regex" -version = "1.3.6" +version = "1.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6946991529684867e47d86474e3a6d0c0ab9b82d5821e314b1ede31fa3a4b3" +checksum = "a6020f034922e3194c711b82a627453881bc4682166cabb07134a10c26ba7692" dependencies = [ "aho-corasick", "memchr", @@ -1001,12 +1003,12 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" dependencies = [ - "winapi 0.3.8", + "winapi", ] [[package]] name = "ripgrep_all" -version = "0.9.6-alpha.0" +version = "0.9.13-alpha.0" dependencies = [ "bincode", "bzip2", @@ -1062,9 +1064,9 @@ dependencies = [ [[package]] name = "rusqlite" -version = "0.21.0" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a656821bb6317a84b257737b7934f79c0dbb7eb694710475908280ebad3e64" +checksum = "45d0fd62e1df63d254714e6cb40d0a0e82e7a1623e7a27f679d851af092ae58b" dependencies = [ "bitflags", "fallible-iterator", @@ -1073,6 +1075,7 @@ dependencies = [ "libsqlite3-sys", "lru-cache", "memchr", + "smallvec 1.4.0", "time", ] @@ -1093,9 +1096,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "535622e6be132bccd223f4bb2b8ac8d53cda3c7a6394944d3b2b33fb974f9d76" +checksum = "ed3d612bc64430efeb3f7ee6ef26d590dce0c43249217bddc62112540c7941e1" [[package]] name = "scopeguard" @@ -1120,18 +1123,18 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.106" +version = "1.0.110" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df6ac6412072f67cf767ebbde4133a5b2e88e76dc6187fa7104cd16f783399" +checksum = "99e7b308464d16b56eba9964e4972a3eee817760ab60d88c3f86e1fecb08204c" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.106" +version = "1.0.110" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e549e3abf4fb8621bd1609f11dfc9f5e50320802273b12f3811a67e6716ea6c" +checksum = "818fbf6bfa9a42d3bfcaca148547aa00c7b915bec71d1757aa2d44ca68771984" dependencies = [ "proc-macro2", "quote", @@ -1140,9 +1143,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.51" +version = "1.0.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da07b57ee2623368351e9a0488bb0b261322a15a6e0ae53e243cbdc0f4208da9" +checksum = "993948e75b189211a9b31a7528f950c6adc21f9720b6438ff80a7fa2f864cea2" dependencies = [ "itoa", "ryu", @@ -1170,9 +1173,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.2.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c2fb2ec9bcd216a5b0d0ccf31ab17b5ed1d627960edff65bbe95d3ce221cefc" +checksum = "c7cb5678e1615754284ec264d9bb5b4c27d2018577fd90ac0ceb578591ed5ee4" [[package]] name = "strsim" @@ -1182,9 +1185,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "structopt" -version = "0.3.12" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8faa2719539bbe9d77869bfb15d4ee769f99525e707931452c97b693b3f159d" +checksum = "863246aaf5ddd0d6928dfeb1a9ca65f505599e4e1b399935ef7e75107516b4ef" dependencies = [ "clap", "lazy_static", @@ -1193,9 +1196,9 @@ dependencies = [ [[package]] name = "structopt-derive" -version = "0.4.5" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f88b8e18c69496aad6f9ddf4630dd7d585bcaf765786cb415b9aec2fe5a0430" +checksum = "d239ca4b13aee7a2142e6795cbd69e457665ff8037aed33b3effdc430d2f927a" dependencies = [ "heck", "proc-macro-error", @@ -1206,9 +1209,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.17" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03" +checksum = "1425de3c33b0941002740a420b1a906a350b88d08b82b2c8a01035a3f9447bac" dependencies = [ "proc-macro2", "quote", @@ -1261,18 +1264,17 @@ dependencies = [ "rand 0.7.3", "redox_syscall", "remove_dir_all", - "winapi 0.3.8", + "winapi", ] [[package]] name = "term_size" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5b9a66db815dcfd2da92db471106457082577c3c278d4138ab3e3b4e189327" +checksum = "1e4129646ca0ed8f45d09b929036bafad5377103edd06e50bf574b353d2b08d9" dependencies = [ - "kernel32-sys", "libc", - "winapi 0.2.8", + "winapi", ] [[package]] @@ -1305,13 +1307,12 @@ dependencies = [ [[package]] name = "time" -version = "0.1.42" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" +checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" dependencies = [ "libc", - "redox_syscall", - "winapi 0.3.8", + "winapi", ] [[package]] @@ -1329,9 +1330,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.11.2" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" +checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" [[package]] name = "unicode-bidi" @@ -1348,7 +1349,7 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4" dependencies = [ - "smallvec 1.2.0", + "smallvec 1.4.0", ] [[package]] @@ -1394,9 +1395,9 @@ checksum = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168" [[package]] name = "vec_map" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "version_check" @@ -1410,12 +1411,6 @@ version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" -[[package]] -name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" - [[package]] name = "winapi" version = "0.3.8" @@ -1426,12 +1421,6 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu", ] -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" - [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -1440,11 +1429,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa515c5163a99cc82bab70fd3bfdd36d827be85de63737b40fcef2ce084a436e" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" dependencies = [ - "winapi 0.3.8", + "winapi", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 0cc813b..7269704 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,8 @@ description = "rga: ripgrep, but also search in PDFs, E-Books, Office documents, license = "AGPL-3.0-or-later" readme = "README.md" version = "0.9.6-alpha.0" -repository = "https://github.com/phiresky/ripgrep_all" +repository = "https://github.com/phiresky/ripgrep-all" +homepage = "https://github.com/phiresky/ripgrep-all" authors = ["phiresky "] edition = "2018" exclude = [ @@ -38,7 +39,7 @@ tar = "0.4.26" chrono = "0.4.11" encoding_rs = "0.8.22" encoding_rs_io = "0.1.7" -rusqlite = { version = "0.21.0", features = ["vtab", "bundled"] } +rusqlite = { version = "0.23.1", features = ["vtab", "bundled"] } size_format = "1.0.2" structopt = "0.3.12" paste = "0.1.10" diff --git a/README.md b/README.md index a6d5929..680c499 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ demo/ ## INSTALLATION -Linux x64, OSX and Windows binaries are available [in GitHub Releases][latestrelease]. +Linux x64, macOS and Windows binaries are available [in GitHub Releases][latestrelease]. [latestrelease]: https://github.com/phiresky/ripgrep-all/releases/latest @@ -47,7 +47,11 @@ rga will search for all binaries it calls in \$PATH and the directory itself is ### Windows -Just unzip the [Windows binary release][latestrelease] anywhere, possibly somewhere in your \$PATH. It includes all necessary and optional dependencies. +Install ripgrep-all via [Chocolatey](https://chocolatey.org/packages/ripgrep-all): + +``` +choco install ripgrep-all +``` If you get an error like `VCRUNTIME140.DLL could not be found`, you need to install [vc_redist.x64.exe](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads). @@ -57,7 +61,7 @@ If you get an error like `VCRUNTIME140.DLL could not be found`, you need to inst `brew install rga` -To install the dependencies: +To install the dependencies that are each not strictly necessary but very useful: `brew install pandoc poppler tesseract ffmpeg` diff --git a/ci/README.md b/ci/README.md deleted file mode 100644 index 432c721..0000000 --- a/ci/README.md +++ /dev/null @@ -1 +0,0 @@ -everything in here shamelessly copied from ripgrep itself diff --git a/ci/before_deploy.sh b/ci/before_deploy.sh deleted file mode 100755 index 1792c4f..0000000 --- a/ci/before_deploy.sh +++ /dev/null @@ -1,101 +0,0 @@ -#!/bin/bash - -# package the build artifacts - -set -ex - -. "$(dirname $0)/utils.sh" - -# Generate artifacts for release -mk_artifacts() { - CARGO="$(builder)" - "$CARGO" build --target "$TARGET" --release -} - -# run from tmpdir, put results in $1/ -# currently windows only, because other OS probably have a package manager -# also currently just a fixed version of each tool since it doesn't matter much -download_other_binaries() { - outdir="$1" - mkdir -p "$outdir/licenses" "$outdir/lib" - - # ffmpeg - wget -q https://ffmpeg.zeranoe.com/builds/win64/static/ffmpeg-4.1.3-win64-static.zip -O ffmpeg.zip - unzip ffmpeg.zip - cp ffmpeg-*/bin/{ffmpeg,ffprobe}.exe "$outdir/lib" - cp ffmpeg-*/LICENSE.txt "$outdir/licenses/ffmpeg" - - # poppler - wget -q https://blog.alivate.com.au/wp-content/uploads/2018/10/poppler-0.68.0_x86.7z -O poppler.7z - 7z x poppler.7z - for f in pdftotext.exe libpoppler-79.dll libgcc_s_dw2-1.dll libstdc++-6.dll jpeg62.dll libpng16-16.dll libtiff3.dll zlib1.dll freetype6.dll libpoppler-79.dll; do - cp poppler-*/bin/"$f" "$outdir/lib" - done - cp poppler-*/bin/COPYING3 "$outdir/licenses/poppler" - - wget -q https://github.com/jgm/pandoc/releases/download/2.7.3/pandoc-2.7.3-windows-x86_64.zip -O pandoc.zip - unzip pandoc.zip - cp pandoc-*/pandoc.exe "$outdir/lib" - cp pandoc-*/COPYRIGHT.txt "$outdir/licenses/pandoc" - - wget -q https://github.com/BurntSushi/ripgrep/releases/download/11.0.1/ripgrep-11.0.1-x86_64-pc-windows-msvc.zip -O ripgrep.zip - unzip ripgrep.zip - cp rg.exe "$outdir/lib" - -} - -mk_tarball() { - # When cross-compiling, use the right `strip` tool on the binary. - local gcc_prefix="$(gcc_prefix)" - # Create a temporary dir that contains our staging area. - # $tmpdir/$name is what eventually ends up as the deployed archive. - local tmpdir="$(mktemp -d)" - local name="${PROJECT_NAME}-${TRAVIS_TAG}-${TARGET}" - local staging="$tmpdir/$name" - mkdir -p "$staging/" - # mkdir -p "$staging"/{complete,doc} - # The deployment directory is where the final archive will reside. - # This path is known by the .travis.yml configuration. - local out_dir="$(pwd)/deployment" - mkdir -p "$out_dir" - # Find the correct (most recent) Cargo "out" directory. The out directory - # contains shell completion files and the man page. - local cargo_out_dir="$(cargo_out_dir "target/$TARGET")" - - bin_ext="" - if is_windows; then - bin_ext=".exe" - fi - - # Copy the binaries and strip it. - for binary in rga rga-preproc; do - cp "target/$TARGET/release/$binary$bin_ext" "$staging/$binary$bin_ext" - # "${gcc_prefix}strip" "$staging/$binary" - done - # Copy the licenses and README. - cp {README.md,LICENSE.md} "$staging/" - # Copy documentation and man page. - # cp {CHANGELOG.md,FAQ.md,GUIDE.md} "$staging/doc/" - #if command -V a2x 2>&1 > /dev/null; then - # # The man page should only exist if we have asciidoc installed. - # cp "$cargo_out_dir/rg.1" "$staging/doc/" - #fi - # Copy shell completion files. - # cp "$cargo_out_dir"/{rg.bash,rg.fish,_rg.ps1} "$staging/complete/" - # cp complete/_rg "$staging/complete/" - - if is_windows; then - (cd "$tmpdir" && download_other_binaries "$name") - (cd "$tmpdir" && 7z a "$out_dir/$name.7z" "$name") - else - (cd "$tmpdir" && tar czf "$out_dir/$name.tar.gz" "$name") - fi - rm -rf "$tmpdir" -} - -main() { - mk_artifacts - mk_tarball -} - -main diff --git a/ci/build_deb.sh b/ci/build_deb.sh deleted file mode 100755 index 1d7548f..0000000 --- a/ci/build_deb.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/bash - -set -e - -# This script builds a binary dpkg for Debian based distros. It does not -# currently run in CI, and is instead run manually and the resulting dpkg is -# uploaded to GitHub via the web UI. -# -# Note that this requires 'cargo deb', which can be installed with -# 'cargo install cargo-deb'. -# -# This should be run from the root of the ripgrep repo. - -if ! command -V cargo-deb > /dev/null 2>&1; then - echo "cargo-deb command missing" >&2 - exit 1 -fi - -# 'cargo deb' does not seem to provide a way to specify an asset that is -# created at build time, such as ripgrep's man page. To work around this, -# we force a debug build, copy out the man page (and shell completions) -# produced from that build, put it into a predictable location and then build -# the deb, which knows where to look. - -DEPLOY_DIR=deployment/deb -mkdir -p "$DEPLOY_DIR" -cargo build - -# Find and copy man page. -manpage="$(find ./target/debug -name rg.1 -print0 | xargs -0 ls -t | head -n1)" -cp "$manpage" "$DEPLOY_DIR/" - -# Do the same for shell completions. -compbash="$(find ./target/debug -name rg.bash -print0 | xargs -0 ls -t | head -n1)" -cp "$compbash" "$DEPLOY_DIR/" -compfish="$(find ./target/debug -name rg.fish -print0 | xargs -0 ls -t | head -n1)" -cp "$compfish" "$DEPLOY_DIR/" -compzsh="complete/_rg" -cp "$compzsh" "$DEPLOY_DIR/" - -cargo deb diff --git a/ci/install.sh b/ci/install.sh deleted file mode 100755 index 37af9d7..0000000 --- a/ci/install.sh +++ /dev/null @@ -1,61 +0,0 @@ -#!/bin/bash - -# install stuff needed for the `script` phase - -# Where rustup gets installed. -export PATH="$PATH:$HOME/.cargo/bin" - -set -ex - -. "$(dirname $0)/utils.sh" - -install_rustup() { - curl https://sh.rustup.rs -sSf \ - | sh -s -- -y --default-toolchain="$TRAVIS_RUST_VERSION" - rustc -V - cargo -V -} - -install_targets() { - if [ $(host) != "$TARGET" ]; then - rustup target add $TARGET - fi -} - -install_osx_dependencies() { - if ! is_osx; then - return - fi - - brew install asciidoc docbook-xsl -} - -configure_cargo() { - local prefix=$(gcc_prefix) - if [ -n "${prefix}" ]; then - local gcc_suffix= - if [ -n "$GCC_VERSION" ]; then - gcc_suffix="-$GCC_VERSION" - fi - local gcc="${prefix}gcc${gcc_suffix}" - - # information about the cross compiler - "${gcc}" -v - - # tell cargo which linker to use for cross compilation - mkdir -p .cargo - cat >>.cargo/config <&2 - exit 1 -fi -version="$1" - -# Linux and Darwin builds. -for arch in i686 x86_64; do - for target in apple-darwin unknown-linux-musl; do - url="https://github.com/BurntSushi/ripgrep/releases/download/$version/ripgrep-$version-$arch-$target.tar.gz" - sha=$(curl -sfSL "$url" | sha256sum) - echo "$version-$arch-$target $sha" - done -done - -# Source. -for ext in zip tar.gz; do - url="https://github.com/BurntSushi/ripgrep/archive/$version.$ext" - sha=$(curl -sfSL "$url" | sha256sum) - echo "source.$ext $sha" -done diff --git a/ci/test_complete.sh b/ci/test_complete.sh deleted file mode 100755 index 985ef11..0000000 --- a/ci/test_complete.sh +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/env zsh - -emulate zsh -o extended_glob -o no_function_argzero -o no_unset - -## -# Compares options in `rg --help` output to options in zsh completion function - -get_comp_args() { - # Technically there are many options that the completion system sets that - # our function may rely on, but we'll trust that we've got it mostly right - setopt local_options unset - - # Our completion function recognises a special variable which tells it to - # dump the _arguments specs and then just return. But do this in a sub-shell - # anyway to avoid any weirdness - ( _RG_COMPLETE_LIST_ARGS=1 source $1 ) -} - -main() { - local diff - local rg="${0:a:h}/../target/${TARGET:-}/release/rg" - local _rg="${0:a:h}/../complete/_rg" - local -a help_args comp_args - - [[ -e $rg ]] || rg=${rg/%\/release\/rg/\/debug\/rg} - - rg=${rg:a} - _rg=${_rg:a} - - [[ -e $rg ]] || { - print -r >&2 "File not found: $rg" - return 1 - } - [[ -e $_rg ]] || { - print -r >&2 "File not found: $_rg" - return 1 - } - - print -rl - 'Comparing options:' "-$rg" "+$_rg" - - # 'Parse' options out of the `--help` output. To prevent false positives we - # only look at lines where the first non-white-space character is `-`, or - # where a long option starting with certain letters (see `_rg`) is found. - # Occasionally we may have to handle some manually, however - help_args=( ${(f)"$( - $rg --help | - $rg -i -- '^\s+--?[a-z0-9]|--[imnp]' | - $rg -ior '$1' -- $'[\t /\"\'`.,](-[a-z0-9]|--[a-z0-9-]+)\\b' | - $rg -v -- --print0 | # False positives - sort -u - )"} ) - - # 'Parse' options out of the completion function - comp_args=( ${(f)"$( get_comp_args $_rg )"} ) - - # Note that we currently exclude hidden (!...) options; matching these - # properly against the `--help` output could be irritating - comp_args=( ${comp_args#\(*\)} ) # Strip excluded options - comp_args=( ${comp_args#\*} ) # Strip repetition indicator - comp_args=( ${comp_args%%-[:[]*} ) # Strip everything after -optname- - comp_args=( ${comp_args%%[:+=[]*} ) # Strip everything after other optspecs - comp_args=( ${comp_args##[^-]*} ) # Remove non-options - comp_args=( ${(f)"$( print -rl - $comp_args | sort -u )"} ) - - (( $#help_args )) || { - print -r >&2 'Failed to get help_args' - return 1 - } - (( $#comp_args )) || { - print -r >&2 'Failed to get comp_args' - return 1 - } - - diff="$( - if diff --help 2>&1 | grep -qF -- '--label'; then - diff -U2 \ - --label '`rg --help`' \ - --label '`_rg`' \ - =( print -rl - $help_args ) =( print -rl - $comp_args ) - else - diff -U2 \ - -L '`rg --help`' \ - -L '`_rg`' \ - =( print -rl - $help_args ) =( print -rl - $comp_args ) - fi - )" - - (( $#diff )) && { - printf >&2 '%s\n' 'zsh completion options differ from `--help` options:' - printf >&2 '%s\n' $diff - return 1 - } - printf 'OK\n' - return 0 -} - -main "$@" diff --git a/ci/ubuntu-install-packages b/ci/ubuntu-install-packages new file mode 100755 index 0000000..1a24852 --- /dev/null +++ b/ci/ubuntu-install-packages @@ -0,0 +1 @@ +#!/bin/sh diff --git a/ci/utils.sh b/ci/utils.sh deleted file mode 100755 index 791485a..0000000 --- a/ci/utils.sh +++ /dev/null @@ -1,116 +0,0 @@ -#!/bin/bash - -# Various utility functions used through CI. - -# Finds Cargo's `OUT_DIR` directory from the most recent build. -# -# This requires one parameter corresponding to the target directory -# to search for the build output. -cargo_out_dir() { - # This works by finding the most recent stamp file, which is produced by - # every ripgrep build. - target_dir="$1" - find "$target_dir" -name ripgrep-stamp -print0 \ - | xargs -0 ls -t \ - | head -n1 \ - | xargs dirname -} - -host() { - case "$TRAVIS_OS_NAME" in - linux) - echo x86_64-unknown-linux-gnu - ;; - osx) - echo x86_64-apple-darwin - ;; - windows) - echo x86_64-pc-windows-msvc - esac -} - -architecture() { - case "$TARGET" in - x86_64-*) - echo amd64 - ;; - i686-*|i586-*|i386-*) - echo i386 - ;; - arm*-unknown-linux-gnueabihf) - echo armhf - ;; - *) - die "architecture: unexpected target $TARGET" - ;; - esac -} - -gcc_prefix() { - case "$(architecture)" in - armhf) - echo arm-linux-gnueabihf- - ;; - *) - return - ;; - esac -} - -is_musl() { - case "$TARGET" in - *-musl) return 0 ;; - *) return 1 ;; - esac -} - -is_x86() { - case "$(architecture)" in - amd64|i386) return 0 ;; - *) return 1 ;; - esac -} - -is_x86_64() { - case "$(architecture)" in - amd64) return 0 ;; - *) return 1 ;; - esac -} - -is_arm() { - case "$(architecture)" in - armhf) return 0 ;; - *) return 1 ;; - esac -} - -is_linux() { - case "$TRAVIS_OS_NAME" in - linux) return 0 ;; - *) return 1 ;; - esac -} - -is_osx() { - case "$TRAVIS_OS_NAME" in - osx) return 0 ;; - *) return 1 ;; - esac -} - -is_windows() { - case "$TRAVIS_OS_NAME" in - windows) return 0 ;; - *) return 1 ;; - esac -} - -builder() { - if is_musl && is_x86_64; then - cargo install cross - echo "cross" - else - echo "cargo" - fi -} diff --git a/src/adapters/pdfpages.rs b/src/adapters/pdfpages.rs index f3ec0e9..27a611a 100644 --- a/src/adapters/pdfpages.rs +++ b/src/adapters/pdfpages.rs @@ -11,98 +11,98 @@ use std::process::Command; static EXTENSIONS: &[&str] = &["pdf"]; lazy_static! { - static ref METADATA: AdapterMeta = AdapterMeta { - name: "pdfpages".to_owned(), - version: 1, - description: "Converts a pdf to its individual pages as png files. Only useful in combination with tesseract".to_owned(), - recurses: true, - fast_matchers: EXTENSIONS - .iter() - .map(|s| FastMatcher::FileExtension(s.to_string())) - .collect(), - slow_matchers: Some(vec![SlowMatcher::MimeType( + static ref METADATA: AdapterMeta = AdapterMeta { + name: "pdfpages".to_owned(), + version: 1, + description: "Converts a pdf to its individual pages as png files. Only useful in combination with tesseract".to_owned(), + recurses: true, + fast_matchers: EXTENSIONS + .iter() + .map(|s| FastMatcher::FileExtension(s.to_string())) + .collect(), + slow_matchers: Some(vec![SlowMatcher::MimeType( "application/pdf".to_owned() )]) - }; + }; } #[derive(Default)] pub struct PdfPagesAdapter {} impl PdfPagesAdapter { - pub fn new() -> PdfPagesAdapter { - PdfPagesAdapter {} - } + pub fn new() -> PdfPagesAdapter { + PdfPagesAdapter {} + } } impl GetMetadata for PdfPagesAdapter { - fn metadata(&self) -> &AdapterMeta { - &METADATA - } + fn metadata(&self) -> &AdapterMeta { + &METADATA + } } /// A pdf is basically converted to a zip that has Page X.png files. /// This way, something like tesseract can process the pages individually impl FileAdapter for PdfPagesAdapter { - fn adapt(&self, ai: AdaptInfo, _detection_reason: &SlowMatcher) -> Fallible<()> { - let AdaptInfo { - filepath_hint, - is_real_file, - oup, - line_prefix, - archive_recursion_depth, - config, - .. - } = ai; - if !is_real_file { - // todo: read to memory and then use that blob if size < max - writeln!(oup, "{}[rga: skipping pdfpages in archive]", line_prefix,)?; - return Ok(()); - } - let inp_fname = filepath_hint; - let exe_name = "gm"; - let out_dir = tempfile::Builder::new().prefix("pdfpages-").tempdir()?; - let out_fname = out_dir.path().join("out%04d.png"); - debug!("writing to temp dir: {}", out_fname.display()); - let mut cmd = Command::new(exe_name); - cmd.arg("convert") - .arg("-density") - .arg("200") - .arg(inp_fname) - .arg("+adjoin") - .arg(out_fname); + fn adapt(&self, ai: AdaptInfo, _detection_reason: &SlowMatcher) -> Fallible<()> { + let AdaptInfo { + filepath_hint, + is_real_file, + oup, + line_prefix, + archive_recursion_depth, + config, + .. + } = ai; + if !is_real_file { + // todo: read to memory and then use that blob if size < max + writeln!(oup, "{}[rga: skipping pdfpages in archive]", line_prefix,)?; + return Ok(()); + } + let inp_fname = filepath_hint; + let exe_name = "gm"; + let out_dir = tempfile::Builder::new().prefix("pdfpages-").tempdir()?; + let out_fname = out_dir.path().join("out%04d.png"); + debug!("writing to temp dir: {}", out_fname.display()); + let mut cmd = Command::new(exe_name); + cmd.arg("convert") + .arg("-density") + .arg("200") + .arg(inp_fname) + .arg("+adjoin") + .arg(out_fname); - let mut cmd = cmd.spawn().map_err(|e| { - map_exe_error(e, exe_name, "Make sure you have imagemagick installed.") - })?; - let args = config.args; + let mut cmd = cmd + .spawn() + .map_err(|e| map_exe_error(e, exe_name, "Make sure you have imagemagick installed."))?; + let args = config.args; - let status = cmd.wait()?; - if status.success() { - } else { - return Err(format_err!("subprocess failed: {:?}", status)); - } - for (i, filename) in glob::glob( - out_dir - .path() - .join("out*.png") - .to_str() - .expect("temp path has invalid encoding"), - )? - .enumerate() - { - let mut ele = BufReader::new(File::open(filename?)?); - rga_preproc(AdaptInfo { - filepath_hint: &PathBuf::from(format!("Page {}.png", i + 1)), - is_real_file: false, - inp: &mut ele, - oup, - line_prefix: &format!("{}Page {}:", line_prefix, i + 1), - archive_recursion_depth: archive_recursion_depth + 1, - config: PreprocConfig { cache: None, args }, - })?; - } - Ok(()) - } + let status = cmd.wait()?; + if status.success() { + } else { + return Err(format_err!("subprocess failed: {:?}", status)); + } + for (i, filename) in glob::glob( + out_dir + .path() + .join("out*.png") + .to_str() + .expect("temp path has invalid encoding"), + )? + .enumerate() + { + let mut ele = BufReader::new(File::open(filename?)?); + rga_preproc(AdaptInfo { + filepath_hint: &PathBuf::from(format!("Page {}.png", i + 1)), + is_real_file: false, + inp: &mut ele, + oup, + line_prefix: &format!("{}Page {}:", line_prefix, i + 1), + archive_recursion_depth: archive_recursion_depth + 1, + config: PreprocConfig { cache: None, args }, + })?; + } + Ok(()) + } } /*// todo: do this in an actually streaming fashion and less slow @@ -111,28 +111,28 @@ impl FileAdapter for PdfPagesAdapter { let split_seq = hex_literal::hex!("4945 4e44 ae42 6082 8950 4e47 0d0a 1a0a"); let split_seq_inx = 8; fn split_by_seq<'a>( - split_seq: &'a [u8], - split_inx: usize, - read: &mut Read, + split_seq: &'a [u8], + split_inx: usize, + read: &mut Read, ) -> Fallible + 'a> { - let regex = split_seq - .iter() - .map(|c| format!("\\x{:0>2x}", c)) - .collect::>() - .join(""); - let restr = format!("(?-u){}", regex); - eprintln!("re: {}", restr); - let re = regex::bytes::Regex::new(&restr)?; + let regex = split_seq + .iter() + .map(|c| format!("\\x{:0>2x}", c)) + .collect::>() + .join(""); + let restr = format!("(?-u){}", regex); + eprintln!("re: {}", restr); + let re = regex::bytes::Regex::new(&restr)?; - let mut all = Vec::new(); - read.read_to_end(&mut all)?; - let mut out: Vec>> = Vec::new(); - let mut last = 0; - for (i, split) in re.find_iter(&all).enumerate() { - let pos = split.start() + split_inx; - out.push(Cursor::new(Vec::from(&all[last..pos]))); - last = pos; - } - out.push(Cursor::new(Vec::from(&all[last..]))); - Ok(out) + let mut all = Vec::new(); + read.read_to_end(&mut all)?; + let mut out: Vec>> = Vec::new(); + let mut last = 0; + for (i, split) in re.find_iter(&all).enumerate() { + let pos = split.start() + split_inx; + out.push(Cursor::new(Vec::from(&all[last..pos]))); + last = pos; + } + out.push(Cursor::new(Vec::from(&all[last..]))); + Ok(out) }*/ diff --git a/src/adapters/poppler.rs b/src/adapters/poppler.rs index 6be887c..1b501d7 100644 --- a/src/adapters/poppler.rs +++ b/src/adapters/poppler.rs @@ -17,9 +17,7 @@ lazy_static! { .iter() .map(|s| FastMatcher::FileExtension(s.to_string())) .collect(), - slow_matchers: Some(vec![SlowMatcher::MimeType( - "application/pdf".to_owned() - )]) + slow_matchers: Some(vec![SlowMatcher::MimeType("application/pdf".to_owned())]) }; } #[derive(Default)] diff --git a/src/adapters/tesseract.rs b/src/adapters/tesseract.rs index 652634c..c1244c7 100644 --- a/src/adapters/tesseract.rs +++ b/src/adapters/tesseract.rs @@ -6,39 +6,39 @@ use std::process::Command; static EXTENSIONS: &[&str] = &["jpg", "png"]; lazy_static! { - static ref METADATA: AdapterMeta = AdapterMeta { - name: "tesseract".to_owned(), - version: 1, - description: "Uses tesseract to run OCR on images to make them searchable. May need -j1 to prevent overloading the system. Make sure you have tesseract installed.".to_owned(), - recurses: false, - fast_matchers: EXTENSIONS - .iter() - .map(|s| FastMatcher::FileExtension(s.to_string())) - .collect(), - slow_matchers: None - }; + static ref METADATA: AdapterMeta = AdapterMeta { + name: "tesseract".to_owned(), + version: 1, + description: "Uses tesseract to run OCR on images to make them searchable. May need -j1 to prevent overloading the system. Make sure you have tesseract installed.".to_owned(), + recurses: false, + fast_matchers: EXTENSIONS + .iter() + .map(|s| FastMatcher::FileExtension(s.to_string())) + .collect(), + slow_matchers: None + }; } #[derive(Default)] pub struct TesseractAdapter {} impl TesseractAdapter { - pub fn new() -> TesseractAdapter { - TesseractAdapter {} - } + pub fn new() -> TesseractAdapter { + TesseractAdapter {} + } } impl GetMetadata for TesseractAdapter { - fn metadata(&self) -> &AdapterMeta { - &METADATA - } + fn metadata(&self) -> &AdapterMeta { + &METADATA + } } impl SpawningFileAdapter for TesseractAdapter { - fn get_exe(&self) -> &str { - "tesseract" - } - fn command(&self, _filepath_hint: &Path, mut cmd: Command) -> Command { - // rg already does threading - cmd.env("OMP_THREAD_LIMIT", "1").arg("-").arg("-"); - cmd - } + fn get_exe(&self) -> &str { + "tesseract" + } + fn command(&self, _filepath_hint: &Path, mut cmd: Command) -> Command { + // rg already does threading + cmd.env("OMP_THREAD_LIMIT", "1").arg("-").arg("-"); + cmd + } } diff --git a/src/args.rs b/src/args.rs index fbbdbeb..1522317 100644 --- a/src/args.rs +++ b/src/args.rs @@ -30,8 +30,10 @@ set_default!(max_archive_recursion, 4, i32); #[derive(StructOpt, Debug, Deserialize, Serialize)] #[structopt( + name = "ripgrep-all", rename_all = "kebab-case", - author = "https://github.com/phiresky/ripgrep-all", + about = env!("CARGO_PKG_DESCRIPTION"), + author = env!("CARGO_PKG_HOMEPAGE"), // TODO: long_about does not seem to work to only show this on short help after_help = "-h shows a concise overview, --help shows more detail and advanced options.\n\nAll other options not shown here are passed directly to rg, especially [PATTERN] and [PATH ...]" )] @@ -42,7 +44,7 @@ pub struct RgaArgs { /// /// By default, rga caches the extracted text, if it is small enough, /// to a database in ~/Library/Caches/rga on macOS, - /// ~/.cache/rga on other Unixes, + /// ~/.cache/rga on other Unixes, /// or C:\Users\username\AppData\Local\rga` on Windows. /// This way, repeated searches on the same set of files will be much faster. /// If you pass this flag, all caching will be disabled. diff --git a/src/matching.rs b/src/matching.rs index ec475af..71a7d4b 100644 --- a/src/matching.rs +++ b/src/matching.rs @@ -13,115 +13,115 @@ use std::rc::Rc; #[derive(Clone)] pub enum FastMatcher { - // MimeType(Regex), - /** - * without the leading dot, e.g. "jpg" or "tar.gz". Matched as /.*\.ext$/ - * - */ - FileExtension(String), - // todo: maybe add others, e.g. regex on whole filename or even paths - // todo: maybe allow matching a directory (e.g. /var/lib/postgres) + // MimeType(Regex), + /** + * without the leading dot, e.g. "jpg" or "tar.gz". Matched as /.*\.ext$/ + * + */ + FileExtension(String), + // todo: maybe add others, e.g. regex on whole filename or even paths + // todo: maybe allow matching a directory (e.g. /var/lib/postgres) } #[derive(Clone)] pub enum SlowMatcher { - /// any type of fast matcher - Fast(FastMatcher), - /// - /// match by exact mime type extracted using tree_magic - /// TODO: allow match ignoring suffix etc? - MimeType(String), + /// any type of fast matcher + Fast(FastMatcher), + /// + /// match by exact mime type extracted using tree_magic + /// TODO: allow match ignoring suffix etc? + MimeType(String), } pub struct FileMeta { - // filename is not actually a utf8 string, but since we can't do regex on OsStr and can't get a &[u8] from OsStr either, - // and since we probably only want to do only matching on ascii stuff anyways, this is the filename as a string with non-valid bytes removed - pub lossy_filename: String, - // only given when slow matching is enabled - pub mimetype: Option, + // filename is not actually a utf8 string, but since we can't do regex on OsStr and can't get a &[u8] from OsStr either, + // and since we probably only want to do only matching on ascii stuff anyways, this is the filename as a string with non-valid bytes removed + pub lossy_filename: String, + // only given when slow matching is enabled + pub mimetype: Option, } pub fn extension_to_regex(extension: &str) -> Regex { - Regex::new(&format!("\\.{}$", ®ex::escape(extension))).expect("we know this regex compiles") + Regex::new(&format!("\\.{}$", ®ex::escape(extension))).expect("we know this regex compiles") } pub fn adapter_matcher>( - adapter_names: &[T], - slow: bool, + adapter_names: &[T], + slow: bool, ) -> Fallible Option<(Rc, SlowMatcher)>> { - let adapters = get_adapters_filtered(adapter_names)?; - // need order later - let adapter_names: Vec = adapters.iter().map(|e| e.metadata().name.clone()).collect(); - let mut fname_regexes = vec![]; - let mut mime_regexes = vec![]; - for adapter in adapters.into_iter() { - let metadata = adapter.metadata(); - use SlowMatcher::*; - for matcher in metadata.get_matchers(slow) { - match matcher.as_ref() { - MimeType(re) => { - mime_regexes.push((re.clone(), adapter.clone(), MimeType(re.clone()))) - } - Fast(FastMatcher::FileExtension(re)) => fname_regexes.push(( - extension_to_regex(re), - adapter.clone(), - Fast(FastMatcher::FileExtension(re.clone())), - )), - }; - } - } - let fname_regex_set = RegexSet::new(fname_regexes.iter().map(|p| p.0.as_str()))?; - let mime_regex_set = RegexSet::new(mime_regexes.iter().map(|p| p.0.as_str()))?; - Ok(move |meta: FileMeta| { - let fname_matches: Vec<_> = fname_regex_set - .matches(&meta.lossy_filename) - .into_iter() - .collect(); - let mime_matches: Vec<_> = if slow { - mime_regex_set - .matches(&meta.mimetype.expect("No mimetype?")) - .into_iter() - .collect() - } else { - vec![] - }; - if fname_matches.len() + mime_matches.len() > 1 { - // get first according to original priority list... - // todo: kinda ugly - let fa = fname_matches - .iter() - .map(|e| (fname_regexes[*e].1.clone(), fname_regexes[*e].2.clone())); - let fb = mime_matches - .iter() - .map(|e| (mime_regexes[*e].1.clone(), mime_regexes[*e].2.clone())); - let mut v = vec![]; - v.extend(fa); - v.extend(fb); - v.sort_by_key(|e| { - adapter_names - .iter() - .position(|r| r == &e.0.metadata().name) - .expect("impossib7") - }); - eprintln!( - "Warning: found multiple adapters for {}:", - meta.lossy_filename - ); - for mmatch in v.iter() { - eprintln!(" - {}", mmatch.0.metadata().name); - } - return Some(v[0].clone()); - } - if mime_matches.is_empty() { - if fname_matches.is_empty() { - None - } else { - let (_, adapter, matcher) = &fname_regexes[fname_matches[0]]; - Some((adapter.clone(), matcher.clone())) - } - } else { - let (_, adapter, matcher) = &mime_regexes[mime_matches[0]]; - Some((adapter.clone(), matcher.clone())) - } - }) + let adapters = get_adapters_filtered(adapter_names)?; + // need order later + let adapter_names: Vec = adapters.iter().map(|e| e.metadata().name.clone()).collect(); + let mut fname_regexes = vec![]; + let mut mime_regexes = vec![]; + for adapter in adapters.into_iter() { + let metadata = adapter.metadata(); + use SlowMatcher::*; + for matcher in metadata.get_matchers(slow) { + match matcher.as_ref() { + MimeType(re) => { + mime_regexes.push((re.clone(), adapter.clone(), MimeType(re.clone()))) + } + Fast(FastMatcher::FileExtension(re)) => fname_regexes.push(( + extension_to_regex(re), + adapter.clone(), + Fast(FastMatcher::FileExtension(re.clone())), + )), + }; + } + } + let fname_regex_set = RegexSet::new(fname_regexes.iter().map(|p| p.0.as_str()))?; + let mime_regex_set = RegexSet::new(mime_regexes.iter().map(|p| p.0.as_str()))?; + Ok(move |meta: FileMeta| { + let fname_matches: Vec<_> = fname_regex_set + .matches(&meta.lossy_filename) + .into_iter() + .collect(); + let mime_matches: Vec<_> = if slow { + mime_regex_set + .matches(&meta.mimetype.expect("No mimetype?")) + .into_iter() + .collect() + } else { + vec![] + }; + if fname_matches.len() + mime_matches.len() > 1 { + // get first according to original priority list... + // todo: kinda ugly + let fa = fname_matches + .iter() + .map(|e| (fname_regexes[*e].1.clone(), fname_regexes[*e].2.clone())); + let fb = mime_matches + .iter() + .map(|e| (mime_regexes[*e].1.clone(), mime_regexes[*e].2.clone())); + let mut v = vec![]; + v.extend(fa); + v.extend(fb); + v.sort_by_key(|e| { + adapter_names + .iter() + .position(|r| r == &e.0.metadata().name) + .expect("impossib7") + }); + eprintln!( + "Warning: found multiple adapters for {}:", + meta.lossy_filename + ); + for mmatch in v.iter() { + eprintln!(" - {}", mmatch.0.metadata().name); + } + return Some(v[0].clone()); + } + if mime_matches.is_empty() { + if fname_matches.is_empty() { + None + } else { + let (_, adapter, matcher) = &fname_regexes[fname_matches[0]]; + Some((adapter.clone(), matcher.clone())) + } + } else { + let (_, adapter, matcher) = &mime_regexes[mime_matches[0]]; + Some((adapter.clone(), matcher.clone())) + } + }) } diff --git a/src/preproc.rs b/src/preproc.rs index 0716159..495133e 100644 --- a/src/preproc.rs +++ b/src/preproc.rs @@ -79,14 +79,16 @@ pub fn rga_preproc(ai: AdaptInfo) -> Fallible<()> { &args.adapters[..], ); debug!("cache key: {:?}", key); - bincode::serialize(&key).expect("could not serialize path") // key in the cache database + bincode::serialize(&key).expect("could not serialize path") + // key in the cache database } else { let key = ( clean_path, meta.modified().expect("weird OS that can't into mtime"), ); debug!("cache key: {:?}", key); - bincode::serialize(&key).expect("could not serialize path") // key in the cache database + bincode::serialize(&key).expect("could not serialize path") + // key in the cache database } }; cache.write().unwrap().get_or_run(