Implement reading and writing of config files

This commit is contained in:
Robbert van der Helm
2020-07-13 14:31:33 +02:00
parent 4537b6a5b0
commit 21d48c3022
4 changed files with 98 additions and 4 deletions
+13
View File
@@ -290,6 +290,17 @@ version = "1.0.114"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5317f7588f0a5078ee60ef675ef96735a1442132dc645eb1d12c018620ed8cd3"
[[package]]
name = "serde_derive"
version = "1.0.114"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a0be94b04690fbaed37cddffc5c134bf537c8e3329d53e982fe04c374978f8e"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "strsim"
version = "0.10.0"
@@ -430,6 +441,8 @@ dependencies = [
"aho-corasick",
"clap",
"rayon",
"serde",
"serde_derive",
"toml",
"walkdir",
"xdg",
+2
View File
@@ -13,6 +13,8 @@ license = "GPL-3.0-or-later"
aho-corasick = "0.7.13"
clap = "3.0.0-beta.1"
rayon = "1.3.1"
serde = "1.0.114"
serde_derive = "1.0.114"
toml = "0.5.6"
walkdir = "2.3.1"
xdg = "2.2.0"
+67 -3
View File
@@ -14,13 +14,21 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
use serde_derive::{Deserialize, Serialize};
use std::fs;
use std::path::{Path, PathBuf};
use xdg::BaseDirectories;
/// The name of the config file, relative to `$XDG_CONFIG_HOME/CONFIG_PREFIX`.
const CONFIG_FILE_NAME: &str = "config.toml";
/// The name of the configuration directory, relative to `$XDG_CONFIG_HOME`.
const CONFIG_PREFIX: &str = "yabridgectl";
const LIBYABRIDGE_NAME: &str = "libyabridge.so";
/// The configuration used for yabridgectl. This will be serialized to and deserialized from
/// `$XDG_CONFIG_HOME/yabridge/config.toml`.
#[derive(Deserialize, Serialize, Debug)]
pub struct Config {
/// The installation method to use. We will default to creating copies since that works
/// everywehre.
@@ -34,6 +42,55 @@ pub struct Config {
}
impl Config {
/// Try to read the config file, creating a new default file if necessary. This will fail if the
/// file could not be created or if it could not be parsed.
pub fn read() -> Result<Config, String> {
match base_directories()?.find_config_file(CONFIG_FILE_NAME) {
Some(path) => {
let toml_str = fs::read_to_string(&path).map_err(|err| {
format!(
"Could not read config file at '{}': {}",
path.display(),
err
)
})?;
Ok(toml::from_str(&toml_str)
.map_err(|err| format!("Could not parse TOML: {:#?}", err))?)
}
None => {
let defaults = Config {
method: InstallationMethod::Copy,
yabridge_home: None,
plugin_dirs: Vec::new(),
};
// If no existing config file exists, then write a new config file with default
// values
defaults.write()?;
Ok(defaults)
}
}
}
/// Write the config to disk, creating the file if it does not yet exist.
pub fn write(&self) -> Result<(), String> {
let toml_str = toml::to_string_pretty(&self)
.map_err(|err| format!("Could not format TOML: {}", err))?;
let config_file = base_directories()?
.place_config_file(CONFIG_FILE_NAME)
.map_err(|err| format!("Could not write config file: {}", err))?;
fs::write(&config_file, toml_str).map_err(|err| {
format!(
"Could not write config file to '{}': {}",
config_file.display(),
err
)
})
}
/// Return the path to `libyabridge.so`, or a descriptive error if it can't be found. If
/// `yabridge_home` is `None`, then we'll search in both `/usr/lib` and
/// `$XDG_DATA_HOME/yabridge`.
@@ -54,9 +111,7 @@ impl Config {
None => {
// Search in the two common installation locations if no path was set explicitely
let system_path = Path::new("/usr/lib");
let user_path = BaseDirectories::new()
.map_err(|err| format!("Error while parsing base directories:\n{}", err))?
.get_data_home();
let user_path = base_directories()?.get_data_home();
for directory in &[system_path, &user_path] {
let candidate = directory.join(LIBYABRIDGE_NAME);
if candidate.exists() {
@@ -77,6 +132,8 @@ impl Config {
}
/// Specifies how yabridge will be set up for the found plugins.
#[derive(Deserialize, Serialize, Debug)]
#[serde(rename_all = "snake_case")]
pub enum InstallationMethod {
/// Create a copy of `libyabridge.so` for every Windows VST2 plugin .dll file found. After
/// updating yabridge, the user will have to rerun `yabridgectl sync` to copy over the new
@@ -87,3 +144,10 @@ pub enum InstallationMethod {
/// modify the `PATH` environment variable.
Symlink,
}
/// Fetch the XDG base directories, converting any error messages if this somehow fails into a
/// printable string to reduce boiler plate.
fn base_directories() -> Result<BaseDirectories, String> {
BaseDirectories::with_prefix(CONFIG_PREFIX)
.map_err(|err| format!("Error while parsing base directories: {}", err))
}
+16 -1
View File
@@ -16,6 +16,21 @@
mod config;
use config::Config;
fn main() {
println!("Hello, world!");
// TODO: Remove debug
match Config::read() {
Ok(config) => {
println!("Read config:\n\n{:#?}\n", config);
println!(
"Searching for libyabridge.toml:\n\n{:?}",
config.libyabridge()
);
}
Err(err) => {
eprintln!("Error while reading config:\n\n{}", err);
std::process::exit(1);
}
}
}