From d964157bfc76065238fd3dd22b8a4b2ab956604d Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Wed, 31 Jan 2024 21:18:43 +0100 Subject: [PATCH] STUFF --- .gitignore | 1 + Cargo.lock | 632 +++++++++++++++++++++++++++++++++++++++ Cargo.toml | 7 + src/bin/fuf.rs | 6 +- src/cli/commands/db.rs | 12 + src/cli/commands/misc.rs | 8 + src/cli/commands/mod.rs | 2 + src/cli/mod.rs | 72 +++++ src/cli/utils.rs | 9 + src/db.rs | 41 +++ src/lib.rs | 3 + src/workspace.rs | 60 ++++ tests/helpers.rs | 21 ++ tests/init.rs | 27 ++ 14 files changed, 900 insertions(+), 1 deletion(-) create mode 100644 src/cli/commands/db.rs create mode 100644 src/cli/commands/misc.rs create mode 100644 src/cli/commands/mod.rs create mode 100644 src/cli/mod.rs create mode 100644 src/cli/utils.rs create mode 100644 src/db.rs create mode 100644 src/workspace.rs create mode 100644 tests/helpers.rs create mode 100644 tests/init.rs diff --git a/.gitignore b/.gitignore index ea8c4bf..4b9ab5a 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target +.fuf diff --git a/Cargo.lock b/Cargo.lock index 62662ca..938eca0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,638 @@ # 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 = "ambient-authority" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9d4ee0d472d1cd2e28c97dfa124b3d8d992e10eb0a035f33f5d12e3a177ba3b" + +[[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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2faccea4cc4ab4a667ce676a30e8ec13922a692c99bb8f5b11f1502c72e04220" + +[[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", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +dependencies = [ + "anstyle", + "windows-sys", +] + +[[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 = "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 = "bitflags" +version = "2.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" + +[[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 = "cap-primitives" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90a0b44fc796b1a84535a63753d50ba3972c4db55c7255c186f79140e63d56d0" +dependencies = [ + "ambient-authority", + "fs-set-times", + "io-extras", + "io-lifetimes", + "ipnet", + "maybe-owned", + "rustix", + "windows-sys", + "winx", +] + +[[package]] +name = "cap-std" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "266626ce180cf9709f317d0bf9754e3a5006359d87f4bf792f06c9c5f1b63c0f" +dependencies = [ + "cap-primitives", + "io-extras", + "io-lifetimes", + "rustix", +] + +[[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 = "clap" +version = "4.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c" +dependencies = [ + "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", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" + +[[package]] +name = "color-eyre" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a667583cca8c4f8436db8de46ea8233c42a7d9ae424a82d338f2e4675229204" +dependencies = [ + "backtrace", + "color-spantrace", + "eyre", + "indenter", + "once_cell", + "owo-colors", + "tracing-error", +] + +[[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", + "tracing-core", + "tracing-error", +] + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + +[[package]] +name = "constant_time_eq" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" + +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys", +] + +[[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 = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + [[package]] name = "fix-und-fertig" version = "0.1.0" +dependencies = [ + "blake3", + "cap-std", + "clap", + "color-eyre", + "tempfile", +] + +[[package]] +name = "fs-set-times" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "033b337d725b97690d86893f9de22b67b80dcc4e9ad815f348254c38119db8fb" +dependencies = [ + "io-lifetimes", + "rustix", + "windows-sys", +] + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "indenter" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" + +[[package]] +name = "io-extras" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c301e73fb90e8a29e600a9f402d095765f74310d582916a952f618836a1bd1ed" +dependencies = [ + "io-lifetimes", + "windows-sys", +] + +[[package]] +name = "io-lifetimes" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a611371471e98973dbcab4e0ec66c31a10bc356eeb4d54a0e05eac8158fe38c" + +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + +[[package]] +name = "itoa" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" + +[[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.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "linux-raw-sys" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" + +[[package]] +name = "maybe-owned" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4facc753ae494aeb6e3c22f839b158aebd4f9270f55cd3c79906c45476c47ab4" + +[[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 = "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 = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "proc-macro2" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +dependencies = [ + "unicode-ident", +] + +[[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 1.3.2", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustix" +version = "0.38.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca" +dependencies = [ + "bitflags 2.4.2", + "errno", + "itoa", + "libc", + "linux-raw-sys", + "once_cell", + "windows-sys", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "2.0.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" +dependencies = [ + "cfg-if", + "fastrand", + "redox_syscall", + "rustix", + "windows-sys", +] + +[[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 = "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", + "tracing-core", +] + +[[package]] +name = "unicode-ident" +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 = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[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-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +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", +] + +[[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.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + +[[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.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + +[[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.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + +[[package]] +name = "winx" +version = "0.36.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9643b83820c0cd246ecabe5fa454dd04ba4fa67996369466d0747472d337346" +dependencies = [ + "bitflags 2.4.2", + "windows-sys", +] diff --git a/Cargo.toml b/Cargo.toml index c3cddad..17d9e35 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,3 +6,10 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +blake3 = "1.5.0" +cap-std = "3.0.0" +clap = { version = "4.4.18", features = ["derive"] } +color-eyre = "0.6.2" + +[dev-dependencies] +tempfile = "3.9.0" diff --git a/src/bin/fuf.rs b/src/bin/fuf.rs index e71fdf5..ced2646 100644 --- a/src/bin/fuf.rs +++ b/src/bin/fuf.rs @@ -1 +1,5 @@ -fn main() {} \ No newline at end of file +use color_eyre::Result; + +fn main() -> Result<()> { + fix_und_fertig::cli::main() +} \ No newline at end of file diff --git a/src/cli/commands/db.rs b/src/cli/commands/db.rs new file mode 100644 index 0000000..3018c60 --- /dev/null +++ b/src/cli/commands/db.rs @@ -0,0 +1,12 @@ +//! `fuf db` commands. + +use color_eyre::Result; +use std::{path::Path}; + +use crate::{cli::utils, workspace::Workspace}; + +pub fn save_file(workspace: &Workspace, path: &Path) -> Result<()> { + let file = utils::read_file(path)?; + + Ok(()) +} diff --git a/src/cli/commands/misc.rs b/src/cli/commands/misc.rs new file mode 100644 index 0000000..14e6c56 --- /dev/null +++ b/src/cli/commands/misc.rs @@ -0,0 +1,8 @@ +use cap_std::fs::Dir; +use color_eyre::Result; + +use crate::workspace::Workspace; + +pub fn init(dir: &Dir) -> Result<()> { + Workspace::init(dir) +} diff --git a/src/cli/commands/mod.rs b/src/cli/commands/mod.rs new file mode 100644 index 0000000..4864aaf --- /dev/null +++ b/src/cli/commands/mod.rs @@ -0,0 +1,2 @@ +pub mod db; +pub mod misc; diff --git a/src/cli/mod.rs b/src/cli/mod.rs new file mode 100644 index 0000000..e7b50d0 --- /dev/null +++ b/src/cli/mod.rs @@ -0,0 +1,72 @@ +//! The command line interface and commands. + +mod commands; +mod utils; + +use std::{ + env, + fs::File, + path::{Path, PathBuf}, +}; + +use cap_std::fs::Dir; +use clap::{Parser, Subcommand}; +use color_eyre::{eyre::Context, Result}; + +use crate::workspace; + +#[derive(Debug, Parser)] +#[command(name = "fuf")] +#[command(about = "The fix-und-fertig revision control system", long_about = None)] +pub struct Cli { + #[command(subcommand)] + command: Command, +} + +#[derive(Debug, Subcommand)] +pub enum Command { + /// Create a new fix-und-fertig workspace. + Init {}, + /// Low-level commands for working with the .fuf database. + Db { + #[command(subcommand)] + command: DbCommand, + }, +} + +#[derive(Debug, Subcommand)] +pub enum DbCommand { + /// Save a file into the database and get the hash. + SaveFile { path: PathBuf }, +} + +pub fn main() -> Result<()> { + let cwd = env::current_dir().wrap_err("failed to get current directory")?; + let cwd = cwd + .canonicalize() + .wrap_err("failed to canonicalize working directory. does it still exist?")?; + + let cli: Cli = Cli::parse(); + + run_command(&cwd, cli) +} + +pub fn run_command(cwd: &Path, cli: Cli) -> Result<()> { + match cli.command { + Command::Init {} => { + let cwd_file = File::open(&cwd) + .wrap_err_with(|| format!("failed to open working directory {}", cwd.display()))?; + let dir = Dir::from_std_file(cwd_file); + commands::misc::init(&dir) + .wrap_err_with(|| format!("creating fix-und-fertig workspace in {}", cwd.display())) + } + Command::Db { command } => { + let workspace = + workspace::Workspace::find(&cwd).wrap_err("failed to open workspace")?; + + match command { + DbCommand::SaveFile { path } => commands::db::save_file(&workspace, &path), + } + } + } +} diff --git a/src/cli/utils.rs b/src/cli/utils.rs new file mode 100644 index 0000000..ca9987d --- /dev/null +++ b/src/cli/utils.rs @@ -0,0 +1,9 @@ +///! Utilities for the CLI functions. These should *not* be used outside of the CLI-specific code! + +use color_eyre::{eyre::Context, Result}; +use std::path::Path; + +/// [`std::fs::read`], adding the path to the error message. +pub(super) fn read_file(path: &Path) -> Result> { + std::fs::read(path).wrap_err_with(|| format!("trying to open {}", path.display())) +} diff --git a/src/db.rs b/src/db.rs new file mode 100644 index 0000000..e11f020 --- /dev/null +++ b/src/db.rs @@ -0,0 +1,41 @@ +//! Content-addressed database for objects. +//! My idea was to use SQLite for this but using the fs will be easier at first so I'm gonna do that lol. +//! +//! Currently, the database is structured like this: +//! +//! ```text +//! .fuf +//! |-- db +//! |-- objects +//! |-- 0d +//! | |-- 0da893381fdb97c73eb9ca8c68fb0a04803f1f17d8c72a72c84b9535f62c08cd +//! |-- 60 +//! |-- 60d4301d00238a934f94eacd0d4963ca7810afd9f198256e9f6aea2d8c101793 +//! ``` + +use cap_std::fs::Dir; +use color_eyre::{eyre::Context, Result}; + +pub struct Db { + db: Dir, + objects: Dir, +} + +impl Db { + pub fn init(dir: &Dir) -> Result<()> { + dir.create_dir(".fuf/db").wrap_err("creating .fuf/db")?; + dir.create_dir(".fuf/db/objects") + .wrap_err("creating .fuf/db/objects")?; + Ok(()) + } + pub fn open(dir: &Dir) -> Result { + let db = dir + .open_dir(".fuf/db") + .wrap_err("error opening .fuf/db in workspace")?; + let objects = db + .open_dir("objects") + .wrap_err("error opening .fuf/db/objects")?; + + Ok(Self { db, objects }) + } +} diff --git a/src/lib.rs b/src/lib.rs index e69de29..fc245b6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -0,0 +1,3 @@ +pub mod cli; +mod db; +mod workspace; diff --git a/src/workspace.rs b/src/workspace.rs new file mode 100644 index 0000000..aec0e2a --- /dev/null +++ b/src/workspace.rs @@ -0,0 +1,60 @@ +use std::{ + fs::File, + path::{Path, PathBuf}, +}; + +use crate::db::Db; +use cap_std::fs::Dir; +use color_eyre::{ + eyre::{bail, Context}, + Result, +}; + +pub struct Workspace { + root: Dir, + db: Db, +} + +impl Workspace { + pub fn init(dir: &Dir) -> Result<()> { + dir.create_dir(".fuf").wrap_err("creating .fuf")?; + Db::init(&dir)?; + Ok(()) + } + + pub fn find(dir: &Path) -> Result { + let Some(root) = find_workspace_dir(dir)? else { + bail!("you are not in a fix-und-fertig workspace, indicated by a .fuf directory"); + }; + + Self::open_root(&root).wrap_err_with(|| format!("opening workspace {}", root.display())) + } + + pub fn open_root(root: &Path) -> Result { + let dir = File::open(root).wrap_err("opening workspace directory")?; + let dir = Dir::from_std_file(dir); + let db = Db::open(&dir).wrap_err("opening .fuf database")?; + Ok(Self { root: dir, db }) + } +} + +/// Finds the workspace that `dir` is part of. +pub fn find_workspace_dir(mut dir: &Path) -> Result> { + assert!(dir.is_absolute()); + // No cap-std yet, we need to figure out the workspace first. + loop { + let readdir = std::fs::read_dir(dir) + .wrap_err_with(|| format!("failed to read path {}", dir.display()))?; + + for child in readdir { + let child = child + .wrap_err_with(|| format!("failed to read entry in directory {}", dir.display()))?; + if child.path().ends_with(".fuf") {} + } + + let Some(parent) = dir.parent() else { + return Ok(None); + }; + dir = parent; + } +} diff --git a/tests/helpers.rs b/tests/helpers.rs new file mode 100644 index 0000000..677dd71 --- /dev/null +++ b/tests/helpers.rs @@ -0,0 +1,21 @@ +use clap::{CommandFactory, FromArgMatches}; +use color_eyre::Result; +use std::ffi::OsStr; + +use fix_und_fertig::cli::Cli; + +pub fn tmpdir() -> tempfile::TempDir { + tempfile::TempDir::new().unwrap() +} + +pub fn run_in>(dir: &tempfile::TempDir, args: impl AsRef<[S]>) -> Result<()> { + let mut matches = ::command().get_matches_from( + [OsStr::new("fuf")] + .into_iter() + .chain(args.as_ref().into_iter().map(AsRef::as_ref)), + ); + let cli = + ::from_arg_matches_mut(&mut matches).expect("invalid CLI args"); + + fix_und_fertig::cli::run_command(dir.path(), cli) +} diff --git a/tests/init.rs b/tests/init.rs new file mode 100644 index 0000000..e5c967f --- /dev/null +++ b/tests/init.rs @@ -0,0 +1,27 @@ +mod helpers; +use helpers::*; + +#[test] +fn init() { + let dir = tmpdir(); + + run_in(&dir, ["init"]).unwrap(); + + assert!(dir.path().join(".fuf").is_dir()); + assert!(dir.path().join(".fuf").join("db").is_dir()); + assert!(dir.path().join(".fuf").join("db").join("objects").is_dir()); +} + +#[test] +fn double_init() { + let dir = tmpdir(); + + run_in(&dir, ["init"]).unwrap(); + + assert!(dir.path().join(".fuf").is_dir()); + assert!(dir.path().join(".fuf").join("db").is_dir()); + assert!(dir.path().join(".fuf").join("db").join("objects").is_dir()); + + + assert!(run_in(&dir, ["init"]).is_err()); +}