Compare commits
9 Commits
main
...
e17db09859
| Author | SHA1 | Date | |
|---|---|---|---|
|
e17db09859
|
|||
|
b94e5b3394
|
|||
|
115f1d5db3
|
|||
|
845d59040c
|
|||
|
936c6b4741
|
|||
|
332ef8e00d
|
|||
|
ebdbd0e8a5
|
|||
|
9c0d125995
|
|||
|
98999336dc
|
@@ -1,4 +0,0 @@
|
|||||||
kind: template
|
|
||||||
load: bust_gobin_default_template.yaml
|
|
||||||
name: char
|
|
||||||
data: {}
|
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1 +1,2 @@
|
|||||||
dist/
|
target/
|
||||||
|
.vscode/
|
||||||
|
|||||||
527
Cargo.lock
generated
Normal file
527
Cargo.lock
generated
Normal file
@@ -0,0 +1,527 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "addr2line"
|
||||||
|
version = "0.19.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97"
|
||||||
|
dependencies = [
|
||||||
|
"gimli",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "adler"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "backtrace"
|
||||||
|
version = "0.3.67"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca"
|
||||||
|
dependencies = [
|
||||||
|
"addr2line",
|
||||||
|
"cc",
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"miniz_oxide",
|
||||||
|
"object",
|
||||||
|
"rustc-demangle",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cc"
|
||||||
|
version = "1.0.78"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "char"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"clap",
|
||||||
|
"color-eyre",
|
||||||
|
"eyre",
|
||||||
|
"serde",
|
||||||
|
"toml",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap"
|
||||||
|
version = "4.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4ec7a4128863c188deefe750ac1d1dfe66c236909f845af04beed823638dc1b2"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"clap_lex",
|
||||||
|
"is-terminal",
|
||||||
|
"strsim",
|
||||||
|
"termcolor",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_lex"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "783fe232adfca04f90f56201b26d79682d4cd2625e0bc7290b95123afe558ade"
|
||||||
|
dependencies = [
|
||||||
|
"os_str_bytes",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "color-eyre"
|
||||||
|
version = "0.6.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a667583cca8c4f8436db8de46ea8233c42a7d9ae424a82d338f2e4675229204"
|
||||||
|
dependencies = [
|
||||||
|
"backtrace",
|
||||||
|
"color-spantrace",
|
||||||
|
"eyre",
|
||||||
|
"indenter",
|
||||||
|
"once_cell",
|
||||||
|
"owo-colors",
|
||||||
|
"tracing-error",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "color-spantrace"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1ba75b3d9449ecdccb27ecbc479fdc0b87fa2dd43d2f8298f9bf0e59aacc8dce"
|
||||||
|
dependencies = [
|
||||||
|
"once_cell",
|
||||||
|
"owo-colors",
|
||||||
|
"tracing-core",
|
||||||
|
"tracing-error",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "errno"
|
||||||
|
version = "0.2.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
|
||||||
|
dependencies = [
|
||||||
|
"errno-dragonfly",
|
||||||
|
"libc",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "errno-dragonfly"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "eyre"
|
||||||
|
version = "0.6.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb"
|
||||||
|
dependencies = [
|
||||||
|
"indenter",
|
||||||
|
"once_cell",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gimli"
|
||||||
|
version = "0.27.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dec7af912d60cdbd3677c1af9352ebae6fb8394d165568a2234df0fa00f87793"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.12.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hermit-abi"
|
||||||
|
version = "0.2.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indenter"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indexmap"
|
||||||
|
version = "1.9.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"hashbrown",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "io-lifetimes"
|
||||||
|
version = "1.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e7d6c6f8c91b4b9ed43484ad1a938e393caf35960fce7f82a040497207bd8e9e"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "is-terminal"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi",
|
||||||
|
"io-lifetimes",
|
||||||
|
"rustix",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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.139"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "linux-raw-sys"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "miniz_oxide"
|
||||||
|
version = "0.6.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
|
||||||
|
dependencies = [
|
||||||
|
"adler",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "object"
|
||||||
|
version = "0.30.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2b8c786513eb403643f2a88c244c2aaa270ef2153f55094587d0c48a3cf22a83"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.17.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "os_str_bytes"
|
||||||
|
version = "6.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "owo-colors"
|
||||||
|
version = "3.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pin-project-lite"
|
||||||
|
version = "0.2.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.50"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.23"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc-demangle"
|
||||||
|
version = "0.1.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustix"
|
||||||
|
version = "0.36.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d4fdebc4b395b7fbb9ab11e462e20ed9051e7b16e42d24042c776eca0ac81b03"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"errno",
|
||||||
|
"io-lifetimes",
|
||||||
|
"libc",
|
||||||
|
"linux-raw-sys",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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 = "sharded-slab"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strsim"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "1.0.107"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "termcolor"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thread_local"
|
||||||
|
version = "1.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180"
|
||||||
|
dependencies = [
|
||||||
|
"once_cell",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml"
|
||||||
|
version = "0.5.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
|
||||||
|
dependencies = [
|
||||||
|
"indexmap",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing"
|
||||||
|
version = "0.1.37"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"pin-project-lite",
|
||||||
|
"tracing-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-core"
|
||||||
|
version = "0.1.30"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
|
||||||
|
dependencies = [
|
||||||
|
"once_cell",
|
||||||
|
"valuable",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-error"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e"
|
||||||
|
dependencies = [
|
||||||
|
"tracing",
|
||||||
|
"tracing-subscriber",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-subscriber"
|
||||||
|
version = "0.3.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70"
|
||||||
|
dependencies = [
|
||||||
|
"sharded-slab",
|
||||||
|
"thread_local",
|
||||||
|
"tracing-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "valuable"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
|
||||||
|
|
||||||
|
[[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-util"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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.42.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm",
|
||||||
|
"windows_aarch64_msvc",
|
||||||
|
"windows_i686_gnu",
|
||||||
|
"windows_i686_msvc",
|
||||||
|
"windows_x86_64_gnu",
|
||||||
|
"windows_x86_64_gnullvm",
|
||||||
|
"windows_x86_64_msvc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.42.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.42.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.42.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.42.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.42.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.42.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.42.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
|
||||||
13
Cargo.toml
Normal file
13
Cargo.toml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
[package]
|
||||||
|
name = "char"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
clap = "4.1.1"
|
||||||
|
color-eyre = "0.6.2"
|
||||||
|
eyre = "0.6.8"
|
||||||
|
serde = { version = "1.0.152", features = ["derive"] }
|
||||||
|
toml = { version = "0.5.11", features = ["preserve_order"] }
|
||||||
26
README.md
26
README.md
@@ -1,26 +0,0 @@
|
|||||||
# Char
|
|
||||||
|
|
||||||
Char is an organizations best friend, it helps with code sharing when either
|
|
||||||
using a multi-repo strategy or mono repo. The goal of the project is to
|
|
||||||
facilitate sharing of presets and plugins to reduce the required complexity
|
|
||||||
developers have to take on.
|
|
||||||
|
|
||||||
This project is best suited with a standard library of plugins (which serves the
|
|
||||||
function of libraries), as well `kjuulh/bust` which is a platform agnostic
|
|
||||||
CI/task setup
|
|
||||||
|
|
||||||
This is in very early stages, and for now it officially supports scaffolding.
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
The `examples` folder shows how to load plugins, though presets are still
|
|
||||||
pending.
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
# file: .char.yml
|
|
||||||
registry: git.front.kjuulh.io
|
|
||||||
plugins:
|
|
||||||
"kjuulh/char#/plugins/gocli":
|
|
||||||
vars:
|
|
||||||
name: "char"
|
|
||||||
```
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
package char
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"log"
|
|
||||||
|
|
||||||
"git.front.kjuulh.io/kjuulh/char/pkg/charcontext"
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
type RequiredArg struct {
|
|
||||||
Required bool
|
|
||||||
Value string
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewDoCommand(charctx *charcontext.CharContext) *cobra.Command {
|
|
||||||
cmd := &cobra.Command{
|
|
||||||
Use: "do",
|
|
||||||
}
|
|
||||||
about, err := charctx.About(context.Background())
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, a := range about {
|
|
||||||
for _, c := range a.Commands {
|
|
||||||
requiredArgs := make(map[string]*RequiredArg, len(c.Args))
|
|
||||||
for _, arg := range c.Args {
|
|
||||||
requiredArgs[arg] = &RequiredArg{
|
|
||||||
Required: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, required := range c.Required {
|
|
||||||
if _, ok := requiredArgs[required]; ok {
|
|
||||||
requiredArg := requiredArgs[required]
|
|
||||||
requiredArg.Required = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
doCmd := &cobra.Command{
|
|
||||||
Use: c.Name,
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
if err := cmd.ParseFlags(args); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := charctx.Do(cmd.Context(), a.ClientName, c.Name, nil); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for argName, argValue := range requiredArgs {
|
|
||||||
doCmd.PersistentFlags().StringVar(&argValue.Value, argName, "", "")
|
|
||||||
if argValue.Required {
|
|
||||||
doCmd.MarkPersistentFlagRequired(argName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.AddCommand(doCmd)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return cmd
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
package char
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
func NewLimitedCharCmd() *cobra.Command {
|
|
||||||
cmd := &cobra.Command{
|
|
||||||
Use: "char",
|
|
||||||
}
|
|
||||||
|
|
||||||
return cmd
|
|
||||||
}
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
package char
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"git.front.kjuulh.io/kjuulh/char/pkg/charcontext"
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
func NewLsCommand(charctx *charcontext.CharContext) *cobra.Command {
|
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
|
||||||
Use: "ls",
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
ctx := cmd.Context()
|
|
||||||
|
|
||||||
about, err := charctx.About(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, a := range about {
|
|
||||||
fmt.Printf("plugin: %s\n", a.Name)
|
|
||||||
fmt.Printf("\tversion: %s\n", a.Version)
|
|
||||||
fmt.Printf("\tabout: %s\n", a.About)
|
|
||||||
if len(a.Vars) > 0 {
|
|
||||||
fmt.Println("\tVars:")
|
|
||||||
for _, av := range a.Vars {
|
|
||||||
fmt.Printf("\t\t%s\n", av)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(a.Commands) > 0 {
|
|
||||||
fmt.Println("\tCommands:")
|
|
||||||
for _, ac := range a.Commands {
|
|
||||||
fmt.Printf("\t\t%s\n", ac.Name)
|
|
||||||
if len(ac.Args) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fmt.Println("\t\tArgs")
|
|
||||||
for _, aca := range ac.Args {
|
|
||||||
isrequired := false
|
|
||||||
for _, acr := range ac.Required {
|
|
||||||
if acr == aca {
|
|
||||||
isrequired = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if isrequired {
|
|
||||||
fmt.Printf("\t\t\t%s: required\n", aca)
|
|
||||||
} else {
|
|
||||||
fmt.Printf("\t\t\t%s\n", aca)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println()
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
return cmd
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
package char
|
|
||||||
|
|
||||||
import (
|
|
||||||
"git.front.kjuulh.io/kjuulh/char/pkg/charcontext"
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
)
|
|
||||||
|
|
||||||
func NewCharCmd(charctx *charcontext.CharContext) *cobra.Command {
|
|
||||||
cmd := &cobra.Command{
|
|
||||||
Use: "char",
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.AddCommand(
|
|
||||||
NewLsCommand(charctx),
|
|
||||||
NewDoCommand(charctx),
|
|
||||||
)
|
|
||||||
|
|
||||||
return cmd
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
registry: git.front.kjuulh.io
|
|
||||||
plugins:
|
|
||||||
"kjuulh/char#plugins/gocli": {}
|
|
||||||
"kjuulh/char#plugins/rust": {}
|
|
||||||
2
examples/basic/.gitignore
vendored
2
examples/basic/.gitignore
vendored
@@ -1,2 +0,0 @@
|
|||||||
.char/plugins/
|
|
||||||
char
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
go build -o char ../../main.go
|
|
||||||
|
|
||||||
function devcharls() {
|
|
||||||
CHAR_DEV_MODE=true ./char ls 2&> /dev/null
|
|
||||||
}
|
|
||||||
|
|
||||||
function charls() {
|
|
||||||
./char ls 2&> /dev/null
|
|
||||||
}
|
|
||||||
|
|
||||||
echo "scratch"
|
|
||||||
time devcharls
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
echo "ready"
|
|
||||||
time charls
|
|
||||||
echo ""
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
go build -o char ../../main.go
|
|
||||||
|
|
||||||
CHAR_DEV_MODE=true ./char ls
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
go build -o char ../../main.go
|
|
||||||
|
|
||||||
echo "base"
|
|
||||||
CHAR_DEV_MODE=true ./char do -h
|
|
||||||
|
|
||||||
echo
|
|
||||||
echo "--------"
|
|
||||||
echo "local_up"
|
|
||||||
CHAR_DEV_MODE=false ./char do local_up --fish something
|
|
||||||
55
examples/service/char.toml
Normal file
55
examples/service/char.toml
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
[char]
|
||||||
|
plan = "plans/base/"
|
||||||
|
dependencies = ["plans/extension"]
|
||||||
|
|
||||||
|
[char.overrides]
|
||||||
|
org = "overrides/org"
|
||||||
|
|
||||||
|
[application]
|
||||||
|
name = "service"
|
||||||
|
|
||||||
|
[config]
|
||||||
|
# provides both local and k8s by default can also be set using:
|
||||||
|
# config.k8s.rabbitmq = true
|
||||||
|
# config.docker-compose.rabbitmq = true
|
||||||
|
rabbitmq = true
|
||||||
|
postgres = true
|
||||||
|
|
||||||
|
[config.org]
|
||||||
|
squad = "kjuulh"
|
||||||
|
domain = "tooling"
|
||||||
|
|
||||||
|
[config.pipeline]
|
||||||
|
path = "char/ci/" # most of these are default, showing them here as a showcase
|
||||||
|
|
||||||
|
[config.actions]
|
||||||
|
path = "char/actions"
|
||||||
|
|
||||||
|
[config.releaser]
|
||||||
|
type = "rust-releaser"
|
||||||
|
|
||||||
|
[config.cargo]
|
||||||
|
crates = ["crates/service_core", "crates/service_util"]
|
||||||
|
|
||||||
|
[config.rust_bin]
|
||||||
|
name = "service"
|
||||||
|
logging = { pretty = true }
|
||||||
|
|
||||||
|
[config.environments.local]
|
||||||
|
type = "docker-compose" # technically default
|
||||||
|
|
||||||
|
[config.environments.local.env]
|
||||||
|
"env" = "local"
|
||||||
|
"db.hostname" = "postgres"
|
||||||
|
"db.secret" = "postgres"
|
||||||
|
|
||||||
|
[config.k8s]
|
||||||
|
monitoring = true
|
||||||
|
|
||||||
|
[config.environments.dev]
|
||||||
|
type = "k8s"
|
||||||
|
|
||||||
|
[config.environments.local.dev]
|
||||||
|
"env" = "local"
|
||||||
|
"db.hostname" = "service-db"
|
||||||
|
"db.secret" = { type = "secret" }
|
||||||
8
examples/service/char/actions/Cargo.toml
Normal file
8
examples/service/char/actions/Cargo.toml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
[package]
|
||||||
|
name = "actions"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
3
examples/service/char/actions/src/main.rs
Normal file
3
examples/service/char/actions/src/main.rs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
fn main() {
|
||||||
|
println!("Hello, world!");
|
||||||
|
}
|
||||||
0
examples/service/char/ci/.gitkeep
Normal file
0
examples/service/char/ci/.gitkeep
Normal file
7
examples/service/char/overrides/org/Cargo.lock
generated
Normal file
7
examples/service/char/overrides/org/Cargo.lock
generated
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "org"
|
||||||
|
version = "0.1.0"
|
||||||
8
examples/service/char/overrides/org/Cargo.toml
Normal file
8
examples/service/char/overrides/org/Cargo.toml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
[package]
|
||||||
|
name = "org"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
0
examples/service/char/overrides/org/char.toml
Normal file
0
examples/service/char/overrides/org/char.toml
Normal file
3
examples/service/char/overrides/org/src/main.rs
Normal file
3
examples/service/char/overrides/org/src/main.rs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
fn main() {
|
||||||
|
println!("Hello, world!");
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"rustc_fingerprint":13769919407148446586,"outputs":{"10376369925670944939":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.dylib\nlib___.dylib\nlib___.a\nlib___.dylib\n/Users/kah/.rustup/toolchains/stable-aarch64-apple-darwin\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_arch=\"aarch64\"\ntarget_endian=\"little\"\ntarget_env=\"\"\ntarget_family=\"unix\"\ntarget_feature=\"aes\"\ntarget_feature=\"crc\"\ntarget_feature=\"dit\"\ntarget_feature=\"dotprod\"\ntarget_feature=\"dpb\"\ntarget_feature=\"dpb2\"\ntarget_feature=\"fcma\"\ntarget_feature=\"fhm\"\ntarget_feature=\"flagm\"\ntarget_feature=\"fp16\"\ntarget_feature=\"frintts\"\ntarget_feature=\"jsconv\"\ntarget_feature=\"lor\"\ntarget_feature=\"lse\"\ntarget_feature=\"neon\"\ntarget_feature=\"paca\"\ntarget_feature=\"pacg\"\ntarget_feature=\"pan\"\ntarget_feature=\"pmuv3\"\ntarget_feature=\"ras\"\ntarget_feature=\"rcpc\"\ntarget_feature=\"rcpc2\"\ntarget_feature=\"rdm\"\ntarget_feature=\"sb\"\ntarget_feature=\"sha2\"\ntarget_feature=\"sha3\"\ntarget_feature=\"ssbs\"\ntarget_feature=\"vh\"\ntarget_has_atomic=\"128\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"macos\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"apple\"\nunix\n","stderr":""},"15697416045686424142":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.dylib\nlib___.dylib\nlib___.a\nlib___.dylib\n","stderr":""},"4614504638168534921":{"success":true,"status":"","code":0,"stdout":"rustc 1.66.0 (69f9c33d7 2022-12-12)\nbinary: rustc\ncommit-hash: 69f9c33d71c871fc16ac445211281c6e7a340943\ncommit-date: 2022-12-12\nhost: aarch64-apple-darwin\nrelease: 1.66.0\nLLVM version: 15.0.2\n","stderr":""}},"successes":{}}
|
||||||
3
examples/service/char/overrides/org/target/CACHEDIR.TAG
Normal file
3
examples/service/char/overrides/org/target/CACHEDIR.TAG
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
Signature: 8a477f597d28d172789f06886806bc55
|
||||||
|
# This file is a cache directory tag created by cargo.
|
||||||
|
# For information about cache directory tags see https://bford.info/cachedir/
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
baa57697ce65b314
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"rustc":15520539443732555526,"features":"[]","target":10808372008975436347,"profile":11736316127369858332,"path":1684066648322511884,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/org-2413d5d1cd4f3ae1/dep-bin-org"}}],"rustflags":[],"metadata":7797948686568424061,"config":2202906307356721367,"compile_kind":0}
|
||||||
Binary file not shown.
@@ -0,0 +1 @@
|
|||||||
|
This file has an mtime of when this was started.
|
||||||
BIN
examples/service/char/overrides/org/target/debug/deps/org-2413d5d1cd4f3ae1
Executable file
BIN
examples/service/char/overrides/org/target/debug/deps/org-2413d5d1cd4f3ae1
Executable file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,5 @@
|
|||||||
|
/Users/kah/git/git.front.kjuulh.io/kjuulh/char/examples/service/char/overrides/org/target/debug/deps/org-2413d5d1cd4f3ae1: src/main.rs
|
||||||
|
|
||||||
|
/Users/kah/git/git.front.kjuulh.io/kjuulh/char/examples/service/char/overrides/org/target/debug/deps/org-2413d5d1cd4f3ae1.d: src/main.rs
|
||||||
|
|
||||||
|
src/main.rs:
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
examples/service/char/overrides/org/target/debug/org
Executable file
BIN
examples/service/char/overrides/org/target/debug/org
Executable file
Binary file not shown.
1
examples/service/char/overrides/org/target/debug/org.d
Normal file
1
examples/service/char/overrides/org/target/debug/org.d
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/Users/kah/git/git.front.kjuulh.io/kjuulh/char/examples/service/char/overrides/org/target/debug/org: /Users/kah/git/git.front.kjuulh.io/kjuulh/char/examples/service/char/overrides/org/src/main.rs
|
||||||
5
examples/service/plans/base/char.toml
Normal file
5
examples/service/plans/base/char.toml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
[char]
|
||||||
|
|
||||||
|
[plan]
|
||||||
|
|
||||||
|
name = "base"
|
||||||
31
go.mod
31
go.mod
@@ -1,31 +0,0 @@
|
|||||||
module git.front.kjuulh.io/kjuulh/char
|
|
||||||
|
|
||||||
go 1.19
|
|
||||||
|
|
||||||
require (
|
|
||||||
github.com/hashicorp/go-hclog v1.5.0
|
|
||||||
github.com/hashicorp/go-plugin v1.4.9
|
|
||||||
github.com/spf13/cobra v1.7.0
|
|
||||||
github.com/stretchr/testify v1.8.2
|
|
||||||
golang.org/x/sync v0.2.0
|
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
|
||||||
)
|
|
||||||
|
|
||||||
require (
|
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
|
||||||
github.com/fatih/color v1.13.0 // indirect
|
|
||||||
github.com/golang/protobuf v1.3.4 // indirect
|
|
||||||
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb // indirect
|
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
|
||||||
github.com/mattn/go-colorable v0.1.12 // indirect
|
|
||||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
|
||||||
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77 // indirect
|
|
||||||
github.com/oklog/run v1.0.0 // indirect
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a // indirect
|
|
||||||
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 // indirect
|
|
||||||
golang.org/x/text v0.3.0 // indirect
|
|
||||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 // indirect
|
|
||||||
google.golang.org/grpc v1.27.1 // indirect
|
|
||||||
)
|
|
||||||
133
go.sum
133
go.sum
@@ -1,133 +0,0 @@
|
|||||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
|
||||||
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
|
|
||||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
|
||||||
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
|
|
||||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
|
||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
|
||||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
|
||||||
github.com/golang/protobuf v1.3.4 h1:87PNWwrRvUSnqS4dlcBU/ftvOIBep4sYuBLlh6rX2wk=
|
|
||||||
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
|
||||||
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
|
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
|
||||||
github.com/hashicorp/go-hclog v0.14.1 h1:nQcJDQwIAGnmoUWp8ubocEX40cCml/17YkF6csQLReU=
|
|
||||||
github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
|
||||||
github.com/hashicorp/go-hclog v1.3.1 h1:vDwF1DFNZhntP4DAjuTpOw3uEgMUpXh1pB5fW9DqHpo=
|
|
||||||
github.com/hashicorp/go-hclog v1.3.1/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
|
|
||||||
github.com/hashicorp/go-hclog v1.4.0 h1:ctuWFGrhFha8BnnzxqeRGidlEcQkDyL5u8J8t5eA11I=
|
|
||||||
github.com/hashicorp/go-hclog v1.4.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
|
|
||||||
github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c=
|
|
||||||
github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
|
|
||||||
github.com/hashicorp/go-plugin v1.4.5 h1:oTE/oQR4eghggRg8VY7PAz3dr++VwDNBGCcOfIvHpBo=
|
|
||||||
github.com/hashicorp/go-plugin v1.4.5/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s=
|
|
||||||
github.com/hashicorp/go-plugin v1.4.6 h1:MDV3UrKQBM3du3G7MApDGvOsMYy3JQJ4exhSoKBAeVA=
|
|
||||||
github.com/hashicorp/go-plugin v1.4.6/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s=
|
|
||||||
github.com/hashicorp/go-plugin v1.4.9 h1:ESiK220/qE0aGxWdzKIvRH69iLiuN/PjoLTm69RoWtU=
|
|
||||||
github.com/hashicorp/go-plugin v1.4.9/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s=
|
|
||||||
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb h1:b5rjCoWHc7eqmAS4/qyk21ZsHyb6Mxv/jykxvNTkU4M=
|
|
||||||
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
|
|
||||||
github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
|
|
||||||
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
|
||||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
|
||||||
github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE=
|
|
||||||
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
|
|
||||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
|
||||||
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
|
||||||
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
|
|
||||||
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
|
||||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
|
||||||
github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10=
|
|
||||||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
|
||||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
|
||||||
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
|
||||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
|
||||||
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77 h1:7GoSOOW2jpsfkntVKaS2rAr1TJqfcxotyaUcuxoZSzg=
|
|
||||||
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
|
||||||
github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=
|
|
||||||
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
|
||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
|
||||||
github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
|
|
||||||
github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
|
|
||||||
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
|
|
||||||
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
|
|
||||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
|
||||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
|
||||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
|
||||||
github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s=
|
|
||||||
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
|
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
|
||||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
|
||||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
|
||||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
|
||||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
|
||||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
|
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
|
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
|
|
||||||
golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be h1:QAcqgptGM8IQBC9K/RC4o+O9YmqEm0diQn9QmZw/0mU=
|
|
||||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 h1:nonptSpoQ4vQjyraW20DXPAglgQfVnM9ZC6MmNLMR60=
|
|
||||||
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
|
||||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
|
||||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
|
||||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
|
||||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
|
||||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE=
|
|
||||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
|
||||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
|
||||||
google.golang.org/grpc v1.27.1 h1:zvIju4sqAGvwKspUQOhwnpcqSbzi7/H6QomNNjTL4sk=
|
|
||||||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
|
||||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
|
||||||
29
main.go
29
main.go
@@ -1,29 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"log"
|
|
||||||
|
|
||||||
"git.front.kjuulh.io/kjuulh/char/cmd/char"
|
|
||||||
"git.front.kjuulh.io/kjuulh/char/pkg/charcontext"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
charctx, err := charcontext.NewCharContext(context.Background())
|
|
||||||
if err != nil {
|
|
||||||
if errors.Is(err, charcontext.ErrNoContextFound) {
|
|
||||||
log.Print("you are not in a char context, as such you will be presented with limited options")
|
|
||||||
if err := char.NewLimitedCharCmd().Execute(); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
defer charctx.Close()
|
|
||||||
|
|
||||||
if err := char.NewCharCmd(charctx).Execute(); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
package charcontext
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"log"
|
|
||||||
|
|
||||||
"git.front.kjuulh.io/kjuulh/char/pkg/plugins/provider"
|
|
||||||
"git.front.kjuulh.io/kjuulh/char/pkg/register"
|
|
||||||
"git.front.kjuulh.io/kjuulh/char/pkg/schema"
|
|
||||||
)
|
|
||||||
|
|
||||||
type CharContext struct {
|
|
||||||
contextPath string
|
|
||||||
pluginRegister *register.PluginRegister
|
|
||||||
schema *schema.CharSchema
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewCharContext(ctx context.Context) (*CharContext, error) {
|
|
||||||
localPath, err := FindLocalRoot(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
gpp := provider.NewGitPluginProvider()
|
|
||||||
|
|
||||||
s, err := schema.ParseFile(ctx, ".char.yml")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
plugins, err := s.GetPlugins(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = gpp.FetchPlugins(ctx, s.Registry, plugins)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
builder := register.NewPluginRegisterBuilder()
|
|
||||||
|
|
||||||
for name, plugin := range plugins {
|
|
||||||
builder = builder.Add(name.Hash(), plugin.Opts.Path)
|
|
||||||
}
|
|
||||||
|
|
||||||
r, err := builder.Build(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &CharContext{
|
|
||||||
contextPath: localPath,
|
|
||||||
pluginRegister: r,
|
|
||||||
schema: s,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cc *CharContext) Close() {
|
|
||||||
if err := cc.pluginRegister.Close(); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cc *CharContext) About(ctx context.Context) ([]register.AboutItem, error) {
|
|
||||||
return cc.pluginRegister.About(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cc *CharContext) Do(ctx context.Context, clientName string, commandName string, args map[string]string) error {
|
|
||||||
return cc.pluginRegister.Do(ctx, clientName, commandName, args)
|
|
||||||
}
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
package charcontext
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
)
|
|
||||||
|
|
||||||
var ErrNoContextFound = errors.New("could not find project root")
|
|
||||||
|
|
||||||
const CharFileName = ".char.yml"
|
|
||||||
|
|
||||||
func FindLocalRoot(ctx context.Context) (string, error) {
|
|
||||||
curdir, err := os.Getwd()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return recursiveFindLocalRoot(ctx, curdir)
|
|
||||||
|
|
||||||
//output, err := exec.Command("git", "rev-parse", "--show-toplevel").CombinedOutput()
|
|
||||||
//if err != nil {
|
|
||||||
// return "", err
|
|
||||||
//}
|
|
||||||
//if len(output) == 0 {
|
|
||||||
// return "", errors.New("could not find absolute path")
|
|
||||||
//}
|
|
||||||
//if _, err := os.Stat(string(output)); errors.Is(err, os.ErrNotExist) {
|
|
||||||
// return "", fmt.Errorf("path does not exist %s", string(output))
|
|
||||||
//}
|
|
||||||
|
|
||||||
//return string(output), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func recursiveFindLocalRoot(ctx context.Context, localpath string) (string, error) {
|
|
||||||
entries, err := os.ReadDir(localpath)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, entry := range entries {
|
|
||||||
if entry.Name() == CharFileName {
|
|
||||||
return localpath, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if localpath == "/" {
|
|
||||||
return "", ErrNoContextFound
|
|
||||||
}
|
|
||||||
|
|
||||||
return recursiveFindLocalRoot(ctx, path.Dir(localpath))
|
|
||||||
}
|
|
||||||
|
|
||||||
func ChangeToPath(_ context.Context, path string) error {
|
|
||||||
return os.Chdir(path)
|
|
||||||
}
|
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
package provider
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"git.front.kjuulh.io/kjuulh/char/pkg/schema"
|
|
||||||
"golang.org/x/sync/errgroup"
|
|
||||||
)
|
|
||||||
|
|
||||||
type GitPluginProvider struct{}
|
|
||||||
|
|
||||||
func NewGitPluginProvider() *GitPluginProvider {
|
|
||||||
return &GitPluginProvider{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gpp *GitPluginProvider) FetchPlugins(ctx context.Context, registry string, plugins schema.CharSchemaPlugins) error {
|
|
||||||
errgroup, ctx := errgroup.WithContext(ctx)
|
|
||||||
baseDir := ".char/plugins"
|
|
||||||
if os.Getenv("CHAR_DEV_MODE") == "true" {
|
|
||||||
if err := os.RemoveAll(baseDir); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := os.MkdirAll(baseDir, 0755); err != nil {
|
|
||||||
return fmt.Errorf("path already exists cannot create: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for n, plugin := range plugins {
|
|
||||||
n, plugin := n, plugin
|
|
||||||
errgroup.Go(func() error {
|
|
||||||
dest := fmt.Sprintf(
|
|
||||||
"%s/%s",
|
|
||||||
strings.TrimRight(baseDir, "/"), n.Hash(),
|
|
||||||
)
|
|
||||||
fileinfo, err := os.Stat(dest)
|
|
||||||
if errors.Is(err, os.ErrNotExist) {
|
|
||||||
log.Printf("fetching git plugin repo: %s", n)
|
|
||||||
return gpp.FetchPlugin(
|
|
||||||
ctx,
|
|
||||||
registry,
|
|
||||||
plugin,
|
|
||||||
dest,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if fileinfo.ModTime().Add(time.Hour * 1).Before(time.Now()) {
|
|
||||||
log.Printf("fetching git plugin repo: %s as it is stale", n)
|
|
||||||
return gpp.FetchPlugin(
|
|
||||||
ctx,
|
|
||||||
registry,
|
|
||||||
plugin,
|
|
||||||
dest,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := errgroup.Wait(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gpp *GitPluginProvider) FetchPlugin(ctx context.Context, registry string, plugin *schema.CharSchemaPlugin, dest string) error {
|
|
||||||
cloneUrl, err := plugin.Opts.GetCloneUrl(
|
|
||||||
ctx,
|
|
||||||
registry,
|
|
||||||
&schema.CloneUrlOpt{
|
|
||||||
Protocol: schema.GitProtocolSsh,
|
|
||||||
SshUser: "git",
|
|
||||||
},
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := os.Stat(dest); !errors.Is(err, os.ErrNotExist) {
|
|
||||||
if err = os.RemoveAll(dest); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
output, err := exec.Command(
|
|
||||||
"git",
|
|
||||||
"clone",
|
|
||||||
"--depth=1",
|
|
||||||
cloneUrl,
|
|
||||||
dest,
|
|
||||||
).CombinedOutput()
|
|
||||||
if len(output) > 0 {
|
|
||||||
log.Print(string(output))
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
package register
|
|
||||||
|
|
||||||
import "context"
|
|
||||||
|
|
||||||
type AboutCommand struct {
|
|
||||||
Name string `json:"name" yaml:"name"`
|
|
||||||
Args []string `json:"args" yaml:"args"`
|
|
||||||
Required []string `json:"required" yaml:"required"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type About struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Version string `json:"version"`
|
|
||||||
About string `json:"about"`
|
|
||||||
Vars []string `json:"vars"`
|
|
||||||
Commands []*AboutCommand `json:"commands"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DoCommand struct {
|
|
||||||
CommandName string `json:"commandName"`
|
|
||||||
Args map[string]string `json:"args"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Plugin interface {
|
|
||||||
About(ctx context.Context) (*About, error)
|
|
||||||
Do(ctx context.Context, cmd *DoCommand) error
|
|
||||||
}
|
|
||||||
|
|
||||||
const PluginKey = "plugin"
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
package register
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/rpc"
|
|
||||||
|
|
||||||
"github.com/hashicorp/go-plugin"
|
|
||||||
)
|
|
||||||
|
|
||||||
type PluginAPI struct {
|
|
||||||
path string
|
|
||||||
Impl Plugin
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pa *PluginAPI) Server(*plugin.MuxBroker) (any, error) {
|
|
||||||
return &PluginServer{Impl: pa.Impl}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*PluginAPI) Client(b *plugin.MuxBroker, c *rpc.Client) (any, error) {
|
|
||||||
return &PluginClient{client: c}, nil
|
|
||||||
}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
package register
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/hashicorp/go-hclog"
|
|
||||||
"github.com/hashicorp/go-plugin"
|
|
||||||
)
|
|
||||||
|
|
||||||
type PluginBuilder struct {
|
|
||||||
serveConfig *plugin.ServeConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewPluginBuilder(p Plugin) *PluginBuilder {
|
|
||||||
logger := hclog.New(&hclog.LoggerOptions{
|
|
||||||
Level: hclog.Debug,
|
|
||||||
Output: os.Stderr,
|
|
||||||
JSONFormat: false,
|
|
||||||
})
|
|
||||||
|
|
||||||
var pluginMap = map[string]plugin.Plugin{
|
|
||||||
PluginKey: &PluginAPI{
|
|
||||||
Impl: p,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
serveConfig := &plugin.ServeConfig{
|
|
||||||
HandshakeConfig: plugin.HandshakeConfig{
|
|
||||||
ProtocolVersion: 1,
|
|
||||||
MagicCookieKey: "BASIC_PLUGIN",
|
|
||||||
MagicCookieValue: "char",
|
|
||||||
},
|
|
||||||
Plugins: pluginMap,
|
|
||||||
Logger: logger,
|
|
||||||
}
|
|
||||||
|
|
||||||
return &PluginBuilder{
|
|
||||||
serveConfig: serveConfig,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pr *PluginBuilder) Serve(ctx context.Context) error {
|
|
||||||
plugin.Serve(
|
|
||||||
pr.serveConfig,
|
|
||||||
)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
package register
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"encoding/json"
|
|
||||||
"net/rpc"
|
|
||||||
)
|
|
||||||
|
|
||||||
type PluginClient struct {
|
|
||||||
client *rpc.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do implements Plugin
|
|
||||||
func (pc *PluginClient) Do(ctx context.Context, cmd *DoCommand) error {
|
|
||||||
err := pc.client.Call("Plugin.Do", cmd, new(string))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ Plugin = &PluginClient{}
|
|
||||||
|
|
||||||
func (pc *PluginClient) About(ctx context.Context) (*About, error) {
|
|
||||||
var resp string
|
|
||||||
err := pc.client.Call("Plugin.About", new(any), &resp)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var about About
|
|
||||||
err = json.Unmarshal([]byte(resp), &about)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &about, nil
|
|
||||||
}
|
|
||||||
@@ -1,248 +0,0 @@
|
|||||||
package register
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/hashicorp/go-hclog"
|
|
||||||
"github.com/hashicorp/go-plugin"
|
|
||||||
"golang.org/x/sync/errgroup"
|
|
||||||
)
|
|
||||||
|
|
||||||
type PluginRegisterBuilder struct {
|
|
||||||
plugins map[string]PluginAPI
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewPluginRegisterBuilder() *PluginRegisterBuilder {
|
|
||||||
return &PluginRegisterBuilder{
|
|
||||||
plugins: make(map[string]PluginAPI),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pr *PluginRegisterBuilder) Add(name, path string) *PluginRegisterBuilder {
|
|
||||||
pr.plugins[name] = PluginAPI{
|
|
||||||
path: path,
|
|
||||||
}
|
|
||||||
|
|
||||||
return pr
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pr *PluginRegisterBuilder) Build(ctx context.Context) (*PluginRegister, error) {
|
|
||||||
clients := make(map[string]*pluginClientWrapper, 0)
|
|
||||||
errgroup, _ := errgroup.WithContext(ctx)
|
|
||||||
|
|
||||||
if err := os.MkdirAll(".char/plugins/", 0755); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for name, p := range pr.plugins {
|
|
||||||
name, p := name, p
|
|
||||||
|
|
||||||
errgroup.Go(func() error {
|
|
||||||
pluginPath := fmt.Sprintf(".char/plugins/%s/dist/plugin", name)
|
|
||||||
|
|
||||||
_, err := os.Stat(pluginPath)
|
|
||||||
if err != nil || os.Getenv("CHAR_DEV_MODE") == "true" {
|
|
||||||
log.Printf("building: %s", name)
|
|
||||||
cmd := exec.Command(
|
|
||||||
"sh",
|
|
||||||
"-c",
|
|
||||||
fmt.Sprintf(
|
|
||||||
"(cd .char/plugins/%s; go build -o dist/plugin %s/main.go)",
|
|
||||||
name,
|
|
||||||
strings.TrimSuffix(
|
|
||||||
strings.TrimSuffix(
|
|
||||||
p.path,
|
|
||||||
"main.go",
|
|
||||||
),
|
|
||||||
"/",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
output, err := cmd.CombinedOutput()
|
|
||||||
if len(output) > 0 {
|
|
||||||
log.Println(string(output))
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("could not build plugin: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client := plugin.NewClient(&plugin.ClientConfig{
|
|
||||||
HandshakeConfig: plugin.HandshakeConfig{
|
|
||||||
ProtocolVersion: 1,
|
|
||||||
MagicCookieKey: "BASIC_PLUGIN",
|
|
||||||
MagicCookieValue: "char",
|
|
||||||
},
|
|
||||||
Logger: hclog.New(&hclog.LoggerOptions{
|
|
||||||
Name: "char",
|
|
||||||
Output: os.Stdout,
|
|
||||||
Level: hclog.Debug,
|
|
||||||
}),
|
|
||||||
Cmd: exec.Command(
|
|
||||||
fmt.Sprintf(
|
|
||||||
".char/plugins/%s/dist/plugin",
|
|
||||||
name,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Plugins: map[string]plugin.Plugin{
|
|
||||||
PluginKey: &p,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
rpcClient, err := client.Client()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
raw, err := rpcClient.Dispense("plugin")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
pluginApi, ok := raw.(Plugin)
|
|
||||||
if !ok {
|
|
||||||
return errors.New("could not cast as plugin")
|
|
||||||
}
|
|
||||||
|
|
||||||
clients[name] = &pluginClientWrapper{
|
|
||||||
plugin: pluginApi,
|
|
||||||
client: client,
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
err := errgroup.Wait()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &PluginRegister{
|
|
||||||
clients: clients,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---
|
|
||||||
|
|
||||||
type pluginClientWrapper struct {
|
|
||||||
plugin Plugin
|
|
||||||
client *plugin.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pcw *pluginClientWrapper) Close() {
|
|
||||||
pcw.client.Kill()
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---
|
|
||||||
|
|
||||||
type PluginRegister struct {
|
|
||||||
clients map[string]*pluginClientWrapper
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pr *PluginRegister) Close() error {
|
|
||||||
errgroup, _ := errgroup.WithContext(context.Background())
|
|
||||||
|
|
||||||
for _, c := range pr.clients {
|
|
||||||
c := c
|
|
||||||
|
|
||||||
errgroup.Go(func() error {
|
|
||||||
c.Close()
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := errgroup.Wait(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type CommandAboutItem struct {
|
|
||||||
Name string
|
|
||||||
Args []string
|
|
||||||
Required []string
|
|
||||||
}
|
|
||||||
|
|
||||||
type CommandAboutItems []*CommandAboutItem
|
|
||||||
|
|
||||||
func FromAboutCommands(commands []*AboutCommand) CommandAboutItems {
|
|
||||||
cai := make(CommandAboutItems, 0)
|
|
||||||
for _, command := range commands {
|
|
||||||
cai = append(cai, &CommandAboutItem{
|
|
||||||
Name: command.Name,
|
|
||||||
Args: command.Args,
|
|
||||||
Required: command.Required,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return cai
|
|
||||||
}
|
|
||||||
|
|
||||||
type AboutItem struct {
|
|
||||||
Name string
|
|
||||||
Version string
|
|
||||||
About string
|
|
||||||
Vars []string
|
|
||||||
Commands CommandAboutItems
|
|
||||||
ClientName string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pr *PluginRegister) About(ctx context.Context) ([]AboutItem, error) {
|
|
||||||
list := make([]AboutItem, 0)
|
|
||||||
|
|
||||||
errgroup, ctx := errgroup.WithContext(ctx)
|
|
||||||
|
|
||||||
for name, c := range pr.clients {
|
|
||||||
name, c := name, c
|
|
||||||
errgroup.Go(func() error {
|
|
||||||
about, err := c.plugin.About(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
list = append(list, AboutItem{
|
|
||||||
Name: about.Name,
|
|
||||||
Version: about.Version,
|
|
||||||
About: about.About,
|
|
||||||
Vars: about.Vars,
|
|
||||||
Commands: FromAboutCommands(about.Commands),
|
|
||||||
ClientName: name,
|
|
||||||
})
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := errgroup.Wait(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return list, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pr *PluginRegister) Do(ctx context.Context, clientName string, commandName string, args map[string]string) error {
|
|
||||||
errgroup, ctx := errgroup.WithContext(ctx)
|
|
||||||
|
|
||||||
client, ok := pr.clients[clientName]
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("plugin was not found: %s", clientName)
|
|
||||||
}
|
|
||||||
|
|
||||||
errgroup.Go(func() error {
|
|
||||||
return client.plugin.Do(ctx, &DoCommand{
|
|
||||||
CommandName: commandName,
|
|
||||||
Args: args,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
if err := errgroup.Wait(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
package register
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"encoding/json"
|
|
||||||
)
|
|
||||||
|
|
||||||
type PluginServer struct {
|
|
||||||
Impl Plugin
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ps *PluginServer) Do(args *DoCommand, resp *string) error {
|
|
||||||
//rawReq, ok := args.(string)
|
|
||||||
//if !ok {
|
|
||||||
// return errors.New("args is not a string")
|
|
||||||
//}
|
|
||||||
|
|
||||||
//var doReq DoRequest
|
|
||||||
//if err := json.Unmarshal([]byte(rawReq), &doReq); err != nil {
|
|
||||||
// return err
|
|
||||||
//}
|
|
||||||
|
|
||||||
if err := ps.Impl.Do(context.Background(), args); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
*resp = ""
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ps *PluginServer) About(args any, resp *string) error {
|
|
||||||
r, err := ps.Impl.About(context.Background())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
respB, err := json.Marshal(r)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
*resp = string(respB)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
package schema
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"gopkg.in/yaml.v3"
|
|
||||||
)
|
|
||||||
|
|
||||||
type CharSchema struct {
|
|
||||||
Registry string `json:"registry" yaml:"registry"`
|
|
||||||
Plugins CharSchemaPlugins `json:"plugins" yaml:"plugins"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func ParseFile(ctx context.Context, path string) (*CharSchema, error) {
|
|
||||||
if _, err := os.Stat(path); errors.Is(err, os.ErrNotExist) {
|
|
||||||
return nil, fmt.Errorf("could not parse file, as it is not found or permitted: %s", path)
|
|
||||||
}
|
|
||||||
|
|
||||||
file, err := os.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("could not read file: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return Parse(file)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Parse(content []byte) (*CharSchema, error) {
|
|
||||||
var schema CharSchema
|
|
||||||
if err := yaml.Unmarshal(content, &schema); err != nil {
|
|
||||||
return nil, fmt.Errorf("could not deserialize yaml into CharSchema: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &schema, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cs *CharSchema) GetPlugins(ctx context.Context) (CharSchemaPlugins, error) {
|
|
||||||
plugins := make(map[CharSchemaPluginName]*CharSchemaPlugin, len(cs.Plugins))
|
|
||||||
for n, plugin := range cs.Plugins {
|
|
||||||
po, err := n.Get()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
plugin.Opts = po
|
|
||||||
plugins[n] = plugin
|
|
||||||
}
|
|
||||||
return plugins, nil
|
|
||||||
}
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
package schema
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"crypto/sha256"
|
|
||||||
"encoding/hex"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type CharSchemaPluginName string
|
|
||||||
|
|
||||||
func (cspn CharSchemaPluginName) Hash() string {
|
|
||||||
bytes := sha256.Sum256([]byte(cspn))
|
|
||||||
return hex.EncodeToString(bytes[:])
|
|
||||||
}
|
|
||||||
|
|
||||||
type PluginOps struct {
|
|
||||||
Org string
|
|
||||||
RepositoryName string
|
|
||||||
Path string
|
|
||||||
Version string
|
|
||||||
}
|
|
||||||
|
|
||||||
type GitProtocol string
|
|
||||||
|
|
||||||
const (
|
|
||||||
GitProtocolHttps GitProtocol = "https"
|
|
||||||
GitProtocolSsh = "ssh"
|
|
||||||
)
|
|
||||||
|
|
||||||
type CloneUrlOpt struct {
|
|
||||||
Protocol GitProtocol
|
|
||||||
SshUser string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (po *PluginOps) GetCloneUrl(ctx context.Context, registry string, opt *CloneUrlOpt) (string, error) {
|
|
||||||
if opt == nil {
|
|
||||||
return "", errors.New("opt is required")
|
|
||||||
}
|
|
||||||
switch opt.Protocol {
|
|
||||||
case GitProtocolHttps:
|
|
||||||
return fmt.Sprintf("https://%s/%s/%s.git", registry, po.Org, po.RepositoryName), nil
|
|
||||||
case GitProtocolSsh:
|
|
||||||
return fmt.Sprintf("%s@%s:%s/%s.git", opt.SshUser, registry, po.Org, po.RepositoryName), nil
|
|
||||||
default:
|
|
||||||
return "", errors.New("protocol not allowed")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var memo = map[string]*PluginOps{}
|
|
||||||
|
|
||||||
func (cspn CharSchemaPluginName) Get() (*PluginOps, error) {
|
|
||||||
if m, ok := memo[string(cspn)]; ok {
|
|
||||||
return m, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
po := &PluginOps{}
|
|
||||||
reg := regexp.MustCompile(
|
|
||||||
`(?P<org>[\d\w\-_\.]+)\/(?P<repo>[\d\w\-_\.]+)(?P<path>#[\d\w\-_\.\/]+)?(?P<version>@[\d\w\-_\.\/]+)?(?P<path>#[\d\w\-_\.\/]+)?`,
|
|
||||||
)
|
|
||||||
matches := reg.FindStringSubmatch(string(cspn))
|
|
||||||
tags := reg.SubexpNames()
|
|
||||||
|
|
||||||
matchTags := make(map[string]string, len(matches))
|
|
||||||
for i, match := range matches {
|
|
||||||
tag := tags[i]
|
|
||||||
if existingTag, ok := matchTags[tag]; !ok || existingTag == "" {
|
|
||||||
matchTags[tag] = match
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if org, ok := matchTags["org"]; ok {
|
|
||||||
po.Org = org
|
|
||||||
}
|
|
||||||
if repo, ok := matchTags["repo"]; ok {
|
|
||||||
po.RepositoryName = repo
|
|
||||||
}
|
|
||||||
if path, ok := matchTags["path"]; ok {
|
|
||||||
po.Path = strings.TrimLeft(path, "#")
|
|
||||||
}
|
|
||||||
if version, ok := matchTags["version"]; ok {
|
|
||||||
po.Version = strings.TrimLeft(version, "@")
|
|
||||||
}
|
|
||||||
|
|
||||||
if po.Org == "" || po.RepositoryName == "" {
|
|
||||||
return nil, errors.New("could not find org or repository name")
|
|
||||||
}
|
|
||||||
|
|
||||||
memo[string(cspn)] = po
|
|
||||||
|
|
||||||
return po, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type CharSchemaPlugins map[CharSchemaPluginName]*CharSchemaPlugin
|
|
||||||
type CharSchemaPluginVarName string
|
|
||||||
type CharSchemaPluginVars map[CharSchemaPluginVarName]string
|
|
||||||
|
|
||||||
type CharSchemaPlugin struct {
|
|
||||||
Opts *PluginOps
|
|
||||||
Vars CharSchemaPluginVars `json:"vars"`
|
|
||||||
}
|
|
||||||
@@ -1,126 +0,0 @@
|
|||||||
package schema_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"git.front.kjuulh.io/kjuulh/char/pkg/schema"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestSchemaNameCanParse(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
tt := []struct {
|
|
||||||
name string
|
|
||||||
inputString schema.CharSchemaPluginName
|
|
||||||
expected schema.PluginOps
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "default string",
|
|
||||||
inputString: `kju123K_-ulh/someRepo-._123`,
|
|
||||||
expected: schema.PluginOps{
|
|
||||||
Org: "kju123K_-ulh",
|
|
||||||
RepositoryName: "someRepo-._123",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "default string with path",
|
|
||||||
inputString: `kju123K_-ulh/someRepo-._123#somepath/sometoherpath/somethridpath`,
|
|
||||||
expected: schema.PluginOps{
|
|
||||||
Org: "kju123K_-ulh",
|
|
||||||
RepositoryName: "someRepo-._123",
|
|
||||||
Path: "somepath/sometoherpath/somethridpath",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "default string with version",
|
|
||||||
inputString: `kju123K_-ulh/someRepo-._123@12l3.jk1lj`,
|
|
||||||
expected: schema.PluginOps{
|
|
||||||
Org: "kju123K_-ulh",
|
|
||||||
RepositoryName: "someRepo-._123",
|
|
||||||
Version: "12l3.jk1lj",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "default string with version and path",
|
|
||||||
inputString: `kju123K_-ulh/someRepo-._123@12l3.jk1lj#somepath/sometoherpath/somethridpath`,
|
|
||||||
expected: schema.PluginOps{
|
|
||||||
Org: "kju123K_-ulh",
|
|
||||||
RepositoryName: "someRepo-._123",
|
|
||||||
Version: "12l3.jk1lj",
|
|
||||||
Path: "somepath/sometoherpath/somethridpath",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "default string with path and version",
|
|
||||||
inputString: `kju123K_-ulh/someRepo-._123#somepath/sometoherpath/somethridpath@12l3.jk1lj`,
|
|
||||||
expected: schema.PluginOps{
|
|
||||||
Org: "kju123K_-ulh",
|
|
||||||
RepositoryName: "someRepo-._123",
|
|
||||||
Version: "12l3.jk1lj",
|
|
||||||
Path: "somepath/sometoherpath/somethridpath",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tc := range tt {
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
|
||||||
actual, _ := tc.inputString.Get()
|
|
||||||
require.Equal(t, tc.expected, *actual)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPluginOpt(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
tt := []struct {
|
|
||||||
name string
|
|
||||||
pluginOpt schema.PluginOps
|
|
||||||
cloneUrlOpt schema.CloneUrlOpt
|
|
||||||
registry string
|
|
||||||
expected string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "ssh values",
|
|
||||||
pluginOpt: schema.PluginOps{
|
|
||||||
Org: "kjuulh",
|
|
||||||
RepositoryName: "char",
|
|
||||||
Path: "",
|
|
||||||
Version: "",
|
|
||||||
},
|
|
||||||
cloneUrlOpt: schema.CloneUrlOpt{
|
|
||||||
Protocol: schema.GitProtocolSsh,
|
|
||||||
SshUser: "git",
|
|
||||||
},
|
|
||||||
registry: "git.front.kjuulh.io",
|
|
||||||
expected: "git@git.front.kjuulh.io:kjuulh/char.git",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "https values",
|
|
||||||
pluginOpt: schema.PluginOps{
|
|
||||||
Org: "kjuulh",
|
|
||||||
RepositoryName: "char",
|
|
||||||
Path: "",
|
|
||||||
Version: "",
|
|
||||||
},
|
|
||||||
cloneUrlOpt: schema.CloneUrlOpt{
|
|
||||||
Protocol: schema.GitProtocolHttps,
|
|
||||||
},
|
|
||||||
registry: "git.front.kjuulh.io",
|
|
||||||
expected: "https://git.front.kjuulh.io/kjuulh/char.git",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tc := range tt {
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
|
||||||
url, err := tc.pluginOpt.GetCloneUrl(context.Background(), tc.registry, &tc.cloneUrlOpt)
|
|
||||||
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.Equal(t, tc.expected, url)
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
package schema_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"git.front.kjuulh.io/kjuulh/char/pkg/schema"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestSchemaParse(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
tt := []struct {
|
|
||||||
name string
|
|
||||||
input string
|
|
||||||
expected *schema.CharSchema
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "with plugins",
|
|
||||||
input: `
|
|
||||||
registry: git.front.kjuulh.io
|
|
||||||
plugins:
|
|
||||||
"kjuulh/char#plugins/gocli": {}
|
|
||||||
"kjuulh/char#plugins/rust": {}
|
|
||||||
`,
|
|
||||||
expected: &schema.CharSchema{
|
|
||||||
Registry: "git.front.kjuulh.io",
|
|
||||||
Plugins: map[schema.CharSchemaPluginName]*schema.CharSchemaPlugin{
|
|
||||||
"kjuulh/char#plugins/gocli": {},
|
|
||||||
"kjuulh/char#plugins/rust": {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tc := range tt {
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
|
||||||
s, err := schema.Parse([]byte(tc.input))
|
|
||||||
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.Equal(t, tc.expected, s)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetPlugins(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
tt := []struct {
|
|
||||||
name string
|
|
||||||
input string
|
|
||||||
expected schema.CharSchemaPlugins
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "with plugins",
|
|
||||||
input: `
|
|
||||||
registry: git.front.kjuulh.io
|
|
||||||
plugins:
|
|
||||||
"kjuulh/char#plugins/gocli@v1.9.0": {}
|
|
||||||
"kjuulh/char#plugins/rust": {}
|
|
||||||
`,
|
|
||||||
expected: map[schema.CharSchemaPluginName]*schema.CharSchemaPlugin{
|
|
||||||
"kjuulh/char#plugins/gocli@v1.9.0": {
|
|
||||||
Opts: &schema.PluginOps{
|
|
||||||
Org: "kjuulh",
|
|
||||||
RepositoryName: "char",
|
|
||||||
Path: "plugins/gocli",
|
|
||||||
Version: "v1.9.0",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"kjuulh/char#plugins/rust": {
|
|
||||||
Opts: &schema.PluginOps{
|
|
||||||
Org: "kjuulh",
|
|
||||||
RepositoryName: "char",
|
|
||||||
Path: "plugins/rust",
|
|
||||||
Version: "",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tc := range tt {
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
|
||||||
s, err := schema.Parse([]byte(tc.input))
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
plugins, err := s.GetPlugins(context.Background())
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
require.Equal(t, tc.expected, plugins)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"log"
|
|
||||||
|
|
||||||
"git.front.kjuulh.io/kjuulh/char/pkg/register"
|
|
||||||
"github.com/hashicorp/go-hclog"
|
|
||||||
)
|
|
||||||
|
|
||||||
type GoCliPlugin struct{}
|
|
||||||
|
|
||||||
// Do implements register.Plugin
|
|
||||||
func (*GoCliPlugin) Do(ctx context.Context, cmd *register.DoCommand) error {
|
|
||||||
hclog.L().Info("received command", "commandName", cmd.CommandName)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*GoCliPlugin) About(ctx context.Context) (*register.About, error) {
|
|
||||||
return ®ister.About{
|
|
||||||
Name: "gocli",
|
|
||||||
Version: "v0.0.1",
|
|
||||||
About: "golang cli provides a set of actions and presets supporting golang development",
|
|
||||||
Vars: []string{
|
|
||||||
"dev.mode",
|
|
||||||
},
|
|
||||||
Commands: []*register.AboutCommand{
|
|
||||||
{
|
|
||||||
Name: "local_up",
|
|
||||||
Args: []string{"fish"},
|
|
||||||
Required: []string{"fish"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ register.Plugin = &GoCliPlugin{}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if err := register.
|
|
||||||
NewPluginBuilder(
|
|
||||||
&GoCliPlugin{},
|
|
||||||
).
|
|
||||||
Serve(context.Background()); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"log"
|
|
||||||
|
|
||||||
"git.front.kjuulh.io/kjuulh/char/pkg/register"
|
|
||||||
"github.com/hashicorp/go-hclog"
|
|
||||||
)
|
|
||||||
|
|
||||||
type GoCliPlugin struct{}
|
|
||||||
|
|
||||||
// Do implements register.Plugin
|
|
||||||
func (*GoCliPlugin) Do(ctx context.Context, cmd *register.DoCommand) error {
|
|
||||||
hclog.L().Info("received command", "commandName", cmd.CommandName)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*GoCliPlugin) About(ctx context.Context) (*register.About, error) {
|
|
||||||
return ®ister.About{
|
|
||||||
Name: "rust",
|
|
||||||
Version: "v0.0.1",
|
|
||||||
About: "rust cli provides a set of actions and presets supporting rust development",
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ register.Plugin = &GoCliPlugin{}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if err := register.
|
|
||||||
NewPluginBuilder(
|
|
||||||
&GoCliPlugin{},
|
|
||||||
).
|
|
||||||
Serve(context.Background()); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json"
|
|
||||||
}
|
|
||||||
44
src/cli.rs
Normal file
44
src/cli.rs
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
deps,
|
||||||
|
resolvers::{install, Resolver},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct Cli {
|
||||||
|
deps: deps::Deps,
|
||||||
|
install: Box<dyn Resolver + Send + Sync>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Cli {
|
||||||
|
pub fn new(deps: deps::Deps) -> eyre::Result<Self> {
|
||||||
|
Ok(Self {
|
||||||
|
deps: deps.clone(),
|
||||||
|
install: install::Install::new(deps),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn matches(self, args: &[&str]) -> eyre::Result<()> {
|
||||||
|
let mut cli = clap::Command::new("char")
|
||||||
|
.arg(clap::Arg::new("path").long("path").short('p'))
|
||||||
|
.subcommand(self.install.cmd()?);
|
||||||
|
|
||||||
|
let matches = cli.clone().get_matches_from(args);
|
||||||
|
|
||||||
|
let path = matches.get_one::<String>("path");
|
||||||
|
if let Some(p) = path {
|
||||||
|
let path = PathBuf::from(p);
|
||||||
|
if !path.exists() {
|
||||||
|
eyre::bail!("no char.toml exists at --path")
|
||||||
|
}
|
||||||
|
self.deps.parser.set_path(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
match matches.subcommand() {
|
||||||
|
Some(("install", args)) => self.install.matches(args)?,
|
||||||
|
_ => cli.print_help()?,
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
29
src/context/mod.rs
Normal file
29
src/context/mod.rs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
use crate::models::Char;
|
||||||
|
|
||||||
|
pub struct Context {}
|
||||||
|
|
||||||
|
impl Context {
|
||||||
|
pub fn new(chars: Vec<Char>) -> Self {
|
||||||
|
Self {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ContextBuilder {
|
||||||
|
chars: Vec<Char>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ContextBuilder {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self { chars: vec![] }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_char(mut self, char: &Char) -> Self {
|
||||||
|
self.chars.push(char.clone());
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(self) -> Context {
|
||||||
|
Context::new(self.chars)
|
||||||
|
}
|
||||||
|
}
|
||||||
33
src/deps.rs
Normal file
33
src/deps.rs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
use std::{ops::Deref, sync::Arc};
|
||||||
|
|
||||||
|
use crate::{parser::Parser, services::downloader::Downloader};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Deps {
|
||||||
|
inner: Arc<InnerDeps>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct InnerDeps {
|
||||||
|
pub parser: Parser,
|
||||||
|
pub downloader: Downloader,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Deps {
|
||||||
|
fn default() -> Self {
|
||||||
|
let parser = Parser::default();
|
||||||
|
let downloader = Downloader::new(parser.clone());
|
||||||
|
|
||||||
|
Self {
|
||||||
|
inner: Arc::new(InnerDeps { parser, downloader }),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for Deps {
|
||||||
|
type Target = Arc<InnerDeps>;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.inner
|
||||||
|
}
|
||||||
|
}
|
||||||
32
src/main.rs
Normal file
32
src/main.rs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
pub mod cli;
|
||||||
|
mod deps;
|
||||||
|
mod models;
|
||||||
|
mod parser;
|
||||||
|
mod resolvers;
|
||||||
|
mod services;
|
||||||
|
mod context;
|
||||||
|
|
||||||
|
fn main() -> eyre::Result<()> {
|
||||||
|
color_eyre::install()?;
|
||||||
|
|
||||||
|
let args = std::env::args();
|
||||||
|
|
||||||
|
let deps = deps::Deps::default();
|
||||||
|
|
||||||
|
let c = cli::Cli::new(deps)?;
|
||||||
|
c.matches(
|
||||||
|
args.collect::<Vec<String>>()
|
||||||
|
.iter()
|
||||||
|
.map(|s| s.as_str())
|
||||||
|
.collect::<Vec<&str>>()
|
||||||
|
.as_slice(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let p = std::path::PathBuf::from("examples/service/char.toml");
|
||||||
|
|
||||||
|
let char = std::fs::read_to_string(p)?.parse::<models::Char>()?;
|
||||||
|
|
||||||
|
dbg!(char);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
48
src/models.rs
Normal file
48
src/models.rs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
type Overrides = BTreeMap<String, String>;
|
||||||
|
type Dependencies = Vec<String>;
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
pub struct Conf {
|
||||||
|
pub plan: String,
|
||||||
|
pub dependencies: Option<Dependencies>,
|
||||||
|
pub overrides: Option<Overrides>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
pub struct Application {
|
||||||
|
name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
pub struct Plan {
|
||||||
|
name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum Char {
|
||||||
|
Application {
|
||||||
|
char: Option<Conf>,
|
||||||
|
application: Application,
|
||||||
|
config: BTreeMap<String, toml::Value>,
|
||||||
|
},
|
||||||
|
Plan {
|
||||||
|
char: Option<Conf>,
|
||||||
|
plan: Plan,
|
||||||
|
config: BTreeMap<String, toml::Value>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::str::FromStr for Char {
|
||||||
|
type Err = eyre::Error;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
let t: Char = toml::from_str(s)?;
|
||||||
|
|
||||||
|
Ok(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
62
src/parser.rs
Normal file
62
src/parser.rs
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
use std::{
|
||||||
|
path::PathBuf,
|
||||||
|
sync::{Arc, RwLock},
|
||||||
|
};
|
||||||
|
|
||||||
|
use eyre::Context;
|
||||||
|
|
||||||
|
use crate::models::{self, Char};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Parser {
|
||||||
|
path: Arc<RwLock<Option<PathBuf>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Parser {
|
||||||
|
pub fn new(path: PathBuf) -> Self {
|
||||||
|
Self {
|
||||||
|
path: Arc::new(RwLock::new(Some(path))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_path(&self, path: PathBuf) {
|
||||||
|
let mut writer = self.path.write().unwrap();
|
||||||
|
*writer = Some(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_path(&self) -> eyre::Result<PathBuf> {
|
||||||
|
let read_path = self.path.read().unwrap();
|
||||||
|
let path = match read_path.clone() {
|
||||||
|
Some(p) => p,
|
||||||
|
None => todo!(), // find using git later on
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse(&self) -> eyre::Result<models::Char> {
|
||||||
|
let mut path = self.get_path()?;
|
||||||
|
if !path.ends_with("char.toml") {
|
||||||
|
path.push("char.toml")
|
||||||
|
}
|
||||||
|
let contents =
|
||||||
|
std::fs::read_to_string(&path).context("char.toml doesn't exist at that path")?;
|
||||||
|
|
||||||
|
contents.parse::<Char>()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_from(&self, path: &PathBuf) -> eyre::Result<models::Char> {
|
||||||
|
let contents =
|
||||||
|
std::fs::read_to_string(path).context("char.toml doesn't exist at that path")?;
|
||||||
|
|
||||||
|
contents.parse::<Char>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Parser {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
path: Arc::new(RwLock::new(None)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
29
src/resolvers/install.rs
Normal file
29
src/resolvers/install.rs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
use crate::deps;
|
||||||
|
|
||||||
|
use super::{DynResolver, Resolver};
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Install {
|
||||||
|
deps: deps::Deps,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Install {
|
||||||
|
pub fn new(deps: deps::Deps) -> DynResolver {
|
||||||
|
Box::new(Self { deps })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Resolver for Install {
|
||||||
|
fn cmd(&self) -> eyre::Result<clap::Command> {
|
||||||
|
let install = clap::Command::new("install");
|
||||||
|
|
||||||
|
Ok(install)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn matches(&self, _args: &clap::ArgMatches) -> eyre::Result<()> {
|
||||||
|
self.deps.downloader.download()?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
8
src/resolvers/mod.rs
Normal file
8
src/resolvers/mod.rs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
pub(crate) mod install;
|
||||||
|
|
||||||
|
pub trait Resolver {
|
||||||
|
fn cmd(&self) -> eyre::Result<clap::Command>;
|
||||||
|
fn matches(&self, args: &clap::ArgMatches) -> eyre::Result<()>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type DynResolver = Box<dyn Resolver + Send + Sync>;
|
||||||
96
src/services/downloader.rs
Normal file
96
src/services/downloader.rs
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
use std::{fs::canonicalize, path::PathBuf};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
context::{Context, ContextBuilder},
|
||||||
|
models::{Char, Conf},
|
||||||
|
parser::Parser,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Downloader {
|
||||||
|
parser: Parser,
|
||||||
|
}
|
||||||
|
#[allow(dead_code)]
|
||||||
|
impl Downloader {
|
||||||
|
pub fn new(parser: Parser) -> Self {
|
||||||
|
Self { parser }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Unfolds char
|
||||||
|
/// 1. Download path
|
||||||
|
/// 2. Parse char in downloaded path
|
||||||
|
/// 3. Repeat from 1. until there are no more parents
|
||||||
|
pub fn download(&self) -> eyre::Result<Context> {
|
||||||
|
let mut context_builder = ContextBuilder::new();
|
||||||
|
|
||||||
|
let char = self.parser.parse()?;
|
||||||
|
context_builder = context_builder.add_char(&char);
|
||||||
|
let first_char_path = self.parser.get_path()?;
|
||||||
|
|
||||||
|
let mut root = std::env::current_dir()?;
|
||||||
|
root = root.join(&first_char_path);
|
||||||
|
root.push(".char");
|
||||||
|
let output = self.create_output_dir(&root)?;
|
||||||
|
|
||||||
|
let mut parent_char = char;
|
||||||
|
let path = first_char_path;
|
||||||
|
loop {
|
||||||
|
parent_char = match &parent_char {
|
||||||
|
Char::Application {
|
||||||
|
char,
|
||||||
|
application: _,
|
||||||
|
config: _,
|
||||||
|
} => match char {
|
||||||
|
Some(c) => self.download_plan(c, &path, &output)?,
|
||||||
|
None => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Char::Plan {
|
||||||
|
char,
|
||||||
|
plan: _,
|
||||||
|
config: _,
|
||||||
|
} => match char {
|
||||||
|
Some(_c) => todo!(),
|
||||||
|
None => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(context_builder.build())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn download_plan(
|
||||||
|
&self,
|
||||||
|
conf: &Conf,
|
||||||
|
path: &PathBuf,
|
||||||
|
output_path: &PathBuf,
|
||||||
|
) -> eyre::Result<Char> {
|
||||||
|
let plan = &conf.plan;
|
||||||
|
|
||||||
|
// TODO: decide whether it is a file or a git repo
|
||||||
|
// TODO: Starting with files only, as such implement git repo later
|
||||||
|
|
||||||
|
let path_buf = std::path::PathBuf::from(plan);
|
||||||
|
let path = path.join(path_buf);
|
||||||
|
if !path.exists() {
|
||||||
|
eyre::bail!("path doesn't exist: {}", path.to_string_lossy())
|
||||||
|
}
|
||||||
|
let path = canonicalize(path)?;
|
||||||
|
|
||||||
|
dbg!(path);
|
||||||
|
dbg!(output_path);
|
||||||
|
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_output_dir(&self, root: &PathBuf) -> eyre::Result<PathBuf> {
|
||||||
|
let mut output = root.clone();
|
||||||
|
output.push("plans");
|
||||||
|
std::fs::create_dir_all(&output)?;
|
||||||
|
|
||||||
|
Ok(output)
|
||||||
|
}
|
||||||
|
}
|
||||||
1
src/services/mod.rs
Normal file
1
src/services/mod.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
pub mod downloader;
|
||||||
Reference in New Issue
Block a user