Preserve Windows readonly file modes
ci / test (push) Canceled after 0s
ci / fuzz-smoke (push) Canceled after 0s
ci / windows-client (push) Canceled after 0s
ci / package-release (linux-x86_64, ubuntu-latest, , , ) (push) Canceled after 0s
ci / package-release (macos-aarch64, macos-14, , , ) (push) Canceled after 0s
ci / package-release (macos-x86_64, macos-13, , , ) (push) Canceled after 0s
ci / package-release (windows-aarch64, windows-latest, aarch64, windows, aarch64-pc-windows-msvc) (push) Canceled after 0s
ci / package-release (windows-x86_64, windows-latest, , , ) (push) Canceled after 0s
ci / remote-bench (push) Canceled after 0s
ci / publish-gitea-release (push) Canceled after 0s
ci / test (push) Canceled after 0s
ci / fuzz-smoke (push) Canceled after 0s
ci / windows-client (push) Canceled after 0s
ci / package-release (linux-x86_64, ubuntu-latest, , , ) (push) Canceled after 0s
ci / package-release (macos-aarch64, macos-14, , , ) (push) Canceled after 0s
ci / package-release (macos-x86_64, macos-13, , , ) (push) Canceled after 0s
ci / package-release (windows-aarch64, windows-latest, aarch64, windows, aarch64-pc-windows-msvc) (push) Canceled after 0s
ci / package-release (windows-x86_64, windows-latest, , , ) (push) Canceled after 0s
ci / remote-bench (push) Canceled after 0s
ci / publish-gitea-release (push) Canceled after 0s
This commit is contained in:
+57
-3
@@ -3811,7 +3811,19 @@ fn mode_for(path: &Path, preserve: bool) -> Result<Option<u32>> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
#[cfg(windows)]
|
||||
fn mode_for(path: &Path, preserve: bool) -> Result<Option<u32>> {
|
||||
if !preserve {
|
||||
return Ok(None);
|
||||
}
|
||||
let metadata = fs::metadata(path)?;
|
||||
Ok(Some(windows_mode_from_readonly(
|
||||
metadata.is_dir(),
|
||||
metadata.permissions().readonly(),
|
||||
)))
|
||||
}
|
||||
|
||||
#[cfg(not(any(unix, windows)))]
|
||||
fn mode_for(_path: &Path, _preserve: bool) -> Result<Option<u32>> {
|
||||
Ok(None)
|
||||
}
|
||||
@@ -3830,11 +3842,40 @@ fn set_local_mode(path: &Path, mode: Option<u32>, preserve: bool) -> Result<()>
|
||||
fs::set_permissions(path, permissions).with_context(|| format!("chmod {}", path.display()))
|
||||
}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
#[cfg(windows)]
|
||||
fn set_local_mode(path: &Path, mode: Option<u32>, preserve: bool) -> Result<()> {
|
||||
if !preserve {
|
||||
return Ok(());
|
||||
}
|
||||
let Some(mode) = mode else {
|
||||
return Ok(());
|
||||
};
|
||||
let mut permissions = fs::metadata(path)?.permissions();
|
||||
permissions.set_readonly(windows_readonly_from_mode(mode));
|
||||
fs::set_permissions(path, permissions)
|
||||
.with_context(|| format!("set readonly mode {}", path.display()))
|
||||
}
|
||||
|
||||
#[cfg(not(any(unix, windows)))]
|
||||
fn set_local_mode(_path: &Path, _mode: Option<u32>, _preserve: bool) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg_attr(not(any(test, windows)), allow(dead_code))]
|
||||
fn windows_mode_from_readonly(is_dir: bool, readonly: bool) -> u32 {
|
||||
match (is_dir, readonly) {
|
||||
(true, true) => 0o555,
|
||||
(true, false) => 0o777,
|
||||
(false, true) => 0o444,
|
||||
(false, false) => 0o666,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(not(any(test, windows)), allow(dead_code))]
|
||||
fn windows_readonly_from_mode(mode: u32) -> bool {
|
||||
mode & 0o222 == 0
|
||||
}
|
||||
|
||||
fn parse_local_forwards(raw: &[String]) -> Result<Vec<LocalForward>> {
|
||||
raw.iter().map(|value| parse_local_forward(value)).collect()
|
||||
}
|
||||
@@ -10100,7 +10141,7 @@ mod tests {
|
||||
toml_bare_key_or_quoted, top_trace_events, trace_report_warnings, unix_update_script,
|
||||
update_binary_version_for_installer, update_installer_url, update_version_status,
|
||||
upsert_managed_block, valid_forward_host, vscode_safe_alias, wake_repaint_retry_deadline,
|
||||
windows_update_script,
|
||||
windows_mode_from_readonly, windows_readonly_from_mode, windows_update_script,
|
||||
};
|
||||
use dosh::config::{ClientConfig, CommandExtension, HostConfig};
|
||||
use dosh::native::EnvVar;
|
||||
@@ -10186,6 +10227,19 @@ mod tests {
|
||||
assert!(local_symlink_target_is_dir(&link, "missing-dir\\"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn windows_mode_mapping_preserves_readonly_semantics() {
|
||||
assert_eq!(windows_mode_from_readonly(false, true), 0o444);
|
||||
assert_eq!(windows_mode_from_readonly(false, false), 0o666);
|
||||
assert_eq!(windows_mode_from_readonly(true, true), 0o555);
|
||||
assert_eq!(windows_mode_from_readonly(true, false), 0o777);
|
||||
|
||||
assert!(windows_readonly_from_mode(0o444));
|
||||
assert!(windows_readonly_from_mode(0o555));
|
||||
assert!(!windows_readonly_from_mode(0o644));
|
||||
assert!(!windows_readonly_from_mode(0o755));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cleanup_stream_state_removes_all_per_stream_state_only_for_target() {
|
||||
let stream_id = 42;
|
||||
|
||||
Reference in New Issue
Block a user