tool-sync 0.2.0

tool-sync is a CLI tool that manages installation of other CLI tools from GitHub Releases by downloading binaries and storing them in a local directory.
Documentation
name: CI

on:
  pull_request:
    types: [synchronize, opened, reopened]
  push:
    branches: [main]
  schedule:
    # additionally run once per week (At 00:00 on Sunday) to maintain cache
    - cron: '0 0 * * 0'

env:
  CARGO_TERM_COLOR: always

jobs:
  build:
    name: ${{ matrix.os }}
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]

    steps:
    - uses: actions/checkout@v3

    - uses: actions/cache@v3
      name: Cache cargo
      with:
        path: |
          ~/.cargo/bin/
          ~/.cargo/registry/index/
          ~/.cargo/registry/cache/
          ~/.cargo/git/db/
          target
        key: ${{ runner.os }}-${{ hashFiles('Cargo.lock') }}

    - name: Build
      run: cargo build --verbose

    - name: Unit tests
      run: cargo test --verbose

    - if: matrix.os != 'windows-latest'
      name: "Integration test: [unix] [install ripgrep]"
      env:
          SYNC_DIR: "install-ripgrep"
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      run: |
          mkdir $SYNC_DIR
          cargo run -- --config=tests/$SYNC_DIR.toml install ripgrep

          ls -l $SYNC_DIR

          if [[ ! -x $SYNC_DIR/rg ]]; then echo "error on: rg"; false; fi

    - if: matrix.os != 'windows-latest'
      name: "Integration test: [unix] [sync-ripgrep]"
      env:
          SYNC_DIR: "sync-ripgrep"
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      run: |
          mkdir $SYNC_DIR
          cargo run -- --config=tests/$SYNC_DIR.toml sync

          ls -l $SYNC_DIR

          if [[ ! -x $SYNC_DIR/rg ]]; then echo "error on: rg"; false; fi

    - if: matrix.os == 'windows-latest'
      name: "Integration test: [windows] [sync-ripgrep]"
      env:
          SYNC_DIR: "sync-ripgrep"
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      run: |
          mkdir $env:SYNC_DIR
          cargo run -- --config="tests\$env:SYNC_DIR.toml" sync

          ls -l $env:SYNC_DIR

          if (!(Test-Path $env:SYNC_DIR\rg.exe)) {
              throw 'error on rg.exe'
          }

    - if: matrix.os != 'windows-latest'
      name: "Integration test: [unix] [sync-full]"
      env:
          SYNC_DIR: "sync-full"
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      run: |
          mkdir $SYNC_DIR
          cargo run -- --config=tests/$SYNC_DIR.toml sync

          ls -l $SYNC_DIR

          if [[ ! -x $SYNC_DIR/bat   ]]; then echo "error on: bat";   false; fi
          if [[ ! -x $SYNC_DIR/difft ]]; then echo "error on: difft"; false; fi
          if [[ ! -x $SYNC_DIR/exa   ]]; then echo "error on: exa";   false; fi
          if [[ ! -x $SYNC_DIR/fd    ]]; then echo "error on: fd";    false; fi
          if [[ ! -x $SYNC_DIR/rg    ]]; then echo "error on: rg";    false; fi
          if [[ ! -x $SYNC_DIR/tool  ]]; then echo "error on: tool";  false; fi
          if [[ ! -x $SYNC_DIR/gh  ]]; then echo "error on: gh";  false; fi

          # disabled because of: https://github.com/alexcrichton/tar-rs/issues/295
          # if [[ ! -x $SYNC_DIR/tokei ]]; then echo "error on: tokei"; false; fi

    - if: matrix.os != 'windows-latest'
      name: "Characterization test: [unix] [default-config]"
      env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      run: |
          cargo run -- default-config > tools.toml

          diff tools.toml tests/default-config.toml

          if [[ $? == 1 ]]; then diff tools.toml tests/default-config.toml; false; fi

    - if: matrix.os == 'windows-latest'
      name: "Integration test: [windows] [full-database]"
      env:
          SYNC_DIR: "sync-full"
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      run: |
          mkdir $env:SYNC_DIR
          cargo run -- --config="tests\$env:SYNC_DIR.toml" sync

          ls -l $env:SYNC_DIR

          if (!(Test-Path $env:SYNC_DIR\bat.exe)) {
              throw 'error on bat.exe'
          }
          if (!(Test-Path $env:SYNC_DIR\difft.exe)) {
              throw 'error on difft.exe'
          }
          if (!(Test-Path $env:SYNC_DIR\fd.exe)) {
              throw 'error on fd.exe'
          }
          if (!(Test-Path $env:SYNC_DIR\rg.exe)) {
              throw 'error on rg.exe'
          }
          if (!(Test-Path $env:SYNC_DIR\tool.exe)) {
              throw 'error on tool.exe'
          }
          if (!(Test-Path $env:SYNC_DIR\gh.exe)) {
              throw 'error on gh.exe'
          }

  rustfmt:
    name: rustfmt
    runs-on: ubuntu-latest
    steps:
    - name: Checkout repository
      uses: actions/checkout@v3

    - name: Install Rust
      uses: actions-rs/toolchain@v1
      with:
          toolchain: stable
          components: rustfmt
          override: true

    - name: Check formatting
      run: |
        cargo fmt --all -- --check

  clippy_check:
    name: clippy
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - run: rustup component add clippy
      - uses: actions-rs/clippy-check@v1
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          args: --all-features