init
This commit is contained in:
commit
c4f493966a
5 changed files with 893 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/target
|
482
Cargo.lock
generated
Normal file
482
Cargo.lock
generated
Normal file
|
@ -0,0 +1,482 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aho-corasick"
|
||||||
|
version = "1.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstream"
|
||||||
|
version = "0.6.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"anstyle-parse",
|
||||||
|
"anstyle-query",
|
||||||
|
"anstyle-wincon",
|
||||||
|
"colorchoice",
|
||||||
|
"utf8parse",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle"
|
||||||
|
version = "1.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-parse"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140"
|
||||||
|
dependencies = [
|
||||||
|
"utf8parse",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-query"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-wincon"
|
||||||
|
version = "3.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"windows-sys 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap"
|
||||||
|
version = "4.4.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b"
|
||||||
|
dependencies = [
|
||||||
|
"clap_builder",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_builder"
|
||||||
|
version = "4.4.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663"
|
||||||
|
dependencies = [
|
||||||
|
"anstream",
|
||||||
|
"anstyle",
|
||||||
|
"clap_lex",
|
||||||
|
"strsim",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_lex"
|
||||||
|
version = "0.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "colorchoice"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "console"
|
||||||
|
version = "0.15.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8"
|
||||||
|
dependencies = [
|
||||||
|
"encode_unicode",
|
||||||
|
"lazy_static",
|
||||||
|
"libc",
|
||||||
|
"unicode-width",
|
||||||
|
"windows-sys 0.45.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "encode_unicode"
|
||||||
|
version = "0.3.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "equivalent"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.14.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indexmap"
|
||||||
|
version = "2.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897"
|
||||||
|
dependencies = [
|
||||||
|
"equivalent",
|
||||||
|
"hashbrown",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itoa"
|
||||||
|
version = "1.0.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "json-patch"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "55ff1e1486799e3f64129f8ccad108b38290df9cd7015cd31bed17239f0789d6"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"thiserror",
|
||||||
|
"treediff",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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.149"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mdpatch"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"clap",
|
||||||
|
"console",
|
||||||
|
"json-patch",
|
||||||
|
"regex",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"serde_yaml",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.6.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.69"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.33"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex"
|
||||||
|
version = "1.10.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-automata",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-automata"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-syntax"
|
||||||
|
version = "0.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ryu"
|
||||||
|
version = "1.0.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.190"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.190"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_json"
|
||||||
|
version = "1.0.108"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b"
|
||||||
|
dependencies = [
|
||||||
|
"itoa",
|
||||||
|
"ryu",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_yaml"
|
||||||
|
version = "0.9.27"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3cc7a1570e38322cfe4154732e5110f887ea57e22b76f4bfd32b5bdd3368666c"
|
||||||
|
dependencies = [
|
||||||
|
"indexmap",
|
||||||
|
"itoa",
|
||||||
|
"ryu",
|
||||||
|
"serde",
|
||||||
|
"unsafe-libyaml",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strsim"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.38"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "1.0.50"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "1.0.50"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "treediff"
|
||||||
|
version = "4.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "52984d277bdf2a751072b5df30ec0377febdb02f7696d64c2d7d54630bac4303"
|
||||||
|
dependencies = [
|
||||||
|
"serde_json",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-width"
|
||||||
|
version = "0.1.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unsafe-libyaml"
|
||||||
|
version = "0.2.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f28467d3e1d3c6586d8f25fa243f544f5800fec42d97032474e17222c2b75cfa"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "utf8parse"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.45.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets 0.42.2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.48.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets 0.48.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.42.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm 0.42.2",
|
||||||
|
"windows_aarch64_msvc 0.42.2",
|
||||||
|
"windows_i686_gnu 0.42.2",
|
||||||
|
"windows_i686_msvc 0.42.2",
|
||||||
|
"windows_x86_64_gnu 0.42.2",
|
||||||
|
"windows_x86_64_gnullvm 0.42.2",
|
||||||
|
"windows_x86_64_msvc 0.42.2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm 0.48.5",
|
||||||
|
"windows_aarch64_msvc 0.48.5",
|
||||||
|
"windows_i686_gnu 0.48.5",
|
||||||
|
"windows_i686_msvc 0.48.5",
|
||||||
|
"windows_x86_64_gnu 0.48.5",
|
||||||
|
"windows_x86_64_gnullvm 0.48.5",
|
||||||
|
"windows_x86_64_msvc 0.48.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.42.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.42.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.42.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.42.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.42.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.42.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.42.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
19
Cargo.toml
Normal file
19
Cargo.toml
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
[package]
|
||||||
|
name = "mdpatch"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
strip = true
|
||||||
|
lto = true
|
||||||
|
codegen-units = 1
|
||||||
|
panic = "abort"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
clap = { version = "4.4.7", features = ["cargo"] }
|
||||||
|
console = "0.15.7"
|
||||||
|
json-patch = "1.2.0"
|
||||||
|
regex = "1.10.2"
|
||||||
|
serde = "1.0.190"
|
||||||
|
serde_json = "1.0.108"
|
||||||
|
serde_yaml = "0.9.27"
|
27
src/args.rs
Normal file
27
src/args.rs
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
use clap::{arg, command, ArgMatches};
|
||||||
|
|
||||||
|
pub fn get_args() -> ArgMatches {
|
||||||
|
command!()
|
||||||
|
.about("Patch the frontmatter of markdown files")
|
||||||
|
.arg(arg!([markdown] "Markdown File").required(true))
|
||||||
|
.arg(arg!(-p --patch <PATCH> "Apply JSON Patch file. If set to '-' read from stdin").required(false).conflicts_with("merge"))
|
||||||
|
.arg(arg!(--merge <FILE> "Merge Markdown frontmatter. If set to '-' read from stdin").required(false).conflicts_with("patch"))
|
||||||
|
.arg(arg!(-a --add "Only patch add operations").required(false).conflicts_with("merge"))
|
||||||
|
.arg(arg!(-m --modify "Only patch modify operations").required(false).conflicts_with("merge"))
|
||||||
|
.arg(arg!(-d --delete "Only patch delete operations").required(false).conflicts_with("merge"))
|
||||||
|
.arg(arg!(-v --verbose "Print out what changes will be made to the document").required(false))
|
||||||
|
.arg(arg!(-n --dryrun "Dont modify the input file. Only print what would be done").required(false))
|
||||||
|
.arg(arg!(-o --output <OUTPUT> "Write patched file to output path. Dont modify the input file directly. If set to '-' output to stdout"))
|
||||||
|
.arg(arg!(--notest "Ignore tests in JSON Patch files").conflicts_with("merge"))
|
||||||
|
.arg(
|
||||||
|
arg!(-x --exclude <JSONPATH>... "Exclude json path from patch")
|
||||||
|
.required(false)
|
||||||
|
.conflicts_with("keys"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
arg!(-k --keys <JSONPATH>... "Only include the specified json paths in patch")
|
||||||
|
.required(false)
|
||||||
|
.conflicts_with("exclude"),
|
||||||
|
)
|
||||||
|
.get_matches()
|
||||||
|
}
|
364
src/main.rs
Normal file
364
src/main.rs
Normal file
|
@ -0,0 +1,364 @@
|
||||||
|
use std::io::Read;
|
||||||
|
|
||||||
|
use json_patch::PatchOperation;
|
||||||
|
use serde_json::Value;
|
||||||
|
|
||||||
|
mod args;
|
||||||
|
|
||||||
|
trait ErrorExit {
|
||||||
|
type T;
|
||||||
|
|
||||||
|
fn quit_on_error(self, msg: &str) -> Self::T;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, E> ErrorExit for Result<T, E> {
|
||||||
|
type T = T;
|
||||||
|
|
||||||
|
fn quit_on_error(self, msg: &str) -> T {
|
||||||
|
self.map_or_else(
|
||||||
|
|_| {
|
||||||
|
eprintln!("{} {msg}", console::Style::new().red().apply_to("Error:"));
|
||||||
|
std::process::exit(1);
|
||||||
|
},
|
||||||
|
|res| res,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// seperate markdown string into frontmatter and markdown content
|
||||||
|
#[must_use]
|
||||||
|
pub fn markdown_with_frontmatter(markdown: &str) -> (Option<String>, String) {
|
||||||
|
let frontmatter_regex = regex::Regex::new(r"(?s)^---\s*\n(.*?)\n---\s*\n(.*)$").unwrap();
|
||||||
|
|
||||||
|
frontmatter_regex.captures(markdown).map_or_else(
|
||||||
|
|| (None, markdown.to_string()),
|
||||||
|
|captures| {
|
||||||
|
let frontmatter = captures.get(1).map(|m| m.as_str().to_string());
|
||||||
|
let remaining_markdown = captures
|
||||||
|
.get(2)
|
||||||
|
.map(|m| m.as_str().to_string())
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
(frontmatter, remaining_markdown)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn assemble_markdown_doc(content: &str, frontmatter: serde_json::Value) -> String {
|
||||||
|
let frontmatter = serde_yaml::to_string(&serde_yaml::to_value(frontmatter).unwrap()).unwrap();
|
||||||
|
format!("---\n{frontmatter}---\n\n{content}")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remove_test_operations(patch: Vec<PatchOperation>) -> Vec<PatchOperation> {
|
||||||
|
patch
|
||||||
|
.into_iter()
|
||||||
|
.filter(|x| !matches!(x, json_patch::PatchOperation::Test(_)))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remove_add_operations(patch: Vec<PatchOperation>) -> Vec<PatchOperation> {
|
||||||
|
patch
|
||||||
|
.into_iter()
|
||||||
|
.filter(|x| !matches!(x, json_patch::PatchOperation::Add(_)))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remove_modify_operations(patch: Vec<PatchOperation>) -> Vec<PatchOperation> {
|
||||||
|
patch
|
||||||
|
.into_iter()
|
||||||
|
.filter(|x| {
|
||||||
|
!matches!(
|
||||||
|
x,
|
||||||
|
json_patch::PatchOperation::Replace(_)
|
||||||
|
| json_patch::PatchOperation::Move(_)
|
||||||
|
| json_patch::PatchOperation::Copy(_)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remove_delete_operations(patch: Vec<PatchOperation>) -> Vec<PatchOperation> {
|
||||||
|
patch
|
||||||
|
.into_iter()
|
||||||
|
.filter(|x| !matches!(x, json_patch::PatchOperation::Remove(_)))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn exclude_json_paths(patch: &serde_json::Value, paths: &[String]) -> serde_json::Value {
|
||||||
|
let filtered: Vec<serde_json::Value> = patch
|
||||||
|
.as_array()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.filter(|x| {
|
||||||
|
let mut is_excluded = false;
|
||||||
|
for exclude in paths {
|
||||||
|
if x.as_object()
|
||||||
|
.unwrap()
|
||||||
|
.get("path")
|
||||||
|
.unwrap()
|
||||||
|
.as_str()
|
||||||
|
.unwrap()
|
||||||
|
.starts_with(exclude)
|
||||||
|
{
|
||||||
|
is_excluded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
!is_excluded
|
||||||
|
})
|
||||||
|
.cloned()
|
||||||
|
.collect();
|
||||||
|
serde_json::to_value(filtered).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn include_only_json_paths(patch: &serde_json::Value, paths: &[String]) -> serde_json::Value {
|
||||||
|
let filtered: Vec<serde_json::Value> = patch
|
||||||
|
.as_array()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.filter(|x| {
|
||||||
|
let mut is_included = false;
|
||||||
|
for include in paths {
|
||||||
|
if x.as_object()
|
||||||
|
.unwrap()
|
||||||
|
.get("path")
|
||||||
|
.unwrap()
|
||||||
|
.as_str()
|
||||||
|
.unwrap()
|
||||||
|
.starts_with(include)
|
||||||
|
{
|
||||||
|
is_included = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is_included
|
||||||
|
})
|
||||||
|
.cloned()
|
||||||
|
.collect();
|
||||||
|
serde_json::to_value(filtered).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn only_include_json_pointers(paths: &[String], json_value: &Value) -> Value {
|
||||||
|
match json_value {
|
||||||
|
Value::Object(obj) => {
|
||||||
|
let mut filtered_obj = serde_json::Map::new();
|
||||||
|
for path in paths {
|
||||||
|
if let Some(key) = path.strip_prefix('/') {
|
||||||
|
if let Some(value) = obj.get(key) {
|
||||||
|
filtered_obj
|
||||||
|
.insert(key.to_string(), only_include_json_pointers(paths, value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Value::Object(filtered_obj)
|
||||||
|
}
|
||||||
|
Value::Array(arr) => {
|
||||||
|
let filtered_arr: Vec<Value> = arr
|
||||||
|
.iter()
|
||||||
|
.map(|item| only_include_json_pointers(paths, item))
|
||||||
|
.collect();
|
||||||
|
Value::Array(filtered_arr)
|
||||||
|
}
|
||||||
|
_ => json_value.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn exclude_json_by_paths(paths: &[String], json_value: &Value) -> Value {
|
||||||
|
match json_value {
|
||||||
|
Value::Object(obj) => {
|
||||||
|
let mut filtered_obj = serde_json::Map::new();
|
||||||
|
for (key, value) in obj {
|
||||||
|
if !paths.iter().any(|path| path == &("/".to_string() + key)) {
|
||||||
|
filtered_obj.insert(key.clone(), exclude_json_by_paths(paths, value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Value::Object(filtered_obj)
|
||||||
|
}
|
||||||
|
Value::Array(arr) => {
|
||||||
|
let filtered_arr: Vec<Value> = arr
|
||||||
|
.iter()
|
||||||
|
.map(|item| exclude_json_by_paths(paths, item))
|
||||||
|
.collect();
|
||||||
|
Value::Array(filtered_arr)
|
||||||
|
}
|
||||||
|
_ => json_value.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let args = args::get_args();
|
||||||
|
|
||||||
|
let markdown_file = args.get_one::<String>("markdown").unwrap();
|
||||||
|
|
||||||
|
let (frontmatter, markdown_content) = markdown_with_frontmatter(
|
||||||
|
&std::fs::read_to_string(markdown_file).quit_on_error("Could not read markdown file"),
|
||||||
|
);
|
||||||
|
let frontmatter = frontmatter
|
||||||
|
.ok_or(0)
|
||||||
|
.quit_on_error("Could not parse frontmatter");
|
||||||
|
let mut frontmatter = serde_json::to_value(
|
||||||
|
&serde_yaml::from_str::<serde_yaml::Value>(&frontmatter)
|
||||||
|
.quit_on_error("Frontmatter is no valid yaml"),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
if let Some(patch_file) = args.get_one::<String>("patch") {
|
||||||
|
let mut patch: Vec<json_patch::PatchOperation> = serde_json::from_str(
|
||||||
|
&(if patch_file == "-" {
|
||||||
|
let mut str = String::new();
|
||||||
|
std::io::stdin()
|
||||||
|
.read_to_string(&mut str)
|
||||||
|
.quit_on_error("Coult not read stdin");
|
||||||
|
str
|
||||||
|
} else {
|
||||||
|
std::fs::read_to_string(patch_file).quit_on_error("Could not read patch file")
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.quit_on_error("Could not parse patch file");
|
||||||
|
|
||||||
|
if args.get_flag("add") | args.get_flag("modify") | args.get_flag("delete") {
|
||||||
|
if !args.get_flag("add") {
|
||||||
|
patch = remove_add_operations(patch);
|
||||||
|
}
|
||||||
|
if !args.get_flag("modify") {
|
||||||
|
patch = remove_modify_operations(patch);
|
||||||
|
}
|
||||||
|
if !args.get_flag("delete") {
|
||||||
|
patch = remove_delete_operations(patch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if args.get_flag("notest") {
|
||||||
|
patch = remove_test_operations(patch);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut patch = serde_json::to_value(patch).unwrap();
|
||||||
|
|
||||||
|
if let Some(excludes) = args.get_many::<String>("exclude") {
|
||||||
|
let excludes: Vec<String> = excludes.cloned().collect();
|
||||||
|
patch = exclude_json_paths(&patch, &excludes);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(includes) = args.get_many::<String>("keys") {
|
||||||
|
let includes: Vec<String> = includes.cloned().collect();
|
||||||
|
patch = include_only_json_paths(&patch, &includes);
|
||||||
|
}
|
||||||
|
|
||||||
|
let patch: Vec<json_patch::PatchOperation> = serde_json::from_value(patch).unwrap();
|
||||||
|
|
||||||
|
if args.get_flag("verbose") | args.get_flag("dryrun") {
|
||||||
|
for op in patch.clone() {
|
||||||
|
match op {
|
||||||
|
PatchOperation::Add(op) => {
|
||||||
|
eprintln!(
|
||||||
|
"Add {} at {}",
|
||||||
|
console::Style::new().green().apply_to(op.value),
|
||||||
|
console::Style::new().bright().red().apply_to(op.path)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
PatchOperation::Remove(op) => {
|
||||||
|
eprintln!(
|
||||||
|
"Remove value at {}",
|
||||||
|
console::Style::new().bright().red().apply_to(op.path)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
PatchOperation::Replace(op) => {
|
||||||
|
eprintln!(
|
||||||
|
"Replace value at {} with {}",
|
||||||
|
console::Style::new().bright().red().apply_to(op.path),
|
||||||
|
console::Style::new().green().apply_to(op.value)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
PatchOperation::Move(op) => {
|
||||||
|
eprintln!(
|
||||||
|
"Move value from {} to {}",
|
||||||
|
console::Style::new().bright().red().apply_to(op.from),
|
||||||
|
console::Style::new().green().apply_to(op.path)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
PatchOperation::Copy(op) => {
|
||||||
|
eprintln!(
|
||||||
|
"Copy value from {} to {}",
|
||||||
|
console::Style::new().bright().red().apply_to(op.from),
|
||||||
|
console::Style::new().green().apply_to(op.path)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
PatchOperation::Test(op) => {
|
||||||
|
eprintln!(
|
||||||
|
"Test value at {} for {}",
|
||||||
|
console::Style::new().bright().red().apply_to(op.path),
|
||||||
|
console::Style::new().green().apply_to(op.value)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !args.get_flag("dryrun") {
|
||||||
|
if let Err(e) = json_patch::patch(&mut frontmatter, &patch) {
|
||||||
|
eprintln!(
|
||||||
|
"{} Patch failed",
|
||||||
|
console::Style::new().red().apply_to("Error:")
|
||||||
|
);
|
||||||
|
eprintln!("{e}");
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
let markdown_doc = assemble_markdown_doc(&markdown_content, frontmatter);
|
||||||
|
if let Some(output_path) = args.get_one::<String>("output") {
|
||||||
|
if output_path == "-" {
|
||||||
|
print!("{markdown_doc}");
|
||||||
|
} else {
|
||||||
|
std::fs::write(output_path, markdown_doc)
|
||||||
|
.quit_on_error("Could not write output file");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::fs::write(markdown_file, markdown_doc)
|
||||||
|
.quit_on_error("Could not write patched file");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if let Some(merge_file) = args.get_one::<String>("merge") {
|
||||||
|
// TODO : Add support for merging frontmatter from markdown file
|
||||||
|
let mut merge_doc: serde_json::Value = serde_json::from_str(
|
||||||
|
&(if merge_file == "-" {
|
||||||
|
let mut str = String::new();
|
||||||
|
std::io::stdin()
|
||||||
|
.read_to_string(&mut str)
|
||||||
|
.quit_on_error("Coult not read stdin");
|
||||||
|
str
|
||||||
|
} else {
|
||||||
|
std::fs::read_to_string(merge_file).quit_on_error("Could not read merge file")
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.quit_on_error("Could not parse merge file");
|
||||||
|
|
||||||
|
if let Some(excludes) = args.get_many::<String>("exclude") {
|
||||||
|
let excludes: Vec<String> = excludes.cloned().collect();
|
||||||
|
merge_doc = exclude_json_by_paths(&excludes, &merge_doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(includes) = args.get_many::<String>("keys") {
|
||||||
|
let includes: Vec<String> = includes.cloned().collect();
|
||||||
|
merge_doc = only_include_json_pointers(&includes, &merge_doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if args.get_flag("verbose") | args.get_flag("dryrun") {
|
||||||
|
eprintln!("Merging {}", serde_json::to_string(&merge_doc).unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
if !args.get_flag("dryrun") {
|
||||||
|
json_patch::merge(&mut frontmatter, &merge_doc);
|
||||||
|
|
||||||
|
let markdown_doc = assemble_markdown_doc(&markdown_content, frontmatter);
|
||||||
|
if let Some(output_path) = args.get_one::<String>("output") {
|
||||||
|
if output_path == "-" {
|
||||||
|
print!("{markdown_doc}");
|
||||||
|
} else {
|
||||||
|
std::fs::write(output_path, markdown_doc)
|
||||||
|
.quit_on_error("Could not write output file");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::fs::write(markdown_file, markdown_doc)
|
||||||
|
.quit_on_error("Could not write patched file");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue