From bdf5a0ac904548e2277e87204878c4660e63288d Mon Sep 17 00:00:00 2001 From: Igor Date: Fri, 11 Oct 2024 03:45:08 +0400 Subject: [PATCH] refactor: replace lazy_static with std::sync::LazyLock --- Cargo.lock | 3 - brush-core/Cargo.toml | 1 - brush-core/src/builtins/declare.rs | 10 +- brush-core/src/keywords.rs | 9 +- brush-core/src/namedoptions.rs | 1436 +++++++++++++------------- brush-core/src/shell.rs | 9 +- brush-shell/Cargo.toml | 1 - brush-shell/src/main.rs | 8 +- fuzz/Cargo.toml | 1 - fuzz/fuzz_targets/fuzz_arithmetic.rs | 22 +- fuzz/fuzz_targets/fuzz_parse.rs | 21 +- 11 files changed, 763 insertions(+), 758 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9c914c9e..75013ad3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -265,7 +265,6 @@ dependencies = [ "hostname", "indexmap", "itertools 0.13.0", - "lazy_static", "nix 0.29.0", "os_pipe", "pprof", @@ -286,7 +285,6 @@ dependencies = [ "assert_cmd", "brush-core", "brush-parser", - "lazy_static", "libfuzzer-sys", "tokio", ] @@ -371,7 +369,6 @@ dependencies = [ "human-panic", "indent", "junit-report", - "lazy_static", "pathdiff", "regex", "serde", diff --git a/brush-core/Cargo.toml b/brush-core/Cargo.toml index 7531a41e..cca1997d 100644 --- a/brush-core/Cargo.toml +++ b/brush-core/Cargo.toml @@ -27,7 +27,6 @@ fancy-regex = "0.13.0" futures = "0.3.31" indexmap = "2.6.0" itertools = "0.13.0" -lazy_static = "1.5.0" rand = "0.8.5" thiserror = "1.0.64" tracing = "0.1.40" diff --git a/brush-core/src/builtins/declare.rs b/brush-core/src/builtins/declare.rs index 407af940..ddd09c00 100644 --- a/brush-core/src/builtins/declare.rs +++ b/brush-core/src/builtins/declare.rs @@ -1,6 +1,6 @@ use clap::Parser; use itertools::Itertools; -use std::io::Write; +use std::{io::Write, sync::LazyLock}; use crate::{ builtins, commands, @@ -322,10 +322,10 @@ impl DeclareCommand { // We need to handle the case of someone invoking `declare array[index]`. // In such case, we ignore the index and treat it as a declaration of // the array. - lazy_static::lazy_static! { - static ref ARRAY_AND_INDEX_RE: fancy_regex::Regex = - fancy_regex::Regex::new(r"^(.*?)\[(.*?)\]$").unwrap(); - } + static ARRAY_AND_INDEX_RE: LazyLock = + LazyLock::new(|| { + fancy_regex::Regex::new(r"^(.*?)\[(.*?)\]$").unwrap() + }); if let Some(captures) = ARRAY_AND_INDEX_RE.captures(s)? { name = captures.get(1).unwrap().as_str().to_owned(); assigned_index = Some(captures.get(2).unwrap().as_str().to_owned()); diff --git a/brush-core/src/keywords.rs b/brush-core/src/keywords.rs index 07681af1..479037ca 100644 --- a/brush-core/src/keywords.rs +++ b/brush-core/src/keywords.rs @@ -1,4 +1,5 @@ use std::collections::HashSet; +use std::sync::LazyLock; use crate::Shell; @@ -31,10 +32,10 @@ fn get_keywords(sh_mode_only: bool) -> HashSet { keywords } -lazy_static::lazy_static! { - pub(crate) static ref SH_MODE_KEYWORDS: HashSet = get_keywords(true); - pub(crate) static ref KEYWORDS: HashSet = get_keywords(false); -} +pub(crate) static SH_MODE_KEYWORDS: LazyLock> = + LazyLock::new(|| get_keywords(true)); +pub(crate) static KEYWORDS: LazyLock> = + LazyLock::new(|| get_keywords(false)); pub fn is_keyword(shell: &Shell, name: &str) -> bool { if shell.options.sh_mode { diff --git a/brush-core/src/namedoptions.rs b/brush-core/src/namedoptions.rs index 8f87adbb..0d3b577d 100644 --- a/brush-core/src/namedoptions.rs +++ b/brush-core/src/namedoptions.rs @@ -1,5 +1,5 @@ -use lazy_static::lazy_static; use std::collections::HashMap; +use std::sync::LazyLock; use crate::options::RuntimeOptions; @@ -17,716 +17,724 @@ impl OptionDefinition { } } -lazy_static! { - pub(crate) static ref SET_OPTIONS: HashMap = HashMap::from([ - ( - 'a', - OptionDefinition::new( - |options| options.export_variables_on_modification, - |options, value| options.export_variables_on_modification = value - ) - ), - ( - 'b', - OptionDefinition::new( - |options| options.notify_job_termination_immediately, - |options, value| options.notify_job_termination_immediately = value - ) - ), - ( - 'e', - OptionDefinition::new( - |options| options.exit_on_nonzero_command_exit, - |options, value| options.exit_on_nonzero_command_exit = value - ) - ), - ( - 'f', - OptionDefinition::new( - |options| options.disable_filename_globbing, - |options, value| options.disable_filename_globbing = value - ) - ), - ( - 'h', - OptionDefinition::new( - |options| options.remember_command_locations, - |options, value| options.remember_command_locations = value - ) - ), - ( - 'i', - OptionDefinition::new( - |options| options.interactive, - |options, value| options.interactive = value - ) - ), - ( - 'k', - OptionDefinition::new( - |options| options.place_all_assignment_args_in_command_env, - |options, value| options.place_all_assignment_args_in_command_env = value - ) - ), - ( - 'm', - OptionDefinition::new( - |options| options.enable_job_control, - |options, value| options.enable_job_control = value - ) - ), - ( - 'n', - OptionDefinition::new( - |options| options.do_not_execute_commands, - |options, value| options.do_not_execute_commands = value - ) - ), - ( - 'p', - OptionDefinition::new( - |options| options.real_effective_uid_mismatch, - |options, value| options.real_effective_uid_mismatch = value - ) - ), - ( - 't', - OptionDefinition::new( - |options| options.exit_after_one_command, - |options, value| options.exit_after_one_command = value - ) - ), - ( - 'u', - OptionDefinition::new( - |options| options.treat_unset_variables_as_error, - |options, value| options.treat_unset_variables_as_error = value - ) - ), - ( - 'v', - OptionDefinition::new( - |options| options.print_shell_input_lines, - |options, value| options.print_shell_input_lines = value - ) - ), - ( - 'x', - OptionDefinition::new( - |options| options.print_commands_and_arguments, - |options, value| options.print_commands_and_arguments = value - ) - ), - ( - 'B', - OptionDefinition::new( - |options| options.perform_brace_expansion, - |options, value| options.perform_brace_expansion = value - ) - ), - ( - 'C', - OptionDefinition::new( - |options| options.disallow_overwriting_regular_files_via_output_redirection, - |options, value| options - .disallow_overwriting_regular_files_via_output_redirection = - value - ) - ), - ( - 'E', - OptionDefinition::new( - |options| options.shell_functions_inherit_err_trap, - |options, value| options.shell_functions_inherit_err_trap = value - ) - ), - ( - 'H', - OptionDefinition::new( - |options| options.enable_bang_style_history_substitution, - |options, value| options.enable_bang_style_history_substitution = value - ) - ), - ( - 'P', - OptionDefinition::new( - |options| options.do_not_resolve_symlinks_when_changing_dir, - |options, value| options.do_not_resolve_symlinks_when_changing_dir = value - ) - ), - ( - 'T', - OptionDefinition::new( - |options| options.shell_functions_inherit_debug_and_return_traps, - |options, value| options.shell_functions_inherit_debug_and_return_traps = value - ) - ), - ( - 's', - OptionDefinition::new( - |options| options.read_commands_from_stdin, - |options, value| options.read_commands_from_stdin = value - ) - ), - ]); - pub(crate) static ref SET_O_OPTIONS: HashMap<&'static str, OptionDefinition> = HashMap::from([ - ( - "allexport", - OptionDefinition::new( - |options| options.export_variables_on_modification, - |options, value| options.export_variables_on_modification = value - ) - ), - ( - "braceexpand", - OptionDefinition::new( - |options| options.perform_brace_expansion, - |options, value| options.perform_brace_expansion = value - ) - ), - ( - "emacs", - OptionDefinition::new( - |options| options.emacs_mode, - |options, value| options.emacs_mode = value - ) - ), - ( - "errexit", - OptionDefinition::new( - |options| options.exit_on_nonzero_command_exit, - |options, value| options.exit_on_nonzero_command_exit = value - ) - ), - ( - "errtrace", - OptionDefinition::new( - |options| options.shell_functions_inherit_err_trap, - |options, value| options.shell_functions_inherit_err_trap = value - ) - ), - ( - "functrace", - OptionDefinition::new( - |options| options.shell_functions_inherit_debug_and_return_traps, - |options, value| options.shell_functions_inherit_debug_and_return_traps = value - ) - ), - ( - "hashall", - OptionDefinition::new( - |options| options.remember_command_locations, - |options, value| options.remember_command_locations = value - ) - ), - ( - "histexpand", - OptionDefinition::new( - |options| options.enable_bang_style_history_substitution, - |options, value| options.enable_bang_style_history_substitution = value - ) - ), - ( - "history", - OptionDefinition::new( - |options| options.enable_command_history, - |options, value| options.enable_command_history = value - ) - ), - ( - "ignoreeof", - OptionDefinition::new( - |options| options.ignore_eof, - |options, value| options.ignore_eof = value - ) - ), - ( - "interactive-comments", - OptionDefinition::new( - |options| options.interactive_comments, - |options, value| options.interactive_comments = value - ) - ), - ( - "keyword", - OptionDefinition::new( - |options| options.place_all_assignment_args_in_command_env, - |options, value| options.place_all_assignment_args_in_command_env = value - ) - ), - ( - "monitor", - OptionDefinition::new( - |options| options.enable_job_control, - |options, value| options.enable_job_control = value - ) - ), - ( - "noclobber", - OptionDefinition::new( - |options| options.disallow_overwriting_regular_files_via_output_redirection, - |options, value| options - .disallow_overwriting_regular_files_via_output_redirection = - value - ) - ), - ( - "noexec", - OptionDefinition::new( - |options| options.do_not_execute_commands, - |options, value| options.do_not_execute_commands = value - ) - ), - ( - "noglob", - OptionDefinition::new( - |options| options.disable_filename_globbing, - |options, value| options.disable_filename_globbing = value - ) - ), - ("nolog", OptionDefinition::new(|_| false, |_, _| ())), - ( - "notify", - OptionDefinition::new( - |options| options.notify_job_termination_immediately, - |options, value| options.notify_job_termination_immediately = value - ) - ), - ( - "nounset", - OptionDefinition::new( - |options| options.treat_unset_variables_as_error, - |options, value| options.treat_unset_variables_as_error = value - ) - ), - ( - "onecmd", - OptionDefinition::new( - |options| options.exit_after_one_command, - |options, value| options.exit_after_one_command = value - ) - ), - ( - "physical", - OptionDefinition::new( - |options| options.do_not_resolve_symlinks_when_changing_dir, - |options, value| options.do_not_resolve_symlinks_when_changing_dir = value - ) - ), - ( - "pipefail", - OptionDefinition::new( - |options| options.return_first_failure_from_pipeline, - |options, value| options.return_first_failure_from_pipeline = value - ) - ), - ( - "posix", - OptionDefinition::new( - |options| options.posix_mode, - |options, value| options.posix_mode = value - ) - ), - ( - "privileged", - OptionDefinition::new( - |options| options.real_effective_uid_mismatch, - |options, value| options.real_effective_uid_mismatch = value - ) - ), - ( - "verbose", - OptionDefinition::new( - |options| options.print_shell_input_lines, - |options, value| options.print_shell_input_lines = value - ) - ), - ( - "vi", - OptionDefinition::new( - |options| options.vi_mode, - |options, value| options.vi_mode = value - ) - ), - ( - "xtrace", - OptionDefinition::new( - |options| options.print_commands_and_arguments, - |options, value| options.print_commands_and_arguments = value - ) - ), - ]); - pub(crate) static ref SHOPT_OPTIONS: HashMap<&'static str, OptionDefinition> = HashMap::from([ - ( - "autocd", - OptionDefinition::new( - |options| options.auto_cd, - |options, value| options.auto_cd = value - ) - ), - ( - "assoc_expand_once", - OptionDefinition::new( - |options| options.assoc_expand_once, - |options, value| options.assoc_expand_once = value - ) - ), - ( - "cdable_vars", - OptionDefinition::new( - |options| options.cdable_vars, - |options, value| options.cdable_vars = value - ) - ), - ( - "cdspell", - OptionDefinition::new( - |options| options.cd_autocorrect_spelling, - |options, value| options.cd_autocorrect_spelling = value - ) - ), - ( - "checkhash", - OptionDefinition::new( - |options| options.check_hashtable_before_command_exec, - |options, value| options.check_hashtable_before_command_exec = value - ) - ), - ( - "checkjobs", - OptionDefinition::new( - |options| options.check_jobs_before_exit, - |options, value| options.check_jobs_before_exit = value - ) - ), - ( - "checkwinsize", - OptionDefinition::new( - |options| options.check_window_size_after_external_commands, - |options, value| options.check_window_size_after_external_commands = value - ) - ), - ( - "cmdhist", - OptionDefinition::new( - |options| options.save_multiline_cmds_in_history, - |options, value| options.save_multiline_cmds_in_history = value - ) - ), - ( - "compat31", - OptionDefinition::new( - |options| options.compat31, - |options, value| options.compat31 = value - ) - ), - ( - "compat32", - OptionDefinition::new( - |options| options.compat32, - |options, value| options.compat32 = value - ) - ), - ( - "compat40", - OptionDefinition::new( - |options| options.compat40, - |options, value| options.compat40 = value - ) - ), - ( - "compat41", - OptionDefinition::new( - |options| options.compat41, - |options, value| options.compat41 = value - ) - ), - ( - "compat42", - OptionDefinition::new( - |options| options.compat42, - |options, value| options.compat42 = value - ) - ), - ( - "compat43", - OptionDefinition::new( - |options| options.compat43, - |options, value| options.compat43 = value - ) - ), - ( - "compat44", - OptionDefinition::new( - |options| options.compat44, - |options, value| options.compat44 = value - ) - ), - ( - "complete_fullquote", - OptionDefinition::new( - |options| options.quote_all_metachars_in_completion, - |options, value| options.quote_all_metachars_in_completion = value - ) - ), - ( - "direxpand", - OptionDefinition::new( - |options| options.expand_dir_names_on_completion, - |options, value| options.expand_dir_names_on_completion = value - ) - ), - ( - "dirspell", - OptionDefinition::new( - |options| options.autocorrect_dir_spelling_on_completion, - |options, value| options.autocorrect_dir_spelling_on_completion = value - ) - ), - ( - "dotglob", - OptionDefinition::new( - |options| options.glob_matches_dotfiles, - |options, value| options.glob_matches_dotfiles = value - ) - ), - ( - "execfail", - OptionDefinition::new( - |options| options.exit_on_exec_fail, - |options, value| options.exit_on_exec_fail = value - ) - ), - ( - "expand_aliases", - OptionDefinition::new( - |options| options.expand_aliases, - |options, value| options.expand_aliases = value - ) - ), - ( - "extdebug", - OptionDefinition::new( - |options| options.enable_debugger, - |options, value| options.enable_debugger = value - ) - ), - ( - "extglob", - OptionDefinition::new( - |options| options.extended_globbing, - |options, value| options.extended_globbing = value - ) - ), - ( - "extquote", - OptionDefinition::new( - |options| options.extquote, - |options, value| options.extquote = value - ) - ), - ( - "failglob", - OptionDefinition::new( - |options| options.fail_expansion_on_globs_without_match, - |options, value| options.fail_expansion_on_globs_without_match = value - ) - ), - ( - "force_fignore", - OptionDefinition::new( - |options| options.force_fignore, - |options, value| options.force_fignore = value - ) - ), - ( - "globasciiranges", - OptionDefinition::new( - |options| options.glob_ranges_use_c_locale, - |options, value| options.glob_ranges_use_c_locale = value - ) - ), - ( - "globstar", - OptionDefinition::new( - |options| options.enable_star_star_glob, - |options, value| options.enable_star_star_glob = value - ) - ), - ( - "gnu_errfmt", - OptionDefinition::new( - |options| options.errors_in_gnu_format, - |options, value| options.errors_in_gnu_format = value - ) - ), - ( - "histappend", - OptionDefinition::new( - |options| options.append_to_history_file, - |options, value| options.append_to_history_file = value - ) - ), - ( - "histreedit", - OptionDefinition::new( - |options| options.allow_reedit_failed_history_subst, - |options, value| options.allow_reedit_failed_history_subst = value - ) - ), - ( - "histverify", - OptionDefinition::new( - |options| options.allow_modifying_history_substitution, - |options, value| options.allow_modifying_history_substitution = value - ) - ), - ( - "hostcomplete", - OptionDefinition::new( - |options| options.enable_hostname_completion, - |options, value| options.enable_hostname_completion = value - ) - ), - ( - "huponexit", - OptionDefinition::new( - |options| options.send_sighup_to_all_jobs_on_exit, - |options, value| options.send_sighup_to_all_jobs_on_exit = value - ) - ), - ( - "inherit_errexit", - OptionDefinition::new( - |options| options.command_subst_inherits_errexit, - |options, value| options.command_subst_inherits_errexit = value - ) - ), - ( - "interactive_comments", - OptionDefinition::new( - |options| options.interactive_comments, - |options, value| options.interactive_comments = value - ) - ), - ( - "lastpipe", - OptionDefinition::new( - |options| options.run_last_pipeline_cmd_in_current_shell, - |options, value| options.run_last_pipeline_cmd_in_current_shell = value - ) - ), - ( - "lithist", - OptionDefinition::new( - |options| options.embed_newlines_in_multiline_cmds_in_history, - |options, value| options.embed_newlines_in_multiline_cmds_in_history = value - ) - ), - ( - "localvar_inherit", - OptionDefinition::new( - |options| options.local_vars_inherit_value_and_attrs, - |options, value| options.local_vars_inherit_value_and_attrs = value - ) - ), - ( - "localvar_unset", - OptionDefinition::new( - |options| options.localvar_unset, - |options, value| options.localvar_unset = value - ) - ), - ( - "login_shell", - OptionDefinition::new( - |options| options.login_shell, - |options, value| options.login_shell = value - ) - ), - ( - "mailwarn", - OptionDefinition::new( - |options| options.mail_warn, - |options, value| options.mail_warn = value - ) - ), - ( - "no_empty_cmd_completion", - OptionDefinition::new( - |options| options.no_empty_cmd_completion, - |options, value| options.no_empty_cmd_completion = value - ) - ), - ( - "nocaseglob", - OptionDefinition::new( - |options| options.case_insensitive_pathname_expansion, - |options, value| options.case_insensitive_pathname_expansion = value - ) - ), - ( - "nocasematch", - OptionDefinition::new( - |options| options.case_insensitive_conditionals, - |options, value| options.case_insensitive_conditionals = value - ) - ), - ( - "nullglob", - OptionDefinition::new( - |options| options.expand_non_matching_patterns_to_null, - |options, value| options.expand_non_matching_patterns_to_null = value - ) - ), - ( - "progcomp", - OptionDefinition::new( - |options| options.programmable_completion, - |options, value| options.programmable_completion = value - ) - ), - ( - "progcomp_alias", - OptionDefinition::new( - |options| options.programmable_completion_alias, - |options, value| options.programmable_completion_alias = value - ) - ), - ( - "promptvars", - OptionDefinition::new( - |options| options.expand_prompt_strings, - |options, value| options.expand_prompt_strings = value - ) - ), - ( - "restricted_shell", - OptionDefinition::new( - |options| options.restricted_shell, - |options, value| options.restricted_shell = value - ) - ), - ( - "shift_verbose", - OptionDefinition::new( - |options| options.shift_verbose, - |options, value| options.shift_verbose = value - ) - ), - ( - "sourcepath", - OptionDefinition::new( - |options| options.source_builtin_searches_path, - |options, value| options.source_builtin_searches_path = value - ) - ), - ( - "xpg_echo", - OptionDefinition::new( - |options| options.echo_builtin_expands_escape_sequences, - |options, value| options.echo_builtin_expands_escape_sequences = value - ) - ), - ]); -} +pub(crate) static SET_OPTIONS: LazyLock> = + LazyLock::new(|| { + HashMap::from([ + ( + 'a', + OptionDefinition::new( + |options| options.export_variables_on_modification, + |options, value| options.export_variables_on_modification = value, + ), + ), + ( + 'b', + OptionDefinition::new( + |options| options.notify_job_termination_immediately, + |options, value| options.notify_job_termination_immediately = value, + ), + ), + ( + 'e', + OptionDefinition::new( + |options| options.exit_on_nonzero_command_exit, + |options, value| options.exit_on_nonzero_command_exit = value, + ), + ), + ( + 'f', + OptionDefinition::new( + |options| options.disable_filename_globbing, + |options, value| options.disable_filename_globbing = value, + ), + ), + ( + 'h', + OptionDefinition::new( + |options| options.remember_command_locations, + |options, value| options.remember_command_locations = value, + ), + ), + ( + 'i', + OptionDefinition::new( + |options| options.interactive, + |options, value| options.interactive = value, + ), + ), + ( + 'k', + OptionDefinition::new( + |options| options.place_all_assignment_args_in_command_env, + |options, value| options.place_all_assignment_args_in_command_env = value, + ), + ), + ( + 'm', + OptionDefinition::new( + |options| options.enable_job_control, + |options, value| options.enable_job_control = value, + ), + ), + ( + 'n', + OptionDefinition::new( + |options| options.do_not_execute_commands, + |options, value| options.do_not_execute_commands = value, + ), + ), + ( + 'p', + OptionDefinition::new( + |options| options.real_effective_uid_mismatch, + |options, value| options.real_effective_uid_mismatch = value, + ), + ), + ( + 't', + OptionDefinition::new( + |options| options.exit_after_one_command, + |options, value| options.exit_after_one_command = value, + ), + ), + ( + 'u', + OptionDefinition::new( + |options| options.treat_unset_variables_as_error, + |options, value| options.treat_unset_variables_as_error = value, + ), + ), + ( + 'v', + OptionDefinition::new( + |options| options.print_shell_input_lines, + |options, value| options.print_shell_input_lines = value, + ), + ), + ( + 'x', + OptionDefinition::new( + |options| options.print_commands_and_arguments, + |options, value| options.print_commands_and_arguments = value, + ), + ), + ( + 'B', + OptionDefinition::new( + |options| options.perform_brace_expansion, + |options, value| options.perform_brace_expansion = value, + ), + ), + ( + 'C', + OptionDefinition::new( + |options| options.disallow_overwriting_regular_files_via_output_redirection, + |options, value| { + options.disallow_overwriting_regular_files_via_output_redirection = value + }, + ), + ), + ( + 'E', + OptionDefinition::new( + |options| options.shell_functions_inherit_err_trap, + |options, value| options.shell_functions_inherit_err_trap = value, + ), + ), + ( + 'H', + OptionDefinition::new( + |options| options.enable_bang_style_history_substitution, + |options, value| options.enable_bang_style_history_substitution = value, + ), + ), + ( + 'P', + OptionDefinition::new( + |options| options.do_not_resolve_symlinks_when_changing_dir, + |options, value| options.do_not_resolve_symlinks_when_changing_dir = value, + ), + ), + ( + 'T', + OptionDefinition::new( + |options| options.shell_functions_inherit_debug_and_return_traps, + |options, value| options.shell_functions_inherit_debug_and_return_traps = value, + ), + ), + ( + 's', + OptionDefinition::new( + |options| options.read_commands_from_stdin, + |options, value| options.read_commands_from_stdin = value, + ), + ), + ]) + }); + +pub(crate) static SET_O_OPTIONS: LazyLock> = + LazyLock::new(|| { + HashMap::from([ + ( + "allexport", + OptionDefinition::new( + |options| options.export_variables_on_modification, + |options, value| options.export_variables_on_modification = value, + ), + ), + ( + "braceexpand", + OptionDefinition::new( + |options| options.perform_brace_expansion, + |options, value| options.perform_brace_expansion = value, + ), + ), + ( + "emacs", + OptionDefinition::new( + |options| options.emacs_mode, + |options, value| options.emacs_mode = value, + ), + ), + ( + "errexit", + OptionDefinition::new( + |options| options.exit_on_nonzero_command_exit, + |options, value| options.exit_on_nonzero_command_exit = value, + ), + ), + ( + "errtrace", + OptionDefinition::new( + |options| options.shell_functions_inherit_err_trap, + |options, value| options.shell_functions_inherit_err_trap = value, + ), + ), + ( + "functrace", + OptionDefinition::new( + |options| options.shell_functions_inherit_debug_and_return_traps, + |options, value| options.shell_functions_inherit_debug_and_return_traps = value, + ), + ), + ( + "hashall", + OptionDefinition::new( + |options| options.remember_command_locations, + |options, value| options.remember_command_locations = value, + ), + ), + ( + "histexpand", + OptionDefinition::new( + |options| options.enable_bang_style_history_substitution, + |options, value| options.enable_bang_style_history_substitution = value, + ), + ), + ( + "history", + OptionDefinition::new( + |options| options.enable_command_history, + |options, value| options.enable_command_history = value, + ), + ), + ( + "ignoreeof", + OptionDefinition::new( + |options| options.ignore_eof, + |options, value| options.ignore_eof = value, + ), + ), + ( + "interactive-comments", + OptionDefinition::new( + |options| options.interactive_comments, + |options, value| options.interactive_comments = value, + ), + ), + ( + "keyword", + OptionDefinition::new( + |options| options.place_all_assignment_args_in_command_env, + |options, value| options.place_all_assignment_args_in_command_env = value, + ), + ), + ( + "monitor", + OptionDefinition::new( + |options| options.enable_job_control, + |options, value| options.enable_job_control = value, + ), + ), + ( + "noclobber", + OptionDefinition::new( + |options| options.disallow_overwriting_regular_files_via_output_redirection, + |options, value| { + options.disallow_overwriting_regular_files_via_output_redirection = value + }, + ), + ), + ( + "noexec", + OptionDefinition::new( + |options| options.do_not_execute_commands, + |options, value| options.do_not_execute_commands = value, + ), + ), + ( + "noglob", + OptionDefinition::new( + |options| options.disable_filename_globbing, + |options, value| options.disable_filename_globbing = value, + ), + ), + ("nolog", OptionDefinition::new(|_| false, |_, _| ())), + ( + "notify", + OptionDefinition::new( + |options| options.notify_job_termination_immediately, + |options, value| options.notify_job_termination_immediately = value, + ), + ), + ( + "nounset", + OptionDefinition::new( + |options| options.treat_unset_variables_as_error, + |options, value| options.treat_unset_variables_as_error = value, + ), + ), + ( + "onecmd", + OptionDefinition::new( + |options| options.exit_after_one_command, + |options, value| options.exit_after_one_command = value, + ), + ), + ( + "physical", + OptionDefinition::new( + |options| options.do_not_resolve_symlinks_when_changing_dir, + |options, value| options.do_not_resolve_symlinks_when_changing_dir = value, + ), + ), + ( + "pipefail", + OptionDefinition::new( + |options| options.return_first_failure_from_pipeline, + |options, value| options.return_first_failure_from_pipeline = value, + ), + ), + ( + "posix", + OptionDefinition::new( + |options| options.posix_mode, + |options, value| options.posix_mode = value, + ), + ), + ( + "privileged", + OptionDefinition::new( + |options| options.real_effective_uid_mismatch, + |options, value| options.real_effective_uid_mismatch = value, + ), + ), + ( + "verbose", + OptionDefinition::new( + |options| options.print_shell_input_lines, + |options, value| options.print_shell_input_lines = value, + ), + ), + ( + "vi", + OptionDefinition::new( + |options| options.vi_mode, + |options, value| options.vi_mode = value, + ), + ), + ( + "xtrace", + OptionDefinition::new( + |options| options.print_commands_and_arguments, + |options, value| options.print_commands_and_arguments = value, + ), + ), + ]) + }); +pub(crate) static SHOPT_OPTIONS: LazyLock> = + LazyLock::new(|| { + HashMap::from([ + ( + "autocd", + OptionDefinition::new( + |options| options.auto_cd, + |options, value| options.auto_cd = value, + ), + ), + ( + "assoc_expand_once", + OptionDefinition::new( + |options| options.assoc_expand_once, + |options, value| options.assoc_expand_once = value, + ), + ), + ( + "cdable_vars", + OptionDefinition::new( + |options| options.cdable_vars, + |options, value| options.cdable_vars = value, + ), + ), + ( + "cdspell", + OptionDefinition::new( + |options| options.cd_autocorrect_spelling, + |options, value| options.cd_autocorrect_spelling = value, + ), + ), + ( + "checkhash", + OptionDefinition::new( + |options| options.check_hashtable_before_command_exec, + |options, value| options.check_hashtable_before_command_exec = value, + ), + ), + ( + "checkjobs", + OptionDefinition::new( + |options| options.check_jobs_before_exit, + |options, value| options.check_jobs_before_exit = value, + ), + ), + ( + "checkwinsize", + OptionDefinition::new( + |options| options.check_window_size_after_external_commands, + |options, value| options.check_window_size_after_external_commands = value, + ), + ), + ( + "cmdhist", + OptionDefinition::new( + |options| options.save_multiline_cmds_in_history, + |options, value| options.save_multiline_cmds_in_history = value, + ), + ), + ( + "compat31", + OptionDefinition::new( + |options| options.compat31, + |options, value| options.compat31 = value, + ), + ), + ( + "compat32", + OptionDefinition::new( + |options| options.compat32, + |options, value| options.compat32 = value, + ), + ), + ( + "compat40", + OptionDefinition::new( + |options| options.compat40, + |options, value| options.compat40 = value, + ), + ), + ( + "compat41", + OptionDefinition::new( + |options| options.compat41, + |options, value| options.compat41 = value, + ), + ), + ( + "compat42", + OptionDefinition::new( + |options| options.compat42, + |options, value| options.compat42 = value, + ), + ), + ( + "compat43", + OptionDefinition::new( + |options| options.compat43, + |options, value| options.compat43 = value, + ), + ), + ( + "compat44", + OptionDefinition::new( + |options| options.compat44, + |options, value| options.compat44 = value, + ), + ), + ( + "complete_fullquote", + OptionDefinition::new( + |options| options.quote_all_metachars_in_completion, + |options, value| options.quote_all_metachars_in_completion = value, + ), + ), + ( + "direxpand", + OptionDefinition::new( + |options| options.expand_dir_names_on_completion, + |options, value| options.expand_dir_names_on_completion = value, + ), + ), + ( + "dirspell", + OptionDefinition::new( + |options| options.autocorrect_dir_spelling_on_completion, + |options, value| options.autocorrect_dir_spelling_on_completion = value, + ), + ), + ( + "dotglob", + OptionDefinition::new( + |options| options.glob_matches_dotfiles, + |options, value| options.glob_matches_dotfiles = value, + ), + ), + ( + "execfail", + OptionDefinition::new( + |options| options.exit_on_exec_fail, + |options, value| options.exit_on_exec_fail = value, + ), + ), + ( + "expand_aliases", + OptionDefinition::new( + |options| options.expand_aliases, + |options, value| options.expand_aliases = value, + ), + ), + ( + "extdebug", + OptionDefinition::new( + |options| options.enable_debugger, + |options, value| options.enable_debugger = value, + ), + ), + ( + "extglob", + OptionDefinition::new( + |options| options.extended_globbing, + |options, value| options.extended_globbing = value, + ), + ), + ( + "extquote", + OptionDefinition::new( + |options| options.extquote, + |options, value| options.extquote = value, + ), + ), + ( + "failglob", + OptionDefinition::new( + |options| options.fail_expansion_on_globs_without_match, + |options, value| options.fail_expansion_on_globs_without_match = value, + ), + ), + ( + "force_fignore", + OptionDefinition::new( + |options| options.force_fignore, + |options, value| options.force_fignore = value, + ), + ), + ( + "globasciiranges", + OptionDefinition::new( + |options| options.glob_ranges_use_c_locale, + |options, value| options.glob_ranges_use_c_locale = value, + ), + ), + ( + "globstar", + OptionDefinition::new( + |options| options.enable_star_star_glob, + |options, value| options.enable_star_star_glob = value, + ), + ), + ( + "gnu_errfmt", + OptionDefinition::new( + |options| options.errors_in_gnu_format, + |options, value| options.errors_in_gnu_format = value, + ), + ), + ( + "histappend", + OptionDefinition::new( + |options| options.append_to_history_file, + |options, value| options.append_to_history_file = value, + ), + ), + ( + "histreedit", + OptionDefinition::new( + |options| options.allow_reedit_failed_history_subst, + |options, value| options.allow_reedit_failed_history_subst = value, + ), + ), + ( + "histverify", + OptionDefinition::new( + |options| options.allow_modifying_history_substitution, + |options, value| options.allow_modifying_history_substitution = value, + ), + ), + ( + "hostcomplete", + OptionDefinition::new( + |options| options.enable_hostname_completion, + |options, value| options.enable_hostname_completion = value, + ), + ), + ( + "huponexit", + OptionDefinition::new( + |options| options.send_sighup_to_all_jobs_on_exit, + |options, value| options.send_sighup_to_all_jobs_on_exit = value, + ), + ), + ( + "inherit_errexit", + OptionDefinition::new( + |options| options.command_subst_inherits_errexit, + |options, value| options.command_subst_inherits_errexit = value, + ), + ), + ( + "interactive_comments", + OptionDefinition::new( + |options| options.interactive_comments, + |options, value| options.interactive_comments = value, + ), + ), + ( + "lastpipe", + OptionDefinition::new( + |options| options.run_last_pipeline_cmd_in_current_shell, + |options, value| options.run_last_pipeline_cmd_in_current_shell = value, + ), + ), + ( + "lithist", + OptionDefinition::new( + |options| options.embed_newlines_in_multiline_cmds_in_history, + |options, value| options.embed_newlines_in_multiline_cmds_in_history = value, + ), + ), + ( + "localvar_inherit", + OptionDefinition::new( + |options| options.local_vars_inherit_value_and_attrs, + |options, value| options.local_vars_inherit_value_and_attrs = value, + ), + ), + ( + "localvar_unset", + OptionDefinition::new( + |options| options.localvar_unset, + |options, value| options.localvar_unset = value, + ), + ), + ( + "login_shell", + OptionDefinition::new( + |options| options.login_shell, + |options, value| options.login_shell = value, + ), + ), + ( + "mailwarn", + OptionDefinition::new( + |options| options.mail_warn, + |options, value| options.mail_warn = value, + ), + ), + ( + "no_empty_cmd_completion", + OptionDefinition::new( + |options| options.no_empty_cmd_completion, + |options, value| options.no_empty_cmd_completion = value, + ), + ), + ( + "nocaseglob", + OptionDefinition::new( + |options| options.case_insensitive_pathname_expansion, + |options, value| options.case_insensitive_pathname_expansion = value, + ), + ), + ( + "nocasematch", + OptionDefinition::new( + |options| options.case_insensitive_conditionals, + |options, value| options.case_insensitive_conditionals = value, + ), + ), + ( + "nullglob", + OptionDefinition::new( + |options| options.expand_non_matching_patterns_to_null, + |options, value| options.expand_non_matching_patterns_to_null = value, + ), + ), + ( + "progcomp", + OptionDefinition::new( + |options| options.programmable_completion, + |options, value| options.programmable_completion = value, + ), + ), + ( + "progcomp_alias", + OptionDefinition::new( + |options| options.programmable_completion_alias, + |options, value| options.programmable_completion_alias = value, + ), + ), + ( + "promptvars", + OptionDefinition::new( + |options| options.expand_prompt_strings, + |options, value| options.expand_prompt_strings = value, + ), + ), + ( + "restricted_shell", + OptionDefinition::new( + |options| options.restricted_shell, + |options, value| options.restricted_shell = value, + ), + ), + ( + "shift_verbose", + OptionDefinition::new( + |options| options.shift_verbose, + |options, value| options.shift_verbose = value, + ), + ), + ( + "sourcepath", + OptionDefinition::new( + |options| options.source_builtin_searches_path, + |options, value| options.source_builtin_searches_path = value, + ), + ), + ( + "xpg_echo", + OptionDefinition::new( + |options| options.echo_builtin_expands_escape_sequences, + |options, value| options.echo_builtin_expands_escape_sequences = value, + ), + ), + ]) + }); diff --git a/brush-core/src/shell.rs b/brush-core/src/shell.rs index 3190bed0..cd414757 100644 --- a/brush-core/src/shell.rs +++ b/brush-core/src/shell.rs @@ -156,11 +156,10 @@ pub struct FunctionCall { function_definition: Arc, } -lazy_static::lazy_static! { - // NOTE: We have difficulty with xterm escape sequences going through rustyline; - // so we compile a regex that can be used to strip them out. - static ref PROMPT_XTERM_ESCAPE_SEQ_REGEX: fancy_regex::Regex = fancy_regex::Regex::new("\x1b][0-2];[^\x07]*\x07").unwrap(); -} +// NOTE: We have difficulty with xterm escape sequences going through rustyline; +// so we compile a regex that can be used to strip them out. +static PROMPT_XTERM_ESCAPE_SEQ_REGEX: std::sync::LazyLock = + std::sync::LazyLock::new(|| fancy_regex::Regex::new("\x1b][0-2];[^\x07]*\x07").unwrap()); impl Shell { /// Returns a new shell instance created with the given options. diff --git a/brush-shell/Cargo.toml b/brush-shell/Cargo.toml index 5adad28a..6c6d0092 100644 --- a/brush-shell/Cargo.toml +++ b/brush-shell/Cargo.toml @@ -42,7 +42,6 @@ cfg-if = "1.0.0" clap = { version = "4.5.17", features = ["derive", "wrap_help"] } const_format = "0.2.33" git-version = "0.3.9" -lazy_static = "1.5.0" tracing = "0.1.40" tracing-subscriber = "0.3.18" human-panic = "2.0.1" diff --git a/brush-shell/src/main.rs b/brush-shell/src/main.rs index e003c7bd..113417a3 100644 --- a/brush-shell/src/main.rs +++ b/brush-shell/src/main.rs @@ -10,12 +10,12 @@ mod shell_factory; use crate::args::{CommandLineArgs, InputBackend}; use brush_interactive::InteractiveShell; +use std::sync::LazyLock; use std::{path::Path, sync::Arc}; -lazy_static::lazy_static! { - static ref TRACE_EVENT_CONFIG: Arc>> = - Arc::new(tokio::sync::Mutex::new(None)); -} +static TRACE_EVENT_CONFIG: LazyLock< + Arc>>, +> = LazyLock::new(|| Arc::new(tokio::sync::Mutex::new(None))); // WARN: this implementation shadows `clap::Parser::parse_from` one so it must be defined // after the `use clap::Parser` diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index d3360fd6..19f1fa75 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -18,7 +18,6 @@ cargo-fuzz = true [dependencies] anyhow = "1.0.89" assert_cmd = "2.0.15" -lazy_static = "1.5.0" libfuzzer-sys = "0.4" tokio = { version = "1.40.0", features = ["rt"] } diff --git a/fuzz/fuzz_targets/fuzz_arithmetic.rs b/fuzz/fuzz_targets/fuzz_arithmetic.rs index 1930b837..33cd76ab 100644 --- a/fuzz/fuzz_targets/fuzz_arithmetic.rs +++ b/fuzz/fuzz_targets/fuzz_arithmetic.rs @@ -1,20 +1,22 @@ #![no_main] +use std::sync::LazyLock; + use anyhow::Result; use brush_parser::ast; use libfuzzer_sys::fuzz_target; -lazy_static::lazy_static! { - static ref TOKIO_RT: tokio::runtime::Runtime = tokio::runtime::Runtime::new().unwrap(); - static ref SHELL_TEMPLATE: brush_core::Shell = { - let options = brush_core::CreateOptions { - no_profile: true, - no_rc: true, - ..Default::default() - }; - TOKIO_RT.block_on(brush_core::Shell::new(&options)).unwrap() +static TOKIO_RT: LazyLock = + LazyLock::new(|| tokio::runtime::Runtime::new().unwrap()); + +static SHELL_TEMPLATE: LazyLock = LazyLock::new(|| { + let options = brush_core::CreateOptions { + no_profile: true, + no_rc: true, + ..Default::default() }; -} + TOKIO_RT.block_on(brush_core::Shell::new(&options)).unwrap() +}); async fn eval_arithmetic_async( mut shell: brush_core::Shell, diff --git a/fuzz/fuzz_targets/fuzz_parse.rs b/fuzz/fuzz_targets/fuzz_parse.rs index 3f83ceba..927f0710 100644 --- a/fuzz/fuzz_targets/fuzz_parse.rs +++ b/fuzz/fuzz_targets/fuzz_parse.rs @@ -2,18 +2,19 @@ use anyhow::Result; use libfuzzer_sys::fuzz_target; +use std::sync::LazyLock; -lazy_static::lazy_static! { - static ref TOKIO_RT: tokio::runtime::Runtime = tokio::runtime::Runtime::new().unwrap(); - static ref SHELL_TEMPLATE: brush_core::Shell = { - let options = brush_core::CreateOptions { - no_profile: true, - no_rc: true, - ..Default::default() - }; - TOKIO_RT.block_on(brush_core::Shell::new(&options)).unwrap() +static TOKIO_RT: LazyLock = + LazyLock::new(|| tokio::runtime::Runtime::new().unwrap()); + +static SHELL_TEMPLATE: LazyLock = LazyLock::new(|| { + let options = brush_core::CreateOptions { + no_profile: true, + no_rc: true, + ..Default::default() }; -} + TOKIO_RT.block_on(brush_core::Shell::new(&options)).unwrap() +}); async fn parse_async(shell: brush_core::Shell, input: String) -> Result<()> { //