Now move permissions

This commit is contained in:
Benjamin Sago 2017-05-20 21:21:17 +01:00
parent 753fbc294a
commit 3f8b547f2d
3 changed files with 137 additions and 80 deletions

View File

@ -83,8 +83,6 @@ use std::path::PathBuf;
use std::string::ToString; use std::string::ToString;
use std::sync::{Arc, Mutex, MutexGuard}; use std::sync::{Arc, Mutex, MutexGuard};
use ansi_term::Style;
use datetime::fmt::DateFormat; use datetime::fmt::DateFormat;
use datetime::{LocalDateTime, DatePiece}; use datetime::{LocalDateTime, DatePiece};
use datetime::TimeZone; use datetime::TimeZone;
@ -498,7 +496,7 @@ impl<'a, U: Users+Groups+'a> Table<'a, U> {
use output::column::TimeType::*; use output::column::TimeType::*;
match *column { match *column {
Column::Permissions => self.render_permissions(file.type_char(), file.permissions(), xattrs), Column::Permissions => file.permissions().render(&self.opts.colours, file.type_char(), xattrs),
Column::FileSize(fmt) => self.render_size(file.size(), fmt), Column::FileSize(fmt) => self.render_size(file.size(), fmt),
Column::Timestamp(Modified) => self.render_time(file.modified_time()), Column::Timestamp(Modified) => self.render_time(file.modified_time()),
Column::Timestamp(Created) => self.render_time(file.created_time()), Column::Timestamp(Created) => self.render_time(file.created_time()),
@ -512,56 +510,6 @@ impl<'a, U: Users+Groups+'a> Table<'a, U> {
} }
} }
fn render_permissions(&self, file_type: f::Type, permissions: f::Permissions, xattrs: bool) -> TextCell {
let perms = self.opts.colours.perms;
let types = self.opts.colours.filetypes;
let bit = |bit, chr: &'static str, style: Style| {
if bit { style.paint(chr) } else { self.opts.colours.punctuation.paint("-") }
};
let type_char = match file_type {
f::Type::File => types.normal.paint("."),
f::Type::Directory => types.directory.paint("d"),
f::Type::Pipe => types.pipe.paint("|"),
f::Type::Link => types.symlink.paint("l"),
f::Type::CharDevice => types.device.paint("c"),
f::Type::BlockDevice => types.device.paint("b"),
f::Type::Socket => types.socket.paint("s"),
f::Type::Special => types.special.paint("?"),
};
let x_colour = if file_type.is_regular_file() { perms.user_execute_file }
else { perms.user_execute_other };
let mut chars = vec![
type_char,
bit(permissions.user_read, "r", perms.user_read),
bit(permissions.user_write, "w", perms.user_write),
bit(permissions.user_execute, "x", x_colour),
bit(permissions.group_read, "r", perms.group_read),
bit(permissions.group_write, "w", perms.group_write),
bit(permissions.group_execute, "x", perms.group_execute),
bit(permissions.other_read, "r", perms.other_read),
bit(permissions.other_write, "w", perms.other_write),
bit(permissions.other_execute, "x", perms.other_execute),
];
if xattrs {
chars.push(perms.attribute.paint("@"));
}
// As these are all ASCII characters, we can guarantee that theyre
// all going to be one character wide, and dont need to compute the
// cells display width.
let width = DisplayWidth::from(chars.len());
TextCell {
contents: chars.into(),
width: width,
}
}
fn render_links(&self, links: f::Links) -> TextCell { fn render_links(&self, links: f::Links) -> TextCell {
let style = if links.multiple { self.opts.colours.links.multi_link_file } let style = if links.multiple { self.opts.colours.links.multi_link_file }
else { self.opts.colours.links.normal }; else { self.opts.colours.links.normal };
@ -741,30 +689,3 @@ impl<'a, U: Users+Groups+'a> Table<'a, U> {
cells cells
} }
} }
#[cfg(test)]
pub mod test {
use super::Environment;
use users::mock::MockUsers;
use datetime::fmt::DateFormat;
impl Default for Environment<MockUsers> {
fn default() -> Self {
use locale;
use users::mock::MockUsers;
use std::sync::Mutex;
Environment {
current_year: 1234,
numeric: locale::Numeric::english(),
time: locale::Time::english(),
date_and_time: DateFormat::parse("{2>:D} {4>:M} {2>:h}:{02>:m}").unwrap(),
date_and_year: DateFormat::parse("{2>:D} {:M} {5>:Y}").unwrap(),
tz: None,
users: Mutex::new(MockUsers::with_current_uid(0)),
}
}
}
}

View File

@ -18,3 +18,4 @@ pub mod file_name;
mod escape; mod escape;
mod users; mod users;
mod groups; mod groups;
mod permissions;

135
src/output/permissions.rs Normal file
View File

@ -0,0 +1,135 @@
use fs::fields as f;
use output::colours::Colours;
use output::cell::{TextCell, DisplayWidth};
use ansi_term::Style;
impl f::Permissions {
pub fn render(&self, colours: &Colours, file_type: f::Type, xattrs: bool) -> TextCell {
let bit = |bit, chr: &'static str, style: Style| {
if bit { style.paint(chr) } else { colours.punctuation.paint("-") }
};
let type_char = match file_type {
f::Type::File => colours.filetypes.normal.paint("."),
f::Type::Directory => colours.filetypes.directory.paint("d"),
f::Type::Pipe => colours.filetypes.pipe.paint("|"),
f::Type::Link => colours.filetypes.symlink.paint("l"),
f::Type::CharDevice => colours.filetypes.device.paint("c"),
f::Type::BlockDevice => colours.filetypes.device.paint("b"),
f::Type::Socket => colours.filetypes.socket.paint("s"),
f::Type::Special => colours.filetypes.special.paint("?"),
};
let x_colour = if file_type.is_regular_file() { colours.perms.user_execute_file }
else { colours.perms.user_execute_other };
let mut chars = vec![
type_char,
bit(self.user_read, "r", colours.perms.user_read),
bit(self.user_write, "w", colours.perms.user_write),
bit(self.user_execute, "x", x_colour),
bit(self.group_read, "r", colours.perms.group_read),
bit(self.group_write, "w", colours.perms.group_write),
bit(self.group_execute, "x", colours.perms.group_execute),
bit(self.other_read, "r", colours.perms.other_read),
bit(self.other_write, "w", colours.perms.other_write),
bit(self.other_execute, "x", colours.perms.other_execute),
];
if xattrs {
chars.push(colours.perms.attribute.paint("@"));
}
// As these are all ASCII characters, we can guarantee that theyre
// all going to be one character wide, and dont need to compute the
// cells display width.
let width = DisplayWidth::from(chars.len());
TextCell {
contents: chars.into(),
width: width,
}
}
}
#[cfg(test)]
#[allow(unused_results)]
pub mod test {
use output::details::Details;
use fs::fields as f;
use output::cell::TextCell;
use users::{User, Group};
use users::mock::MockUsers;
use users::os::unix::GroupExt;
use ansi_term::Colour::*;
#[test]
fn named() {
let mut details = Details::default();
details.colours.users.group_not_yours = Fixed(101).normal();
let mut users = MockUsers::with_current_uid(1000);
users.add_group(Group::new(100, "folk"));
let group = f::Group(100);
let expected = TextCell::paint_str(Fixed(101).normal(), "folk");
assert_eq!(expected, group.render(&details.colours, &users))
}
#[test]
fn unnamed() {
let mut details = Details::default();
details.colours.users.group_not_yours = Fixed(87).normal();
let users = MockUsers::with_current_uid(1000);
let group = f::Group(100);
let expected = TextCell::paint_str(Fixed(87).normal(), "100");
assert_eq!(expected, group.render(&details.colours, &users));
}
#[test]
fn primary() {
let mut details = Details::default();
details.colours.users.group_yours = Fixed(64).normal();
let mut users = MockUsers::with_current_uid(2);
users.add_user(User::new(2, "eve", 100));
users.add_group(Group::new(100, "folk"));
let group = f::Group(100);
let expected = TextCell::paint_str(Fixed(64).normal(), "folk");
assert_eq!(expected, group.render(&details.colours, &users))
}
#[test]
fn secondary() {
let mut details = Details::default();
details.colours.users.group_yours = Fixed(31).normal();
let mut users = MockUsers::with_current_uid(2);
users.add_user(User::new(2, "eve", 666));
let test_group = Group::new(100, "folk").add_member("eve");
users.add_group(test_group);
let group = f::Group(100);
let expected = TextCell::paint_str(Fixed(31).normal(), "folk");
assert_eq!(expected, group.render(&details.colours, &users))
}
#[test]
fn overflow() {
let mut details = Details::default();
details.colours.users.group_not_yours = Blue.underline();
let group = f::Group(2_147_483_648);
let expected = TextCell::paint_str(Blue.underline(), "2147483648");
assert_eq!(expected, group.render(&details.colours, &MockUsers::with_current_uid(0)));
}
}