]> git.proxmox.com Git - rustc.git/blame - src/tools/tidy/src/bins.rs
New upstream version 1.64.0+dfsg1
[rustc.git] / src / tools / tidy / src / bins.rs
CommitLineData
a7813a04
XL
1//! Tidy check to ensure that there are no binaries checked into the source tree
2//! by accident.
3//!
4//! In the past we've accidentally checked in test binaries and such which add a
9fa01778
XL
5//! huge amount of bloat to the Git history, so it's good to just ensure we
6//! don't do that again.
a7813a04 7
cdc7bbd5 8pub use os_impl::*;
a7813a04 9
9fa01778 10// All files are executable on Windows, so just check on Unix.
a7813a04 11#[cfg(windows)]
cdc7bbd5
XL
12mod os_impl {
13 use std::path::Path;
14
15 pub fn check_filesystem_support(_sources: &[&Path], _output: &Path) -> bool {
16 return false;
17 }
18
19 pub fn check(_path: &Path, _bad: &mut bool) {}
20}
a7813a04
XL
21
22#[cfg(unix)]
cdc7bbd5 23mod os_impl {
a7813a04
XL
24 use std::fs;
25 use std::os::unix::prelude::*;
cdc7bbd5 26 use std::path::Path;
dfeec247 27 use std::process::{Command, Stdio};
a7813a04 28
cdc7bbd5
XL
29 enum FilesystemSupport {
30 Supported,
31 Unsupported,
32 ReadOnlyFs,
33 }
34
35 use FilesystemSupport::*;
36
29967ef6
XL
37 fn is_executable(path: &Path) -> std::io::Result<bool> {
38 Ok(path.metadata()?.mode() & 0o111 != 0)
39 }
40
cdc7bbd5
XL
41 pub fn check_filesystem_support(sources: &[&Path], output: &Path) -> bool {
42 // We want to avoid false positives on filesystems that do not support the
43 // executable bit. This occurs on some versions of Window's linux subsystem,
44 // for example.
45 //
46 // We try to create the temporary file first in the src directory, which is
47 // the preferred location as it's most likely to be on the same filesystem,
48 // and then in the output (`build`) directory if that fails. Sometimes we
49 // see the source directory mounted as read-only which means we can't
50 // readily create a file there to test.
51 //
52 // See #36706 and #74753 for context.
53
54 fn check_dir(dir: &Path) -> FilesystemSupport {
55 let path = dir.join("tidy-test-file");
56 match fs::File::create(&path) {
57 Ok(file) => {
58 let exec = is_executable(&path).unwrap_or(false);
59 std::mem::drop(file);
60 std::fs::remove_file(&path).expect("Deleted temp file");
61 // If the file is executable, then we assume that this
62 // filesystem does not track executability, so skip this check.
63 return if exec { Unsupported } else { Supported };
64 }
65 Err(e) => {
66 // If the directory is read-only or we otherwise don't have rights,
67 // just don't run this check.
68 //
69 // 30 is the "Read-only filesystem" code at least in one CI
70 // environment.
71 if e.raw_os_error() == Some(30) {
72 eprintln!("tidy: Skipping binary file check, read-only filesystem");
73 return ReadOnlyFs;
74 }
75
76 panic!("unable to create temporary file `{:?}`: {:?}", path, e);
77 }
78 };
29967ef6 79 }
29967ef6 80
cdc7bbd5
XL
81 for &source_dir in sources {
82 match check_dir(source_dir) {
83 Unsupported => return false,
84 ReadOnlyFs => {
85 return match check_dir(output) {
86 Supported => true,
87 _ => false,
88 };
89 }
90 _ => {}
91 }
9e0c209e 92 }
cdc7bbd5
XL
93
94 return true;
9e0c209e
SL
95 }
96
cdc7bbd5
XL
97 #[cfg(unix)]
98 pub fn check(path: &Path, bad: &mut bool) {
064997fb
FG
99 const ALLOWED: &[&str] = &["configure"];
100
cdc7bbd5
XL
101 crate::walk_no_read(
102 path,
064997fb
FG
103 &mut |path| {
104 crate::filter_dirs(path)
105 || path.ends_with("src/etc")
106 // This is a list of directories that we almost certainly
107 // don't need to walk. A future PR will likely want to
108 // remove these in favor of crate::walk_no_read using git
109 // ls-files to discover the paths we should check, which
110 // would naturally ignore all of these directories. It's
111 // also likely faster than walking the directory tree
112 // directly (since git is just reading from a couple files
113 // to produce the results).
114 || path.ends_with("target")
115 || path.ends_with("build")
116 || path.ends_with(".git")
117 },
cdc7bbd5
XL
118 &mut |entry| {
119 let file = entry.path();
120 let filename = file.file_name().unwrap().to_string_lossy();
121 let extensions = [".py", ".sh"];
122 if extensions.iter().any(|e| filename.ends_with(e)) {
123 return;
124 }
a7813a04 125
cdc7bbd5
XL
126 if t!(is_executable(&file), file) {
127 let rel_path = file.strip_prefix(path).unwrap();
128 let git_friendly_path = rel_path.to_str().unwrap().replace("\\", "/");
064997fb
FG
129
130 if ALLOWED.contains(&git_friendly_path.as_str()) {
131 return;
132 }
133
cdc7bbd5
XL
134 let output = Command::new("git")
135 .arg("ls-files")
136 .arg(&git_friendly_path)
137 .current_dir(path)
138 .stderr(Stdio::null())
139 .output()
140 .unwrap_or_else(|e| {
5e7ed085 141 panic!("could not run git ls-files: {e}");
cdc7bbd5
XL
142 });
143 let path_bytes = rel_path.as_os_str().as_bytes();
144 if output.status.success() && output.stdout.starts_with(path_bytes) {
145 tidy_error!(bad, "binary checked into source: {}", file.display());
146 }
dfeec247 147 }
cdc7bbd5
XL
148 },
149 )
150 }
a7813a04 151}