summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilfred Hughes <me@wilfred.me.uk>2023-12-30 11:19:49 -0800
committerWilfred Hughes <me@wilfred.me.uk>2023-12-30 11:20:00 -0800
commitdb0c150f61ce6f0923d65f74471bfee7ddf4e0e5 (patch)
tree84ba10b843db2135a008781b1b7afcf35c970292
parent68f28a808506f6e1929e569c7c410b554a4d40dd (diff)
Report permission changes
Fixes #605
-rw-r--r--CHANGELOG.md4
-rw-r--r--sample_files/compare.expected2
-rw-r--r--src/main.rs69
3 files changed, 73 insertions, 2 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c406a4934..14007e1cd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,10 @@ Added support for Salesforce Apex.
Improved parsing of regex literals in Clojure and strictness
annotations in Haskell.
+### Diffing
+
+Difftastic will now also report file permission changes.
+
### Display
Fixed a rare crash when the last non-blank line had changes for
diff --git a/sample_files/compare.expected b/sample_files/compare.expected
index 61ce95301..c8b7cb46a 100644
--- a/sample_files/compare.expected
+++ b/sample_files/compare.expected
@@ -23,7 +23,7 @@ sample_files/change_outer_before.el sample_files/change_outer_after.el
8ed3308b9eabd486bdbe9aa2e7dc9be6 -
sample_files/chinese_before.po sample_files/chinese_after.po
-b5cf768305ee724d456aedfc20095226 -
+097250024d46c75a159b8a8efe9a1e51 -
sample_files/clojure_before.clj sample_files/clojure_after.clj
34a723cb5ec5a81f3ae5c01a64bca6c2 -
diff --git a/src/main.rs b/src/main.rs
index 76e45d98f..ba0e028be 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -73,6 +73,7 @@ use crate::parse::syntax;
#[global_allocator]
static GLOBAL: MiMalloc = MiMalloc;
+use std::fs::Permissions;
use std::path::Path;
use std::{env, thread};
@@ -330,6 +331,62 @@ fn main() {
};
}
+#[cfg(unix)]
+fn compare_permissions(lhs: &Permissions, rhs: &Permissions) -> Option<String> {
+ use std::os::unix::fs::PermissionsExt;
+
+ let lhs_mode = lhs.mode();
+ let rhs_mode = rhs.mode();
+
+ if lhs_mode != rhs_mode {
+ let lhs_mode = format!("{:o}", lhs_mode);
+ let rhs_mode = format!("{:o}", rhs_mode);
+ Some(format!(
+ "File permissions changed from {} to {}.",
+ lhs_mode, rhs_mode
+ ))
+ } else {
+ None
+ }
+}
+
+#[cfg(windows)]
+fn compare_permissions(lhs: &Permissions, rhs: &Permissions) -> Option<String> {
+ if lhs.readonly() != rhs.readonly() {
+ Some(format!(
+ "File permissions changed from {} to {}.",
+ if lhs.readonly() {
+ "readonly"
+ } else {
+ "read-write"
+ },
+ if rhs.readonly() {
+ "readonly"
+ } else {
+ "read-write"
+ },
+ ))
+ } else {
+ None
+ }
+}
+
+#[cfg(not(any(unix, windows)))]
+fn compare_permissions(_lhs: &Permissions, _rhs: &Permissions) -> Option<String> {
+ None
+}
+
+fn describe_permissions_change(lhs_path: &FileArgument, rhs_path: &FileArgument) -> Option<String> {
+ match (lhs_path, rhs_path) {
+ (FileArgument::NamedPath(lhs_path), FileArgument::NamedPath(rhs_path)) => {
+ let lhs_metadata = std::fs::metadata(lhs_path).ok()?;
+ let rhs_metadata = std::fs::metadata(rhs_path).ok()?;
+ compare_permissions(&lhs_metadata.permissions(), &rhs_metadata.permissions())
+ }
+ _ => None,
+ }
+}
+
/// Print a diff between two files.
fn diff_file(
display_path: &str,
@@ -365,9 +422,19 @@ fn diff_file(
rhs_src.retain(|c| c != '\r');
}
+ let mut extra_info = renamed;
+ if let Some(permissions_change) = describe_permissions_change(lhs_path, rhs_path) {
+ if let Some(extra_info) = &mut extra_info {
+ extra_info.push('\n');
+ extra_info.push_str(&permissions_change);
+ } else {
+ extra_info = Some(permissions_change);
+ }
+ }
+
diff_file_content(
display_path,
- renamed,
+ extra_info,
lhs_path,
rhs_path,
&lhs_src,