From 92b05a877eb772985d2f4fc9cd198ca642b69b6a Mon Sep 17 00:00:00 2001 From: diogo464 Date: Tue, 8 Feb 2022 09:21:12 +0000 Subject: removed old code --- Cargo.lock | 627 ------------------------------------ Cargo.toml | 2 - dotup/Cargo.toml | 14 - dotup/src/archive.rs | 44 --- dotup/src/depot.rs | 484 ---------------------------- dotup/src/error.rs | 21 -- dotup/src/lib.rs | 18 -- dotup/src/utils.rs | 94 ------ dotup/tests/integration_tests.rs | 126 -------- dotup/tests/testing_depot.toml | 7 - dotup_cli/Cargo.toml | 29 -- dotup_cli/src/commands/init.rs | 22 -- dotup_cli/src/commands/install.rs | 25 -- dotup_cli/src/commands/link.rs | 134 -------- dotup_cli/src/commands/mod.rs | 11 - dotup_cli/src/commands/mv.rs | 53 --- dotup_cli/src/commands/status.rs | 175 ---------- dotup_cli/src/commands/uninstall.rs | 26 -- dotup_cli/src/commands/unlink.rs | 43 --- dotup_cli/src/config.rs | 10 - dotup_cli/src/main.rs | 111 ------- dotup_cli/src/utils.rs | 182 ----------- dotup_cli/tests/cli.rs | 145 --------- 23 files changed, 2403 deletions(-) delete mode 100644 Cargo.lock delete mode 100644 Cargo.toml delete mode 100644 dotup/Cargo.toml delete mode 100644 dotup/src/archive.rs delete mode 100644 dotup/src/depot.rs delete mode 100644 dotup/src/error.rs delete mode 100644 dotup/src/lib.rs delete mode 100644 dotup/src/utils.rs delete mode 100644 dotup/tests/integration_tests.rs delete mode 100644 dotup/tests/testing_depot.toml delete mode 100644 dotup_cli/Cargo.toml delete mode 100644 dotup_cli/src/commands/init.rs delete mode 100644 dotup_cli/src/commands/install.rs delete mode 100644 dotup_cli/src/commands/link.rs delete mode 100644 dotup_cli/src/commands/mod.rs delete mode 100644 dotup_cli/src/commands/mv.rs delete mode 100644 dotup_cli/src/commands/status.rs delete mode 100644 dotup_cli/src/commands/uninstall.rs delete mode 100644 dotup_cli/src/commands/unlink.rs delete mode 100644 dotup_cli/src/config.rs delete mode 100644 dotup_cli/src/main.rs delete mode 100644 dotup_cli/src/utils.rs delete mode 100644 dotup_cli/tests/cli.rs diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index dd07c28..0000000 --- a/Cargo.lock +++ /dev/null @@ -1,627 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "aho-corasick" -version = "0.7.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" -dependencies = [ - "memchr", -] - -[[package]] -name = "ansi_term" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" -dependencies = [ - "winapi", -] - -[[package]] -name = "anyhow" -version = "1.0.51" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b26702f315f53b6071259e15dd9d64528213b44d61de1ec926eca7715d62203" - -[[package]] -name = "assert_cmd" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e996dc7940838b7ef1096b882e29ec30a3149a3a443cdc8dba19ed382eca1fe2" -dependencies = [ - "bstr", - "doc-comment", - "predicates", - "predicates-core", - "predicates-tree", - "wait-timeout", -] - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi", -] - -[[package]] -name = "autocfg" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" - -[[package]] -name = "bitflags" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" - -[[package]] -name = "bstr" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90682c8d613ad3373e66de8c6411e0ae2ab2571e879d2efbf73558cc66f21279" -dependencies = [ - "lazy_static", - "memchr", - "regex-automata", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "clap" -version = "3.0.0-rc.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9468f8012246b0836c6fd11725102b0844254985f2462b6c637d50040ef49df0" -dependencies = [ - "atty", - "bitflags", - "clap_derive", - "indexmap", - "lazy_static", - "os_str_bytes", - "strsim", - "termcolor", - "textwrap", -] - -[[package]] -name = "clap_derive" -version = "3.0.0-rc.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b72e1af32a4de4d21a43d26de33fe69c00e895371bd8b1523d674f011b610467" -dependencies = [ - "heck", - "proc-macro-error", - "proc-macro2", - "quote", - "syn", -] - -[[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 = "dotup" -version = "0.1.0" -dependencies = [ - "log", - "serde", - "slotmap", - "tempfile", - "thiserror", - "toml", -] - -[[package]] -name = "dotup_cli" -version = "0.1.0" -dependencies = [ - "ansi_term", - "anyhow", - "assert_cmd", - "clap", - "dotup", - "flexi_logger", - "log", - "tempfile", -] - -[[package]] -name = "either" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" - -[[package]] -name = "flexi_logger" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11be38a063886b7be57de89636d65c07d318c1f9bd985cd8ab2c343786a910bc" -dependencies = [ - "ansi_term", - "atty", - "glob", - "lazy_static", - "log", - "regex", - "rustversion", - "thiserror", - "time", -] - -[[package]] -name = "getrandom" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "glob" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" - -[[package]] -name = "hashbrown" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" - -[[package]] -name = "heck" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "indexmap" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" -dependencies = [ - "autocfg", - "hashbrown", -] - -[[package]] -name = "itertools" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" - -[[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.106" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a60553f9a9e039a333b4e9b20573b9e9b9c0bb3a11e201ccc48ef4283456d673" - -[[package]] -name = "log" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "memchr" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" - -[[package]] -name = "os_str_bytes" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" -dependencies = [ - "memchr", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" - -[[package]] -name = "predicates" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6e46ca79eb4e21e2ec14430340c71250ab69332abf85521c95d3a8bc336aa76" -dependencies = [ - "difflib", - "itertools", - "predicates-core", -] - -[[package]] -name = "predicates-core" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57e35a3326b75e49aa85f5dc6ec15b41108cf5aee58eabb1f274dd18b73c2451" - -[[package]] -name = "predicates-tree" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15f553275e5721409451eb85e15fd9a860a6e5ab4496eb215987502b5f5391f2" -dependencies = [ - "predicates-core", - "treeline", -] - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro2" -version = "1.0.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "quote" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", - "rand_hc", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rand_hc" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" -dependencies = [ - "rand_core", -] - -[[package]] -name = "redox_syscall" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab49abadf3f9e1c4bc499e8845e152ad87d2ad2d30371841171169e9d75feee" -dependencies = [ - "bitflags", -] - -[[package]] -name = "regex" -version = "1.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" - -[[package]] -name = "regex-syntax" -version = "0.6.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" - -[[package]] -name = "remove_dir_all" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi", -] - -[[package]] -name = "rustversion" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61b3909d758bb75c79f23d4736fac9433868679d3ad2ea7a61e3c25cfda9a088" - -[[package]] -name = "serde" -version = "1.0.132" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9875c23cf305cd1fd7eb77234cbb705f21ea6a72c637a5c6db5fe4b8e7f008" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.132" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc0db5cb2556c0e558887d9bbdcf6ac4471e83ff66cf696e5419024d1606276" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "slotmap" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1e08e261d0e8f5c43123b7adf3e4ca1690d655377ac93a03b2c9d3e98de1342" -dependencies = [ - "version_check", -] - -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - -[[package]] -name = "syn" -version = "1.0.81" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2afee18b8beb5a596ecb4a2dce128c719b4ba399d34126b9e4396e3f9860966" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "tempfile" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" -dependencies = [ - "cfg-if", - "libc", - "rand", - "redox_syscall", - "remove_dir_all", - "winapi", -] - -[[package]] -name = "termcolor" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "textwrap" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" - -[[package]] -name = "thiserror" -version = "1.0.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "time" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41effe7cfa8af36f439fac33861b66b049edc6f9a32331e2312660529c1c24ad" -dependencies = [ - "itoa", - "libc", - "time-macros", -] - -[[package]] -name = "time-macros" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25eb0ca3468fc0acc11828786797f6ef9aa1555e4a211a60d64cc8e4d1be47d6" - -[[package]] -name = "toml" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" -dependencies = [ - "serde", -] - -[[package]] -name = "treeline" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7f741b240f1a48843f9b8e0444fb55fb2a4ff67293b50a9179dfd5ea67f8d41" - -[[package]] -name = "unicode-segmentation" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" - -[[package]] -name = "unicode-xid" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" - -[[package]] -name = "version_check" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" - -[[package]] -name = "wait-timeout" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" -dependencies = [ - "libc", -] - -[[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml deleted file mode 100644 index 76e6a10..0000000 --- a/Cargo.toml +++ /dev/null @@ -1,2 +0,0 @@ -[workspace] -members = ["dotup", "dotup_cli"] diff --git a/dotup/Cargo.toml b/dotup/Cargo.toml deleted file mode 100644 index fe4876c..0000000 --- a/dotup/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -edition = "2018" -name = "dotup" -version = "0.1.0" - -[dependencies] -log = "0.4" -serde = { version = "*", features = ["derive"] } -thiserror = "1.0" -toml = "0.5" -slotmap = "1.0" - -[dev-dependencies] -tempfile = "3.2" diff --git a/dotup/src/archive.rs b/dotup/src/archive.rs deleted file mode 100644 index 7328b5b..0000000 --- a/dotup/src/archive.rs +++ /dev/null @@ -1,44 +0,0 @@ -use serde::{Deserialize, Serialize}; -use std::path::{Path, PathBuf}; - -use crate::internal_prelude::*; - -#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct ArchiveLink { - pub origin: PathBuf, - pub destination: PathBuf, -} - -#[derive(Debug, Default, Clone, Serialize, Deserialize)] -pub struct Archive { - pub links: Vec, -} - -pub fn archive_exists(path: impl AsRef) -> bool { - utils::is_file(path).unwrap_or_default() -} - -pub fn archive_read(path: impl AsRef) -> Result { - let contents = std::fs::read_to_string(path)?; - archive_deserialize(contents) -} - -pub fn archive_write(path: impl AsRef, archive: &Archive) -> Result<()> { - let serialized = archive_serialize(archive)?; - std::fs::write(path, &serialized)?; - Ok(()) -} - -pub fn archive_serialize(archive: &Archive) -> Result { - match toml::to_string_pretty(archive) { - Ok(serialized) => Ok(serialized), - Err(e) => Err(Error::SerializationError(Box::new(e))), - } -} - -pub fn archive_deserialize(contents: impl AsRef) -> Result { - match toml::from_str(contents.as_ref()) { - Ok(archive) => Ok(archive), - Err(e) => Err(Error::SerializationError(Box::new(e))), - } -} diff --git a/dotup/src/depot.rs b/dotup/src/depot.rs deleted file mode 100644 index 658c0f6..0000000 --- a/dotup/src/depot.rs +++ /dev/null @@ -1,484 +0,0 @@ -use slotmap::SlotMap; -use std::{ - collections::HashMap, - fs::Metadata, - path::{Path, PathBuf}, -}; -use thiserror::Error; - -use crate::{internal_prelude::*, Archive, ArchiveLink}; - -#[derive(Debug, Error)] -pub enum LinkCreateError { - #[error("Link origin is outside depot base\nDepot : {}\nLink : {}", .depot_base.display(), .origin.display())] - LinkOriginOutsideDepot { - depot_base: PathBuf, - origin: PathBuf, - }, - #[error("Link path is not relative : {}", .0.display())] - LinkPathIsNotRelative(PathBuf), - #[error("Link origin doesnt exist : {}", .0.display())] - LinkOriginDoesntExist(PathBuf), - #[error("Cannot create link for directory {} beacause it has a linked child", .0.display())] - DirectoryHasLinkedChildren(PathBuf), - #[error("Cannot create link for file {} beacause it has a linked parent", .0.display())] - FileHasLinkedParent(PathBuf), - #[error(transparent)] - IOError(#[from] std::io::Error), -} - -#[derive(Debug, Error)] -pub enum LinkInstallError { - #[error(transparent)] - IOError(#[from] std::io::Error), - #[error("File already exists at {}", .0.display())] - FileExists(PathBuf, Metadata), - /// .0 = LinkPath , .1 = LinkDestination - #[error("Link already exists {} -> {}", .0.display(), .1.display())] - LinkExists(PathBuf, PathBuf), -} - -#[derive(Debug)] -pub struct DepotConfig { - /// The archive used to initialize the depot. - /// A default archive can be create if one didnt already exist. - pub archive: Archive, - /// Path to the archive file. This path must be valid and must exist. - pub archive_path: PathBuf, -} - -slotmap::new_key_type! { pub struct LinkID; } - -#[derive(Debug)] -pub struct LinkCreateParams { - pub origin: PathBuf, - /// This must be a relative path - pub destination: PathBuf, -} - -impl LinkCreateParams { - pub fn new(origin: impl Into, destination: impl Into) -> Self { - Self { - origin: origin.into(), - destination: destination.into(), - } - } -} - -impl std::fmt::Display for LinkCreateParams { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!( - f, - "{} -> {}", - self.origin.display(), - self.destination.display() - ) - } -} - -impl From for LinkCreateParams { - fn from(archive_link: ArchiveLink) -> Self { - Self { - origin: archive_link.origin, - destination: archive_link.destination, - } - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -enum LinkType { - File, - Directory, -} - -#[derive(Debug)] -pub struct Link { - id: LinkID, - ty: LinkType, - /// The origin path, when joined with the depot base path, must be valid and it point to a file that exists. - origin: PathBuf, - /// Canonical version of origin - origin_canonical: PathBuf, - /// The destination path has to be a relative path. - /// To install a link the destination path is joined with the - /// install path and the file at base path + origin path is linked - /// to this resulting destination path. - destination: PathBuf, -} - -impl Link { - pub fn id(&self) -> LinkID { - self.id - } - - fn link_type(&self) -> LinkType { - self.ty - } - - /// The relative path to the origin file. Relative from depot folder. - pub fn origin(&self) -> &Path { - &self.origin - } - - pub fn origin_canonical(&self) -> &Path { - &self.origin_canonical - } - - /// The relative path to the install destination. - /// This path should be concatenated with an install destination to get the actual destination - /// for this link. - pub fn destination(&self) -> &Path { - &self.destination - } - - /// Where this link would be installed with the given `install_base`. - pub fn install_destination(&self, install_base: &Path) -> PathBuf { - utils::weakly_canonical(install_base.join(self.destination())) - } -} - -impl std::fmt::Display for Link { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!( - f, - "{} -> {}", - self.origin().display(), - self.destination().display() - ) - } -} - -#[derive(Debug)] -pub struct Depot { - // Must be canonical path - base_path: PathBuf, - // Must be canonical path - archive_path: PathBuf, - // Maps the origin to the link - links: SlotMap, - links_by_origin: HashMap, -} - -impl Depot { - /// Creates a new [`Depot`] using the config. - /// Fails if any of the links in the provided archive fail to be created. - pub fn new(config: DepotConfig) -> Result { - depot_create(config) - } - - /// Creates a new link from the description. - /// The origin path must exist. - /// If a link with the same origin already existed then it is replaced. - pub fn create_link(&mut self, link_desc: LinkCreateParams) -> Result { - let link = depot_create_link(self, link_desc)?; - let link_id = depot_insert_link(self, link); - Ok(link_id) - } - - pub fn get_link(&self, link_id: LinkID) -> Option<&Link> { - depot_get_link(self, link_id) - } - - pub fn get_link_by_path(&self, path: &Path) -> Option<&Link> { - self.get_link_id_by_path(path) - .map(|id| self.get_link(id).unwrap()) - } - - pub fn get_link_id_by_path(&self, path: &Path) -> Option { - let weak = utils::weakly_canonical(path); - for link in self.links() { - if link.origin_canonical() == weak { - return Some(link.id()); - } - } - None - } - - pub fn rename_link(&mut self, link_id: LinkID, origin: &Path) { - // TODO: improve - if let Some(id) = self.get_link_id_by_path(origin) { - if link_id != id { - self.remove_link(id); - } - } - if let Some(link) = self.links.get_mut(link_id) { - let origin_canonical = utils::weakly_canonical(origin); - if !origin_canonical.starts_with(&self.base_path) { - panic!("new origin outside depot"); - } - - link.origin = origin_canonical; - link.origin_canonical = utils::weakly_canonical(&link.origin); - } - } - - /// checks if there are any linked files/directories under the path `path` - /// if `path` is a path to a file and that file is linked then this function returns true - pub fn subpath_has_links(&self, path: &Path) -> bool { - let canonical = utils::weakly_canonical(path); - for link in self.links() { - if link.origin_canonical().starts_with(&canonical) { - return true; - } - } - false - } - - pub fn remove_link(&mut self, link_id: LinkID) { - depot_remove_link(self, link_id) - } - - pub fn remove_link_by_path(&mut self, path: &Path) { - if let Some(id) = self.get_link_id_by_path(path) { - self.remove_link(id); - } - } - - /// Archives this depot so it can be serialized - pub fn archive(&self) -> Archive { - depot_archive(self) - } - - pub fn links(&self) -> impl Iterator { - depot_links(self) - } - - pub fn install_link( - &self, - link: &Link, - install_base: impl AsRef, - ) -> Result<(), LinkInstallError> { - depot_install_link(self, link, install_base.as_ref()) - } - - pub fn is_link_installed(&self, link: &Link, install_base: impl AsRef) -> bool { - depot_is_link_installed(link, install_base.as_ref()) - } - - pub fn uninstall_link(&self, link: &Link, install_base: impl AsRef) -> Result<()> { - depot_uninstall_link(self, link, install_base.as_ref()) - } - - pub fn base_path(&self) -> &Path { - &self.base_path - } - - pub fn archive_path(&self) -> &Path { - &self.archive_path - } -} - -fn depot_create(config: DepotConfig) -> Result { - let archive_path = match config.archive_path.canonicalize() { - Ok(canonicalized) => canonicalized, - Err(e) => return Err(Error::ArchiveMissing(config.archive_path, e)), - }; - if !archive_path.is_file() { - return Err(Error::ArchivePathNotFile(archive_path)); - } - let base_path = archive_path - .parent() - .expect("Failed to get parent of archive path") - .to_path_buf(); - - let mut depot = Depot { - base_path, - archive_path, - links: Default::default(), - links_by_origin: Default::default(), - }; - - for archive_link in config.archive.links { - let link_desc = LinkCreateParams::from(archive_link); - let link = depot_create_link(&depot, link_desc)?; - depot_insert_link(&mut depot, link); - } - - Ok(depot) -} - -fn depot_archive(depot: &Depot) -> Archive { - let mut links = Vec::new(); - - for link in depot_links(depot) { - let archive_link = link_to_archive_link(link); - links.push(archive_link); - } - - Archive { links } -} - -/// Create a valid link for that given Depot using the given link desc. -/// The link id is corrected when the link is inserted in the depot. -fn depot_create_link(depot: &Depot, link_desc: LinkCreateParams) -> Result { - // link_ensure_relative_path(&link_desc.origin)?; - link_ensure_relative_path(&link_desc.destination)?; - debug_assert!(utils::is_canonical(depot.base_path())); - - // Check if the file/directory at origin actually exists - let origin_joined = depot.base_path().join(&link_desc.origin); - let origin_result = origin_joined.canonicalize(); - let origin_canonical = match origin_result { - Ok(canonical) => canonical, - Err(e) => match e.kind() { - std::io::ErrorKind::NotFound => { - return Err(LinkCreateError::LinkOriginDoesntExist(origin_joined)) - } - _ => return Err(e.into()), - }, - }; - - if !origin_canonical.starts_with(depot.base_path()) { - return Err(LinkCreateError::LinkOriginOutsideDepot { - depot_base: depot.base_path().to_path_buf(), - origin: origin_canonical, - }); - } - - // unwrap should be fine, this path starts with the prefix - let origin = origin_canonical - .strip_prefix(depot.base_path()) - .unwrap() - .to_path_buf(); - let destination = link_desc.destination; - - let ty = if origin.is_dir() { - for link in depot.links() { - if link.origin().starts_with(&origin) && link.origin() != origin { - return Err(LinkCreateError::DirectoryHasLinkedChildren(origin)); - } - } - LinkType::Directory - } else { - for link in depot.links() { - if origin.starts_with(link.origin()) && origin != link.origin() { - assert_eq!(link.link_type(), LinkType::Directory); - return Err(LinkCreateError::FileHasLinkedParent(origin)); - } - } - LinkType::File - }; - - Ok(Link { - id: Default::default(), - ty, - origin, - origin_canonical, - destination, - }) -} - -fn depot_get_link(depot: &Depot, link_id: LinkID) -> Option<&Link> { - depot.links.get(link_id) -} - -fn depot_remove_link(depot: &mut Depot, link_id: LinkID) { - depot.links.remove(link_id); -} - -fn depot_install_link( - _depot: &Depot, - link: &Link, - install_base: &Path, -) -> Result<(), LinkInstallError> { - let final_origin = link.origin_canonical(); - let final_destination = link.install_destination(install_base); - - log::debug!("Final origin : {}", final_origin.display()); - log::debug!("Final destination : {}", final_destination.display()); - - if let Some(dest_base) = final_destination.parent() { - std::fs::create_dir_all(dest_base)?; - } - - // Exit early if there is some error or if the link already exists - match std::fs::symlink_metadata(&final_destination) { - Ok(metadata) => { - let filetype = metadata.file_type(); - if filetype.is_symlink() { - let symlink_destination = std::fs::read_link(&final_destination)?; - if symlink_destination == final_origin { - return Ok(()); - } - log::trace!( - "Symlink destinations where not equal : {} != {}", - final_origin.display(), - symlink_destination.display() - ); - return Err(LinkInstallError::LinkExists( - final_destination, - symlink_destination, - )); - } else { - return Err(LinkInstallError::FileExists(final_destination, metadata)); - } - } - Err(e) if e.kind() == std::io::ErrorKind::NotFound => {} - Err(e) => return Err(e.into()), - }; - - log::debug!( - "Creating symlink from {} to {}", - final_origin.display(), - final_destination.display() - ); - std::os::unix::fs::symlink(&final_origin, &final_destination)?; - - Ok(()) -} - -fn depot_is_link_installed(link: &Link, install_base: &Path) -> bool { - let origin_canonical = link.origin_canonical(); - let install_destination = link.install_destination(install_base); - match std::fs::read_link(&install_destination) { - Ok(target) if target == origin_canonical => true, - _ => false, - } -} - -fn depot_uninstall_link(_depot: &Depot, link: &Link, install_base: &Path) -> Result<()> { - let origin_canonical = link.origin_canonical(); - let install_destination = link.install_destination(install_base); - let link_target = match std::fs::read_link(&install_destination) { - Ok(target) => target, - Err(e) if e.kind() == std::io::ErrorKind::NotFound => return Ok(()), - Err(e) => return Err(e.into()), - }; - - if link_target.canonicalize()? == origin_canonical { - std::fs::remove_file(&install_destination)?; - } - - Ok(()) -} - -fn depot_insert_link(depot: &mut Depot, mut link: Link) -> LinkID { - let origin = link.origin().to_path_buf(); - if let Some(link_id) = depot.links_by_origin.remove(&origin) { - depot.links.remove(link_id); - } - let link_id = depot.links.insert_with_key(move |k| { - link.id = k; - link - }); - depot.links_by_origin.insert(origin, link_id); - link_id -} - -fn depot_links(depot: &Depot) -> impl Iterator { - depot.links.values() -} - -fn link_ensure_relative_path(path: &Path) -> Result<(), LinkCreateError> { - if !path.is_relative() { - return Err(LinkCreateError::LinkPathIsNotRelative(path.to_path_buf())); - } - Ok(()) -} - -fn link_to_archive_link(depot_link: &Link) -> ArchiveLink { - ArchiveLink { - origin: depot_link.origin().to_path_buf(), - destination: depot_link.destination().to_path_buf(), - } -} diff --git a/dotup/src/error.rs b/dotup/src/error.rs deleted file mode 100644 index 8ad801d..0000000 --- a/dotup/src/error.rs +++ /dev/null @@ -1,21 +0,0 @@ -use crate::{LinkCreateError, LinkInstallError}; -use std::path::PathBuf; -use thiserror::Error; - -#[derive(Debug, Error)] -pub enum Error { - #[error("Link install error : {0}")] - LinkInstallError(#[from] LinkInstallError), - #[error("Link create error : {0}")] - LinkCreateError(#[from] LinkCreateError), - #[error("Link origin doesnt exist : {}", .0.display())] - ArchivePathNotFile(PathBuf), - #[error("The archive path did not exist : {}\n{}", .0.display(), .1)] - ArchiveMissing(PathBuf, std::io::Error), - #[error("Deserialization error : {0}")] - SerializationError(Box), - #[error(transparent)] - IOError(#[from] std::io::Error), -} - -pub type Result = std::result::Result; diff --git a/dotup/src/lib.rs b/dotup/src/lib.rs deleted file mode 100644 index 96c4cd7..0000000 --- a/dotup/src/lib.rs +++ /dev/null @@ -1,18 +0,0 @@ -mod archive; -mod depot; -mod error; - -pub mod utils; - -pub use archive::{ - archive_deserialize, archive_exists, archive_read, archive_serialize, archive_write, Archive, - ArchiveLink, -}; -pub use depot::{ - Depot, DepotConfig, Link, LinkCreateError, LinkCreateParams, LinkID, LinkInstallError, -}; -pub use error::{Error, Result}; - -pub(crate) mod internal_prelude { - pub use super::{utils, Error, Result}; -} diff --git a/dotup/src/utils.rs b/dotup/src/utils.rs deleted file mode 100644 index c9ea959..0000000 --- a/dotup/src/utils.rs +++ /dev/null @@ -1,94 +0,0 @@ -use std::path::{Component, Path, PathBuf}; - -pub fn is_file(path: impl AsRef) -> std::io::Result { - let metadata = match std::fs::metadata(path) { - Ok(metadata) => metadata, - Err(e) => match e.kind() { - std::io::ErrorKind::NotFound => return Ok(false), - _ => return Err(e), - }, - }; - Ok(metadata.is_file()) -} - -pub fn is_directory(path: impl AsRef) -> std::io::Result { - let metadata = match std::fs::metadata(path) { - Ok(metadata) => metadata, - Err(e) => match e.kind() { - std::io::ErrorKind::NotFound => return Ok(false), - _ => return Err(e), - }, - }; - Ok(metadata.is_dir()) -} - -pub fn is_canonical(path: &Path) -> bool { - path == weakly_canonical(path).as_path() -} - -pub fn weakly_canonical(path: impl AsRef) -> PathBuf { - let cwd = std::env::current_dir().expect("Failed to obtain current directory"); - weakly_canonical_cwd(path, cwd) -} - -fn weakly_canonical_cwd(path: impl AsRef, cwd: PathBuf) -> PathBuf { - // Adapated from - // https://github.com/rust-lang/cargo/blob/fede83ccf973457de319ba6fa0e36ead454d2e20/src/cargo/util/paths.rs#L61 - let path = path.as_ref(); - - let mut components = path.components().peekable(); - let mut canonical = cwd; - let prefix = if let Some(c @ Component::Prefix(..)) = components.peek().cloned() { - components.next(); - PathBuf::from(c.as_os_str()) - } else { - PathBuf::new() - }; - - for component in components { - match component { - Component::Prefix(_) => unreachable!(), - Component::RootDir => { - canonical = prefix.clone(); - canonical.push(component.as_os_str()) - } - Component::CurDir => {} - Component::ParentDir => { - canonical.pop(); - } - Component::Normal(p) => canonical.push(p), - }; - } - - canonical -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn weak_canonical_test() { - let cwd = PathBuf::from("/home/user"); - assert_eq!( - PathBuf::from("/home/dest"), - weakly_canonical_cwd("../dest", cwd.clone()) - ); - assert_eq!( - PathBuf::from("/home/dest/configs/init.vim"), - weakly_canonical_cwd("../dest/configs/init.vim", cwd.clone()) - ); - assert_eq!( - PathBuf::from("/dest/configs/init.vim"), - weakly_canonical_cwd("/dest/configs/init.vim", cwd.clone()) - ); - assert_eq!( - PathBuf::from("/home/user/configs/nvim/lua/setup.lua"), - weakly_canonical_cwd("./configs/nvim/lua/setup.lua", cwd.clone()) - ); - assert_eq!( - PathBuf::from("/home/user/configs/nvim/lua/setup.lua"), - weakly_canonical_cwd("configs/nvim/lua/setup.lua", cwd.clone()) - ); - } -} diff --git a/dotup/tests/integration_tests.rs b/dotup/tests/integration_tests.rs deleted file mode 100644 index d6bed8d..0000000 --- a/dotup/tests/integration_tests.rs +++ /dev/null @@ -1,126 +0,0 @@ -use std::path::{Path, PathBuf}; - -use dotup::{ArchiveLink, Depot, DepotConfig, LinkCreateParams}; -use tempfile::TempDir; - -const TESTING_DEPOT_NAME: &str = "depot.toml"; -const TESTING_DEPOT_CONTENTS: &str = include_str!("testing_depot.toml"); - -fn create_empty_file(path: impl AsRef) { - let path = path.as_ref(); - if let Some(parent) = path.parent() { - std::fs::create_dir_all(parent).unwrap(); - } - std::fs::write(path, "").unwrap(); -} - -fn prepare_empty_temp_dir() -> TempDir { - TempDir::new().unwrap() -} - -fn prepare_temp_dir() -> TempDir { - let dir = TempDir::new().unwrap(); - std::fs::write(dir.path().join(TESTING_DEPOT_NAME), TESTING_DEPOT_CONTENTS).unwrap(); - create_empty_file(dir.path().join("o1/file1.txt")); - create_empty_file(dir.path().join("o2/file2.txt")); - dir -} - -fn read_depot(dir: &TempDir) -> Depot { - let archive_path = dir.path().join(TESTING_DEPOT_NAME); - Depot::new(DepotConfig { - archive: dotup::archive_read(&archive_path).unwrap(), - archive_path, - }) - .unwrap() -} - -#[test] -fn test_archive_deserialize() { - let archive = dotup::archive_deserialize(&TESTING_DEPOT_CONTENTS).unwrap(); - - let link1 = ArchiveLink { - origin: PathBuf::from("o1/file1.txt"), - destination: PathBuf::from("d1/file.txt"), - }; - let link2 = ArchiveLink { - origin: PathBuf::from("o2/file2.txt"), - destination: PathBuf::from("d2/d2/file.txt"), - }; - - assert_eq!(2, archive.links.len()); - assert!(archive.links.contains(&link1)); - assert!(archive.links.contains(&link2)); -} - -#[test] -fn test_archive_exists() { - let empty_dir = prepare_empty_temp_dir(); - let dir = prepare_temp_dir(); - - assert!(!dotup::archive_exists( - empty_dir.path().join(TESTING_DEPOT_NAME) - )); - assert!(dotup::archive_exists(dir.path().join(TESTING_DEPOT_NAME))); -} - -#[test] -fn test_depot_create() { - let empty_dir = prepare_empty_temp_dir(); - let dir = prepare_temp_dir(); - - let d1 = Depot::new(DepotConfig { - archive: Default::default(), - archive_path: empty_dir.path().join(TESTING_DEPOT_NAME), - }); - assert!(d1.is_err()); - - let archive_path = dir.path().join(TESTING_DEPOT_NAME); - let d2 = Depot::new(DepotConfig { - archive: dotup::archive_read(&archive_path).unwrap(), - archive_path, - }); - assert!(d2.is_ok()); -} - -#[test] -fn test_depot_create_link() { - let dir = prepare_temp_dir(); - let mut depot = read_depot(&dir); - - create_empty_file(dir.path().join("o3/file.txt")); - - let l1 = depot.create_link(LinkCreateParams { - origin: PathBuf::from("o3/file.txt"), - destination: PathBuf::from(".config/file.txt"), - }); - assert!(l1.is_ok()); - - let l2 = depot.create_link(LinkCreateParams { - origin: PathBuf::from("o4/file.txt"), - destination: PathBuf::from(".config/file.txt"), - }); - assert!(l2.is_err()); -} - -#[test] -fn test_depot_install_uninstall_link() { - let dir = prepare_temp_dir(); - let depot = read_depot(&dir); - let install_base = dir.path(); - - for link in depot.links() { - depot.install_link(link, install_base).unwrap(); - } - - for link in depot.links() { - let link_path = link.install_destination(install_base); - let link_target = std::fs::read_link(&link_path).unwrap(); - assert_eq!(link_target.canonicalize().unwrap(), link.origin_canonical()); - } - - for link in depot.links() { - depot.uninstall_link(link, install_base).unwrap(); - assert!(!link.install_destination(install_base).exists()); - } -} diff --git a/dotup/tests/testing_depot.toml b/dotup/tests/testing_depot.toml deleted file mode 100644 index ee5224a..0000000 --- a/dotup/tests/testing_depot.toml +++ /dev/null @@ -1,7 +0,0 @@ -[[links]] -origin = "o1/file1.txt" -destination = "d1/file.txt" - -[[links]] -origin = "o2/file2.txt" -destination = "d2/d2/file.txt" diff --git a/dotup_cli/Cargo.toml b/dotup_cli/Cargo.toml deleted file mode 100644 index 89b8c27..0000000 --- a/dotup_cli/Cargo.toml +++ /dev/null @@ -1,29 +0,0 @@ -[package] -edition = "2018" -name = "dotup_cli" -version = "0.1.0" - -[[bin]] -name = "dotup" -path = "src/main.rs" -doc = false - -[dependencies] -anyhow = "1.0" -log = "0.4" -ansi_term = "0.12.1" - -[dependencies.clap] -features = ["derive"] -version = "3.0.0-rc.7" - -[dependencies.dotup] -path = "../dotup" - -[dependencies.flexi_logger] -features = ["colors"] -version = "0.22" - -[dev-dependencies] -tempfile = "3.2" -assert_cmd = "2.0" diff --git a/dotup_cli/src/commands/init.rs b/dotup_cli/src/commands/init.rs deleted file mode 100644 index 45129bf..0000000 --- a/dotup_cli/src/commands/init.rs +++ /dev/null @@ -1,22 +0,0 @@ -use super::prelude::*; - -/// Creates an empty depot file if one doesnt already exist. -/// -/// By default this will create the file in the current directory -/// but the --depot flag can be used to change this path. -#[derive(Parser)] -pub struct Opts {} - -pub fn main(config: Config, opts: Opts) -> anyhow::Result<()> { - if !dotup::utils::is_file(&config.archive_path)? { - let archive = Archive::default(); - log::info!("Creating archive at {}", &config.archive_path.display()); - utils::write_archive(&config.archive_path, &archive)?; - } else { - log::warn!( - "Archive file already exists : '{}'", - config.archive_path.display() - ); - } - Ok(()) -} diff --git a/dotup_cli/src/commands/install.rs b/dotup_cli/src/commands/install.rs deleted file mode 100644 index 6d9fbf7..0000000 --- a/dotup_cli/src/commands/install.rs +++ /dev/null @@ -1,25 +0,0 @@ -use std::path::PathBuf; - -use super::prelude::*; - -/// Install links. (Creates symlinks). -/// -/// Installing a link will create the necessary directories. -/// If a file or directory already exists at the location a link would be installed this command will fail. -#[derive(Parser)] -pub struct Opts { - /// The files/directories to install. - #[clap(min_values = 1, default_value = ".")] - paths: Vec, -} - -pub fn main(config: Config, opts: Opts) -> anyhow::Result<()> { - let depot = utils::read_depot(&config.archive_path)?; - - for link in utils::collect_links_by_base_paths(&depot, &opts.paths) { - log::info!("Installing link {}", link); - depot.install_link(link, &config.install_path)?; - } - - Ok(()) -} diff --git a/dotup_cli/src/commands/link.rs b/dotup_cli/src/commands/link.rs deleted file mode 100644 index d1f61ea..0000000 --- a/dotup_cli/src/commands/link.rs +++ /dev/null @@ -1,134 +0,0 @@ -use std::{ - fs::{DirEntry, Metadata}, - path::{Path, PathBuf}, -}; - -use super::prelude::*; - -/// Creates links -/// -/// If a link is created for a file that already had a link then the old link will be overwritten. -/// By default creating a link to a directory will recursively link all files under that -/// directory, to actually link a directory use the --directory flag. -#[derive(Parser)] -pub struct Opts { - /// Treats the paths as directories. This will create links to the actual directories instead - /// of recursively linking all files under them. - #[clap(long)] - directory: bool, - - /// The paths to link. The last path is the destination. - paths: Vec, -} - -// TODO: require destination -// remove else branch -pub fn main(config: Config, opts: Opts) -> anyhow::Result<()> { - let mut depot = utils::read_depot(&config.archive_path)?; - - let (origins, destination) = match opts.paths.as_slice() { - p @ [] | p @ [_] => (p, None), - [o @ .., dest] => (o, Some(dest)), - _ => unreachable!(), - }; - - if let Some(destination) = destination { - let params = if opts.directory { - origins - .iter() - .map(|p| LinkCreateParams { - origin: p.to_path_buf(), - destination: destination.clone(), - }) - .collect() - } else { - let mut params = Vec::new(); - for origin in origins { - generate_link_params(&depot, origin, destination, origin, &mut params)?; - } - params - }; - - for link_params in params { - log::info!("Creating link : {}", link_params); - depot.create_link(link_params)?; - } - } else { - let base_path = match origins { - [] => std::env::current_dir()?, - [path] => path.clone(), - _ => unreachable!(), - }; - - for link in utils::collect_links_by_base_paths(&depot, std::iter::once(base_path)) { - log::info!("{}", link); - } - } - - utils::write_depot(&depot)?; - - Ok(()) -} - -fn generate_link_params( - depot: &Depot, - origin: &Path, - destination: &Path, - base: &Path, - params: &mut Vec, -) -> anyhow::Result<()> { - let metadata = std::fs::metadata(origin)?; - if metadata.is_file() { - generate_file_link_params(depot, origin, destination, base, params)?; - } else if metadata.is_dir() { - generate_directory_link_params_recursive(depot, origin, destination, base, params)?; - } - Ok(()) -} - -fn generate_file_link_params( - depot: &Depot, - origin: &Path, - destination: &Path, - base: &Path, - params: &mut Vec, -) -> anyhow::Result<()> { - let origin_canonical = origin - .canonicalize() - .expect("Failed to canonicalize origin path"); - let base_canonical = base - .canonicalize() - .expect("Failed to canonicalize base path"); - - log::debug!("Origin canonical : {}", origin_canonical.display()); - log::debug!("Base : {}", base.display()); - - let partial = origin_canonical - .strip_prefix(base_canonical) - .expect("Failed to remove prefix from origin path"); - let destination = destination.join(partial); - let origin = origin_canonical - .strip_prefix(depot.base_path()) - .unwrap_or(&origin_canonical); - - let link_params = LinkCreateParams { - origin: origin.to_path_buf(), - destination, - }; - params.push(link_params); - Ok(()) -} - -fn generate_directory_link_params_recursive( - depot: &Depot, - dir_path: &Path, - destination: &Path, - base: &Path, - params: &mut Vec, -) -> anyhow::Result<()> { - for origin in dir_path.read_dir()? { - let origin = origin?.path(); - generate_link_params(depot, &origin, destination, base, params)?; - } - Ok(()) -} diff --git a/dotup_cli/src/commands/mod.rs b/dotup_cli/src/commands/mod.rs deleted file mode 100644 index bd92599..0000000 --- a/dotup_cli/src/commands/mod.rs +++ /dev/null @@ -1,11 +0,0 @@ -pub mod init; -pub mod install; -pub mod link; -pub mod mv; -pub mod status; -pub mod uninstall; -pub mod unlink; - -mod prelude { - pub use crate::prelude::*; -} diff --git a/dotup_cli/src/commands/mv.rs b/dotup_cli/src/commands/mv.rs deleted file mode 100644 index aae2715..0000000 --- a/dotup_cli/src/commands/mv.rs +++ /dev/null @@ -1,53 +0,0 @@ -use std::path::{Path, PathBuf}; - -use super::prelude::*; - -/// Install links. (Creates symlinks). -/// -/// Installing a link will create the necessary directories. -/// If a file or directory already exists at the location a link would be installed this command will fail. -#[derive(Parser)] -pub struct Opts { - /// The files/directories to move - #[clap(min_values = 2)] - paths: Vec, -} - -pub fn main(config: Config, opts: Opts) -> anyhow::Result<()> { - let mut depot = utils::read_depot(&config.archive_path)?; - - let (sources, destination) = match opts.paths.as_slice() { - [source, destination] => {} - [sources @ .., destination] => { - let mut curr_destination = destination.to_owned(); - for source in sources { - let filename = match source.file_name() { - Some(filename) => filename, - None => { - log::warn!("Ignoring '{}', unknown file name", source.display()); - continue; - } - }; - curr_destination.push(filename); - std::fs::rename(source, &curr_destination)?; - if let Some(id) = depot.get_link_id_by_path(&source) { - depot.rename_link(id, &curr_destination); - } - curr_destination.pop(); - } - } - _ => unreachable!(), - }; - - utils::write_depot(&depot)?; - - Ok(()) -} - -fn rename(depot: &mut Depot, source: &Path, destination: &Path) -> anyhow::Result<()> { - std::fs::rename(source, &destination)?; - if let Some(id) = depot.get_link_id_by_path(&source) { - depot.rename_link(id, &destination); - } - Ok(()) -} diff --git a/dotup_cli/src/commands/status.rs b/dotup_cli/src/commands/status.rs deleted file mode 100644 index b7221db..0000000 --- a/dotup_cli/src/commands/status.rs +++ /dev/null @@ -1,175 +0,0 @@ -use std::path::{Path, PathBuf}; - -use ansi_term::Colour; -use clap::Parser; -use dotup::{Depot, Link}; - -use crate::{utils, Config}; - -/// Shows information about links -/// -/// If a link is created for a file that already had a link then the old link will be overwritten. -/// By default creating a link to a directory will recursively link all files under that -/// directory, to actually link a directory use the --directory flag. -#[derive(Parser)] -pub struct Opts { - /// The location where links will be installed to. - /// Defaults to the home directory. - #[clap(long)] - install_base: Option, - - /// The paths to show the status of - paths: Vec, -} - -#[derive(Debug)] -struct State { - max_depth: u32, - install_path: PathBuf, -} - -pub fn main(config: Config, opts: Opts) -> anyhow::Result<()> { - let mut depot = utils::read_depot(&config.archive_path)?; - - // walk dir - // if node is file: - // if linked - // print name in green and destination blue - // if invalid - // print name and destination red - // if not linked - // print name in gray - // if node is directory: - // if linked - // print name in green and destination blue - // if invalid - // print name and destination red - // if not linked: - // print name in gray - // if contains files that are linked/invalid: - // recurse into directory - // - - let depot_base = depot.base_path(); - let mut paths = Vec::new(); - for path in opts.paths { - let canonical = dotup::utils::weakly_canonical(&path); - if canonical.starts_with(depot_base) { - paths.push(canonical); - } else { - log::warn!("Path '{}' is outside the depot", path.display()); - } - } - - if paths.is_empty() { - paths.push(PathBuf::from(".")); - } - - let state = State { - max_depth: u32::MAX, - install_path: config.install_path, - }; - - let (directories, files) = utils::collect_read_dir_split(".")?; - for path in directories.into_iter().chain(files.into_iter()) { - display_status_path(&depot, &state, &path, 0); - } - - utils::write_depot(&depot)?; - - Ok(()) -} - -fn display_status_path(depot: &Depot, state: &State, path: &Path, depth: u32) { - if depth == state.max_depth { - return; - } - - if path.is_dir() { - display_status_directory(depot, state, path, depth); - } else { - display_status_file(depot, state, path, depth); - } -} - -fn display_status_directory(depot: &Depot, state: &State, path: &Path, depth: u32) { - assert!(path.is_dir()); - if depth == state.max_depth || !depot.subpath_has_links(path) { - return; - } - - if let Some(link) = depot.get_link_by_path(path) { - print_link(depot, state, link, depth); - } else { - for entry in std::fs::read_dir(path).unwrap() { - let entry = match entry { - Ok(entry) => entry, - Err(_) => continue, - }; - let entry_path = entry.path().canonicalize().unwrap(); - let entry_path_stripped = entry_path - .strip_prefix(std::env::current_dir().unwrap()) - .unwrap(); - - print_identation(depth); - println!( - "{}", - Colour::Yellow.paint(&format!("{}", path.file_name().unwrap().to_string_lossy())) - ); - - display_status_path(depot, state, &entry_path_stripped, depth + 1); - } - } -} - -fn display_status_file(depot: &Depot, state: &State, path: &Path, depth: u32) { - print_identation(depth); - if let Some(link) = depot.get_link_by_path(path) { - print_link(depot, state, link, depth); - } else { - print_unlinked(path, depth); - } -} - -fn print_link(depot: &Depot, state: &State, link: &Link, depth: u32) { - let origin = link.origin(); - let dest = link.destination(); - let filename = match origin.file_name() { - Some(filename) => filename, - None => return, - }; - - print_identation(depth); - if depot.is_link_installed(link, &state.install_path) { - println!( - "{} -> {}", - Colour::Green.paint(&format!("{}", filename.to_string_lossy())), - Colour::Blue.paint(&format!("{}", dest.display())), - ); - } else { - println!( - "{}", - Colour::Red.paint(&format!( - "{} -> {}", - filename.to_string_lossy(), - dest.display() - )) - ); - } -} - -fn print_unlinked(path: &Path, depth: u32) { - let filename = match path.file_name() { - Some(filename) => filename, - None => return, - }; - - print_identation(depth); - println!("{}", filename.to_string_lossy()); -} - -fn print_identation(depth: u32) { - for i in 0..depth { - print!(" "); - } -} diff --git a/dotup_cli/src/commands/uninstall.rs b/dotup_cli/src/commands/uninstall.rs deleted file mode 100644 index fe44bf0..0000000 --- a/dotup_cli/src/commands/uninstall.rs +++ /dev/null @@ -1,26 +0,0 @@ -use std::path::PathBuf; - -use super::prelude::*; - -/// Uninstalls links. (Removes symlinks). -/// -/// Uninstalling a link for a file that didnt have a link will do nothing. -/// Uninstalling a directory will recursively uninstall all files under it. -/// Symlinks are only deleted if they were pointing to the correct file. -#[derive(Parser)] -pub struct Opts { - /// The files/directories to uninstall. - #[clap(min_values = 1, default_value = ".")] - paths: Vec, -} - -pub fn main(config: Config, opts: Opts) -> anyhow::Result<()> { - let depot = utils::read_depot(&config.archive_path)?; - - for link in utils::collect_links_by_base_paths(&depot, &opts.paths) { - log::info!("Uninstalling link : {}", link); - depot.uninstall_link(link, &config.install_path)?; - } - - Ok(()) -} diff --git a/dotup_cli/src/commands/unlink.rs b/dotup_cli/src/commands/unlink.rs deleted file mode 100644 index abe23e3..0000000 --- a/dotup_cli/src/commands/unlink.rs +++ /dev/null @@ -1,43 +0,0 @@ -use std::{ - fs::{DirEntry, Metadata}, - path::{Path, PathBuf}, -}; - -use super::prelude::*; - -/// Unlinks files/directories. -/// -/// This will recursively remove links. If a path is a directory then it will remove all links -/// recursively. -/// The links are not uninstall by default, see the --uninstall parameter. -#[derive(Parser)] -pub struct Opts { - /// Specify the install base if the links are also to be uninstalled. - #[clap(long)] - uninstall: Option, - - /// The paths to unlink. - #[clap(required = true, min_values = 1)] - paths: Vec, -} - -pub fn main(config: Config, opts: Opts) -> anyhow::Result<()> { - let mut depot = utils::read_depot(&config.archive_path)?; - - for link_id in utils::collect_link_ids_by_base_paths(&depot, &opts.paths) { - let link = depot.get_link(link_id).unwrap(); - log::info!( - "Unlinking(uninstall = {}) : {}", - opts.uninstall.is_some(), - link - ); - if let Some(ref install_base) = opts.uninstall { - depot.uninstall_link(link, &install_base)?; - } - depot.remove_link(link_id); - } - - utils::write_depot(&depot)?; - - Ok(()) -} diff --git a/dotup_cli/src/config.rs b/dotup_cli/src/config.rs deleted file mode 100644 index dabaf74..0000000 --- a/dotup_cli/src/config.rs +++ /dev/null @@ -1,10 +0,0 @@ -use std::path::PathBuf; - -#[derive(Debug)] -pub struct Config { - pub archive_path: PathBuf, - pub install_path: PathBuf, - pub working_path: PathBuf, -} - -impl Config {} diff --git a/dotup_cli/src/main.rs b/dotup_cli/src/main.rs deleted file mode 100644 index 0d730da..0000000 --- a/dotup_cli/src/main.rs +++ /dev/null @@ -1,111 +0,0 @@ -#![allow(unused)] - -pub mod commands; -pub mod config; -pub mod utils; - -pub use config::Config; - -pub mod prelude { - pub use super::{utils, Config}; - pub use clap::{AppSettings, Parser}; - pub use dotup::{Archive, Depot, DepotConfig, Link, LinkCreateParams, LinkID}; -} - -use clap::{AppSettings, Parser}; -use flexi_logger::Logger; -use std::{ - collections::HashMap, - iter::FromIterator, - path::{Path, PathBuf}, -}; - -use prelude::*; - -#[derive(Parser)] -struct Opts { - /// Path to the depot file. - /// - /// By default it will try to find a file named "depot.toml" in the current directory or any of - /// the parent directories. - #[clap(long)] - depot: Option, - - /// Disable output to the console - #[clap(short, long)] - quiet: bool, - - /// A level of verbosity, and can be used multiple times - /// - /// Level 1 - Info - /// - /// Level 2 - Debug - /// - /// Level 3 - Trace - #[clap(short, long, parse(from_occurrences))] - verbose: i32, - - /// The location where links will be installed to. - /// Defaults to the home directory. - #[clap(short, long)] - install_path: Option, - - #[clap(subcommand)] - subcmd: SubCommand, -} - -#[derive(Parser)] -enum SubCommand { - Init(commands::init::Opts), - Link(commands::link::Opts), - Mv(commands::mv::Opts), - Status(commands::status::Opts), - Unlink(commands::unlink::Opts), - Install(commands::install::Opts), - Uninstall(commands::uninstall::Opts), -} - -fn main() -> anyhow::Result<()> { - let opts = Opts::parse(); - - if !opts.quiet { - let log_level = match opts.verbose { - 0 => "warn", - 1 => "info", - 2 => "debug", - _ => "trace", - }; - - Logger::try_with_env_or_str(log_level)? - .format(flexi_logger::colored_default_format) - .set_palette("196;208;32;198;15".to_string()) - .start()?; - } - - let archive_path = match opts.depot { - Some(path) => path, - None => utils::find_archive_path()?, - }; - let install_path = match opts.install_path { - Some(path) => path, - None => utils::home_directory()?, - }; - let working_path = std::env::current_dir().expect("Failed to obtain current working directory"); - log::debug!("Archive path : {}", archive_path.display()); - - let config = Config { - archive_path, - install_path, - working_path, - }; - - match opts.subcmd { - SubCommand::Init(opts) => commands::init::main(config, opts), - SubCommand::Link(opts) => commands::link::main(config, opts), - SubCommand::Mv(opts) => commands::mv::main(config, opts), - SubCommand::Status(opts) => commands::status::main(config, opts), - SubCommand::Unlink(opts) => commands::unlink::main(config, opts), - SubCommand::Install(opts) => commands::install::main(config, opts), - SubCommand::Uninstall(opts) => commands::uninstall::main(config, opts), - } -} diff --git a/dotup_cli/src/utils.rs b/dotup_cli/src/utils.rs deleted file mode 100644 index b9a76a7..0000000 --- a/dotup_cli/src/utils.rs +++ /dev/null @@ -1,182 +0,0 @@ -use std::{ - collections::VecDeque, - path::{Path, PathBuf}, -}; - -use crate::prelude::*; - -const DEFAULT_DEPOT_NAME: &str = "depot.toml"; - -pub fn home_directory() -> anyhow::Result { - match std::env::var("HOME") { - Ok(val) => Ok(PathBuf::from(val)), - Err(e) => { - log::error!("Failed to get home directory from enviornment variable"); - Err(e.into()) - } - } -} - -pub fn find_archive_path() -> anyhow::Result { - let cwd = std::env::current_dir()?; - let compn = cwd.components().count(); - let mut start = PathBuf::new(); - for _ in 0..=compn { - start.push(DEFAULT_DEPOT_NAME); - if dotup::archive_exists(&start) { - return Ok(start); - } - start.pop(); - start.push(".."); - } - Ok(PathBuf::from(DEFAULT_DEPOT_NAME)) -} - -pub fn write_archive(path: impl AsRef, archive: &Archive) -> anyhow::Result<()> { - let path = path.as_ref(); - log::debug!("Writing archive to {}", path.display()); - match dotup::archive_write(path, archive) { - Ok(_) => Ok(()), - Err(e) => { - log::error!( - "Failed to write archive to : {}\nError : {}", - path.display(), - e - ); - Err(e.into()) - } - } -} - -pub fn write_depot(depot: &Depot) -> anyhow::Result<()> { - let write_path = depot.archive_path(); - let archive = depot.archive(); - match dotup::archive_write(write_path, &archive) { - Ok(_) => Ok(()), - Err(e) => { - log::error!( - "Failed to write depot archive to : {}\nError : {}", - write_path.display(), - e - ); - Err(e.into()) - } - } -} - -pub fn read_archive(path: impl AsRef) -> anyhow::Result { - let path = path.as_ref(); - match dotup::archive_read(path) { - Ok(archive) => Ok(archive), - Err(e) => { - log::error!( - "Failed to read archive from : {}\nError : {}", - path.display(), - e - ); - Err(e.into()) - } - } -} - -pub fn read_depot(archive_path: impl AsRef) -> anyhow::Result { - let archive_path = archive_path.as_ref().to_path_buf(); - let archive = read_archive(&archive_path)?; - let depot_config = DepotConfig { - archive: Default::default(), - archive_path, - }; - let mut depot = Depot::new(depot_config)?; - - for archive_link in archive.links { - let link_params = LinkCreateParams::from(archive_link); - if let Err(e) = depot.create_link(link_params) { - log::warn!("Error while adding link : {}", e); - } - } - - Ok(depot) -} - -pub fn collect_links_by_base_paths( - depot: &Depot, - paths: impl IntoIterator>, -) -> Vec<&Link> { - let canonical_paths: Vec<_> = paths - .into_iter() - .map(|p| p.as_ref().canonicalize().unwrap()) - .collect(); - - depot - .links() - .filter(|&l| { - canonical_paths - .iter() - .any(|p| l.origin_canonical().starts_with(p)) - }) - .collect() -} - -pub fn collect_link_ids_by_base_paths( - depot: &Depot, - paths: impl IntoIterator>, -) -> Vec { - collect_links_by_base_paths(depot, paths) - .into_iter() - .map(|l| l.id()) - .collect() -} - -/// Returns a list of canonical paths to all the files in `dir`. This includes files in -/// subdirectories. -/// Fails if dir isnt a directory or if there is some other io error. -pub fn collect_files_in_dir(dir: impl Into) -> anyhow::Result> { - let mut paths = Vec::new(); - let mut dirs = VecDeque::new(); - dirs.push_back(dir.into()); - - while let Some(dir) = dirs.pop_front() { - for entry in std::fs::read_dir(dir)? { - let entry = entry?; - let filetype = entry.file_type()?; - if filetype.is_dir() { - dirs.push_back(entry.path()); - } else { - paths.push(entry.path()); - } - } - } - - Ok(paths) -} - -/// Collects the result of std::fs::read_dir into two vecs -/// The first one contains all the directories and the second one all the files -pub fn collect_read_dir_split( - dir: impl AsRef, -) -> anyhow::Result<(Vec, Vec)> { - Ok(std::fs::read_dir(dir)? - .filter_map(|e| e.ok()) - .map(|e| e.path()) - .partition(|p| p.is_dir())) -} - -/// Checks if `path` is inside a git repository -pub fn path_is_in_git_repo(path: &Path) -> bool { - let mut path = if !path.is_absolute() { - dbg!(dotup::utils::weakly_canonical(path)) - } else { - path.to_owned() - }; - let recurse = path.pop(); - path.push(".git"); - if path.is_dir() { - return true; - } - if recurse { - path.pop(); - return path_is_in_git_repo(&path); - } else { - return false; - } -} diff --git a/dotup_cli/tests/cli.rs b/dotup_cli/tests/cli.rs deleted file mode 100644 index c836f63..0000000 --- a/dotup_cli/tests/cli.rs +++ /dev/null @@ -1,145 +0,0 @@ -use assert_cmd::{assert::Assert, prelude::*}; -use dotup::ArchiveLink; -use std::{ - path::{Path, PathBuf}, - process::Command, -}; -use tempfile::TempDir; - -const DEPOT_FILE_NAME: &str = "depot.toml"; -const BIN_NAME: &str = "dotup"; - -fn create_empty_file(path: impl AsRef) { - let path = path.as_ref(); - if let Some(parent) = path.parent() { - std::fs::create_dir_all(parent).unwrap(); - } - std::fs::write(path, "").unwrap(); -} - -fn prepare_command(dir: &TempDir) -> Command { - let mut cmd = Command::cargo_bin(BIN_NAME).unwrap(); - cmd.current_dir(dir.path()); - cmd -} - -fn run_command(dir: &TempDir, cmd: &str) -> Assert { - let mut c = prepare_command(dir); - c.current_dir(dir.path()); - c.args(cmd.split_whitespace()); - c.assert() -} - -fn prepare_dir() -> TempDir { - let dir = TempDir::new().unwrap(); - create_empty_file(dir.path().join("o1/file.txt")); - create_empty_file(dir.path().join("o1/dir/file.txt")); - create_empty_file(dir.path().join("o2/file1.txt")); - create_empty_file(dir.path().join("o2/file2.txt")); - dir -} - -#[test] -fn test_cli_init() { - let dir = prepare_dir(); - let assert = run_command(&dir, "init"); - - assert.success().code(0); - assert!(dir.path().join(DEPOT_FILE_NAME).is_file()); -} - -#[test] -fn test_cli_link() { - let dir = prepare_dir(); - run_command(&dir, "init").success(); - - let assert = run_command(&dir, "link o1 .config"); - assert.success().code(0); - - let assert = run_command(&dir, "link --directory o2 .scripts"); - assert.success().code(0); - - let archive = dotup::archive_read(dir.path().join(DEPOT_FILE_NAME)).unwrap(); - let link1 = ArchiveLink { - origin: PathBuf::from("o1/file.txt"), - destination: PathBuf::from(".config/file.txt"), - }; - let link2 = ArchiveLink { - origin: PathBuf::from("o1/dir/file.txt"), - destination: PathBuf::from(".config/dir/file.txt"), - }; - let link3 = ArchiveLink { - origin: PathBuf::from("o2"), - destination: PathBuf::from(".scripts"), - }; - - assert!(archive.links.contains(&link1)); - assert!(archive.links.contains(&link2)); - assert!(archive.links.contains(&link3)); -} - -#[test] -fn test_cli_install_uninstall_unlink() { - let dir = prepare_dir(); - run_command(&dir, "init").success(); - run_command(&dir, "link o1 .config").success(); - run_command(&dir, "link --directory o2 .scripts").success(); - - let install_dir = TempDir::new().unwrap(); - let install_base = format!("{}", install_dir.path().display()); - run_command( - &dir, - &format!("--install-path {} install o1 o2", install_base), - ) - .success(); - - assert_eq!( - std::fs::read_link(install_dir.path().join(".config/file.txt")).unwrap(), - dir.path().join("o1/file.txt") - ); - assert_eq!( - std::fs::read_link(install_dir.path().join(".config/dir/file.txt")).unwrap(), - dir.path().join("o1/dir/file.txt") - ); - assert_eq!( - std::fs::read_link(install_dir.path().join(".scripts")).unwrap(), - dir.path().join("o2") - ); - - run_command( - &dir, - &format!("--install-path {} uninstall o1/file.txt", install_base), - ) - .success(); - assert!(!install_dir.path().join(".config/file.txt").exists()); - assert!(install_dir.path().join(".config/dir/file.txt").exists()); - assert!(install_dir.path().join(".scripts").exists()); - - run_command( - &dir, - &format!("--install-path {} uninstall o1", install_base), - ) - .success(); - assert!(!install_dir.path().join(".config/file.txt").exists()); - assert!(!install_dir.path().join(".config/dir/file.txt").exists()); - assert!(install_dir.path().join(".scripts").exists()); - - assert_eq!( - 3, - dotup::archive_read(dir.path().join(DEPOT_FILE_NAME)) - .unwrap() - .links - .len() - ); - - run_command(&dir, &format!("unlink --uninstall {} o2", install_base)).success(); - assert!(!install_dir.path().join(".scripts").exists()); - - assert_eq!( - 2, - dotup::archive_read(dir.path().join(DEPOT_FILE_NAME)) - .unwrap() - .links - .len() - ); -} -- cgit