feat: implement backup layers using meta manager
							parent
							
								
									a236c36a4f
								
							
						
					
					
						commit
						29636ffcdb
					
				| 
						 | 
				
			
			@ -0,0 +1,46 @@
 | 
			
		|||
use std::error::Error;
 | 
			
		||||
use std::fmt;
 | 
			
		||||
use std::str::FromStr;
 | 
			
		||||
 | 
			
		||||
#[derive(Clone, Debug)]
 | 
			
		||||
pub struct ManagerConfig {
 | 
			
		||||
    pub name: String,
 | 
			
		||||
    pub frequency: u32,
 | 
			
		||||
    pub chain_len: u64,
 | 
			
		||||
    pub chains: u64,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
pub struct ParseManagerConfigErr;
 | 
			
		||||
 | 
			
		||||
impl Error for ParseManagerConfigErr {}
 | 
			
		||||
 | 
			
		||||
impl fmt::Display for ParseManagerConfigErr {
 | 
			
		||||
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 | 
			
		||||
        write!(f, "parse manager config err")
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl FromStr for ManagerConfig {
 | 
			
		||||
    type Err = ParseManagerConfigErr;
 | 
			
		||||
 | 
			
		||||
    fn from_str(s: &str) -> Result<Self, Self::Err> {
 | 
			
		||||
        let splits: Vec<&str> = s.split(',').collect();
 | 
			
		||||
 | 
			
		||||
        if let [name, frequency, chains, chain_len] = splits[..] {
 | 
			
		||||
            let name: String = name.parse().map_err(|_| ParseManagerConfigErr)?;
 | 
			
		||||
            let frequency: u32 = frequency.parse().map_err(|_| ParseManagerConfigErr)?;
 | 
			
		||||
            let chains: u64 = chains.parse().map_err(|_| ParseManagerConfigErr)?;
 | 
			
		||||
            let chain_len: u64 = chain_len.parse().map_err(|_| ParseManagerConfigErr)?;
 | 
			
		||||
 | 
			
		||||
            Ok(ManagerConfig {
 | 
			
		||||
                name,
 | 
			
		||||
                chains,
 | 
			
		||||
                chain_len,
 | 
			
		||||
                frequency,
 | 
			
		||||
            })
 | 
			
		||||
        } else {
 | 
			
		||||
            Err(ParseManagerConfigErr)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,83 @@
 | 
			
		|||
use super::{Manager, ManagerConfig};
 | 
			
		||||
use chrono::Utc;
 | 
			
		||||
use serde::Deserialize;
 | 
			
		||||
use serde::Serialize;
 | 
			
		||||
use std::io;
 | 
			
		||||
use std::path::PathBuf;
 | 
			
		||||
 | 
			
		||||
pub struct MetaManager<T>
 | 
			
		||||
where
 | 
			
		||||
    T: Clone + Serialize + for<'de> Deserialize<'de>,
 | 
			
		||||
{
 | 
			
		||||
    backup_dir: PathBuf,
 | 
			
		||||
    config_dir: PathBuf,
 | 
			
		||||
    world_dir: PathBuf,
 | 
			
		||||
    default_metadata: T,
 | 
			
		||||
    managers: Vec<Manager<T>>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<T> MetaManager<T>
 | 
			
		||||
where
 | 
			
		||||
    T: Clone + Serialize + for<'de> Deserialize<'de>,
 | 
			
		||||
{
 | 
			
		||||
    pub fn new<P1: Into<PathBuf>, P2: Into<PathBuf>, P3: Into<PathBuf>>(
 | 
			
		||||
        backup_dir: P1,
 | 
			
		||||
        config_dir: P2,
 | 
			
		||||
        world_dir: P3,
 | 
			
		||||
        default_metadata: T,
 | 
			
		||||
    ) -> Self {
 | 
			
		||||
        MetaManager {
 | 
			
		||||
            backup_dir: backup_dir.into(),
 | 
			
		||||
            config_dir: config_dir.into(),
 | 
			
		||||
            world_dir: world_dir.into(),
 | 
			
		||||
            default_metadata,
 | 
			
		||||
            managers: Vec::new(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn add(&mut self, config: &ManagerConfig) -> io::Result<()> {
 | 
			
		||||
        // Backup dir itself should exist, but we control its contents, so we can create
 | 
			
		||||
        // separate directories for each layer
 | 
			
		||||
        let path = self.backup_dir.join(&config.name);
 | 
			
		||||
        std::fs::create_dir(&path)?;
 | 
			
		||||
 | 
			
		||||
        let mut manager = Manager::new(
 | 
			
		||||
            path,
 | 
			
		||||
            self.config_dir.clone(),
 | 
			
		||||
            self.world_dir.clone(),
 | 
			
		||||
            self.default_metadata.clone(),
 | 
			
		||||
            config.chain_len,
 | 
			
		||||
            config.chains,
 | 
			
		||||
            chrono::Duration::minutes(config.frequency.into()),
 | 
			
		||||
        );
 | 
			
		||||
        manager.load()?;
 | 
			
		||||
        self.managers.push(manager);
 | 
			
		||||
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn add_all(&mut self, configs: &Vec<ManagerConfig>) -> io::Result<()> {
 | 
			
		||||
        for config in configs {
 | 
			
		||||
            self.add(config)?;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn next_scheduled_time(&self) -> Option<chrono::DateTime<Utc>> {
 | 
			
		||||
        self.managers.iter().map(|m| m.next_scheduled_time()).min()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn perform_backup_cycle(&mut self) -> io::Result<()> {
 | 
			
		||||
        if let Some(manager) = self
 | 
			
		||||
            .managers
 | 
			
		||||
            .iter_mut()
 | 
			
		||||
            .min_by_key(|m| m.next_scheduled_time())
 | 
			
		||||
        {
 | 
			
		||||
            manager.create_backup()?;
 | 
			
		||||
            manager.remove_old_backups()
 | 
			
		||||
        } else {
 | 
			
		||||
            Ok(())
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,3 +1,9 @@
 | 
			
		|||
mod config;
 | 
			
		||||
mod meta;
 | 
			
		||||
 | 
			
		||||
pub use config::ManagerConfig;
 | 
			
		||||
pub use meta::MetaManager;
 | 
			
		||||
 | 
			
		||||
use super::Backup;
 | 
			
		||||
use chrono::Utc;
 | 
			
		||||
use serde::Deserialize;
 | 
			
		||||
| 
						 | 
				
			
			@ -26,7 +32,6 @@ where
 | 
			
		|||
{
 | 
			
		||||
    const METADATA_FILE: &str = "alex.json";
 | 
			
		||||
 | 
			
		||||
    /// Initialize a new instance of a `BackupManager`.
 | 
			
		||||
    pub fn new<P1: Into<PathBuf>, P2: Into<PathBuf>, P3: Into<PathBuf>>(
 | 
			
		||||
        backup_dir: P1,
 | 
			
		||||
        config_dir: P2,
 | 
			
		||||
| 
						 | 
				
			
			@ -1,9 +1,11 @@
 | 
			
		|||
mod delta;
 | 
			
		||||
mod manager;
 | 
			
		||||
pub mod manager;
 | 
			
		||||
mod path;
 | 
			
		||||
 | 
			
		||||
use delta::Delta;
 | 
			
		||||
pub use manager::Manager;
 | 
			
		||||
pub use manager::ManagerConfig;
 | 
			
		||||
pub use manager::MetaManager;
 | 
			
		||||
 | 
			
		||||
use chrono::Utc;
 | 
			
		||||
use flate2::write::GzEncoder;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										76
									
								
								src/cli.rs
								
								
								
								
							
							
						
						
									
										76
									
								
								src/cli.rs
								
								
								
								
							| 
						 | 
				
			
			@ -1,52 +1,7 @@
 | 
			
		|||
use crate::backup::ManagerConfig;
 | 
			
		||||
use crate::server::ServerType;
 | 
			
		||||
use clap::{Args, Parser, Subcommand};
 | 
			
		||||
use std::error::Error;
 | 
			
		||||
use std::fmt;
 | 
			
		||||
use std::path::PathBuf;
 | 
			
		||||
use std::str::FromStr;
 | 
			
		||||
 | 
			
		||||
#[derive(Clone, Debug)]
 | 
			
		||||
pub struct ManagerConfig {
 | 
			
		||||
    name: String,
 | 
			
		||||
    frequency: u32,
 | 
			
		||||
    chain_len: u64,
 | 
			
		||||
    chains: u64,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
pub struct ParseManagerConfigErr;
 | 
			
		||||
 | 
			
		||||
impl Error for ParseManagerConfigErr {}
 | 
			
		||||
 | 
			
		||||
impl fmt::Display for ParseManagerConfigErr {
 | 
			
		||||
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 | 
			
		||||
        write!(f, "parse manager config err")
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl FromStr for ManagerConfig {
 | 
			
		||||
    type Err = ParseManagerConfigErr;
 | 
			
		||||
 | 
			
		||||
    fn from_str(s: &str) -> Result<Self, Self::Err> {
 | 
			
		||||
        let splits: Vec<&str> = s.split(',').collect();
 | 
			
		||||
 | 
			
		||||
        if let [name, frequency, chains, chain_len] = splits[..] {
 | 
			
		||||
            let name: String = name.parse().map_err(|_| ParseManagerConfigErr)?;
 | 
			
		||||
            let frequency: u32 = frequency.parse().map_err(|_| ParseManagerConfigErr)?;
 | 
			
		||||
            let chains: u64 = chains.parse().map_err(|_| ParseManagerConfigErr)?;
 | 
			
		||||
            let chain_len: u64 = chain_len.parse().map_err(|_| ParseManagerConfigErr)?;
 | 
			
		||||
 | 
			
		||||
            Ok(ManagerConfig {
 | 
			
		||||
                name,
 | 
			
		||||
                chains,
 | 
			
		||||
                chain_len,
 | 
			
		||||
                frequency,
 | 
			
		||||
            })
 | 
			
		||||
        } else {
 | 
			
		||||
            Err(ParseManagerConfigErr)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Parser)]
 | 
			
		||||
#[command(author, version, about, long_about = None)]
 | 
			
		||||
| 
						 | 
				
			
			@ -86,35 +41,6 @@ pub struct Cli {
 | 
			
		|||
    #[arg(long, env = "ALEX_LAYERS", global = true, value_delimiter = ';')]
 | 
			
		||||
    pub layers: Vec<ManagerConfig>,
 | 
			
		||||
 | 
			
		||||
    /// Length of a backup chain
 | 
			
		||||
    #[arg(
 | 
			
		||||
        short = 'l',
 | 
			
		||||
        long,
 | 
			
		||||
        default_value_t = 4,
 | 
			
		||||
        env = "ALEX_CHAIN_LEN",
 | 
			
		||||
        global = true
 | 
			
		||||
    )]
 | 
			
		||||
    pub chain_len: u64,
 | 
			
		||||
    /// How many backup chains to keep
 | 
			
		||||
    #[arg(
 | 
			
		||||
        short = 'n',
 | 
			
		||||
        long,
 | 
			
		||||
        default_value_t = 7,
 | 
			
		||||
        env = "ALEX_CHAINS",
 | 
			
		||||
        global = true
 | 
			
		||||
    )]
 | 
			
		||||
    pub chains: u64,
 | 
			
		||||
 | 
			
		||||
    /// How frequently to perform a backup, in minutes; 0 to disable.
 | 
			
		||||
    #[arg(
 | 
			
		||||
        short = 't',
 | 
			
		||||
        long,
 | 
			
		||||
        default_value_t = 0,
 | 
			
		||||
        env = "ALEX_FREQUENCY",
 | 
			
		||||
        global = true
 | 
			
		||||
    )]
 | 
			
		||||
    pub frequency: u32,
 | 
			
		||||
 | 
			
		||||
    /// Type of server
 | 
			
		||||
    #[arg(long, default_value = "unknown", env = "ALEX_SERVER", global = true)]
 | 
			
		||||
    pub server: ServerType,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										43
									
								
								src/main.rs
								
								
								
								
							
							
						
						
									
										43
									
								
								src/main.rs
								
								
								
								
							| 
						 | 
				
			
			@ -5,7 +5,7 @@ mod signals;
 | 
			
		|||
mod stdin;
 | 
			
		||||
 | 
			
		||||
use clap::Parser;
 | 
			
		||||
use cli::{BackupArgs, Cli, Commands, RunArgs};
 | 
			
		||||
use cli::{Cli, Commands, RunArgs};
 | 
			
		||||
use std::io;
 | 
			
		||||
use std::sync::{Arc, Mutex};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -13,7 +13,7 @@ fn backups_thread(counter: Arc<Mutex<server::ServerProcess>>) {
 | 
			
		|||
    loop {
 | 
			
		||||
        let next_scheduled_time = {
 | 
			
		||||
            let server = counter.lock().unwrap();
 | 
			
		||||
            server.backups.next_scheduled_time()
 | 
			
		||||
            server.backups.next_scheduled_time().unwrap()
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        let now = chrono::offset::Utc::now();
 | 
			
		||||
| 
						 | 
				
			
			@ -39,11 +39,9 @@ fn command_run(cli: &Cli, args: &RunArgs) -> io::Result<()> {
 | 
			
		|||
        .config(cli.config.clone())
 | 
			
		||||
        .world(cli.world.clone())
 | 
			
		||||
        .backup(cli.backup.clone())
 | 
			
		||||
        .managers(cli.layers.clone())
 | 
			
		||||
        .xms(args.xms)
 | 
			
		||||
        .xmx(args.xmx)
 | 
			
		||||
        .chain_len(cli.chain_len)
 | 
			
		||||
        .chains_to_keep(cli.chains)
 | 
			
		||||
        .frequency(cli.frequency);
 | 
			
		||||
        .xmx(args.xmx);
 | 
			
		||||
    cmd.canonicalize()?;
 | 
			
		||||
 | 
			
		||||
    if args.dry {
 | 
			
		||||
| 
						 | 
				
			
			@ -54,7 +52,7 @@ fn command_run(cli: &Cli, args: &RunArgs) -> io::Result<()> {
 | 
			
		|||
 | 
			
		||||
    let counter = Arc::new(Mutex::new(cmd.spawn()?));
 | 
			
		||||
 | 
			
		||||
    if cli.frequency > 0 {
 | 
			
		||||
    if !cli.layers.is_empty() {
 | 
			
		||||
        let clone = Arc::clone(&counter);
 | 
			
		||||
        std::thread::spawn(move || backups_thread(clone));
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -67,32 +65,23 @@ fn command_run(cli: &Cli, args: &RunArgs) -> io::Result<()> {
 | 
			
		|||
    signals::handle_signals(&mut signals, counter)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn commands_backup(cli: &Cli, _args: &BackupArgs) -> io::Result<()> {
 | 
			
		||||
    let metadata = server::Metadata {
 | 
			
		||||
        server_type: cli.server,
 | 
			
		||||
        server_version: cli.server_version.clone(),
 | 
			
		||||
    };
 | 
			
		||||
// fn commands_backup(cli: &Cli, _args: &BackupArgs) -> io::Result<()> {
 | 
			
		||||
//     let metadata = server::Metadata {
 | 
			
		||||
//         server_type: cli.server,
 | 
			
		||||
//         server_version: cli.server_version.clone(),
 | 
			
		||||
//     };
 | 
			
		||||
//     let mut meta = MetaManager::new(cli.backup, cli.config, cli.world, metadata);
 | 
			
		||||
//     meta.add_all(&cli.layers)?;
 | 
			
		||||
 | 
			
		||||
    let mut manager = backup::Manager::new(
 | 
			
		||||
        cli.backup.clone(),
 | 
			
		||||
        cli.config.clone(),
 | 
			
		||||
        cli.world.clone(),
 | 
			
		||||
        metadata,
 | 
			
		||||
        cli.chain_len,
 | 
			
		||||
        cli.chains,
 | 
			
		||||
        chrono::Duration::minutes(cli.frequency.into()),
 | 
			
		||||
    );
 | 
			
		||||
    manager.load()?;
 | 
			
		||||
 | 
			
		||||
    manager.create_backup()?;
 | 
			
		||||
    manager.remove_old_backups()
 | 
			
		||||
}
 | 
			
		||||
//     manager.create_backup()?;
 | 
			
		||||
//     manager.remove_old_backups()
 | 
			
		||||
// }
 | 
			
		||||
 | 
			
		||||
fn main() -> io::Result<()> {
 | 
			
		||||
    let cli = Cli::parse();
 | 
			
		||||
 | 
			
		||||
    match &cli.command {
 | 
			
		||||
        Commands::Run(args) => command_run(&cli, args),
 | 
			
		||||
        Commands::Backup(args) => commands_backup(&cli, args),
 | 
			
		||||
        Commands::Backup(_) => Ok(()),
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,40 +1,12 @@
 | 
			
		|||
use crate::backup::Manager as BackupManager;
 | 
			
		||||
use crate::server::ServerProcess;
 | 
			
		||||
use clap::ValueEnum;
 | 
			
		||||
use serde::{Deserialize, Serialize};
 | 
			
		||||
use crate::backup::ManagerConfig;
 | 
			
		||||
use crate::backup::MetaManager;
 | 
			
		||||
use crate::server::{Metadata, ServerProcess, ServerType};
 | 
			
		||||
use std::fmt;
 | 
			
		||||
use std::fs::File;
 | 
			
		||||
use std::io::Write;
 | 
			
		||||
use std::path::{Path, PathBuf};
 | 
			
		||||
use std::process::{Command, Stdio};
 | 
			
		||||
 | 
			
		||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum, Serialize, Deserialize)]
 | 
			
		||||
pub enum ServerType {
 | 
			
		||||
    Unknown,
 | 
			
		||||
    Paper,
 | 
			
		||||
    Forge,
 | 
			
		||||
    Vanilla,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl fmt::Display for ServerType {
 | 
			
		||||
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 | 
			
		||||
        let s = match self {
 | 
			
		||||
            ServerType::Unknown => "Unknown",
 | 
			
		||||
            ServerType::Paper => "PaperMC",
 | 
			
		||||
            ServerType::Forge => "Forge",
 | 
			
		||||
            ServerType::Vanilla => "Vanilla",
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        write!(f, "{}", s)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Clone, Serialize, Deserialize)]
 | 
			
		||||
pub struct Metadata {
 | 
			
		||||
    pub server_type: ServerType,
 | 
			
		||||
    pub server_version: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub struct ServerCommand {
 | 
			
		||||
    type_: ServerType,
 | 
			
		||||
    version: String,
 | 
			
		||||
| 
						 | 
				
			
			@ -45,9 +17,7 @@ pub struct ServerCommand {
 | 
			
		|||
    backup_dir: PathBuf,
 | 
			
		||||
    xms: u64,
 | 
			
		||||
    xmx: u64,
 | 
			
		||||
    chain_len: u64,
 | 
			
		||||
    chains_to_keep: u64,
 | 
			
		||||
    frequency: u32,
 | 
			
		||||
    managers: Vec<ManagerConfig>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ServerCommand {
 | 
			
		||||
| 
						 | 
				
			
			@ -62,9 +32,7 @@ impl ServerCommand {
 | 
			
		|||
            backup_dir: PathBuf::from("backups"),
 | 
			
		||||
            xms: 1024,
 | 
			
		||||
            xmx: 2048,
 | 
			
		||||
            chain_len: 4,
 | 
			
		||||
            chains_to_keep: 7,
 | 
			
		||||
            frequency: 0,
 | 
			
		||||
            managers: Vec::new(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -105,18 +73,9 @@ impl ServerCommand {
 | 
			
		|||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn chain_len(mut self, v: u64) -> Self {
 | 
			
		||||
        self.chain_len = v;
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
    pub fn managers(mut self, configs: Vec<ManagerConfig>) -> Self {
 | 
			
		||||
        self.managers = configs;
 | 
			
		||||
 | 
			
		||||
    pub fn chains_to_keep(mut self, v: u64) -> Self {
 | 
			
		||||
        self.chains_to_keep = v;
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn frequency(mut self, v: u32) -> Self {
 | 
			
		||||
        self.frequency = v;
 | 
			
		||||
        self
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -207,22 +166,19 @@ impl ServerCommand {
 | 
			
		|||
            server_type: self.type_,
 | 
			
		||||
            server_version: self.version.clone(),
 | 
			
		||||
        };
 | 
			
		||||
        let mut manager = BackupManager::new(
 | 
			
		||||
        let mut meta = MetaManager::new(
 | 
			
		||||
            self.backup_dir.clone(),
 | 
			
		||||
            self.config_dir.clone(),
 | 
			
		||||
            self.world_dir.clone(),
 | 
			
		||||
            metadata,
 | 
			
		||||
            self.chain_len,
 | 
			
		||||
            self.chains_to_keep,
 | 
			
		||||
            chrono::Duration::minutes(self.frequency.into()),
 | 
			
		||||
        );
 | 
			
		||||
        manager.load()?;
 | 
			
		||||
        meta.add_all(&self.managers)?;
 | 
			
		||||
 | 
			
		||||
        let mut cmd = self.create_cmd();
 | 
			
		||||
        self.accept_eula()?;
 | 
			
		||||
        let child = cmd.spawn()?;
 | 
			
		||||
 | 
			
		||||
        Ok(ServerProcess::new(manager, child))
 | 
			
		||||
        Ok(ServerProcess::new(meta, child))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,36 @@
 | 
			
		|||
mod command;
 | 
			
		||||
mod process;
 | 
			
		||||
 | 
			
		||||
pub use command::{Metadata, ServerCommand, ServerType};
 | 
			
		||||
pub use command::ServerCommand;
 | 
			
		||||
pub use process::ServerProcess;
 | 
			
		||||
 | 
			
		||||
use clap::ValueEnum;
 | 
			
		||||
use serde::{Deserialize, Serialize};
 | 
			
		||||
use std::fmt;
 | 
			
		||||
 | 
			
		||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum, Serialize, Deserialize)]
 | 
			
		||||
pub enum ServerType {
 | 
			
		||||
    Unknown,
 | 
			
		||||
    Paper,
 | 
			
		||||
    Forge,
 | 
			
		||||
    Vanilla,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl fmt::Display for ServerType {
 | 
			
		||||
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 | 
			
		||||
        let s = match self {
 | 
			
		||||
            ServerType::Unknown => "Unknown",
 | 
			
		||||
            ServerType::Paper => "PaperMC",
 | 
			
		||||
            ServerType::Forge => "Forge",
 | 
			
		||||
            ServerType::Vanilla => "Vanilla",
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        write!(f, "{}", s)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Clone, Serialize, Deserialize)]
 | 
			
		||||
pub struct Metadata {
 | 
			
		||||
    pub server_type: ServerType,
 | 
			
		||||
    pub server_version: String,
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,15 +1,15 @@
 | 
			
		|||
use crate::backup::Manager as BackupManager;
 | 
			
		||||
use crate::backup::MetaManager;
 | 
			
		||||
use crate::server::Metadata;
 | 
			
		||||
use std::io::Write;
 | 
			
		||||
use std::process::Child;
 | 
			
		||||
 | 
			
		||||
pub struct ServerProcess {
 | 
			
		||||
    child: Child,
 | 
			
		||||
    pub backups: BackupManager<Metadata>,
 | 
			
		||||
    pub backups: MetaManager<Metadata>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ServerProcess {
 | 
			
		||||
    pub fn new(manager: BackupManager<Metadata>, child: Child) -> ServerProcess {
 | 
			
		||||
    pub fn new(manager: MetaManager<Metadata>, child: Child) -> ServerProcess {
 | 
			
		||||
        ServerProcess {
 | 
			
		||||
            child,
 | 
			
		||||
            backups: manager,
 | 
			
		||||
| 
						 | 
				
			
			@ -59,16 +59,12 @@ impl ServerProcess {
 | 
			
		|||
        std::thread::sleep(std::time::Duration::from_secs(10));
 | 
			
		||||
 | 
			
		||||
        let start_time = chrono::offset::Utc::now();
 | 
			
		||||
        let res = self.backups.create_backup();
 | 
			
		||||
        let res = self.backups.perform_backup_cycle();
 | 
			
		||||
 | 
			
		||||
        // The server's save feature needs to be enabled again even if the archive failed to create
 | 
			
		||||
        self.custom("save-on")?;
 | 
			
		||||
        self.custom("save-all")?;
 | 
			
		||||
 | 
			
		||||
        if res.is_ok() {
 | 
			
		||||
            self.backups.remove_old_backups()?;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let duration = chrono::offset::Utc::now() - start_time;
 | 
			
		||||
        let duration_str = format!(
 | 
			
		||||
            "{}m{}s",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue