annotate rust/hg-core/src/checkexec.rs @ 52664:f5091286b10c

packaging: modernize (compat PEP 517) with less distutils and setup.py calls - setup.py: less distutils imports and setuptools required distutils is deprecated and one should import commands from setuptools to support modern workflows depending on PEP 517 and 518. Moreover, for Python >=3.12, distutils comes from setuptools. It corresponds to old and unmaintain code that do not support PEP 517. The PEP 517 frontends (pip, build, pipx, PDM, UV, etc.) are responsible for creating a venv just for the build. The build dependencies (currently only setuptools) are specified in the pyproject.toml file. Therefore, there is no reason to support building without setuptools. Calling directly setup.py is deprecated and we have to use a PEP 517 frontend. For this commit we use pip with venv. - run-tests.py: install with pip instead of direct call of setup.py Mercurial is then built in an isolated environment. - Makefile: use venv+pip instead of setup.py
author paugier <pierre.augier@univ-grenoble-alpes.fr>
date Wed, 08 Jan 2025 05:07:00 +0100
parents 66e34bc44280
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
49894
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
1 use std::fs;
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
2 use std::io;
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
3 use std::os::unix::fs::{MetadataExt, PermissionsExt};
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
4 use std::path::Path;
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
5
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
6 const EXECFLAGS: u32 = 0o111;
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
7
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
8 fn is_executable(path: impl AsRef<Path>) -> Result<bool, io::Error> {
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
9 let metadata = fs::metadata(path)?;
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
10 let mode = metadata.mode();
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
11 Ok(mode & EXECFLAGS != 0)
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
12 }
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
13
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
14 fn make_executable(path: impl AsRef<Path>) -> Result<(), io::Error> {
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
15 let mode = fs::metadata(path.as_ref())?.mode();
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
16 fs::set_permissions(
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
17 path,
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
18 fs::Permissions::from_mode((mode & 0o777) | EXECFLAGS),
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
19 )?;
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
20 Ok(())
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
21 }
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
22
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
23 fn copy_mode(
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
24 src: impl AsRef<Path>,
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
25 dst: impl AsRef<Path>,
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
26 ) -> Result<(), io::Error> {
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
27 let mode = match fs::symlink_metadata(src) {
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
28 Ok(metadata) => metadata.mode(),
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
29 Err(e) if e.kind() == io::ErrorKind::NotFound =>
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
30 // copymode in python has a more complicated handling of FileNotFound
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
31 // error, which we don't need because all it does is applying
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
32 // umask, which the OS already does when we mkdir.
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
33 {
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
34 return Ok(())
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
35 }
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
36 Err(e) => return Err(e),
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
37 };
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
38 fs::set_permissions(dst, fs::Permissions::from_mode(mode))?;
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
39 Ok(())
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
40 }
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
41
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
42 fn check_exec_impl(path: impl AsRef<Path>) -> Result<bool, io::Error> {
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
43 let basedir = path.as_ref().join(".hg");
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
44 let cachedir = basedir.join("wcache");
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
45 let storedir = basedir.join("store");
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
46
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
47 if !cachedir.exists() {
49895
07792fd1837f doc: add a few comments
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49894
diff changeset
48 // we want to create the 'cache' directory, not the '.hg' one.
07792fd1837f doc: add a few comments
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49894
diff changeset
49 // Automatically creating '.hg' directory could silently spawn
07792fd1837f doc: add a few comments
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49894
diff changeset
50 // invalid Mercurial repositories. That seems like a bad idea.
49894
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
51 fs::create_dir(&cachedir)
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
52 .and_then(|()| {
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
53 if storedir.exists() {
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
54 copy_mode(&storedir, &cachedir)
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
55 } else {
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
56 copy_mode(&basedir, &cachedir)
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
57 }
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
58 })
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
59 .ok();
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
60 }
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
61
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
62 let leave_file: bool;
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
63 let checkdir: &Path;
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
64 let checkisexec = cachedir.join("checkisexec");
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
65 let checknoexec = cachedir.join("checknoexec");
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
66 if cachedir.is_dir() {
49895
07792fd1837f doc: add a few comments
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49894
diff changeset
67 // Check if both files already exist in cache and have correct
07792fd1837f doc: add a few comments
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49894
diff changeset
68 // permissions. if so, we assume that permissions work.
07792fd1837f doc: add a few comments
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49894
diff changeset
69 // If not, we delete the files and try again.
49894
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
70 match is_executable(&checkisexec) {
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
71 Err(e) if e.kind() == io::ErrorKind::NotFound => (),
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
72 Err(e) => return Err(e),
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
73 Ok(is_exec) => {
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
74 if is_exec {
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
75 let noexec_is_exec = match is_executable(&checknoexec) {
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
76 Err(e) if e.kind() == io::ErrorKind::NotFound => {
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
77 fs::write(&checknoexec, "")?;
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
78 is_executable(&checknoexec)?
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
79 }
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
80 Err(e) => return Err(e),
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
81 Ok(exec) => exec,
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
82 };
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
83 if !noexec_is_exec {
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
84 // check-exec is exec and check-no-exec is not exec
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
85 return Ok(true);
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
86 }
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
87 fs::remove_file(&checknoexec)?;
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
88 }
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
89 fs::remove_file(&checkisexec)?;
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
90 }
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
91 }
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
92 checkdir = &cachedir;
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
93 leave_file = true;
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
94 } else {
49895
07792fd1837f doc: add a few comments
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49894
diff changeset
95 // no cache directory (probably because .hg doesn't exist):
07792fd1837f doc: add a few comments
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 49894
diff changeset
96 // check directly in `path` and don't leave the temp file behind
49894
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
97 checkdir = path.as_ref();
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
98 leave_file = false;
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
99 };
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
100
52525
66e34bc44280 rhg: set the expected temp file permissions (0o666 minus umask)
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50413
diff changeset
101 let tmp_file = tempfile::Builder::new()
66e34bc44280 rhg: set the expected temp file permissions (0o666 minus umask)
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50413
diff changeset
102 .permissions(std::fs::Permissions::from_mode(0o666))
66e34bc44280 rhg: set the expected temp file permissions (0o666 minus umask)
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50413
diff changeset
103 .tempfile_in(checkdir)?;
66e34bc44280 rhg: set the expected temp file permissions (0o666 minus umask)
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents: 50413
diff changeset
104
49894
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
105 if !is_executable(tmp_file.path())? {
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
106 make_executable(tmp_file.path())?;
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
107 if is_executable(tmp_file.path())? {
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
108 if leave_file {
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
109 tmp_file.persist(checkisexec).ok();
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
110 }
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
111 return Ok(true);
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
112 }
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
113 }
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
114
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
115 Ok(false)
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
116 }
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
117
50413
e2c8b30ab4e7 rustdoc: wording for checkexec
Georges Racinet <georges.racinet@octobus.net>
parents: 50412
diff changeset
118 /// This function is a Rust rewrite of the `checkexec` function from
e2c8b30ab4e7 rustdoc: wording for checkexec
Georges Racinet <georges.racinet@octobus.net>
parents: 50412
diff changeset
119 /// `posix.py`.
e2c8b30ab4e7 rustdoc: wording for checkexec
Georges Racinet <georges.racinet@octobus.net>
parents: 50412
diff changeset
120 ///
e2c8b30ab4e7 rustdoc: wording for checkexec
Georges Racinet <georges.racinet@octobus.net>
parents: 50412
diff changeset
121 /// Returns `true` if the filesystem supports execute permissions.
49894
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
122 pub fn check_exec(path: impl AsRef<Path>) -> bool {
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
123 check_exec_impl(path).unwrap_or(false)
678588b01af1 rhg: implement checkexec to support weird filesystems
Arseniy Alekseyev <aalekseyev@janestreet.com>
parents:
diff changeset
124 }