mod archives;
mod build_tools;
mod containers;
mod filesystem;
mod git;
mod network;
mod package_managers;
mod predicates;
mod shells;
mod system;
mod text_processing;
use nu_protocol::ast::ExternalArgument;
pub use predicates::extract_external_arg_text;
use super::CommonEffect;
use crate::context::LintContext;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ExternEffect {
CommonEffect(CommonEffect),
NoDataInStdout,
ModifiesFileSystem,
WritesDataToStdErr,
ModifiesNetworkState,
SlowStreamingOutput,
}
pub type CommandEffects = (
&'static str,
&'static [(ExternEffect, predicates::Predicate)],
);
const ALL_COMMANDS: &[&[CommandEffects]] = &[
filesystem::COMMANDS,
archives::COMMANDS,
text_processing::COMMANDS,
network::COMMANDS,
git::COMMANDS,
build_tools::COMMANDS,
containers::COMMANDS,
package_managers::COMMANDS,
system::COMMANDS,
shells::COMMANDS,
];
pub fn has_external_side_effect(
command_name: &str,
side_effect: ExternEffect,
context: &LintContext,
args: &[ExternalArgument],
) -> bool {
log::trace!("Checking external side effect '{side_effect:?}' for command '{command_name}'");
for commands in ALL_COMMANDS {
if let Some((_, effects)) = commands.iter().find(|(name, _)| *name == command_name)
&& let Some((_, predicate)) = effects.iter().find(|(effect, _)| *effect == side_effect)
{
log::trace!("Checking external predicate for side effect '{side_effect:?}'");
let result = predicate(context, args);
if result {
log::trace!("External predicate matched for side effect '{side_effect:?}'");
}
return result;
}
}
log::trace!(
"No matching external side effect '{side_effect:?}' found for command '{command_name}'"
);
false
}
pub fn has_external_recursive_flag(args: &[ExternalArgument], context: &LintContext) -> bool {
args.iter().any(|arg| {
let arg_text = extract_external_arg_text(arg, context);
matches!(
arg_text,
text if text.contains("-r")
|| text.contains("--recursive")
|| text.contains("-rf")
|| text.contains("-fr")
|| text.contains("--force")
)
})
}