Simple tool for automatic file management

Compare changes

Choose any two refs to compare.

+9
.build.yml
···
···
+
# SPDX-FileCopyrightText: 2024 Łukasz Niemier <#@hauleth.dev>
+
#
+
# SPDX-License-Identifier: EUPL-1.2
+
+
image: nixos/24.05
+
environment:
+
NIX_CONFIG: "experimental-features = nix-command flakes"
+
tasks:
+
- build: nix build ./ptsd
+6
.cargo/config.toml
···
···
+
# SPDX-FileCopyrightText: 2024 Łukasz Niemier <#@hauleth.dev>
+
#
+
# SPDX-License-Identifier: EUPL-1.2
+
+
[alias]
+
xtask = "run --package xtask --"
+4
.gitignore
···
/target
···
+
# SPDX-FileCopyrightText: 2024 Łukasz Niemier <#@hauleth.dev>
+
#
+
# SPDX-License-Identifier: EUPL-1.2
+
/target
+5
.mailmap
···
···
+
# SPDX-FileCopyrightText: 2024 Łukasz Niemier <#@hauleth.dev>
+
#
+
# SPDX-License-Identifier: EUPL-1.2
+
+
Łukasz Niemier <~@hauleth.dev> <lukasz@niemier.pl>
+607 -343
Cargo.lock
···
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
-
version = 3
[[package]]
name = "addr2line"
-
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
dependencies = [
"gimli",
]
[[package]]
-
name = "adler"
-
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "aho-corasick"
-
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
dependencies = [
"memchr",
]
···
]
[[package]]
name = "async-stream"
-
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51"
dependencies = [
"async-stream-impl",
"futures-core",
···
[[package]]
name = "async-stream-impl"
-
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
dependencies = [
"proc-macro2",
"quote",
···
[[package]]
name = "async-trait"
-
version = "0.1.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9"
dependencies = [
"proc-macro2",
"quote",
···
[[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.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
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 = "bumpalo"
-
version = "3.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
[[package]]
name = "bytes"
-
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
[[package]]
name = "cc"
-
version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
dependencies = [
-
"libc",
]
[[package]]
name = "cfg-if"
-
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
-
version = "0.4.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
dependencies = [
"android-tzdata",
"iana-time-zone",
"num-traits",
-
"windows-targets 0.48.5",
]
[[package]]
name = "color-eyre"
-
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "5a667583cca8c4f8436db8de46ea8233c42a7d9ae424a82d338f2e4675229204"
dependencies = [
"backtrace",
"color-spantrace",
···
[[package]]
name = "color-spantrace"
-
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "cd6be1b2a7e382e2b98b43b2adcca6bb0e465af0bdd38123873ae61eb17a72c2"
dependencies = [
"once_cell",
"owo-colors",
···
]
[[package]]
name = "core-foundation-sys"
-
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
[[package]]
name = "erased-serde"
-
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "55d05712b2d8d88102bc9868020c9e5c7a1f5527c452b9b97450a1d006140ba7"
dependencies = [
"serde",
]
[[package]]
name = "eyre"
-
version = "0.6.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "b6267a1fa6f59179ea4afc8e50fd8612a3cc60bc858f786ff877a4a8cb042799"
dependencies = [
"indenter",
"once_cell",
]
[[package]]
-
name = "form_urlencoded"
-
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
-
dependencies = [
-
"percent-encoding",
-
]
[[package]]
name = "futures"
-
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"
dependencies = [
"futures-channel",
"futures-core",
···
[[package]]
name = "futures-channel"
-
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
dependencies = [
"futures-core",
"futures-sink",
···
[[package]]
name = "futures-core"
-
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
[[package]]
name = "futures-executor"
-
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d"
dependencies = [
"futures-core",
"futures-task",
···
[[package]]
name = "futures-io"
-
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
[[package]]
name = "futures-macro"
-
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
dependencies = [
"proc-macro2",
"quote",
···
[[package]]
name = "futures-sink"
-
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
[[package]]
name = "futures-task"
-
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
[[package]]
name = "futures-util"
-
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
dependencies = [
"futures-channel",
"futures-core",
···
]
[[package]]
name = "gimli"
-
version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
[[package]]
-
name = "hermit-abi"
-
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
[[package]]
name = "iana-time-zone"
-
version = "0.1.59"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"wasm-bindgen",
-
"windows-core",
]
[[package]]
···
]
[[package]]
-
name = "idna"
-
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
dependencies = [
-
"unicode-bidi",
-
"unicode-normalization",
]
[[package]]
-
name = "indenter"
-
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
[[package]]
-
name = "inventory"
-
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "c8573b2b1fb643a372c73b23f4da5f888677feef3305146d68a539250a9bccc7"
[[package]]
name = "itoa"
-
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
[[package]]
name = "js-sys"
-
version = "0.3.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1"
dependencies = [
"wasm-bindgen",
]
[[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.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7"
[[package]]
name = "lock_api"
-
version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
dependencies = [
"autocfg",
"scopeguard",
···
[[package]]
name = "log"
-
version = "0.4.20"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
-
-
[[package]]
-
name = "malloc_buf"
-
version = "0.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb"
-
dependencies = [
-
"libc",
-
]
[[package]]
name = "memchr"
-
version = "2.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
[[package]]
name = "miniz_oxide"
-
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
dependencies = [
-
"adler",
]
[[package]]
name = "mio"
-
version = "0.8.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09"
dependencies = [
"libc",
"wasi",
-
"windows-sys",
]
[[package]]
name = "num-traits"
-
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
dependencies = [
"autocfg",
]
[[package]]
-
name = "num_cpus"
-
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
dependencies = [
-
"hermit-abi",
-
"libc",
]
[[package]]
-
name = "objc"
-
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1"
dependencies = [
-
"malloc_buf",
]
[[package]]
name = "object"
-
version = "0.32.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
dependencies = [
"memchr",
]
[[package]]
name = "once_cell"
-
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "owo-colors"
-
version = "3.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
[[package]]
name = "parking_lot"
-
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
dependencies = [
"lock_api",
"parking_lot_core",
···
[[package]]
name = "parking_lot_core"
-
version = "0.9.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
-
"windows-targets 0.48.5",
]
[[package]]
···
[[package]]
name = "pin-project-lite"
-
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
[[package]]
name = "pin-utils"
···
[[package]]
name = "proc-macro2"
-
version = "1.0.76"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c"
dependencies = [
"unicode-ident",
]
···
dependencies = [
"async-stream",
"async-trait",
"color-eyre",
"futures",
"libc",
"regex",
"serde",
···
[[package]]
name = "quote"
-
version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [
"proc-macro2",
]
[[package]]
name = "redox_syscall"
-
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
dependencies = [
"bitflags",
]
[[package]]
name = "regex"
-
version = "1.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
dependencies = [
"aho-corasick",
"memchr",
···
[[package]]
name = "regex-automata"
-
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
dependencies = [
"aho-corasick",
"memchr",
···
[[package]]
name = "regex-syntax"
-
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
[[package]]
name = "rustc-demangle"
-
version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
[[package]]
name = "ryu"
-
version = "1.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
[[package]]
name = "scopeguard"
···
[[package]]
name = "serde"
-
version = "1.0.195"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-
version = "1.0.195"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c"
dependencies = [
"proc-macro2",
"quote",
···
[[package]]
name = "serde_json"
-
version = "1.0.111"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4"
dependencies = [
"itoa",
"ryu",
"serde",
]
···
]
[[package]]
name = "signal-hook-registry"
-
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
dependencies = [
"libc",
]
[[package]]
name = "slab"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
[[package]]
name = "smallvec"
-
version = "1.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
[[package]]
name = "syn"
-
version = "2.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
dependencies = [
"proc-macro2",
"quote",
···
]
[[package]]
-
name = "thread_local"
-
version = "1.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152"
dependencies = [
-
"cfg-if",
-
"once_cell",
]
[[package]]
-
name = "tinyvec"
-
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
dependencies = [
-
"tinyvec_macros",
]
[[package]]
-
name = "tinyvec_macros"
-
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "tokio"
-
version = "1.35.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104"
dependencies = [
"backtrace",
"bytes",
"libc",
"mio",
-
"num_cpus",
"parking_lot",
"pin-project-lite",
"signal-hook-registry",
"tokio-macros",
-
"windows-sys",
]
[[package]]
name = "tokio-macros"
-
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
dependencies = [
"proc-macro2",
"quote",
···
[[package]]
name = "tokio-stream"
-
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842"
dependencies = [
"futures-core",
"pin-project-lite",
···
[[package]]
name = "tracing"
-
version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
dependencies = [
"pin-project-lite",
"tracing-core",
···
[[package]]
name = "tracing-core"
-
version = "0.1.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
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.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b"
dependencies = [
"sharded-slab",
"thread_local",
···
[[package]]
name = "trash"
-
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "6e7b1a28f9550f43ac27987f2144d7798520c6dee6a7eb1dedfe3131e3c257e3"
dependencies = [
"chrono",
"libc",
"log",
-
"objc",
"once_cell",
"scopeguard",
-
"url",
"windows",
]
[[package]]
name = "typetag"
-
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "c43148481c7b66502c48f35b8eef38b6ccdc7a9f04bd4cc294226d901ccc9bc7"
dependencies = [
"erased-serde",
"inventory",
···
[[package]]
name = "typetag-impl"
-
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "291db8a81af4840c10d636e047cac67664e343be44e24dfdbd1492df9a5d3390"
dependencies = [
"proc-macro2",
"quote",
···
]
[[package]]
-
name = "unicode-bidi"
-
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416"
[[package]]
-
name = "unicode-ident"
-
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
-
name = "unicode-normalization"
-
version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
-
dependencies = [
-
"tinyvec",
-
]
[[package]]
-
name = "url"
-
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633"
dependencies = [
-
"form_urlencoded",
-
"idna",
-
"percent-encoding",
]
[[package]]
name = "valuable"
-
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
[[package]]
name = "wasi"
···
[[package]]
name = "wasm-bindgen"
-
version = "0.2.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
-
version = "0.2.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd"
dependencies = [
"bumpalo",
"log",
-
"once_cell",
"proc-macro2",
"quote",
"syn",
···
[[package]]
name = "wasm-bindgen-macro"
-
version = "0.2.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
···
[[package]]
name = "wasm-bindgen-macro-support"
-
version = "0.2.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7"
dependencies = [
"proc-macro2",
"quote",
···
[[package]]
name = "wasm-bindgen-shared"
-
version = "0.2.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b"
[[package]]
name = "wildmatch"
-
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "495ec47bf3c1345005f40724f0269362c8556cbc43aed0526ed44cae1d35fceb"
[[package]]
name = "windows"
-
version = "0.44.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "9e745dab35a0c4c77aa3ce42d595e13d2003d6902d6b08c9ef5fc326d08da12b"
dependencies = [
-
"windows-targets 0.42.2",
]
[[package]]
name = "windows-core"
-
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [
-
"windows-targets 0.52.0",
]
[[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-targets"
-
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
dependencies = [
-
"windows_aarch64_gnullvm 0.52.0",
-
"windows_aarch64_msvc 0.52.0",
-
"windows_i686_gnu 0.52.0",
-
"windows_i686_msvc 0.52.0",
-
"windows_x86_64_gnu 0.52.0",
-
"windows_x86_64_gnullvm 0.52.0",
-
"windows_x86_64_msvc 0.52.0",
]
[[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_gnullvm"
-
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
[[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_aarch64_msvc"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
[[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_gnu"
-
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
[[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_i686_msvc"
-
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
[[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_gnu"
-
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
[[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_gnullvm"
-
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
[[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"
-
-
[[package]]
-
name = "windows_x86_64_msvc"
-
version = "0.52.0"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
···
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
+
version = 4
[[package]]
name = "addr2line"
+
version = "0.24.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
dependencies = [
"gimli",
]
[[package]]
+
name = "adler2"
+
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
[[package]]
name = "aho-corasick"
+
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [
"memchr",
]
···
]
[[package]]
+
name = "anstream"
+
version = "0.6.19"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933"
+
dependencies = [
+
"anstyle",
+
"anstyle-parse",
+
"anstyle-query",
+
"anstyle-wincon",
+
"colorchoice",
+
"is_terminal_polyfill",
+
"utf8parse",
+
]
+
+
[[package]]
+
name = "anstyle"
+
version = "1.0.11"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd"
+
+
[[package]]
+
name = "anstyle-parse"
+
version = "0.2.7"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"
+
dependencies = [
+
"utf8parse",
+
]
+
+
[[package]]
+
name = "anstyle-query"
+
version = "1.1.3"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9"
+
dependencies = [
+
"windows-sys 0.59.0",
+
]
+
+
[[package]]
+
name = "anstyle-wincon"
+
version = "3.0.9"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882"
+
dependencies = [
+
"anstyle",
+
"once_cell_polyfill",
+
"windows-sys 0.59.0",
+
]
+
+
[[package]]
name = "async-stream"
+
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476"
dependencies = [
"async-stream-impl",
"futures-core",
···
[[package]]
name = "async-stream-impl"
+
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d"
dependencies = [
"proc-macro2",
"quote",
···
[[package]]
name = "async-trait"
+
version = "0.1.88"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5"
dependencies = [
"proc-macro2",
"quote",
···
[[package]]
name = "autocfg"
+
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
name = "backtrace"
+
version = "0.3.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002"
dependencies = [
"addr2line",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
+
"windows-targets",
]
[[package]]
name = "bitflags"
+
version = "2.9.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
+
+
[[package]]
+
name = "block2"
+
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f"
+
dependencies = [
+
"objc2",
+
]
[[package]]
name = "bumpalo"
+
version = "3.18.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee"
+
+
[[package]]
+
name = "byteorder"
+
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "bytes"
+
version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
[[package]]
name = "cc"
+
version = "1.2.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "956a5e21988b87f372569b66183b78babf23ebc2e744b733e4350a752c4dafac"
dependencies = [
+
"shlex",
+
]
+
+
[[package]]
+
name = "cfb"
+
version = "0.7.3"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "d38f2da7a0a2c4ccf0065be06397cc26a81f4e528be095826eee9d4adbb8c60f"
+
dependencies = [
+
"byteorder",
+
"fnv",
+
"uuid",
]
[[package]]
name = "cfg-if"
+
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
[[package]]
name = "chrono"
+
version = "0.4.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d"
dependencies = [
"android-tzdata",
"iana-time-zone",
"num-traits",
+
"windows-link",
]
[[package]]
+
name = "clap"
+
version = "4.5.40"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f"
+
dependencies = [
+
"clap_builder",
+
"clap_derive",
+
]
+
+
[[package]]
+
name = "clap_builder"
+
version = "4.5.40"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e"
+
dependencies = [
+
"anstream",
+
"anstyle",
+
"clap_lex",
+
"strsim",
+
]
+
+
[[package]]
+
name = "clap_derive"
+
version = "4.5.40"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce"
+
dependencies = [
+
"heck",
+
"proc-macro2",
+
"quote",
+
"syn",
+
]
+
+
[[package]]
+
name = "clap_lex"
+
version = "0.7.5"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675"
+
+
[[package]]
name = "color-eyre"
+
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "e5920befb47832a6d61ee3a3a846565cfa39b331331e68a3b1d1116630f2f26d"
dependencies = [
"backtrace",
"color-spantrace",
···
[[package]]
name = "color-spantrace"
+
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "b8b88ea9df13354b55bc7234ebcce36e6ef896aca2e42a15de9e10edce01b427"
dependencies = [
"once_cell",
"owo-colors",
···
]
[[package]]
+
name = "colorchoice"
+
version = "1.0.4"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
+
+
[[package]]
name = "core-foundation-sys"
+
version = "0.8.7"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
+
+
[[package]]
+
name = "dirs"
+
version = "6.0.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e"
+
dependencies = [
+
"dirs-sys",
+
]
+
+
[[package]]
+
name = "dirs-sys"
+
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab"
+
dependencies = [
+
"libc",
+
"option-ext",
+
"redox_users",
+
"windows-sys 0.59.0",
+
]
[[package]]
name = "erased-serde"
+
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "e004d887f51fcb9fef17317a2f3525c887d8aa3f4f50fed920816a688284a5b7"
dependencies = [
"serde",
+
"typeid",
]
[[package]]
name = "eyre"
+
version = "0.6.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec"
dependencies = [
"indenter",
"once_cell",
]
[[package]]
+
name = "fnv"
+
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "futures"
+
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876"
dependencies = [
"futures-channel",
"futures-core",
···
[[package]]
name = "futures-channel"
+
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
dependencies = [
"futures-core",
"futures-sink",
···
[[package]]
name = "futures-core"
+
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
[[package]]
name = "futures-executor"
+
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f"
dependencies = [
"futures-core",
"futures-task",
···
[[package]]
name = "futures-io"
+
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
[[package]]
name = "futures-macro"
+
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
dependencies = [
"proc-macro2",
"quote",
···
[[package]]
name = "futures-sink"
+
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
[[package]]
name = "futures-task"
+
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
[[package]]
name = "futures-util"
+
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
dependencies = [
"futures-channel",
"futures-core",
···
]
[[package]]
+
name = "getrandom"
+
version = "0.2.16"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
+
dependencies = [
+
"cfg-if",
+
"libc",
+
"wasi",
+
]
+
+
[[package]]
name = "gimli"
+
version = "0.31.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
[[package]]
+
name = "heck"
+
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "iana-time-zone"
+
version = "0.1.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
+
"log",
"wasm-bindgen",
+
"windows-core 0.61.2",
]
[[package]]
···
]
[[package]]
+
name = "indenter"
+
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
+
+
[[package]]
+
name = "infer"
+
version = "0.19.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "a588916bfdfd92e71cacef98a63d9b1f0d74d6599980d11894290e7ddefffcf7"
dependencies = [
+
"cfb",
]
[[package]]
+
name = "inventory"
+
version = "0.3.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "ab08d7cd2c5897f2c949e5383ea7c7db03fb19130ffcfbf7eda795137ae3cb83"
+
dependencies = [
+
"rustversion",
+
]
[[package]]
+
name = "is_terminal_polyfill"
+
version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]]
name = "itoa"
+
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
[[package]]
name = "js-sys"
+
version = "0.3.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
dependencies = [
+
"once_cell",
"wasm-bindgen",
]
[[package]]
name = "lazy_static"
+
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "libc"
+
version = "0.2.172"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
+
+
[[package]]
+
name = "libredox"
+
version = "0.1.3"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
+
dependencies = [
+
"bitflags",
+
"libc",
+
]
[[package]]
name = "lock_api"
+
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765"
dependencies = [
"autocfg",
"scopeguard",
···
[[package]]
name = "log"
+
version = "0.4.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
[[package]]
name = "memchr"
+
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "miniz_oxide"
+
version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
dependencies = [
+
"adler2",
]
[[package]]
name = "mio"
+
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c"
dependencies = [
"libc",
"wasi",
+
"windows-sys 0.59.0",
]
[[package]]
name = "num-traits"
+
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
]
[[package]]
+
name = "objc-sys"
+
version = "0.3.5"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310"
+
+
[[package]]
+
name = "objc2"
+
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804"
dependencies = [
+
"objc-sys",
+
"objc2-encode",
]
[[package]]
+
name = "objc2-encode"
+
version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33"
+
+
[[package]]
+
name = "objc2-foundation"
+
version = "0.2.2"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8"
dependencies = [
+
"bitflags",
+
"block2",
+
"libc",
+
"objc2",
]
[[package]]
name = "object"
+
version = "0.36.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
dependencies = [
"memchr",
]
[[package]]
name = "once_cell"
+
version = "1.21.3"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
+
+
[[package]]
+
name = "once_cell_polyfill"
+
version = "1.70.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
+
+
[[package]]
+
name = "option-ext"
+
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
[[package]]
name = "owo-colors"
+
version = "4.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "26995317201fa17f3656c36716aed4a7c81743a9634ac4c99c0eeda495db0cec"
[[package]]
name = "parking_lot"
+
version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13"
dependencies = [
"lock_api",
"parking_lot_core",
···
[[package]]
name = "parking_lot_core"
+
version = "0.9.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
+
"windows-targets",
]
[[package]]
···
[[package]]
name = "pin-project-lite"
+
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
[[package]]
name = "pin-utils"
···
[[package]]
name = "proc-macro2"
+
version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
dependencies = [
"unicode-ident",
]
···
dependencies = [
"async-stream",
"async-trait",
+
"clap",
"color-eyre",
+
"dirs",
"futures",
+
"infer",
"libc",
"regex",
"serde",
···
[[package]]
name = "quote"
+
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
dependencies = [
"proc-macro2",
]
[[package]]
name = "redox_syscall"
+
version = "0.5.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af"
dependencies = [
"bitflags",
]
[[package]]
+
name = "redox_users"
+
version = "0.5.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b"
+
dependencies = [
+
"getrandom",
+
"libredox",
+
"thiserror",
+
]
+
+
[[package]]
name = "regex"
+
version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
dependencies = [
"aho-corasick",
"memchr",
···
[[package]]
name = "regex-automata"
+
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
dependencies = [
"aho-corasick",
"memchr",
···
[[package]]
name = "regex-syntax"
+
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "rustc-demangle"
+
version = "0.1.25"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f"
+
+
[[package]]
+
name = "rustversion"
+
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d"
[[package]]
name = "ryu"
+
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
[[package]]
name = "scopeguard"
···
[[package]]
name = "serde"
+
version = "1.0.219"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
+
version = "1.0.219"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
dependencies = [
"proc-macro2",
"quote",
···
[[package]]
name = "serde_json"
+
version = "1.0.140"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
dependencies = [
"itoa",
+
"memchr",
"ryu",
"serde",
]
···
]
[[package]]
+
name = "shlex"
+
version = "1.3.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
+
[[package]]
name = "signal-hook-registry"
+
version = "1.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410"
dependencies = [
"libc",
]
[[package]]
+
name = "simple-eyre"
+
version = "0.3.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "1b561532e8ffe7ecf09108c4f662896a9ec3eac4999eba84015ec3dcb8cc630a"
+
dependencies = [
+
"eyre",
+
"indenter",
+
]
+
+
[[package]]
name = "slab"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
[[package]]
name = "smallvec"
+
version = "1.15.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
+
+
[[package]]
+
name = "strsim"
+
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "syn"
+
version = "2.0.102"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "f6397daf94fa90f058bd0fd88429dd9e5738999cca8d701813c80723add80462"
dependencies = [
"proc-macro2",
"quote",
···
]
[[package]]
+
name = "thiserror"
+
version = "2.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
dependencies = [
+
"thiserror-impl",
]
[[package]]
+
name = "thiserror-impl"
+
version = "2.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
dependencies = [
+
"proc-macro2",
+
"quote",
+
"syn",
]
[[package]]
+
name = "thread_local"
+
version = "1.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
+
dependencies = [
+
"cfg-if",
+
"once_cell",
+
]
[[package]]
name = "tokio"
+
version = "1.45.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779"
dependencies = [
"backtrace",
"bytes",
"libc",
"mio",
"parking_lot",
"pin-project-lite",
"signal-hook-registry",
"tokio-macros",
+
"windows-sys 0.52.0",
]
[[package]]
name = "tokio-macros"
+
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
dependencies = [
"proc-macro2",
"quote",
···
[[package]]
name = "tokio-stream"
+
version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047"
dependencies = [
"futures-core",
"pin-project-lite",
···
[[package]]
name = "tracing"
+
version = "0.1.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
dependencies = [
"pin-project-lite",
"tracing-core",
···
[[package]]
name = "tracing-core"
+
version = "0.1.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678"
dependencies = [
"once_cell",
"valuable",
···
[[package]]
name = "tracing-error"
+
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "8b1581020d7a273442f5b45074a6a57d5757ad0a47dac0e9f0bd57b81936f3db"
dependencies = [
"tracing",
"tracing-subscriber",
···
[[package]]
name = "tracing-subscriber"
+
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008"
dependencies = [
"sharded-slab",
"thread_local",
···
[[package]]
name = "trash"
+
version = "5.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "22746c6b0c6d85d60a8f0d858f7057dfdf11297c132679f452ec908fba42b871"
dependencies = [
"chrono",
"libc",
"log",
+
"objc2",
+
"objc2-foundation",
"once_cell",
+
"percent-encoding",
"scopeguard",
+
"urlencoding",
"windows",
]
[[package]]
+
name = "typeid"
+
version = "1.0.3"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c"
+
+
[[package]]
name = "typetag"
+
version = "0.2.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "73f22b40dd7bfe8c14230cf9702081366421890435b2d625fa92b4acc4c3de6f"
dependencies = [
"erased-serde",
"inventory",
···
[[package]]
name = "typetag-impl"
+
version = "0.2.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "35f5380909ffc31b4de4f4bdf96b877175a016aa2ca98cee39fcfd8c4d53d952"
dependencies = [
"proc-macro2",
"quote",
···
]
[[package]]
+
name = "unicode-ident"
+
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
[[package]]
+
name = "urlencoding"
+
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
[[package]]
+
name = "utf8parse"
+
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
+
name = "uuid"
+
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d"
dependencies = [
+
"js-sys",
+
"wasm-bindgen",
]
[[package]]
name = "valuable"
+
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
[[package]]
name = "wasi"
···
[[package]]
name = "wasm-bindgen"
+
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
dependencies = [
"cfg-if",
+
"once_cell",
+
"rustversion",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
+
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
dependencies = [
"bumpalo",
"log",
"proc-macro2",
"quote",
"syn",
···
[[package]]
name = "wasm-bindgen-macro"
+
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
···
[[package]]
name = "wasm-bindgen-macro-support"
+
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
dependencies = [
"proc-macro2",
"quote",
···
[[package]]
name = "wasm-bindgen-shared"
+
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
+
dependencies = [
+
"unicode-ident",
+
]
[[package]]
name = "wildmatch"
+
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "68ce1ab1f8c62655ebe1350f589c61e505cf94d385bc6a12899442d9081e71fd"
[[package]]
name = "windows"
+
version = "0.56.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "1de69df01bdf1ead2f4ac895dc77c9351aefff65b2f3db429a343f9cbf05e132"
dependencies = [
+
"windows-core 0.56.0",
+
"windows-targets",
]
[[package]]
name = "windows-core"
+
version = "0.56.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "4698e52ed2d08f8658ab0c39512a7c00ee5fe2688c65f8c0a4f06750d729f2a6"
dependencies = [
+
"windows-implement 0.56.0",
+
"windows-interface 0.56.0",
+
"windows-result 0.1.2",
+
"windows-targets",
]
[[package]]
+
name = "windows-core"
+
version = "0.61.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3"
dependencies = [
+
"windows-implement 0.60.0",
+
"windows-interface 0.59.1",
+
"windows-link",
+
"windows-result 0.3.4",
+
"windows-strings",
]
[[package]]
+
name = "windows-implement"
+
version = "0.56.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b"
dependencies = [
+
"proc-macro2",
+
"quote",
+
"syn",
]
[[package]]
+
name = "windows-implement"
+
version = "0.60.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
dependencies = [
+
"proc-macro2",
+
"quote",
+
"syn",
]
[[package]]
+
name = "windows-interface"
+
version = "0.56.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc"
dependencies = [
+
"proc-macro2",
+
"quote",
+
"syn",
]
[[package]]
+
name = "windows-interface"
+
version = "0.59.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
+
dependencies = [
+
"proc-macro2",
+
"quote",
+
"syn",
+
]
[[package]]
+
name = "windows-link"
+
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38"
[[package]]
+
name = "windows-result"
+
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8"
+
dependencies = [
+
"windows-targets",
+
]
[[package]]
+
name = "windows-result"
+
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6"
+
dependencies = [
+
"windows-link",
+
]
[[package]]
+
name = "windows-strings"
+
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57"
+
dependencies = [
+
"windows-link",
+
]
[[package]]
+
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
+
dependencies = [
+
"windows-targets",
+
]
[[package]]
+
name = "windows-sys"
+
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
+
dependencies = [
+
"windows-targets",
+
]
[[package]]
+
name = "windows-targets"
+
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
+
dependencies = [
+
"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.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
+
name = "windows_aarch64_msvc"
+
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
+
name = "windows_i686_gnu"
+
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
+
name = "windows_i686_gnullvm"
+
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
+
name = "windows_i686_msvc"
+
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
+
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
+
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
+
name = "windows_x86_64_msvc"
+
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
+
name = "xshell"
+
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "9e7290c623014758632efe00737145b6867b66292c42167f2ec381eb566a373d"
+
dependencies = [
+
"xshell-macros",
+
]
[[package]]
+
name = "xshell-macros"
+
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "32ac00cd3f8ec9c1d33fb3e7958a82df6989c42d747bd326c822b1d625283547"
[[package]]
+
name = "xtask"
+
version = "0.1.0"
+
dependencies = [
+
"simple-eyre",
+
"xshell",
+
]
+7 -20
Cargo.toml
···
-
[package]
-
name = "ptsd"
-
version = "0.1.0"
-
edition = "2021"
-
-
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-
[dependencies]
-
async-stream = "0.3.5"
-
async-trait = "0.1.77"
-
color-eyre = "0.6.2"
-
futures = "0.3.30"
-
libc = "0.2.152"
-
regex = "1.10.2"
-
serde = { version = "1.0.195", features = ["derive"] }
-
serde_json = "1.0.111"
-
tokio = { version = "1.35.1", default-features = false, features = ["rt-multi-thread", "fs", "io-std", "io-util", "macros", "process", "parking_lot", "mio"] }
-
tokio-stream = { version = "0.1.14", features = ["fs"] }
-
trash = "3.2.0"
-
typetag = "0.2.15"
-
wildmatch = "2.3.0"
···
+
# SPDX-FileCopyrightText: 2024 Łukasz Niemier <#@hauleth.dev>
+
#
+
# SPDX-License-Identifier: EUPL-1.2
+
[workspace]
+
resolver = "2"
+
default-members = [ "cli" ]
+
members = [ "cli", "xtask"]
+190
LICENSES/EUPL-1.2.txt
···
···
+
EUROPEAN UNION PUBLIC LICENCE v. 1.2
+
EUPL © the European Union 2007, 2016
+
+
This European Union Public Licence (the ‘EUPL’) applies to the Work (as defined below) which is provided under the
+
terms of this Licence. Any use of the Work, other than as authorised under this Licence is prohibited (to the extent such
+
use is covered by a right of the copyright holder of the Work).
+
The Work is provided under the terms of this Licence when the Licensor (as defined below) has placed the following
+
notice immediately following the copyright notice for the Work:
+
Licensed under the EUPL
+
or has expressed by any other means his willingness to license under the EUPL.
+
+
1.Definitions
+
In this Licence, the following terms have the following meaning:
+
— ‘The Licence’:this Licence.
+
— ‘The Original Work’:the work or software distributed or communicated by the Licensor under this Licence, available
+
as Source Code and also as Executable Code as the case may be.
+
— ‘Derivative Works’:the works or software that could be created by the Licensee, based upon the Original Work or
+
modifications thereof. This Licence does not define the extent of modification or dependence on the Original Work
+
required in order to classify a work as a Derivative Work; this extent is determined by copyright law applicable in
+
the country mentioned in Article 15.
+
— ‘The Work’:the Original Work or its Derivative Works.
+
— ‘The Source Code’:the human-readable form of the Work which is the most convenient for people to study and
+
modify.
+
— ‘The Executable Code’:any code which has generally been compiled and which is meant to be interpreted by
+
a computer as a program.
+
— ‘The Licensor’:the natural or legal person that distributes or communicates the Work under the Licence.
+
— ‘Contributor(s)’:any natural or legal person who modifies the Work under the Licence, or otherwise contributes to
+
the creation of a Derivative Work.
+
— ‘The Licensee’ or ‘You’:any natural or legal person who makes any usage of the Work under the terms of the
+
Licence.
+
— ‘Distribution’ or ‘Communication’:any act of selling, giving, lending, renting, distributing, communicating,
+
transmitting, or otherwise making available, online or offline, copies of the Work or providing access to its essential
+
functionalities at the disposal of any other natural or legal person.
+
+
2.Scope of the rights granted by the Licence
+
The Licensor hereby grants You a worldwide, royalty-free, non-exclusive, sublicensable licence to do the following, for
+
the duration of copyright vested in the Original Work:
+
— use the Work in any circumstance and for all usage,
+
— reproduce the Work,
+
— modify the Work, and make Derivative Works based upon the Work,
+
— communicate to the public, including the right to make available or display the Work or copies thereof to the public
+
and perform publicly, as the case may be, the Work,
+
— distribute the Work or copies thereof,
+
— lend and rent the Work or copies thereof,
+
— sublicense rights in the Work or copies thereof.
+
Those rights can be exercised on any media, supports and formats, whether now known or later invented, as far as the
+
applicable law permits so.
+
In the countries where moral rights apply, the Licensor waives his right to exercise his moral right to the extent allowed
+
by law in order to make effective the licence of the economic rights here above listed.
+
The Licensor grants to the Licensee royalty-free, non-exclusive usage rights to any patents held by the Licensor, to the
+
extent necessary to make use of the rights granted on the Work under this Licence.
+
+
3.Communication of the Source Code
+
The Licensor may provide the Work either in its Source Code form, or as Executable Code. If the Work is provided as
+
Executable Code, the Licensor provides in addition a machine-readable copy of the Source Code of the Work along with
+
each copy of the Work that the Licensor distributes or indicates, in a notice following the copyright notice attached to
+
the Work, a repository where the Source Code is easily and freely accessible for as long as the Licensor continues to
+
distribute or communicate the Work.
+
+
4.Limitations on copyright
+
Nothing in this Licence is intended to deprive the Licensee of the benefits from any exception or limitation to the
+
exclusive rights of the rights owners in the Work, of the exhaustion of those rights or of other applicable limitations
+
thereto.
+
+
5.Obligations of the Licensee
+
The grant of the rights mentioned above is subject to some restrictions and obligations imposed on the Licensee. Those
+
obligations are the following:
+
+
Attribution right: The Licensee shall keep intact all copyright, patent or trademarks notices and all notices that refer to
+
the Licence and to the disclaimer of warranties. The Licensee must include a copy of such notices and a copy of the
+
Licence with every copy of the Work he/she distributes or communicates. The Licensee must cause any Derivative Work
+
to carry prominent notices stating that the Work has been modified and the date of modification.
+
+
Copyleft clause: If the Licensee distributes or communicates copies of the Original Works or Derivative Works, this
+
Distribution or Communication will be done under the terms of this Licence or of a later version of this Licence unless
+
the Original Work is expressly distributed only under this version of the Licence — for example by communicating
+
‘EUPL v. 1.2 only’. The Licensee (becoming Licensor) cannot offer or impose any additional terms or conditions on the
+
Work or Derivative Work that alter or restrict the terms of the Licence.
+
+
Compatibility clause: If the Licensee Distributes or Communicates Derivative Works or copies thereof based upon both
+
the Work and another work licensed under a Compatible Licence, this Distribution or Communication can be done
+
under the terms of this Compatible Licence. For the sake of this clause, ‘Compatible Licence’ refers to the licences listed
+
in the appendix attached to this Licence. Should the Licensee's obligations under the Compatible Licence conflict with
+
his/her obligations under this Licence, the obligations of the Compatible Licence shall prevail.
+
+
Provision of Source Code: When distributing or communicating copies of the Work, the Licensee will provide
+
a machine-readable copy of the Source Code or indicate a repository where this Source will be easily and freely available
+
for as long as the Licensee continues to distribute or communicate the Work.
+
Legal Protection: This Licence does not grant permission to use the trade names, trademarks, service marks, or names
+
of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and
+
reproducing the content of the copyright notice.
+
+
6.Chain of Authorship
+
The original Licensor warrants that the copyright in the Original Work granted hereunder is owned by him/her or
+
licensed to him/her and that he/she has the power and authority to grant the Licence.
+
Each Contributor warrants that the copyright in the modifications he/she brings to the Work are owned by him/her or
+
licensed to him/her and that he/she has the power and authority to grant the Licence.
+
Each time You accept the Licence, the original Licensor and subsequent Contributors grant You a licence to their contributions
+
to the Work, under the terms of this Licence.
+
+
7.Disclaimer of Warranty
+
The Work is a work in progress, which is continuously improved by numerous Contributors. It is not a finished work
+
and may therefore contain defects or ‘bugs’ inherent to this type of development.
+
For the above reason, the Work is provided under the Licence on an ‘as is’ basis and without warranties of any kind
+
concerning the Work, including without limitation merchantability, fitness for a particular purpose, absence of defects or
+
errors, accuracy, non-infringement of intellectual property rights other than copyright as stated in Article 6 of this
+
Licence.
+
This disclaimer of warranty is an essential part of the Licence and a condition for the grant of any rights to the Work.
+
+
8.Disclaimer of Liability
+
Except in the cases of wilful misconduct or damages directly caused to natural persons, the Licensor will in no event be
+
liable for any direct or indirect, material or moral, damages of any kind, arising out of the Licence or of the use of the
+
Work, including without limitation, damages for loss of goodwill, work stoppage, computer failure or malfunction, loss
+
of data or any commercial damage, even if the Licensor has been advised of the possibility of such damage. However,
+
the Licensor will be liable under statutory product liability laws as far such laws apply to the Work.
+
+
9.Additional agreements
+
While distributing the Work, You may choose to conclude an additional agreement, defining obligations or services
+
consistent with this Licence. However, if accepting obligations, You may act only on your own behalf and on your sole
+
responsibility, not on behalf of the original Licensor or any other Contributor, and only if You agree to indemnify,
+
defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against such Contributor by
+
the fact You have accepted any warranty or additional liability.
+
+
10.Acceptance of the Licence
+
The provisions of this Licence can be accepted by clicking on an icon ‘I agree’ placed under the bottom of a window
+
displaying the text of this Licence or by affirming consent in any other similar way, in accordance with the rules of
+
applicable law. Clicking on that icon indicates your clear and irrevocable acceptance of this Licence and all of its terms
+
and conditions.
+
Similarly, you irrevocably accept this Licence and all of its terms and conditions by exercising any rights granted to You
+
by Article 2 of this Licence, such as the use of the Work, the creation by You of a Derivative Work or the Distribution
+
or Communication by You of the Work or copies thereof.
+
+
11.Information to the public
+
In case of any Distribution or Communication of the Work by means of electronic communication by You (for example,
+
by offering to download the Work from a remote location) the distribution channel or media (for example, a website)
+
must at least provide to the public the information requested by the applicable law regarding the Licensor, the Licence
+
and the way it may be accessible, concluded, stored and reproduced by the Licensee.
+
+
12.Termination of the Licence
+
The Licence and the rights granted hereunder will terminate automatically upon any breach by the Licensee of the terms
+
of the Licence.
+
Such a termination will not terminate the licences of any person who has received the Work from the Licensee under
+
the Licence, provided such persons remain in full compliance with the Licence.
+
+
13.Miscellaneous
+
Without prejudice of Article 9 above, the Licence represents the complete agreement between the Parties as to the
+
Work.
+
If any provision of the Licence is invalid or unenforceable under applicable law, this will not affect the validity or
+
enforceability of the Licence as a whole. Such provision will be construed or reformed so as necessary to make it valid
+
and enforceable.
+
The European Commission may publish other linguistic versions or new versions of this Licence or updated versions of
+
the Appendix, so far this is required and reasonable, without reducing the scope of the rights granted by the Licence.
+
New versions of the Licence will be published with a unique version number.
+
All linguistic versions of this Licence, approved by the European Commission, have identical value. Parties can take
+
advantage of the linguistic version of their choice.
+
+
14.Jurisdiction
+
Without prejudice to specific agreement between parties,
+
— any litigation resulting from the interpretation of this License, arising between the European Union institutions,
+
bodies, offices or agencies, as a Licensor, and any Licensee, will be subject to the jurisdiction of the Court of Justice
+
of the European Union, as laid down in article 272 of the Treaty on the Functioning of the European Union,
+
— any litigation arising between other parties and resulting from the interpretation of this License, will be subject to
+
the exclusive jurisdiction of the competent court where the Licensor resides or conducts its primary business.
+
+
15.Applicable Law
+
Without prejudice to specific agreement between parties,
+
— this Licence shall be governed by the law of the European Union Member State where the Licensor has his seat,
+
resides or has his registered office,
+
— this licence shall be governed by Belgian law if the Licensor has no seat, residence or registered office inside
+
a European Union Member State.
+
+
+
Appendix
+
+
‘Compatible Licences’ according to Article 5 EUPL are:
+
— GNU General Public License (GPL) v. 2, v. 3
+
— GNU Affero General Public License (AGPL) v. 3
+
— Open Software License (OSL) v. 2.1, v. 3.0
+
— Eclipse Public License (EPL) v. 1.0
+
— CeCILL v. 2.0, v. 2.1
+
— Mozilla Public Licence (MPL) v. 2
+
— GNU Lesser General Public Licence (LGPL) v. 2.1, v. 3
+
— Creative Commons Attribution-ShareAlike v. 3.0 Unported (CC BY-SA 3.0) for works other than software
+
— European Union Public Licence (EUPL) v. 1.1, v. 1.2
+
— Québec Free and Open-Source Licence — Reciprocity (LiLiQ-R) or Strong Reciprocity (LiLiQ-R+).
+
+
The European Commission may update this Appendix to later versions of the above licences without producing
+
a new version of the EUPL, as long as they provide the rights granted in Article 2 of this Licence and protect the
+
covered Source Code from exclusive appropriation.
+
All other changes or additions to this Appendix require the production of a new EUPL version.
+28 -6
README.md
···
# PTSD
Simple tool for automatic file management. Basically `find … -exec`/`fd … --exec`
with configuration file.
## Name
-
It stands for *Python Tremendously Suck Dicks* and it was created in anger after
-
I tried to package [`organize`][] for Nix. It was pain, even when I was working
alongside of one of Poetry maintainers. So as that experience was quite
suboptimal I come up with idea of writing such project on my own and I have gave
it a name that relates to the experience I had with Python.
Hopefully this will be simpler to write and to package it as a Rust project
rather than Python.
-
-
[`organize`]: https://github.com/tfeldmann/organize/tree/main
## Why Rust?
···
need other formats can be easily added as `ptsd` uses Rust's Serde, which allows
us to easily add new formats in the future if needed.
## License
-
I haven't decided yet, so for now we can assume WTFLPL, but it will for sure
-
change in future.
···
+
<!--
+
SPDX-FileCopyrightText: 2024 Łukasz Niemier <#@hauleth.dev>
+
+
SPDX-License-Identifier: EUPL-1.2
+
-->
+
# PTSD
+
[![builds.sr.ht status](https://builds.sr.ht/~hauleth/ptsd.svg)](https://builds.sr.ht/~hauleth/ptsd?)
+
Simple tool for automatic file management. Basically `find … -exec`/`fd … --exec`
with configuration file.
## Name
+
It stands for *Python Tremendously Sucks Dicks* and it was created in anger after
+
I tried to package [Organize][] for Nix. It was pain, even when I was working
alongside of one of Poetry maintainers. So as that experience was quite
suboptimal I come up with idea of writing such project on my own and I have gave
it a name that relates to the experience I had with Python.
Hopefully this will be simpler to write and to package it as a Rust project
rather than Python.
## Why Rust?
···
need other formats can be easily added as `ptsd` uses Rust's Serde, which allows
us to easily add new formats in the future if needed.
+
## Similar tools
+
+
- [Organize][] - written in Python, was "inspiration" to write this tool as
+
packaging this tool for Nixpkgs was a horror. So instead I come up with an
+
idea to write my own.
+
- [Maid][] - written in Ruby, I wanted to use that, but it seems to be a little
+
bit stalled. Also wanted something that would be easier to manage from Nixpkgs
+
instead of separate DSL.
+
- [Hazel][] - commercial software for macOS, with GUI and stuff, but I am
+
developer so instead of spending few minutes of my work (in USD) I prefer to
+
waste few days of my life on writing tool on my own. Also see above about the
+
Nixpkgs stuff.
+
+
[Organize]: https://github.com/tfeldmann/organize
+
[Maid]: https://github.com/maid/maid
+
[Hazel]: https://www.noodlesoft.com
+
## License
+
EUPL-1.2 or later
+10
REUSE.toml
···
···
+
version = 1
+
SPDX-PackageName = "PTSD"
+
SPDX-PackageSupplier = "Łukasz Niemier <#@hauleth.dev>"
+
SPDX-PackageDownloadLocation = "https://git.sr.ht/~hauleth/ptsd"
+
+
[[annotations]]
+
path = "**.lock"
+
precedence = "aggregate"
+
SPDX-FileCopyrightText = "2024 Łukasz Niemier <#@hauleth.dev>"
+
SPDX-License-Identifier = "EUPL-1.2"
+28
cli/Cargo.toml
···
···
+
# SPDX-FileCopyrightText: 2024 Łukasz Niemier <#@hauleth.dev>
+
#
+
# SPDX-License-Identifier: EUPL-1.2
+
+
[package]
+
name = "ptsd"
+
version = "0.1.0"
+
edition = "2021"
+
+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+
[dependencies]
+
async-stream = "0.3.5"
+
async-trait = "0.1.77"
+
clap = { version = "4.4.16", features = ["derive"] }
+
color-eyre = "0.6.2"
+
dirs = "6"
+
futures = "0.3.30"
+
infer = { version = "0.19.0", default-features = false, features = ["alloc", "cfb"] }
+
libc = "0.2.152"
+
regex = "1.10.2"
+
serde = { version = "1.0.195", features = ["derive"] }
+
serde_json = "1.0.111"
+
tokio = { version = "1.35.1", default-features = false, features = ["rt-multi-thread", "fs", "io-std", "io-util", "macros", "process", "parking_lot", "mio"] }
+
tokio-stream = { version = "0.1.14", features = ["fs"] }
+
trash = "5.0"
+
typetag = "0.2.15"
+
wildmatch = "2.3.0"
+79
cli/src/actions.rs
···
···
+
// SPDX-FileCopyrightText: 2024 Łukasz Niemier <#@hauleth.dev>
+
//
+
// SPDX-License-Identifier: EUPL-1.2
+
+
use tokio::fs;
+
use tokio::process::Command;
+
+
use std::path::{Path, PathBuf};
+
+
/// Actions available for file
+
#[derive(Clone, Debug, serde::Deserialize)]
+
#[serde(rename_all = "snake_case")]
+
pub enum Action {
+
/// Run given script with 1st argument. It will be ran in parent directory for given file
+
Script(Box<Path>),
+
/// Move given file to new destination
+
Move(Box<Path>),
+
/// Copy given file to new destination
+
Copy(Box<Path>),
+
/// Print message and do nothing
+
Echo(String),
+
/// Move to trash
+
Trash,
+
}
+
+
impl Action {
+
pub async fn run(self, source: PathBuf, execute: bool) {
+
self.dry_run(&source).await;
+
+
if execute {
+
self.execute(source).await
+
}
+
}
+
+
pub async fn dry_run(&self, source: &Path) {
+
match self {
+
Action::Script(ref script) => println!("Execute {script:?} {source:?}"),
+
Action::Move(ref dest) => println!("Move {source:?} -> {dest:?}"),
+
Action::Copy(ref dest) => println!("Copy {source:?} -> {dest:?}"),
+
Action::Echo(ref message) => println!("{source:?} - {message}"),
+
Action::Trash => println!("Move {source:?} to trash"),
+
}
+
}
+
+
pub async fn execute(self, source: PathBuf) {
+
match self {
+
Action::Script(ref script) => {
+
Command::new(script.as_ref())
+
.arg(&source)
+
.current_dir(source.parent().unwrap())
+
.spawn()
+
.expect("Couldnt spawn process")
+
.wait()
+
.await
+
.expect("Child exited abnormally");
+
}
+
+
Action::Copy(ref dest_dir) => {
+
let dest = crate::job::normalise_path(dest_dir).join(source.file_name().unwrap());
+
fs::copy(&source, dest).await.expect("Couldnt copy file");
+
}
+
+
Action::Move(ref dest_dir) => {
+
let dest = crate::job::normalise_path(dest_dir).join(source.file_name().unwrap());
+
if let Err(err) = fs::rename(&source, &dest).await {
+
if err.raw_os_error() == Some(libc::EXDEV) {
+
panic!("X dev");
+
} else {
+
panic!("Cannot move {source:?} -> {dest:?}: {err:?}");
+
}
+
}
+
}
+
+
Action::Echo(ref message) => println!("{source:?} - {message}"),
+
+
Action::Trash => trash::delete(source).unwrap(),
+
}
+
}
+
}
+212
cli/src/filters.rs
···
···
+
// SPDX-FileCopyrightText: 2024 Łukasz Niemier <#@hauleth.dev>
+
//
+
// SPDX-License-Identifier: EUPL-1.2
+
+
use std::path::Path;
+
+
use async_trait::async_trait;
+
use serde::Deserialize;
+
+
use tokio::fs;
+
use tokio::io::{self, AsyncReadExt, AsyncSeekExt};
+
+
use futures::prelude::*;
+
+
use crate::pattern::Pattern;
+
+
#[typetag::deserialize(tag = "type")]
+
#[async_trait]
+
pub trait Filter: std::fmt::Debug + Sync {
+
async fn matches(&self, path: &Path) -> bool;
+
}
+
+
macro_rules! filter {
+
{
+
$name:literal;
+
$(#[$sattr:meta])*
+
struct $sname:ident {$($(#[$attr:meta])* $fname:ident : $ftype:ty,)*};
+
($self_:ident, $path:ident) -> $body:block
+
} => {
+
#[derive(Debug, serde::Deserialize)]
+
$(#[$sattr])*
+
pub struct $sname { $($(#[$attr])* $fname: $ftype),* }
+
+
#[typetag::deserialize(name = $name)]
+
#[async_trait]
+
impl Filter for $sname {
+
async fn matches(&$self_, $path: &Path) -> bool {
+
$body
+
}
+
}
+
};
+
+
{
+
$name:literal;
+
$(#[$sattr:meta])*
+
struct $sname:ident ($($field:ty),*);
+
($self_:ident, $path:ident) -> $body:block
+
} => {
+
#[derive(Debug, serde::Deserialize)]
+
$(#[$sattr])*
+
pub struct $sname ($($field),*);
+
+
#[typetag::deserialize(name = $name)]
+
#[async_trait]
+
impl Filter for $sname {
+
async fn matches(&$self_, $path: &Path) -> bool {
+
$body
+
}
+
}
+
}
+
}
+
+
filter! {
+
"name";
+
struct Name(Pattern);
+
(self, path) -> {
+
self.0.matches(path)
+
}
+
}
+
+
#[derive(Deserialize)]
+
#[serde(remote = "std::cmp::Ordering")]
+
#[serde(rename_all = "snake_case")]
+
enum Ordering {
+
Less,
+
Equal,
+
Greater,
+
}
+
+
impl Ordering {
+
fn default() -> std::cmp::Ordering { std::cmp::Ordering::Equal }
+
}
+
+
filter! {
+
"size";
+
struct Size {
+
size: u64,
+
#[serde(with = "Ordering", default = "Ordering::default")]
+
ordering: std::cmp::Ordering,
+
};
+
(self, path) -> {
+
with_metadata(path, |metadata| {
+
let len = metadata.len();
+
+
len.cmp(&self.size) == self.ordering
+
})
+
.await
+
}
+
}
+
+
#[derive(Debug, Deserialize)]
+
#[serde(tag = "is", rename_all = "snake_case")]
+
pub enum FileType {
+
Dir,
+
File,
+
Symlink,
+
}
+
+
#[typetag::deserialize(name = "file_type")]
+
#[async_trait]
+
impl Filter for FileType {
+
async fn matches(&self, path: &Path) -> bool {
+
use FileType::*;
+
+
with_metadata(path, |metadata| {
+
let ft = metadata.file_type();
+
+
match *self {
+
Dir => ft.is_dir(),
+
File => ft.is_file(),
+
Symlink => ft.is_symlink(),
+
}
+
})
+
.await
+
}
+
}
+
+
async fn with_metadata<F>(path: &Path, fun: F) -> bool
+
where
+
F: FnOnce(std::fs::Metadata) -> bool,
+
{
+
fs::metadata(path).await.map(fun).unwrap_or(false)
+
}
+
+
filter! {
+
"not";
+
struct Not { filter: Box<dyn Filter>, };
+
(self, path) -> {
+
!self.filter.matches(path).await
+
}
+
}
+
+
filter! {
+
"any";
+
struct Any { filters: Box<[Box<dyn Filter>]>, };
+
(self, path) -> {
+
stream::iter(&*self.filters)
+
.any(|f| f.matches(path))
+
.await
+
}
+
}
+
+
filter! {
+
"all";
+
struct All { filters: Box<[Box<dyn Filter>]>, };
+
(self, path) -> {
+
stream::iter(&*self.filters)
+
.all(|f| f.matches(path))
+
.await
+
}
+
}
+
+
#[derive(Debug, Deserialize)]
+
#[serde(rename_all = "snake_case")]
+
pub enum Magic {
+
Mime(String),
+
Magic {
+
bytes: Box<[u8]>,
+
#[serde(default)]
+
offset: u64,
+
},
+
}
+
+
async fn read_first_bytes(n: usize, path: &Path, offset: u64) -> io::Result<Box<[u8]>> {
+
use std::io::SeekFrom;
+
+
let mut file = fs::File::open(path).await?;
+
+
let mut buf = vec![0; n];
+
+
file.seek(SeekFrom::Start(offset)).await?;
+
file.read_exact(&mut buf).await?;
+
+
Ok(buf.into())
+
}
+
+
async fn guess_mime(path: &Path) -> Option<infer::Type> {
+
let mut file = fs::File::open(path).await.ok()?;
+
+
let mut buf = vec![0; 8192];
+
+
let len = file.read(&mut buf).await.ok()?;
+
+
infer::get(&buf[0..len])
+
}
+
+
#[typetag::deserialize(name = "content_type")]
+
#[async_trait]
+
impl Filter for Magic {
+
async fn matches(&self, file: &Path) -> bool {
+
match *self {
+
Self::Magic { ref bytes, offset } => read_first_bytes(bytes.len(), file, offset)
+
.await
+
.map(|read| read == *bytes)
+
.unwrap_or(false),
+
Self::Mime(ref mime_type) => guess_mime(file)
+
.await
+
.map(|typ| typ.mime_type() == mime_type)
+
.unwrap_or(false),
+
}
+
}
+
}
+52
cli/src/job.rs
···
···
+
// SPDX-FileCopyrightText: 2024 Łukasz Niemier <#@hauleth.dev>
+
//
+
// SPDX-License-Identifier: EUPL-1.2
+
+
use color_eyre::eyre::Result;
+
+
use std::path::{Path, PathBuf};
+
+
use tokio::fs;
+
use tokio_stream::wrappers::ReadDirStream;
+
+
use serde::Deserialize;
+
+
use crate::actions::Action;
+
use crate::filters::Filter;
+
+
/// Definition of the job files
+
#[derive(Debug, Deserialize)]
+
pub struct Job {
+
filter: Box<dyn Filter>,
+
location: PathBuf,
+
actions: Vec<Action>,
+
}
+
+
impl Job {
+
/// Returns stream of actions that should be executed
+
pub async fn actions(
+
&self,
+
) -> Result<impl tokio_stream::Stream<Item = (Action, PathBuf)> + '_> {
+
let loc = normalise_path(&self.location);
+
+
let dir = ReadDirStream::new(fs::read_dir(&loc).await?);
+
+
Ok(async_stream::stream! {
+
for await entry in dir {
+
let entry = entry.unwrap();
+
if self.filter.matches(&entry.path()).await {
+
for action in &self.actions {
+
yield (action.clone(), entry.path())
+
}
+
}
+
}
+
})
+
}
+
}
+
+
pub(crate) fn normalise_path(path: &Path) -> PathBuf {
+
match path.strip_prefix("~") {
+
Ok(prefix) => dirs::home_dir().unwrap().join(prefix),
+
Err(_) => path.to_owned(),
+
}
+
}
+61
cli/src/main.rs
···
···
+
// SPDX-FileCopyrightText: 2024 Łukasz Niemier <#@hauleth.dev>
+
//
+
// SPDX-License-Identifier: EUPL-1.2
+
+
use clap::Parser;
+
use color_eyre::eyre::Result;
+
use futures::prelude::*;
+
+
use std::io::Read;
+
+
mod actions;
+
mod filters;
+
mod job;
+
mod pattern;
+
+
#[derive(Debug, Parser)]
+
struct Args {
+
spec: Option<std::path::PathBuf>,
+
/// Run specified commands instead of printing them
+
#[arg(long = "no-dry-run", short = '!')]
+
execute: bool,
+
#[arg(long)]
+
stdin: bool,
+
}
+
+
impl Args {
+
fn data(&self) -> Result<Box<dyn Read>> {
+
Ok(match self.spec {
+
Some(ref path) if !self.stdin => Box::new(std::fs::File::open(path)?),
+
None if self.stdin => Box::new(std::io::stdin()),
+
_ => unimplemented!(),
+
})
+
}
+
}
+
+
#[tokio::main]
+
async fn main() -> Result<()> {
+
let args = Args::parse();
+
+
let reader = args.data()?;
+
+
let jobs: Vec<job::Job> = serde_json::from_reader(reader)?;
+
+
let tasks: Vec<_> = stream::iter(&jobs)
+
.then(|job| job.actions())
+
.try_collect()
+
.await?;
+
+
if !args.execute {
+
println!("Dry run, to apply changes run with flag `-!`\n");
+
}
+
+
//let out =
+
stream::iter(tasks)
+
.flatten()
+
.then(|(action, path)| action.run(path, args.execute))
+
.count()
+
.await;
+
+
Ok(())
+
}
+84
cli/src/pattern.rs
···
···
+
// SPDX-FileCopyrightText: 2024 Łukasz Niemier <#@hauleth.dev>
+
//
+
// SPDX-License-Identifier: EUPL-1.2
+
+
use std::fmt;
+
use std::path::Path;
+
+
use serde::{de, Deserialize};
+
use wildmatch::WildMatch;
+
+
/// Patterns that can be matched against files
+
#[derive(Debug, Deserialize)]
+
#[serde(rename_all = "snake_case")]
+
pub enum Pattern {
+
#[serde(deserialize_with = "deserialize_wildcard")]
+
Wildcard(WildMatch),
+
#[serde(deserialize_with = "deserialize_regex")]
+
Regex(regex::Regex),
+
Exact(Box<Path>),
+
}
+
+
impl Pattern {
+
pub fn matches(&self, path: &Path) -> bool {
+
match *self {
+
Self::Wildcard(ref pattern) => pattern.matches(path.to_str().unwrap()),
+
Self::Regex(ref pattern) => pattern.is_match(path.to_str().unwrap()),
+
Self::Exact(ref pattern) => **pattern == *path,
+
}
+
}
+
}
+
+
struct RegexVisitor;
+
+
impl<'de> de::Visitor<'de> for RegexVisitor {
+
type Value = regex::Regex;
+
+
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+
write!(formatter, "expected regex string")
+
}
+
+
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
+
where
+
E: de::Error,
+
{
+
match regex::Regex::new(s) {
+
Ok(regex) => Ok(regex),
+
Err(regex::Error::Syntax(ref desc)) => {
+
Err(E::invalid_value(de::Unexpected::Str(s), &desc.as_str()))
+
}
+
Err(_) => unreachable!(),
+
}
+
}
+
}
+
+
fn deserialize_regex<'de, D>(des: D) -> Result<regex::Regex, D::Error>
+
where
+
D: serde::Deserializer<'de>,
+
{
+
des.deserialize_str(RegexVisitor)
+
}
+
+
struct WildcardVisitor;
+
+
impl<'de> de::Visitor<'de> for WildcardVisitor {
+
type Value = WildMatch;
+
+
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+
write!(formatter, "expected regex string")
+
}
+
+
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
+
where
+
E: de::Error,
+
{
+
Ok(WildMatch::new(s))
+
}
+
}
+
+
fn deserialize_wildcard<'de, D>(des: D) -> Result<WildMatch, D::Error>
+
where
+
D: serde::Deserializer<'de>,
+
{
+
des.deserialize_str(WildcardVisitor)
+
}
+105
docs/ptsd.json.5.scd
···
···
+
PTSD.JSON(5) "git.sr.ht/~hauleth/ptsd" "File Formats Manual"
+
+
# NAME
+
+
ptsd.json - actions specification for _ptsd_(1)
+
+
# SYNTAX
+
+
The file should use JSON format with array as a top-level value. Entries of
+
these values should be objects containing at least these fields:
+
+
*location*
+
Directory which will be read for files.
+
+
*filter*
+
Object that defines filter that will select files on which actions will
+
be performed. See _FILTERS_.
+
+
*actions*
+
Array of actions to be performed on files. Actions will be performed
+
from top to bottom. *Moves are not followed*. See _ACTIONS_.
+
+
# FILTERS
+
+
Filters are in form:
+
+
{"type": "<filter_name>", <opts>}
+
+
Available filters are
+
+
*name*
+
Match name of the file against pattern. Available options (exclusive):
+
+
- *exact* - match name exactly
+
- *wildcard* - match name against wildcard pattern
+
- *regex* - match name against regular expression
+
+
*file_type*
+
Match OS type of the file.
+
+
Options:
+
+
- *is* - string that can be one of *dir*, *file*, *symlink* and will
+
return if subject of the test point to file of that type
+
+
*content_type*
+
Match against content type.
+
+
Options:
+
+
- *mime* - will try to deduce MIME type of the file and will look for
+
exact match
+
- *magic* - object with field *bytes* that is array of integers within
+
range 0..255 that describe magic bytes that will be read from the file
+
and matched. Optionally there can be also used option *offset* that
+
describes offset from the beginning of the file for the pattern.
+
+
*size*
+
Match against file size.
+
+
Options:
+
+
- *size* - value which will be compared with the file size
+
- *ordering* - one of *grater*, *equal*, *less* which determines what
+
comparison operator will be used.
+
+
+
There are also meta filters:
+
+
*not*
+
Takes one option *filter* and returns success if filter failed and vice
+
versa.
+
+
*all*
+
Takes one option *filters* which is a list of filters and will succeed
+
if and only if all filters in list are successful match.
+
+
*any*
+
Takes one option *filters* which is a list of filters and will succeed
+
if any of filters in list is successful match.
+
+
# ACTIONS
+
+
Current set of actions that are supported:
+
+
*{"script": "<path>"}*
+
Execute script located at _<path>_ with file name in the question passed
+
as first argument.
+
+
*{"move": "<dest>"}*
+
Move file to directory pointed by the _<dest>_.
+
+
*{"echo": "<msg>"}*
+
Show _<msg>_ next to the filename.
+
+
*"trash"*
+
Move file to trash in platform dependant way.
+
+
# AUTHORS
+
+
Created and maintained by: Łukasz Niemier <#@hauleth.dev>++
+
Sources available at: <https://git.sr.ht/~hauleth/ubin>++
+
Patches and bug reports: <~hauleth/public-inbox@lists.sr.ht>
+
+
; vim: noexpandtab
+3
docs/ptsd.json.5.scd.license
···
···
+
SPDX-FileCopyrightText: 2024 Łukasz Niemier <#@hauleth.dev>
+
+
SPDX-License-Identifier: EUPL-1.2
+16
examples/downloaded-gp-to-guitar.json
···
···
+
[
+
{
+
"location": "~/Downloads/",
+
"filter": {
+
"type": "any",
+
"filters": [
+
{"type": "name", "wildcard": "*.gp"},
+
{"type": "name", "wildcard": "*.gp4"},
+
{"type": "name", "wildcard": "*.gp5"}
+
]
+
},
+
"actions": [
+
{"move": "~/Documents/Guitar/"}
+
]
+
}
+
]
+3
examples/downloaded-gp-to-guitar.json.license
···
···
+
SPDX-FileCopyrightText: 2024 Łukasz Niemier <#@hauleth.dev>
+
+
SPDX-License-Identifier: EUPL-1.2
+19
examples/downloaded-gp-to-guitar.ncl
···
···
+
# SPDX-FileCopyrightText: 2024 Łukasz Niemier <#@hauleth.dev>
+
#
+
# SPDX-License-Identifier: EUPL-1.2
+
+
let Ptsd = import "../ptsd.ncl" in
+
Ptsd.build
+
[
+
{
+
location = "~/Downloads/",
+
filter =
+
'any [
+
'name ('wildcard "*.gp"),
+
'name ('wildcard "*.gp5"),
+
],
+
actions = [
+
'move "~/Documents/Guitar/"
+
]
+
},
+
]
+13
examples/images-in-downloads.json
···
···
+
[
+
{
+
"filter": {
+
"type": "all", "filters": [
+
{"type": "content_type", "mime": "image/png"}
+
]
+
},
+
"location": "~/Downloads",
+
"actions": [
+
"trash"
+
]
+
}
+
]
+3
examples/images-in-downloads.json.license
···
···
+
SPDX-FileCopyrightText: 2024 Łukasz Niemier <#@hauleth.dev>
+
+
SPDX-License-Identifier: EUPL-1.2
+275 -85
flake.lock
···
{
"nodes": {
"devenv": {
"inputs": {
"flake-compat": "flake-compat",
"nix": "nix",
-
"nixpkgs": "nixpkgs",
-
"pre-commit-hooks": "pre-commit-hooks"
},
"locked": {
-
"lastModified": 1704835383,
-
"narHash": "sha256-SoC0rYR9iHW0dVOEmxNEfa8vk9dTK86P5iXTgHafmwM=",
"owner": "cachix",
"repo": "devenv",
-
"rev": "18ef9849d1ecac7a9a7920eb4f2e4adcf67a8c3a",
"type": "github"
},
"original": {
···
"rust-analyzer-src": "rust-analyzer-src"
},
"locked": {
-
"lastModified": 1705040632,
-
"narHash": "sha256-x8mdmY4CKeHDB/eRAHC3YR1WA77IPCxWyijyEFrmwfQ=",
"owner": "nix-community",
"repo": "fenix",
-
"rev": "394b7565db9d174cf65326f094e0f558333dca82",
"type": "github"
},
"original": {
···
"flake-compat": {
"flake": false,
"locked": {
-
"lastModified": 1673956053,
-
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
"owner": "edolstra",
"repo": "flake-compat",
-
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
"type": "github"
},
"original": {
···
},
"flake-parts": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
-
"lastModified": 1704982712,
-
"narHash": "sha256-2Ptt+9h8dczgle2Oo6z5ni5rt/uLMG47UFTR1ry/wgg=",
"owner": "hercules-ci",
"repo": "flake-parts",
-
"rev": "07f6395285469419cf9d078f59b5b49993198c00",
"type": "github"
},
"original": {
···
"systems": "systems"
},
"locked": {
-
"lastModified": 1685518550,
-
"narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=",
"owner": "numtide",
"repo": "flake-utils",
-
"rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef",
"type": "github"
},
"original": {
···
"type": "github"
}
},
"gitignore": {
"inputs": {
"nixpkgs": [
"devenv",
"pre-commit-hooks",
"nixpkgs"
]
},
"locked": {
-
"lastModified": 1660459072,
-
"narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
-
"rev": "a20de23b925fd8264fd7fad6454652e142fd7f73",
"type": "github"
},
"original": {
···
"type": "github"
}
},
-
"lowdown-src": {
"flake": false,
"locked": {
-
"lastModified": 1633514407,
-
"narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=",
-
"owner": "kristapsdz",
-
"repo": "lowdown",
-
"rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8",
"type": "github"
},
"original": {
-
"owner": "kristapsdz",
-
"repo": "lowdown",
"type": "github"
}
},
"nix": {
"inputs": {
-
"lowdown-src": "lowdown-src",
-
"nixpkgs": [
-
"devenv",
-
"nixpkgs"
],
-
"nixpkgs-regression": "nixpkgs-regression"
},
"locked": {
-
"lastModified": 1676545802,
-
"narHash": "sha256-EK4rZ+Hd5hsvXnzSzk2ikhStJnD63odF7SzsQ8CuSPU=",
"owner": "domenkozar",
"repo": "nix",
-
"rev": "7c91803598ffbcfe4a55c44ac6d49b2cf07a527f",
"type": "github"
},
"original": {
"owner": "domenkozar",
-
"ref": "relaxed-flakes",
"repo": "nix",
"type": "github"
}
},
"nixpkgs": {
"locked": {
-
"lastModified": 1678875422,
-
"narHash": "sha256-T3o6NcQPwXjxJMn2shz86Chch4ljXgZn746c2caGxd8=",
"owner": "NixOS",
"repo": "nixpkgs",
-
"rev": "126f49a01de5b7e35a43fd43f891ecf6d3a51459",
"type": "github"
},
"original": {
"owner": "NixOS",
-
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-lib": {
"locked": {
-
"dir": "lib",
-
"lastModified": 1703961334,
-
"narHash": "sha256-M1mV/Cq+pgjk0rt6VxoyyD+O8cOUiai8t9Q6Yyq4noY=",
-
"owner": "NixOS",
-
"repo": "nixpkgs",
-
"rev": "b0d36bd0a420ecee3bc916c91886caca87c894e9",
"type": "github"
},
"original": {
-
"dir": "lib",
-
"owner": "NixOS",
-
"ref": "nixos-unstable",
-
"repo": "nixpkgs",
"type": "github"
}
},
-
"nixpkgs-regression": {
"locked": {
-
"lastModified": 1643052045,
-
"narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
"owner": "NixOS",
"repo": "nixpkgs",
-
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
-
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
"type": "github"
}
},
-
"nixpkgs-stable": {
"locked": {
-
"lastModified": 1685801374,
-
"narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=",
-
"owner": "NixOS",
"repo": "nixpkgs",
-
"rev": "c37ca420157f4abc31e26f436c1145f8951ff373",
"type": "github"
},
"original": {
-
"owner": "NixOS",
-
"ref": "nixos-23.05",
"repo": "nixpkgs",
"type": "github"
}
},
-
"nixpkgs_2": {
"locked": {
-
"lastModified": 1704842529,
-
"narHash": "sha256-OTeQA+F8d/Evad33JMfuXC89VMetQbsU4qcaePchGr4=",
-
"path": "/nix/store/g16z4fs1mrbkxc4x6wm8xbrh13nc7aw4-source",
-
"rev": "eabe8d3eface69f5bb16c18f8662a702f50c20d5",
"type": "path"
},
"original": {
···
},
"pre-commit-hooks": {
"inputs": {
-
"flake-compat": [
-
"devenv",
-
"flake-compat"
-
],
-
"flake-utils": "flake-utils",
-
"gitignore": "gitignore",
"nixpkgs": [
-
"devenv",
"nixpkgs"
-
],
-
"nixpkgs-stable": "nixpkgs-stable"
},
"locked": {
-
"lastModified": 1704725188,
-
"narHash": "sha256-qq8NbkhRZF1vVYQFt1s8Mbgo8knj+83+QlL5LBnYGpI=",
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
-
"rev": "ea96f0c05924341c551a797aaba8126334c505d2",
"type": "github"
},
"original": {
···
"inputs": {
"devenv": "devenv",
"fenix": "fenix",
-
"flake-parts": "flake-parts",
-
"nixpkgs": "nixpkgs_2",
"systems": "systems_2"
}
},
"rust-analyzer-src": {
"flake": false,
"locked": {
-
"lastModified": 1704974004,
-
"narHash": "sha256-H3RdtMxH8moTInVmracgtF8bgFpaEE3zYoSkuv7PBs0=",
"owner": "rust-lang",
"repo": "rust-analyzer",
-
"rev": "9d8889cdfcc3aa0302353fc988ed21ff9bc9925c",
"type": "github"
},
"original": {
"owner": "rust-lang",
"ref": "nightly",
"repo": "rust-analyzer",
"type": "github"
}
},
···
{
"nodes": {
+
"cachix": {
+
"inputs": {
+
"devenv": [
+
"devenv"
+
],
+
"flake-compat": [
+
"devenv"
+
],
+
"git-hooks": [
+
"devenv"
+
],
+
"nixpkgs": "nixpkgs"
+
},
+
"locked": {
+
"lastModified": 1744206633,
+
"narHash": "sha256-pb5aYkE8FOoa4n123slgHiOf1UbNSnKe5pEZC+xXD5g=",
+
"owner": "cachix",
+
"repo": "cachix",
+
"rev": "8a60090640b96f9df95d1ab99e5763a586be1404",
+
"type": "github"
+
},
+
"original": {
+
"owner": "cachix",
+
"ref": "latest",
+
"repo": "cachix",
+
"type": "github"
+
}
+
},
+
"crane": {
+
"locked": {
+
"lastModified": 1746291859,
+
"narHash": "sha256-DdWJLA+D5tcmrRSg5Y7tp/qWaD05ATI4Z7h22gd1h7Q=",
+
"owner": "ipetkov",
+
"repo": "crane",
+
"rev": "dfd9a8dfd09db9aad544c4d3b6c47b12562544a5",
+
"type": "github"
+
},
+
"original": {
+
"owner": "ipetkov",
+
"repo": "crane",
+
"type": "github"
+
}
+
},
"devenv": {
"inputs": {
+
"cachix": "cachix",
"flake-compat": "flake-compat",
+
"git-hooks": "git-hooks",
"nix": "nix",
+
"nixpkgs": "nixpkgs_3"
},
"locked": {
+
"lastModified": 1749550420,
+
"narHash": "sha256-YxbYLZSeEJX76fW0KPDpTjlF3ppQ+uh2z0fM5hEZbLU=",
"owner": "cachix",
"repo": "devenv",
+
"rev": "851a96d662ab265a15212ae4a4ec242a7c420d6f",
"type": "github"
},
"original": {
···
"rust-analyzer-src": "rust-analyzer-src"
},
"locked": {
+
"lastModified": 1749537578,
+
"narHash": "sha256-dYEEiNRw7rClQi4Y7t9jlHjbuUvSbdTdM/jXwXuaDeQ=",
"owner": "nix-community",
"repo": "fenix",
+
"rev": "5e3ce25aa3048f14f206a6c4fab46af6ad939482",
"type": "github"
},
"original": {
···
"flake-compat": {
"flake": false,
"locked": {
+
"lastModified": 1733328505,
+
"narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=",
+
"owner": "edolstra",
+
"repo": "flake-compat",
+
"rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec",
+
"type": "github"
+
},
+
"original": {
"owner": "edolstra",
"repo": "flake-compat",
+
"type": "github"
+
}
+
},
+
"flake-compat_2": {
+
"flake": false,
+
"locked": {
+
"lastModified": 1696426674,
+
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
+
"owner": "edolstra",
+
"repo": "flake-compat",
+
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
"type": "github"
},
"original": {
···
},
"flake-parts": {
"inputs": {
+
"nixpkgs-lib": [
+
"devenv",
+
"nix",
+
"nixpkgs"
+
]
+
},
+
"locked": {
+
"lastModified": 1712014858,
+
"narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=",
+
"owner": "hercules-ci",
+
"repo": "flake-parts",
+
"rev": "9126214d0a59633752a136528f5f3b9aa8565b7d",
+
"type": "github"
+
},
+
"original": {
+
"owner": "hercules-ci",
+
"repo": "flake-parts",
+
"type": "github"
+
}
+
},
+
"flake-parts_2": {
+
"inputs": {
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
+
"lastModified": 1749398372,
+
"narHash": "sha256-tYBdgS56eXYaWVW3fsnPQ/nFlgWi/Z2Ymhyu21zVM98=",
"owner": "hercules-ci",
"repo": "flake-parts",
+
"rev": "9305fe4e5c2a6fcf5ba6a3ff155720fbe4076569",
"type": "github"
},
"original": {
···
"systems": "systems"
},
"locked": {
+
"lastModified": 1731533236,
+
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
+
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
···
"type": "github"
}
},
+
"git-hooks": {
+
"inputs": {
+
"flake-compat": [
+
"devenv"
+
],
+
"gitignore": "gitignore",
+
"nixpkgs": [
+
"devenv",
+
"nixpkgs"
+
]
+
},
+
"locked": {
+
"lastModified": 1746537231,
+
"narHash": "sha256-Wb2xeSyOsCoTCTj7LOoD6cdKLEROyFAArnYoS+noCWo=",
+
"owner": "cachix",
+
"repo": "git-hooks.nix",
+
"rev": "fa466640195d38ec97cf0493d6d6882bc4d14969",
+
"type": "github"
+
},
+
"original": {
+
"owner": "cachix",
+
"repo": "git-hooks.nix",
+
"type": "github"
+
}
+
},
"gitignore": {
"inputs": {
"nixpkgs": [
"devenv",
+
"git-hooks",
+
"nixpkgs"
+
]
+
},
+
"locked": {
+
"lastModified": 1709087332,
+
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
+
"owner": "hercules-ci",
+
"repo": "gitignore.nix",
+
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
+
"type": "github"
+
},
+
"original": {
+
"owner": "hercules-ci",
+
"repo": "gitignore.nix",
+
"type": "github"
+
}
+
},
+
"gitignore_2": {
+
"inputs": {
+
"nixpkgs": [
+
"nickel",
"pre-commit-hooks",
"nixpkgs"
]
},
"locked": {
+
"lastModified": 1709087332,
+
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
+
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
"type": "github"
},
"original": {
···
"type": "github"
}
},
+
"libgit2": {
"flake": false,
"locked": {
+
"lastModified": 1697646580,
+
"narHash": "sha256-oX4Z3S9WtJlwvj0uH9HlYcWv+x1hqp8mhXl7HsLu2f0=",
+
"owner": "libgit2",
+
"repo": "libgit2",
+
"rev": "45fd9ed7ae1a9b74b957ef4f337bc3c8b3df01b5",
+
"type": "github"
+
},
+
"original": {
+
"owner": "libgit2",
+
"repo": "libgit2",
+
"type": "github"
+
}
+
},
+
"nickel": {
+
"inputs": {
+
"crane": "crane",
+
"flake-utils": "flake-utils",
+
"nixpkgs": "nixpkgs_4",
+
"pre-commit-hooks": "pre-commit-hooks",
+
"rust-overlay": "rust-overlay"
+
},
+
"locked": {
+
"lastModified": 1749052401,
+
"narHash": "sha256-iKLjYE4uT+luIRXjEuO7KjgkO+/jFpLjhCI5tO7TVMM=",
+
"owner": "tweag",
+
"repo": "nickel",
+
"rev": "11fba5486e2e9ee35f4a2e661627e8b08e2b9a14",
"type": "github"
},
"original": {
+
"owner": "tweag",
+
"ref": "stable",
+
"repo": "nickel",
"type": "github"
}
},
"nix": {
"inputs": {
+
"flake-compat": [
+
"devenv"
],
+
"flake-parts": "flake-parts",
+
"libgit2": "libgit2",
+
"nixpkgs": "nixpkgs_2",
+
"nixpkgs-23-11": [
+
"devenv"
+
],
+
"nixpkgs-regression": [
+
"devenv"
+
],
+
"pre-commit-hooks": [
+
"devenv"
+
]
},
"locked": {
+
"lastModified": 1745930071,
+
"narHash": "sha256-bYyjarS3qSNqxfgc89IoVz8cAFDkF9yPE63EJr+h50s=",
"owner": "domenkozar",
"repo": "nix",
+
"rev": "b455edf3505f1bf0172b39a735caef94687d0d9c",
"type": "github"
},
"original": {
"owner": "domenkozar",
+
"ref": "devenv-2.24",
"repo": "nix",
"type": "github"
}
},
"nixpkgs": {
"locked": {
+
"lastModified": 1733212471,
+
"narHash": "sha256-M1+uCoV5igihRfcUKrr1riygbe73/dzNnzPsmaLCmpo=",
"owner": "NixOS",
"repo": "nixpkgs",
+
"rev": "55d15ad12a74eb7d4646254e13638ad0c4128776",
"type": "github"
},
"original": {
"owner": "NixOS",
+
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-lib": {
"locked": {
+
"lastModified": 1748740939,
+
"narHash": "sha256-rQaysilft1aVMwF14xIdGS3sj1yHlI6oKQNBRTF40cc=",
+
"owner": "nix-community",
+
"repo": "nixpkgs.lib",
+
"rev": "656a64127e9d791a334452c6b6606d17539476e2",
"type": "github"
},
"original": {
+
"owner": "nix-community",
+
"repo": "nixpkgs.lib",
"type": "github"
}
},
+
"nixpkgs_2": {
"locked": {
+
"lastModified": 1717432640,
+
"narHash": "sha256-+f9c4/ZX5MWDOuB1rKoWj+lBNm0z0rs4CK47HBLxy1o=",
"owner": "NixOS",
"repo": "nixpkgs",
+
"rev": "88269ab3044128b7c2f4c7d68448b2fb50456870",
"type": "github"
},
"original": {
"owner": "NixOS",
+
"ref": "release-24.05",
"repo": "nixpkgs",
"type": "github"
}
},
+
"nixpkgs_3": {
+
"locked": {
+
"lastModified": 1746807397,
+
"narHash": "sha256-zU2z0jlkJGWLhdNr/8AJSxqK8XD0IlQgHp3VZcP56Aw=",
+
"owner": "cachix",
+
"repo": "devenv-nixpkgs",
+
"rev": "c5208b594838ea8e6cca5997fbf784b7cca1ca90",
+
"type": "github"
+
},
+
"original": {
+
"owner": "cachix",
+
"ref": "rolling",
+
"repo": "devenv-nixpkgs",
+
"type": "github"
+
}
+
},
+
"nixpkgs_4": {
"locked": {
+
"lastModified": 1746663147,
+
"narHash": "sha256-Ua0drDHawlzNqJnclTJGf87dBmaO/tn7iZ+TCkTRpRc=",
+
"owner": "nixos",
"repo": "nixpkgs",
+
"rev": "dda3dcd3fe03e991015e9a74b22d35950f264a54",
"type": "github"
},
"original": {
+
"owner": "nixos",
+
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
+
"nixpkgs_5": {
"locked": {
+
"lastModified": 0,
+
"narHash": "sha256-MmJvj6mlWzeRwKGLcwmZpKaOPZ5nJb/6al5CXqJsgjo=",
+
"path": "/nix/store/ad1fkqvkbxhap0gpb688bgrad221lgwj-source",
"type": "path"
},
"original": {
···
},
"pre-commit-hooks": {
"inputs": {
+
"flake-compat": "flake-compat_2",
+
"gitignore": "gitignore_2",
"nixpkgs": [
+
"nickel",
"nixpkgs"
+
]
},
"locked": {
+
"lastModified": 1746537231,
+
"narHash": "sha256-Wb2xeSyOsCoTCTj7LOoD6cdKLEROyFAArnYoS+noCWo=",
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
+
"rev": "fa466640195d38ec97cf0493d6d6882bc4d14969",
"type": "github"
},
"original": {
···
"inputs": {
"devenv": "devenv",
"fenix": "fenix",
+
"flake-parts": "flake-parts_2",
+
"nickel": "nickel",
+
"nixpkgs": "nixpkgs_5",
"systems": "systems_2"
}
},
"rust-analyzer-src": {
"flake": false,
"locked": {
+
"lastModified": 1749493129,
+
"narHash": "sha256-nQ+gKRLXkl7gLY836ULyAwR3O0E/+vakZt78OQ+p9Fc=",
"owner": "rust-lang",
"repo": "rust-analyzer",
+
"rev": "bf6d44581085bb9b6e285902a7fae77325703171",
"type": "github"
},
"original": {
"owner": "rust-lang",
"ref": "nightly",
"repo": "rust-analyzer",
+
"type": "github"
+
}
+
},
+
"rust-overlay": {
+
"inputs": {
+
"nixpkgs": [
+
"nickel",
+
"nixpkgs"
+
]
+
},
+
"locked": {
+
"lastModified": 1746844454,
+
"narHash": "sha256-GcUWDQUDRYrD34ol90KGUpjbVcOfUNbv0s955jPecko=",
+
"owner": "oxalica",
+
"repo": "rust-overlay",
+
"rev": "be092436d4c0c303b654e4007453b69c0e33009e",
+
"type": "github"
+
},
+
"original": {
+
"owner": "oxalica",
+
"repo": "rust-overlay",
"type": "github"
}
},
+21 -7
flake.nix
···
{
inputs = {
nixpkgs.url = "flake:nixpkgs";
···
url = "github:nix-community/fenix";
inputs.nixpkgs.follows = "nixpkgs";
};
devenv.url = "github:cachix/devenv";
};
···
extra-substituters = "https://devenv.cachix.org";
};
-
outputs = {
-
self,
-
flake-parts,
-
...
-
} @ inputs:
flake-parts.lib.mkFlake {inherit inputs;} {
imports = [
inputs.devenv.flakeModule
···
perSystem = {
self',
pkgs,
...
}: {
formatter = pkgs.alejandra;
devenv.shells.default = {
languages.rust = {
enable = true;
};
packages =
-
[]
-
++ pkgs.lib.lists.optionals pkgs.stdenv.isDarwin (with pkgs.darwin.apple_sdk; [
frameworks.Foundation
pkgs.libiconv
pkgs.darwin.libobjc
···
+
# SPDX-FileCopyrightText: 2024 Łukasz Niemier <#@hauleth.dev>
+
#
+
# SPDX-License-Identifier: EUPL-1.2
{
inputs = {
nixpkgs.url = "flake:nixpkgs";
···
url = "github:nix-community/fenix";
inputs.nixpkgs.follows = "nixpkgs";
};
+
nickel.url = "github:tweag/nickel/stable";
devenv.url = "github:cachix/devenv";
};
···
extra-substituters = "https://devenv.cachix.org";
};
+
outputs = {flake-parts, ...} @ inputs:
flake-parts.lib.mkFlake {inherit inputs;} {
imports = [
inputs.devenv.flakeModule
···
perSystem = {
self',
pkgs,
+
inputs',
...
}: {
formatter = pkgs.alejandra;
+
packages = {
+
default = self'.packages.ptsd;
+
ptsd = pkgs.callPackage ./nix/ptsd.nix {};
+
};
+
devenv.shells.default = {
languages.rust = {
enable = true;
};
packages =
+
[
+
pkgs.scdoc
+
pkgs.cargo-nextest
+
pkgs.cargo-outdated
+
pkgs.reuse
+
inputs'.nickel.packages.default
+
]
+
++ pkgs.lib.lists.optionals pkgs.stdenv.isDarwin (let
+
inherit (pkgs.darwin.apple_sdk) frameworks;
+
in [
frameworks.Foundation
pkgs.libiconv
pkgs.darwin.libobjc
+35
nix/ptsd.nix
···
···
+
# SPDX-FileCopyrightText: 2024 Łukasz Niemier <#@hauleth.dev>
+
#
+
# SPDX-License-Identifier: EUPL-1.2
+
{
+
lib,
+
rustPlatform,
+
stdenv,
+
darwin,
+
libiconv,
+
scdoc,
+
}:
+
rustPlatform.buildRustPackage {
+
pname = "ptsd";
+
version = "0.0.1";
+
+
src = ./..;
+
+
cargoLock.lockFile = ../Cargo.lock;
+
+
nativeBuildInputs = [
+
scdoc
+
];
+
+
postInstall = ''
+
OUT=$out/man cargo xtask
+
'';
+
+
buildInputs =
+
[]
+
++ lib.lists.optionals stdenv.isDarwin (with darwin.apple_sdk; [
+
libiconv
+
darwin.libobjc
+
frameworks.Foundation
+
]);
+
}
+96
ptsd.ncl
···
···
+
# SPDX-FileCopyrightText: 2024 Łukasz Niemier <#@hauleth.dev>
+
#
+
# SPDX-License-Identifier: EUPL-1.2
+
let Action = [|
+
'script String,
+
'move String,
+
'echo String,
+
'trash
+
|]
+
in
+
let NameMatch = [| 'exact String, 'wildcard String, 'regex String |] in
+
let FileType = [| 'dir, 'file, 'symlink |] in
+
let ContentMatch = [|
+
'mime String,
+
'magic {
+
offset | Number = 0,
+
bytes | (Array Number),
+
}
+
|]
+
in
+
let rec Filter = [|
+
'name NameMatch,
+
'file_type FileType,
+
'size [| 'less Number, 'equal Number, 'greater Number |],
+
'content_type ContentMatch,
+
'any (Array Filter),
+
'all (Array Filter),
+
'not Filter,
+
|]
+
in
+
{
+
Job = {
+
location
+
| String
+
| doc "Location that will be traversed for patterns",
+
filter
+
| Filter
+
| doc "File filters",
+
actions
+
| Array Action
+
| doc "Actions that should be applied to entry that matches pattern"
+
},
+
+
build | (Array Job) -> Dyn
+
=
+
let actionMatcher = match {
+
'script path => { script = path },
+
'move path => { move = path },
+
'echo msg => { echo = msg },
+
'trash => "trash",
+
}
+
in
+
let nameMatcher = match {
+
'exact val => { exact = val },
+
'wildcard val => { wildcard = val },
+
'regex val => { regex = val },
+
}
+
in
+
let rec filterMapper = match {
+
'name name => { type = "name" } & (nameMatcher name),
+
'file_type type => { type = "file_type", is = type },
+
'content_type type =>
+
type
+
|> match {
+
'mime mime => { type = "content_type", mime = mime },
+
'magic bytes => { type = "content_type", magic = bytes },
+
},
+
'size pred =>
+
let { tag, arg } = std.enum.to_tag_and_arg pred
+
in
+
{
+
type = "size",
+
size = arg,
+
ordering = tag,
+
},
+
'all allFilters =>
+
{
+
type = "all",
+
filters = std.array.map filterMapper allFilters
+
},
+
'any anyFilter =>
+
{
+
type = "any",
+
filters = std.array.map filterMapper anyFilter
+
},
+
}
+
in
+
let jobMapper = fun job =>
+
{
+
location = job.location,
+
filter = filterMapper job.filter,
+
actions = std.array.map actionMatcher job.actions,
+
}
+
in
+
std.array.map jobMapper
+
}
-91
src/filters.rs
···
-
use std::path::Path;
-
-
use async_trait::async_trait;
-
use serde::Deserialize;
-
use tokio::fs;
-
-
use crate::pattern::Pattern;
-
-
#[typetag::deserialize(tag = "type")]
-
#[async_trait]
-
pub trait Filter: std::fmt::Debug {
-
async fn matches(&self, path: &Path) -> bool;
-
}
-
-
#[derive(Debug, Deserialize)]
-
pub struct Name(Pattern);
-
-
#[typetag::deserialize(name = "name")]
-
#[async_trait]
-
impl Filter for Name {
-
async fn matches(&self, path: &Path) -> bool {
-
self.0.matches(path)
-
}
-
}
-
-
#[derive(Debug, Deserialize)]
-
pub struct Size {
-
size: u64,
-
#[serde(with = "Ordering")]
-
ordering: std::cmp::Ordering,
-
}
-
-
#[derive(Deserialize)]
-
#[serde(remote = "std::cmp::Ordering")]
-
enum Ordering {
-
Less,
-
Equal,
-
Greater,
-
}
-
-
#[typetag::deserialize(name = "size")]
-
#[async_trait]
-
impl Filter for Size {
-
async fn matches(&self, path: &Path) -> bool {
-
with_metadata(path, |metadata| {
-
let len = metadata.len();
-
-
self.size.cmp(&len) == self.ordering
-
})
-
.await
-
}
-
}
-
-
#[derive(Debug, Deserialize)]
-
pub enum FileType {
-
Dir,
-
File,
-
Symlink,
-
}
-
-
#[typetag::deserialize(name = "file_type")]
-
#[async_trait]
-
impl Filter for FileType {
-
async fn matches(&self, path: &Path) -> bool {
-
use FileType::*;
-
-
with_metadata(path, |metadata| {
-
let ft = metadata.file_type();
-
-
match *self {
-
Dir => ft.is_dir(),
-
File => ft.is_file(),
-
Symlink => ft.is_symlink(),
-
}
-
})
-
.await
-
}
-
}
-
-
async fn with_metadata<F>(path: &Path, fun: F) -> bool
-
where
-
F: FnOnce(std::fs::Metadata) -> bool,
-
{
-
fs::metadata(path).await.map(fun).unwrap_or(false)
-
}
-
-
#[derive(Debug, Deserialize)]
-
pub enum Magic {
-
Mime(String),
-
Bytes(Box<[u8]>),
-
}
···
-99
src/job.rs
···
-
use color_eyre::eyre::Result;
-
-
use std::path::{Path, PathBuf};
-
-
use tokio::fs;
-
use tokio::process::Command;
-
use tokio_stream::wrappers::ReadDirStream;
-
-
use futures::prelude::*;
-
-
use serde::Deserialize;
-
-
use crate::filters::Filter;
-
-
/// Definition of the job files
-
#[derive(Debug, Deserialize)]
-
pub struct Job {
-
filters: Vec<Box<dyn Filter>>,
-
location: PathBuf,
-
actions: Vec<Action>,
-
}
-
-
impl Job {
-
pub async fn run(&self) -> Result<impl tokio_stream::Stream<Item = (Action, PathBuf)> + '_> {
-
let loc = normalise_path(&self.location);
-
-
let dir = ReadDirStream::new(fs::read_dir(&loc).await?);
-
-
Ok(async_stream::stream! {
-
for await entry in dir {
-
let entry = entry.unwrap();
-
if self.matches_filters(&entry.path()).await {
-
for action in &self.actions {
-
yield (action.clone(), entry.path())
-
}
-
}
-
}
-
})
-
}
-
-
async fn matches_filters(&self, path: &Path) -> bool {
-
stream::iter(&self.filters).all(|f| f.matches(path)).await
-
}
-
}
-
-
/// Actions available for file
-
#[derive(Clone, Debug, Deserialize)]
-
#[serde(untagged)]
-
pub enum Action {
-
/// Run given script with 1st argument. It will be ran in parent directory for given file
-
Script { script: Box<Path> },
-
/// Move given file to new destination
-
Move { move_to: Box<Path> },
-
/// Print message and do nothing
-
Echo { message: String },
-
/// Move to trash
-
Trash,
-
}
-
-
impl Action {
-
pub async fn execute(self, source: PathBuf) {
-
match self {
-
Action::Script { ref script } => {
-
Command::new(script.as_ref())
-
.arg(&source)
-
.current_dir(source.parent().unwrap())
-
.spawn()
-
.expect("Couldnt spawn process")
-
.wait()
-
.await
-
.expect("Child exited abnormally");
-
}
-
-
Action::Move {
-
move_to: ref dest_dir,
-
} => {
-
let dest = normalise_path(dest_dir).join(source.file_name().unwrap());
-
if let Err(err) = fs::rename(&source, &dest).await {
-
if err.raw_os_error() == Some(libc::EXDEV) {
-
panic!("X dev");
-
} else {
-
panic!("Cannot move {source:?} -> {dest:?}: {err:?}");
-
}
-
}
-
}
-
-
Action::Echo { ref message } => println!("{source:?} - {message}"),
-
-
Action::Trash => trash::delete(source).unwrap(),
-
}
-
}
-
}
-
-
fn normalise_path(path: &Path) -> PathBuf {
-
match path.strip_prefix("~") {
-
Ok(prefix) => std::env::home_dir().unwrap().join(prefix),
-
Err(_) => path.to_owned(),
-
}
-
}
···
-34
src/main.rs
···
-
use color_eyre::eyre::Result;
-
use tokio_stream::iter;
-
use futures::StreamExt;
-
-
mod filters;
-
mod job;
-
mod pattern;
-
-
const DATA: &str = r#"
-
[
-
{
-
"filters": [
-
{"type": "name", "Wildcard": "*.dmg"}
-
],
-
"location": "~/Downloads",
-
"actions": [
-
{"message": "move to ~/Documents/Gitara/"}
-
]
-
}
-
]"#;
-
-
#[tokio::main]
-
async fn main() -> Result<()> {
-
let jobs: Vec<job::Job> = serde_json::from_str(DATA).unwrap();
-
-
iter(&jobs)
-
.then(|job| job.run())
-
.map(|result| result.unwrap())
-
.flatten()
-
.for_each_concurrent(None, |(action, path)| action.execute(path))
-
.await;
-
-
Ok(())
-
}
···
-79
src/pattern.rs
···
-
use std::fmt;
-
use std::path::Path;
-
-
use serde::{de, Deserialize};
-
use wildmatch::WildMatch;
-
-
/// Patterns that can be matched against files
-
#[derive(Debug, Deserialize)]
-
pub enum Pattern {
-
#[serde(deserialize_with = "deserialize_wildcard")]
-
Wildcard(WildMatch),
-
#[serde(deserialize_with = "deserialize_regex")]
-
Regex(regex::Regex),
-
Exact(Box<Path>),
-
}
-
-
impl Pattern {
-
pub fn matches(&self, path: &Path) -> bool {
-
match *self {
-
Self::Wildcard(ref pattern) => pattern.matches(path.to_str().unwrap()),
-
Self::Regex(ref pattern) => pattern.is_match(path.to_str().unwrap()),
-
Self::Exact(ref pattern) => **pattern == *path,
-
}
-
}
-
}
-
-
struct RegexVisitor;
-
-
impl<'de> de::Visitor<'de> for RegexVisitor {
-
type Value = regex::Regex;
-
-
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
-
write!(formatter, "expected regex string")
-
}
-
-
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
-
where
-
E: de::Error,
-
{
-
match regex::Regex::new(s) {
-
Ok(regex) => Ok(regex),
-
Err(regex::Error::Syntax(ref desc)) => {
-
Err(E::invalid_value(de::Unexpected::Str(s), &desc.as_str()))
-
}
-
Err(_) => unreachable!(),
-
}
-
}
-
}
-
-
fn deserialize_regex<'de, D>(des: D) -> Result<regex::Regex, D::Error>
-
where
-
D: serde::Deserializer<'de>,
-
{
-
des.deserialize_str(RegexVisitor)
-
}
-
-
struct WildcardVisitor;
-
-
impl<'de> de::Visitor<'de> for WildcardVisitor {
-
type Value = WildMatch;
-
-
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
-
write!(formatter, "expected regex string")
-
}
-
-
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
-
where
-
E: de::Error,
-
{
-
Ok(WildMatch::new(s))
-
}
-
}
-
-
fn deserialize_wildcard<'de, D>(des: D) -> Result<WildMatch, D::Error>
-
where
-
D: serde::Deserializer<'de>,
-
{
-
des.deserialize_str(WildcardVisitor)
-
}
···
+14
xtask/Cargo.toml
···
···
+
# SPDX-FileCopyrightText: 2024 Łukasz Niemier <#@hauleth.dev>
+
#
+
# SPDX-License-Identifier: EUPL-1.2
+
+
[package]
+
name = "xtask"
+
version = "0.1.0"
+
edition = "2021"
+
+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+
[dependencies]
+
simple-eyre = "0.3.1"
+
xshell = "0.2.5"
+39
xtask/src/main.rs
···
···
+
// SPDX-FileCopyrightText: 2024 Łukasz Niemier <#@hauleth.dev>
+
//
+
// SPDX-License-Identifier: EUPL-1.2
+
+
use std::fs;
+
use std::path::Path;
+
+
fn main() -> simple_eyre::Result<()> {
+
let sh = xshell::Shell::new()?;
+
+
let outdir = std::env::var("OUT")?;
+
let outdir = Path::new(&outdir);
+
+
// Generate Manpages using scdoc
+
for entry in fs::read_dir("docs")? {
+
let entry = entry?;
+
let file_name = entry.file_name();
+
let file_name = Path::new(&file_name);
+
if file_name.extension() != Some(std::ffi::OsStr::new("scd")) { continue }
+
+
let outname = Path::file_stem(file_name).unwrap();
+
let page = Path::new(outname).extension().unwrap().to_str().unwrap();
+
+
let outdir = outdir.join(format!("man{page}"));
+
+
fs::create_dir_all(&outdir)?;
+
+
let input = entry.path();
+
let input = Path::new(&input);
+
+
let output = xshell::cmd!(sh, "scdoc").stdin(fs::read(input)?).read()?;
+
+
fs::write(outdir.join(outname), &output)?;
+
+
println!("{:?}", outname);
+
}
+
+
Ok(())
+
}