Explorar el Código

fix: dereferencing links users.

Signed-off-by: Christina Sørensen <christina@cafkafk.com>
Andrzej Grzeslak hace 3 años
padre
commit
97a7f99320
Se han modificado 5 ficheros con 34 adiciones y 16 borrados
  1. 10 3
      src/fs/file.rs
  2. 1 0
      src/output/render/mod.rs
  3. 21 12
      src/output/render/users.rs
  4. 1 1
      src/output/table.rs
  5. 1 0
      src/theme/mod.rs

+ 10 - 3
src/fs/file.rs

@@ -325,9 +325,16 @@ impl<'dir> File<'dir> {
         }
     }
 
-    /// The ID of the user that own this file.
-    pub fn user(&self) -> f::User {
-        f::User(self.metadata.uid())
+    /// The ID of the user that own this file. If dereferencing links, the links
+    /// may be broken, in which case `None` will be returned.
+    pub fn user(&self) -> Option<f::User> {
+        if self.is_link() && self.deref_links {
+            match self.link_target_recurse() {
+               FileTarget::Ok(f) => return f.user(),
+               _ => return None,
+            }
+        }
+        Some(f::User(self.metadata.uid()))
     }
 
     /// The ID of the group that owns this file.

+ 1 - 0
src/output/render/mod.rs

@@ -28,6 +28,7 @@ pub use self::times::Render as TimeRender;
 
 mod users;
 pub use self::users::Colours as UserColours;
+pub use self::users::Render as UserRender;
 
 mod octal;
 // octal uses just one colour

+ 21 - 12
src/output/render/users.rs

@@ -5,16 +5,23 @@ use crate::fs::fields as f;
 use crate::output::cell::TextCell;
 use crate::output::table::UserFormat;
 
+pub trait Render {
+    fn render<C: Colours, U: Users>(self, colours: &C, users: &U, format: UserFormat) -> TextCell;
+}
 
-impl f::User {
-    pub fn render<C: Colours, U: Users>(self, colours: &C, users: &U, format: UserFormat) -> TextCell {
-        let user_name = match (format, users.get_user_by_uid(self.0)) {
-            (_, None)                      => self.0.to_string(),
-            (UserFormat::Numeric, _)       => self.0.to_string(),
+impl Render for Option<f::User> {
+    fn render<C: Colours, U: Users>(self, colours: &C, users: &U, format: UserFormat) -> TextCell {
+        let uid = match self {
+            Some(u) => u.0,
+            None    => return TextCell::blank(colours.no_user()),
+        };
+        let user_name = match (format, users.get_user_by_uid(uid)) {
+            (_, None)                      => uid.to_string(),
+            (UserFormat::Numeric, _)       => uid.to_string(),
             (UserFormat::Name, Some(user)) => user.name().to_string_lossy().into(),
         };
 
-        let style = if users.get_current_uid() == self.0 { colours.you() }
+        let style = if users.get_current_uid() == uid { colours.you() }
                                                     else { colours.someone_else() };
         TextCell::paint(style, user_name)
     }
@@ -24,13 +31,14 @@ impl f::User {
 pub trait Colours {
     fn you(&self) -> Style;
     fn someone_else(&self) -> Style;
+    fn no_user(&self) -> Style;
 }
 
 
 #[cfg(test)]
 #[allow(unused_results)]
 pub mod test {
-    use super::Colours;
+    use super::{Colours, Render};
     use crate::fs::fields as f;
     use crate::output::cell::TextCell;
     use crate::output::table::UserFormat;
@@ -46,6 +54,7 @@ pub mod test {
     impl Colours for TestColours {
         fn you(&self)          -> Style { Red.bold() }
         fn someone_else(&self) -> Style { Blue.underline() }
+        fn no_user(&self)      -> Style { Black.italic() }
     }
 
 
@@ -54,7 +63,7 @@ pub mod test {
         let mut users = MockUsers::with_current_uid(1000);
         users.add_user(User::new(1000, "enoch", 100));
 
-        let user = f::User(1000);
+        let user = Some(f::User(1000));
         let expected = TextCell::paint_str(Red.bold(), "enoch");
         assert_eq!(expected, user.render(&TestColours, &users, UserFormat::Name));
 
@@ -66,7 +75,7 @@ pub mod test {
     fn unnamed() {
         let users = MockUsers::with_current_uid(1000);
 
-        let user = f::User(1000);
+        let user = Some(f::User(1000));
         let expected = TextCell::paint_str(Red.bold(), "1000");
         assert_eq!(expected, user.render(&TestColours, &users, UserFormat::Name));
         assert_eq!(expected, user.render(&TestColours, &users, UserFormat::Numeric));
@@ -77,21 +86,21 @@ pub mod test {
         let mut users = MockUsers::with_current_uid(0);
         users.add_user(User::new(1000, "enoch", 100));
 
-        let user = f::User(1000);
+        let user = Some(f::User(1000));
         let expected = TextCell::paint_str(Blue.underline(), "enoch");
         assert_eq!(expected, user.render(&TestColours, &users, UserFormat::Name));
     }
 
     #[test]
     fn different_unnamed() {
-        let user = f::User(1000);
+        let user = Some(f::User(1000));
         let expected = TextCell::paint_str(Blue.underline(), "1000");
         assert_eq!(expected, user.render(&TestColours, &MockUsers::with_current_uid(0), UserFormat::Numeric));
     }
 
     #[test]
     fn overflow() {
-        let user = f::User(2_147_483_648);
+        let user = Some(f::User(2_147_483_648));
         let expected = TextCell::paint_str(Blue.underline(), "2147483648");
         assert_eq!(expected, user.render(&TestColours, &MockUsers::with_current_uid(0), UserFormat::Numeric));
     }

+ 1 - 1
src/output/table.rs

@@ -13,7 +13,7 @@ use users::UsersCache;
 use crate::fs::{File, fields as f};
 use crate::fs::feature::git::GitCache;
 use crate::output::cell::TextCell;
-use crate::output::render::TimeRender;
+use crate::output::render::{TimeRender, UserRender};
 use crate::output::time::TimeFormat;
 use crate::theme::Theme;
 

+ 1 - 0
src/theme/mod.rs

@@ -290,6 +290,7 @@ impl render::SizeColours for Theme {
 impl render::UserColours for Theme {
     fn you(&self)           -> Style { self.ui.users.user_you }
     fn someone_else(&self)  -> Style { self.ui.users.user_someone_else }
+    fn no_user(&self)       -> Style { self.ui.punctuation }
 }
 
 impl FileNameColours for Theme {