Compare commits
3 commits
889b282aa0
...
fe2b8745a4
Author | SHA1 | Date | |
---|---|---|---|
fe2b8745a4 | |||
26ac4415d3 | |||
6f267e35ba |
7 changed files with 463 additions and 131 deletions
35
.forgejo/workflows/push-main.yml
Normal file
35
.forgejo/workflows/push-main.yml
Normal file
|
@ -0,0 +1,35 @@
|
|||
name: Release Please
|
||||
|
||||
permissions:
|
||||
pull-requests: write
|
||||
contents: write
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
jobs:
|
||||
release-plz:
|
||||
name: Release-plz
|
||||
runs-on: docker
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Run release-plz release-pr
|
||||
uses: https://git.kemitix.net/kemitix/rust@v2.1.0
|
||||
with:
|
||||
args: release-plz release-pr --backend gitea --git-token ${{ secrets.FORGEJO_TOKEN }}
|
||||
env:
|
||||
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
|
||||
- name: Run release-plz release
|
||||
uses: https://git.kemitix.net/kemitix/rust@v2.1.0
|
||||
with:
|
||||
args: release-plz release --backend gitea --git-token ${{ secrets.FORGEJO_TOKEN }}
|
||||
env:
|
||||
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
|
52
.forgejo/workflows/push-next.yml
Normal file
52
.forgejo/workflows/push-next.yml
Normal file
|
@ -0,0 +1,52 @@
|
|||
name: Rust
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["next"]
|
||||
pull_request:
|
||||
branches: ["main"]
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: docker
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
toolchain:
|
||||
- name: stable
|
||||
- name: nightly
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Check TODOs
|
||||
uses: https://git.kemitix.net/kemitix/forgejo-todo-checker@v1.1.0
|
||||
|
||||
- name: Machete
|
||||
uses: https://git.kemitix.net/kemitix/rust@v2.1.0
|
||||
with:
|
||||
args: ${{ matrix.toolchain.name }} cargo machete
|
||||
|
||||
- name: Format
|
||||
uses: https://git.kemitix.net/kemitix/rust@v2.1.0
|
||||
with:
|
||||
args: ${{ matrix.toolchain.name }} cargo fmt --all -- --check
|
||||
|
||||
- name: Clippy
|
||||
uses: https://git.kemitix.net/kemitix/rust@v2.1.0
|
||||
with:
|
||||
args: ${{ matrix.toolchain.name }} cargo hack --feature-powerset clippy
|
||||
|
||||
- name: Build
|
||||
uses: https://git.kemitix.net/kemitix/rust@v2.1.0
|
||||
with:
|
||||
args: ${{ matrix.toolchain.name }} cargo hack --feature-powerset build
|
||||
|
||||
- name: Test
|
||||
uses: https://git.kemitix.net/kemitix/rust@v2.1.0
|
||||
with:
|
||||
args: ${{ matrix.toolchain.name }} cargo hack --feature-powerset test
|
354
Cargo.lock
generated
354
Cargo.lock
generated
|
@ -2,6 +2,15 @@
|
|||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[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.11"
|
||||
|
@ -62,7 +71,9 @@ version = "0.2.0"
|
|||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
"mp4",
|
||||
"pretty_assertions",
|
||||
"regex",
|
||||
"rstest",
|
||||
"taglib",
|
||||
]
|
||||
|
||||
|
@ -73,16 +84,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.3"
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
|
@ -130,6 +135,125 @@ version = "1.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
|
||||
|
||||
[[package]]
|
||||
name = "diff"
|
||||
version = "0.1.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-executor",
|
||||
"futures-io",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
"futures-util",
|
||||
]
|
||||
|
||||
[[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",
|
||||
"futures-util",
|
||||
]
|
||||
|
||||
[[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",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[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-timer"
|
||||
version = "3.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24"
|
||||
|
||||
[[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",
|
||||
"futures-io",
|
||||
"futures-macro",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
"memchr",
|
||||
"pin-project-lite",
|
||||
"pin-utils",
|
||||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.1"
|
||||
|
@ -137,10 +261,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.9"
|
||||
name = "indexmap"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
|
||||
checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
|
@ -149,60 +277,40 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
|
||||
|
||||
[[package]]
|
||||
name = "mp4"
|
||||
version = "0.14.0"
|
||||
name = "memchr"
|
||||
version = "2.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c9ef834d5ed55e494a2ae350220314dc4aacd1c43a9498b00e320e0ea352a5c3"
|
||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
|
||||
|
||||
[[package]]
|
||||
name = "pin-utils"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
|
||||
[[package]]
|
||||
name = "pretty_assertions"
|
||||
version = "1.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"bytes",
|
||||
"num-rational",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"diff",
|
||||
"yansi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.4"
|
||||
name = "proc-macro-crate"
|
||||
version = "3.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0"
|
||||
checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-rational"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-bigint",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"toml_edit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -224,40 +332,92 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.15"
|
||||
name = "regex"
|
||||
version = "1.10.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.188"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e"
|
||||
checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.188"
|
||||
name = "regex-automata"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
|
||||
checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
|
||||
|
||||
[[package]]
|
||||
name = "relative-path"
|
||||
version = "1.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2"
|
||||
|
||||
[[package]]
|
||||
name = "rstest"
|
||||
version = "0.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b423f0e62bdd61734b67cd21ff50871dfaeb9cc74f869dcd6af974fbcb19936"
|
||||
dependencies = [
|
||||
"futures",
|
||||
"futures-timer",
|
||||
"rstest_macros",
|
||||
"rustc_version",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rstest_macros"
|
||||
version = "0.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c5e1711e7d14f74b12a58411c542185ef7fb7f2e7f8ee6e2940a883628522b42"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"glob",
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"relative-path",
|
||||
"rustc_version",
|
||||
"syn",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.105"
|
||||
name = "rustc_version"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360"
|
||||
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -297,23 +457,20 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.47"
|
||||
name = "toml_datetime"
|
||||
version = "0.6.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97a802ec30afc17eee47b2855fc72e0c4cd62be9b4efe6591edde0ec5bd68d8f"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.47"
|
||||
name = "toml_edit"
|
||||
version = "0.22.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b"
|
||||
checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"indexmap",
|
||||
"toml_datetime",
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -393,3 +550,18 @@ name = "windows_x86_64_msvc"
|
|||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.6.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c52ac009d615e79296318c1bcce2d422aaca15ad08515e344feeda07df67a587"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yansi"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
|
||||
|
|
10
Cargo.toml
10
Cargo.toml
|
@ -6,7 +6,11 @@ edition = "2021"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "4.4", features = ["derive", "cargo"] }
|
||||
mp4 = "0.14.0"
|
||||
taglib = "1.0.0"
|
||||
anyhow = "1.0.75"
|
||||
clap = { version = "4.4", features = ["derive", "cargo"] }
|
||||
regex = "1.10"
|
||||
taglib = "1.0.0"
|
||||
|
||||
[dev-dependencies]
|
||||
pretty_assertions = "1.4"
|
||||
rstest = "0.22"
|
||||
|
|
5
justfile
5
justfile
|
@ -1,2 +1,5 @@
|
|||
default:
|
||||
dry-run:
|
||||
cargo run -- --dry-run ~/Nextcloud/Audible-Inbox/
|
||||
|
||||
run:
|
||||
cargo run -- ~/Nextcloud/Audible-Inbox/
|
||||
|
|
120
src/main.rs
120
src/main.rs
|
@ -1,3 +1,8 @@
|
|||
//
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use clap::{crate_version, Parser};
|
||||
use std::{
|
||||
|
@ -17,30 +22,40 @@ struct Arguments {
|
|||
|
||||
/// Path
|
||||
path: Option<String>,
|
||||
|
||||
/// Dry-Run
|
||||
#[clap(long)]
|
||||
dry_run: bool,
|
||||
}
|
||||
impl Arguments {
|
||||
fn not_dry_run(&self) -> bool {
|
||||
!self.dry_run
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args = Arguments::parse();
|
||||
if args.version {
|
||||
println!("Version {}", crate_version!());
|
||||
} else if let Some(path) = args.directory {
|
||||
rename_files_in_directory(path);
|
||||
} else if let Some(path) = args.path {
|
||||
rename_files_in_directory(path);
|
||||
} else if let Some(path) = &args.directory {
|
||||
rename_files_in_directory(path.to_string(), &args);
|
||||
} else if let Some(path) = &args.path {
|
||||
rename_files_in_directory(path.to_string(), &args);
|
||||
} else {
|
||||
eprintln!("Please provide a directory");
|
||||
}
|
||||
}
|
||||
|
||||
fn rename_files_in_directory(directory: String) {
|
||||
fn rename_files_in_directory(directory: String, args: &Arguments) {
|
||||
println!("Renaming files in {}", directory);
|
||||
match rename_files(&directory, &directory) {
|
||||
Ok(count) => println!("Renamed {} files", count),
|
||||
match rename_files(&directory, &directory, args) {
|
||||
Ok(count) if args.not_dry_run() => println!("Renamed {} files", count),
|
||||
Ok(_) => println!("Dry-Run complete"),
|
||||
Err(e) => eprintln!("Error: {}", e),
|
||||
}
|
||||
}
|
||||
|
||||
fn rename_files(directory: &str, base: &str) -> Result<i32> {
|
||||
fn rename_files(directory: &str, base: &str, args: &Arguments) -> Result<i32> {
|
||||
let entries = read_dir(directory).context("Failed to read directory")?;
|
||||
let mut count = 0;
|
||||
for entry in entries {
|
||||
|
@ -48,42 +63,75 @@ fn rename_files(directory: &str, base: &str) -> Result<i32> {
|
|||
let path = entry.path();
|
||||
if path.is_dir() {
|
||||
if let Some(sub_dir) = path.to_str() {
|
||||
count += rename_files(sub_dir, base).context("Failed to rename files")?;
|
||||
count += rename_files(sub_dir, base, args).context("Failed to rename files")?;
|
||||
}
|
||||
}
|
||||
if path.is_file() {
|
||||
if let Ok(file) = taglib::File::new(&path) {
|
||||
if let Ok(tag) = file.tag() {
|
||||
if let Some(title) = tag.title() {
|
||||
if let Some(artist) = tag.artist() {
|
||||
let album = parse_album(&title);
|
||||
count += 1;
|
||||
let new_name = match album.len() {
|
||||
0 => format!("{artist}/{title}/{title}.m4b"),
|
||||
_ => format!("{artist}/{album}/{title}/{title}.m4b"),
|
||||
};
|
||||
println!("Renaming {} to {}", path.display(), new_name);
|
||||
let target_path = Path::new(&base).join(new_name);
|
||||
if !target_path.exists() {
|
||||
let dir = target_path.parent().with_context(|| {
|
||||
format!("Failed to get parent: {:#?}", target_path)
|
||||
})?;
|
||||
create_dir_all(dir).with_context(|| {
|
||||
format!("Failed to create directory: {:#?}", dir)
|
||||
})?;
|
||||
}
|
||||
rename(&path, &target_path).with_context(|| {
|
||||
format!("Failed to rename file: {:#?}", target_path)
|
||||
})?;
|
||||
}
|
||||
}
|
||||
}
|
||||
if !path.is_file() {
|
||||
continue;
|
||||
}
|
||||
let Ok(file) = taglib::File::new(&path) else {
|
||||
continue;
|
||||
};
|
||||
let Ok(tag) = file.tag() else {
|
||||
continue;
|
||||
};
|
||||
let (Some(title), Some(artist)) = (tag.title(), tag.artist()) else {
|
||||
continue;
|
||||
};
|
||||
let album = parse_album(&title);
|
||||
count += 1;
|
||||
let new_name = if album.is_empty() {
|
||||
format!("{artist}/{title}/{title}.m4b")
|
||||
} else {
|
||||
build_series_name(&artist, &album, &title)
|
||||
};
|
||||
println!("==============================");
|
||||
println!("- artist: {artist}");
|
||||
println!("- album : {album}");
|
||||
println!("- title : {title}");
|
||||
println!("> {new_name}");
|
||||
if args.not_dry_run() {
|
||||
let target_path = Path::new(&base).join(new_name);
|
||||
if !target_path.exists() {
|
||||
let dir = target_path
|
||||
.parent()
|
||||
.with_context(|| format!("Failed to get parent: {:#?}", target_path))?;
|
||||
create_dir_all(dir)
|
||||
.with_context(|| format!("Failed to create directory: {:#?}", dir))?;
|
||||
}
|
||||
|
||||
rename(&path, &target_path)
|
||||
.with_context(|| format!("Failed to rename file: {:#?}", target_path))?;
|
||||
}
|
||||
}
|
||||
Ok(count)
|
||||
}
|
||||
|
||||
fn build_series_name(artist: &str, album: &str, title: &str) -> String {
|
||||
let index = parse_index(title);
|
||||
let title = parse_title(title);
|
||||
format!("{artist}/{album}/{index}. {title}/{index}. {title}.m4b")
|
||||
}
|
||||
|
||||
fn parse_index(title: &str) -> String {
|
||||
if let Ok(index_re) = regex::Regex::new(r", Book (?P<INDEX>\d+)") {
|
||||
if let Some(captures) = index_re.captures(title) {
|
||||
let index = captures.name("INDEX").map_or("", |m| m.as_str());
|
||||
return index.to_string();
|
||||
}
|
||||
}
|
||||
String::new()
|
||||
}
|
||||
fn parse_title(title: &str) -> String {
|
||||
if let Ok(title_re) = regex::Regex::new(r"^(?P<TITLE>.*?):") {
|
||||
if let Some(captures) = title_re.captures(title) {
|
||||
let title = captures.name("TITLE").map_or("", |m| m.as_str());
|
||||
return title.to_string();
|
||||
}
|
||||
}
|
||||
title.to_string()
|
||||
}
|
||||
|
||||
fn parse_album(title: &str) -> String {
|
||||
let parts: Vec<&str> = title.split(':').collect();
|
||||
match &parts[..] {
|
||||
|
|
18
src/tests.rs
Normal file
18
src/tests.rs
Normal file
|
@ -0,0 +1,18 @@
|
|||
//
|
||||
use super::*;
|
||||
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[rstest::rstest]
|
||||
#[case("Discworld", "The Truth: Discworld, Book 25", "25. The Truth")]
|
||||
#[case(
|
||||
"A Darker Shade of Magic",
|
||||
"A Conjuring of Light: A Darker Shade of Magic, Book 3",
|
||||
"3. A Conjuring of Light"
|
||||
)]
|
||||
fn parse_series_details(#[case] album: &str, #[case] title: &str, #[case] expected: &str) {
|
||||
let expected_result = format!("Bob/{album}/{expected}/{expected}.m4b");
|
||||
let result = build_series_name("Bob", album, title);
|
||||
|
||||
assert_eq!(result, expected_result);
|
||||
}
|
Loading…
Reference in a new issue