fix: don't overwrite config file
So far we have written a default config file if we encountered any error when trying to read the one that should exist. That included: * missing key-value-pairs, * empty file, and * a non-existant file. Therefore, when a field is added to the Config struct, the entire config file was overwritten with a default config. This occured during #20. Instead, we now provide default values in form of generator functions to serde. Any value that is present in the config is then parsed and replaces the default value. Only if the config file does not exist we create an empty one. Closes #26.
This commit is contained in:
+29
-9
@@ -18,10 +18,10 @@ Main program for `pacdef`. All internal logic happens in [`pacdef_core`].
|
||||
use std::path::Path;
|
||||
use std::process::{ExitCode, Termination};
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use anyhow::{bail, Context, Result};
|
||||
|
||||
use pacdef_core::path::{get_config_path, get_config_path_old_version, get_group_dir};
|
||||
use pacdef_core::{get_args, Config, Group, Pacdef};
|
||||
use pacdef_core::{get_args, Config, Error as PacdefError, Group, Pacdef};
|
||||
|
||||
const MAJOR_UPDATE_MESSAGE: &str = "VERSION UPGRADE
|
||||
You seem to have used version 0.x of pacdef before.
|
||||
@@ -41,7 +41,7 @@ fn handle_final_result(result: Result<()>) -> ExitCode {
|
||||
match result {
|
||||
Ok(_) => ExitCode::SUCCESS,
|
||||
Err(ref e) => {
|
||||
if let Some(root_error) = e.root_cause().downcast_ref::<pacdef_core::Error>() {
|
||||
if let Some(root_error) = e.root_cause().downcast_ref::<PacdefError>() {
|
||||
eprintln!("{root_error}");
|
||||
ExitCode::FAILURE
|
||||
} else {
|
||||
@@ -56,9 +56,23 @@ fn main_inner() -> Result<()> {
|
||||
|
||||
let config_file = get_config_path().context("getting config file")?;
|
||||
|
||||
let config = Config::load(&config_file)
|
||||
.or_else(|_| load_default_config(&config_file))
|
||||
.context("loading config")?;
|
||||
let config = match Config::load(&config_file).context("loading config file") {
|
||||
Ok(config) => config,
|
||||
Err(e) => {
|
||||
if let Some(crate_error) = e.downcast_ref::<PacdefError>() {
|
||||
match crate_error {
|
||||
PacdefError::ConfigFileNotFound => load_default_config(&config_file)?,
|
||||
_ => bail!("unexpected error: {crate_error}"),
|
||||
}
|
||||
} else {
|
||||
bail!("unexpected error: {e:?}");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
dbg!(&config);
|
||||
// .or_else(|_| load_default_config(&config_file))
|
||||
// .context("loading config")?;
|
||||
|
||||
let group_dir = get_group_dir().context("resolving group dir")?;
|
||||
let groups = Group::load(&group_dir, config.warn_not_symlinks)
|
||||
@@ -73,8 +87,14 @@ fn load_default_config(config_file: &Path) -> Result<Config> {
|
||||
println!("{MAJOR_UPDATE_MESSAGE}");
|
||||
}
|
||||
|
||||
let default = Config::default();
|
||||
default.save(config_file)?;
|
||||
if !config_file.exists() {
|
||||
create_empty_config_file(config_file)?;
|
||||
}
|
||||
|
||||
Ok(default)
|
||||
Ok(Config::default())
|
||||
}
|
||||
|
||||
fn create_empty_config_file(config_file: &Path) -> Result<()> {
|
||||
std::fs::File::create(config_file).context("creating empty config file")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ use crate::{impl_backend_constants, Group, Package};
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Arch {
|
||||
pub(crate) binary: String,
|
||||
pub(crate) aur_rm_args: Option<Vec<String>>,
|
||||
pub(crate) aur_rm_args: Vec<String>,
|
||||
pub(crate) packages: HashSet<Package>,
|
||||
}
|
||||
|
||||
@@ -72,9 +72,7 @@ impl Backend for Arch {
|
||||
let mut cmd = Command::new(&self.binary);
|
||||
|
||||
cmd.args(self.get_switches_remove());
|
||||
if let Some(rm_args) = &self.aur_rm_args {
|
||||
cmd.args(rm_args);
|
||||
}
|
||||
cmd.args(&self.aur_rm_args);
|
||||
|
||||
if noconfirm {
|
||||
cmd.args(self.get_switches_noconfirm());
|
||||
@@ -124,7 +122,7 @@ impl Arch {
|
||||
pub(crate) fn new() -> Self {
|
||||
Self {
|
||||
binary: BINARY.to_string(),
|
||||
aur_rm_args: None,
|
||||
aur_rm_args: vec![],
|
||||
packages: HashSet::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,17 +10,30 @@ use serde_derive::{Deserialize, Serialize};
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Config {
|
||||
/// The AUR helper to use for Arch Linux.
|
||||
#[serde(default = "aur_helper")]
|
||||
pub aur_helper: String,
|
||||
/// Additional arguments to pass to `aur_helper` when removing a package.
|
||||
pub aur_rm_args: Option<Vec<String>>,
|
||||
#[serde(default)]
|
||||
pub aur_rm_args: Vec<String>,
|
||||
/// Install Flatpak packages system-wide
|
||||
#[serde(default = "yes")]
|
||||
pub flatpak_systemwide: bool,
|
||||
/// Warn the user when a group is not a symlink.
|
||||
#[serde(default = "yes")]
|
||||
pub warn_not_symlinks: bool,
|
||||
/// Backends the user does not want to use even though the binary exists.
|
||||
#[serde(default)]
|
||||
pub disabled_backends: Vec<String>,
|
||||
}
|
||||
|
||||
fn yes() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn aur_helper() -> String {
|
||||
"paru".into()
|
||||
}
|
||||
|
||||
impl Config {
|
||||
/// Load the config from the associated file.
|
||||
///
|
||||
@@ -69,7 +82,7 @@ impl Default for Config {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
aur_helper: "paru".into(),
|
||||
aur_rm_args: None,
|
||||
aur_rm_args: vec![],
|
||||
flatpak_systemwide: true,
|
||||
warn_not_symlinks: true,
|
||||
disabled_backends: vec![],
|
||||
|
||||
@@ -125,7 +125,7 @@ impl Pacdef {
|
||||
{
|
||||
if let Some(arch) = backend.as_any_mut().downcast_mut::<crate::backend::Arch>() {
|
||||
arch.binary = self.config.aur_helper.clone();
|
||||
arch.aur_rm_args = self.config.aur_rm_args.take();
|
||||
arch.aur_rm_args = self.config.aur_rm_args.clone();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user