mirror of
https://git.ahines.net/joeyahines/Albatross.git
synced 2026-05-08 16:12:13 +00:00
Compare commits
No commits in common. "2283b6f851c4e61322540b09e4fe0562896fc74e" and "38630a4d5718011032085cab104d5c00f711724e" have entirely different histories.
2283b6f851
...
38630a4d57
42
.drone.yml
Normal file
42
.drone.yml
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
---
|
||||||
|
kind: pipeline
|
||||||
|
name: compliance
|
||||||
|
type: docker
|
||||||
|
|
||||||
|
trigger:
|
||||||
|
event:
|
||||||
|
- pull_request
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: build
|
||||||
|
pull: always
|
||||||
|
image: rust:1.55.0
|
||||||
|
commands:
|
||||||
|
- cargo build --verbose
|
||||||
|
|
||||||
|
---
|
||||||
|
kind: pipeline
|
||||||
|
name: release
|
||||||
|
type: docker
|
||||||
|
|
||||||
|
trigger:
|
||||||
|
branch:
|
||||||
|
- master
|
||||||
|
event:
|
||||||
|
- push
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: build
|
||||||
|
pull: always
|
||||||
|
image: rust:1.55.0
|
||||||
|
commands:
|
||||||
|
- cargo build --verbose --release
|
||||||
|
- name: gitea-release
|
||||||
|
pull: always
|
||||||
|
image: jolheiser/drone-gitea-main:latest
|
||||||
|
settings:
|
||||||
|
token:
|
||||||
|
from_secret: gitea_token
|
||||||
|
base: https://git.canopymc.net
|
||||||
|
files:
|
||||||
|
- "target/release/albatross"
|
||||||
@ -1,29 +0,0 @@
|
|||||||
name: Build and Test Albatross
|
|
||||||
on: [push]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Install Task
|
|
||||||
uses: go-task/setup-task@v2
|
|
||||||
with:
|
|
||||||
repo-token: ${{ secrets.TASK_GITHUB_API_TOKEN }}
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- name: Stable with rustfmt and clippy
|
|
||||||
uses: actions-rs/toolchain@v1
|
|
||||||
with:
|
|
||||||
profile: minimal
|
|
||||||
toolchain: stable
|
|
||||||
components: rustfmt, clippy
|
|
||||||
- name: Lint Code
|
|
||||||
run: task check
|
|
||||||
- name: Build
|
|
||||||
run: task build
|
|
||||||
- name: Run Unit Tests
|
|
||||||
run: task test
|
|
||||||
- name: Upload Built Binary
|
|
||||||
uses: christopherHX/gitea-upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: albatross
|
|
||||||
path: target/debug/albatross
|
|
||||||
@ -1,23 +0,0 @@
|
|||||||
name: Build and Release Albatross
|
|
||||||
on: [release]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Install Task
|
|
||||||
uses: go-task/setup-task@v2
|
|
||||||
with:
|
|
||||||
repo-token: ${{ secrets.TASK_GITHUB_API_TOKEN }}
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- name: Stable with rustfmt and clippy
|
|
||||||
uses: actions-rs/toolchain@v1
|
|
||||||
with:
|
|
||||||
profile: minimal
|
|
||||||
toolchain: stable
|
|
||||||
- name: Build Release
|
|
||||||
run: task build:release
|
|
||||||
- uses: https://gitea.com/actions/gitea-release-action@v1
|
|
||||||
with:
|
|
||||||
files: |-
|
|
||||||
target/release/albatross
|
|
||||||
663
Cargo.lock
generated
663
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "albatross"
|
name = "albatross"
|
||||||
version = "0.7.1"
|
version = "0.6.1"
|
||||||
authors = ["Joey Hines <joey@ahines.net>"]
|
authors = ["Joey Hines <joey@ahines.net>"]
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
@ -15,7 +15,7 @@ chrono = "0.4"
|
|||||||
regex = "1.3.9"
|
regex = "1.3.9"
|
||||||
flate2 = "1.0.14"
|
flate2 = "1.0.14"
|
||||||
tar = "0.4.28"
|
tar = "0.4.28"
|
||||||
reqwest = { version = "0.13.2", features = ["blocking", "json"] }
|
reqwest = { version = "0.12.22", features = ["blocking", "json"] }
|
||||||
discord-hooks-rs = { git = "https://github.com/joeyahines/discord-hooks-rs" }
|
discord-hooks-rs = { git = "https://github.com/joeyahines/discord-hooks-rs" }
|
||||||
anvil-region = "0.8.1"
|
anvil-region = "0.8.1"
|
||||||
ssh2 = "0.9.1"
|
ssh2 = "0.9.1"
|
||||||
|
|||||||
45
README.md
45
README.md
@ -8,7 +8,7 @@ Backups can also be transferred to a remote server using SFTP.
|
|||||||
|
|
||||||
## Help
|
## Help
|
||||||
```
|
```
|
||||||
albatross 0.7.0
|
albatross 0.4.0
|
||||||
Backup your Minecraft Server!
|
Backup your Minecraft Server!
|
||||||
|
|
||||||
USAGE:
|
USAGE:
|
||||||
@ -25,7 +25,10 @@ SUBCOMMANDS:
|
|||||||
backup Backup a server
|
backup Backup a server
|
||||||
export Export a backup as a single player world
|
export Export a backup as a single player world
|
||||||
help Prints this message or the help of the given subcommand(s)
|
help Prints this message or the help of the given subcommand(s)
|
||||||
restore Restore certain chunks from a backup```
|
restore Restore certain chunks from a backup
|
||||||
|
|
||||||
|
Process finished with exit code 1
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
@ -46,44 +49,6 @@ Restoring a range of chunks (from -2,-2 to 2,2):
|
|||||||
`albatorss -c test.toml restore world backups/04-11-20_01.51.27_backup.tar.gz sp.tar.gz` (-2,-2) -u (2,2)
|
`albatorss -c test.toml restore world backups/04-11-20_01.51.27_backup.tar.gz sp.tar.gz` (-2,-2) -u (2,2)
|
||||||
|
|
||||||
## Config
|
## Config
|
||||||
|
|
||||||
### For Minecraft Versions After 26.1
|
|
||||||
```toml
|
|
||||||
[backup]
|
|
||||||
# Minecraft sever directory
|
|
||||||
minecraft_dir = "/home/mc/server"
|
|
||||||
# Optional Discord webhook
|
|
||||||
discord_webhook = "https://discordapp.com/api/webhooks/"
|
|
||||||
# Number of backups to keep
|
|
||||||
backups_to_keep = 10
|
|
||||||
|
|
||||||
[backup.output_config]
|
|
||||||
# Directory to place backups
|
|
||||||
path = "./backups"
|
|
||||||
|
|
||||||
[world_26_plus_config]
|
|
||||||
world_name = "world"
|
|
||||||
|
|
||||||
[[world_26_plus_config.dimensions]]
|
|
||||||
# world name
|
|
||||||
world_name = "minecraft/overworld"
|
|
||||||
# world save radius (in blocks)
|
|
||||||
save_radius = 1000
|
|
||||||
|
|
||||||
[[world_26_plus_config.dimensions]]
|
|
||||||
# world name
|
|
||||||
world_name = "minecraft/the_end"
|
|
||||||
# world save radius (in blocks)
|
|
||||||
save_radius = 1000
|
|
||||||
|
|
||||||
[[world_26_plus_config.dimensions]]
|
|
||||||
# world name
|
|
||||||
world_name = "minecraft/the_nether"
|
|
||||||
# world save radius (in blocks)
|
|
||||||
save_radius = 1000
|
|
||||||
```
|
|
||||||
|
|
||||||
### For Minecraft Versions Before 26.1
|
|
||||||
```toml
|
```toml
|
||||||
# Local Backup Config
|
# Local Backup Config
|
||||||
[backup]
|
[backup]
|
||||||
|
|||||||
@ -1,38 +0,0 @@
|
|||||||
# yaml-language-server: $schema=https://taskfile.dev/schema.json
|
|
||||||
|
|
||||||
version: '3'
|
|
||||||
|
|
||||||
tasks:
|
|
||||||
version:
|
|
||||||
desc: Print out Rust version info
|
|
||||||
cmds:
|
|
||||||
- cargo --version
|
|
||||||
- rustc --version
|
|
||||||
- cargo clippy --version
|
|
||||||
build:
|
|
||||||
desc: Debug build
|
|
||||||
cmds:
|
|
||||||
- cargo build --timings --tests --bins
|
|
||||||
test:
|
|
||||||
desc: Test code
|
|
||||||
deps: [build]
|
|
||||||
cmds:
|
|
||||||
- cargo test --locked
|
|
||||||
build:release:
|
|
||||||
desc: Release build
|
|
||||||
cmds:
|
|
||||||
- cargo build --release --locked --timings
|
|
||||||
fmt:
|
|
||||||
desc: Format Rust code
|
|
||||||
cmds:
|
|
||||||
- cargo fmt
|
|
||||||
check:
|
|
||||||
desc: Lint code with Clippy
|
|
||||||
cmds:
|
|
||||||
- cargo check
|
|
||||||
- cargo fmt --check
|
|
||||||
- cargo clippy
|
|
||||||
clean:
|
|
||||||
desc: Purge Rust build cache
|
|
||||||
cmds:
|
|
||||||
- cargo clean
|
|
||||||
138
src/backup.rs
138
src/backup.rs
@ -1,8 +1,6 @@
|
|||||||
use crate::config::{
|
use crate::config::{AlbatrossConfig, RemoteBackupConfig, WorldConfig, WorldType};
|
||||||
AlbatrossConfig, RemoteBackupConfig, World26PlusConfig, WorldConfig, WorldType,
|
|
||||||
};
|
|
||||||
use crate::discord::send_webhook;
|
use crate::discord::send_webhook;
|
||||||
use crate::error::{AlbatrossError, Result};
|
use crate::error::Result;
|
||||||
use crate::region::Region;
|
use crate::region::Region;
|
||||||
use crate::remote::RemoteBackupSite;
|
use crate::remote::RemoteBackupSite;
|
||||||
use crate::remote::file::FileBackup;
|
use crate::remote::file::FileBackup;
|
||||||
@ -45,36 +43,23 @@ pub fn backup_file(file_name: &str, world_path: &Path, backup_path: &Path) -> Re
|
|||||||
pub fn backup_dir(dir_name: &str, world_path: &Path, backup_path: &Path) -> Result<u64> {
|
pub fn backup_dir(dir_name: &str, world_path: &Path, backup_path: &Path) -> Result<u64> {
|
||||||
let src_dir = world_path.join(dir_name);
|
let src_dir = world_path.join(dir_name);
|
||||||
|
|
||||||
if !src_dir.exists() || !src_dir.is_dir() {
|
if !src_dir.exists() {
|
||||||
warn!("Directory '{dir_name}' does not exist in '{world_path:?}'");
|
warn!("Directory '{dir_name}' does not exist in '{world_path:?}'");
|
||||||
return Ok(0);
|
return Ok(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
let backup_dir_path = backup_path.join(dir_name);
|
let backup_dir = backup_path.join(dir_name);
|
||||||
create_dir(&backup_dir_path)?;
|
create_dir(&backup_dir)?;
|
||||||
|
|
||||||
let mut file_count = 0;
|
let mut file_count = 0;
|
||||||
for entry in src_dir.read_dir()? {
|
for entry in src_dir.read_dir()? {
|
||||||
let entry = entry?;
|
let entry = entry?;
|
||||||
let mut target = backup_dir_path.clone();
|
let mut target = backup_dir.clone();
|
||||||
|
|
||||||
if entry.path().is_dir() {
|
|
||||||
let sub_dir = entry.file_name();
|
|
||||||
let world_path = world_path.join(dir_name);
|
|
||||||
let backup_path = backup_path.join(dir_name);
|
|
||||||
|
|
||||||
if !backup_path.exists() {
|
|
||||||
create_dir(&backup_path)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
file_count += backup_dir(sub_dir.to_str().unwrap(), &world_path, &backup_path)?;
|
|
||||||
} else {
|
|
||||||
target.push(entry.file_name());
|
target.push(entry.file_name());
|
||||||
|
|
||||||
copy(entry.path(), target)?;
|
copy(entry.path(), target)?;
|
||||||
file_count += 1;
|
file_count += 1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Ok(file_count)
|
Ok(file_count)
|
||||||
}
|
}
|
||||||
@ -109,10 +94,8 @@ pub fn backup_region(
|
|||||||
let entry = entry?;
|
let entry = entry?;
|
||||||
let file_name = entry.file_name().to_str().unwrap().to_string();
|
let file_name = entry.file_name().to_str().unwrap().to_string();
|
||||||
|
|
||||||
if let Ok(region) = Region::try_from(file_name)
|
if let Ok(region) = Region::try_from(file_name) {
|
||||||
&& region.x.abs() <= save_radius
|
if region.x.abs() <= save_radius && region.y.abs() <= save_radius {
|
||||||
&& region.y.abs() <= save_radius
|
|
||||||
{
|
|
||||||
let mut target = backup_dir.clone();
|
let mut target = backup_dir.clone();
|
||||||
target.push(entry.file_name());
|
target.push(entry.file_name());
|
||||||
|
|
||||||
@ -120,6 +103,7 @@ pub fn backup_region(
|
|||||||
count += 1;
|
count += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(count)
|
Ok(count)
|
||||||
}
|
}
|
||||||
@ -286,7 +270,7 @@ pub fn do_remote_backup(
|
|||||||
/// * `cfg` - config file
|
/// * `cfg` - config file
|
||||||
pub fn do_backup(cfg: AlbatrossConfig, output: Option<PathBuf>) -> Result<()> {
|
pub fn do_backup(cfg: AlbatrossConfig, output: Option<PathBuf>) -> Result<()> {
|
||||||
let server_base_dir = cfg.backup.minecraft_dir.clone();
|
let server_base_dir = cfg.backup.minecraft_dir.clone();
|
||||||
let timer = Instant::now();
|
let worlds = cfg.world_config.clone().expect("No worlds configured");
|
||||||
let time_str = Utc::now().format("%d-%m-%y_%H.%M.%S").to_string();
|
let time_str = Utc::now().format("%d-%m-%y_%H.%M.%S").to_string();
|
||||||
let backup_name = format!("{time_str}_backup.tar.gz");
|
let backup_name = format!("{time_str}_backup.tar.gz");
|
||||||
let mut output_archive = match output {
|
let mut output_archive = match output {
|
||||||
@ -300,21 +284,15 @@ pub fn do_backup(cfg: AlbatrossConfig, output: Option<PathBuf>) -> Result<()> {
|
|||||||
|
|
||||||
create_dir_all(tmp_dir.clone())?;
|
create_dir_all(tmp_dir.clone())?;
|
||||||
|
|
||||||
|
let timer = Instant::now();
|
||||||
|
|
||||||
send_webhook("**Albatross is swooping in to backup your worlds!**", &cfg);
|
send_webhook("**Albatross is swooping in to backup your worlds!**", &cfg);
|
||||||
|
|
||||||
let backup_res = if let Some(worlds) = &cfg.world_config {
|
backup_worlds(&cfg, server_base_dir, worlds, &tmp_dir).map_err(|e| {
|
||||||
backup_worlds(&cfg, server_base_dir, worlds, &tmp_dir)
|
send_webhook("Failed to copy worlds to backup location", &cfg);
|
||||||
} else if let Some(world_config) = &cfg.world_26_plus_config {
|
error!("Failed to copy worlds: {e}");
|
||||||
backup_v26_plus_world_format(&cfg, world_config, &tmp_dir)
|
e
|
||||||
} else {
|
})?;
|
||||||
Err(AlbatrossError::MissingConfig)
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Err(err) = backup_res {
|
|
||||||
send_webhook("Failed to backup worlds", &cfg);
|
|
||||||
error!("Failed to backup worlds: {err}");
|
|
||||||
return Err(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
compress_backup(&tmp_dir, &output_archive).map_err(|e| {
|
compress_backup(&tmp_dir, &output_archive).map_err(|e| {
|
||||||
send_webhook("Failed to compress backup", &cfg);
|
send_webhook("Failed to compress backup", &cfg);
|
||||||
@ -324,7 +302,8 @@ pub fn do_backup(cfg: AlbatrossConfig, output: Option<PathBuf>) -> Result<()> {
|
|||||||
|
|
||||||
remove_dir_all(&tmp_dir)?;
|
remove_dir_all(&tmp_dir)?;
|
||||||
|
|
||||||
let mut local_backup = FileBackup::new(&cfg.backup.output_config, cfg.backup.backups_to_keep)?;
|
let mut local_backup =
|
||||||
|
FileBackup::new(&cfg.backup.output_config, cfg.backup.backups_to_keep).unwrap();
|
||||||
|
|
||||||
match local_backup.cleanup() {
|
match local_backup.cleanup() {
|
||||||
Ok(backups_removed) => {
|
Ok(backups_removed) => {
|
||||||
@ -363,81 +342,10 @@ pub fn do_backup(cfg: AlbatrossConfig, output: Option<PathBuf>) -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Backup a dimension
|
|
||||||
///
|
|
||||||
/// # Param
|
|
||||||
/// * `world_path` - path to the world folder
|
|
||||||
/// * `backup_path` - path to the backup folder
|
|
||||||
/// * `world_config` - world config options
|
|
||||||
pub fn backup_dimension(
|
|
||||||
world_path: &Path,
|
|
||||||
backup_path: &Path,
|
|
||||||
world_config: &WorldConfig,
|
|
||||||
) -> Result<u64> {
|
|
||||||
let dimension_path = Path::new("dimensions").join(&world_config.world_name);
|
|
||||||
let backup_path = backup_path.join(&dimension_path);
|
|
||||||
let src_path = world_path.join(dimension_path);
|
|
||||||
create_dir_all(backup_path.as_path())?;
|
|
||||||
|
|
||||||
backup_dir("data", &src_path, &backup_path)?;
|
|
||||||
let region_count = backup_region("region", world_config.save_radius, &src_path, &backup_path)?;
|
|
||||||
Ok(region_count)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Backup v26.1 + version
|
|
||||||
///
|
|
||||||
/// # Param
|
|
||||||
/// * `world_path` - path to the world folder
|
|
||||||
/// * `backup_path` - path to the backup folder
|
|
||||||
/// * `world_config` - world config options
|
|
||||||
pub fn backup_v26_plus_world_format(
|
|
||||||
cfg: &AlbatrossConfig,
|
|
||||||
world_config: &World26PlusConfig,
|
|
||||||
tmp_dir: &Path,
|
|
||||||
) -> Result<()> {
|
|
||||||
let world_path = cfg.backup.minecraft_dir.join(&world_config.world_name);
|
|
||||||
let backup_path = tmp_dir.join(&world_config.world_name);
|
|
||||||
|
|
||||||
if !backup_path.exists() {
|
|
||||||
create_dir(&backup_path)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
send_webhook(
|
|
||||||
format!("Starting backup **{}**", world_config.world_name).as_str(),
|
|
||||||
cfg,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Backup common files
|
|
||||||
backup_dir("data", &world_path, &backup_path)?;
|
|
||||||
backup_dir("datapacks", &world_path, &backup_path)?;
|
|
||||||
backup_file("level.dat", &world_path, &backup_path)?;
|
|
||||||
backup_file("level.dat_old", &world_path, &backup_path).ok();
|
|
||||||
backup_file("session.lock", &world_path, &backup_path).ok();
|
|
||||||
let player_count = backup_dir("players", &world_path, &backup_path)?;
|
|
||||||
send_webhook(format!("Backed up {player_count} players").as_str(), cfg);
|
|
||||||
info!("Backed up {player_count} players");
|
|
||||||
|
|
||||||
for world_config in &world_config.dimensions {
|
|
||||||
send_webhook(
|
|
||||||
format!("Starting backup of **{}**", world_config.world_name).as_str(),
|
|
||||||
cfg,
|
|
||||||
);
|
|
||||||
info!(
|
|
||||||
"Starting backup of dimension **{}**",
|
|
||||||
world_config.world_name
|
|
||||||
);
|
|
||||||
let region_count = backup_dimension(&world_path, &backup_path, world_config)?;
|
|
||||||
send_webhook(format!("{region_count} regions backed up.").as_str(), cfg);
|
|
||||||
info!("{region_count} regions backed up.")
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn backup_worlds(
|
fn backup_worlds(
|
||||||
cfg: &AlbatrossConfig,
|
cfg: &AlbatrossConfig,
|
||||||
server_base_dir: PathBuf,
|
server_base_dir: PathBuf,
|
||||||
worlds: &[WorldConfig],
|
worlds: Vec<WorldConfig>,
|
||||||
tmp_dir: &Path,
|
tmp_dir: &Path,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
for world in worlds {
|
for world in worlds {
|
||||||
@ -452,15 +360,15 @@ fn backup_worlds(
|
|||||||
let webhook_msg = match world_type {
|
let webhook_msg = match world_type {
|
||||||
WorldType::Overworld => {
|
WorldType::Overworld => {
|
||||||
let (region_count, player_count) =
|
let (region_count, player_count) =
|
||||||
backup_overworld(&world_dir.clone(), tmp_dir, world)?;
|
backup_overworld(&world_dir.clone(), tmp_dir, &world)?;
|
||||||
format!("{region_count} regions and {player_count} player files backed up.")
|
format!("{region_count} regions and {player_count} player files backed up.")
|
||||||
}
|
}
|
||||||
WorldType::Nether => {
|
WorldType::Nether => {
|
||||||
let region_count = backup_nether(&world_dir, tmp_dir, world)?;
|
let region_count = backup_nether(&world_dir, tmp_dir, &world)?;
|
||||||
format!("{region_count} regions backed up.")
|
format!("{region_count} regions backed up.")
|
||||||
}
|
}
|
||||||
WorldType::End => {
|
WorldType::End => {
|
||||||
let region_count = backup_end(&world_dir, tmp_dir, world)?;
|
let region_count = backup_end(&world_dir, tmp_dir, &world)?;
|
||||||
format!("{region_count} regions backed up.")
|
format!("{region_count} regions backed up.")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -64,19 +64,11 @@ pub struct RemoteBackupConfig {
|
|||||||
pub file: Option<FileConfig>,
|
pub file: Option<FileConfig>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Config for individual world configuration
|
|
||||||
#[derive(Debug, Deserialize, Clone)]
|
|
||||||
pub struct World26PlusConfig {
|
|
||||||
pub world_name: String,
|
|
||||||
pub dimensions: Vec<WorldConfig>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Configs
|
/// Configs
|
||||||
#[derive(Debug, Deserialize, Clone)]
|
#[derive(Debug, Deserialize, Clone)]
|
||||||
pub struct AlbatrossConfig {
|
pub struct AlbatrossConfig {
|
||||||
pub backup: BackupConfig,
|
pub backup: BackupConfig,
|
||||||
pub world_config: Option<Vec<WorldConfig>>,
|
pub world_config: Option<Vec<WorldConfig>>,
|
||||||
pub world_26_plus_config: Option<World26PlusConfig>,
|
|
||||||
pub remote: Option<RemoteBackupConfig>,
|
pub remote: Option<RemoteBackupConfig>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,6 @@ pub enum AlbatrossError {
|
|||||||
ChronoParseError(chrono::ParseError),
|
ChronoParseError(chrono::ParseError),
|
||||||
NoSSHAuth,
|
NoSSHAuth,
|
||||||
FTPError(ftp::FtpError),
|
FTPError(ftp::FtpError),
|
||||||
MissingConfig,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::error::Error for AlbatrossError {}
|
impl std::error::Error for AlbatrossError {}
|
||||||
@ -28,7 +27,6 @@ impl std::fmt::Display for AlbatrossError {
|
|||||||
AlbatrossError::ChronoParseError(e) => write!(f, "Unable to parse time: {e}"),
|
AlbatrossError::ChronoParseError(e) => write!(f, "Unable to parse time: {e}"),
|
||||||
AlbatrossError::NoSSHAuth => write!(f, "No SSH auth methods provided in the config"),
|
AlbatrossError::NoSSHAuth => write!(f, "No SSH auth methods provided in the config"),
|
||||||
AlbatrossError::FTPError(e) => write!(f, "FTP error: {e}"),
|
AlbatrossError::FTPError(e) => write!(f, "FTP error: {e}"),
|
||||||
AlbatrossError::MissingConfig => write!(f, "Missing world config"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -74,6 +74,7 @@ fn main() {
|
|||||||
let cfg = AlbatrossConfig::new(opt.config_path.into_os_string().to_str().unwrap())
|
let cfg = AlbatrossConfig::new(opt.config_path.into_os_string().to_str().unwrap())
|
||||||
.expect("Config error");
|
.expect("Config error");
|
||||||
|
|
||||||
|
if cfg.world_config.is_some() {
|
||||||
match opt.sub_command {
|
match opt.sub_command {
|
||||||
SubCommand::Backup { output } => {
|
SubCommand::Backup { output } => {
|
||||||
info!("Starting backup");
|
info!("Starting backup");
|
||||||
@ -130,4 +131,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
info!("No worlds specified in config file!")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user