diff options
author | metamuffin <metamuffin@disroot.org> | 2023-10-24 20:04:19 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2023-10-24 20:04:19 +0200 |
commit | 5ee01d06c0b067f2f07d0288c499897cd0df29f7 (patch) | |
tree | 91dd323219a2102770d40919d5e713b03f48b1e5 /tool | |
parent | d9b3b92e8ddd27aac39269a03a0eeb18e3a62a6a (diff) | |
download | jellything-5ee01d06c0b067f2f07d0288c499897cd0df29f7.tar jellything-5ee01d06c0b067f2f07d0288c499897cd0df29f7.tar.bz2 jellything-5ee01d06c0b067f2f07d0288c499897cd0df29f7.tar.zst |
migration tool
Diffstat (limited to 'tool')
-rw-r--r-- | tool/Cargo.toml | 2 | ||||
-rw-r--r-- | tool/src/import/mod.rs | 5 | ||||
-rw-r--r-- | tool/src/main.rs | 16 | ||||
-rw-r--r-- | tool/src/migrate.rs | 89 |
4 files changed, 111 insertions, 1 deletions
diff --git a/tool/Cargo.toml b/tool/Cargo.toml index c9d46f1..a53e1bd 100644 --- a/tool/Cargo.toml +++ b/tool/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [dependencies] jellycommon = { path = "../common" } +jellybase = { path = "../base" } jellymatroska = { path = "../matroska" } jellyremuxer = { path = "../remuxer" } @@ -13,6 +14,7 @@ env_logger = "0.10.0" anyhow = "1.0.75" clap = { version = "4.4.6", features = ["derive"] } reqwest = { version = "0.11.20", features = ["blocking", "json"] } +indicatif = "0.17.7" serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0.107" diff --git a/tool/src/import/mod.rs b/tool/src/import/mod.rs index e148c98..17f3137 100644 --- a/tool/src/import/mod.rs +++ b/tool/src/import/mod.rs @@ -1,3 +1,8 @@ +/* + This file is part of jellything (https://codeberg.org/metamuffin/jellything) + which is licensed under the GNU Affero General Public License (version 3); see /COPYING. + Copyright (C) 2023 metamuffin <metamuffin.org> +*/ pub mod infojson; pub mod tmdb; diff --git a/tool/src/main.rs b/tool/src/main.rs index 1e84bda..3a670f5 100644 --- a/tool/src/main.rs +++ b/tool/src/main.rs @@ -6,12 +6,14 @@ #![feature(file_create_new)] pub mod import; +pub mod migrate; use base64::Engine; -use clap::{Parser, Subcommand}; +use clap::{Parser, Subcommand, ValueEnum}; use import::import; use jellycommon::{config::GlobalConfig, Node, NodeKind, NodePrivate, NodePublic}; use log::{info, warn}; +use migrate::migrate; use rand::random; use std::{fmt::Debug, fs::File, io::Write, path::PathBuf}; @@ -61,6 +63,17 @@ enum Action { #[arg(short, long)] series: bool, }, + Migrate { + database: PathBuf, + mode: MigrateMode, + save_location: PathBuf, + }, +} + +#[derive(Debug, Clone, Copy, PartialEq, ValueEnum)] +enum MigrateMode { + Import, + Export, } fn main() -> anyhow::Result<()> { @@ -123,6 +136,7 @@ fn main() -> anyhow::Result<()> { Ok(()) } a @ Action::New { .. } => import(a, args.dry), + a @ Action::Migrate { .. } => migrate(a), } } diff --git a/tool/src/migrate.rs b/tool/src/migrate.rs new file mode 100644 index 0000000..7c24087 --- /dev/null +++ b/tool/src/migrate.rs @@ -0,0 +1,89 @@ +/* + This file is part of jellything (https://codeberg.org/metamuffin/jellything) + which is licensed under the GNU Affero General Public License (version 3); see /COPYING. + Copyright (C) 2023 metamuffin <metamuffin.org> +*/ +use crate::{Action, MigrateMode}; +use anyhow::bail; +use indicatif::ProgressIterator; +use jellybase::database::{typed_sled::Tree, Database}; +use log::info; +use serde::Serialize; +use std::{ + fs::File, + io::{BufRead, BufReader, BufWriter, Write}, + path::Path, +}; + +pub(crate) fn migrate(action: Action) -> anyhow::Result<()> { + match action { + Action::Migrate { + mode, + save_location, + database, + } => { + std::fs::create_dir_all(&save_location)?; + let db = Database::open(&database)?; + + info!("processing 'user'"); + process_tree(mode, &save_location.join("user"), &db.user)?; + info!("processing 'invite'"); + process_tree(mode, &save_location.join("invite"), &db.invite)?; + info!("processing 'node'"); + process_tree(mode, &save_location.join("node"), &db.node)?; + info!("done"); + Ok(()) + } + _ => unreachable!(), + } +} + +fn process_tree< + K: Serialize + for<'de> serde::Deserialize<'de>, + V: Serialize + for<'de> serde::Deserialize<'de>, +>( + mode: MigrateMode, + path: &Path, + tree: &Tree<K, V>, +) -> anyhow::Result<()> { + match mode { + MigrateMode::Export => export_tree(path, tree), + MigrateMode::Import => import_tree(path, tree), + } +} + +fn export_tree< + K: Serialize + for<'de> serde::Deserialize<'de>, + V: Serialize + for<'de> serde::Deserialize<'de>, +>( + path: &Path, + tree: &Tree<K, V>, +) -> anyhow::Result<()> { + let mut o = BufWriter::new(File::create(path)?); + let len = tree.len(); + for r in tree.iter().progress_count(len.try_into().unwrap()) { + let (k, v) = r?; + serde_json::to_writer(&mut o, &(k, v))?; + writeln!(&mut o)?; + } + Ok(()) +} + +fn import_tree< + K: Serialize + for<'de> serde::Deserialize<'de>, + V: Serialize + for<'de> serde::Deserialize<'de>, +>( + path: &Path, + tree: &Tree<K, V>, +) -> anyhow::Result<()> { + if !tree.is_empty() { + bail!("tree not empty, `rm -rf` your db please :)") + } + let i = BufReader::new(File::open(path)?); + for l in i.lines() { + let l = l?; + let (k, v) = serde_json::from_str::<(K, V)>(&l)?; + tree.insert(&k, &v)?; + } + Ok(()) +} |