init
This commit is contained in:
commit
0a48113d38
10 changed files with 1660 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/target
|
624
Cargo.lock
generated
Normal file
624
Cargo.lock
generated
Normal file
|
@ -0,0 +1,624 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
"anstyle-query",
|
||||
"anstyle-wincon",
|
||||
"colorchoice",
|
||||
"is_terminal_polyfill",
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-parse"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
|
||||
dependencies = [
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-query"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
|
||||
dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "3.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"once_cell",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8eb5e908ef3a6efbe1ed62520fb7287959888c88485abe072543190ecc66783"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96b01801b5fc6a0a232407abc821660c9c6d25a1cafc0d4f85f29fb8d9afc121"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
"strsim",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
|
||||
|
||||
[[package]]
|
||||
name = "crossterm"
|
||||
version = "0.25.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"crossterm_winapi",
|
||||
"libc",
|
||||
"mio",
|
||||
"parking_lot",
|
||||
"signal-hook",
|
||||
"signal-hook-mio",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossterm_winapi"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dyn-clone"
|
||||
version = "1.0.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125"
|
||||
|
||||
[[package]]
|
||||
name = "fuzzy-matcher"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54614a3312934d066701a80f20f15fa3b56d67ac7722b39eea5b4c9dd1d66c94"
|
||||
dependencies = [
|
||||
"thread_local",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fxhash"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "g"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"inquire",
|
||||
"serde_json",
|
||||
"subprocess",
|
||||
"yansi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inquire"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fddf93031af70e75410a2511ec04d49e758ed2f26dad3404a934e0fb45cc12a"
|
||||
dependencies = [
|
||||
"bitflags 2.8.0",
|
||||
"crossterm",
|
||||
"dyn-clone",
|
||||
"fuzzy-matcher",
|
||||
"fxhash",
|
||||
"newline-converter",
|
||||
"once_cell",
|
||||
"unicode-segmentation",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is_terminal_polyfill"
|
||||
version = "1.70.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.169"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.8.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"wasi",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "newline-converter"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "47b6b097ecb1cbfed438542d16e84fd7ad9b0c76c8a65b7f9039212a3d14dc7f"
|
||||
dependencies = [
|
||||
"unicode-segmentation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.20.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
"parking_lot_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.9.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.5.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834"
|
||||
dependencies = [
|
||||
"bitflags 2.8.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.217"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.217"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.137"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "930cfb6e6abf99298aaad7d29abbef7a9999a9a8806a40088f55f0dcec03146b"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"signal-hook-registry",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-mio"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"mio",
|
||||
"signal-hook",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
version = "1.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||
|
||||
[[package]]
|
||||
name = "subprocess"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c2e86926081dda636c546d8c5e641661049d7562a68f5488be4a1f7f66f6086"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.96"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
dependencies = [
|
||||
"windows-targets 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.59.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.48.5",
|
||||
"windows_aarch64_msvc 0.48.5",
|
||||
"windows_i686_gnu 0.48.5",
|
||||
"windows_i686_msvc 0.48.5",
|
||||
"windows_x86_64_gnu 0.48.5",
|
||||
"windows_x86_64_gnullvm 0.48.5",
|
||||
"windows_x86_64_msvc 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.52.6",
|
||||
"windows_aarch64_msvc 0.52.6",
|
||||
"windows_i686_gnu 0.52.6",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc 0.52.6",
|
||||
"windows_x86_64_gnu 0.52.6",
|
||||
"windows_x86_64_gnullvm 0.52.6",
|
||||
"windows_x86_64_msvc 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
||||
[[package]]
|
||||
name = "yansi"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
|
11
Cargo.toml
Normal file
11
Cargo.toml
Normal file
|
@ -0,0 +1,11 @@
|
|||
[package]
|
||||
name = "g"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "4.5.26", features = ["cargo"] }
|
||||
inquire = "0.7.5"
|
||||
serde_json = "1.0.137"
|
||||
subprocess = "0.2.9"
|
||||
yansi = "1.0.1"
|
38
PKGBUILD
Normal file
38
PKGBUILD
Normal file
|
@ -0,0 +1,38 @@
|
|||
# Maintainer: JMARyA <jmarya@hydrar.de>
|
||||
pkgname=g
|
||||
pkgver=main
|
||||
pkgrel=1
|
||||
pkgdesc="git workflow wrapper"
|
||||
arch=('x86_64')
|
||||
url="https://git.hydrar.de/jmarya/g"
|
||||
license=("MIT")
|
||||
depends=("git" "serie" "ripgrep" "onefetch")
|
||||
makedepends=("rustup" "git")
|
||||
source=("${pkgname}::git+https://git.hydrar.de/jmarya/g.git")
|
||||
sha256sums=("SKIP")
|
||||
|
||||
pkgver() {
|
||||
cd "$srcdir/$pkgname"
|
||||
echo "$(date +%Y.%m.%d)_$(git rev-parse --short HEAD)"
|
||||
}
|
||||
|
||||
prepare() {
|
||||
cd "$srcdir/$pkgname"
|
||||
rustup default nightly
|
||||
cargo fetch
|
||||
}
|
||||
|
||||
build() {
|
||||
cd "$srcdir/$pkgname"
|
||||
cargo build --release
|
||||
}
|
||||
|
||||
check() {
|
||||
cd "$srcdir/$pkgname"
|
||||
cargo test --release
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "$srcdir/$pkgname"
|
||||
install -Dm755 "target/release/g" "$pkgdir/usr/bin/g"
|
||||
}
|
101
README.md
Normal file
101
README.md
Normal file
|
@ -0,0 +1,101 @@
|
|||
# `g`: The TOP G of Git Wrappers
|
||||
|
||||
Welcome to `g`, the ultimate Git wrapper for the hustlers. Inspired by the TOP G mindset, `g` ensures your version control game is faster, cleaner, and dripping with efficiency. Whether you're stacking branches like cash or committing to greatness, `g` is your ticket into the Real Git.
|
||||
|
||||
## Why choose `g`?
|
||||
- **Efficiency is key** - Git commands can feel like a 9-to-5 grind. `g` is here to automate the hustle.
|
||||
- **Stay focused** - Just like in Hustlers University, distractions are the enemy. `g` keeps you in the zone.
|
||||
- **Work like a TOP G** - This isn’t just version control; it’s a lifestyle. Be the alpha in your repo.
|
||||
|
||||
## Commands
|
||||
### Repository Management
|
||||
- `g bootstrap <BASE> <REPO>`
|
||||
|
||||
Initialize a new repository from a base repository.
|
||||
|
||||
> You don’t start from scratch; you leverage the foundation like a true hustler.
|
||||
|
||||
### Branching
|
||||
- `g branch`
|
||||
|
||||
Display all branches.
|
||||
|
||||
> Know your assets, track your investments. This is your repo empire.
|
||||
|
||||
- `g new <BRANCH>`
|
||||
|
||||
Create a new branch.
|
||||
|
||||
> In the world of branching, growth is king.
|
||||
|
||||
- `g remove <BRANCH>`
|
||||
|
||||
Remove a branch.
|
||||
|
||||
> Trim the weak branches so the strong ones can thrive.
|
||||
|
||||
### Syncing
|
||||
- `g fetch`
|
||||
|
||||
Run `git fetch --prune`.
|
||||
|
||||
> Prune like a gardener who only grows money trees. Keep the repo tight and right.
|
||||
|
||||
- `g pull`
|
||||
|
||||
Run `git pull --prune`.
|
||||
|
||||
> Pull harder than a Bugatti in first gear. Stay synced, stay winning.
|
||||
|
||||
- `g push`
|
||||
|
||||
Push changes to a remote repository.
|
||||
|
||||
> Send your code to the cloud like it’s your private jet.
|
||||
|
||||
### Logs and Status
|
||||
- `g log`
|
||||
|
||||
Display the commit log.
|
||||
|
||||
> The hustle doesn’t lie. Your commit history is your legacy.
|
||||
|
||||
- `g status`
|
||||
|
||||
Show the current repository status.
|
||||
|
||||
> Stay on top of your repo. TOP Gs don’t leave things to chance.
|
||||
|
||||
### Commit Management
|
||||
- `g todo`
|
||||
|
||||
Show open TODOs within the repository.
|
||||
|
||||
> Keep the numbers rising, except this one.
|
||||
|
||||
- `g save`
|
||||
|
||||
Create a WIP (Work In Progress) commit.
|
||||
|
||||
> Sometimes you gotta save it now to cash in later.
|
||||
|
||||
- `g commit [-a, --all] [-d, --done] [-i, --interactive] [-m, --message <MSG>]`
|
||||
|
||||
Commit changes.
|
||||
|
||||
- `-all` adds all changed files to Git.
|
||||
|
||||
- `--done` refuses to commit with open TODOs.
|
||||
|
||||
- `--interactive` creates gitmoji commits with an interactive menu.
|
||||
|
||||
- `--message` sets the commit message directly.
|
||||
|
||||
> Seal the deal with a strong message. Every commit should flex."
|
||||
|
||||
### Adding Files
|
||||
- `g add <FILE>`
|
||||
|
||||
Stage files for the next commit.
|
||||
|
||||
> Add value, one file at a time.
|
89
src/args.rs
Normal file
89
src/args.rs
Normal file
|
@ -0,0 +1,89 @@
|
|||
use clap::{arg, command};
|
||||
|
||||
pub fn get_args() -> clap::ArgMatches {
|
||||
command!()
|
||||
.about("Git wrapper")
|
||||
.subcommand(
|
||||
command!("bootstrap")
|
||||
.about("Bootstrap a new repository from base repository")
|
||||
.arg(arg!(<BASE> "Base repository").required(true))
|
||||
.arg(arg!(<NEW> "Repository name").required(true))
|
||||
.alias("bs"),
|
||||
)
|
||||
.subcommand(
|
||||
command!("todo")
|
||||
.about("Show open TODOs in repository")
|
||||
.alias("t"),
|
||||
)
|
||||
.subcommand(
|
||||
command!("new")
|
||||
.about("Create a new branch")
|
||||
.arg(arg!(<BRANCH> "Branch name").required(true))
|
||||
.alias("n"),
|
||||
)
|
||||
.subcommand(
|
||||
command!("commit")
|
||||
.about("Commit current changes")
|
||||
.alias("c")
|
||||
.arg(arg!(-a --all "Add all changed files to commit"))
|
||||
.arg(arg!(-d --done "Only allow commiting if no TODOs are present"))
|
||||
.arg(
|
||||
arg!(-i --interactive "Write interactive commit message with gitmoji standard")
|
||||
.conflicts_with("message"),
|
||||
)
|
||||
.arg(arg!(-m --message <MSG> "Commit message").required(false)),
|
||||
)
|
||||
.subcommand(
|
||||
command!("remove")
|
||||
.about("Remove a branch")
|
||||
.arg(arg!(<BRANCH> "Branch name").required(true))
|
||||
.alias("r"),
|
||||
)
|
||||
.subcommand(command!("branch").about("Show branches").alias("b"))
|
||||
.subcommand(
|
||||
command!()
|
||||
.name("push")
|
||||
.about("Push to a remote")
|
||||
.arg(arg!(-f --force "Force push"))
|
||||
.alias("p"),
|
||||
)
|
||||
.subcommand(
|
||||
command!()
|
||||
.name("status")
|
||||
.about("Show git status")
|
||||
.alias("stat")
|
||||
.alias("stats"),
|
||||
)
|
||||
.subcommand(
|
||||
command!()
|
||||
.name("add")
|
||||
.about("Add files to git")
|
||||
.alias("a")
|
||||
.arg(arg!(<FILE> "File to add").required(true)),
|
||||
)
|
||||
.subcommand(
|
||||
command!()
|
||||
.name("fetch")
|
||||
.about("Run git fetch --prune")
|
||||
.alias("f"),
|
||||
)
|
||||
.subcommand(
|
||||
command!()
|
||||
.name("pull")
|
||||
.about("Run git pull --prune")
|
||||
.alias("p"),
|
||||
)
|
||||
.subcommand(
|
||||
command!()
|
||||
.name("log")
|
||||
.about("Show git commit log")
|
||||
.alias("l"),
|
||||
)
|
||||
.subcommand(
|
||||
command!()
|
||||
.name("save")
|
||||
.about("Create a WIP commit")
|
||||
.alias("s"),
|
||||
)
|
||||
.get_matches()
|
||||
}
|
260
src/git.rs
Normal file
260
src/git.rs
Normal file
|
@ -0,0 +1,260 @@
|
|||
use subprocess::Exec;
|
||||
use yansi::{Color, Paint};
|
||||
|
||||
use crate::{
|
||||
NO_COMMIT_REGEX, no_commit_amount, precommit::rust_pre_commit, read_stdout, show_rg,
|
||||
todos_amount,
|
||||
};
|
||||
|
||||
/// Check if the current repository has a remote set up
|
||||
pub fn has_remote() -> bool {
|
||||
let e = Exec::cmd("git").arg("remote").arg("-v");
|
||||
let str = read_stdout(e);
|
||||
!str.is_empty()
|
||||
}
|
||||
|
||||
/// Create a new branch and switch to it in the current repository
|
||||
pub fn create_new_branch(branch: &str) {
|
||||
let mut git = Exec::cmd("git")
|
||||
.arg("checkout")
|
||||
.arg("-b")
|
||||
.arg(branch)
|
||||
.popen()
|
||||
.unwrap();
|
||||
git.wait().unwrap();
|
||||
if has_remote() {
|
||||
let mut git = Exec::cmd("git")
|
||||
.arg("push")
|
||||
.arg("-u")
|
||||
.arg("origin")
|
||||
.arg(branch)
|
||||
.popen()
|
||||
.unwrap();
|
||||
git.wait().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
/// Push the current repository to remote
|
||||
pub fn push(force: bool) {
|
||||
let mut cmd = Exec::cmd("git")
|
||||
.arg("push")
|
||||
.arg("--set-upstream")
|
||||
.arg("origin");
|
||||
|
||||
if force {
|
||||
cmd = cmd.arg("--force-with-lease");
|
||||
}
|
||||
|
||||
cmd.popen().unwrap().wait().unwrap();
|
||||
}
|
||||
|
||||
/// Delete a branch from the current repository
|
||||
pub fn delete_branch(branch: &str) {
|
||||
let mut git = Exec::cmd("git")
|
||||
.arg("branch")
|
||||
.arg("-d")
|
||||
.arg(branch)
|
||||
.popen()
|
||||
.unwrap();
|
||||
git.wait().unwrap();
|
||||
if has_remote() {
|
||||
let mut git = Exec::cmd("git")
|
||||
.arg("push")
|
||||
.arg("origin")
|
||||
.arg("--delete")
|
||||
.arg(branch)
|
||||
.popen()
|
||||
.unwrap();
|
||||
git.wait().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the title of the last commit
|
||||
pub fn last_commit() -> String {
|
||||
let e = Exec::cmd("git").arg("log").arg("-1").arg("--pretty=%B");
|
||||
read_stdout(e)
|
||||
}
|
||||
|
||||
/// Get all files affected by last commit
|
||||
pub fn last_commit_files() -> Vec<String> {
|
||||
let file_str = read_stdout(
|
||||
Exec::cmd("git")
|
||||
.arg("diff-tree")
|
||||
.arg("--no-commit-id")
|
||||
.arg("--name-only")
|
||||
.arg("-r")
|
||||
.arg("HEAD"),
|
||||
);
|
||||
|
||||
file_str.split('\n').map(|x| x.to_string()).collect()
|
||||
}
|
||||
|
||||
/// Add a file to git
|
||||
pub fn git_add(file: &str) {
|
||||
Exec::cmd("git")
|
||||
.arg("add")
|
||||
.arg(file)
|
||||
.popen()
|
||||
.unwrap()
|
||||
.wait()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
/// Get a Vec of programming languages used in this repository
|
||||
pub fn get_languages() -> Vec<String> {
|
||||
let e: Exec = Exec::cmd("onefetch").arg("-o").arg("json");
|
||||
let json_str = read_stdout(e);
|
||||
if let Result::<serde_json::Value, _>::Ok(json) = serde_json::from_str(&json_str) {
|
||||
let languages = (|| {
|
||||
let fields = json.as_object()?.get("infoFields")?.as_array()?;
|
||||
let langs = fields
|
||||
.iter()
|
||||
.find(|x| x.as_object().unwrap().contains_key("LanguagesInfo"))?;
|
||||
let langs = langs
|
||||
.as_object()?
|
||||
.get("LanguagesInfo")?
|
||||
.as_object()?
|
||||
.get("languagesWithPercentage")?
|
||||
.as_array()?;
|
||||
Some(
|
||||
langs
|
||||
.iter()
|
||||
.map(|x| {
|
||||
x.as_object()
|
||||
.unwrap()
|
||||
.get("language")
|
||||
.unwrap()
|
||||
.as_str()
|
||||
.unwrap()
|
||||
.to_string()
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
})();
|
||||
|
||||
languages.unwrap_or_default()
|
||||
} else {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
/// Commit changes to the repository.
|
||||
pub fn commit(all: bool, done: bool, msg: &str) {
|
||||
// Work In Progress Save Commit
|
||||
if last_commit().as_str() == "WIP" {
|
||||
// Get files affected by commit
|
||||
let last_commit_files = last_commit_files();
|
||||
|
||||
// Reset last commit
|
||||
Exec::cmd("git")
|
||||
.arg("reset")
|
||||
.arg("HEAD~1")
|
||||
.popen()
|
||||
.unwrap()
|
||||
.wait()
|
||||
.unwrap();
|
||||
|
||||
// Readd files affected by commit
|
||||
for file in last_commit_files {
|
||||
git_add(&file);
|
||||
}
|
||||
}
|
||||
|
||||
// Check TODOs
|
||||
let todos = todos_amount();
|
||||
|
||||
if todos > 0 {
|
||||
println!(
|
||||
"{}: Repository still contains {todos} TODO entries.",
|
||||
"Warning".paint(Color::Yellow)
|
||||
);
|
||||
|
||||
if done {
|
||||
println!(
|
||||
"{}",
|
||||
"💀 Make sure to close them before commiting or we can't rest in peace..."
|
||||
.paint(Color::Red)
|
||||
);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Impossible commits
|
||||
if no_commit_amount() > 0 {
|
||||
println!("{}", "Unable to commit because of:".paint(Color::Red));
|
||||
show_rg(NO_COMMIT_REGEX);
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
// Laguage specific pre-commit hooks
|
||||
for lang in get_languages() {
|
||||
match lang.as_str() {
|
||||
"Rust" => {
|
||||
rust_pre_commit();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
if all {
|
||||
Exec::cmd("git")
|
||||
.arg("add")
|
||||
.arg("-A")
|
||||
.popen()
|
||||
.unwrap()
|
||||
.wait()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
Exec::cmd("git")
|
||||
.arg("commit")
|
||||
.arg("-m")
|
||||
.arg(msg)
|
||||
.popen()
|
||||
.unwrap()
|
||||
.wait()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
/// Fetch remote state
|
||||
pub fn fetch() {
|
||||
Exec::cmd("git")
|
||||
.arg("fetch")
|
||||
.arg("--prune")
|
||||
.popen()
|
||||
.unwrap()
|
||||
.wait()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
/// Pull remote changes
|
||||
pub fn pull() {
|
||||
Exec::cmd("git")
|
||||
.arg("pull")
|
||||
.arg("--prune")
|
||||
.popen()
|
||||
.unwrap()
|
||||
.wait()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
/// Bootstrap a git repository using a base template
|
||||
pub fn bootstrap(base: &str, name: &str) {
|
||||
Exec::cmd("git")
|
||||
.arg("clone")
|
||||
.arg(base)
|
||||
.arg(name)
|
||||
.popen()
|
||||
.unwrap()
|
||||
.wait()
|
||||
.unwrap();
|
||||
std::fs::remove_dir_all(std::path::Path::new(name).join(".git")).unwrap();
|
||||
Exec::cmd("git")
|
||||
.arg("init")
|
||||
.arg("--quiet")
|
||||
.cwd(std::path::Path::new(name))
|
||||
.popen()
|
||||
.unwrap()
|
||||
.wait()
|
||||
.unwrap();
|
||||
}
|
360
src/gitmoji.rs
Normal file
360
src/gitmoji.rs
Normal file
|
@ -0,0 +1,360 @@
|
|||
pub fn select_from_list<F: FnOnce(&str) -> String>(
|
||||
prompt: &str,
|
||||
lst: Vec<&str>,
|
||||
quit: bool,
|
||||
then: F,
|
||||
) -> String {
|
||||
match inquire::Select::new(prompt, lst).prompt() {
|
||||
Ok(val) => then(val),
|
||||
Err(_) => {
|
||||
if quit {
|
||||
eprintln!("Nothing selected");
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
String::new()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn select_gitmoji() -> String {
|
||||
let topics = vec![
|
||||
"Fix",
|
||||
"Refactor",
|
||||
"Improve",
|
||||
"Add/Update",
|
||||
"Remove",
|
||||
"Git",
|
||||
"UI",
|
||||
"Dependency",
|
||||
"Security",
|
||||
"Text",
|
||||
"Test",
|
||||
"Fun",
|
||||
"Misc",
|
||||
];
|
||||
|
||||
let select = select_from_list(
|
||||
"Gitmoji Intention Topic",
|
||||
topics,
|
||||
true,
|
||||
|topic| match topic {
|
||||
"Fix" => select_gitmoji_fix(),
|
||||
"Improve" => select_gitmoji_improvement(),
|
||||
"Remove" => select_gitmoji_remove(),
|
||||
"Dependency" => select_gitmoji_dependency(),
|
||||
"Test" => select_gitmoji_test(),
|
||||
"Git" => select_gitmoji_git(),
|
||||
"Refactor" => select_gitmoji_refactor(),
|
||||
"UI" => select_gitmoji_ui(),
|
||||
"Text" => select_gitmoji_text(),
|
||||
"Fun" => select_gitmoji_fun(),
|
||||
"Security" => select_gitmoji_security(),
|
||||
"Add/Update" => select_gitmoji_add_update(),
|
||||
_ => select_gitmoji_misc(),
|
||||
},
|
||||
);
|
||||
|
||||
if select.is_empty() {
|
||||
return select_gitmoji();
|
||||
}
|
||||
|
||||
select
|
||||
}
|
||||
|
||||
pub fn select_gitmoji_fix() -> String {
|
||||
let options = vec![
|
||||
"🐛 Fix a bug",
|
||||
"🩹 Simple fix for a non-critical issue",
|
||||
"🚑️ Critical hotfix",
|
||||
"✏️ Fix typos",
|
||||
"💚 Fix CI Build",
|
||||
"🔒️ Fix security or privacy issues",
|
||||
"🚨 Fix compiler / linter warnings",
|
||||
"🥅 Catch errors",
|
||||
];
|
||||
|
||||
let res = select_from_list("Gitmoji Intention", options, false, |selected| {
|
||||
selected.split_whitespace().next().unwrap().to_string()
|
||||
});
|
||||
|
||||
if res.is_empty() {
|
||||
return select_gitmoji();
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
pub fn select_gitmoji_improvement() -> String {
|
||||
let options = vec![
|
||||
"✨ Introduce new features",
|
||||
"🎨 Improve structure / format of the code",
|
||||
"⚡️ Improve performance",
|
||||
"🧑💻 Improve developer experience",
|
||||
"🚸 Improve user experience / usability",
|
||||
"♿️ Improve accessibility",
|
||||
"🔍️ Improve SEO",
|
||||
];
|
||||
|
||||
let res = select_from_list("Gitmoji Intention", options, false, |selected| {
|
||||
selected.split_whitespace().next().unwrap().to_string()
|
||||
});
|
||||
|
||||
if res.is_empty() {
|
||||
return select_gitmoji();
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
pub fn select_gitmoji_remove() -> String {
|
||||
let options = vec!["🔥 Remove code or files", "⚰️ Remove dead code"];
|
||||
|
||||
let res = select_from_list("Gitmoji Intention", options, false, |selected| {
|
||||
selected.split_whitespace().next().unwrap().to_string()
|
||||
});
|
||||
|
||||
if res.is_empty() {
|
||||
return select_gitmoji();
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
pub fn select_gitmoji_dependency() -> String {
|
||||
let options = vec![
|
||||
"➖ Remove a dependency",
|
||||
"➕ Add a dependency",
|
||||
"⬇️ Downgrade dependencies",
|
||||
"⬆️ Upgrade dependencies",
|
||||
"📌 Pin dependencies to specific versions",
|
||||
];
|
||||
|
||||
let res = select_from_list("Gitmoji Intention", options, false, |selected| {
|
||||
selected.split_whitespace().next().unwrap().to_string()
|
||||
});
|
||||
|
||||
if res.is_empty() {
|
||||
return select_gitmoji();
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
pub fn select_gitmoji_test() -> String {
|
||||
let options = vec![
|
||||
"✅ Add, update, or pass tests",
|
||||
"🧪 Add a failing test",
|
||||
"🤡 Mock things",
|
||||
"⚗️ Perform experiments",
|
||||
];
|
||||
|
||||
let res = select_from_list("Gitmoji Intention", options, false, |selected| {
|
||||
selected.split_whitespace().next().unwrap().to_string()
|
||||
});
|
||||
|
||||
if res.is_empty() {
|
||||
return select_gitmoji();
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
pub fn select_gitmoji_fun() -> String {
|
||||
let options = vec![
|
||||
"🍻 Write code drunkenly",
|
||||
"🍃 Write code high",
|
||||
"❄ Write code on coke",
|
||||
"🍄 Write code on psychedelics",
|
||||
"🥚 Add or update an easter egg",
|
||||
"💩 Write bad code that needs to be improved",
|
||||
];
|
||||
|
||||
let res = select_from_list("Gitmoji Intention", options, false, |selected| {
|
||||
selected.split_whitespace().next().unwrap().to_string()
|
||||
});
|
||||
|
||||
if res.is_empty() {
|
||||
return select_gitmoji();
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
pub fn select_gitmoji_git() -> String {
|
||||
let options = vec![
|
||||
"⏪️ Revert changes",
|
||||
"🔀 Merge branches",
|
||||
"🔖 Release / Version tags",
|
||||
"🙈 Add or update a .gitignore file",
|
||||
];
|
||||
|
||||
let res = select_from_list("Gitmoji Intention", options, false, |selected| {
|
||||
selected.split_whitespace().next().unwrap().to_string()
|
||||
});
|
||||
|
||||
if res.is_empty() {
|
||||
return select_gitmoji();
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
pub fn select_gitmoji_refactor() -> String {
|
||||
let options = vec![
|
||||
"♻️ Refactor code",
|
||||
"🗑️ Deprecate code that needs to be cleaned up",
|
||||
"🚚 Move or rename resources (e.g.: files, paths, routes)",
|
||||
"🍱 Add or update assets",
|
||||
"👽️ Update code due to external API changes",
|
||||
"💡 Add or update comments in source code",
|
||||
"🏷️ Add or update types",
|
||||
];
|
||||
|
||||
let res = select_from_list("Gitmoji Intention", options, false, |selected| {
|
||||
selected.split_whitespace().next().unwrap().to_string()
|
||||
});
|
||||
|
||||
if res.is_empty() {
|
||||
return select_gitmoji();
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
pub fn select_gitmoji_ui() -> String {
|
||||
let options = vec![
|
||||
"💄 Add or update the UI and style files",
|
||||
"📱 Work on responsive design",
|
||||
"💫 Add or update animations and transitions",
|
||||
];
|
||||
|
||||
let res = select_from_list("Gitmoji Intention", options, false, |selected| {
|
||||
selected.split_whitespace().next().unwrap().to_string()
|
||||
});
|
||||
|
||||
if res.is_empty() {
|
||||
return select_gitmoji();
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
pub fn select_gitmoji_text() -> String {
|
||||
let options = vec![
|
||||
"📝 Add or update documentation",
|
||||
"🌐 Internationalization and localization",
|
||||
"💬 Add or update text and literals",
|
||||
"👥 Add or update contributor(s)",
|
||||
"📄 Add or update license",
|
||||
"🔊 Add or update logs",
|
||||
"🔇 Remove logs",
|
||||
];
|
||||
|
||||
let res = select_from_list("Gitmoji Intention", options, false, |selected| {
|
||||
selected.split_whitespace().next().unwrap().to_string()
|
||||
});
|
||||
|
||||
if res.is_empty() {
|
||||
return select_gitmoji();
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
pub fn select_gitmoji_security() -> String {
|
||||
let options = vec![
|
||||
"🛂 Work on code related to authorization, roles and permissions",
|
||||
"🔐 Add or update secrets",
|
||||
"🦺 Add or update code related to validation",
|
||||
];
|
||||
|
||||
let res = select_from_list("Gitmoji Intention", options, false, |selected| {
|
||||
selected.split_whitespace().next().unwrap().to_string()
|
||||
});
|
||||
|
||||
if res.is_empty() {
|
||||
return select_gitmoji();
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
pub fn select_gitmoji_add_update() -> String {
|
||||
let options = vec![
|
||||
"👷 Add or update CI build system",
|
||||
"🔧 Add or update configuration files",
|
||||
"🔨 Add or update development scripts",
|
||||
"📦️ Add or update compiled files or packages",
|
||||
"🚩 Add, update, or remove feature flags",
|
||||
"🩺 Add or update healthcheck",
|
||||
"🧵 Add or update code related to multithreading or concurrency",
|
||||
"🌱 Add or update seed files",
|
||||
"📸 Add or update snapshots",
|
||||
"📈 Add or update analytics or track code",
|
||||
"👔 Add or update business logic",
|
||||
];
|
||||
|
||||
let res = select_from_list("Gitmoji Intention", options, false, |selected| {
|
||||
selected.split_whitespace().next().unwrap().to_string()
|
||||
});
|
||||
|
||||
if res.is_empty() {
|
||||
return select_gitmoji();
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
pub fn select_gitmoji_misc() -> String {
|
||||
let options = vec![
|
||||
"🎉 Begin a project",
|
||||
"🚀 Deploy stuff",
|
||||
"🚧 Work in progress",
|
||||
"💥 Introduce breaking changes",
|
||||
"🗃️ Perform database related changes",
|
||||
"🏗️ Make architectural changes",
|
||||
"🧱 Infrastructure related changes",
|
||||
"💸 Add sponsorships or money related infrastructure",
|
||||
"🧐 Data exploration/inspection",
|
||||
];
|
||||
|
||||
let res = select_from_list("Gitmoji Intention", options, false, |selected| {
|
||||
selected.split_whitespace().next().unwrap().to_string()
|
||||
});
|
||||
|
||||
if res.is_empty() {
|
||||
return select_gitmoji();
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
pub struct CommitMessage {
|
||||
gitmoji: String,
|
||||
title: String,
|
||||
body: Option<String>,
|
||||
}
|
||||
|
||||
impl CommitMessage {
|
||||
pub const fn new(gitmoji: String, title: String, body: Option<String>) -> Self {
|
||||
CommitMessage {
|
||||
gitmoji,
|
||||
title,
|
||||
body,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_msg(&self) -> String {
|
||||
let mut msg = self.gitmoji.clone();
|
||||
msg.push_str(&format!(" {}", self.title));
|
||||
|
||||
if let Some(body) = &self.body {
|
||||
if !body.is_empty() {
|
||||
msg.push_str(&format!("\n\n{body}"));
|
||||
}
|
||||
}
|
||||
|
||||
msg
|
||||
}
|
||||
}
|
154
src/main.rs
Normal file
154
src/main.rs
Normal file
|
@ -0,0 +1,154 @@
|
|||
use git::{bootstrap, commit, create_new_branch, delete_branch, fetch, git_add, pull, push};
|
||||
use gitmoji::{CommitMessage, select_gitmoji};
|
||||
use std::io::Read;
|
||||
use subprocess::{Exec, Redirection};
|
||||
|
||||
mod args;
|
||||
mod git;
|
||||
mod gitmoji;
|
||||
mod precommit;
|
||||
|
||||
pub fn read_stdout(e: Exec) -> String {
|
||||
let mut p = e.stdout(Redirection::Pipe).popen().unwrap();
|
||||
let mut str = String::new();
|
||||
p.stdout.as_mut().unwrap().read_to_string(&mut str).unwrap();
|
||||
str.trim().to_string()
|
||||
}
|
||||
|
||||
const TODO_REGEX: &str = r" (todo|unimplemented|refactor|wip|fix)(:|!|\n|\ :)";
|
||||
const NO_COMMIT_REGEX: &str = r"(NOCOMMIT|ENSURE: )";
|
||||
|
||||
pub fn no_commit_amount() -> u64 {
|
||||
rg_matches(NO_COMMIT_REGEX)
|
||||
}
|
||||
|
||||
pub fn todos_amount() -> u64 {
|
||||
rg_matches(TODO_REGEX)
|
||||
}
|
||||
|
||||
pub fn rg_matches(regex: &str) -> u64 {
|
||||
let mut cmd = Exec::cmd("rg")
|
||||
.arg("-i")
|
||||
.arg("--json")
|
||||
.arg("--multiline")
|
||||
.arg(regex)
|
||||
.stdout(Redirection::Pipe)
|
||||
.popen()
|
||||
.unwrap();
|
||||
cmd.wait().unwrap();
|
||||
let mut str = String::new();
|
||||
cmd.stdout
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.read_to_string(&mut str)
|
||||
.unwrap();
|
||||
let last_line = str.lines().last().unwrap();
|
||||
let val: serde_json::Value = serde_json::from_str(last_line).unwrap();
|
||||
let ret = (|| {
|
||||
val.as_object()
|
||||
.unwrap()
|
||||
.get("data")?
|
||||
.as_object()?
|
||||
.get("stats")?
|
||||
.as_object()?
|
||||
.get("matches")?
|
||||
.as_number()
|
||||
.unwrap()
|
||||
.as_i64()
|
||||
})();
|
||||
ret.unwrap_or(0) as u64
|
||||
}
|
||||
|
||||
pub fn show_rg(regex: &str) {
|
||||
Exec::cmd("rg")
|
||||
.arg("-i")
|
||||
.arg("--multiline")
|
||||
.arg(regex)
|
||||
.popen()
|
||||
.unwrap()
|
||||
.wait()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
pub fn show_todos() {
|
||||
println!("{} todos found.", todos_amount());
|
||||
show_rg(TODO_REGEX);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args = args::get_args();
|
||||
|
||||
match args.subcommand() {
|
||||
Some(("bootstrap", bs_args)) => {
|
||||
let base = bs_args.get_one::<String>("BASE").unwrap();
|
||||
let repo = bs_args.get_one::<String>("NEW").unwrap();
|
||||
bootstrap(base, repo);
|
||||
}
|
||||
Some(("new", new_args)) => {
|
||||
let branch: &String = new_args.get_one("BRANCH").unwrap();
|
||||
create_new_branch(branch);
|
||||
}
|
||||
Some(("remove", rm_args)) => {
|
||||
let branch: &String = rm_args.get_one("BRANCH").unwrap();
|
||||
delete_branch(branch);
|
||||
}
|
||||
Some(("branch", _)) => {
|
||||
Exec::cmd("git")
|
||||
.arg("branch")
|
||||
.popen()
|
||||
.unwrap()
|
||||
.wait()
|
||||
.unwrap();
|
||||
}
|
||||
Some(("push", push_args)) => {
|
||||
let force = push_args.get_flag("force");
|
||||
push(force);
|
||||
}
|
||||
Some(("commit", commit_args)) => {
|
||||
let all = commit_args.get_flag("all");
|
||||
let done = commit_args.get_flag("done");
|
||||
let msg: Option<&String> = commit_args.get_one("message");
|
||||
let interactive = commit_args.get_flag("interactive");
|
||||
|
||||
if interactive || msg.is_none() {
|
||||
let gitmoji = select_gitmoji();
|
||||
let title = inquire::prompt_text("Commit Title").unwrap();
|
||||
let body = inquire::Text::new("Commit Description")
|
||||
.with_page_size(5)
|
||||
.prompt();
|
||||
let msg = CommitMessage::new(gitmoji, title, body.ok()).to_msg();
|
||||
commit(all, done, &msg);
|
||||
} else {
|
||||
commit(all, done, msg.unwrap());
|
||||
}
|
||||
}
|
||||
Some(("save", _)) => {
|
||||
commit(true, false, "WIP");
|
||||
}
|
||||
Some(("fetch", _)) => {
|
||||
fetch();
|
||||
}
|
||||
Some(("pull", _)) => {
|
||||
pull();
|
||||
}
|
||||
Some(("todo", _)) => {
|
||||
show_todos();
|
||||
}
|
||||
Some(("log", _)) => {
|
||||
Exec::cmd("serie").popen().unwrap().wait().unwrap();
|
||||
}
|
||||
Some(("status", _)) => {
|
||||
Exec::cmd("git")
|
||||
.arg("status")
|
||||
.popen()
|
||||
.unwrap()
|
||||
.wait()
|
||||
.unwrap();
|
||||
}
|
||||
Some(("add", args)) => {
|
||||
let file: &String = args.get_one("FILE").unwrap();
|
||||
git_add(file);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
22
src/precommit.rs
Normal file
22
src/precommit.rs
Normal file
|
@ -0,0 +1,22 @@
|
|||
use crate::{git::git_add, read_stdout};
|
||||
use subprocess::Exec;
|
||||
|
||||
pub fn rust_pre_commit() {
|
||||
println!("Running cargo fmt");
|
||||
let e = Exec::cmd("cargo").arg("fmt").arg("--verbose");
|
||||
let out = read_stdout(e);
|
||||
|
||||
for line in out.lines() {
|
||||
println!("line {line}");
|
||||
if line.starts_with("rustfmt") {
|
||||
let mut split: Vec<_> = line.split_whitespace().collect();
|
||||
split.reverse();
|
||||
split.pop();
|
||||
split.pop();
|
||||
split.pop();
|
||||
split.reverse();
|
||||
let file = split.join(" ");
|
||||
git_add(&file);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue