Skip to content

Commit c19f6be

Browse files
Added checks and backups for the output directory
1 parent fe50731 commit c19f6be

File tree

6 files changed

+57
-15
lines changed

6 files changed

+57
-15
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@
1313
- If `--import "Profile Name"` is provided, the mods from the `Profile Name` profile will be imported
1414
- Only check internet connection for subcommands which need it
1515
- Extract internet connection check function
16+
- Created a `check_output_directory()` that uhhh.. checks the output directory
17+
- If it's not called `mods`, it will output a warning
18+
- If it contains stuff, it will ask if you want to create a backup
19+
- So that you don't lose the stuff in there when you upgrade
20+
- Along with the original relative directory check
1621

1722
## `v3.25.1`
1823

Cargo.lock

Lines changed: 9 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ lazy_static = "1.4"
3030
dialoguer = "0.10"
3131
serde_json = "1.0"
3232
itertools = "0.10"
33+
fs_extra = "1.2"
3334
colored = "2.0"
3435
ferinth = "2.2"
3536
libium = "1.11"

src/subcommands/profile/configure.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::subcommands::profile::{pick_minecraft_version, pick_mod_loader};
1+
use super::{check_output_directory, pick_minecraft_version, pick_mod_loader};
22
use anyhow::Result;
33
use dialoguer::{Input, Select};
44
use libium::{config, file_picker};
@@ -53,7 +53,13 @@ pub async fn configure(
5353
if let Some(index) = selection {
5454
match index {
5555
0 => {
56-
if let Some(dir) = file_picker::pick_folder(&profile.output_dir).await {
56+
if let Some(dir) = file_picker::pick_folder(
57+
&profile.output_dir,
58+
"Pick an output directory",
59+
)
60+
.await
61+
{
62+
check_output_directory(&dir).await?;
5763
profile.output_dir = dir;
5864
}
5965
},

src/subcommands/profile/create.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1+
use super::{check_output_directory, check_profile_name, pick_minecraft_version};
12
use anyhow::{bail, Result};
23
use dialoguer::{Confirm, Input, Select};
34
use libium::{config, file_picker, misc};
45
use std::path::PathBuf;
56

6-
use super::{check_profile_name, pick_minecraft_version};
7-
87
#[allow(clippy::option_option)]
98
pub async fn create(
109
config: &mut config::structs::Config,
@@ -39,10 +38,10 @@ pub async fn create(
3938
.with_prompt("Would you like to specify a custom mods directory?")
4039
.interact()?
4140
{
42-
if let Some(dir) = file_picker::pick_folder(&selected_mods_dir).await {
43-
if !dir.is_absolute() {
44-
bail!("The provided output directory is not absolute, i.e. it is a relative path")
45-
}
41+
if let Some(dir) =
42+
file_picker::pick_folder(&selected_mods_dir, "Pick an output directory").await
43+
{
44+
check_output_directory(&dir).await?;
4645
selected_mods_dir = dir;
4746
};
4847
}

src/subcommands/profile/mod.rs

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,22 @@ mod list;
55
pub use configure::configure;
66
pub use create::create;
77
pub use delete::delete;
8+
use fs_extra::dir::{copy, CopyOptions};
89
pub use list::list;
910

11+
use crate::THEME;
1012
use anyhow::{bail, Result};
11-
use dialoguer::Select;
13+
use colored::Colorize;
14+
use dialoguer::{Confirm, Select};
1215
use libium::{
1316
config::{self, structs::ModLoader},
14-
misc,
17+
file_picker, misc, HOME,
1518
};
19+
use std::path::PathBuf;
20+
use tokio::fs::read_dir;
1621

17-
fn pick_mod_loader(default: Option<&ModLoader>) -> std::io::Result<ModLoader> {
18-
let mut picker = Select::with_theme(&*crate::THEME);
22+
fn pick_mod_loader(default: Option<&ModLoader>) -> Result<ModLoader> {
23+
let mut picker = Select::with_theme(&*THEME);
1924
picker
2025
.with_prompt("Which mod loader do you use?")
2126
.items(&["Quilt", "Fabric", "Forge"]);
@@ -36,7 +41,7 @@ fn pick_mod_loader(default: Option<&ModLoader>) -> std::io::Result<ModLoader> {
3641

3742
async fn pick_minecraft_version() -> Result<String> {
3843
let mut latest_versions: Vec<String> = misc::get_major_mc_versions(10).await?;
39-
let selected_version = Select::with_theme(&*crate::THEME)
44+
let selected_version = Select::with_theme(&*THEME)
4045
.with_prompt("Which version of Minecraft do you play?")
4146
.items(&latest_versions)
4247
.default(0)
@@ -53,3 +58,22 @@ fn check_profile_name(config: &mut config::structs::Config, name: &str) -> Resul
5358
}
5459
Ok(())
5560
}
61+
62+
async fn check_output_directory(output_dir: &PathBuf) -> Result<()> {
63+
if output_dir.is_relative() {
64+
bail!("The provided output directory is not absolute, i.e. it is a relative path")
65+
}
66+
if output_dir.file_name().unwrap() != "mods" {
67+
println!("{}", "Warning! The output directory is not called `mods`. Most mod loaders will load a directory called `mods`.".bright_yellow())
68+
}
69+
if output_dir.exists() && read_dir(output_dir).await?.next_entry().await?.is_some() {
70+
if Confirm::with_theme(&*THEME)
71+
.with_prompt("Your output directory is not empty and it will be erased when upgrading. Would like to create a backup of it?")
72+
.interact()?
73+
{
74+
let backup_dir = file_picker::pick_folder(&*HOME, "Where should the backup be made?").await.unwrap();
75+
copy(output_dir, backup_dir, &CopyOptions::new())?;
76+
}
77+
}
78+
Ok(())
79+
}

0 commit comments

Comments
 (0)