diff --git a/website/scripts/docsmg/.gitignore b/website/scripts/docsmg/.gitignore new file mode 100644 index 0000000000..ea8c4bf7f3 --- /dev/null +++ b/website/scripts/docsmg/.gitignore @@ -0,0 +1 @@ +/target diff --git a/website/scripts/docsmg/Cargo.lock b/website/scripts/docsmg/Cargo.lock new file mode 100644 index 0000000000..bd765853d5 --- /dev/null +++ b/website/scripts/docsmg/Cargo.lock @@ -0,0 +1,468 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstream" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" + +[[package]] +name = "anstyle-parse" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + +[[package]] +name = "anyhow" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" + +[[package]] +name = "backtrace" +version = "0.3.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "cc" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaff6f8ce506b9773fa786672d63fc7a191ffea1be33f72bbd4aeacefca9ffc8" + +[[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.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64acc1846d54c1fe936a78dc189c34e28d3f5afc348403f28ecf53660b9b8462" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fb8393d67ba2e7bfaf28a23458e4e2b543cc73a99595511eb207fdb8aede942" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" + +[[package]] +name = "colorchoice" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" + +[[package]] +name = "colored" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" +dependencies = [ + "lazy_static", + "windows-sys 0.48.0", +] + +[[package]] +name = "docsmg" +version = "0.1.0" +dependencies = [ + "anyhow", + "clap", + "colored", + "lazy_static", + "regex", + "tokio", +] + +[[package]] +name = "gimli" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "miniz_oxide" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +dependencies = [ + "adler", +] + +[[package]] +name = "object" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce" +dependencies = [ + "memchr", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "2.0.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0209b68b3613b093e0ec905354eccaedcfe83b8cb37cbdeae64026c3064c16" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tokio" +version = "1.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +dependencies = [ + "backtrace", + "pin-project-lite", +] + +[[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.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff --git a/website/scripts/docsmg/Cargo.toml b/website/scripts/docsmg/Cargo.toml new file mode 100644 index 0000000000..a011ed4b36 --- /dev/null +++ b/website/scripts/docsmg/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "docsmg" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow = "1.0.86" +clap = { version = "4.5.9", features = ["derive", "env"] } +colored = "2.1.0" +lazy_static = "1.5.0" +regex = "1.10.5" +tokio = "1.38.0" diff --git a/website/scripts/docsmg/m.bash b/website/scripts/docsmg/m.bash new file mode 100755 index 0000000000..0c4d022630 --- /dev/null +++ b/website/scripts/docsmg/m.bash @@ -0,0 +1,2 @@ +#!/bin/bash +docsmg move $1 $2 | tee -a migratefile diff --git a/website/scripts/docsmg/mcomplete.bash b/website/scripts/docsmg/mcomplete.bash new file mode 100755 index 0000000000..5cb932430e --- /dev/null +++ b/website/scripts/docsmg/mcomplete.bash @@ -0,0 +1,23 @@ +#!/bin/bash + +_completions () { + if [[ -z "${MIGRATE_PATH}" ]]; + then MIGRATE_PATH="./"; + else MIGRATE_PATH="${MIGRATE_PATH}"; fi + + if [[ -z "${TMP_STRUCTURE_PATH}" ]]; + then TMP_STRUCTURE_PATH="./tmp/"; + else TMP_STRUCTURE_PATH="${TMP_STRUCTURE_PATH}"; fi + + if [[ $1 = $3 ]]; + then LSPATH="$MIGRATE_PATH"; + else LSPATH="$TMP_STRUCTURE_PATH"; fi + + for i in $(compgen -f -- "$LSPATH$2" | cut -d "/" -f 2-); do + if [[ -d "$LSPATH$i" ]]; + then COMPREPLY+=("$i/"); + else COMPREPLY+=("$i"); fi + done +} + +complete -o nospace -o filenames -F _completions m.bash diff --git a/website/scripts/docsmg/src/generate.rs b/website/scripts/docsmg/src/generate.rs new file mode 100644 index 0000000000..86a11b9f0b --- /dev/null +++ b/website/scripts/docsmg/src/generate.rs @@ -0,0 +1,31 @@ +use std::path::PathBuf; + +use crate::{migratefile::read_migrate_file, recurse_directory}; + +pub fn generate(migratefile: Option, migrate_path: PathBuf) { + // if there is a migrate file, read it and get the paths from the left side + let paths: Vec = match migratefile { + Some(i) => { + let contents = read_migrate_file(i); + if let Ok(contents) = contents { + contents.iter().map(|x| x.0.clone()).collect() + } else { + vec![] + } + } + None => { + vec![] + } + }; + // get rid of paths already in the specified migrate file + let paths: Vec = recurse_directory(migrate_path.clone()) + .iter() + .filter(|x| !paths.contains(x)) + .filter_map(|x| x.strip_prefix(migrate_path.clone()).ok()) + .map(|x| x.to_path_buf()) + .collect(); + + for path in paths { + println!("{} -> ", path.display()); + } +} diff --git a/website/scripts/docsmg/src/main.rs b/website/scripts/docsmg/src/main.rs new file mode 100644 index 0000000000..115a2503c4 --- /dev/null +++ b/website/scripts/docsmg/src/main.rs @@ -0,0 +1,83 @@ +use std::{fs, path::PathBuf}; + +use clap::{Parser, Subcommand}; + +mod generate; +mod migrate; +mod migratefile; +mod r#move; + +#[derive(Parser)] +struct Cli { + #[arg(long, env, default_value = "./")] + migrate_path: PathBuf, + + #[command(subcommand)] + command: Commands, +} + +#[derive(Subcommand)] +enum Commands { + Move { + old_path: PathBuf, + new_path: PathBuf, + }, + Migrate { + #[arg(long, name = "FILE", default_value = "./migratefile")] + migratefile: PathBuf, + + #[arg(short, long)] + quiet: bool, + }, + Unmigrate { + #[arg(long, name = "FILE", default_value = "./migratefile")] + migratefile: PathBuf, + + #[arg(short, long)] + quiet: bool, + }, + Generate { + #[arg(long, name = "FILE")] + migratefile: Option, + }, +} + +fn main() { + let cli = Cli::parse(); + + match cli.command { + Commands::Move { old_path, new_path } => r#move::r#move(old_path, new_path), + Commands::Migrate { migratefile, quiet } => { + migrate::migrate(quiet, migratefile, cli.migrate_path) + } + Commands::Unmigrate { migratefile, quiet } => { + migrate::unmigrate(quiet, migratefile, cli.migrate_path) + } + Commands::Generate { migratefile } => generate::generate(migratefile, cli.migrate_path), + } +} + +fn recurse_directory(path: PathBuf) -> Vec { + let paths = fs::read_dir(path).expect("path to exist"); + let mut final_paths = vec![]; + for path in paths { + match path { + Ok(path) => { + if !path.path().is_file() && !path.path().is_dir() { + continue; + } // dont go any further if not a file or directory + let is_dir = path.path().is_dir(); + let path = path.path(); + + if is_dir { + let mut paths = recurse_directory(path); + final_paths.append(&mut paths); + } else { + final_paths.push(path); + } + } + _ => {} + } + } + final_paths +} diff --git a/website/scripts/docsmg/src/migrate.rs b/website/scripts/docsmg/src/migrate.rs new file mode 100644 index 0000000000..44368abb54 --- /dev/null +++ b/website/scripts/docsmg/src/migrate.rs @@ -0,0 +1,212 @@ +use std::{ + collections::HashMap, ffi::OsStr, fmt::format, fs::{read_to_string, write}, path::{Component, Path, PathBuf} +}; + +use colored::Colorize; +use lazy_static::lazy_static; + +use crate::{migratefile::read_migrate_file, recurse_directory}; + +pub fn migrate(quiet: bool, migratefile: PathBuf, migrate_path: PathBuf) { + if !quiet { + println!("Reading migrate file"); + } + let files = read_migrate_file(migratefile); + + let files = match files { + Ok(i) => { + if !quiet { + println!("{}", "Success".green()); + } + i + } + Err(_) => { + println!("{}: Could not read migrate file", "Error".red()); + return; + } + }; + + replace_links(migrate_path.clone(), files.clone()); + let successful_moves = move_files(quiet, migrate_path.clone(), files); + add_redirects(successful_moves.clone(), migrate_path.clone()); +} + +pub fn unmigrate(quiet: bool, migratefile: PathBuf, migrate_path: PathBuf) { + if !quiet { + println!("Reading migrate file"); + } + let files = read_migrate_file(migratefile); + + let files = match files { + Ok(i) => { + if !quiet { + println!("{}", "Success".green()); + } + i + } + Err(_) => { + println!("{}: Could not read migrate file", "Error".red()); + return; + } + }; + + let files: Vec<(PathBuf, PathBuf)> = files.iter().map(|x| (x.1.clone(), x.0.clone())).collect(); //switch files to reverse a migration + replace_links(migrate_path.clone(), files.clone()); + let successful_moves = move_files(quiet, migrate_path.clone(), files); + let successful_moves: Vec<(PathBuf, PathBuf)> = successful_moves + .iter() + .map(|x| (x.1.clone(), x.0.clone())) + .collect(); //switch files to reverse a migration + remove_redirects(successful_moves, migrate_path); +} + +fn move_files( + quiet: bool, + migrate_path: PathBuf, + files: Vec<(PathBuf, PathBuf)>, +) -> Vec<(PathBuf, PathBuf)> { + let mut successful_moves = vec![]; + for file in files { + if !quiet { + print!("{} -> {} : ", file.0.display(), file.1.display()); + } + let rename: anyhow::Result<()> = (|| { + let old_file = migrate_path.join(&file.0); + let new_file = migrate_path.join(&file.1); + std::fs::create_dir_all(&new_file.parent().expect("files to have a parent"))?; + std::fs::rename(&old_file, &new_file)?; + Ok(()) + })(); + match rename { + Ok(_) => { + if !quiet { + println!("{}", "Success".green()); + } + successful_moves.push(file); + } + Err(_) => println!( + "{}: Could not move file {}", + "Error".red(), + file.0.display() + ), + }; + } + successful_moves +} + +fn replace_links(migrate_path: PathBuf, successful_moves: Vec<(PathBuf, PathBuf)>) { + lazy_static! { + static ref find_link: regex::Regex = + regex::Regex::new(r"\[(?.*)\]\((?.*)\)").unwrap(); + } + let files = recurse_directory(migrate_path.clone()); + + for file in files { + let relative_file = file.strip_prefix(migrate_path.clone()).unwrap().to_path_buf(); + let mut contents = match read_to_string(file.clone()) { + Ok(i) => i, + Err(_) => continue, + }; + let mut replace = vec![]; + for successful_move in &successful_moves { + if migrate_path.join(successful_move.0.clone()).canonicalize().unwrap() + == file.clone().canonicalize().unwrap() { + continue; + } + let new_successful_move_from = make_path_relative(successful_move.0.clone(), relative_file.clone()); + let new_successful_move_to = make_path_relative(successful_move.1.clone(), relative_file.clone()); + replace.push((new_successful_move_from, new_successful_move_to)); + } + for i in replace { + println!("{} : {} -> {}", file.display(), i.0.display(), i.1.display()); + contents = contents.replace(&format!("({})", i.0.display()), &format!("({})", i.1.display())); + } + write(file, contents).unwrap(); + } +} + +fn make_path_relative(path: PathBuf, relative_to: PathBuf) -> PathBuf { + let mut subdirs = 0; + let path_components = path.components().collect::>(); + let relative_to_components = relative_to.components().collect::>(); + loop { + if path_components.len() <= subdirs { + break; + } else if path_components[subdirs] + != relative_to_components[subdirs] + { + break; + } + subdirs += 1; + } + let new_path = &path_components[subdirs..] + .iter() + .collect::(); + let backouts = + (0..relative_to_components.len() - subdirs - 1) + .map(|_| PathBuf::from("..")) + .reduce(|acc, e| acc.join(e)) + .unwrap_or(PathBuf::from("")); + //println!("{}, {}", relative_to_components.len() - subdirs - 1, backouts.display()); + let new_path = backouts.join(new_path); + let new_path = if new_path + .to_string_lossy() + .to_string() + .chars() + .next() + .unwrap() + != '.' + { + PathBuf::from(".").join(new_path) + } else { + new_path + }; + + let new_path = if new_path.file_name() == Some(OsStr::new("index.md")) || new_path.file_name() == Some(OsStr::new("index.mdx")) { + new_path.parent().unwrap().to_path_buf() + } else { + new_path + }; + + + new_path +} + +fn add_redirects(successful_moves: Vec<(PathBuf, PathBuf)>, migrate_path: PathBuf) { + let redirects = generate_redirects(successful_moves); + let netlify_path = migrate_path.parent().unwrap().join("netlify.toml"); + let mut netlify_contents = read_to_string(netlify_path.clone()).unwrap(); + for redirect in redirects { + netlify_contents.push_str(&redirect); + } + std::fs::write(netlify_path, netlify_contents).unwrap(); +} + +fn remove_redirects(successful_moves: Vec<(PathBuf, PathBuf)>, migrate_path: PathBuf) { + let redirects = generate_redirects(successful_moves); + let netlify_path = migrate_path.parent().unwrap().join("netlify.toml"); + let mut netlify_contents = read_to_string(netlify_path.clone()).unwrap(); + for redirect in redirects { + netlify_contents = netlify_contents.replace(&redirect, ""); + } + std::fs::write(netlify_path, netlify_contents).unwrap(); +} + +fn generate_redirects(successful_moves: Vec<(PathBuf, PathBuf)>) -> Vec { + successful_moves + .iter() + .map(|x| { + format!( + " +[[redirects]] + from = \"{}\" + to = \"{}\" + status = 301 + force = true +", + x.0.display(), + x.1.display() + ) + }) + .collect() +} diff --git a/website/scripts/docsmg/src/migratefile.rs b/website/scripts/docsmg/src/migratefile.rs new file mode 100644 index 0000000000..c37a1131bf --- /dev/null +++ b/website/scripts/docsmg/src/migratefile.rs @@ -0,0 +1,21 @@ +use std::{fs::read_to_string, path::PathBuf}; + +pub fn read_migrate_file(file: PathBuf) -> anyhow::Result> { + let contents = read_to_string(file)?; + let lines: Vec = contents + .split('\n') + .map(|x| x.to_owned()) + .filter(|x| x != "") + .collect(); + let migrations = lines + .iter() + .filter_map(|x| x.split_once(" -> ")) + .map(|x| { + ( + x.0.parse().expect("a valid path"), + x.1.parse().expect("a valid path"), + ) + }) + .collect::>(); + Ok(migrations) +} diff --git a/website/scripts/docsmg/src/move.rs b/website/scripts/docsmg/src/move.rs new file mode 100644 index 0000000000..64f4e87185 --- /dev/null +++ b/website/scripts/docsmg/src/move.rs @@ -0,0 +1,23 @@ +use std::path::PathBuf; + +use crate::recurse_directory; + +pub fn r#move(old_path: PathBuf, new_path: PathBuf) { + let is_dir = old_path.is_dir(); + if is_dir { + let paths = recurse_directory(old_path.clone()); + for path in paths { + let raw_path = path + .strip_prefix(old_path.clone()) + .expect("path to be within old path"); + let new_path = new_path.join(raw_path); + println!("{} -> {}", path.display(), new_path.display()); + } + } else { + println!( + "{} -> {}", + old_path.to_string_lossy(), + new_path.to_string_lossy() + ); + } +}