|  | 
| 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