aboutsummaryrefslogtreecommitdiff
path: root/tool
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2023-10-24 20:04:19 +0200
committermetamuffin <metamuffin@disroot.org>2023-10-24 20:04:19 +0200
commit5ee01d06c0b067f2f07d0288c499897cd0df29f7 (patch)
tree91dd323219a2102770d40919d5e713b03f48b1e5 /tool
parentd9b3b92e8ddd27aac39269a03a0eeb18e3a62a6a (diff)
downloadjellything-5ee01d06c0b067f2f07d0288c499897cd0df29f7.tar
jellything-5ee01d06c0b067f2f07d0288c499897cd0df29f7.tar.bz2
jellything-5ee01d06c0b067f2f07d0288c499897cd0df29f7.tar.zst
migration tool
Diffstat (limited to 'tool')
-rw-r--r--tool/Cargo.toml2
-rw-r--r--tool/src/import/mod.rs5
-rw-r--r--tool/src/main.rs16
-rw-r--r--tool/src/migrate.rs89
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(())
+}