From 3240afccf11ade6c906fef03c6902e4d4b9990d3 Mon Sep 17 00:00:00 2001 From: Ross MacArthur Date: Sun, 25 Aug 2024 17:13:20 +0200 Subject: [PATCH] Stop defaulting to Zsh and allow unspecified shell --- README.md | 4 +- docs/README_TEMPLATE.md | 4 +- src/config/file.rs | 6 -- src/config/mod.rs | 2 +- src/config/normalize.rs | 56 ++++++++++++------- src/lock/mod.rs | 23 ++++---- src/lock/plugin.rs | 46 +++++++++++---- tests/testdata/clean/plugins.lock | 6 -- .../clean_permission_denied/plugins.lock | 6 -- .../deprecated_directories/plugins.toml | 2 + .../deprecated_get_filter/plugins.toml | 2 + .../testdata/directories_default/plugins.toml | 2 + .../directories_xdg_from_env/plugins.toml | 2 + tests/testdata/empty/plugins.lock | 6 -- .../github_bad_reinstall/plugins.toml | 2 + tests/testdata/github_bad_url/plugins.toml | 2 + tests/testdata/github_branch/plugins.toml | 2 + tests/testdata/github_https/plugins.toml | 2 + tests/testdata/github_submodule/plugins.toml | 2 + tests/testdata/github_tag/plugins.toml | 2 + tests/testdata/hooks/plugins.toml | 2 + tests/testdata/inline/plugins.toml | 2 + .../override_config_file/plugins.lock | 6 -- tests/testdata/override_data_dir/plugins.lock | 6 -- tests/testdata/profiles/plugins.toml | 2 + 25 files changed, 113 insertions(+), 84 deletions(-) diff --git a/README.md b/README.md index b3702ae9..e4f8e31a 100644 --- a/README.md +++ b/README.md @@ -20,10 +20,10 @@ - Local plugins. - Inline plugins. - Highly configurable install methods using templates. -- Shell agnostic, with sensible defaults for Zsh. +- Shell agnostic, with sensible defaults for Bash or Zsh - Super-fast plugin loading and parallel installation. See [benchmarks]. - Config file using [TOML](https://toml.io) syntax. -- Clean `~/.zshrc` or `~/.bashrc` (just add 1 line). +- Clean `~/.bashrc` or `~/.zshrc` (just add 1 line). [benchmarks]: https://github.com/rossmacarthur/zsh-plugin-manager-benchmark diff --git a/docs/README_TEMPLATE.md b/docs/README_TEMPLATE.md index 6c3299ba..25ddb195 100644 --- a/docs/README_TEMPLATE.md +++ b/docs/README_TEMPLATE.md @@ -20,10 +20,10 @@ - Local plugins. - Inline plugins. - Highly configurable install methods using templates. -- Shell agnostic, with sensible defaults for Zsh. +- Shell agnostic, with sensible defaults for Bash or Zsh - Super-fast plugin loading and parallel installation. See [benchmarks]. - Config file using [TOML](https://toml.io) syntax. -- Clean `~/.zshrc` or `~/.bashrc` (just add 1 line). +- Clean `~/.bashrc` or `~/.zshrc` (just add 1 line). [benchmarks]: https://github.com/rossmacarthur/zsh-plugin-manager-benchmark diff --git a/src/config/file.rs b/src/config/file.rs index 4ebf8d62..1196604e 100644 --- a/src/config/file.rs +++ b/src/config/file.rs @@ -175,12 +175,6 @@ impl_serialize_as_str! { GitHubRepository } // Deserialization implementations //////////////////////////////////////////////////////////////////////////////// -impl Default for Shell { - fn default() -> Self { - Self::Zsh - } -} - /// Produced when we fail to parse the shell type. #[derive(Debug, Error)] #[error("expected one of `bash` or `zsh`, got `{}`", self.0)] diff --git a/src/config/mod.rs b/src/config/mod.rs index 6e13c586..dc76ba35 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -25,7 +25,7 @@ pub use crate::config::profile::MatchesProfile; #[derive(Debug)] pub struct Config { /// What type of shell is being used. - pub shell: Shell, + pub shell: Option, /// Which files to match and use in a plugin's directory. pub matches: Option>, /// The default list of template names to apply to each matched file. diff --git a/src/config/normalize.rs b/src/config/normalize.rs index 6d89f128..4d051d88 100644 --- a/src/config/normalize.rs +++ b/src/config/normalize.rs @@ -39,8 +39,6 @@ pub fn normalize(raw_config: RawConfig, warnings: &mut Vec) -> Result) -> Result, templates: &IndexMap, warnings: &mut Vec, ) -> Result { @@ -250,14 +248,30 @@ where /// Check whether the specifed templates actually exist. fn validate_template_names( - shell: Shell, + shell: Option, apply: &Option>, templates: &IndexMap, ) -> Result<()> { if let Some(apply) = apply { for name in apply { - if !shell.default_templates().contains_key(name) && !templates.contains_key(name) { - bail!("unknown template `{name}`"); + if !templates.contains_key(name) + && !shell + .map(|s| s.default_templates().contains_key(name)) + .unwrap_or(false) + { + match shell { + Some(shell) => { + if !shell.default_templates().contains_key(name) { + bail!("unknown template `{name}`"); + } + } + None => { + bail!( + "unknown template `{name}` (help: set `shell` to use default \ + templates)" + ); + } + } } } } @@ -297,7 +311,7 @@ mod tests { let err = normalize_plugin( raw, "test".to_string(), - Shell::default(), + Some(Shell::Zsh), &IndexMap::new(), &mut Vec::new(), ) @@ -330,7 +344,7 @@ mod tests { let plugin = normalize_plugin( raw_plugin, name, - Shell::default(), + Some(Shell::Zsh), &IndexMap::new(), &mut Vec::new(), ) @@ -368,7 +382,7 @@ mod tests { let plugin = normalize_plugin( raw_plugin, name, - Shell::default(), + Some(Shell::Zsh), &IndexMap::new(), &mut Vec::new(), ) @@ -399,7 +413,7 @@ mod tests { let plugin = normalize_plugin( raw_plugin, name, - Shell::default(), + Some(Shell::Zsh), &IndexMap::new(), &mut Vec::new(), ) @@ -437,7 +451,7 @@ mod tests { let plugin = normalize_plugin( raw_plugin, name, - Shell::default(), + Some(Shell::Zsh), &IndexMap::new(), &mut Vec::new(), ) @@ -471,7 +485,7 @@ mod tests { let plugin = normalize_plugin( raw_plugin, name, - Shell::default(), + Some(Shell::Zsh), &IndexMap::new(), &mut Vec::new(), ) @@ -504,7 +518,7 @@ mod tests { let plugin = normalize_plugin( raw_plugin, name, - Shell::default(), + Some(Shell::Zsh), &IndexMap::new(), &mut Vec::new(), ) @@ -538,7 +552,7 @@ mod tests { let plugin = normalize_plugin( raw_plugin, name, - Shell::default(), + Some(Shell::Zsh), &IndexMap::new(), &mut Vec::new(), ) @@ -568,7 +582,7 @@ mod tests { let plugin = normalize_plugin( raw_plugin, name, - Shell::default(), + Some(Shell::Zsh), &IndexMap::new(), &mut Vec::new(), ) @@ -591,7 +605,7 @@ mod tests { let err = normalize_plugin( raw_plugin, "test".to_string(), - Shell::default(), + Some(Shell::Zsh), &IndexMap::new(), &mut Vec::new(), ) @@ -617,7 +631,7 @@ mod tests { let err = normalize_plugin( raw_plugin, "test".to_string(), - Shell::default(), + Some(Shell::Zsh), &IndexMap::new(), &mut Vec::new(), ) @@ -649,7 +663,7 @@ mod tests { let plugin = normalize_plugin( raw_plugin, name, - Shell::default(), + Some(Shell::Zsh), &IndexMap::new(), &mut Vec::new(), ) @@ -673,7 +687,7 @@ mod tests { let plugin = normalize_plugin( raw_plugin, name, - Shell::default(), + Some(Shell::Zsh), &IndexMap::new(), &mut Vec::new(), ) @@ -691,7 +705,7 @@ mod tests { let err = normalize_plugin( raw_plugin, "test".to_string(), - Shell::default(), + Some(Shell::Zsh), &IndexMap::new(), &mut Vec::new(), ) @@ -715,7 +729,7 @@ mod tests { let err = normalize_plugin( raw_plugin, "test".to_string(), - Shell::default(), + Some(Shell::Zsh), &IndexMap::new(), &mut Vec::new(), ) diff --git a/src/lock/mod.rs b/src/lock/mod.rs index 4381cec8..00e5f177 100644 --- a/src/lock/mod.rs +++ b/src/lock/mod.rs @@ -57,7 +57,9 @@ pub fn config(ctx: &Context, config: Config) -> Result { } = config; let templates = { - let mut map = shell.default_templates().clone(); + let mut map = shell + .map(|s| s.default_templates().clone()) + .unwrap_or_default(); for (name, template) in templates { map.insert(name, template); } @@ -88,8 +90,10 @@ pub fn config(ctx: &Context, config: Config) -> Result { let matches = matches .as_deref() - .unwrap_or_else(|| shell.default_matches()); - let apply = apply.as_ref().unwrap_or_else(|| Shell::default_apply()); + .or_else(|| shell.map(|s| s.default_matches())); + let apply = apply + .as_deref() + .or_else(|| shell.map(|s| s.default_apply())); let count = map.len(); let mut errors = Vec::new(); @@ -171,7 +175,7 @@ pub fn config(ctx: &Context, config: Config) -> Result { impl Shell { /// The default files to match on for this shell. - fn default_matches(&self) -> &[String] { + fn default_matches(&self) -> &'static [String] { static DEFAULT_MATCHES_BASH: Lazy> = Lazy::new(|| { vec_into![ "{{ name }}.plugin.bash", @@ -225,7 +229,7 @@ impl Shell { } /// The default template names to apply. - fn default_apply() -> &'static Vec { + fn default_apply(&self) -> &'static [String] { static DEFAULT_APPLY: Lazy> = Lazy::new(|| vec_into!["source"]); &DEFAULT_APPLY } @@ -316,7 +320,7 @@ mod tests { let dir = temp.path(); let ctx = Context::testing(dir); let cfg = Config { - shell: Shell::Zsh, + shell: Some(Shell::Zsh), matches: None, apply: None, templates: IndexMap::new(), @@ -327,10 +331,7 @@ mod tests { assert_eq!(locked.ctx, ctx); assert_eq!(locked.plugins, Vec::new()); - assert_eq!( - locked.templates, - Shell::default().default_templates().clone(), - ); + assert_eq!(locked.templates, Shell::Zsh.default_templates().clone(),); assert_eq!(locked.errors.len(), 0); } @@ -339,7 +340,7 @@ mod tests { let temp = tempfile::tempdir().expect("create temporary directory"); let ctx = Context::testing(temp.path()); let cfg = Config { - shell: Shell::Zsh, + shell: Some(Shell::Zsh), matches: None, apply: None, templates: IndexMap::new(), diff --git a/src/lock/plugin.rs b/src/lock/plugin.rs index 15bbeb1f..5aa35c20 100644 --- a/src/lock/plugin.rs +++ b/src/lock/plugin.rs @@ -1,7 +1,7 @@ use std::collections::BTreeMap; use std::path::{Path, PathBuf}; -use anyhow::{bail, Context as ResultExt, Result}; +use anyhow::{anyhow, bail, Context as ResultExt, Result}; use maplit::hashmap; use serde::Serialize; @@ -15,8 +15,8 @@ use crate::util::TEMPLATE_ENGINE; pub fn lock( ctx: &Context, locked_source: LockedSource, - global_matches: &[String], - global_apply: &[String], + global_matches: Option<&[String]>, + global_apply: Option<&[String]>, plugin: ExternalPlugin, ) -> Result { let ExternalPlugin { @@ -29,7 +29,14 @@ pub fn lock( profiles: _, } = plugin; - let apply = apply.unwrap_or_else(|| global_apply.to_vec()); + let apply = apply.map_or_else( + || { + global_apply.map(|a| a.to_vec()).ok_or_else(|| { + anyhow!("no global `apply` defined (help: set `shell` to use defaults)") + }) + }, + Ok, + )?; let hooks = hooks.unwrap_or(BTreeMap::new()); Ok(if let Source::Remote { .. } = source { @@ -77,13 +84,16 @@ pub fn lock( bail!("failed to find any files matching any of `{:?}`", patterns); } // Otherwise we try to figure out which files to use... - } else { + } else if let Some(global_matches) = global_matches { for g in global_matches { let pattern = render_template(g, &data)?; if match_globs(dir, &[pattern], &mut files)? { break; } } + // Else bail :( + } else { + bail!("no `uses` or global `match` defined (help: set `shell` to use defaults)"); } LockedExternalPlugin { @@ -170,7 +180,14 @@ mod tests { let locked_source = source::lock(&ctx, plugin.source.clone()).unwrap(); let clone_dir = dir.join("repos/github.com/rossmacarthur/sheldon-test"); - let locked = lock(&ctx, locked_source, &[], &["hello".into()], plugin).unwrap(); + let locked = lock( + &ctx, + locked_source, + Some(&[]), + Some(&["hello".into()]), + plugin, + ) + .unwrap(); assert_eq!(locked.name, String::from("test")); assert_eq!(locked.dir(), clone_dir); @@ -207,8 +224,8 @@ mod tests { let locked = lock( &ctx, locked_source, - &["*.plugin.zsh".to_string()], - &["hello".to_string()], + Some(&["*.plugin.zsh".to_string()]), + Some(&["hello".to_string()]), plugin, ) .unwrap(); @@ -242,8 +259,8 @@ mod tests { let locked = lock( &ctx, locked_source, - &["*doesnotexist*".to_string()], - &["PATH".to_string()], + Some(&["*doesnotexist*".to_string()]), + Some(&["PATH".to_string()]), plugin, ) .unwrap(); @@ -276,7 +293,14 @@ mod tests { let locked_source = source::lock(&ctx, plugin.source.clone()).unwrap(); let download_dir = dir.join("downloads/github.com/rossmacarthur/sheldon-test/raw/master"); - let locked = lock(&ctx, locked_source, &[], &["hello".to_string()], plugin).unwrap(); + let locked = lock( + &ctx, + locked_source, + Some(&[]), + Some(&["hello".to_string()]), + plugin, + ) + .unwrap(); assert_eq!(locked.name, String::from("test")); assert_eq!(locked.dir(), download_dir); diff --git a/tests/testdata/clean/plugins.lock b/tests/testdata/clean/plugins.lock index 6eb056f1..15916132 100644 --- a/tests/testdata/clean/plugins.lock +++ b/tests/testdata/clean/plugins.lock @@ -6,9 +6,3 @@ config_file = "/plugins.toml" plugins = [] [templates] -PATH = 'export PATH="{{ dir }}:$PATH"' -path = 'path=( "{{ dir }}" $path )' -fpath = 'fpath=( "{{ dir }}" $fpath )' -source = ''' -{{ hooks?.pre | nl }}{% for file in files %}source "{{ file }}" -{% endfor %}{{ hooks?.post | nl }}''' diff --git a/tests/testdata/clean_permission_denied/plugins.lock b/tests/testdata/clean_permission_denied/plugins.lock index 6eb056f1..15916132 100644 --- a/tests/testdata/clean_permission_denied/plugins.lock +++ b/tests/testdata/clean_permission_denied/plugins.lock @@ -6,9 +6,3 @@ config_file = "/plugins.toml" plugins = [] [templates] -PATH = 'export PATH="{{ dir }}:$PATH"' -path = 'path=( "{{ dir }}" $path )' -fpath = 'fpath=( "{{ dir }}" $fpath )' -source = ''' -{{ hooks?.pre | nl }}{% for file in files %}source "{{ file }}" -{% endfor %}{{ hooks?.post | nl }}''' diff --git a/tests/testdata/deprecated_directories/plugins.toml b/tests/testdata/deprecated_directories/plugins.toml index 308ce0e6..833dd497 100644 --- a/tests/testdata/deprecated_directories/plugins.toml +++ b/tests/testdata/deprecated_directories/plugins.toml @@ -1,3 +1,5 @@ +shell = "zsh" + [plugins.testa] remote = "https://raw.githubusercontent.com/rossmacarthur/sheldon-test/master/test.plugin.zsh" diff --git a/tests/testdata/deprecated_get_filter/plugins.toml b/tests/testdata/deprecated_get_filter/plugins.toml index e35f2635..c684a295 100644 --- a/tests/testdata/deprecated_get_filter/plugins.toml +++ b/tests/testdata/deprecated_get_filter/plugins.toml @@ -1,3 +1,5 @@ +shell = "zsh" + [templates] source = """{{ hooks | get: "pre" | nl }}{% for file in files %}source "{{ file }}"\n{% endfor %}{{ hooks | get: "post" | nl }}""" diff --git a/tests/testdata/directories_default/plugins.toml b/tests/testdata/directories_default/plugins.toml index 308ce0e6..833dd497 100644 --- a/tests/testdata/directories_default/plugins.toml +++ b/tests/testdata/directories_default/plugins.toml @@ -1,3 +1,5 @@ +shell = "zsh" + [plugins.testa] remote = "https://raw.githubusercontent.com/rossmacarthur/sheldon-test/master/test.plugin.zsh" diff --git a/tests/testdata/directories_xdg_from_env/plugins.toml b/tests/testdata/directories_xdg_from_env/plugins.toml index 308ce0e6..833dd497 100644 --- a/tests/testdata/directories_xdg_from_env/plugins.toml +++ b/tests/testdata/directories_xdg_from_env/plugins.toml @@ -1,3 +1,5 @@ +shell = "zsh" + [plugins.testa] remote = "https://raw.githubusercontent.com/rossmacarthur/sheldon-test/master/test.plugin.zsh" diff --git a/tests/testdata/empty/plugins.lock b/tests/testdata/empty/plugins.lock index 6eb056f1..15916132 100644 --- a/tests/testdata/empty/plugins.lock +++ b/tests/testdata/empty/plugins.lock @@ -6,9 +6,3 @@ config_file = "/plugins.toml" plugins = [] [templates] -PATH = 'export PATH="{{ dir }}:$PATH"' -path = 'path=( "{{ dir }}" $path )' -fpath = 'fpath=( "{{ dir }}" $fpath )' -source = ''' -{{ hooks?.pre | nl }}{% for file in files %}source "{{ file }}" -{% endfor %}{{ hooks?.post | nl }}''' diff --git a/tests/testdata/github_bad_reinstall/plugins.toml b/tests/testdata/github_bad_reinstall/plugins.toml index 9e7fd473..91e8f76b 100644 --- a/tests/testdata/github_bad_reinstall/plugins.toml +++ b/tests/testdata/github_bad_reinstall/plugins.toml @@ -1,3 +1,5 @@ +shell = "zsh" + [plugins.test] github = "rossmacarthur/sheldon-test" tag = "bad-tag" diff --git a/tests/testdata/github_bad_url/plugins.toml b/tests/testdata/github_bad_url/plugins.toml index df7584b2..b87a2c31 100644 --- a/tests/testdata/github_bad_url/plugins.toml +++ b/tests/testdata/github_bad_url/plugins.toml @@ -1,3 +1,5 @@ +shell = "zsh" + [plugins.test] github = "rossmacarthur/sheldon-test" diff --git a/tests/testdata/github_branch/plugins.toml b/tests/testdata/github_branch/plugins.toml index 1d6e85f9..a957c50f 100644 --- a/tests/testdata/github_branch/plugins.toml +++ b/tests/testdata/github_branch/plugins.toml @@ -1,3 +1,5 @@ +shell = "zsh" + [plugins.test] github = "rossmacarthur/sheldon-test" branch = "feature" diff --git a/tests/testdata/github_https/plugins.toml b/tests/testdata/github_https/plugins.toml index d52407f7..65ea0253 100644 --- a/tests/testdata/github_https/plugins.toml +++ b/tests/testdata/github_https/plugins.toml @@ -1,2 +1,4 @@ +shell = "zsh" + [plugins.test] github = "rossmacarthur/sheldon-test" diff --git a/tests/testdata/github_submodule/plugins.toml b/tests/testdata/github_submodule/plugins.toml index f098c098..bc852767 100644 --- a/tests/testdata/github_submodule/plugins.toml +++ b/tests/testdata/github_submodule/plugins.toml @@ -1,3 +1,5 @@ +shell = "zsh" + [plugins.test] github = "rossmacarthur/sheldon-test" branch = "recursive-recursive" diff --git a/tests/testdata/github_tag/plugins.toml b/tests/testdata/github_tag/plugins.toml index c6d39bcc..30ae92c3 100644 --- a/tests/testdata/github_tag/plugins.toml +++ b/tests/testdata/github_tag/plugins.toml @@ -1,3 +1,5 @@ +shell = "zsh" + [plugins.test] github = "rossmacarthur/sheldon-test" tag = "v0.1.0" diff --git a/tests/testdata/hooks/plugins.toml b/tests/testdata/hooks/plugins.toml index 5055e1a4..201c0ba1 100644 --- a/tests/testdata/hooks/plugins.toml +++ b/tests/testdata/hooks/plugins.toml @@ -1,3 +1,5 @@ +shell = "zsh" + [plugins.test] github = "rossmacarthur/sheldon-test" [plugins.test.hooks] diff --git a/tests/testdata/inline/plugins.toml b/tests/testdata/inline/plugins.toml index 87d9e191..03e31277 100644 --- a/tests/testdata/inline/plugins.toml +++ b/tests/testdata/inline/plugins.toml @@ -1,3 +1,5 @@ +shell = "zsh" + [plugins.test] github = "rossmacarthur/sheldon-test" diff --git a/tests/testdata/override_config_file/plugins.lock b/tests/testdata/override_config_file/plugins.lock index c42107c0..d1b001ee 100644 --- a/tests/testdata/override_config_file/plugins.lock +++ b/tests/testdata/override_config_file/plugins.lock @@ -6,9 +6,3 @@ config_file = "/test.toml" plugins = [] [templates] -PATH = 'export PATH="{{ dir }}:$PATH"' -path = 'path=( "{{ dir }}" $path )' -fpath = 'fpath=( "{{ dir }}" $fpath )' -source = ''' -{{ hooks?.pre | nl }}{% for file in files %}source "{{ file }}" -{% endfor %}{{ hooks?.post | nl }}''' diff --git a/tests/testdata/override_data_dir/plugins.lock b/tests/testdata/override_data_dir/plugins.lock index b0f52435..fa518e72 100644 --- a/tests/testdata/override_data_dir/plugins.lock +++ b/tests/testdata/override_data_dir/plugins.lock @@ -6,9 +6,3 @@ config_file = "/plugins.toml" plugins = [] [templates] -PATH = 'export PATH="{{ dir }}:$PATH"' -path = 'path=( "{{ dir }}" $path )' -fpath = 'fpath=( "{{ dir }}" $fpath )' -source = ''' -{{ hooks?.pre | nl }}{% for file in files %}source "{{ file }}" -{% endfor %}{{ hooks?.post | nl }}''' diff --git a/tests/testdata/profiles/plugins.toml b/tests/testdata/profiles/plugins.toml index cd88d2b3..845aa0d1 100644 --- a/tests/testdata/profiles/plugins.toml +++ b/tests/testdata/profiles/plugins.toml @@ -1,3 +1,5 @@ +shell = "zsh" + [plugins.test] github = "rossmacarthur/sheldon-test" profiles = ["p1", "p2"]