47 Commits

Author SHA1 Message Date
6196f89342 with @me
Some checks failed
continuous-integration/drone/push Build is failing
2023-01-11 22:44:36 +01:00
ab464fbb6b with actual review functionality 2023-01-11 22:44:36 +01:00
e4e33ebda2 fixed tests 2023-01-11 22:44:36 +01:00
ffc0659a84 limit table to 20 items 2023-01-11 22:44:36 +01:00
b7a865b48e colored table 2023-01-11 22:44:36 +01:00
35b50d802a Merge pull request 'Added display review' (#4) from feature/review into main
Some checks failed
continuous-integration/drone/push Build is failing
Reviewed-on: https://git.front.kjuulh.io/kjuulh/toolkit/pulls/4
2023-01-11 21:40:35 +00:00
06b673286a Added display review
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is failing
2023-01-10 22:27:12 +01:00
0cfd38e682 chore(release) git pull should not cause error if no upstream
Some checks failed
continuous-integration/drone/push Build is failing
2023-01-10 20:21:11 +01:00
a1f337dac2 Update all dependencies
Some checks failed
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is failing
2022-12-22 19:46:31 +00:00
64897d32e4 chore(release) fix errors 2022-12-19 10:11:05 +01:00
0408fe856d chore(release) with updated formula for sourcegraph tap 2022-12-19 09:20:58 +01:00
4e3b711567 chore(release) with dependencies v0.1.7
All checks were successful
continuous-integration/drone/push Build is passing
2022-12-18 23:18:42 +01:00
7f0bff57eb forgot string
All checks were successful
continuous-integration/drone/push Build is passing
2022-12-18 23:18:05 +01:00
92f167e7e8 fix name of drone
All checks were successful
continuous-integration/drone/push Build is passing
2022-12-18 23:14:11 +01:00
c7ebd6350e chore(release) v0.1.6
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/tag Build is failing
2022-12-18 23:10:29 +01:00
d7d55d24f5 with proper name for version
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone Build is failing
2022-12-18 23:01:43 +01:00
6381c189cb correct binName
Some checks failed
continuous-integration/drone Build is failing
2022-12-18 22:54:52 +01:00
d0568e48ec with drone 2022-12-18 22:54:28 +01:00
f66a6c858d chore(release) with dependencies v0.1.5 2022-12-18 22:53:14 +01:00
267d546d2e chore(release) with dependencies 2022-12-18 22:49:48 +01:00
87c9c36f6c Add new dependencies 2022-12-18 22:48:29 +01:00
2f19707e94 chore(release) with updated version 2022-12-18 22:40:18 +01:00
a79d0ee6d4 chore(release) working on homebrew tap releaser 2022-12-18 22:30:16 +01:00
32ad2b3fd7 remove constraint 2022-12-18 22:29:18 +01:00
0a3a4d4f74 updated tag name 2022-12-18 22:28:04 +01:00
95f3254f81 chore(release) with updated version 2022-12-18 22:24:08 +01:00
5894bd5bb1 chore(release) fix pipeline 2022-12-18 22:21:07 +01:00
560f8f4fd0 chore(release) rename again 2022-12-18 22:12:17 +01:00
e1d8e27c23 rename formulas 2022-12-18 22:06:54 +01:00
2e19df72b0 chore(release) working on homebrew tap releaser 2022-12-18 22:03:21 +01:00
08b3e1cf5b chore(release) working on homebrew tap releaser 2022-12-18 21:56:54 +01:00
d592b5f2d8 brew github token 2022-12-18 21:56:27 +01:00
3f06afce02 chore(release) with other owner 2022-12-18 21:45:29 +01:00
d553bf06b7 remove arrow 2022-12-18 21:39:35 +01:00
7427f8f8d8 chore(release) with debug 2022-12-18 21:37:13 +01:00
e350d8c13d chore(release) with tag in release 2022-12-18 21:32:26 +01:00
27f5287c82 chore(release) with renamed release 2022-12-18 21:27:21 +01:00
cf7ce40afd move releaser 2022-12-18 21:22:18 +01:00
8149da56fb chore(release) working on homebrew tap releaser 2022-12-18 21:18:29 +01:00
af591b9802 fix lock 2022-12-18 21:15:36 +01:00
300d16d630 chore(release) working on homebrew tap releaser 2022-12-18 21:13:45 +01:00
09f6ad35f9 with license-file 2022-12-18 21:10:10 +01:00
64f853d025 with bin install 2022-12-18 21:06:42 +01:00
07a2143d50 with homebrew releaser 2022-12-18 21:05:31 +01:00
0ca6347f1f chore(release) add github release 2022-12-18 20:18:08 +01:00
9fc27f2c0e with required fields 2022-12-18 20:14:28 +01:00
98cb397ea9 add releaser 2022-12-18 20:05:49 +01:00
22 changed files with 1296 additions and 33 deletions

5
.drone.yml Normal file
View File

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

89
.github/workflows/release-published.yml vendored Normal file
View File

@@ -0,0 +1,89 @@
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

114
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,114 @@
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 }}

469
Cargo.lock generated
View File

@@ -2,6 +2,27 @@
# 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"
@@ -22,9 +43,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "4.0.29"
version = "4.0.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d63b9e9c07271b9957ad22c173bae2a4d9a81127680962039296abcd2f8251d"
checksum = "a7db700bc935f9e43e88d00b0850dae18a63773cfbec6d8e070fccf7fef89a39"
dependencies = [
"bitflags",
"clap_lex",
@@ -43,6 +64,65 @@ 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"
@@ -63,6 +143,18 @@ 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"
@@ -94,6 +186,21 @@ 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"
@@ -109,12 +216,25 @@ 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"
@@ -152,6 +272,27 @@ 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"
@@ -164,6 +305,85 @@ 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"
@@ -177,19 +397,93 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
[[package]]
name = "proc-macro2"
version = "1.0.47"
name = "output_vt100"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
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"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.21"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
dependencies = [
"proc-macro2",
]
@@ -214,6 +508,23 @@ 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"
@@ -228,6 +539,18 @@ 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"
@@ -237,6 +560,79 @@ 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"
@@ -264,10 +660,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "1.0.105"
name = "strum"
version = "0.24.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908"
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"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
dependencies = [
"proc-macro2",
"quote",
@@ -284,19 +699,25 @@ dependencies = [
]
[[package]]
name = "thiserror"
version = "1.0.37"
name = "termtree"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e"
checksum = "95059e91184749cb66be6dc994f67f182b6d897cb3df74a5bf66b5e709295fd8"
[[package]]
name = "thiserror"
version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.37"
version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb"
checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
dependencies = [
"proc-macro2",
"quote",
@@ -316,7 +737,7 @@ dependencies = [
[[package]]
name = "toolkit"
version = "0.1.0"
version = "0.1.10"
dependencies = [
"clap",
"eyre",
@@ -329,9 +750,15 @@ dependencies = [
[[package]]
name = "unicode-ident"
version = "1.0.5"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
[[package]]
name = "unicode-width"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
[[package]]
name = "util"
@@ -445,3 +872,9 @@ 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,7 +1,11 @@
[package]
name = "toolkit"
version = "0.1.0"
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.10"
edition = "2021"
license-file = "LICENSE"
authors = ["Kasper J. Hermansen contact@kjuulh.io"]
readme = "README.md"
[workspace]
members = [
@@ -13,7 +17,7 @@ members = [
]
[workspace.dependencies]
clap = { version = "4.0.29", features = ["cargo"] }
clap = { version = "4.0.32", features = ["cargo"] }
eyre = "0.6.8"
dirs = "4.0.0"
walkdir = "2.3.2"

0
LICENSE Normal file
View File

61
README.md Normal file
View File

@@ -0,0 +1,61 @@
# 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)

BIN
assets/demo.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 MiB

View File

@@ -11,3 +11,13 @@ 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,5 +1,6 @@
use std::io::Write;
use clap::value_parser;
use eyre::Context;
pub struct FuzzyClone;
@@ -201,13 +202,18 @@ impl FuzzyClone {
}),
)?;
} else {
util::shell::run(&["git", "pull"], None)?;
let _ = util::shell::run(
&["git", "pull"],
Some(util::shell::RunOptions {
path: git_repo_path.clone(),
}),
);
}
Ok(git_repo_path)
}
fn run() -> eyre::Result<()> {
fn run(print_dest: &bool) -> eyre::Result<()> {
let settings = Self::get_settings()?;
if settings.auto_update {
println!("running auto update");
@@ -234,10 +240,17 @@ impl FuzzyClone {
let chosen = util::shell::run_with_input_and_output(&["fzf"], entries_str)?;
let chosen = std::str::from_utf8(&chosen.stdout)?;
Self::clone(GitHubEntry::from(chosen.to_string()).ok_or(eyre::anyhow!(
let path = 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(())
}
@@ -255,13 +268,24 @@ 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()?,
_ => Self::run(print_dest)?,
}
Ok(())

View File

@@ -1,6 +1,8 @@
mod auth;
mod fuzzy_clone;
mod gh;
mod review;
pub(crate) mod review_backend;
pub struct GitHub;
@@ -31,6 +33,7 @@ impl util::Cmd for GitHub {
auth::Auth::cmd()?,
gh::Gh::cmd()?,
fuzzy_clone::FuzzyClone::cmd()?,
review::Review::cmd()?,
])
.allow_external_subcommands(true))
}
@@ -41,6 +44,7 @@ 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")),
}

257
crates/github/src/review.rs Normal file
View File

@@ -0,0 +1,257 @@
use crate::review_backend::{
models::{MenuChoice, 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>) -> 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)? {
Some(choice) => match choice {
MenuChoice::Exit => eyre::bail!(ReviewErrors::UserExit),
MenuChoice::List => return self.run(review_requested.clone()),
_ => eyre::bail!("invalid choice"),
},
None => {}
},
MenuChoice::Search => todo!(),
MenuChoice::List => return self.run(review_requested.clone()),
}
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>) -> 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)? {
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) -> eyre::Result<Option<MenuChoice>> {
self.backend.pr_open_browser(pr)?;
self.present_pr_menu(pr)
}
fn present_pr_menu(&self, pr: &PullRequest) -> 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);
}
ReviewMenuChoice::Open => return self.open_browser(pr),
ReviewMenuChoice::Skip => {}
ReviewMenuChoice::Merge => self.merge(pr)?,
ReviewMenuChoice::ApproveAndMerge => {
self.approve(pr)?;
self.merge(pr)?;
}
}
Ok(None)
}
fn merge(&self, pr: &PullRequest) -> eyre::Result<()> {
self.backend.enable_auto_merge(pr);
Ok(())
}
}
impl util::Cmd for Review {
fn cmd() -> eyre::Result<clap::Command> {
Ok(clap::Command::new("review"))
}
fn exec(_: &clap::ArgMatches) -> eyre::Result<()> {
Self::default().run(Some("lunarway/squad-aura".into()))
}
}
#[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(Some("kjuulh".into()));
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

@@ -0,0 +1,194 @@
pub mod models;
use std::io::Write;
use self::models::{MenuChoice, 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) -> 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",
"@me",
//review_request.unwrap().as_str(),
"--label",
"dependencies",
//"--checks=pending",
"--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) -> eyre::Result<()> {
util::shell::run(
&[
"gh",
"pr",
"merge",
pr.number.to_string().as_str(),
"--auto",
"--repo",
pr.repository.name.as_str(),
],
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

@@ -0,0 +1,31 @@
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,
}
pub enum MenuChoice {
Exit,
Begin,
Search,
List,
}
pub enum ReviewMenuChoice {
Exit,
List,
Approve,
Open,
Skip,
Merge,
ApproveAndMerge,
}

View File

@@ -1,5 +1,3 @@
use std::{borrow::Borrow, ffi::OsString};
pub struct Search;
impl util::Cmd for Search {
@@ -12,8 +10,8 @@ impl util::Cmd for Search {
fn exec(args: &clap::ArgMatches) -> eyre::Result<()> {
match args.subcommand() {
Some((external, args)) => {
let mut raw = args
.get_many::<OsString>("")
let raw = args
.get_many::<std::ffi::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(&["ytop", "--version"], "".into()) {
if let Err(_) = util::shell::run_with_input_and_output(&["btm", "--version"], "".into()) {
return Err(eyre::anyhow!(
"could not find ytop, please install or add to PATH"
"could not find btm, please install or add to PATH"
));
}
util::shell::run(&["ytop"], None)?;
util::shell::run(&["btm"], None)?;
Ok(())
}

View File

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

View File

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

0
man/.gitkeep Normal file
View File

13
src/init/fish.rs Normal file
View File

@@ -0,0 +1,13 @@
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(())
}
}

20
src/init/mod.rs Normal file
View File

@@ -0,0 +1,20 @@
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,5 +1,6 @@
use util::Cmd;
mod init;
mod prereqs;
fn main() -> eyre::Result<()> {
@@ -10,7 +11,9 @@ fn main() -> eyre::Result<()> {
sourcegraph::Sourcegraph::cmd()?,
github::GitHub::cmd()?,
stats::Stats::cmd()?,
init::Init::cmd()?,
])
.subcommand_required(true)
.get_matches();
match matches.subcommand() {
@@ -19,6 +22,7 @@ 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!")),
}
}