diff --git a/Cargo.lock b/Cargo.lock index 2a4c647..5a64bf8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -22,9 +22,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.21" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" dependencies = [ "anstyle", "anstyle-parse", @@ -43,9 +43,9 @@ checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" [[package]] name = "anstyle-parse" -version = "0.2.7" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" dependencies = [ "utf8parse", ] @@ -56,7 +56,7 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -67,14 +67,14 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.61.2", + "windows-sys", ] [[package]] name = "anyhow" -version = "1.0.100" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" [[package]] name = "autocfg" @@ -97,6 +97,16 @@ dependencies = [ "objc2", ] +[[package]] +name = "bstr" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cee35f73844aa3014bb606320a6c1f010249dbdf43342fe54b5a4f6a8ed4b79" +dependencies = [ + "memchr", + "serde_core", +] + [[package]] name = "bumpalo" version = "3.19.1" @@ -146,9 +156,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.57" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6899ea499e3fb9305a65d5ebf6e3d2248c5fab291f300ad0a704fbe142eae31a" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" dependencies = [ "clap_builder", "clap_derive", @@ -156,9 +166,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.57" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b12c8b680195a62a8364d16b8447b01b6c2c8f9aaf68bee653be34d4245e238" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" dependencies = [ "anstream", "anstyle", @@ -168,9 +178,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.55" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5" +checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" dependencies = [ "heck", "proc-macro2", @@ -180,9 +190,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.7" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3e64b0cc0439b12df2fa678eae89a1c56a529fd067a9115f7827f1fffd22b32" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" [[package]] name = "colorchoice" @@ -196,15 +206,40 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "crossbeam-deque" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5181e0de7b61eb03a81e347d6dd8797bae9da5146707b51077e2d71a54ec0ceb" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" + [[package]] name = "ctrlc" -version = "3.5.1" +version = "3.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73736a89c4aff73035ba2ed2e565061954da00d4970fc9ac25dcc85a2a20d790" +checksum = "e0b1fab2ae45819af2d0731d60f2afe17227ebb1a1538a236da84c93e9a60162" dependencies = [ "dispatch2", "nix", - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -227,20 +262,14 @@ checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" [[package]] name = "env_filter" -version = "0.1.4" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" +checksum = "900d271a03799a1ee8d1ca9b19893b48ca674a9284fefcfb85f05e74ed314217" dependencies = [ "log", "regex", ] -[[package]] -name = "env_home" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f84e12ccf0a7ddc17a6c41c93326024c42920d7ee630d04950e6926645c0fe" - [[package]] name = "equivalent" version = "1.0.2" @@ -254,18 +283,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys", ] [[package]] name = "filetime" -version = "0.2.27" +version = "0.2.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98844151eee8917efc50bd9e8318cb963ae8b297431495d3f758616ea5c57db" +checksum = "5c287a33c7f0a620c38e641e7f60827713987b3c0f26e8ddc9462cc69cf75759" dependencies = [ "cfg-if", "libc", - "libredox", ] [[package]] @@ -275,10 +303,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" [[package]] -name = "glob" -version = "0.3.3" +name = "globset" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" +checksum = "52dfc19153a48bde0cbd630453615c8151bce3a5adfac7a0aebfbf0a1e1f57e3" +dependencies = [ + "aho-corasick", + "bstr", + "log", + "regex-automata", + "regex-syntax", +] [[package]] name = "hashbrown" @@ -322,6 +357,22 @@ dependencies = [ "cc", ] +[[package]] +name = "ignore" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2adf14691c72bcfc1058740436a35bdd3ae9c07d1a941ef00b749e9ea16aefa7" +dependencies = [ + "crossbeam-deque", + "globset", + "log", + "memchr", + "regex-automata", + "same-file", + "walkdir", + "winapi-util", +] + [[package]] name = "indexmap" version = "2.13.0" @@ -350,20 +401,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.180" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc" - -[[package]] -name = "libredox" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" -dependencies = [ - "bitflags", - "libc", - "redox_syscall", -] +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "linux-raw-sys" @@ -373,7 +413,7 @@ checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" [[package]] name = "lisensor" -version = "0.2.2" +version = "0.3.0" dependencies = [ "chrono", "pistonite-cu", @@ -382,9 +422,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.29" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" [[package]] name = "memchr" @@ -394,9 +434,9 @@ checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "nix" -version = "0.30.1" +version = "0.31.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" +checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d" dependencies = [ "bitflags", "cfg-if", @@ -452,9 +492,9 @@ checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "oneshot" -version = "0.1.13" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "269bca4c2591a28585d6bf10d9ed0332b7d76900a1b02bec41bdc3a2cdcda107" +checksum = "cfe21416a02c693fb9f980befcb230ecc70b0b3d1cc4abf88b9675c4c1457f0c" [[package]] name = "pathdiff" @@ -470,9 +510,9 @@ checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pistonite-cu" -version = "0.7.4" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3b18427d8fab2be730e99547fc7d8561b88dcfdbc44ad0c12b133cf54c09511" +checksum = "39f3e8417cadec1f78a815859d43a9466ccf66d369ed0a0b88d7c74d8dcd321e" dependencies = [ "anyhow", "clap", @@ -480,7 +520,7 @@ dependencies = [ "dunce", "env_filter", "filetime", - "glob", + "ignore", "libc", "log", "num_cpus", @@ -494,23 +534,23 @@ dependencies = [ "toml", "unicode-width", "which", - "windows-sys 0.61.2", + "windows-sys", ] [[package]] name = "pistonite-cu-proc-macros" -version = "0.2.6" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e718dd81a0ec3dd511004e565b521c63a26204d7bfce9100007bbd3e7a11cebf" +checksum = "bce38ec372f52eac41b7b34dffcebcd59d93d9822d43827f102862e3bd861a05" dependencies = [ "pistonite-pm", ] [[package]] name = "pistonite-pm" -version = "0.2.5" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb759ff95dafff75b9b43ed487a6eff22630bbf8d2d4b220ba97f307dfea2c65" +checksum = "74a4071385830e3df275fbbf41324cae3f7d51358c73f18bb9288127d94d4529" dependencies = [ "proc-macro2", "quote", @@ -528,27 +568,18 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.44" +version = "1.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" +checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" dependencies = [ "proc-macro2", ] -[[package]] -name = "redox_syscall" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f3fe0889e69e2ae9e41f4d6c4c0181701d00e4697b356fb1f74173a5e0ee27" -dependencies = [ - "bitflags", -] - [[package]] name = "regex" -version = "1.12.3" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +checksum = "2a0e75113e14dc5acb068cd0786884f214f1312650a3d36d269f5c4f3cdee8a2" dependencies = [ "aho-corasick", "memchr", @@ -569,9 +600,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.9" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" [[package]] name = "rustix" @@ -583,7 +614,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -592,6 +623,15 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "serde" version = "1.0.228" @@ -624,9 +664,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "1.0.4" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" dependencies = [ "serde_core", ] @@ -645,9 +685,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.114" +version = "2.0.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" +checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" dependencies = [ "proc-macro2", "quote", @@ -656,19 +696,19 @@ dependencies = [ [[package]] name = "terminal_size" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b8cb979cb11c32ce1603f8137b22262a9d131aaa5c37b5678025f22b8becd0" +checksum = "230a1b821ccbd75b185820a1f1ff7b14d21da1e442e22c0863ea5f08771a8874" dependencies = [ "rustix", - "windows-sys 0.60.2", + "windows-sys", ] [[package]] name = "tokio" -version = "1.49.0" +version = "1.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" +checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" dependencies = [ "bytes", "pin-project-lite", @@ -677,9 +717,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ "proc-macro2", "quote", @@ -688,9 +728,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.9.11+spec-1.1.0" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3afc9a848309fe1aaffaed6e1546a7a14de1f935dc9d89d32afd9a44bab7c46" +checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee" dependencies = [ "indexmap", "serde_core", @@ -703,27 +743,27 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.7.5+spec-1.1.0" +version = "1.1.1+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" dependencies = [ "serde_core", ] [[package]] name = "toml_parser" -version = "1.0.6+spec-1.1.0" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ "winnow", ] [[package]] name = "toml_writer" -version = "1.0.6+spec-1.1.0" +version = "1.1.1+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607" +checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" [[package]] name = "unicode-ident" @@ -743,6 +783,16 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "wasm-bindgen" version = "0.2.108" @@ -790,13 +840,20 @@ dependencies = [ [[package]] name = "which" -version = "8.0.0" +version = "8.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fabb953106c3c8eea8306e4393700d7657561cb43122571b172bbfb7c7ba1d" +checksum = "48d7cd18d4acb58fb3cdfe9ea54e6cd96a4e7d4cc45c56338b236e82dad47248" dependencies = [ - "env_home", - "rustix", - "winsafe", + "libc", +] + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys", ] [[package]] @@ -858,15 +915,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-sys" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" -dependencies = [ - "windows-targets", -] - [[package]] name = "windows-sys" version = "0.61.2" @@ -876,79 +924,8 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-targets" -version = "0.53.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" -dependencies = [ - "windows-link", - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" - -[[package]] -name = "windows_i686_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" - -[[package]] -name = "windows_i686_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" - [[package]] name = "winnow" -version = "0.7.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" - -[[package]] -name = "winsafe" -version = "0.0.19" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" +checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1" diff --git a/Cargo.toml b/Cargo.toml index 139c145..240a6ba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "lisensor" -version = "0.2.2" +version = "0.3.0" edition = "2024" description = "Tool to automatically add, check, and fix license notices in the source files" license = "MIT" @@ -22,7 +22,7 @@ serde = "1" [dependencies.cu] package = "pistonite-cu" -version = "0.7.4" +version = "0.9.0" features = ["print", "fs", "coroutine-heavy", "toml"] # path = "../cu/packages/copper" diff --git a/Lisensor.toml b/Lisensor.toml index 40417cc..234c721 100644 --- a/Lisensor.toml +++ b/Lisensor.toml @@ -1,3 +1,2 @@ [Pistonite] -"src/**/*" = "MIT" -"tests/**/*.rs" = "MIT" +"{src,tests}/**/*.rs" = "MIT" diff --git a/README.md b/README.md index 89c0d4d..8781412 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,8 @@ used by tests in the project, but might be helpful for integrating `lisensor` in ## Config By default, `lisensor` looks for `Lisensor.toml` then `lisensor.toml` -in the current directory if no config files are specified. +in the current directory if no config files are specified. If not found +then it tries to search the parent directories until one is found. Globs in the config file are relative to the directory containing the config file, meaning running `lisensor` from anywhere will result diff --git a/Taskfile.yml b/Taskfile.yml index 28ccb7b..00dd3dc 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -27,9 +27,8 @@ tasks: - cargo test --test fixture_test test-inline-cmd: - dir: src cmds: - - cargo run -- -H Pistonite -L MIT **/*.rs + - cargo run -- -H Pistonite -L MIT './**/*.rs' --no-config fix: - cargo run -- -f diff --git a/src/cli.rs b/src/cli.rs index c49c598..013a0bb 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -1,6 +1,8 @@ // SPDX-License-Identifier: MIT // Copyright (c) 2025-2026 Pistonite +use std::path::Path; + use cu::pre::*; use crate::Config; @@ -18,11 +20,17 @@ pub struct Cli { #[clap(short = 'L', long, requires("holder"))] pub license: Option, + /// Do not attempt discovering config file + #[clap(long, requires("holder"))] + pub no_config: bool, + #[clap(flatten)] pub common: cu::cli::Flags, /// Paths to config files, or in inline config mode, glob patterns for source files /// to apply the license notice. + /// + /// In inline config mode, the glob patterns are relative to the current working directory pub paths: Vec, } @@ -30,12 +38,20 @@ pub struct Cli { pub fn config_from_cli(args: &mut crate::Cli) -> cu::Result { match (args.holder.take(), args.license.take()) { (Some(holder), Some(license)) => { - if let Some(config_path) = crate::try_find_default_config_file() { - cu::bail!( - "--holder or --license cannot be specified when {config_path} is present in the current directory" - ); + if !args.no_config { + if let Some(config_path) = crate::try_find_default_config_file() { + cu::error!( + "--holder or --license cannot be specified when config file is present: '{}'", + config_path.display() + ); + cu::hint!( + "this error exists to prevent accidental misuse; use --no-config to skip discovering config file if intended" + ); + cu::bail!("invalid command line usage"); + } } Ok(Config::new( + std::env::current_dir()?, holder, license, std::mem::take(&mut args.paths), @@ -48,16 +64,16 @@ pub fn config_from_cli(args: &mut crate::Cli) -> cu::Result { None => { let Some(config_path) = crate::try_find_default_config_file() else { cu::bail!( - "cannot find Lisensor.toml, and no config files are specified on the command line." + "cannot find config file, and no config files are specified on the command line." ); }; - Config::build(config_path)? + Config::build(&config_path)? } - Some(first) => Config::build(&first)?, + Some(first) => Config::build(Path::new(&first))?, }; for path in iter { - config.absorb(Config::build(&path)?)?; + config.absorb(Config::build(Path::new(&path))?)?; } Ok(config) diff --git a/src/config.rs b/src/config.rs index 7909542..4a250b5 100644 --- a/src/config.rs +++ b/src/config.rs @@ -3,23 +3,45 @@ use std::collections::BTreeMap; use std::ops::Deref; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::sync::Arc; use cu::pre::*; +static CONFIG_NAMES: &[&str] = &["Lisensor.toml", "lisensor.toml"]; + /// Try finding the default config files according to the order /// specified in the documentation (see repo README) -pub fn try_find_default_config_file() -> Option<&'static str> { - ["Lisensor.toml", "lisensor.toml"] - .into_iter() - .find(|x| Path::new(x).exists()) +pub fn try_find_default_config_file() -> Option { + for x in CONFIG_NAMES { + if Path::new(x).exists() { + cu::debug!("found config {x} in current directory"); + return Some(PathBuf::from(x)); + } + } + cu::debug!("discovering config in parent directories"); + let mut curr = Path::new(".").normalize().ok()?; + loop { + curr = curr.parent_abs().ok()?; + cu::debug!("looking for config in '{}'", curr.display()); + let mut p = curr.clone(); + for x in CONFIG_NAMES { + p.push(x); + if p.exists() { + cu::debug!("found config '{}'", p.display()); + return Some(p); + } + p.pop(); + } + } } /// Config object #[derive(Debug, Default, Clone, PartialEq, Eq)] pub struct Config { - // glob -> (holder, license) + /// the root directory to run the program + root: PathBuf, + /// glob -> (holder, license) globs: BTreeMap, Arc)>, } @@ -32,7 +54,7 @@ struct TomlConfig(BTreeMap>); impl Config { /// Create a config object from a single holder and license, /// with multiple glob patterns. - pub fn new(holder: String, license: String, glob_list: Vec) -> Self { + pub fn new(root: PathBuf, holder: String, license: String, glob_list: Vec) -> Self { let holder = Arc::new(holder); let license = Arc::new(license); let mut globs = BTreeMap::new(); @@ -48,25 +70,22 @@ impl Config { } } } - Self { globs } + Self { root, globs } } /// Build the config by reading the file specified, error if conflicts are detected /// /// The globs specified in the config file are relative to the parent directory - /// of `path`. - pub fn build(path: &str) -> cu::Result { - let raw = toml::parse::(&cu::fs::read_string(path)?)?; - let parent = Path::new(path) - .parent() + /// of `config_path`. + pub fn build(config_path: &Path) -> cu::Result { + let raw = toml::parse::(&cu::fs::read_string(config_path)?)?; + let root = config_path + .parent_abs() .context("failed to get parent path for config")?; let mut globs = BTreeMap::new(); for (holder, table) in raw.0 { let holder = Arc::new(holder); for (glob, license) in table { - // globs in config files are resolved relative - // to the directory where the config file is in - let glob = parent.join(glob).into_utf8()?; use std::collections::btree_map::Entry; match globs.entry(glob) { Entry::Vacant(entry) => { @@ -76,7 +95,10 @@ impl Config { let glob = entry.key(); let (curr_holder, curr_license) = entry.get(); if *curr_holder == holder && curr_license.deref() == license.as_str() { - cu::warn!("glob '{glob}' specified multiple times in '{path}'!"); + cu::warn!( + "glob '{glob}' specified multiple times in '{}'!", + config_path.display() + ); continue; } cu::error!("conflicting config specified for glob '{glob}':"); @@ -91,7 +113,10 @@ impl Config { } } } - Ok(Self { globs }) + Ok(Self { + root: root.to_path_buf(), + globs, + }) } /// Merge another config into self, error if conflicts are detected @@ -124,14 +149,39 @@ impl Config { } } -impl Config { - /// Iterate the resolve paths as (path, holder, license) - #[allow(clippy::should_implement_trait)] - pub fn into_iter(self) -> impl Iterator, Arc)> { - // we can't implement the IntoIterator trait because - // the map object has an unnamed function type - self.globs - .into_iter() - .map(|(path, (holder, license))| (path, holder, license)) +impl IntoIterator for Config { + type Item = ConfigEntry; + type IntoIter = ConfigIntoIter; + fn into_iter(self) -> Self::IntoIter { + ConfigIntoIter { + root: Arc::new(self.root), + globs_iter: self.globs.into_iter(), + } } } + +pub struct ConfigIntoIter { + root: Arc, + globs_iter: std::collections::btree_map::IntoIter, Arc)>, +} + +impl Iterator for ConfigIntoIter { + type Item = ConfigEntry; + fn next(&mut self) -> Option { + let (glob, (holder, license)) = self.globs_iter.next()?; + Some(ConfigEntry { + root: Arc::clone(&self.root), + glob, + holder, + license, + }) + } +} + +/// Config for one file +pub struct ConfigEntry { + pub root: Arc, + pub glob: String, + pub holder: Arc, + pub license: Arc, +} diff --git a/src/runner.rs b/src/runner.rs index 55f7816..149ef5e 100644 --- a/src/runner.rs +++ b/src/runner.rs @@ -5,7 +5,7 @@ use std::collections::BTreeMap; use std::path::PathBuf; use std::sync::Arc; -use crate::{Config, format}; +use crate::{Config, ConfigEntry, format}; /// Issues found #[derive(Debug, Default, Clone, PartialEq)] @@ -45,16 +45,14 @@ pub async fn run(config: Config, fix: bool) -> cu::Result> { // avoid opening too many files. max open 1024 files let pool = cu::co::pool(1024); - for (glob, holder, license) in config.into_iter() { - let result = run_glob( - &glob, - holder, - license, - fix, - &pool, - &mut handles, - &mut path_map, + for entry in config { + let glob = entry.glob.clone(); + cu::debug!( + "running glob '{glob}', holder={:?}, license={:?}", + entry.holder, + entry.license ); + let result = run_glob_config(entry, fix, &pool, &mut handles, &mut path_map); match result { Ok(matched) => { if !matched { @@ -75,7 +73,7 @@ pub async fn run(config: Config, fix: bool) -> cu::Result> { // handle glob errors first if !glob_errors.is_empty() { for (glob, error) in &glob_errors { - cu::error!("while globbing '{glob}': {error}"); + cu::error!("while globbing '{glob}': {error:?}"); } cu::error!( "got {} errors while searching for files, see above", @@ -95,6 +93,13 @@ pub async fn run(config: Config, fix: bool) -> cu::Result> { cu::progress!(bar += 1, "{}", path.display()); } + if total == 0 { + cu::bail!("input did not match any files"); + } + for x in no_match_glob { + cu::warn!("glob '{x}' did not match any files!"); + } + if !errors.is_empty() { let failed = errors.len(); cu::error!("checked {total} files, found {failed} issue(s)."); @@ -109,24 +114,26 @@ pub async fn run(config: Config, fix: bool) -> cu::Result> { Ok(Ok(())) } -fn run_glob( - glob: &str, - holder: Arc, - license: Arc, +fn run_glob_config( + config: ConfigEntry, fix: bool, pool: &cu::co::Pool, handles: &mut Vec)>>, path_map: &mut BTreeMap, Arc)>, ) -> cu::Result { let mut matched = false; - for path in cu::fs::glob(glob)? { - let path = path?; - if !path.is_file() { + let mut walker = cu::fs::walker(&*config.root); + let glob = &config.glob; + walker.git(true).glob_includes([glob])?; + for entry in walker.walk()? { + let entry = entry?; + if !entry.is_file() { continue; } matched = true; - let holder = Arc::clone(&holder); - let license = Arc::clone(&license); + let holder = Arc::clone(&config.holder); + let license = Arc::clone(&config.license); + let path = entry.path().to_path_buf(); // in fix mode, run additional check for if there are conflicts // in the config. Otherwise, the fix result is arbitrary diff --git a/tests/fixture_test.rs b/tests/fixture_test.rs index 59865c6..21dd9a6 100644 --- a/tests/fixture_test.rs +++ b/tests/fixture_test.rs @@ -1,15 +1,13 @@ // SPDX-License-Identifier: MIT // Copyright (c) 2025-2026 Pistonite -use std::path::Path; - use lisensor::{Config, run}; pub fn run_fixture(name: &str) -> cu::Result<()> { - cu::cli::level("qq"); + // cu::cli::level("qq"); let update_output = std::env::var("FIXTURE_UPDATE").unwrap_or_default().as_str() == "1"; - let fixtures = Path::new("tests").join("fixtures"); + let fixtures = cu::path!("tests" / "fixtures"); let input_path = fixtures.join(name); cu::debug!("running fixture: {name}"); @@ -18,9 +16,10 @@ pub fn run_fixture(name: &str) -> cu::Result<()> { std::fs::copy(&input_path, &input_copy_path)?; let config = Config::new( + fixtures.clone(), "TestHolder".to_string(), "TestLicense".to_string(), - vec![input_copy_path.to_string_lossy().into_owned()], + vec![format!("{name}_out")], ); let config2 = config.clone();