Skip to content

Commit

Permalink
Avoid mutating config/saucefile contents when --show flag is active.
Browse files Browse the repository at this point in the history
  • Loading branch information
DanCardin committed Feb 9, 2021
1 parent b79a4bc commit b30ccfa
Show file tree
Hide file tree
Showing 11 changed files with 164 additions and 140 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "sauce"
version = "0.6.2"
version = "0.6.3"
authors = ["Dan Cardin <[email protected]>"]
edition = "2018"
description = "A tool for managing directory-specific state."
Expand Down
3 changes: 0 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -292,9 +292,6 @@ project) which would enable things like `sauce --as prod` or

## Planned Work

- only **print** `sauce config` command results when `--show` flag has
been used

- ability to subdivide targets by shell

i.e. allow one to specify `[alias.fish]`.
Expand Down
7 changes: 5 additions & 2 deletions src/cli/shape.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ pub struct CliOptions {
#[clap(long)]
pub autoload: bool,

/// Only **show** the intended output of the command rather than executing it.
/// For typical commands such as `sauce` and `sauce clear` this outputs the exact
/// shell output that would have executed. For mutating commands like `sauce config`
/// and `sauce set`, the change is printed but not saved.
#[clap(long)]
pub show: bool,

Expand Down Expand Up @@ -122,7 +124,8 @@ pub enum SetKinds {
/// Key-value pairs, delimited by an "=".
#[derive(Clap, Debug)]
pub struct SetVarKind {
pub values: Vec<String>,
#[clap(parse(try_from_str = crate::cli::utilities::parse_key_val))]
pub values: Vec<(String, String)>,
}

/// Key value pair, supplied as individual arguments
Expand Down
7 changes: 5 additions & 2 deletions src/cli/utilities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ where
}

/// Accept data from stdin
pub fn get_input(values: &[String]) -> Vec<String> {
pub fn get_input(values: &[(String, String)]) -> Vec<(String, String)> {
let mut result = Vec::new();
result.extend_from_slice(values);

Expand All @@ -31,7 +31,10 @@ pub fn get_input(values: &[String]) -> Vec<String> {
if let Some(b) = buffer.strip_suffix("\n") {
buffer = b.to_string();
}
result.push(buffer);

if let Ok(keyval) = parse_key_val(&buffer) {
result.push(keyval);
}
}
}

Expand Down
37 changes: 36 additions & 1 deletion src/output.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
use crate::colors::{TABLE_BLUE, TABLE_YELLOW};
use crate::toml::{ensure_section, write_document};
use crate::{
colors::{BLUE, TABLE_BLUE, TABLE_YELLOW, YELLOW},
toml::unwrap_toml_value,
};
use anyhow::Result;
use comfy_table::{Attribute, Cell, ContentArrangement, Row, Table};
use std::{
fmt::Display,
io::{stderr, stdout, Write},
ops::Deref,
path::Path,
};
use toml_edit::{Document, Item};

use ansi_term::{ANSIString, ANSIStrings};

Expand Down Expand Up @@ -175,6 +181,35 @@ impl Output {
self.err.flush()?;
Ok(())
}

pub fn write_toml<I, T>(
&mut self,
file: &Path,
document: &mut Document,
heading: &str,
values: I,
) where
I: IntoIterator<Item = (T, Item)>,
T: AsRef<str>,
{
for (name, value) in values.into_iter() {
self.notify(&[
"Setting ".into(),
BLUE.bold().paint(name.as_ref()),
" = ".into(),
YELLOW.paint(unwrap_toml_value(value.as_value().unwrap())),
]);

if !self.show {
let section = ensure_section(document, heading);
section[name.as_ref()] = value;
}
}

if !self.show {
write_document(file, document, self);
}
}
}

impl Default for Output {
Expand Down
94 changes: 23 additions & 71 deletions src/saucefile.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
use crate::settings::Settings;
use crate::toml::write_document;
use crate::{filter::FilterOptions, Context};
use crate::{settings::Settings, toml::unwrap_toml_value};
use indexmap::IndexMap;
use itertools::iproduct;
use toml_edit::Table;

use crate::toml::get_document;
use std::path::PathBuf;
use std::str::FromStr;
use toml_edit::{value, Document, Item, Value};
use toml_edit::{Document, Item, Value};

#[derive(Debug)]
pub struct Saucefile {
Expand Down Expand Up @@ -46,39 +43,6 @@ impl Saucefile {
Settings::from_document(self.path.clone(), &self.document)
}

pub fn set_var(&mut self, name: &str, raw_value: &str) {
let toml_value = Value::from_str(&raw_value).unwrap_or_else(|_| Value::from(raw_value));
let env_section = self.document.as_table_mut().entry("environment");
if env_section.is_none() {
*env_section = Item::Table(Table::new());
}
self.document["environment"][&name] = value(toml_value);
}

pub fn set_alias(&mut self, name: &str, raw_value: &str) {
let toml_value = Value::from_str(&raw_value).unwrap_or_else(|_| Value::from(raw_value));

let alias_section = self.document.as_table_mut().entry("alias");
if alias_section.is_none() {
*alias_section = Item::Table(Table::new());
}
self.document["alias"][&name] = value(toml_value);
}

pub fn set_function(&mut self, name: &str, body: &str) {
let toml_value = Value::from_str(&body).unwrap_or_else(|_| Value::from(body));

let alias_section = self.document.as_table_mut().entry("function");
if alias_section.is_none() {
*alias_section = Item::Table(Table::new());
}
self.document["function"][&name] = value(toml_value);
}

pub fn write(&mut self, context: &mut Context) {
write_document(&context.sauce_path, &self.document, &mut context.output);
}

fn section(
&mut self,
sections: &[&str],
Expand Down Expand Up @@ -142,18 +106,6 @@ impl Default for Saucefile {
}
}

fn unwrap_toml_value(value: &Value) -> String {
match value {
Value::InlineTable(_) => value.as_inline_table().unwrap().to_string(),
Value::Array(_) => value.as_array().unwrap().to_string(),
Value::String(_) => value.as_str().unwrap().to_string(),
Value::Integer(_) => value.as_integer().unwrap().to_string(),
Value::Boolean(_) => value.as_bool().unwrap().to_string(),
Value::Float(_) => value.as_float().unwrap().to_string(),
Value::DateTime(_) => value.as_date_time().unwrap().to_string(),
}
}

#[cfg(test)]
mod tests {
mod section {
Expand Down Expand Up @@ -312,15 +264,15 @@ mod tests {
assert_eq!(result, &[]);
}

#[test]
fn it_roundtrips_value() {
let mut sauce = Saucefile::default();
// #[test]
// fn it_roundtrips_value() {
// let mut sauce = Saucefile::default();

sauce.set_var("meow", "5");
let result = sauce.vars(&FilterOptions::default());
// sauce.set_var("meow", "5");
// let result = sauce.vars(&FilterOptions::default());

assert_eq!(result, vec![("meow", "5".to_string())]);
}
// assert_eq!(result, vec![("meow", "5".to_string())]);
// }
}

mod aliases {
Expand All @@ -334,15 +286,15 @@ mod tests {
assert_eq!(result, &[]);
}

#[test]
fn it_roundtrips_value() {
let mut sauce = Saucefile::default();
// #[test]
// fn it_roundtrips_value() {
// let mut sauce = Saucefile::default();

sauce.set_alias("meow", "5");
let result = sauce.aliases(&FilterOptions::default());
// sauce.set_alias("meow", "5");
// let result = sauce.aliases(&FilterOptions::default());

assert_eq!(result, vec![("meow", "5".to_string())]);
}
// assert_eq!(result, vec![("meow", "5".to_string())]);
// }
}

mod functions {
Expand All @@ -356,14 +308,14 @@ mod tests {
assert_eq!(result, &[]);
}

#[test]
fn it_roundtrips_value() {
let mut sauce = Saucefile::default();
// #[test]
// fn it_roundtrips_value() {
// let mut sauce = Saucefile::default();

sauce.set_function("meow", "5");
let result = sauce.functions(&FilterOptions::default());
// sauce.set_function("meow", "5");
// let result = sauce.functions(&FilterOptions::default());

assert_eq!(result, vec![("meow", "5".to_string())]);
}
// assert_eq!(result, vec![("meow", "5".to_string())]);
// }
}
}
16 changes: 5 additions & 11 deletions src/settings.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use crate::{
colors::{RED, YELLOW},
output::ErrorCode,
toml::write_document,
};
use anyhow::Result;
use std::{
Expand Down Expand Up @@ -84,14 +83,13 @@ impl Settings {
if settings_section.is_none() {
*settings_section = Item::Table(Table::new());
}
let settings = &mut document["settings"];

let mut values = pairs
let values = pairs
.iter()
.filter_map(|(setting, value)| match setting.as_ref() {
"autoload" | "autoload-hook" => {
if let Ok(parsed_value) = value.as_ref().parse::<Value>() {
Some((setting, toml_edit::value(parsed_value)))
Some((setting.as_ref(), toml_edit::value(parsed_value)))
} else {
output.notify_error(
ErrorCode::ParseError,
Expand All @@ -114,17 +112,13 @@ impl Settings {
None
}
})
.peekable();
.collect::<Vec<_>>();

if values.peek().is_none() {
if values.is_empty() {
return;
}

for (setting, value) in values {
settings[setting.as_ref()] = value;
}

write_document(&self.file, &document, output);
output.write_toml(&self.file, &mut document, "settings", values);
}
}

Expand Down
Loading

0 comments on commit b30ccfa

Please sign in to comment.