From ade5a15d7993dbb4aa30d6c742913f7f13e85608 Mon Sep 17 00:00:00 2001 From: Dan Cardin Date: Sun, 21 Feb 2021 10:12:17 -0500 Subject: [PATCH] feat: Describe the cascaded saucefiles being loaded. --- CHANGELOG.md | 304 ++++++++----------------------------------- Cargo.lock | 2 +- Cargo.toml | 2 +- Makefile | 2 +- src/saucefile.rs | 45 +++++-- src/shell/actions.rs | 13 +- src/shell/context.rs | 46 ++++++- tests/execute.rs | 9 +- 8 files changed, 140 insertions(+), 283 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b34694..7c8f4bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,315 +1,117 @@ # Changelog -## Overview - -- [unreleased](#unreleased) -- [`0.6.5`](#065) – _2021.02.15_ -- [`0.6.4`](#064) – _2021.02.12_ -- [`0.6.3`](#063) – _2021.02.09_ -- [`0.6.2`](#062) – _2021.02.06_ -- [`0.6.1`](#061) – _2021.02.06_ -- [`0.6.0`](#060) – _2021.02.06_ -- [`0.5.1`](#051) – _2021.02.01_ -- [`0.5.0`](#050) – _2021.01.27_ -- [`0.4.0`](#040) – _2021.01.23_ -- [`0.3.0`](#030) – _2021.01.18_ -- [`0.2.1`](#021) – _2021.01.15_ -- [`0.2.0`](#020) – _2021.01.13_ -- [`0.1.2`](#012) – _2021.01.12_ - -## _[Unreleased]_ - -_nothing new to show for… yet!_ - -## [0.6.5] - -_2021.02.15_ - -### Contributors - - -- Dan Cardin () - -### Changes - -#### Documentation - -- **Update cli help text.** ([`56ba5e1`]) - -## [0.6.4] - -_2021.02.12_ - -### Changes - -## [0.6.3] - -_2021.02.09_ - -### Changes - -## [0.6.2] - -_2021.02.06_ - -### Changes - -## [0.6.1] - -_2021.02.06_ - -### Changes - -## [0.6.0] - -_2021.02.06_ - -### Changes - -## [0.5.1] - -_2021.02.01_ - -### Changes - -## [0.5.0] - -_2021.01.27_ - -### Contributors - - -- Dan Cardin () - -### Changes - -#### Bug Fixes - -- **Incorrect ci trigger branch name.** ([`fb9dd38`]) - -## [0.4.0] - -_2021.01.23_ - -### Contributors - - -- Dan Cardin () - -### Changes - -#### Bug Fixes - -- **The addition of the autoload flag caused normal `sauce` to start failing.** ([`f8b21d7`]) - - Fix (and tests) reenables normal `sauce` behavior, and autoload behavior - only kicks in once `--autoload` is used. +### [v0.6.6](https://github.com/DanCardin/sauce/compare/v0.6.5...v0.6.6) (2021-02-21) #### Features -- **Add autoload feature and settings for zsh.** ([`2511e3c`]) - -- **Add the ability to autoload and settings to toggle it.** ([`fda3420`]) - -#### Documentation - -- **update readme to include better installation/setup instructions.** ([`f462e1a`]) +* Describe the cascaded saucefiles being loaded. 1ffa279 -#### Tests -- **Add saucefile tests.** ([`7cb1b44`]) +### [v0.6.5](https://github.com/DanCardin/sauce/compare/v0.6.4...v0.6.5) (2021-02-15) -## [0.3.0] - -_2021.01.18_ - -### Contributors +#### Features +* Add `sauce move` command. 5872f83 -- Dan Cardin () +#### Fixes -### Changes +* Add missing clear-ignore config setting for subcommend. b904035 -#### Tests -- **Add tests for filter parsing logic.** ([`b59f166`]) +### [v0.6.4](https://github.com/DanCardin/sauce/compare/v0.6.3...v0.6.4) (2021-02-12) -#### Features +#### Fixes -- **Protect ancestor saucefiles from modification.** ([`dcb86f1`]) +* escape behavior of escaped newlines. e9d7e41 - Internally store them in a separate structure to prevent them - from being accidentally updated through i.e. a bug. -- **Detect and dispatch to per-shell behavior.** ([`da2c43e`]) +### [v0.6.3](https://github.com/DanCardin/sauce/compare/v0.6.2...v0.6.3) (2021-02-09) -#### Bug Fixes -- **Avoid one of the collect calls in glob parser.** ([`1754845`]) +### [v0.6.2](https://github.com/DanCardin/sauce/compare/v0.6.1...v0.6.2) (2021-02-06) -## [0.2.1] -_2021.01.15_ +### [v0.6.1](https://github.com/DanCardin/sauce/compare/v0.6.0...v0.6.1) (2021-02-06) -### Contributors +## [v0.6.0](https://github.com/DanCardin/sauce/compare/v0.5.1...v0.6.0) (2021-02-06) -- Dan Cardin () +### Features -### Changes +* Add shell exec command. 97a473a +* Add quiet and verbose flags and update some help text. 44ffd85 -#### doc -- **Add badges to the readme.** ([`40796cc`]) +### [v0.5.1](https://github.com/DanCardin/sauce/compare/v0.5.0...v0.5.1) (2021-02-01) #### Features -- **Add CI/releases.** ([`90cd2b4`]) - -- **Add optional path to the "edit" command.** ([`7641fd8`]) +* Add options for configuring color output. d35f014 +* Propagate output to more locations and colorize most output. 9b8487f -#### Bug Fixes +#### Fixes -- **Cargo.toml license.** ([`9b1c7e4`]) +* stdin blocking on set var when there is no stdin. c22dcf9 -## [0.2.0] -_2021.01.13_ +## [v0.5.0](https://github.com/DanCardin/sauce/compare/v0.4.0...v0.5.0) (2021-01-27) -### Changes +### Features -## [0.1.2] +* Add fish support and remove autodetect. 4afc9f9 +* Add autoload functionality to bash. 8d87890 -_2021.01.12_ +### Fixes -### Contributors +* Use grcov action instead of installing it manually. 5a7ac24 +* Incorrect ci trigger branch name. fb9dd38 -- Dan Cardin () +## [v0.4.0](https://github.com/DanCardin/sauce/compare/v0.3.0...v0.4.0) (2021-01-23) -### Changes +### Features -#### Bug Fixes +* Add code coverage. eedfba6 +* Add autoload feature and settings for zsh. 2511e3c +* Add the ability to autoload and settings to toggle it. fda3420 -- **Multiline format preservation (shell quoting issue).** ([`49c1c23`]) +### Fixes -- **Switch to snailquote to properly handle double-quoting multiline strings.** ([`939a67b`]) +* The addition of the autoload flag caused normal `sauce` to start failing. f8b21d7 -[unreleased]: https://github.com/DanCardin/sauce/compare/v0.6.5...HEAD -[0.6.5]: https://github.com/DanCardin/sauce/releases/tag/v0.6.5 -[0.6.4]: https://github.com/DanCardin/sauce/releases/tag/v0.6.4 -[0.6.3]: https://github.com/DanCardin/sauce/releases/tag/v0.6.3 -[0.6.2]: https://github.com/DanCardin/sauce/releases/tag/v0.6.2 -[0.6.1]: https://github.com/DanCardin/sauce/releases/tag/v0.6.1 -[0.6.0]: https://github.com/DanCardin/sauce/releases/tag/v0.6.0 -[0.5.1]: https://github.com/DanCardin/sauce/releases/tag/v0.5.1 -[0.5.0]: https://github.com/DanCardin/sauce/releases/tag/v0.5.0 -[0.4.0]: https://github.com/DanCardin/sauce/releases/tag/v0.4.0 -[0.3.0]: https://github.com/DanCardin/sauce/releases/tag/v0.3.0 -[0.2.1]: https://github.com/DanCardin/sauce/releases/tag/v0.2.1 -[0.2.0]: https://github.com/DanCardin/sauce/releases/tag/v0.2.0 -[0.1.2]: https://github.com/DanCardin/sauce/releases/tag/v0.1.2 +## [v0.3.0](https://github.com/DanCardin/sauce/compare/v0.2.1...v0.3.0) (2021-01-18) -[`56ba5e1`]: https://github.com/DanCardin/sauce/commit/56ba5e1efa8c62864f6ab669171866aedf20ccf2 -[`fb9dd38`]: https://github.com/DanCardin/sauce/commit/fb9dd38c23d126801b63d5e193020564f6487a3d -[`f8b21d7`]: https://github.com/DanCardin/sauce/commit/f8b21d7b9500aab40a125839686593b35fc4dd13 -[`2511e3c`]: https://github.com/DanCardin/sauce/commit/2511e3ccf4eed9bc73e7a7f8c275aaaa23c14116 -[`f462e1a`]: https://github.com/DanCardin/sauce/commit/f462e1a4e32e3a16ad1f07de43e74b3be21c2781 -[`fda3420`]: https://github.com/DanCardin/sauce/commit/fda34204331d6cc362c6c0f718b762fa30c8fd7f -[`7cb1b44`]: https://github.com/DanCardin/sauce/commit/7cb1b44f41f1075a7d87ce790a9a80cacc205654 -[`b59f166`]: https://github.com/DanCardin/sauce/commit/b59f166250be6a37011a14329241d4d0628cb1fe -[`dcb86f1`]: https://github.com/DanCardin/sauce/commit/dcb86f1db357c8a90af2e21b6397626c18c3af98 -[`1754845`]: https://github.com/DanCardin/sauce/commit/1754845194994c8aa5b0c260d3fc8d31b5773fb1 -[`da2c43e`]: https://github.com/DanCardin/sauce/commit/da2c43e6b1a4bdac6cfb5d469b1827f11441afc6 -[`40796cc`]: https://github.com/DanCardin/sauce/commit/40796cccaf4a3b62831fc72425200119d9d8e7f5 -[`90cd2b4`]: https://github.com/DanCardin/sauce/commit/90cd2b4fdf9a99ba5bd05701234df7f4caf95318 -[`9b1c7e4`]: https://github.com/DanCardin/sauce/commit/9b1c7e4f17903a523f6ba19e9638bcdd7a6916fc -[`7641fd8`]: https://github.com/DanCardin/sauce/commit/7641fd8d854db072dfff41ad0b4cd2afda2c0992 -[`49c1c23`]: https://github.com/DanCardin/sauce/commit/49c1c2310048bc0472f867464bb0a9907433e476 -[`939a67b`]: https://github.com/DanCardin/sauce/commit/939a67ba13a37d081128d5ed7a28d1acfba6a647 - diff --git a/Cargo.lock b/Cargo.lock index c0cd5ec..f30a23f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -638,7 +638,7 @@ checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581" [[package]] name = "sauce" -version = "0.6.5" +version = "0.6.6" dependencies = [ "ansi_term 0.12.1", "anyhow", diff --git a/Cargo.toml b/Cargo.toml index 4c1c9f2..837c3b3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sauce" -version = "0.6.5" +version = "0.6.6" authors = ["Dan Cardin "] edition = "2018" description = "A tool for managing directory-specific state." diff --git a/Makefile b/Makefile index 6b63f78..76514e3 100644 --- a/Makefile +++ b/Makefile @@ -15,4 +15,4 @@ format: cargo fmt changelog: - jilu | sponge CHANGELOG.md + convco changelog > CHANGELOG.md diff --git a/src/saucefile.rs b/src/saucefile.rs index 8253c8a..55e75cb 100644 --- a/src/saucefile.rs +++ b/src/saucefile.rs @@ -9,8 +9,8 @@ use toml_edit::{Document, Item, Value}; #[derive(Debug)] pub struct Saucefile { - pub path: PathBuf, - pub ancestors: Vec, + pub path: Option, + pub ancestors: Vec<(PathBuf, Document)>, pub document: Document, } @@ -20,7 +20,11 @@ impl Saucefile { T: IntoIterator, { let mut base_sf = Self { - path: path.to_path_buf(), + path: if path.is_file() { + Some(path.to_path_buf()) + } else { + None + }, ..Default::default() }; @@ -33,7 +37,7 @@ impl Saucefile { let document = get_document(&path, output); if paths.peek().is_some() { - base_sf.ancestors.push(document) + base_sf.ancestors.push((path, document)); } else { base_sf.document = document; } @@ -42,17 +46,36 @@ impl Saucefile { } pub fn settings(&self) -> Settings { - Settings::from_document(self.path.clone(), &self.document) + if let Some(path) = &self.path { + Settings::from_document(path.clone(), &self.document) + } else { + Settings::default() + } + } + + fn ancestors(&self) -> impl Iterator { + let ancestors = self.ancestors.iter().map(|(p, d)| (p, d)); + + let mut tail = Vec::new(); + if let Some(path) = &self.path { + tail.push((path, &self.document)); + } + ancestors.chain(tail) + } + + pub fn paths(&self) -> impl Iterator { + self.ancestors().map(|(p, _)| p) + } + + fn documents(&self) -> impl Iterator { + self.ancestors().map(|(_, d)| d) } fn section(&self, sections: &[&str], filter_options: &FilterOptions) -> Vec<(&str, String)> { let tag = filter_options.as_.unwrap_or("default"); - let documents = self.ancestors.iter().chain(vec![&self.document]); - - iproduct!(documents, sections) - .map(|(document, section)| document[section].as_table()) - .filter_map(|x| x) + iproduct!(self.documents(), sections) + .filter_map(|(document, section)| document[section].as_table()) .flat_map(|vars| vars.iter()) .filter(|(key, _)| { filter_options.glob_match(sections, key) @@ -97,7 +120,7 @@ impl Saucefile { impl Default for Saucefile { fn default() -> Self { Self { - path: PathBuf::new(), + path: Some(PathBuf::new()), document: Document::new(), ancestors: Vec::new(), } diff --git a/src/shell/actions.rs b/src/shell/actions.rs index b1914e2..a6fb6f2 100644 --- a/src/shell/actions.rs +++ b/src/shell/actions.rs @@ -175,7 +175,7 @@ pub fn execute( global_settings: &Settings, filter_options: &FilterOptions, autoload_flag: bool, -) { +) -> bool { // The `autoload_flag` indicates that the "context" of the execution is happening during // an autoload, i.e. `cd`. It's the precondition for whether we need to check the settings to // see whether we **actually** should perform the autoload, or exit early. @@ -185,7 +185,7 @@ pub fn execute( .resolve_precedence(&global_settings) .autoload { - return; + return false; } output.output(render_items(saucefile.vars(&filter_options), |k, v| { @@ -198,11 +198,7 @@ pub fn execute( saucefile.functions(&filter_options), |k, v| shell.set_function(k, v), )); - - output.notify(&[ - BLUE.bold().paint("Sourced "), - YELLOW.paint(saucefile.path.to_string_lossy()), - ]); + true } fn render_items(items: Vec<(&str, String)>, mut format_row: F) -> String @@ -410,7 +406,7 @@ mod tests { #[test] fn it_executes() { let shell = TestShell {}; - let (out, err, mut output) = setup(); + let (out, _, mut output) = setup(); let mut saucefile = Saucefile::default(); let section = ensure_section(&mut saucefile.document, "environment"); @@ -435,7 +431,6 @@ mod tests { out.value(), "export var=varvalue;\n\nalias alias=aliasvalue;\n\nfunction fn=fnvalue;\n\n" ); - assert_eq!(err.value(), "Sourced \n"); } #[test] diff --git a/src/shell/context.rs b/src/shell/context.rs index e0d4aa3..66d09e6 100644 --- a/src/shell/context.rs +++ b/src/shell/context.rs @@ -1,11 +1,13 @@ +use ansi_term::ANSIString; use anyhow::Result; +use itertools::Itertools; use path_absolutize::Absolutize; use std::path::PathBuf; use std::{env, path::Path}; use toml_edit::Item; use crate::{ - colors::RED, + colors::{BLUE, RED, YELLOW}, filter::FilterOptions, output::{ErrorCode, Output}, saucefile::Saucefile, @@ -179,14 +181,24 @@ impl<'a> Context<'a> { pub fn execute(&mut self, shell_kind: &dyn Shell, autoload: bool, output: &mut Output) { self.load_saucefile(output); self.load_settings(output); - actions::execute( + + let saucefile = self.saucefile(); + let sauced = actions::execute( output, shell_kind, - self.saucefile(), + saucefile, self.settings(), &self.filter_options, autoload, ); + + if !sauced { + // We may sometimes opt to *not* execute, i.e. certain autoload scenarios. + return; + } + + let message = materialize_path_message("Sauced", &self.data_dir, saucefile.paths()); + output.notify(&message); } pub fn cascade_paths(&self) -> impl Iterator { @@ -262,6 +274,34 @@ impl<'a> Context<'a> { } } +fn materialize_path_message<'a>( + action: &'a str, + data_dir: &'a Path, + paths: impl Iterator, +) -> Vec> { + let parent_dir = &data_dir.parent().unwrap_or(data_dir); + let paths = paths + .filter_map(|p| p.strip_prefix(parent_dir).ok()) + .map(|p| p.to_string_lossy()) + .join(", "); + + let mut result = Vec::new(); + + if paths.is_empty() { + result.push(RED.bold().paint("No saucefiles exist")); + return result; + } + + result.push(BLUE.bold().paint(format!("{} ", action))); + result.push(YELLOW.paint(paths.clone())); + + if !paths.starts_with(data_dir.to_string_lossy().as_ref()) { + result.push(BLUE.bold().paint(" from ")); + result.push(YELLOW.paint(data_dir.to_string_lossy())); + } + result +} + impl<'a> Default for Context<'a> { fn default() -> Self { Self { diff --git a/tests/execute.rs b/tests/execute.rs index 42d442e..de624ce 100644 --- a/tests/execute.rs +++ b/tests/execute.rs @@ -17,10 +17,7 @@ fn it_works_when_no_saucefile_exists() { let shell_kind = Zsh {}; context.execute(&shell_kind, false, &mut output); assert_eq!(out.value(), ""); - assert_eq!( - err.value(), - format!("Sourced {}\n", context.sauce_path.to_string_lossy()) - ); + assert_eq!(err.value(), format!("No saucefiles exist\n")); } #[test] @@ -45,7 +42,7 @@ function meow { ); assert_eq!( err.value(), - format!("Sourced {}\n", context.sauce_path.to_string_lossy()) + format!("Sauced {}\n", context.sauce_path.to_string_lossy()) ); } @@ -76,7 +73,7 @@ fn it_loads_with_autoload_flag_when_autoload_is_enabled() { context.execute(&shell_kind, true, &mut output); assert_eq!( err.value(), - format!("Sourced {}\n", context.sauce_path.to_string_lossy()) + format!("Sauced {}\n", context.sauce_path.to_string_lossy()) ); }