feat: store server info in metadata file; change cli flags
parent
ef631fab1d
commit
53dc3783ca
|
@ -14,10 +14,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
* Chain length descibres how many incremental backups to create from the
|
* Chain length descibres how many incremental backups to create from the
|
||||||
same full backup
|
same full backup
|
||||||
* "backups to keep" has been replaced by "chains to keep"
|
* "backups to keep" has been replaced by "chains to keep"
|
||||||
|
* Server type & version is now stored as metadata in the metadata file
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
* Running the server now uses the `run` CLI subcommand
|
* Running the server now uses the `run` CLI subcommand
|
||||||
|
* `server_type` and `server_version` arguments are now optional flags
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ impl Delta {
|
||||||
|
|
||||||
/// Update the current state so that its result becomes the merge of itself and the other
|
/// Update the current state so that its result becomes the merge of itself and the other
|
||||||
/// state.
|
/// state.
|
||||||
|
#[allow(dead_code)]
|
||||||
pub fn merge(&mut self, delta: &Self) {
|
pub fn merge(&mut self, delta: &Self) {
|
||||||
for (dir, added) in delta.added.iter() {
|
for (dir, added) in delta.added.iter() {
|
||||||
// Files that were removed in the current state, but added in the new state, are no
|
// Files that were removed in the current state, but added in the new state, are no
|
||||||
|
|
|
@ -1,18 +1,27 @@
|
||||||
use super::Backup;
|
use super::Backup;
|
||||||
|
use serde::de::DeserializeOwned;
|
||||||
|
use serde::Serialize;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
pub struct Manager {
|
pub struct Manager<T>
|
||||||
|
where
|
||||||
|
T: Clone + Serialize + DeserializeOwned,
|
||||||
|
{
|
||||||
backup_dir: PathBuf,
|
backup_dir: PathBuf,
|
||||||
config_dir: PathBuf,
|
config_dir: PathBuf,
|
||||||
world_dir: PathBuf,
|
world_dir: PathBuf,
|
||||||
|
default_metadata: T,
|
||||||
chain_len: u64,
|
chain_len: u64,
|
||||||
chains_to_keep: u64,
|
chains_to_keep: u64,
|
||||||
chains: Vec<Vec<Backup>>,
|
chains: Vec<Vec<Backup<T>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Manager {
|
impl<T> Manager<T>
|
||||||
|
where
|
||||||
|
T: Clone + Serialize + DeserializeOwned,
|
||||||
|
{
|
||||||
const METADATA_FILE: &str = "alex.json";
|
const METADATA_FILE: &str = "alex.json";
|
||||||
|
|
||||||
/// Initialize a new instance of a `BackupManager`.
|
/// Initialize a new instance of a `BackupManager`.
|
||||||
|
@ -20,6 +29,7 @@ impl Manager {
|
||||||
backup_dir: PathBuf,
|
backup_dir: PathBuf,
|
||||||
config_dir: PathBuf,
|
config_dir: PathBuf,
|
||||||
world_dir: PathBuf,
|
world_dir: PathBuf,
|
||||||
|
metadata: T,
|
||||||
chain_len: u64,
|
chain_len: u64,
|
||||||
chains_to_keep: u64,
|
chains_to_keep: u64,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
@ -27,6 +37,7 @@ impl Manager {
|
||||||
backup_dir,
|
backup_dir,
|
||||||
config_dir,
|
config_dir,
|
||||||
world_dir,
|
world_dir,
|
||||||
|
default_metadata: metadata,
|
||||||
chain_len,
|
chain_len,
|
||||||
chains_to_keep,
|
chains_to_keep,
|
||||||
chains: Vec::new(),
|
chains: Vec::new(),
|
||||||
|
@ -40,32 +51,32 @@ impl Manager {
|
||||||
(PathBuf::from("worlds"), self.world_dir.clone()),
|
(PathBuf::from("worlds"), self.world_dir.clone()),
|
||||||
];
|
];
|
||||||
|
|
||||||
// I kinda hate this statement, please just let me combine let statements in if statements
|
// We start a new chain if the current chain is complete, or if there isn't a first chain
|
||||||
// already
|
// yet
|
||||||
let backup = if let Some(current_chain) = self.chains.last() {
|
if let Some(current_chain) = self.chains.last() {
|
||||||
let current_chain_len: u64 = current_chain.len().try_into().unwrap();
|
let current_chain_len: u64 = current_chain.len().try_into().unwrap();
|
||||||
|
|
||||||
if current_chain_len < self.chain_len {
|
if current_chain_len >= self.chain_len {
|
||||||
if let Some(previous_backup) = current_chain.last() {
|
self.chains.push(Vec::new());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.chains.push(Vec::new());
|
||||||
|
}
|
||||||
|
|
||||||
|
let current_chain = self.chains.last_mut().unwrap();
|
||||||
|
|
||||||
|
let mut backup = if !current_chain.is_empty() {
|
||||||
|
let previous_backup = current_chain.last().unwrap();
|
||||||
let state = Backup::state(current_chain);
|
let state = Backup::state(current_chain);
|
||||||
|
|
||||||
Backup::create_from(state, previous_backup.start_time, &self.backup_dir, dirs)?
|
Backup::create_from(state, previous_backup.start_time, &self.backup_dir, dirs)?
|
||||||
} else {
|
} else {
|
||||||
Backup::create(&self.backup_dir, dirs)?
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.chains.push(Vec::new());
|
|
||||||
|
|
||||||
Backup::create(&self.backup_dir, dirs)?
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.chains.push(Vec::new());
|
|
||||||
|
|
||||||
Backup::create(&self.backup_dir, dirs)?
|
Backup::create(&self.backup_dir, dirs)?
|
||||||
};
|
};
|
||||||
|
|
||||||
// The above statement always creates this element, so this unwrap is safe
|
backup.set_metadata(self.default_metadata.clone());
|
||||||
self.chains.last_mut().unwrap().push(backup);
|
|
||||||
|
current_chain.push(backup);
|
||||||
|
|
||||||
self.save()?;
|
self.save()?;
|
||||||
|
|
||||||
|
@ -73,7 +84,7 @@ impl Manager {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Delete all backups associated with outdated chains, and forget those chains.
|
/// Delete all backups associated with outdated chains, and forget those chains.
|
||||||
pub fn remove_old_backups(&mut self) -> std::io::Result<()> {
|
pub fn remove_old_backups(&mut self) -> io::Result<()> {
|
||||||
let chains_to_store: usize = self.chains_to_keep.try_into().unwrap();
|
let chains_to_store: usize = self.chains_to_keep.try_into().unwrap();
|
||||||
|
|
||||||
if chains_to_store < self.chains.len() {
|
if chains_to_store < self.chains.len() {
|
||||||
|
@ -91,15 +102,15 @@ impl Manager {
|
||||||
std::fs::remove_file(path)?;
|
std::fs::remove_file(path)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
self.save()?;
|
self.save()?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write the in-memory state to disk.
|
/// Write the in-memory state to disk.
|
||||||
pub fn save(&self) -> std::io::Result<()> {
|
pub fn save(&self) -> io::Result<()> {
|
||||||
let json_file = File::create(self.backup_dir.join(Self::METADATA_FILE))?;
|
let json_file = File::create(self.backup_dir.join(Self::METADATA_FILE))?;
|
||||||
serde_json::to_writer(json_file, &self.chains)?;
|
serde_json::to_writer(json_file, &self.chains)?;
|
||||||
|
|
||||||
|
@ -107,7 +118,7 @@ impl Manager {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Overwrite the in-memory state with the on-disk state.
|
/// Overwrite the in-memory state with the on-disk state.
|
||||||
pub fn load(&mut self) -> std::io::Result<()> {
|
pub fn load(&mut self) -> io::Result<()> {
|
||||||
let json_file = match File::open(self.backup_dir.join(Self::METADATA_FILE)) {
|
let json_file = match File::open(self.backup_dir.join(Self::METADATA_FILE)) {
|
||||||
Ok(f) => f,
|
Ok(f) => f,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -121,6 +132,7 @@ impl Manager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.chains = serde_json::from_reader(json_file)?;
|
self.chains = serde_json::from_reader(json_file)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -22,21 +22,37 @@ pub enum BackupType {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents a successful backup
|
/// Represents a successful backup
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct Backup {
|
pub struct Backup<T: Clone> {
|
||||||
/// When the backup was started (also corresponds to the name)
|
/// When the backup was started (also corresponds to the name)
|
||||||
pub start_time: chrono::DateTime<Utc>,
|
pub start_time: chrono::DateTime<Utc>,
|
||||||
/// Type of the backup
|
/// Type of the backup
|
||||||
pub type_: BackupType,
|
pub type_: BackupType,
|
||||||
pub delta: Delta,
|
pub delta: Delta,
|
||||||
|
/// Additional metadata that can be associated with a given backup
|
||||||
|
pub metadata: Option<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Backup {
|
impl Backup<()> {
|
||||||
|
/// Return the path to a backup file by properly formatting the data.
|
||||||
|
pub fn path<P: AsRef<Path>>(backup_dir: P, start_time: chrono::DateTime<Utc>) -> PathBuf {
|
||||||
|
let backup_dir = backup_dir.as_ref();
|
||||||
|
|
||||||
|
let filename = format!("{}", start_time.format(Self::FILENAME_FORMAT));
|
||||||
|
backup_dir.join(filename)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Clone> Backup<T> {
|
||||||
const FILENAME_FORMAT: &str = "%Y-%m-%d_%H-%M-%S.tar.gz";
|
const FILENAME_FORMAT: &str = "%Y-%m-%d_%H-%M-%S.tar.gz";
|
||||||
|
|
||||||
|
pub fn set_metadata(&mut self, metadata: T) {
|
||||||
|
self.metadata = Some(metadata);
|
||||||
|
}
|
||||||
|
|
||||||
/// Resolve the state of the list of backups by applying their deltas in-order to an initially
|
/// Resolve the state of the list of backups by applying their deltas in-order to an initially
|
||||||
/// empty state.
|
/// empty state.
|
||||||
pub fn state(backups: &Vec<Backup>) -> HashMap<PathBuf, HashSet<PathBuf>> {
|
pub fn state(backups: &Vec<Self>) -> HashMap<PathBuf, HashSet<PathBuf>> {
|
||||||
let mut state: HashMap<PathBuf, HashSet<PathBuf>> = HashMap::new();
|
let mut state: HashMap<PathBuf, HashSet<PathBuf>> = HashMap::new();
|
||||||
|
|
||||||
for backup in backups {
|
for backup in backups {
|
||||||
|
@ -46,14 +62,6 @@ impl Backup {
|
||||||
state
|
state
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the path to a backup file by properly formatting the data.
|
|
||||||
pub fn path<P: AsRef<Path>>(backup_dir: P, start_time: chrono::DateTime<Utc>) -> PathBuf {
|
|
||||||
let backup_dir = backup_dir.as_ref();
|
|
||||||
|
|
||||||
let filename = format!("{}", start_time.format(Self::FILENAME_FORMAT));
|
|
||||||
backup_dir.join(filename)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a new Full backup, populated with the given directories.
|
/// Create a new Full backup, populated with the given directories.
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
|
@ -71,7 +79,7 @@ impl Backup {
|
||||||
) -> io::Result<Self> {
|
) -> io::Result<Self> {
|
||||||
let start_time = chrono::offset::Utc::now();
|
let start_time = chrono::offset::Utc::now();
|
||||||
|
|
||||||
let path = Self::path(backup_dir, start_time);
|
let path = Backup::path(backup_dir, start_time);
|
||||||
let tar_gz = File::create(path)?;
|
let tar_gz = File::create(path)?;
|
||||||
let enc = GzEncoder::new(tar_gz, Compression::default());
|
let enc = GzEncoder::new(tar_gz, Compression::default());
|
||||||
let mut ar = tar::Builder::new(enc);
|
let mut ar = tar::Builder::new(enc);
|
||||||
|
@ -96,6 +104,7 @@ impl Backup {
|
||||||
type_: BackupType::Full,
|
type_: BackupType::Full,
|
||||||
start_time,
|
start_time,
|
||||||
delta,
|
delta,
|
||||||
|
metadata: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,7 +117,7 @@ impl Backup {
|
||||||
) -> io::Result<Self> {
|
) -> io::Result<Self> {
|
||||||
let start_time = chrono::offset::Utc::now();
|
let start_time = chrono::offset::Utc::now();
|
||||||
|
|
||||||
let path = Self::path(backup_dir, start_time);
|
let path = Backup::path(backup_dir, start_time);
|
||||||
let tar_gz = File::create(path)?;
|
let tar_gz = File::create(path)?;
|
||||||
let enc = GzEncoder::new(tar_gz, Compression::default());
|
let enc = GzEncoder::new(tar_gz, Compression::default());
|
||||||
let mut ar = tar::Builder::new(enc);
|
let mut ar = tar::Builder::new(enc);
|
||||||
|
@ -145,6 +154,7 @@ impl Backup {
|
||||||
type_: BackupType::Incremental,
|
type_: BackupType::Incremental,
|
||||||
start_time,
|
start_time,
|
||||||
delta,
|
delta,
|
||||||
|
metadata: None,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
20
src/cli.rs
20
src/cli.rs
|
@ -53,6 +53,12 @@ pub struct Cli {
|
||||||
global = true
|
global = true
|
||||||
)]
|
)]
|
||||||
pub chains: u64,
|
pub chains: u64,
|
||||||
|
/// Type of server
|
||||||
|
#[arg(long, default_value = "unknown", env = "ALEX_SERVER")]
|
||||||
|
pub server: ServerType,
|
||||||
|
/// Version string for the server, e.g. 1.19.4-545
|
||||||
|
#[arg(long, default_value = "", env = "ALEX_SERVER_VERSION")]
|
||||||
|
pub server_version: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subcommand)]
|
#[derive(Subcommand)]
|
||||||
|
@ -66,12 +72,6 @@ pub enum Commands {
|
||||||
|
|
||||||
#[derive(Args)]
|
#[derive(Args)]
|
||||||
pub struct RunArgs {
|
pub struct RunArgs {
|
||||||
/// Type of server
|
|
||||||
pub type_: ServerType,
|
|
||||||
/// Version string for the server, e.g. 1.19.4-545
|
|
||||||
#[arg(env = "ALEX_SERVER_VERSION")]
|
|
||||||
pub server_version: String,
|
|
||||||
|
|
||||||
/// Server jar to execute
|
/// Server jar to execute
|
||||||
#[arg(
|
#[arg(
|
||||||
long,
|
long,
|
||||||
|
@ -103,10 +103,4 @@ pub struct RunArgs {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Args)]
|
#[derive(Args)]
|
||||||
pub struct BackupArgs {
|
pub struct BackupArgs {}
|
||||||
/// Type of server
|
|
||||||
pub type_: ServerType,
|
|
||||||
/// Version string for the server, e.g. 1.19.4-545
|
|
||||||
#[arg(env = "ALEX_SERVER_VERSION")]
|
|
||||||
pub server_version: String,
|
|
||||||
}
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ fn backups_thread(counter: Arc<Mutex<server::ServerProcess>>, frequency: u64) {
|
||||||
fn command_run(cli: &Cli, args: &RunArgs) -> io::Result<()> {
|
fn command_run(cli: &Cli, args: &RunArgs) -> io::Result<()> {
|
||||||
let (_, mut signals) = signals::install_signal_handlers()?;
|
let (_, mut signals) = signals::install_signal_handlers()?;
|
||||||
|
|
||||||
let mut cmd = server::ServerCommand::new(args.type_, &args.server_version)
|
let mut cmd = server::ServerCommand::new(cli.server, &cli.server_version)
|
||||||
.java(&args.java)
|
.java(&args.java)
|
||||||
.jar(args.jar.clone())
|
.jar(args.jar.clone())
|
||||||
.config(cli.config.clone())
|
.config(cli.config.clone())
|
||||||
|
@ -60,10 +60,16 @@ fn command_run(cli: &Cli, args: &RunArgs) -> io::Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn commands_backup(cli: &Cli, _args: &BackupArgs) -> io::Result<()> {
|
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 manager = backup::Manager::new(
|
let mut manager = backup::Manager::new(
|
||||||
cli.backup.clone(),
|
cli.backup.clone(),
|
||||||
cli.config.clone(),
|
cli.config.clone(),
|
||||||
cli.world.clone(),
|
cli.world.clone(),
|
||||||
|
metadata,
|
||||||
cli.chain_len,
|
cli.chain_len,
|
||||||
cli.chains,
|
cli.chains,
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
use crate::backup::Manager as BackupManager;
|
use crate::backup::Manager as BackupManager;
|
||||||
use crate::server::ServerProcess;
|
use crate::server::ServerProcess;
|
||||||
use clap::ValueEnum;
|
use clap::ValueEnum;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::process::{Command, Stdio};
|
use std::process::{Command, Stdio};
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum, Serialize, Deserialize)]
|
||||||
pub enum ServerType {
|
pub enum ServerType {
|
||||||
|
Unknown,
|
||||||
Paper,
|
Paper,
|
||||||
Forge,
|
Forge,
|
||||||
Vanilla,
|
Vanilla,
|
||||||
|
@ -17,6 +19,7 @@ pub enum ServerType {
|
||||||
impl fmt::Display for ServerType {
|
impl fmt::Display for ServerType {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let s = match self {
|
let s = match self {
|
||||||
|
ServerType::Unknown => "Unknown",
|
||||||
ServerType::Paper => "PaperMC",
|
ServerType::Paper => "PaperMC",
|
||||||
ServerType::Forge => "Forge",
|
ServerType::Forge => "Forge",
|
||||||
ServerType::Vanilla => "Vanilla",
|
ServerType::Vanilla => "Vanilla",
|
||||||
|
@ -26,6 +29,12 @@ impl fmt::Display for ServerType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
|
pub struct Metadata {
|
||||||
|
pub server_type: ServerType,
|
||||||
|
pub server_version: String,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct ServerCommand {
|
pub struct ServerCommand {
|
||||||
type_: ServerType,
|
type_: ServerType,
|
||||||
version: String,
|
version: String,
|
||||||
|
@ -187,10 +196,15 @@ impl ServerCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spawn(&mut self) -> std::io::Result<ServerProcess> {
|
pub fn spawn(&mut self) -> std::io::Result<ServerProcess> {
|
||||||
|
let metadata = Metadata {
|
||||||
|
server_type: self.type_,
|
||||||
|
server_version: self.version.clone(),
|
||||||
|
};
|
||||||
let mut manager = BackupManager::new(
|
let mut manager = BackupManager::new(
|
||||||
self.backup_dir.clone(),
|
self.backup_dir.clone(),
|
||||||
self.config_dir.clone(),
|
self.config_dir.clone(),
|
||||||
self.world_dir.clone(),
|
self.world_dir.clone(),
|
||||||
|
metadata,
|
||||||
self.chain_len,
|
self.chain_len,
|
||||||
self.chains_to_keep,
|
self.chains_to_keep,
|
||||||
);
|
);
|
||||||
|
@ -200,12 +214,7 @@ impl ServerCommand {
|
||||||
self.accept_eula()?;
|
self.accept_eula()?;
|
||||||
let child = cmd.spawn()?;
|
let child = cmd.spawn()?;
|
||||||
|
|
||||||
Ok(ServerProcess::new(
|
Ok(ServerProcess::new(manager, child))
|
||||||
self.type_,
|
|
||||||
self.version.clone(),
|
|
||||||
manager,
|
|
||||||
child,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
mod command;
|
mod command;
|
||||||
mod process;
|
mod process;
|
||||||
|
|
||||||
pub use command::{ServerCommand, ServerType};
|
pub use command::{Metadata, ServerCommand, ServerType};
|
||||||
pub use process::ServerProcess;
|
pub use process::ServerProcess;
|
||||||
|
|
|
@ -1,25 +1,16 @@
|
||||||
use crate::backup::Manager as BackupManager;
|
use crate::backup::Manager as BackupManager;
|
||||||
use crate::server::ServerType;
|
use crate::server::Metadata;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::process::Child;
|
use std::process::Child;
|
||||||
|
|
||||||
pub struct ServerProcess {
|
pub struct ServerProcess {
|
||||||
type_: ServerType,
|
|
||||||
version: String,
|
|
||||||
child: Child,
|
child: Child,
|
||||||
backups: BackupManager,
|
backups: BackupManager<Metadata>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerProcess {
|
impl ServerProcess {
|
||||||
pub fn new(
|
pub fn new(manager: BackupManager<Metadata>, child: Child) -> ServerProcess {
|
||||||
type_: ServerType,
|
|
||||||
version: String,
|
|
||||||
manager: BackupManager,
|
|
||||||
child: Child,
|
|
||||||
) -> ServerProcess {
|
|
||||||
ServerProcess {
|
ServerProcess {
|
||||||
type_,
|
|
||||||
version,
|
|
||||||
child,
|
child,
|
||||||
backups: manager,
|
backups: manager,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue