Auto merge of #117644 - cuviper:beta-next, r=cuviper
[beta] backports - ensure the parent path's existence on `x install` #116349 - Remove `cfg_match` from the prelude #117162 - improve and fix `x install` #117383 - Update to LLVM 17.0.4 #117436 r? cuviper
This commit is contained in:
commit
efc300e546
4 changed files with 125 additions and 115 deletions
|
|
@ -290,6 +290,9 @@ pub mod assert_matches {
|
|||
pub use crate::macros::{assert_matches, debug_assert_matches};
|
||||
}
|
||||
|
||||
#[unstable(feature = "cfg_match", issue = "115585")]
|
||||
pub use crate::macros::cfg_match;
|
||||
|
||||
#[macro_use]
|
||||
mod internal_macros;
|
||||
|
||||
|
|
|
|||
|
|
@ -168,6 +168,94 @@ pub macro assert_matches {
|
|||
},
|
||||
}
|
||||
|
||||
/// A macro for defining `#[cfg]` match-like statements.
|
||||
///
|
||||
/// It is similar to the `if/elif` C preprocessor macro by allowing definition of a cascade of
|
||||
/// `#[cfg]` cases, emitting the implementation which matches first.
|
||||
///
|
||||
/// This allows you to conveniently provide a long list `#[cfg]`'d blocks of code
|
||||
/// without having to rewrite each clause multiple times.
|
||||
///
|
||||
/// Trailing `_` wildcard match arms are **optional** and they indicate a fallback branch when
|
||||
/// all previous declarations do not evaluate to true.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(cfg_match)]
|
||||
///
|
||||
/// cfg_match! {
|
||||
/// cfg(unix) => {
|
||||
/// fn foo() { /* unix specific functionality */ }
|
||||
/// }
|
||||
/// cfg(target_pointer_width = "32") => {
|
||||
/// fn foo() { /* non-unix, 32-bit functionality */ }
|
||||
/// }
|
||||
/// _ => {
|
||||
/// fn foo() { /* fallback implementation */ }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[unstable(feature = "cfg_match", issue = "115585")]
|
||||
#[rustc_diagnostic_item = "cfg_match"]
|
||||
pub macro cfg_match {
|
||||
// with a final wildcard
|
||||
(
|
||||
$(cfg($initial_meta:meta) => { $($initial_tokens:item)* })+
|
||||
_ => { $($extra_tokens:item)* }
|
||||
) => {
|
||||
cfg_match! {
|
||||
@__items ();
|
||||
$((($initial_meta) ($($initial_tokens)*)),)+
|
||||
(() ($($extra_tokens)*)),
|
||||
}
|
||||
},
|
||||
|
||||
// without a final wildcard
|
||||
(
|
||||
$(cfg($extra_meta:meta) => { $($extra_tokens:item)* })*
|
||||
) => {
|
||||
cfg_match! {
|
||||
@__items ();
|
||||
$((($extra_meta) ($($extra_tokens)*)),)*
|
||||
}
|
||||
},
|
||||
|
||||
// Internal and recursive macro to emit all the items
|
||||
//
|
||||
// Collects all the previous cfgs in a list at the beginning, so they can be
|
||||
// negated. After the semicolon is all the remaining items.
|
||||
(@__items ($($_:meta,)*);) => {},
|
||||
(
|
||||
@__items ($($no:meta,)*);
|
||||
(($($yes:meta)?) ($($tokens:item)*)),
|
||||
$($rest:tt,)*
|
||||
) => {
|
||||
// Emit all items within one block, applying an appropriate #[cfg]. The
|
||||
// #[cfg] will require all `$yes` matchers specified and must also negate
|
||||
// all previous matchers.
|
||||
#[cfg(all(
|
||||
$($yes,)?
|
||||
not(any($($no),*))
|
||||
))]
|
||||
cfg_match! { @__identity $($tokens)* }
|
||||
|
||||
// Recurse to emit all other items in `$rest`, and when we do so add all
|
||||
// our `$yes` matchers to the list of `$no` matchers as future emissions
|
||||
// will have to negate everything we just matched as well.
|
||||
cfg_match! {
|
||||
@__items ($($no,)* $($yes,)?);
|
||||
$($rest,)*
|
||||
}
|
||||
},
|
||||
|
||||
// Internal macro to make __apply work out right for different match types,
|
||||
// because of how macros match/expand stuff.
|
||||
(@__identity $($tokens:item)*) => {
|
||||
$($tokens)*
|
||||
}
|
||||
}
|
||||
|
||||
/// Asserts that a boolean expression is `true` at runtime.
|
||||
///
|
||||
/// This will invoke the [`panic!`] macro if the provided expression cannot be
|
||||
|
|
@ -321,95 +409,6 @@ pub macro debug_assert_matches($($arg:tt)*) {
|
|||
}
|
||||
}
|
||||
|
||||
/// A macro for defining `#[cfg]` match-like statements.
|
||||
///
|
||||
/// It is similar to the `if/elif` C preprocessor macro by allowing definition of a cascade of
|
||||
/// `#[cfg]` cases, emitting the implementation which matches first.
|
||||
///
|
||||
/// This allows you to conveniently provide a long list `#[cfg]`'d blocks of code
|
||||
/// without having to rewrite each clause multiple times.
|
||||
///
|
||||
/// Trailing `_` wildcard match arms are **optional** and they indicate a fallback branch when
|
||||
/// all previous declarations do not evaluate to true.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(cfg_match)]
|
||||
///
|
||||
/// cfg_match! {
|
||||
/// cfg(unix) => {
|
||||
/// fn foo() { /* unix specific functionality */ }
|
||||
/// }
|
||||
/// cfg(target_pointer_width = "32") => {
|
||||
/// fn foo() { /* non-unix, 32-bit functionality */ }
|
||||
/// }
|
||||
/// _ => {
|
||||
/// fn foo() { /* fallback implementation */ }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[macro_export]
|
||||
#[unstable(feature = "cfg_match", issue = "115585")]
|
||||
#[rustc_diagnostic_item = "cfg_match"]
|
||||
macro_rules! cfg_match {
|
||||
// with a final wildcard
|
||||
(
|
||||
$(cfg($initial_meta:meta) => { $($initial_tokens:item)* })+
|
||||
_ => { $($extra_tokens:item)* }
|
||||
) => {
|
||||
cfg_match! {
|
||||
@__items ();
|
||||
$((($initial_meta) ($($initial_tokens)*)),)+
|
||||
(() ($($extra_tokens)*)),
|
||||
}
|
||||
};
|
||||
|
||||
// without a final wildcard
|
||||
(
|
||||
$(cfg($extra_meta:meta) => { $($extra_tokens:item)* })*
|
||||
) => {
|
||||
cfg_match! {
|
||||
@__items ();
|
||||
$((($extra_meta) ($($extra_tokens)*)),)*
|
||||
}
|
||||
};
|
||||
|
||||
// Internal and recursive macro to emit all the items
|
||||
//
|
||||
// Collects all the previous cfgs in a list at the beginning, so they can be
|
||||
// negated. After the semicolon is all the remaining items.
|
||||
(@__items ($($_:meta,)*);) => {};
|
||||
(
|
||||
@__items ($($no:meta,)*);
|
||||
(($($yes:meta)?) ($($tokens:item)*)),
|
||||
$($rest:tt,)*
|
||||
) => {
|
||||
// Emit all items within one block, applying an appropriate #[cfg]. The
|
||||
// #[cfg] will require all `$yes` matchers specified and must also negate
|
||||
// all previous matchers.
|
||||
#[cfg(all(
|
||||
$($yes,)?
|
||||
not(any($($no),*))
|
||||
))]
|
||||
cfg_match! { @__identity $($tokens)* }
|
||||
|
||||
// Recurse to emit all other items in `$rest`, and when we do so add all
|
||||
// our `$yes` matchers to the list of `$no` matchers as future emissions
|
||||
// will have to negate everything we just matched as well.
|
||||
cfg_match! {
|
||||
@__items ($($no,)* $($yes,)?);
|
||||
$($rest,)*
|
||||
}
|
||||
};
|
||||
|
||||
// Internal macro to make __apply work out right for different match types,
|
||||
// because of how macros match/expand stuff.
|
||||
(@__identity $($tokens:item)*) => {
|
||||
$($tokens)*
|
||||
};
|
||||
}
|
||||
|
||||
/// Returns whether the given expression matches any of the given patterns.
|
||||
///
|
||||
/// Like in a `match` expression, the pattern can be optionally followed by `if`
|
||||
|
|
|
|||
|
|
@ -46,10 +46,10 @@ fn sanitize_sh(path: &Path) -> String {
|
|||
}
|
||||
|
||||
fn is_dir_writable_for_user(dir: &PathBuf) -> bool {
|
||||
let tmp_file = dir.join(".tmp");
|
||||
match fs::File::create(&tmp_file) {
|
||||
let tmp = dir.join(".tmp");
|
||||
match fs::create_dir_all(&tmp) {
|
||||
Ok(_) => {
|
||||
fs::remove_file(tmp_file).unwrap();
|
||||
fs::remove_dir_all(tmp).unwrap();
|
||||
true
|
||||
}
|
||||
Err(e) => {
|
||||
|
|
@ -73,16 +73,27 @@ fn install_sh(
|
|||
|
||||
let prefix = default_path(&builder.config.prefix, "/usr/local");
|
||||
let sysconfdir = prefix.join(default_path(&builder.config.sysconfdir, "/etc"));
|
||||
let destdir_env = env::var_os("DESTDIR").map(PathBuf::from);
|
||||
|
||||
// Sanity check for the user write access on prefix and sysconfdir
|
||||
assert!(
|
||||
is_dir_writable_for_user(&prefix),
|
||||
"User doesn't have write access on `install.prefix` path in the `config.toml`.",
|
||||
);
|
||||
assert!(
|
||||
is_dir_writable_for_user(&sysconfdir),
|
||||
"User doesn't have write access on `install.sysconfdir` path in `config.toml`."
|
||||
);
|
||||
// Sanity checks on the write access of user.
|
||||
//
|
||||
// When the `DESTDIR` environment variable is present, there is no point to
|
||||
// check write access for `prefix` and `sysconfdir` individually, as they
|
||||
// are combined with the path from the `DESTDIR` environment variable. In
|
||||
// this case, we only need to check the `DESTDIR` path, disregarding the
|
||||
// `prefix` and `sysconfdir` paths.
|
||||
if let Some(destdir) = &destdir_env {
|
||||
assert!(is_dir_writable_for_user(destdir), "User doesn't have write access on DESTDIR.");
|
||||
} else {
|
||||
assert!(
|
||||
is_dir_writable_for_user(&prefix),
|
||||
"User doesn't have write access on `install.prefix` path in the `config.toml`.",
|
||||
);
|
||||
assert!(
|
||||
is_dir_writable_for_user(&sysconfdir),
|
||||
"User doesn't have write access on `install.sysconfdir` path in `config.toml`."
|
||||
);
|
||||
}
|
||||
|
||||
let datadir = prefix.join(default_path(&builder.config.datadir, "share"));
|
||||
let docdir = prefix.join(default_path(&builder.config.docdir, "share/doc/rust"));
|
||||
|
|
@ -96,13 +107,13 @@ fn install_sh(
|
|||
let mut cmd = Command::new(SHELL);
|
||||
cmd.current_dir(&empty_dir)
|
||||
.arg(sanitize_sh(&tarball.decompressed_output().join("install.sh")))
|
||||
.arg(format!("--prefix={}", prepare_dir(prefix)))
|
||||
.arg(format!("--sysconfdir={}", prepare_dir(sysconfdir)))
|
||||
.arg(format!("--datadir={}", prepare_dir(datadir)))
|
||||
.arg(format!("--docdir={}", prepare_dir(docdir)))
|
||||
.arg(format!("--bindir={}", prepare_dir(bindir)))
|
||||
.arg(format!("--libdir={}", prepare_dir(libdir)))
|
||||
.arg(format!("--mandir={}", prepare_dir(mandir)))
|
||||
.arg(format!("--prefix={}", prepare_dir(&destdir_env, prefix)))
|
||||
.arg(format!("--sysconfdir={}", prepare_dir(&destdir_env, sysconfdir)))
|
||||
.arg(format!("--datadir={}", prepare_dir(&destdir_env, datadir)))
|
||||
.arg(format!("--docdir={}", prepare_dir(&destdir_env, docdir)))
|
||||
.arg(format!("--bindir={}", prepare_dir(&destdir_env, bindir)))
|
||||
.arg(format!("--libdir={}", prepare_dir(&destdir_env, libdir)))
|
||||
.arg(format!("--mandir={}", prepare_dir(&destdir_env, mandir)))
|
||||
.arg("--disable-ldconfig");
|
||||
builder.run(&mut cmd);
|
||||
t!(fs::remove_dir_all(&empty_dir));
|
||||
|
|
@ -112,19 +123,16 @@ fn default_path(config: &Option<PathBuf>, default: &str) -> PathBuf {
|
|||
config.as_ref().cloned().unwrap_or_else(|| PathBuf::from(default))
|
||||
}
|
||||
|
||||
fn prepare_dir(mut path: PathBuf) -> String {
|
||||
fn prepare_dir(destdir_env: &Option<PathBuf>, mut path: PathBuf) -> String {
|
||||
// The DESTDIR environment variable is a standard way to install software in a subdirectory
|
||||
// while keeping the original directory structure, even if the prefix or other directories
|
||||
// contain absolute paths.
|
||||
//
|
||||
// More information on the environment variable is available here:
|
||||
// https://www.gnu.org/prep/standards/html_node/DESTDIR.html
|
||||
if let Some(destdir) = env::var_os("DESTDIR").map(PathBuf::from) {
|
||||
// Sanity check for the user write access on DESTDIR
|
||||
assert!(is_dir_writable_for_user(&destdir), "User doesn't have write access on DESTDIR.");
|
||||
|
||||
if let Some(destdir) = destdir_env {
|
||||
let without_destdir = path.clone();
|
||||
path = destdir;
|
||||
path = destdir.clone();
|
||||
// Custom .join() which ignores disk roots.
|
||||
for part in without_destdir.components() {
|
||||
if let Component::Normal(s) = part {
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit febc39711a7c91560eb0f0980916ae23c343b99d
|
||||
Subproject commit fef3d7b14ede45d051dc688aae0bb8c8b02a0566
|
||||
Loading…
Add table
Add a link
Reference in a new issue