Skip to content

Commit cdae40c

Browse files
Warn when paths are too long for Windows
This also adds a section in the provisioning docs about the "Enable Win32 long paths" option. Precise instructions are behind a Stack Overflow link, because this option is unstable and may change.
1 parent be930f9 commit cdae40c

File tree

2 files changed

+29
-3
lines changed

2 files changed

+29
-3
lines changed

docs/agent-machine-setup-windows.md

+11
Original file line numberDiff line numberDiff line change
@@ -120,3 +120,14 @@ cargo run --release -- prepare-local
120120
```
121121

122122
Remember to run `cargo run -- create-lists` before running the tests.
123+
124+
# Troubleshooting
125+
126+
## Overlong paths
127+
128+
If you encounter warnings about paths being too long, you should disable the
129+
260 character limit. This option is called "Enable Win32 long paths" in the
130+
policy editor. See this [Stack Overflow question][so-long-path] for more
131+
details.
132+
133+
[so-long-path]: https://superuser.com/questions/1119883/windows-10-enable-ntfs-long-paths-policy-option-missing

src/utils/fs.rs

+18-3
Original file line numberDiff line numberDiff line change
@@ -30,20 +30,35 @@ fn strip_verbatim_from_prefix(prefix: &path::PrefixComponent<'_>) -> Option<Path
3030
}
3131

3232
pub(crate) fn try_canonicalize<P: AsRef<Path>>(path: P) -> PathBuf {
33-
let p = fs::canonicalize(&path).unwrap_or_else(|_| path.as_ref().to_path_buf());
33+
let mut p = fs::canonicalize(&path).unwrap_or_else(|_| path.as_ref().to_path_buf());
3434

3535
// `fs::canonicalize` returns an extended-length path on Windows. Such paths not supported by
36-
// many programs, including rustup.
36+
// many programs, including rustup. We strip the `\\?\` prefix of the canonicalized path, but
37+
// this changes the meaning of some path components, and imposes a length of around 260
38+
// characters.
3739
if cfg!(windows) {
40+
// A conservative estimate for the maximum length of a path on Windows.
41+
//
42+
// The additional 12 byte restriction is applied when creating directories. It ensures that
43+
// files can always be created inside that directory without exceeding the path limit.
44+
const MAX_PATH_LEN: usize = 260 - 12;
45+
3846
let mut components = p.components();
3947
let first_component = components.next().unwrap();
4048

4149
if let path::Component::Prefix(prefix) = first_component {
4250
if let Some(mut modified_path) = strip_verbatim_from_prefix(&prefix) {
4351
modified_path.push(components.as_path());
44-
return modified_path;
52+
p = modified_path;
4553
}
4654
}
55+
56+
if p.as_os_str().len() >= MAX_PATH_LEN {
57+
warn!(
58+
"Canonicalized path is too long for Windows: {:?}",
59+
p.as_os_str(),
60+
);
61+
}
4762
}
4863

4964
p

0 commit comments

Comments
 (0)