Compare commits

..

No commits in common. "main" and "v0.1.0" have entirely different histories.
main ... v0.1.0

22 changed files with 30 additions and 1353 deletions

View File

@ -1,5 +0,0 @@
kind: template
load: bust_rustbin_default_template.yaml
name: toolkit
data:
binName: toolkit

View File

@ -1,89 +0,0 @@
name: release-published
on:
release:
types: [published]
jobs:
brew-releaser:
name: Homebrew releaser
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Release to homebrew tap
uses: Justintime50/homebrew-releaser@v1
with:
# The name of the homebrew tap to publish your formula to as it appears on GitHub.
# Required - strings.
homebrew_owner: kjuulh
homebrew_tap: homebrew-brew
# The name of the folder in your homebrew tap where formula will be committed to.
# Default is shown - string.
formula_folder: formula
# The GitHub Token (saved as a repo secret) that has `repo` permissions for the homebrew tap you want to release to.
# Required - string.
github_token: ${{ secrets.BREW_GITHUB_TOKEN }}
# Git author info used to commit to the homebrew tap.
# Defaults are shown - strings.
commit_owner: kjuulh
commit_email: homebrew-releaser@kjuulh.io
# Custom dependencies in case other formulas are needed to build the current one.
# Optional - multiline string.
depends_on: |
"fzf"
"gh"
"dust"
"bottom"
"procs"
"sourcegraph/src-cli/src-cli"
"tokei"
"bandwhich"
# Custom install command for your formula.
# Required - string.
install: 'bin.install "toolkit"'
# Custom test command for your formula so you can run `brew test`.
# Optional - string.
#test: 'assert_match("my script output", shell_output("my-script-command"))'
# Adds URL and checksum targets for different OS and architecture pairs. Using this option assumes
# a tar archive exists on your GitHub repo with the following URL pattern (this cannot be customized):
# https://github.com/{GITHUB_OWNER}/{REPO_NAME}/releases/download/{TAG}/{REPO_NAME}-{VERSION}-{OPERATING_SYSTEM}-{ARCHITECTURE}.tar.gz'
# Darwin AMD pre-existing path example: https://github.com/justintime50/myrepo/releases/download/v1.2.0/myrepo-1.2.0-darwin-amd64.tar.gz
# Linux ARM pre-existing path example: https://github.com/justintime50/myrepo/releases/download/v1.2.0/myrepo-1.2.0-linux-arm64.tar.gz
# Optional - booleans.
target_darwin_amd64: true
target_darwin_arm64: true
target_linux_amd64: true
target_linux_arm64: true
# Update your homebrew tap's README with a table of all projects in the tap.
# This is done by pulling the information from all your formula.rb files - eg:
#
# | Project | Description | Install |
# | ------------------------------------------ | ------------ | ------------------------ |
# | [formula_1](https://github.com/user/repo1) | helpful text | `brew install formula_1` |
# | [formula_2](https://github.com/user/repo2) | helpful text | `brew install formula_2` |
# | [formula_3](https://github.com/user/repo3) | helpful text | `brew install formula_3` |
#
# Simply place the following in your README or wrap your project in these comment tags:
# <!-- project_table_start -->
# TABLE HERE
# <!--project_table_end -->
#
# Finally, mark `update_readme_table` as `true` in your GitHub Action config and we'll do the work of building a custom table for you.
# Default is `false` - boolean.
update_readme_table: true
# Skips committing the generated formula to a homebrew tap (useful for local testing).
# Default is shown - boolean.
skip_commit: false
# Logs debugging info to console.
# Default is shown - boolean.
debug: true

View File

@ -1,114 +0,0 @@
name: release
on:
push:
branches:
- main
- next
pull_request:
workflow_dispatch:
env:
CARGO_INCREMENTAL: 0
jobs:
release:
name: ${{ matrix.target }}
permissions:
contents: write
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-musl
release-target: linux-amd64
deb: true
- os: ubuntu-latest
target: arm-unknown-linux-musleabihf
release-target: linux-arm
- os: ubuntu-latest
target: armv7-unknown-linux-musleabihf
release-target: linux-arm7
- os: ubuntu-latest
target: aarch64-unknown-linux-musl
release-target: linux-arm64
deb: true
- os: macos-11
target: x86_64-apple-darwin
release-target: darwin-amd64
- os: macos-11
target: aarch64-apple-darwin
release-target: darwin-arm64
steps:
- name: Checkout repository
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Get version
id: get_version
run: sed -En 's/^version = "(.*)"/value=\1/p' Cargo.toml >> $GITHUB_OUTPUT
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
profile: minimal
override: true
target: ${{ matrix.target }}
- name: Setup cache
uses: Swatinem/rust-cache@v2
with:
key: ${{ matrix.target }}
- name: Build binary
uses: actions-rs/cargo@v1
with:
command: build
args: --release --locked --target=${{ matrix.target }} --color=always --verbose
use-cross: ${{ runner.os == 'Linux' }}
- name: Install cargo-deb
if: ${{ matrix.deb == true }}
uses: actions-rs/install@v0.1
with:
crate: cargo-deb
- name: Build deb
if: ${{ matrix.deb == true }}
uses: actions-rs/cargo@v1
with:
command: deb
args: --no-build --no-strip --output=. --target=${{ matrix.target }}
- name: Package (*nix)
if: runner.os != 'Windows'
run: >
tar -cv
LICENSE README.md
man/
-C target/${{ matrix.target }}/release/ toolkit
| gzip --best
> 'toolkit-${{ steps.get_version.outputs.value }}-${{ matrix.release-target }}.tar.gz'
- name: Upload artifact
uses: actions/upload-artifact@v3
with:
name: ${{ matrix.release-target }}
path: |
*.deb
*.tar.gz
*.zip
- name: Create release
if: ${{ github.ref == 'refs/heads/main' && startsWith(github.event.head_commit.message, 'chore(release)') }}
uses: softprops/action-gh-release@v1
with:
draft: true
files: |
*.deb
*.tar.gz
*.zip
name: v${{ steps.get_version.outputs.value }}
tag_name: v${{ steps.get_version.outputs.value }}

463
Cargo.lock generated
View File

@ -2,27 +2,6 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "0.7.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
dependencies = [
"memchr",
]
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "base64"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
[[package]]
name = "bitflags"
version = "1.3.2"
@ -43,9 +22,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "4.0.32"
version = "4.0.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7db700bc935f9e43e88d00b0850dae18a63773cfbec6d8e070fccf7fef89a39"
checksum = "4d63b9e9c07271b9957ad22c173bae2a4d9a81127680962039296abcd2f8251d"
dependencies = [
"bitflags",
"clap_lex",
@ -64,65 +43,6 @@ dependencies = [
"os_str_bytes",
]
[[package]]
name = "comfy-table"
version = "6.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e7b787b0dc42e8111badfdbe4c3059158ccb2db8780352fa1b01e8ccf45cc4d"
dependencies = [
"crossterm",
"strum",
"strum_macros",
"unicode-width",
]
[[package]]
name = "crossterm"
version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67"
dependencies = [
"bitflags",
"crossterm_winapi",
"libc",
"mio",
"parking_lot",
"signal-hook",
"signal-hook-mio",
"winapi",
]
[[package]]
name = "crossterm_winapi"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ae1b35a484aa10e07fe0638d02301c5ad24de82d310ccbd2f3693da5f09bf1c"
dependencies = [
"winapi",
]
[[package]]
name = "ctor"
version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096"
dependencies = [
"quote",
"syn",
]
[[package]]
name = "diff"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
[[package]]
name = "difflib"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8"
[[package]]
name = "dirs"
version = "4.0.0"
@ -143,18 +63,6 @@ dependencies = [
"winapi",
]
[[package]]
name = "downcast"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1"
[[package]]
name = "either"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
[[package]]
name = "errno"
version = "0.2.8"
@ -186,21 +94,6 @@ dependencies = [
"once_cell",
]
[[package]]
name = "float-cmp"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4"
dependencies = [
"num-traits",
]
[[package]]
name = "fragile"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa"
[[package]]
name = "getrandom"
version = "0.2.8"
@ -216,25 +109,12 @@ dependencies = [
name = "github"
version = "0.1.0"
dependencies = [
"base64",
"clap",
"comfy-table",
"dirs",
"eyre",
"mockall",
"pretty_assertions",
"serde",
"serde_json",
"thiserror",
"util",
]
[[package]]
name = "heck"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
[[package]]
name = "hermit-abi"
version = "0.2.6"
@ -272,27 +152,6 @@ dependencies = [
"windows-sys",
]
[[package]]
name = "itertools"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.138"
@ -305,85 +164,6 @@ version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
[[package]]
name = "lock_api"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
dependencies = [
"autocfg",
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
]
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "mio"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de"
dependencies = [
"libc",
"log",
"wasi",
"windows-sys",
]
[[package]]
name = "mockall"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50e4a1c770583dac7ab5e2f6c139153b783a53a1bbee9729613f193e59828326"
dependencies = [
"cfg-if",
"downcast",
"fragile",
"lazy_static",
"mockall_derive",
"predicates",
"predicates-tree",
]
[[package]]
name = "mockall_derive"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "832663583d5fa284ca8810bf7015e46c9fff9622d3cf34bd1eea5003fec06dd0"
dependencies = [
"cfg-if",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "normalize-line-endings"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be"
[[package]]
name = "num-traits"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
dependencies = [
"autocfg",
]
[[package]]
name = "once_cell"
version = "1.16.0"
@ -396,94 +176,20 @@ version = "6.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
[[package]]
name = "output_vt100"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66"
dependencies = [
"winapi",
]
[[package]]
name = "parking_lot"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
dependencies = [
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
"windows-sys",
]
[[package]]
name = "predicates"
version = "2.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59230a63c37f3e18569bdb90e4a89cbf5bf8b06fea0b84e65ea10cc4df47addd"
dependencies = [
"difflib",
"float-cmp",
"itertools",
"normalize-line-endings",
"predicates-core",
"regex",
]
[[package]]
name = "predicates-core"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72f883590242d3c6fc5bf50299011695fa6590c2c70eac95ee1bdb9a733ad1a2"
[[package]]
name = "predicates-tree"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54ff541861505aabf6ea722d2131ee980b8276e10a1297b94e896dd8b621850d"
dependencies = [
"predicates-core",
"termtree",
]
[[package]]
name = "pretty_assertions"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a25e9bcb20aa780fd0bb16b72403a9064d6b3f22f026946029acb941a50af755"
dependencies = [
"ctor",
"diff",
"output_vt100",
"yansi",
]
[[package]]
name = "proc-macro2"
version = "1.0.49"
version = "1.0.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5"
checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.23"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
dependencies = [
"proc-macro2",
]
@ -508,23 +214,6 @@ dependencies = [
"thiserror",
]
[[package]]
name = "regex"
version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
[[package]]
name = "rustix"
version = "0.36.5"
@ -539,18 +228,6 @@ dependencies = [
"windows-sys",
]
[[package]]
name = "rustversion"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70"
[[package]]
name = "ryu"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
[[package]]
name = "same-file"
version = "1.0.6"
@ -560,79 +237,6 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "serde"
version = "1.0.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "signal-hook"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a253b5e89e2698464fc26b545c9edceb338e18a89effeeecfea192c3025be29d"
dependencies = [
"libc",
"signal-hook-registry",
]
[[package]]
name = "signal-hook-mio"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af"
dependencies = [
"libc",
"mio",
"signal-hook",
]
[[package]]
name = "signal-hook-registry"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0"
dependencies = [
"libc",
]
[[package]]
name = "smallvec"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
[[package]]
name = "sourcegraph"
version = "0.1.0"
@ -659,30 +263,11 @@ version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "strum"
version = "0.24.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f"
[[package]]
name = "strum_macros"
version = "0.24.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59"
dependencies = [
"heck",
"proc-macro2",
"quote",
"rustversion",
"syn",
]
[[package]]
name = "syn"
version = "1.0.107"
version = "1.0.105"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908"
dependencies = [
"proc-macro2",
"quote",
@ -698,26 +283,20 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "termtree"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95059e91184749cb66be6dc994f67f182b6d897cb3df74a5bf66b5e709295fd8"
[[package]]
name = "thiserror"
version = "1.0.38"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.38"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb"
dependencies = [
"proc-macro2",
"quote",
@ -737,7 +316,7 @@ dependencies = [
[[package]]
name = "toolkit"
version = "0.1.14"
version = "0.1.0"
dependencies = [
"clap",
"eyre",
@ -750,15 +329,9 @@ dependencies = [
[[package]]
name = "unicode-ident"
version = "1.0.6"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
[[package]]
name = "unicode-width"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
[[package]]
name = "util"
@ -872,9 +445,3 @@ name = "windows_x86_64_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
[[package]]
name = "yansi"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"

View File

@ -1,11 +1,7 @@
[package]
name = "toolkit"
description = "Toolkit is an opinionated toolkit complementing a personal development workflow. Many of the commands are quite verbose, and well suited for adding to your shell toolbelt"
version = "0.1.14"
version = "0.1.0"
edition = "2021"
license-file = "LICENSE"
authors = ["Kasper J. Hermansen contact@kjuulh.io"]
readme = "README.md"
[workspace]
members = [
@ -17,7 +13,7 @@ members = [
]
[workspace.dependencies]
clap = { version = "4.0.32", features = ["cargo"] }
clap = { version = "4.0.29", features = ["cargo"] }
eyre = "0.6.8"
dirs = "4.0.0"
walkdir = "2.3.2"

View File

View File

@ -1,61 +0,0 @@
# Toolkit
This is an opinionated toolkit, which reflect my (@kjuulh) way of working. This
project aims to enhance a general workflow, and provides tools that may be
useful outside of project work. For project work see repo:kjuulh/bust or
repo:kjuulh/char, which aims for the same thing, but for projects themselves.
## Install
Currenly I only publish homebrew packages, however, all artifacts are released
via. released, that includes deb packages as well.
### Homebrew
```
brew install kjuulh/brew/toolkit
```
## Configuration
To use toolkit you will need a series of environment variables, they are only
needed if you need the associated tool.
```
export SRC_ENDPOINT=https://sourcegraph.com
export SRC_ACCESS_TOKEN=
export GITHUB_FC_ROOT="/Users/<username>/git/github.com"
export GITHUB_FC_ORGS="kjuulh"
```
`SRC` is sourcegraph integration. The endpoint is either to the public instance,
or your own domain. The access token is a personal access token. If either of
these are missing. A prompt will be shown on the first run
`GITHUB_FC` is the fuzzy clone setup. First is the destination path, this is
where the orgs will be placed. Second is ORGS, that is which orgs to subscribe
to. The total path in this case will end up being
`/Users/<username>/git/github.com/kjuulh`.
You will also require other integration such as a GitHub integration through
`gh`.
## Usage
```
Usage: toolkit <COMMAND>
Commands:
prereqs
tldr
sourcegraph
github
stats
init
help Print this message or the help of the given subcommand(s)
Options:
-h, --help Print help information
```
![demo](assets/demo.gif)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 MiB

View File

@ -11,13 +11,3 @@ util = { path = "../util" }
eyre.workspace = true
clap.workspace = true
dirs.workspace = true
serde = { version = "1.0.152", features = ["derive"] }
serde_json = "1.0.91"
comfy-table = "6.1.4"
pretty_assertions = "1.3.0"
base64 = "0.21.0"
thiserror = "1.0.38"
[dev-dependencies]
mockall = "0.11.2"

View File

@ -1,6 +1,5 @@
use std::io::Write;
use clap::value_parser;
use eyre::Context;
pub struct FuzzyClone;
@ -202,18 +201,13 @@ impl FuzzyClone {
}),
)?;
} else {
let _ = util::shell::run(
&["git", "pull"],
Some(util::shell::RunOptions {
path: git_repo_path.clone(),
}),
);
util::shell::run(&["git", "pull"], None)?;
}
Ok(git_repo_path)
}
fn run(print_dest: &bool) -> eyre::Result<()> {
fn run() -> eyre::Result<()> {
let settings = Self::get_settings()?;
if settings.auto_update {
println!("running auto update");
@ -240,17 +234,10 @@ impl FuzzyClone {
let chosen = util::shell::run_with_input_and_output(&["fzf"], entries_str)?;
let chosen = std::str::from_utf8(&chosen.stdout)?;
let path = Self::clone(GitHubEntry::from(chosen.to_string()).ok_or(eyre::anyhow!(
Self::clone(GitHubEntry::from(chosen.to_string()).ok_or(eyre::anyhow!(
"could not parse choice as github entry <org>/<repo>"
))?)?;
if *print_dest {
print!(
"{}",
path.to_str().ok_or(eyre::anyhow!("path was not found"))?
);
}
Ok(())
}
@ -268,24 +255,13 @@ impl util::Cmd for FuzzyClone {
Ok(clap::Command::new("fuzzy-clone")
.alias("fc")
.alias("c")
.arg(
clap::Arg::new("print-dest")
.long("print-dest")
.value_name("print-dest")
.value_parser(value_parser!(bool))
.num_args(0..=1)
.require_equals(true)
.default_missing_value("true"),
)
.subcommand(clap::Command::new("update")))
}
fn exec(args: &clap::ArgMatches) -> eyre::Result<()> {
let print_dest = args.get_one::<bool>("print-dest").unwrap_or(&false);
match args.subcommand() {
Some(("update", _)) => Self::update()?,
_ => Self::run(print_dest)?,
_ => Self::run()?,
}
Ok(())

View File

@ -1,8 +1,6 @@
mod auth;
mod fuzzy_clone;
mod gh;
mod review;
pub(crate) mod review_backend;
pub struct GitHub;
@ -33,7 +31,6 @@ impl util::Cmd for GitHub {
auth::Auth::cmd()?,
gh::Gh::cmd()?,
fuzzy_clone::FuzzyClone::cmd()?,
review::Review::cmd()?,
])
.allow_external_subcommands(true))
}
@ -44,7 +41,6 @@ impl util::Cmd for GitHub {
Some(("fuzzy-clone", subm)) => fuzzy_clone::FuzzyClone::exec(subm),
Some(("fc", subm)) => fuzzy_clone::FuzzyClone::exec(subm),
Some(("gh", subm)) => gh::Gh::exec(subm),
Some(("review", subm)) => review::Review::exec(subm),
Some((external, args)) => Self::run(external, args),
_ => Err(eyre::anyhow!("missing argument")),
}

View File

@ -1,298 +0,0 @@
use crate::review_backend::{
models::{MenuChoice, MergeStrategy, PullRequest, ReviewMenuChoice},
DefaultReviewBackend, DynReviewBackend,
};
use comfy_table::{presets::UTF8_HORIZONTAL_ONLY, Cell, Table};
use thiserror::Error;
pub struct Review {
backend: DynReviewBackend,
}
impl Default for Review {
fn default() -> Self {
Self::new(std::sync::Arc::new(DefaultReviewBackend::new()))
}
}
#[derive(Debug, Error)]
pub enum ReviewErrors {
#[error("user chose to exit")]
UserExit,
}
impl Review {
fn new(backend: DynReviewBackend) -> Self {
Self { backend }
}
/// Workflow
/// 1. Fetch list of repos
/// 2. Present menu
/// 3. Choose begin quick review
/// 4. Present pr and use delta to view changes
/// 5. Approve, open, skip or quit
/// 6. Repeat from 4
fn run(
&self,
review_requested: Option<String>,
merge_strategy: &Option<MergeStrategy>,
) -> eyre::Result<()> {
let prs = self.backend.get_prs(review_requested.clone())?;
let prs_table = Self::generate_prs_table(&prs);
self.backend.present_prs(prs_table)?;
match self.backend.present_menu()? {
MenuChoice::Exit => eyre::bail!(ReviewErrors::UserExit),
MenuChoice::Begin => match self.review(&prs, &merge_strategy)? {
Some(choice) => match choice {
MenuChoice::Exit => eyre::bail!(ReviewErrors::UserExit),
MenuChoice::List => return self.run(review_requested.clone(), merge_strategy),
_ => eyre::bail!("invalid choice"),
},
None => {}
},
MenuChoice::Search => todo!(),
MenuChoice::List => return self.run(review_requested.clone(), merge_strategy),
}
Ok(())
}
fn generate_prs_table(prs: &[PullRequest]) -> String {
let mut table = Table::new();
let table = table
.load_preset(UTF8_HORIZONTAL_ONLY)
.set_content_arrangement(comfy_table::ContentArrangement::Dynamic)
.set_header(vec![
Cell::new("repo").add_attribute(comfy_table::Attribute::Bold),
Cell::new("title").add_attribute(comfy_table::Attribute::Bold),
Cell::new("number").add_attribute(comfy_table::Attribute::Bold),
])
.add_rows(prs.iter().take(20).map(|pr| {
let pr = pr.clone();
vec![
Cell::new(pr.repository.name).fg(comfy_table::Color::Green),
Cell::new(pr.title),
Cell::new(pr.number.to_string()),
]
}));
table.to_string()
}
fn review(
&self,
prs: &Vec<PullRequest>,
merge_strategy: &Option<MergeStrategy>,
) -> eyre::Result<Option<MenuChoice>> {
for pr in prs {
self.backend.clear()?;
self.backend.present_pr(pr)?;
self.review_pr(pr)?;
if let Some(choice) = self.present_pr_menu(pr, merge_strategy)? {
return Ok(Some(choice));
}
}
Ok(None)
}
fn review_pr(&self, pr: &PullRequest) -> eyre::Result<()> {
self.backend.present_diff(pr)?;
Ok(())
}
fn approve(&self, pr: &PullRequest) -> eyre::Result<()> {
self.backend.approve(pr)?;
Ok(())
}
fn open_browser(
&self,
pr: &PullRequest,
merge_strategy: &Option<MergeStrategy>,
) -> eyre::Result<Option<MenuChoice>> {
self.backend.pr_open_browser(pr)?;
self.present_pr_menu(pr, merge_strategy)
}
fn present_pr_menu(
&self,
pr: &PullRequest,
merge_strategy: &Option<MergeStrategy>,
) -> eyre::Result<Option<MenuChoice>> {
self.backend.present_pr(pr)?;
match self.backend.present_review_menu(pr)? {
ReviewMenuChoice::Exit => return Ok(Some(MenuChoice::Exit)),
ReviewMenuChoice::List => return Ok(Some(MenuChoice::List)),
ReviewMenuChoice::Approve => {
self.approve(pr)?;
return self.present_pr_menu(pr, merge_strategy);
}
ReviewMenuChoice::Open => return self.open_browser(pr, merge_strategy),
ReviewMenuChoice::Skip => {}
ReviewMenuChoice::Merge => self.merge(pr, merge_strategy)?,
ReviewMenuChoice::ApproveAndMerge => {
self.approve(pr)?;
self.merge(pr, merge_strategy)?;
}
}
Ok(None)
}
fn merge(&self, pr: &PullRequest, merge_strategy: &Option<MergeStrategy>) -> eyre::Result<()> {
self.backend.enable_auto_merge(pr, merge_strategy)?;
Ok(())
}
}
impl util::Cmd for Review {
fn cmd() -> eyre::Result<clap::Command> {
Ok(clap::Command::new("review")
.arg(
clap::Arg::new("review-requested")
.long("review-requested")
.default_value("@me")
.help("which user or team to pull reviews from"),
)
.arg(
clap::Arg::new("merge-strategy")
.long("merge-strategy")
.help(
"when merging which merge strategy to use, possible values: [squash, merge]",
),
))
}
fn exec(args: &clap::ArgMatches) -> eyre::Result<()> {
let request_requested = args
.get_one::<String>("review-requested")
.map(|r| r.clone());
let squash = args
.get_one::<String>("merge-strategy")
.and_then(|s| match s.as_str() {
"squash" => Some(MergeStrategy::Squash),
"merge" => Some(MergeStrategy::MergeCommit),
_ => None,
});
Self::default().run(request_requested, &squash)
}
}
#[cfg(test)]
mod tests {
use crate::review_backend::{
models::{self, Repository},
MockReviewBackend,
};
use super::*;
use base64::Engine;
use mockall::predicate::eq;
use pretty_assertions::assert_eq;
#[test]
fn can_fetch_prs() {
let mut backend = MockReviewBackend::new();
let prs = vec![
PullRequest {
title: "some-title".into(),
number: 0,
repository: Repository {
name: "some-name".into(),
},
},
PullRequest {
title: "some-other-title".into(),
number: 1,
repository: Repository {
name: "some-other-name".into(),
},
},
];
let backendprs = prs.clone();
backend
.expect_get_prs()
.with(eq(Some("kjuulh".into())))
.times(1)
.returning(move |_| Ok(backendprs.clone()));
backend
.expect_present_menu()
.times(1)
.returning(|| Ok(models::MenuChoice::Exit));
backend.expect_present_prs().times(1).returning(|_| Ok(()));
let review = Review::new(std::sync::Arc::new(backend));
let res = review.run(None, &None);
assert_err::<ReviewErrors, _>(res)
}
#[test]
fn can_generate_table() {
let prs = vec![
PullRequest {
title: "some-title".into(),
number: 0,
repository: Repository {
name: "some-name".into(),
},
},
PullRequest {
title: "some-other-title".into(),
number: 1,
repository: Repository {
name: "some-other-name".into(),
},
},
];
let expected_table = "4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAChtbMW0gcmVwbyAgICAgICAgICAgIBtbMG0gG1sxbSB0aXRsZSAgICAgICAgICAgIBtbMG0gG1sxbSBudW1iZXIgG1swbQrilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZAKG1szODs1OzEwbSBzb21lLW5hbWUgICAgICAgG1szOW0gIHNvbWUtdGl0bGUgICAgICAgICAwICAgICAgCuKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgAobWzM4OzU7MTBtIHNvbWUtb3RoZXItbmFtZSAbWzM5bSAgc29tZS1vdGhlci10aXRsZSAgIDEgICAgICAK4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA";
let output = Review::generate_prs_table(&prs);
compare_tables(output, expected_table)
}
fn compare_tables(actual: String, snapshot: &str) {
let b64 = base64::engine::general_purpose::STANDARD_NO_PAD;
let snapshot = snapshot.clone().replace("\n", "").replace(" ", "");
println!("expected");
println!(
"{}",
std::str::from_utf8(
b64.decode(&snapshot)
.expect("table to be decodeable")
.as_slice()
)
.expect("to be utf8")
);
println!("actual");
println!("{actual}");
assert_eq!(b64.encode(actual), snapshot);
}
fn assert_err<TExpected, TVal>(res: eyre::Result<TVal>) {
match res {
Err(e) => {
if !e.is::<ReviewErrors>() {
panic!("invalid error: {}", e)
}
}
_ => panic!("error not thrown"),
}
}
}

View File

@ -1,207 +0,0 @@
pub mod models;
use std::io::Write;
use self::models::{MenuChoice, MergeStrategy, PullRequest, ReviewMenuChoice};
#[cfg(test)]
use mockall::{automock, predicate::*};
#[cfg_attr(test, automock)]
pub trait ReviewBackend {
fn get_prs(&self, review_request: Option<String>) -> eyre::Result<Vec<PullRequest>>;
fn present_prs(&self, table: String) -> eyre::Result<()>;
fn present_menu(&self) -> eyre::Result<MenuChoice>;
fn present_diff(&self, pr: &PullRequest) -> eyre::Result<()>;
fn present_review_menu(&self, pr: &PullRequest) -> eyre::Result<ReviewMenuChoice>;
fn approve(&self, pr: &PullRequest) -> eyre::Result<()>;
fn pr_open_browser(&self, pr: &PullRequest) -> eyre::Result<()>;
fn clear(&self) -> eyre::Result<()>;
fn enable_auto_merge(
&self,
pr: &PullRequest,
merge_strategy: &Option<MergeStrategy>,
) -> eyre::Result<()>;
fn present_pr(&self, pr: &PullRequest) -> eyre::Result<()>;
}
pub type DynReviewBackend = std::sync::Arc<dyn ReviewBackend + Send + Sync>;
#[derive(Default)]
pub struct DefaultReviewBackend;
impl ReviewBackend for DefaultReviewBackend {
fn get_prs(&self, review_request: Option<String>) -> eyre::Result<Vec<PullRequest>> {
let raw_prs = util::shell::run_with_input_and_output(
&[
"gh",
"search",
"prs",
"--state=open",
"--review-requested",
review_request.unwrap_or("@me".into()).as_str(),
"--label",
"dependencies",
"--json",
"repository,number,title",
],
"".into(),
)?;
let prs_json = std::str::from_utf8(raw_prs.stdout.as_slice())?;
let prs: Vec<PullRequest> = serde_json::from_str(prs_json)?;
Ok(prs)
}
fn present_prs(&self, table: String) -> eyre::Result<()> {
println!("{table}");
Ok(())
}
fn present_menu(&self) -> eyre::Result<MenuChoice> {
println!("Menu");
println!("Begin (b), Exit (q), Menu (m), Search (s), List (l)");
print!("> ");
std::io::stdout().flush()?;
let mut raw_choice = String::new();
std::io::stdin().read_line(&mut raw_choice)?;
let choice = match raw_choice.chars().take(1).next() {
None => models::MenuChoice::Exit,
Some(raw_choice) => match raw_choice {
'b' => models::MenuChoice::Begin,
'q' => models::MenuChoice::Exit,
'm' => self.present_menu()?,
's' => models::MenuChoice::Search,
'l' => models::MenuChoice::List,
_ => self.present_menu()?,
},
};
Ok(choice)
}
fn present_diff(&self, pr: &PullRequest) -> eyre::Result<()> {
util::shell::run(
&[
"gh",
"pr",
"diff",
pr.number.to_string().as_str(),
"--repo",
pr.repository.name.as_str(),
],
None,
)?;
Ok(())
}
fn present_review_menu(&self, pr: &PullRequest) -> eyre::Result<ReviewMenuChoice> {
println!("");
println!("Review - Menu");
println!("Approve (a), Merge (m), Approve and auto-merge (c), Skip (s), List (l), Open in browser (o), Exit (q)");
print!("> ");
std::io::stdout().flush()?;
let mut raw_choice = String::new();
std::io::stdin().read_line(&mut raw_choice)?;
let choice = match raw_choice.chars().take(1).next() {
None => ReviewMenuChoice::Exit,
Some(raw_choice) => match raw_choice {
'q' => ReviewMenuChoice::Exit,
'l' => ReviewMenuChoice::List,
'a' => ReviewMenuChoice::Approve,
'o' => ReviewMenuChoice::Open,
's' | 'n' => ReviewMenuChoice::Skip,
'm' => ReviewMenuChoice::Merge,
'c' => ReviewMenuChoice::ApproveAndMerge,
_ => self.present_review_menu(pr)?,
},
};
Ok(choice)
}
fn approve(&self, pr: &PullRequest) -> eyre::Result<()> {
util::shell::run(
&[
"gh",
"pr",
"review",
pr.number.to_string().as_str(),
"--approve",
"--repo",
pr.repository.name.as_str(),
],
None,
)?;
Ok(())
}
fn pr_open_browser(&self, pr: &PullRequest) -> eyre::Result<()> {
util::shell::run(
&[
"gh",
"pr",
"view",
pr.number.to_string().as_str(),
"-w",
"--repo",
pr.repository.name.as_str(),
],
None,
)?;
Ok(())
}
fn clear(&self) -> eyre::Result<()> {
print!("{esc}[2J{esc}[1;1H", esc = 27 as char);
std::io::stdout().flush()?;
Ok(())
}
fn enable_auto_merge(
&self,
pr: &PullRequest,
merge_strategy: &Option<MergeStrategy>,
) -> eyre::Result<()> {
let number = pr.number.to_string();
let mut args = vec![
"gh",
"pr",
"merge",
number.as_str(),
"--auto",
"--repo",
pr.repository.name.as_str(),
];
if let Some(merge_strategy) = merge_strategy {
match merge_strategy {
MergeStrategy::Squash => args.push("--squash"),
MergeStrategy::MergeCommit => args.push("--merge"),
}
}
util::shell::run(args.as_slice(), None)?;
Ok(())
}
fn present_pr(&self, pr: &PullRequest) -> eyre::Result<()> {
println!("repo: {} - title: {}", pr.repository.name, pr.title);
Ok(())
}
}
impl DefaultReviewBackend {
pub fn new() -> Self {
Self {}
}
}

View File

@ -1,37 +0,0 @@
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
pub struct Repository {
#[serde(rename(deserialize = "nameWithOwner"))]
pub name: String,
}
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
pub struct PullRequest {
pub title: String,
pub number: usize,
pub repository: Repository,
}
#[derive(Debug, Clone)]
pub enum MergeStrategy {
Squash,
MergeCommit,
}
pub enum MenuChoice {
Exit,
Begin,
Search,
List,
}
pub enum ReviewMenuChoice {
Exit,
List,
Approve,
Open,
Skip,
Merge,
ApproveAndMerge,
}

View File

@ -1,3 +1,5 @@
use std::{borrow::Borrow, ffi::OsString};
pub struct Search;
impl util::Cmd for Search {
@ -10,8 +12,8 @@ impl util::Cmd for Search {
fn exec(args: &clap::ArgMatches) -> eyre::Result<()> {
match args.subcommand() {
Some((external, args)) => {
let raw = args
.get_many::<std::ffi::OsString>("")
let mut raw = args
.get_many::<OsString>("")
.ok_or(eyre::anyhow!("please pass some args to search"))?
.map(|s| s.as_os_str())
.map(|s| s.to_string_lossy().to_string())

View File

@ -2,13 +2,13 @@ pub struct Perf;
impl Perf {
fn run() -> eyre::Result<()> {
if let Err(_) = util::shell::run_with_input_and_output(&["btm", "--version"], "".into()) {
if let Err(_) = util::shell::run_with_input_and_output(&["ytop", "--version"], "".into()) {
return Err(eyre::anyhow!(
"could not find btm, please install or add to PATH"
"could not find ytop, please install or add to PATH"
));
}
util::shell::run(&["btm"], None)?;
util::shell::run(&["ytop"], None)?;
Ok(())
}

View File

@ -8,7 +8,7 @@ impl Procs {
));
}
util::shell::run_with_input(&["procs"], "".into())?;
util::shell::run(&["procs"], None)?;
Ok(())
}

View File

@ -12,9 +12,7 @@ impl util::Cmd for Update {
let mut tldr_cache_dir = cache_dir.clone();
tldr_cache_dir.push("kah-toolkit/tldr/store/");
if let Err(_) = std::fs::remove_dir_all(&tldr_cache_dir) {
// ignored
}
std::fs::remove_dir_all(&tldr_cache_dir)?;
std::fs::create_dir_all(&tldr_cache_dir)?;
util::shell::run(

View File

View File

@ -1,13 +0,0 @@
pub struct Fish;
impl util::Cmd for Fish {
fn cmd() -> eyre::Result<clap::Command> {
let cmd = clap::Command::new("fish").subcommands(&[]);
Ok(cmd)
}
fn exec(args: &clap::ArgMatches) -> eyre::Result<()> {
Ok(())
}
}

View File

@ -1,20 +0,0 @@
mod fish;
pub struct Init;
impl util::Cmd for Init {
fn cmd() -> eyre::Result<clap::Command> {
let cmd = clap::Command::new("init")
.subcommands(&[fish::Fish::cmd()?])
.subcommand_required(true);
Ok(cmd)
}
fn exec(args: &clap::ArgMatches) -> eyre::Result<()> {
match args.subcommand() {
Some(("fish", args)) => fish::Fish::exec(args),
_ => Err(eyre::anyhow!("missing command!")),
}
}
}

View File

@ -1,6 +1,5 @@
use util::Cmd;
mod init;
mod prereqs;
fn main() -> eyre::Result<()> {
@ -11,9 +10,7 @@ fn main() -> eyre::Result<()> {
sourcegraph::Sourcegraph::cmd()?,
github::GitHub::cmd()?,
stats::Stats::cmd()?,
init::Init::cmd()?,
])
.subcommand_required(true)
.get_matches();
match matches.subcommand() {
@ -22,7 +19,6 @@ fn main() -> eyre::Result<()> {
Some(("sourcegraph", subcmd)) => sourcegraph::Sourcegraph::exec(subcmd),
Some(("github", subcmd)) => github::GitHub::exec(subcmd),
Some(("stats", subcmd)) => stats::Stats::exec(subcmd),
Some(("init", subcmd)) => init::Init::exec(subcmd),
_ => Err(eyre::anyhow!("no command selected!")),
}
}