Skip to content

Commit

Permalink
feat: add default paths for config file
Browse files Browse the repository at this point in the history
  • Loading branch information
DevYukine committed Jan 16, 2024
1 parent 26793d2 commit c823b08
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 2 deletions.
19 changes: 18 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,27 @@ Options:
```

### Example config.json
### Config file

This is useful if you don't want a super long CLI command and your configs do not change often, note that all the options can be specified via the CLI as well and are fully optional in this config file (will be merged with the CLI options if specified)

There are multiple default locations where the config file will be searched for, in this order (once found it will not look for the config file in the other locations):
1. The path specified via the --config-file CLI option
2. In the same folder as the red_oxide executable
3. `%APPDATA%/red_oxide/red_oxide.config.json` (only on Windows)
4. `$XDG_CONFIG_HOME/red_oxide/red_oxide.config.json`
5. `HOME/.config/red_oxide/red_oxide.config.json`
6. `HOME/red_oxide.config.json`

HOME is determined by these environment variables on Windows in this order:
1. `%HOME%`
2. `%USERPROFILE%`
3. `%HOMEDRIVE%\%HOMEPATH%`

HOME is determined by these environment variables on Linux in this order:
1. `$HOME`


```json
{
"api_key": "YOUR_API_KEY",
Expand Down
107 changes: 106 additions & 1 deletion src/config/config.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,117 @@
use crate::config::constants::{
CONFIG_FILE_NAME, CONFIG_PATH, HOME_ENV, PROJECT_NAME, WINDOWS_APPDATA_ENV,
WINDOWS_HOMEDRIVE_ENV, WINDOWS_HOMEPATH_ENV, WINDOWS_USERPROFILE_ENV, XDG_CONFIG_ENV,
};
use crate::config::models::RedOxideConfig;
use crate::redacted::models::ReleaseType::{Flac, Mp3320, Mp3V0};
use crate::{TranscodeCommand, ERROR};
use console::Term;
use std::env;
use std::path::PathBuf;
use tokio::fs::File;
use tokio::io::AsyncReadExt;

pub fn search_config_in_default_locations() -> anyhow::Result<Option<PathBuf>> {
let mut path;

let current_dir = env::current_dir()?;
let current_dir_config = current_dir.join(CONFIG_FILE_NAME);

if current_dir_config.exists() {
path = Some(current_dir_config);
return Ok(path);
}

if cfg!(windows) {
path = get_config_path_from_default_location_by_env(WINDOWS_APPDATA_ENV);

if let Some(path) = path {
return Ok(Some(path));
}
}

path = get_config_path_from_default_location_by_env(XDG_CONFIG_ENV);

if let Some(path) = path {
return Ok(Some(path));
}

let home_env = get_home_env();

if let Some(home) = home_env {
let mut home_config = PathBuf::from(home.clone())
.join(CONFIG_PATH)
.join(PROJECT_NAME)
.join(CONFIG_FILE_NAME);

if home_config.exists() {
path = Some(home_config);
return Ok(path);
}

home_config = PathBuf::from(home).join(CONFIG_FILE_NAME);

if home_config.exists() {
path = Some(home_config);
return Ok(path);
}
}

Ok(path)
}

fn get_config_path_from_default_location_by_env(env: &str) -> Option<PathBuf> {
let env_resolved = env::var(env).unwrap_or(String::new());

if !env_resolved.is_empty() {
let env_config_home = PathBuf::from(env_resolved)
.join(PROJECT_NAME)
.join(CONFIG_FILE_NAME);

if env_config_home.exists() {
return Some(env_config_home);
}
}

None
}

#[cfg(target_os = "windows")]
fn get_home_env() -> Option<String> {
if let Ok(home) = env::var(HOME_ENV) {
return Some(home);
}

if let Ok(user_profile) = env::var(WINDOWS_USERPROFILE_ENV) {
return Some(user_profile);
}

let home_drive = env::var(WINDOWS_HOMEDRIVE_ENV).unwrap_or(String::new());
let home_path = env::var(WINDOWS_HOMEPATH_ENV).unwrap_or(String::new());

if !home_drive.is_empty() && !home_path.is_empty() {
return Some(format!("{}\\{}", home_drive, home_path));
}

None
}

#[cfg(not(target_os = "windows"))]
fn get_home_env() -> Option<String> {
if let Ok(home) = env::var(UNIX_HOME_ENV) {
return Some(home);
}

None
}

pub async fn apply_config(cmd: &mut TranscodeCommand, term: &Term) -> anyhow::Result<()> {
if let Some(config_path) = &cmd.config_file {
let found_config = match &cmd.config_file {
None => search_config_in_default_locations()?,
Some(config_file) => Some(config_file.clone()),
};

if let Some(config_path) = found_config {
let mut file = File::open(config_path).await?;
let mut contents = vec![];
file.read_to_end(&mut contents).await?;
Expand Down
13 changes: 13 additions & 0 deletions src/config/constants.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
pub const CONFIG_FILE_NAME: &str = "red_oxide.config.json";
pub const PROJECT_NAME: &str = "red_oxide";

pub const CONFIG_PATH: &str = ".config";

pub const XDG_CONFIG_ENV: &str = "XDG_CONFIG_HOME";

pub const HOME_ENV: &str = "HOME";

pub const WINDOWS_APPDATA_ENV: &str = "APPDATA";
pub const WINDOWS_USERPROFILE_ENV: &str = "USERPROFILE";
pub const WINDOWS_HOMEDRIVE_ENV: &str = "HOMEDRIVE";
pub const WINDOWS_HOMEPATH_ENV: &str = "HOMEPATH";
1 change: 1 addition & 0 deletions src/config/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
pub mod config;
mod constants;
pub mod models;

0 comments on commit c823b08

Please sign in to comment.