diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..c76b5ad --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +*.MP4 filter=lfs diff=lfs merge=lfs -text +*.mp4 filter=lfs diff=lfs merge=lfs -text diff --git a/.gitignore b/.gitignore index c81097a..ea8c4bf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1 @@ /target -output -tests/working_test_data -tests/real_videos diff --git a/.vscode/launch.json b/.vscode/launch.json index 2fb6a37..83e5dd1 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,69 +1,81 @@ { - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "type": "lldb", - "request": "launch", - "name": "Debug in test", - "cargo": { - "args": [ - "build", - "--bin=gopro-chaptered-video-assembler", - "--package=gopro-chaptered-video-assembler" - ], - "filter": { - "name": "gopro-chaptered-video-assembler", - "kind": "bin" - } - }, - "args": ["-i", "tests/working_test_data", "-o", "tests/output"], - "cwd": "${workspaceFolder}", - "env": { - "RUST_BACKTRACE": "1" - } - }, - { - "type": "lldb", - "request": "launch", - "name": "Debug in apostrophe", - "cargo": { - "args": [ - "build", - "--bin=gopro-chaptered-video-assembler", - "--package=gopro-chaptered-video-assembler" - ], - "filter": { - "name": "gopro-chaptered-video-assembler", - "kind": "bin" - } - }, - "args": ["-i", "tests/working_test_data/Test's Apostrophe", "-o", "tests/output"], - "cwd": "${workspaceFolder}", - "env": { - "RUST_BACKTRACE": "1" - } - }, - { - "type": "lldb", - "request": "launch", - "name": "Debug unit tests in executable 'gopro-chaptered-video-assembler'", - "cargo": { - "args": [ - "test", - "--no-run", - "--bin=gopro-chaptered-video-assembler", - "--package=gopro-chaptered-video-assembler" - ], - "filter": { - "name": "gopro-chaptered-video-assembler", - "kind": "bin" - } - }, - "args": [], - "cwd": "${workspaceFolder}" + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "lldb", + "request": "launch", + "name": "Debug in test", + "cargo": { + "args": [ + "build", + "--bin=gopro-chaptered-video-assembler", + "--package=gopro-chaptered-video-assembler" + ], + "filter": { + "name": "gopro-chaptered-video-assembler", + "kind": "bin" } - ] -} \ No newline at end of file + }, + "args": [ + "--input", + "/home/alichtman/Desktop/Development/projects/gopro-chaptered-video-assembler/tests/data/real_videos", + "--output", + "/home/alichtman/Desktop/Development/projects/gopro-chaptered-video-assembler/tests/data/actual_output", + "--yes", + "--copy-single-chapter-instead-of-rename" + ], + "cwd": "${workspaceFolder}", + "env": { + "RUST_BACKTRACE": "full" + } + }, + { + "type": "lldb", + "request": "launch", + "name": "Debug in apostrophe", + "cargo": { + "args": [ + "build", + "--bin=gopro-chaptered-video-assembler", + "--package=gopro-chaptered-video-assembler" + ], + "filter": { + "name": "gopro-chaptered-video-assembler", + "kind": "bin" + } + }, + "args": [ + "-i", + "tests/working_test_data/Test's Apostrophe", + "-o", + "tests/output" + ], + "cwd": "${workspaceFolder}", + "env": { + "RUST_BACKTRACE": "1" + } + }, + { + "type": "lldb", + "request": "launch", + "name": "Debug unit tests in executable 'gopro-chaptered-video-assembler'", + "cargo": { + "args": [ + "test", + "--no-run", + "--bin=gopro-chaptered-video-assembler", + "--package=gopro-chaptered-video-assembler" + ], + "filter": { + "name": "gopro-chaptered-video-assembler", + "kind": "bin" + } + }, + "args": [], + "cwd": "${workspaceFolder}" + } + ] +} diff --git a/Cargo.lock b/Cargo.lock index fabaa83..1166495 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,27 +3,145 @@ version = 3 [[package]] -name = "atty" -version = "0.2.14" +name = "aho-corasick" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", + "memchr", +] + +[[package]] +name = "anstream" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" + +[[package]] +name = "anstyle-parse" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +dependencies = [ + "utf8parse", ] +[[package]] +name = "anstyle-query" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + +[[package]] +name = "anyhow" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" + +[[package]] +name = "arrayref" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + +[[package]] +name = "assert_cmd" +version = "2.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00ad3f3a942eee60335ab4342358c161ee296829e0d16ff42fc1d6cb07815467" +dependencies = [ + "anstyle", + "bstr", + "doc-comment", + "predicates", + "predicates-core", + "predicates-tree", + "wait-timeout", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "blake3" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0231f06152bf547e9c2b5194f247cd97aacf6dcd8b15d8e5ec0663f64580da87" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", +] + +[[package]] +name = "bstr" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c48f0051a4b4c5e0b6d365cd04af53aeaa209e3cc15ec2cdb69e73cc87fbd0dc" +dependencies = [ + "memchr", + "regex-automata", + "serde", +] + +[[package]] +name = "camino" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" + [[package]] name = "cc" -version = "1.0.79" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] [[package]] name = "cfg-if" @@ -33,110 +151,150 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.1.8" +version = "4.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d7ae14b20b94cb02149ed21a86c423859cbe18dc7ed69845cace50e52b40a5" +checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c" dependencies = [ - "bitflags", + "clap_builder", "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7" +dependencies = [ + "anstream", + "anstyle", "clap_lex", - "is-terminal", - "once_cell", "strsim", - "termcolor", ] [[package]] name = "clap_derive" -version = "4.1.8" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44bec8e5c9d09e439c4335b1af0abaab56dcf3b94999a936e1bb47b9134288f0" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" dependencies = [ "heck", - "proc-macro-error", "proc-macro2", "quote", - "syn 1.0.109", + "syn", ] [[package]] name = "clap_lex" -version = "0.3.2" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "350b9cf31731f9957399229e9b2adc51eeabdfbe9d71d9a0552275fd12710d09" -dependencies = [ - "os_str_bytes", -] +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "colored" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd" +checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" dependencies = [ - "atty", "lazy_static", - "winapi", + "windows-sys 0.48.0", ] [[package]] -name = "dirs" -version = "4.0.0" +name = "constant_time_eq" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" -dependencies = [ - "dirs-sys", -] +checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" [[package]] -name = "dirs-sys" -version = "0.3.7" +name = "crossbeam-deque" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "libc", - "redox_users", - "winapi", + "crossbeam-epoch", + "crossbeam-utils", ] [[package]] -name = "errno" -version = "0.2.8" +name = "crossbeam-epoch" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "errno-dragonfly", - "libc", - "winapi", + "crossbeam-utils", ] [[package]] -name = "errno-dragonfly" -version = "0.1.2" +name = "crossbeam-utils" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" + +[[package]] +name = "deranged" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ - "cc", - "libc", + "powerfmt", ] +[[package]] +name = "difflib" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" + +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + [[package]] name = "filetime" -version = "0.2.20" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a3de6e8d11b22ff9edc6d916f890800597d60f8b2da1caf2955c274638d6412" +checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" dependencies = [ "cfg-if", "libc", "redox_syscall", - "windows-sys", + "windows-sys 0.52.0", ] +[[package]] +name = "float-cmp" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" +dependencies = [ + "num-traits", +] + +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "getrandom" -version = "0.2.8" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", "libc", @@ -147,11 +305,15 @@ dependencies = [ name = "gopro-chaptered-video-assembler" version = "0.5.0" dependencies = [ + "assert_cmd", "clap", "colored", "filetime", + "fs_extra", "log", + "merkle_hash", "normpath", + "predicates", "simplelog", "uuid", "xdg", @@ -164,82 +326,75 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] -name = "hermit-abi" -version = "0.1.19" +name = "itoa" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] -name = "hermit-abi" -version = "0.3.1" +name = "lazy_static" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] -name = "io-lifetimes" -version = "1.0.6" +name = "libc" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfa919a82ea574332e2de6e74b4c36e74d41982b335080fa59d4ef31be20fdf3" -dependencies = [ - "libc", - "windows-sys", -] +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] -name = "is-terminal" -version = "0.4.4" +name = "log" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b6b32576413a8e69b90e952e4a026476040d81017b80445deda5f2d3921857" -dependencies = [ - "hermit-abi 0.3.1", - "io-lifetimes", - "rustix", - "windows-sys", -] +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] -name = "itoa" -version = "1.0.6" +name = "memchr" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] -name = "lazy_static" -version = "1.4.0" +name = "merkle_hash" +version = "3.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "0fad8dc52477aa6f1751748a5ee1c6d50db7092e8dab1d687840dfa23e2ae4e5" +dependencies = [ + "anyhow", + "blake3", + "camino", + "rayon", +] [[package]] -name = "libc" -version = "0.2.140" +name = "normalize-line-endings" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" +checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" [[package]] -name = "linux-raw-sys" -version = "0.1.4" +name = "normpath" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" +checksum = "ec60c60a693226186f5d6edf073232bfb6464ed97eb22cf3b01c1e8198fd97f5" +dependencies = [ + "windows-sys 0.48.0", +] [[package]] -name = "log" -version = "0.4.17" +name = "num-conv" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] -name = "normpath" -version = "1.1.0" +name = "num-traits" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "972dec05f98e7c787ede35d7a9ea4735eb7788c299287352757b3def6cc1f7b5" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" dependencies = [ - "windows-sys", + "autocfg", ] [[package]] @@ -252,98 +407,136 @@ dependencies = [ ] [[package]] -name = "once_cell" -version = "1.17.1" +name = "powerfmt" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] -name = "os_str_bytes" -version = "6.4.1" +name = "predicates" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" +checksum = "68b87bfd4605926cdfefc1c3b5f8fe560e3feca9d5552cf68c466d3d8236c7e8" +dependencies = [ + "anstyle", + "difflib", + "float-cmp", + "normalize-line-endings", + "predicates-core", + "regex", +] [[package]] -name = "proc-macro-error" -version = "1.0.4" +name = "predicates-core" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] +checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174" [[package]] -name = "proc-macro-error-attr" -version = "1.0.4" +name = "predicates-tree" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf" dependencies = [ - "proc-macro2", - "quote", - "version_check", + "predicates-core", + "termtree", ] [[package]] name = "proc-macro2" -version = "1.0.52" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d0e1ae9e836cc3beddd63db0df682593d7e2d3d891ae8c9083d2113e1744224" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.26" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] +[[package]] +name = "rayon" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "redox_syscall" -version = "0.2.16" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ "bitflags", ] [[package]] -name = "redox_users" -version = "0.4.3" +name = "regex" +version = "1.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" dependencies = [ - "getrandom", - "redox_syscall", - "thiserror", + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", ] [[package]] -name = "rustix" -version = "0.36.9" +name = "regex-automata" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd5c6ff11fecd55b40746d1995a02f2eb375bf8c00d192d521ee09f42bef37bc" +checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" dependencies = [ - "bitflags", - "errno", - "io-lifetimes", - "libc", - "linux-raw-sys", - "windows-sys", + "aho-corasick", + "memchr", + "regex-syntax", ] +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + [[package]] name = "serde" -version = "1.0.158" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771d4d9c4163ee138805e12c710dd365e4f44be8be0503cb1bb9eb989425d9c9" +checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.196" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "simplelog" @@ -364,20 +557,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.10" +version = "2.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aad1363ed6d37b84299588d62d3a7d95b5a5c2d9aad5c85609fda12afaa1f40" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" dependencies = [ "proc-macro2", "quote", @@ -394,34 +576,23 @@ dependencies = [ ] [[package]] -name = "thiserror" -version = "1.0.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.40" +name = "termtree" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.10", -] +checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" [[package]] name = "time" -version = "0.3.20" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890" +checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" dependencies = [ + "deranged", "itoa", "libc", + "num-conv", "num_threads", + "powerfmt", "serde", "time-core", "time-macros", @@ -429,39 +600,49 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.8" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd80a657e71da814b8e5d60d3374fc6d35045062245d80224748ae522dd76f36" +checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" dependencies = [ + "num-conv", "time-core", ] [[package]] name = "unicode-ident" -version = "1.0.8" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "utf8parse" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.3.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79" +checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" dependencies = [ "getrandom", ] [[package]] -name = "version_check" -version = "0.9.4" +name = "wait-timeout" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] [[package]] name = "wasi" @@ -487,9 +668,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ "winapi", ] @@ -502,75 +683,138 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" -version = "0.45.0" +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-sys" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.0", ] [[package]] name = "windows-targets" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "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.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.2" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.42.2" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.42.2" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" [[package]] name = "windows_i686_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" +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.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.42.2" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +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" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] name = "xdg" -version = "2.4.1" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4583db5cbd4c4c0303df2d15af80f0539db703fa1c68802d4cbbd2dd0f88f6" -dependencies = [ - "dirs", -] +checksum = "213b7324336b53d2414b2db8537e56544d981803139155afa84f76eeebb7a546" diff --git a/Cargo.toml b/Cargo.toml index 0780a0e..8a99b4b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "gopro-chaptered-video-assembler" version = "0.5.0" edition = "2021" -authors = ["Aaron Lichtman"] +authors = ["Aaron Lichtman "] description = "Assembles all chaptered GoPro video files in a directory into 'complete' files." license-file = "LICENSE" homepage = "https://github.com/alichtman/gopro-chaptered-video-assembler" @@ -16,8 +16,14 @@ keywords = ["gopro", "video", "assembler", "chaptered", "ffmpeg"] clap = { version = "4.1.8", features = ["derive"] } colored = "2.0.0" filetime = "0.2.20" +fs_extra = "1.3.0" log = "0.4.17" +merkle_hash = "3.6.1" normpath = "1.1.0" simplelog = "0.12.1" uuid = { version = "1.3.0", features = ["v4"] } xdg = "2.4.1" + +[dev-dependencies] +assert_cmd = "2.0" +predicates = "3.1" diff --git a/src/cli.rs b/src/cli.rs index 42ffbef..f9cd586 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -27,9 +27,9 @@ pub struct CliArgs { /// Skips renaming single chapter videos #[arg( - short = 'n', - long = "no-single-chapter-rename", + short = 'c', + long = "copy-single-chapter-instead-of-rename", default_value = "false" )] - pub no_single_chapter_rename: bool, + pub copy_single_chapter_instead_of_renaming: bool, } diff --git a/src/ffmpeg.rs b/src/ffmpeg.rs index 1a8f968..19f4838 100644 --- a/src/ffmpeg.rs +++ b/src/ffmpeg.rs @@ -46,7 +46,11 @@ pub fn concatenate_mp4s_from_demuxer_file( info!("Dry run, skipping ffmpeg command!"); return; } - let output = command.spawn().unwrap().wait_with_output().unwrap(); + let output = command + .spawn() + .expect("Command failed to run") + .wait_with_output() + .expect("Command output failed to be collected"); // if ffmpeg doesn't run successfully, scream and die if !output.status.success() { diff --git a/src/main.rs b/src/main.rs index 7a585cf..de6bbdd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -26,16 +26,20 @@ fn main() { initialize_logging(); print_header(); let args = CliArgs::parse(); + print!("{:#?}", args); - // Canonicalize input and output paths up front, creating the output directory if needed. + // Canonicalize input path up front. We don't handle the output path until later to avoid creating the output path if the user cancels the operation. let input_dir = args .input .clone() .unwrap() .canonicalize() .expect("Could not canonicalize input dir path. Does it exist?"); - let output_dir = normalize_and_create_if_needed(args.output.clone().unwrap()); + actually_do_things_with_input_and_output_paths(input_dir, args); +} + +fn actually_do_things_with_input_and_output_paths(input_dir: PathBuf, args: CliArgs) { let input_files = filesystem::get_files_in_directory(input_dir.to_str().unwrap()); if input_files.is_empty() { error!( @@ -54,6 +58,10 @@ fn main() { // Extract data for each video file let videos = parse_gopro_files_directory(input_files); + + // TODO: Ensure all videos are valid mp4s. (#10) + // println!("{:?}", videos); + // Sort the videos by video number, preparing them to be "concat demuxed" by ffmpeg https://stackoverflow.com/a/11175851 let mut multichapter_videos_sorted = gopro::sort_gopro_files(videos); // Filter out videos that only have one chapter to be renamed separately @@ -66,7 +74,7 @@ fn main() { print_expected_output( single_chapter_videos.clone(), multichapter_videos_sorted.clone(), - args.no_single_chapter_rename.clone(), + args.copy_single_chapter_instead_of_renaming.clone(), ); match get_confirmation_before_proceeeding(args.auto_confirm_yes) { true => (), @@ -75,6 +83,7 @@ fn main() { process::exit(0); } } + let output_dir = normalize_and_create_if_needed(args.output.clone().unwrap()); combine_multichapter_videos( multichapter_videos_sorted.clone(), @@ -82,9 +91,11 @@ fn main() { args.clone(), ); - if args.no_single_chapter_rename { - info!("Skipping single chapter rename"); + if args.copy_single_chapter_instead_of_renaming { + print!("Copying single chapter videos instead of renaming"); + copy_single_chapter_videos(single_chapter_videos, output_dir, args.clone()); } else { + print!("Renaming single chapter videos"); rename_single_chapter_videos(single_chapter_videos, output_dir, args.clone()); } @@ -94,6 +105,8 @@ fn main() { } } +// There's some needless code duplication here. Could be cleaner + fn rename_single_chapter_videos( single_chapter_videos: std::collections::HashMap>, output_dir: PathBuf, @@ -116,3 +129,26 @@ fn rename_single_chapter_videos( } } } + +fn copy_single_chapter_videos( + single_chapter_videos: std::collections::HashMap>, + output_dir: PathBuf, + args: CliArgs, +) { + for video in single_chapter_videos { + let video_number = video.0; + let video_path = video.1[0].abs_path.clone(); + let output_path = gen_output_path(&output_dir, video_number, "mp4"); + info!( + "Copying {} to {}", + video_path.to_string_lossy().green().bold(), + output_path.to_string_lossy().blue().bold() + ); + if args.dry_run { + info!("Dry run, skipping copy!"); + continue; + } else { + std::fs::copy(video_path, output_path).expect("Failed to copy file"); + } + } +} diff --git a/src/printing.rs b/src/printing.rs index c915771..6c3cbc1 100644 --- a/src/printing.rs +++ b/src/printing.rs @@ -45,7 +45,7 @@ pub fn get_confirmation_before_proceeeding(skip_confirmation: bool) -> bool { pub fn print_expected_output( single_chapter_videos: std::collections::HashMap>, multichapter_videos_sorted: std::collections::HashMap>, - no_single_chapter_rename: bool, + copy_single_chapter_instead_of_renaming: bool, ) { let mut total_chapters_to_combine = 0; let total_videos_to_output = multichapter_videos_sorted.len(); @@ -53,16 +53,16 @@ pub fn print_expected_output( total_chapters_to_combine += value.len(); } info!( - "Found {} video(s) with {} total chapters to combine", + "These make up {} video(s), with {} total chapters to combine", total_videos_to_output.to_string().blue().bold(), total_chapters_to_combine.to_string().blue().bold() ); if total_videos_to_output > 0 { info!("{:#?}", multichapter_videos_sorted); } - if no_single_chapter_rename { + if copy_single_chapter_instead_of_renaming { info!( - "Skipping renaming of {} single chapter video(s)", + "And {} single chapter video(s) to copy", single_chapter_videos.len().to_string().blue().bold() ); } else { @@ -76,7 +76,12 @@ pub fn print_expected_output( pub fn print_remove_commands( multichapter_videos: std::collections::HashMap>, ) { - println!("{}", "Run the following command(s) to remove the merged chapters".yellow().bold()); + println!( + "{}", + "Run the following command(s) to remove the merged chapters" + .yellow() + .bold() + ); for (_key, chapters) in multichapter_videos { for chapter in chapters { println!("rm '{}'", chapter.abs_path.to_str().unwrap().blue().bold()); diff --git a/tests/data/expected_output/GoPro_2352.mp4 b/tests/data/expected_output/GoPro_2352.mp4 new file mode 100644 index 0000000..a8801cc --- /dev/null +++ b/tests/data/expected_output/GoPro_2352.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d8332113edf2b3cf15319a863a5858093cc53b1149a225d9e742a3ea28937185 +size 136038059 diff --git a/tests/data/expected_output/GoPro_4855.mp4 b/tests/data/expected_output/GoPro_4855.mp4 new file mode 100644 index 0000000..4d69c2e --- /dev/null +++ b/tests/data/expected_output/GoPro_4855.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:93ea737d2e3c5f4422b2019eb9d84e701fa0a4fe96ee552dcd3f59a9882f6a68 +size 61789453 diff --git a/tests/data/expected_output/GoPro_7322.mp4 b/tests/data/expected_output/GoPro_7322.mp4 new file mode 100644 index 0000000..74d75e0 --- /dev/null +++ b/tests/data/expected_output/GoPro_7322.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b72216e88c86f5a143c13a3df0926b66d9039550d5edf7d259bacaac44225870 +size 652853591 diff --git a/tests/data/expected_output/GoPro_7329.mp4 b/tests/data/expected_output/GoPro_7329.mp4 new file mode 100644 index 0000000..91bcad4 --- /dev/null +++ b/tests/data/expected_output/GoPro_7329.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:67401b0fa2219bebb8813f7718952cfe13eac579298a17c366905bc55b2e8bfe +size 381247351 diff --git a/tests/data/real_videos/GH017322.MP4 b/tests/data/real_videos/GH017322.MP4 new file mode 100644 index 0000000..e451744 --- /dev/null +++ b/tests/data/real_videos/GH017322.MP4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1a7d889207b32c0064b682bd30618b6dd845a13ffd2b3b1b150c0cbc9b2db6e4 +size 231805343 diff --git a/tests/data/real_videos/GH017329.MP4 b/tests/data/real_videos/GH017329.MP4 new file mode 100644 index 0000000..7299b69 --- /dev/null +++ b/tests/data/real_videos/GH017329.MP4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:961b165b120dd708e6430144a14ce448d882a2c1edebd86f51ed3aec1b88f9c1 +size 129846626 diff --git a/tests/data/real_videos/GH027322.MP4 b/tests/data/real_videos/GH027322.MP4 new file mode 100644 index 0000000..e02c55f --- /dev/null +++ b/tests/data/real_videos/GH027322.MP4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9daed89e05168f95414824c84af036334894ba57d0ec512155fae7e949612928 +size 421041915 diff --git a/tests/data/real_videos/GH027329.MP4 b/tests/data/real_videos/GH027329.MP4 new file mode 100644 index 0000000..5345976 --- /dev/null +++ b/tests/data/real_videos/GH027329.MP4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0b57e4e08094b677b8f6ec525668a37c401c3fde95aef8faa7113de54b51918c +size 251395360 diff --git a/tests/data/real_videos/GX012352.MP4 b/tests/data/real_videos/GX012352.MP4 new file mode 100644 index 0000000..a8801cc --- /dev/null +++ b/tests/data/real_videos/GX012352.MP4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d8332113edf2b3cf15319a863a5858093cc53b1149a225d9e742a3ea28937185 +size 136038059 diff --git a/tests/data/real_videos/GX014855.MP4 b/tests/data/real_videos/GX014855.MP4 new file mode 100644 index 0000000..4d69c2e --- /dev/null +++ b/tests/data/real_videos/GX014855.MP4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:93ea737d2e3c5f4422b2019eb9d84e701fa0a4fe96ee552dcd3f59a9882f6a68 +size 61789453 diff --git a/tests/integration_test.rs b/tests/integration_test.rs new file mode 100644 index 0000000..7599602 --- /dev/null +++ b/tests/integration_test.rs @@ -0,0 +1,70 @@ +use assert_cmd::prelude::*; +use merkle_hash::{Algorithm, Encodable, MerkleTree}; +use std::path::PathBuf; +use std::process::Command; + +extern crate fs_extra; +use std::fs; + +pub(crate) fn get_hash_of_directory(dir: &PathBuf) -> Vec { + let tree = MerkleTree::builder(dir.to_str().unwrap()) + .algorithm(Algorithm::Blake3) + .hash_names(false) + .build() + .unwrap(); + let master_hash = tree.root.item.hash; + master_hash +} + +pub(crate) fn get_path_to_source_videos() -> PathBuf { + let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + path.push("tests/data/real_videos"); + path +} + +pub(crate) fn get_path_to_test_output() -> PathBuf { + let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + path.push("tests/data/actual_output"); + path +} + +pub(crate) fn get_path_to_expected_output() -> PathBuf { + let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + path.push("tests/data/expected_output"); + path +} + +pub(crate) fn setup() { + self::teardown(); + let _ = fs::create_dir(get_path_to_test_output()); +} + +pub(crate) fn teardown() { + for entry in vec![get_path_to_test_output()] { + let _ = fs::remove_dir_all(entry); + } +} + +#[test] +fn test_run_on_dir() { + self::setup(); + let mut cmd = Command::cargo_bin(env!("CARGO_PKG_NAME")).unwrap(); + cmd.arg("--input") + .arg(get_path_to_source_videos()) + .arg("--output") + .arg(get_path_to_test_output()) + .arg("--yes") + .arg("--copy-single-chapter-instead-of-rename"); + let output = cmd.unwrap(); + print!("{:#?}", output); + // Check that actual_output matches expected_output + let expected_output_hash = get_hash_of_directory(&get_path_to_expected_output()); + let actual_output_hash = get_hash_of_directory(&get_path_to_test_output()); + assert!(expected_output_hash == actual_output_hash); + print!( + "\n{:#?} was the merkle hash for both the expected and actual", + expected_output_hash.to_hex_string() + ); + + self::teardown(); +} diff --git a/tests/setup-test.sh b/tests/setup-test.sh deleted file mode 100755 index 57cf048..0000000 --- a/tests/setup-test.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -# Exit if not in git root -if [ ! -d .git ]; then - echo "Not in git root" - exit 1 -fi - -rm -rf tests/output tests/working_test_data -mkdir tests/working_test_data -mkdir "tests/working_test_data/Test\'s Apostrophe" -cp -vp tests/real_videos/* tests/working_test_data/ -cp -vp tests/real_videos/* "tests/working_test_data/Test\'s Apostrophe"