diff --git a/Cargo.lock b/Cargo.lock index 094cd15605..20644e20be 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1035,15 +1035,6 @@ dependencies = [ "windows-sys 0.45.0", ] -[[package]] -name = "is_executable" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa9acdc6d67b75e626ad644734e8bc6df893d9cd2a834129065d3dd6158ea9c8" -dependencies = [ - "winapi", -] - [[package]] name = "itertools" version = "0.10.5" @@ -1947,7 +1938,6 @@ dependencies = [ "ignore", "imperative", "insta", - "is_executable", "itertools", "js-sys", "libcst", diff --git a/crates/ruff/Cargo.toml b/crates/ruff/Cargo.toml index a1905e66b0..7d610d475a 100644 --- a/crates/ruff/Cargo.toml +++ b/crates/ruff/Cargo.toml @@ -57,7 +57,6 @@ titlecase = { version = "2.2.1" } toml = { workspace = true } # https://docs.rs/getrandom/0.2.7/getrandom/#webassembly-support -# For (future) wasm-pack support [target.'cfg(all(target_family = "wasm", target_os = "unknown"))'.dependencies] getrandom = { version = "0.2.7", features = ["js"] } console_error_panic_hook = { version = "0.1.7" } @@ -66,9 +65,6 @@ serde-wasm-bindgen = { version = "0.4" } js-sys = { version = "0.3.60" } wasm-bindgen = { version = "0.2.83" } -[target.'cfg(not(target_family = "wasm"))'.dependencies] -is_executable = "1.0.1" - [dev-dependencies] insta = { version = "1.19.0", features = ["yaml", "redactions"] } test-case = { version = "2.2.2" } diff --git a/crates/ruff/src/rules/flake8_executable/helpers.rs b/crates/ruff/src/rules/flake8_executable/helpers.rs index db47bcba38..26a13ec972 100644 --- a/crates/ruff/src/rules/flake8_executable/helpers.rs +++ b/crates/ruff/src/rules/flake8_executable/helpers.rs @@ -1,3 +1,8 @@ +#[cfg(target_family = "unix")] +use std::os::unix::fs::PermissionsExt; +#[cfg(target_family = "unix")] +use std::path::Path; + use once_cell::sync::Lazy; use regex::Regex; @@ -33,6 +38,17 @@ pub fn extract_shebang(line: &str) -> ShebangDirective { } } +#[cfg(target_family = "unix")] +pub fn is_executable(filepath: &Path) -> bool { + { + let Ok(metadata) = filepath.metadata() else { + return false; + }; + let permissions = metadata.permissions(); + permissions.mode() & 0o111 != 0 + } +} + #[cfg(test)] mod tests { use crate::rules::flake8_executable::helpers::{ diff --git a/crates/ruff/src/rules/flake8_executable/rules/shebang_missing.rs b/crates/ruff/src/rules/flake8_executable/rules/shebang_missing.rs index 9e478e90cc..bbeb5d32b5 100644 --- a/crates/ruff/src/rules/flake8_executable/rules/shebang_missing.rs +++ b/crates/ruff/src/rules/flake8_executable/rules/shebang_missing.rs @@ -1,12 +1,13 @@ +#![allow(unused_imports)] + use std::path::Path; -#[cfg(not(target_family = "wasm"))] -use is_executable::IsExecutable; use ruff_macros::{define_violation, derive_message_formats}; -#[cfg(not(target_family = "wasm"))] use crate::ast::types::Range; use crate::registry::Diagnostic; +#[cfg(target_family = "unix")] +use crate::rules::flake8_executable::helpers::is_executable; use crate::violation::Violation; define_violation!( @@ -20,9 +21,9 @@ impl Violation for ShebangMissingExecutableFile { } /// EXE002 -#[cfg(not(target_family = "wasm"))] +#[cfg(target_family = "unix")] pub fn shebang_missing(filepath: &Path) -> Option { - if filepath.is_executable() { + if is_executable(filepath) { let diagnostic = Diagnostic::new(ShebangMissingExecutableFile, Range::default()); Some(diagnostic) } else { @@ -30,7 +31,7 @@ pub fn shebang_missing(filepath: &Path) -> Option { } } -#[cfg(target_family = "wasm")] +#[cfg(not(target_family = "unix"))] pub fn shebang_missing(_filepath: &Path) -> Option { None } diff --git a/crates/ruff/src/rules/flake8_executable/rules/shebang_not_executable.rs b/crates/ruff/src/rules/flake8_executable/rules/shebang_not_executable.rs index de56253ef7..3f369a2523 100644 --- a/crates/ruff/src/rules/flake8_executable/rules/shebang_not_executable.rs +++ b/crates/ruff/src/rules/flake8_executable/rules/shebang_not_executable.rs @@ -1,14 +1,15 @@ +#![allow(unused_imports)] + use std::path::Path; -#[cfg(not(target_family = "wasm"))] -use is_executable::IsExecutable; -use ruff_macros::{define_violation, derive_message_formats}; -#[cfg(not(target_family = "wasm"))] use rustpython_parser::ast::Location; -#[cfg(not(target_family = "wasm"))] +use ruff_macros::{define_violation, derive_message_formats}; + use crate::ast::types::Range; use crate::registry::Diagnostic; +#[cfg(target_family = "unix")] +use crate::rules::flake8_executable::helpers::is_executable; use crate::rules::flake8_executable::helpers::ShebangDirective; use crate::violation::Violation; @@ -23,14 +24,14 @@ impl Violation for ShebangNotExecutable { } /// EXE001 -#[cfg(not(target_family = "wasm"))] +#[cfg(target_family = "unix")] pub fn shebang_not_executable( filepath: &Path, lineno: usize, shebang: &ShebangDirective, ) -> Option { if let ShebangDirective::Match(_, start, end, _) = shebang { - if filepath.is_executable() { + if is_executable(filepath) { None } else { let diagnostic = Diagnostic::new( @@ -47,7 +48,7 @@ pub fn shebang_not_executable( } } -#[cfg(target_family = "wasm")] +#[cfg(not(target_family = "unix"))] pub fn shebang_not_executable( _filepath: &Path, _lineno: usize,