Skip to content

Commit

Permalink
support for separators (multiple docs) in single yaml file
Browse files Browse the repository at this point in the history
  • Loading branch information
pasteley committed Sep 28, 2024
1 parent fdd5255 commit f5234df
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 18 deletions.
10 changes: 10 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ shadow-rs = { version = "0.35.0", default-features = false }
sysinfo = "0.31.4"
thiserror = "1.0.63"
yaml-rust = "0.4.5"
yaml-split = "0.4.0"

[dev-dependencies]
testresult = "0.4.1"
Expand Down
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,16 @@ data:

# Export photos in vCards
ABIncludePhotosInVCard: true
---
# Multiple yaml docs in single file.
description: Dock

kill: ["Dock"]

data:
# Automatically hide and show the Dock
com.apple.dock:
autohide: true
```
You may also use full paths to `.plist` files instead of domain names. This is the only way to set values in /Library/Preferences/.
Expand Down
50 changes: 32 additions & 18 deletions src/cmd/apply.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::collections::HashMap;
use std::io::{BufReader, BufRead};
use std::ffi::OsStr;
use std::fs;
use std::fs::File;
use std::os::unix::ffi::OsStrExt;

use camino::Utf8PathBuf;
Expand All @@ -9,6 +10,7 @@ use colored::Colorize;
use log::{debug, error, trace};
use serde::{Deserialize, Serialize};
use sysinfo::{Signal, System};
use yaml_split::DocumentIterator;

use crate::defaults::{write_defaults_values, MacOSDefaults};
use crate::errors::DefaultsError as E;
Expand Down Expand Up @@ -81,14 +83,30 @@ struct DefaultsConfig(HashMap<String, HashMap<String, plist::Value>>);

pub fn apply_defaults(path: &Utf8PathBuf) -> Result<bool> {
//
let s = fs::read_to_string(path).map_err(|e| E::FileRead {
let file = File::open(path).map_err(|e| E::FileRead {
path: path.to_owned(),
source: e,
})?;

trace!("Task '{path}' contents: <<<{s}>>>");
let reader = BufReader::new(file);

let config: MacOSDefaults = serde_yaml::from_str(&s).map_err(|e| E::InvalidYaml {
trace!("Processing YAML documents from file: {}", path);

let mut any_changed = false;

for doc in DocumentIterator::new(reader) {
let doc = doc.map_err(|e| E::YamlSplitError {
path: path.to_owned(),
source: e,
})?;
any_changed |= process_yaml_document(doc.as_bytes(), path)?;
}

Ok(any_changed)
}

fn process_yaml_document(doc: impl BufRead, path: &Utf8PathBuf) -> Result<bool> {
let config: MacOSDefaults = serde_yaml::from_reader(doc).map_err(|e| E::InvalidYaml {
path: path.to_owned(),
source: e,
})?;
Expand All @@ -104,26 +122,20 @@ pub fn apply_defaults(path: &Utf8PathBuf) -> Result<bool> {
println!(" {} {}", "▶".green(), description.bold().white());
}

let (passed, errors): (Vec<_>, Vec<_>) = defaults
.0
let results: Vec<_> = defaults.0
.into_iter()
.map(|(domain, prefs)| write_defaults_values(&domain, prefs, config.current_host))
.partition(Result::is_ok);

debug!("Passed: {passed:?}");
debug!("Errored: {errors:?}");
.collect();

let changed = passed.iter().flatten().any(|&value| value);
let (passed, errors): (Vec<_>, Vec<_>) = results.into_iter().partition(Result::is_ok);

let errors: Vec<_> = errors.into_iter().map(Result::unwrap_err).collect();
let passed: Vec<_> = passed.into_iter().map(Result::unwrap).collect();
let changed = passed.iter().any(|r| *r.as_ref().unwrap());

if changed && passed.into_iter().any(|r| r) {
if changed {
if let Some(kill) = config.kill {
for process in &kill {
for process in kill {
println!(" {} Restarting: {}", "✖".blue(), process.white());

kill_process_by_name(process);
kill_process_by_name(&process);
}
}
}
Expand All @@ -138,7 +150,9 @@ pub fn apply_defaults(path: &Utf8PathBuf) -> Result<bool> {

let mut errors_iter = errors.into_iter();

Err(errors_iter.next().ok_or(E::UnexpectedNone)?).wrap_err_with(|| eyre!("{:?}", errors_iter.collect::<Vec<_>>()))
let first_error = errors_iter.next().ok_or(E::UnexpectedNone)??;

Err(eyre!("{:?}", errors_iter.collect::<Vec<_>>())).wrap_err(first_error)
}

fn kill_process_by_name(name: &str) {
Expand Down
3 changes: 3 additions & 0 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,7 @@ pub enum DefaultsError {

#[error("Eyre error.")]
EyreError { source: color_eyre::Report },

#[error("failed to split YAML file {path}")]
YamlSplitError { path: Utf8PathBuf, source: yaml_split::YamlSplitError },
}

0 comments on commit f5234df

Please sign in to comment.