|
1 | 1 | use std::borrow::Borrow;
|
2 | 2 | use std::collections;
|
3 | 3 | use std::fs;
|
| 4 | +use std::io; |
| 5 | +use std::os; |
| 6 | +use std::path::Path; |
4 | 7 |
|
5 | 8 | use crate::support::{paths, project};
|
6 | 9 | use cargo::core::{enable_nightly_features, Shell};
|
@@ -54,6 +57,44 @@ fn write_config_toml(config: &str) {
|
54 | 57 | fs::write(path, config).unwrap();
|
55 | 58 | }
|
56 | 59 |
|
| 60 | +// Several test fail on windows if the user does not have permission to |
| 61 | +// create symlinks (the `SeCreateSymbolicLinkPrivilege`). Instead of |
| 62 | +// disabling these test on Windows, use this function to test whether we |
| 63 | +// have permission, and return otherwise. This way, we still don't run these |
| 64 | +// tests most of the time, but at least we do if the user has the right |
| 65 | +// permissions. |
| 66 | +// This function is derived from libstd fs tests. |
| 67 | +pub fn got_symlink_permission() -> bool { |
| 68 | + if cfg!(unix) { |
| 69 | + return true; |
| 70 | + } |
| 71 | + let link = paths::root().join("some_hopefully_unique_link_name"); |
| 72 | + let target = paths::root().join("nonexisting_target"); |
| 73 | + |
| 74 | + match symlink_file(&target, &link) { |
| 75 | + Ok(_) => true, |
| 76 | + // ERROR_PRIVILEGE_NOT_HELD = 1314 |
| 77 | + Err(ref err) if err.raw_os_error() == Some(1314) => false, |
| 78 | + Err(_) => true, |
| 79 | + } |
| 80 | +} |
| 81 | + |
| 82 | +#[cfg(unix)] |
| 83 | +fn symlink_file(target: &Path, link: &Path) -> io::Result<()> { |
| 84 | + os::unix::fs::symlink(target, link) |
| 85 | +} |
| 86 | + |
| 87 | +#[cfg(windows)] |
| 88 | +fn symlink_file(target: &Path, link: &Path) -> io::Result<()> { |
| 89 | + os::windows::fs::symlink_file(target, link) |
| 90 | +} |
| 91 | + |
| 92 | +fn symlink_config_to_config_toml() { |
| 93 | + let toml_path = paths::root().join(".cargo/config.toml"); |
| 94 | + let symlink_path = paths::root().join(".cargo/config"); |
| 95 | + t!(symlink_file(&toml_path, &symlink_path)); |
| 96 | +} |
| 97 | + |
57 | 98 | fn new_config(env: &[(&str, &str)]) -> Config {
|
58 | 99 | enable_nightly_features(); // -Z advanced-env
|
59 | 100 | let output = Box::new(fs::File::create(paths::root().join("shell.out")).unwrap());
|
@@ -132,6 +173,42 @@ f1 = 1
|
132 | 173 | assert_eq!(config.get::<Option<i32>>("foo.f1").unwrap(), Some(1));
|
133 | 174 | }
|
134 | 175 |
|
| 176 | +#[cargo_test] |
| 177 | +fn config_ambiguous_filename_symlink_doesnt_warn() { |
| 178 | + // Windows requires special permissions to create symlinks. |
| 179 | + // If we don't have permission, just skip this test. |
| 180 | + if !got_symlink_permission() { |
| 181 | + return; |
| 182 | + }; |
| 183 | + |
| 184 | + write_config_toml( |
| 185 | + "\ |
| 186 | +[foo] |
| 187 | +f1 = 1 |
| 188 | +", |
| 189 | + ); |
| 190 | + |
| 191 | + symlink_config_to_config_toml(); |
| 192 | + |
| 193 | + let config = new_config(&[]); |
| 194 | + |
| 195 | + assert_eq!(config.get::<Option<i32>>("foo.f1").unwrap(), Some(1)); |
| 196 | + |
| 197 | + // It should NOT have warned for the symlink. |
| 198 | + drop(config); // Paranoid about flushing the file. |
| 199 | + let path = paths::root().join("shell.out"); |
| 200 | + let output = fs::read_to_string(path).unwrap(); |
| 201 | + let unexpected = "\ |
| 202 | +warning: Both `[..]/.cargo/config` and `[..]/.cargo/config.toml` exist. Using `[..]/.cargo/config` |
| 203 | +"; |
| 204 | + if lines_match(unexpected, &output) { |
| 205 | + panic!( |
| 206 | + "Found unexpected:\n{}\nActual error:\n{}\n", |
| 207 | + unexpected, output |
| 208 | + ); |
| 209 | + } |
| 210 | +} |
| 211 | + |
135 | 212 | #[cargo_test]
|
136 | 213 | fn config_ambiguous_filename() {
|
137 | 214 | write_config(
|
|
0 commit comments