2015-01-26 01:16:19 +00:00
|
|
|
use std::ascii::AsciiExt;
|
2015-04-03 22:14:49 +00:00
|
|
|
use std::env::current_dir;
|
Use new io + path + fs libraries (LOTS OF CHANGES)
Exa now uses the new IO, Path, and Filesystem libraries that have been out for a while now.
Unfortunately, the new libraries don't *entirely* cover the range of the old libraries just yet: in particular, to become more cross-platform, the data in `UnstableFileStat` isn't available in the Unix `MetadataExt` yet. Much of this is contained in rust-lang/rfcs#1044 (which is due to be implemented in rust-lang/rust#14711), but it's not *entirely* there yet.
As such, this commits a serious loss of functionality: no symlink viewing, no hard links or blocks, or users or groups. Also, some of the code could now be optimised. I just wanted to commit this to sort out most of the 'teething problems' of having a different path system in advance.
Here's an example problem that took ages to fix for you, just because you read this far: when I first got exa to compile, it worked mostly fine, except calling `exa` by itself didn't list the current directory. I traced where the command-line options were being generated, to where files and directories were sorted, to where the threads were spawned... and the problem turned out to be that it was using the full path as the file name, rather than just the last component, and these paths happened to begin with `.`, so it thought they were dotfiles.
2015-04-23 12:00:34 +00:00
|
|
|
use std::fs;
|
|
|
|
use std::io;
|
2015-05-03 10:55:10 +00:00
|
|
|
use std::os::unix;
|
2015-05-03 11:46:05 +00:00
|
|
|
use std::os::unix::fs::{MetadataExt, PermissionsExt};
|
Use new io + path + fs libraries (LOTS OF CHANGES)
Exa now uses the new IO, Path, and Filesystem libraries that have been out for a while now.
Unfortunately, the new libraries don't *entirely* cover the range of the old libraries just yet: in particular, to become more cross-platform, the data in `UnstableFileStat` isn't available in the Unix `MetadataExt` yet. Much of this is contained in rust-lang/rfcs#1044 (which is due to be implemented in rust-lang/rust#14711), but it's not *entirely* there yet.
As such, this commits a serious loss of functionality: no symlink viewing, no hard links or blocks, or users or groups. Also, some of the code could now be optimised. I just wanted to commit this to sort out most of the 'teething problems' of having a different path system in advance.
Here's an example problem that took ages to fix for you, just because you read this far: when I first got exa to compile, it worked mostly fine, except calling `exa` by itself didn't list the current directory. I traced where the command-line options were being generated, to where files and directories were sorted, to where the threads were spawned... and the problem turned out to be that it was using the full path as the file name, rather than just the last component, and these paths happened to begin with `.`, so it thought they were dotfiles.
2015-04-23 12:00:34 +00:00
|
|
|
use std::path::{Component, Path, PathBuf};
|
2014-05-04 20:33:14 +00:00
|
|
|
|
2015-02-13 21:24:10 +00:00
|
|
|
use ansi_term::{ANSIString, ANSIStrings, Colour, Style};
|
2014-12-02 14:20:28 +00:00
|
|
|
use ansi_term::Style::Plain;
|
|
|
|
use ansi_term::Colour::{Red, Green, Yellow, Blue, Purple, Cyan, Fixed};
|
2014-07-01 18:00:36 +00:00
|
|
|
|
2014-12-12 14:13:08 +00:00
|
|
|
use users::Users;
|
2014-12-12 11:17:55 +00:00
|
|
|
|
2015-02-10 16:08:10 +00:00
|
|
|
use locale;
|
2015-04-23 12:46:37 +00:00
|
|
|
|
|
|
|
use unicode_width::UnicodeWidthStr;
|
2015-02-10 16:08:10 +00:00
|
|
|
|
2014-12-18 07:00:31 +00:00
|
|
|
use number_prefix::{binary_prefix, decimal_prefix, Prefixed, Standalone, PrefixNames};
|
|
|
|
|
2015-02-09 18:14:05 +00:00
|
|
|
use datetime::local::{LocalDateTime, DatePiece};
|
2015-02-10 18:14:56 +00:00
|
|
|
use datetime::format::{DateFormat};
|
2015-02-09 16:33:27 +00:00
|
|
|
|
2015-02-05 14:39:56 +00:00
|
|
|
use column::{Column, Cell};
|
2014-11-23 21:29:11 +00:00
|
|
|
use column::Column::*;
|
2014-06-16 23:27:05 +00:00
|
|
|
use dir::Dir;
|
2014-06-17 21:17:22 +00:00
|
|
|
use filetype::HasType;
|
2015-02-09 16:33:27 +00:00
|
|
|
use options::{SizeFormat, TimeType};
|
2015-04-23 12:46:37 +00:00
|
|
|
use output::details::UserLocale;
|
2015-03-26 00:37:12 +00:00
|
|
|
use feature::Attribute;
|
2014-06-16 23:27:05 +00:00
|
|
|
|
2015-01-24 12:38:05 +00:00
|
|
|
/// This grey value is directly in between white and black, so it's guaranteed
|
2015-05-03 10:51:57 +00:00
|
|
|
/// to show up on either backgrounded terminal.
|
2014-11-23 21:29:11 +00:00
|
|
|
pub static GREY: Colour = Fixed(244);
|
2014-07-01 18:00:36 +00:00
|
|
|
|
2015-01-24 12:38:05 +00:00
|
|
|
/// A **File** is a wrapper around one of Rust's Path objects, along with
|
|
|
|
/// associated data about the file.
|
|
|
|
///
|
|
|
|
/// Each file is definitely going to have its filename displayed at least
|
|
|
|
/// once, have its file extension extracted at least once, and have its stat
|
|
|
|
/// information queried at least once, so it makes sense to do all this at the
|
|
|
|
/// start and hold on to all the information.
|
2014-05-04 20:33:14 +00:00
|
|
|
pub struct File<'a> {
|
2014-06-29 20:02:14 +00:00
|
|
|
pub name: String,
|
2014-11-26 07:40:52 +00:00
|
|
|
pub dir: Option<&'a Dir>,
|
2014-06-29 20:02:14 +00:00
|
|
|
pub ext: Option<String>,
|
Use new io + path + fs libraries (LOTS OF CHANGES)
Exa now uses the new IO, Path, and Filesystem libraries that have been out for a while now.
Unfortunately, the new libraries don't *entirely* cover the range of the old libraries just yet: in particular, to become more cross-platform, the data in `UnstableFileStat` isn't available in the Unix `MetadataExt` yet. Much of this is contained in rust-lang/rfcs#1044 (which is due to be implemented in rust-lang/rust#14711), but it's not *entirely* there yet.
As such, this commits a serious loss of functionality: no symlink viewing, no hard links or blocks, or users or groups. Also, some of the code could now be optimised. I just wanted to commit this to sort out most of the 'teething problems' of having a different path system in advance.
Here's an example problem that took ages to fix for you, just because you read this far: when I first got exa to compile, it worked mostly fine, except calling `exa` by itself didn't list the current directory. I traced where the command-line options were being generated, to where files and directories were sorted, to where the threads were spawned... and the problem turned out to be that it was using the full path as the file name, rather than just the last component, and these paths happened to begin with `.`, so it thought they were dotfiles.
2015-04-23 12:00:34 +00:00
|
|
|
pub path: PathBuf,
|
|
|
|
pub stat: fs::Metadata,
|
2015-02-22 12:55:13 +00:00
|
|
|
pub xattrs: Vec<Attribute>,
|
2015-02-03 13:27:23 +00:00
|
|
|
pub this: Option<Dir>,
|
2014-05-04 20:33:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> File<'a> {
|
2015-01-24 12:38:05 +00:00
|
|
|
/// Create a new File object from the given Path, inside the given Dir, if
|
|
|
|
/// appropriate. Paths specified directly on the command-line have no Dirs.
|
|
|
|
///
|
2015-05-03 12:10:25 +00:00
|
|
|
/// This uses `symlink_metadata` instead of `metadata`, which doesn't
|
|
|
|
/// follow symbolic links.
|
Use new io + path + fs libraries (LOTS OF CHANGES)
Exa now uses the new IO, Path, and Filesystem libraries that have been out for a while now.
Unfortunately, the new libraries don't *entirely* cover the range of the old libraries just yet: in particular, to become more cross-platform, the data in `UnstableFileStat` isn't available in the Unix `MetadataExt` yet. Much of this is contained in rust-lang/rfcs#1044 (which is due to be implemented in rust-lang/rust#14711), but it's not *entirely* there yet.
As such, this commits a serious loss of functionality: no symlink viewing, no hard links or blocks, or users or groups. Also, some of the code could now be optimised. I just wanted to commit this to sort out most of the 'teething problems' of having a different path system in advance.
Here's an example problem that took ages to fix for you, just because you read this far: when I first got exa to compile, it worked mostly fine, except calling `exa` by itself didn't list the current directory. I traced where the command-line options were being generated, to where files and directories were sorted, to where the threads were spawned... and the problem turned out to be that it was using the full path as the file name, rather than just the last component, and these paths happened to begin with `.`, so it thought they were dotfiles.
2015-04-23 12:00:34 +00:00
|
|
|
pub fn from_path(path: &Path, parent: Option<&'a Dir>, recurse: bool) -> io::Result<File<'a>> {
|
2015-05-03 12:10:25 +00:00
|
|
|
fs::symlink_metadata(path).map(|stat| File::with_stat(stat, path, parent, recurse))
|
2014-11-25 01:27:26 +00:00
|
|
|
}
|
2014-11-25 20:50:23 +00:00
|
|
|
|
2015-01-24 12:38:05 +00:00
|
|
|
/// Create a new File object from the given Stat result, and other data.
|
Use new io + path + fs libraries (LOTS OF CHANGES)
Exa now uses the new IO, Path, and Filesystem libraries that have been out for a while now.
Unfortunately, the new libraries don't *entirely* cover the range of the old libraries just yet: in particular, to become more cross-platform, the data in `UnstableFileStat` isn't available in the Unix `MetadataExt` yet. Much of this is contained in rust-lang/rfcs#1044 (which is due to be implemented in rust-lang/rust#14711), but it's not *entirely* there yet.
As such, this commits a serious loss of functionality: no symlink viewing, no hard links or blocks, or users or groups. Also, some of the code could now be optimised. I just wanted to commit this to sort out most of the 'teething problems' of having a different path system in advance.
Here's an example problem that took ages to fix for you, just because you read this far: when I first got exa to compile, it worked mostly fine, except calling `exa` by itself didn't list the current directory. I traced where the command-line options were being generated, to where files and directories were sorted, to where the threads were spawned... and the problem turned out to be that it was using the full path as the file name, rather than just the last component, and these paths happened to begin with `.`, so it thought they were dotfiles.
2015-04-23 12:00:34 +00:00
|
|
|
pub fn with_stat(stat: fs::Metadata, path: &Path, parent: Option<&'a Dir>, recurse: bool) -> File<'a> {
|
2015-02-23 11:32:35 +00:00
|
|
|
let filename = path_filename(path);
|
2014-06-21 18:39:27 +00:00
|
|
|
|
2015-02-03 13:27:23 +00:00
|
|
|
// If we are recursing, then the `this` field contains a Dir object
|
|
|
|
// that represents the current File as a directory, if it is a
|
|
|
|
// directory. This is used for the --tree option.
|
Use new io + path + fs libraries (LOTS OF CHANGES)
Exa now uses the new IO, Path, and Filesystem libraries that have been out for a while now.
Unfortunately, the new libraries don't *entirely* cover the range of the old libraries just yet: in particular, to become more cross-platform, the data in `UnstableFileStat` isn't available in the Unix `MetadataExt` yet. Much of this is contained in rust-lang/rfcs#1044 (which is due to be implemented in rust-lang/rust#14711), but it's not *entirely* there yet.
As such, this commits a serious loss of functionality: no symlink viewing, no hard links or blocks, or users or groups. Also, some of the code could now be optimised. I just wanted to commit this to sort out most of the 'teething problems' of having a different path system in advance.
Here's an example problem that took ages to fix for you, just because you read this far: when I first got exa to compile, it worked mostly fine, except calling `exa` by itself didn't list the current directory. I traced where the command-line options were being generated, to where files and directories were sorted, to where the threads were spawned... and the problem turned out to be that it was using the full path as the file name, rather than just the last component, and these paths happened to begin with `.`, so it thought they were dotfiles.
2015-04-23 12:00:34 +00:00
|
|
|
let this = if recurse && stat.is_dir() {
|
2015-02-03 13:27:23 +00:00
|
|
|
Dir::readdir(path).ok()
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
|
2014-12-12 11:17:55 +00:00
|
|
|
File {
|
Use new io + path + fs libraries (LOTS OF CHANGES)
Exa now uses the new IO, Path, and Filesystem libraries that have been out for a while now.
Unfortunately, the new libraries don't *entirely* cover the range of the old libraries just yet: in particular, to become more cross-platform, the data in `UnstableFileStat` isn't available in the Unix `MetadataExt` yet. Much of this is contained in rust-lang/rfcs#1044 (which is due to be implemented in rust-lang/rust#14711), but it's not *entirely* there yet.
As such, this commits a serious loss of functionality: no symlink viewing, no hard links or blocks, or users or groups. Also, some of the code could now be optimised. I just wanted to commit this to sort out most of the 'teething problems' of having a different path system in advance.
Here's an example problem that took ages to fix for you, just because you read this far: when I first got exa to compile, it worked mostly fine, except calling `exa` by itself didn't list the current directory. I traced where the command-line options were being generated, to where files and directories were sorted, to where the threads were spawned... and the problem turned out to be that it was using the full path as the file name, rather than just the last component, and these paths happened to begin with `.`, so it thought they were dotfiles.
2015-04-23 12:00:34 +00:00
|
|
|
path: path.to_path_buf(),
|
2015-02-23 14:52:07 +00:00
|
|
|
dir: parent,
|
|
|
|
stat: stat,
|
|
|
|
ext: ext(&filename),
|
2015-03-26 00:37:12 +00:00
|
|
|
xattrs: Attribute::llist(path).unwrap_or(Vec::new()),
|
2015-02-23 14:52:07 +00:00
|
|
|
name: filename.to_string(),
|
|
|
|
this: this,
|
2014-12-12 11:17:55 +00:00
|
|
|
}
|
2014-05-04 20:33:14 +00:00
|
|
|
}
|
|
|
|
|
Use new io + path + fs libraries (LOTS OF CHANGES)
Exa now uses the new IO, Path, and Filesystem libraries that have been out for a while now.
Unfortunately, the new libraries don't *entirely* cover the range of the old libraries just yet: in particular, to become more cross-platform, the data in `UnstableFileStat` isn't available in the Unix `MetadataExt` yet. Much of this is contained in rust-lang/rfcs#1044 (which is due to be implemented in rust-lang/rust#14711), but it's not *entirely* there yet.
As such, this commits a serious loss of functionality: no symlink viewing, no hard links or blocks, or users or groups. Also, some of the code could now be optimised. I just wanted to commit this to sort out most of the 'teething problems' of having a different path system in advance.
Here's an example problem that took ages to fix for you, just because you read this far: when I first got exa to compile, it worked mostly fine, except calling `exa` by itself didn't list the current directory. I traced where the command-line options were being generated, to where files and directories were sorted, to where the threads were spawned... and the problem turned out to be that it was using the full path as the file name, rather than just the last component, and these paths happened to begin with `.`, so it thought they were dotfiles.
2015-04-23 12:00:34 +00:00
|
|
|
pub fn is_directory(&self) -> bool {
|
|
|
|
self.stat.is_dir()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_file(&self) -> bool {
|
|
|
|
self.stat.is_file()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_link(&self) -> bool {
|
2015-05-03 12:10:25 +00:00
|
|
|
self.stat.file_type().is_symlink()
|
Use new io + path + fs libraries (LOTS OF CHANGES)
Exa now uses the new IO, Path, and Filesystem libraries that have been out for a while now.
Unfortunately, the new libraries don't *entirely* cover the range of the old libraries just yet: in particular, to become more cross-platform, the data in `UnstableFileStat` isn't available in the Unix `MetadataExt` yet. Much of this is contained in rust-lang/rfcs#1044 (which is due to be implemented in rust-lang/rust#14711), but it's not *entirely* there yet.
As such, this commits a serious loss of functionality: no symlink viewing, no hard links or blocks, or users or groups. Also, some of the code could now be optimised. I just wanted to commit this to sort out most of the 'teething problems' of having a different path system in advance.
Here's an example problem that took ages to fix for you, just because you read this far: when I first got exa to compile, it worked mostly fine, except calling `exa` by itself didn't list the current directory. I traced where the command-line options were being generated, to where files and directories were sorted, to where the threads were spawned... and the problem turned out to be that it was using the full path as the file name, rather than just the last component, and these paths happened to begin with `.`, so it thought they were dotfiles.
2015-04-23 12:00:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_pipe(&self) -> bool {
|
2015-05-03 12:10:25 +00:00
|
|
|
false // TODO: Still waiting on this one...
|
Use new io + path + fs libraries (LOTS OF CHANGES)
Exa now uses the new IO, Path, and Filesystem libraries that have been out for a while now.
Unfortunately, the new libraries don't *entirely* cover the range of the old libraries just yet: in particular, to become more cross-platform, the data in `UnstableFileStat` isn't available in the Unix `MetadataExt` yet. Much of this is contained in rust-lang/rfcs#1044 (which is due to be implemented in rust-lang/rust#14711), but it's not *entirely* there yet.
As such, this commits a serious loss of functionality: no symlink viewing, no hard links or blocks, or users or groups. Also, some of the code could now be optimised. I just wanted to commit this to sort out most of the 'teething problems' of having a different path system in advance.
Here's an example problem that took ages to fix for you, just because you read this far: when I first got exa to compile, it worked mostly fine, except calling `exa` by itself didn't list the current directory. I traced where the command-line options were being generated, to where files and directories were sorted, to where the threads were spawned... and the problem turned out to be that it was using the full path as the file name, rather than just the last component, and these paths happened to begin with `.`, so it thought they were dotfiles.
2015-04-23 12:00:34 +00:00
|
|
|
}
|
|
|
|
|
2015-01-24 12:38:05 +00:00
|
|
|
/// Whether this file is a dotfile or not.
|
2014-05-05 09:51:24 +00:00
|
|
|
pub fn is_dotfile(&self) -> bool {
|
2015-02-22 17:11:33 +00:00
|
|
|
self.name.starts_with(".")
|
2014-05-05 09:51:24 +00:00
|
|
|
}
|
|
|
|
|
2015-01-24 12:38:05 +00:00
|
|
|
/// Whether this file is a temporary file or not.
|
2014-06-17 08:35:40 +00:00
|
|
|
pub fn is_tmpfile(&self) -> bool {
|
2015-02-22 17:11:33 +00:00
|
|
|
let name = &self.name;
|
2014-06-29 20:02:14 +00:00
|
|
|
name.ends_with("~") || (name.starts_with("#") && name.ends_with("#"))
|
2014-06-16 11:43:34 +00:00
|
|
|
}
|
2014-06-21 18:39:27 +00:00
|
|
|
|
2015-01-24 12:38:05 +00:00
|
|
|
/// Get the data for a column, formatted as a coloured string.
|
2015-02-10 18:14:56 +00:00
|
|
|
pub fn display<U: Users>(&self, column: &Column, users_cache: &mut U, locale: &UserLocale) -> Cell {
|
2014-05-04 20:33:14 +00:00
|
|
|
match *column {
|
2015-02-09 18:14:05 +00:00
|
|
|
Permissions => self.permissions_string(),
|
2015-02-10 18:14:56 +00:00
|
|
|
FileSize(f) => self.file_size(f, &locale.numeric),
|
|
|
|
Timestamp(t, y) => self.timestamp(t, y, &locale.time),
|
|
|
|
HardLinks => self.hard_links(&locale.numeric),
|
2015-02-09 18:14:05 +00:00
|
|
|
Inode => self.inode(),
|
2015-02-10 18:14:56 +00:00
|
|
|
Blocks => self.blocks(&locale.numeric),
|
2015-02-09 18:14:05 +00:00
|
|
|
User => self.user(users_cache),
|
|
|
|
Group => self.group(users_cache),
|
|
|
|
GitStatus => self.git_status(),
|
2014-05-04 20:33:14 +00:00
|
|
|
}
|
|
|
|
}
|
2014-06-21 18:39:27 +00:00
|
|
|
|
2015-01-24 12:38:05 +00:00
|
|
|
/// The "file name view" is what's displayed in the column and lines
|
|
|
|
/// views, but *not* in the grid view.
|
|
|
|
///
|
2015-01-24 17:32:30 +00:00
|
|
|
/// It consists of the file name coloured in the appropriate style,
|
|
|
|
/// with special formatting for a symlink.
|
2015-02-03 13:48:39 +00:00
|
|
|
pub fn file_name_view(&self) -> String {
|
Use new io + path + fs libraries (LOTS OF CHANGES)
Exa now uses the new IO, Path, and Filesystem libraries that have been out for a while now.
Unfortunately, the new libraries don't *entirely* cover the range of the old libraries just yet: in particular, to become more cross-platform, the data in `UnstableFileStat` isn't available in the Unix `MetadataExt` yet. Much of this is contained in rust-lang/rfcs#1044 (which is due to be implemented in rust-lang/rust#14711), but it's not *entirely* there yet.
As such, this commits a serious loss of functionality: no symlink viewing, no hard links or blocks, or users or groups. Also, some of the code could now be optimised. I just wanted to commit this to sort out most of the 'teething problems' of having a different path system in advance.
Here's an example problem that took ages to fix for you, just because you read this far: when I first got exa to compile, it worked mostly fine, except calling `exa` by itself didn't list the current directory. I traced where the command-line options were being generated, to where files and directories were sorted, to where the threads were spawned... and the problem turned out to be that it was using the full path as the file name, rather than just the last component, and these paths happened to begin with `.`, so it thought they were dotfiles.
2015-04-23 12:00:34 +00:00
|
|
|
if self.is_link() {
|
2015-01-24 17:32:30 +00:00
|
|
|
self.symlink_file_name_view()
|
|
|
|
}
|
|
|
|
else {
|
2015-02-03 13:48:39 +00:00
|
|
|
self.file_colour().paint(&*self.name).to_string()
|
2015-01-24 17:32:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// If this file is a symlink, returns a string displaying its name,
|
|
|
|
/// and an arrow pointing to the file it links to, which is also
|
2015-01-24 17:26:26 +00:00
|
|
|
/// coloured in the appropriate style.
|
|
|
|
///
|
|
|
|
/// If the symlink target doesn't exist, then instead of displaying
|
|
|
|
/// an error, highlight the target and arrow in red. The error would
|
|
|
|
/// be shown out of context, and it's almost always because the
|
|
|
|
/// target doesn't exist.
|
2015-02-03 13:48:39 +00:00
|
|
|
fn symlink_file_name_view(&self) -> String {
|
2015-01-24 17:26:26 +00:00
|
|
|
let name = &*self.name;
|
|
|
|
let style = self.file_colour();
|
|
|
|
|
Use new io + path + fs libraries (LOTS OF CHANGES)
Exa now uses the new IO, Path, and Filesystem libraries that have been out for a while now.
Unfortunately, the new libraries don't *entirely* cover the range of the old libraries just yet: in particular, to become more cross-platform, the data in `UnstableFileStat` isn't available in the Unix `MetadataExt` yet. Much of this is contained in rust-lang/rfcs#1044 (which is due to be implemented in rust-lang/rust#14711), but it's not *entirely* there yet.
As such, this commits a serious loss of functionality: no symlink viewing, no hard links or blocks, or users or groups. Also, some of the code could now be optimised. I just wanted to commit this to sort out most of the 'teething problems' of having a different path system in advance.
Here's an example problem that took ages to fix for you, just because you read this far: when I first got exa to compile, it worked mostly fine, except calling `exa` by itself didn't list the current directory. I traced where the command-line options were being generated, to where files and directories were sorted, to where the threads were spawned... and the problem turned out to be that it was using the full path as the file name, rather than just the last component, and these paths happened to begin with `.`, so it thought they were dotfiles.
2015-04-23 12:00:34 +00:00
|
|
|
if let Ok(path) = fs::read_link(&self.path) {
|
2015-01-24 17:32:30 +00:00
|
|
|
let target_path = match self.dir {
|
Use new io + path + fs libraries (LOTS OF CHANGES)
Exa now uses the new IO, Path, and Filesystem libraries that have been out for a while now.
Unfortunately, the new libraries don't *entirely* cover the range of the old libraries just yet: in particular, to become more cross-platform, the data in `UnstableFileStat` isn't available in the Unix `MetadataExt` yet. Much of this is contained in rust-lang/rfcs#1044 (which is due to be implemented in rust-lang/rust#14711), but it's not *entirely* there yet.
As such, this commits a serious loss of functionality: no symlink viewing, no hard links or blocks, or users or groups. Also, some of the code could now be optimised. I just wanted to commit this to sort out most of the 'teething problems' of having a different path system in advance.
Here's an example problem that took ages to fix for you, just because you read this far: when I first got exa to compile, it worked mostly fine, except calling `exa` by itself didn't list the current directory. I traced where the command-line options were being generated, to where files and directories were sorted, to where the threads were spawned... and the problem turned out to be that it was using the full path as the file name, rather than just the last component, and these paths happened to begin with `.`, so it thought they were dotfiles.
2015-04-23 12:00:34 +00:00
|
|
|
Some(dir) => dir.join(&*path),
|
2015-01-24 17:32:30 +00:00
|
|
|
None => path,
|
|
|
|
};
|
|
|
|
|
|
|
|
match self.target_file(&target_path) {
|
2015-02-23 11:32:35 +00:00
|
|
|
Ok(file) => {
|
|
|
|
|
|
|
|
// Generate a preview for the path this symlink links to.
|
|
|
|
// The preview should consist of the directory of the file
|
|
|
|
// (if present) in cyan, an extra slash if necessary, then
|
|
|
|
// the target file, colourised in the appropriate style.
|
|
|
|
let mut path_prefix = String::new();
|
|
|
|
|
Use new io + path + fs libraries (LOTS OF CHANGES)
Exa now uses the new IO, Path, and Filesystem libraries that have been out for a while now.
Unfortunately, the new libraries don't *entirely* cover the range of the old libraries just yet: in particular, to become more cross-platform, the data in `UnstableFileStat` isn't available in the Unix `MetadataExt` yet. Much of this is contained in rust-lang/rfcs#1044 (which is due to be implemented in rust-lang/rust#14711), but it's not *entirely* there yet.
As such, this commits a serious loss of functionality: no symlink viewing, no hard links or blocks, or users or groups. Also, some of the code could now be optimised. I just wanted to commit this to sort out most of the 'teething problems' of having a different path system in advance.
Here's an example problem that took ages to fix for you, just because you read this far: when I first got exa to compile, it worked mostly fine, except calling `exa` by itself didn't list the current directory. I traced where the command-line options were being generated, to where files and directories were sorted, to where the threads were spawned... and the problem turned out to be that it was using the full path as the file name, rather than just the last component, and these paths happened to begin with `.`, so it thought they were dotfiles.
2015-04-23 12:00:34 +00:00
|
|
|
let path_bytes: Vec<Component> = file.path.components().collect();
|
2015-02-23 11:32:35 +00:00
|
|
|
if !path_bytes.is_empty() {
|
|
|
|
// Use init() to add all but the last component of the
|
|
|
|
// path to the prefix. init() panics when given an
|
|
|
|
// empty list, hence the check.
|
|
|
|
for component in path_bytes.init().iter() {
|
Use new io + path + fs libraries (LOTS OF CHANGES)
Exa now uses the new IO, Path, and Filesystem libraries that have been out for a while now.
Unfortunately, the new libraries don't *entirely* cover the range of the old libraries just yet: in particular, to become more cross-platform, the data in `UnstableFileStat` isn't available in the Unix `MetadataExt` yet. Much of this is contained in rust-lang/rfcs#1044 (which is due to be implemented in rust-lang/rust#14711), but it's not *entirely* there yet.
As such, this commits a serious loss of functionality: no symlink viewing, no hard links or blocks, or users or groups. Also, some of the code could now be optimised. I just wanted to commit this to sort out most of the 'teething problems' of having a different path system in advance.
Here's an example problem that took ages to fix for you, just because you read this far: when I first got exa to compile, it worked mostly fine, except calling `exa` by itself didn't list the current directory. I traced where the command-line options were being generated, to where files and directories were sorted, to where the threads were spawned... and the problem turned out to be that it was using the full path as the file name, rather than just the last component, and these paths happened to begin with `.`, so it thought they were dotfiles.
2015-04-23 12:00:34 +00:00
|
|
|
path_prefix.push_str(&*component.as_os_str().to_string_lossy());
|
2015-05-03 12:10:25 +00:00
|
|
|
|
|
|
|
if component != &Component::RootDir {
|
|
|
|
path_prefix.push_str("/");
|
|
|
|
}
|
2015-02-23 11:32:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
format!("{} {} {}",
|
|
|
|
style.paint(name),
|
|
|
|
GREY.paint("=>"),
|
|
|
|
ANSIStrings(&[ Cyan.paint(&path_prefix),
|
|
|
|
file.file_colour().paint(&file.name) ]))
|
|
|
|
},
|
2015-02-03 13:48:39 +00:00
|
|
|
Err(filename) => format!("{} {} {}",
|
|
|
|
style.paint(name),
|
|
|
|
Red.paint("=>"),
|
2015-02-22 17:11:33 +00:00
|
|
|
Red.underline().paint(&filename)),
|
2014-06-21 09:11:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2015-02-03 13:48:39 +00:00
|
|
|
style.paint(name).to_string()
|
2014-06-21 09:11:50 +00:00
|
|
|
}
|
|
|
|
}
|
2014-06-21 18:39:27 +00:00
|
|
|
|
2015-01-24 12:38:05 +00:00
|
|
|
/// The `ansi_term::Style` that this file's name should be painted.
|
|
|
|
pub fn file_colour(&self) -> Style {
|
|
|
|
self.get_type().style()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// The Unicode 'display width' of the filename.
|
|
|
|
///
|
|
|
|
/// This is related to the number of graphemes in the string: most
|
|
|
|
/// characters are 1 columns wide, but in some contexts, certain
|
|
|
|
/// characters are actually 2 columns wide.
|
2015-01-12 00:31:24 +00:00
|
|
|
pub fn file_name_width(&self) -> usize {
|
2015-04-23 12:46:37 +00:00
|
|
|
UnicodeWidthStr::width(&self.name[..])
|
2014-07-22 14:41:20 +00:00
|
|
|
}
|
|
|
|
|
2015-01-24 17:26:26 +00:00
|
|
|
/// Assuming the current file is a symlink, follows the link and
|
|
|
|
/// returns a File object from the path the link points to.
|
|
|
|
///
|
|
|
|
/// If statting the file fails (usually because the file on the
|
|
|
|
/// other end doesn't exist), returns the *filename* of the file
|
|
|
|
/// that should be there.
|
|
|
|
fn target_file(&self, target_path: &Path) -> Result<File, String> {
|
2015-02-23 11:32:35 +00:00
|
|
|
let filename = path_filename(target_path);
|
2014-11-25 20:50:23 +00:00
|
|
|
|
2015-05-03 12:10:25 +00:00
|
|
|
// Use plain `metadata` instead of `symlink_metadata` - we *want* to follow links.
|
Use new io + path + fs libraries (LOTS OF CHANGES)
Exa now uses the new IO, Path, and Filesystem libraries that have been out for a while now.
Unfortunately, the new libraries don't *entirely* cover the range of the old libraries just yet: in particular, to become more cross-platform, the data in `UnstableFileStat` isn't available in the Unix `MetadataExt` yet. Much of this is contained in rust-lang/rfcs#1044 (which is due to be implemented in rust-lang/rust#14711), but it's not *entirely* there yet.
As such, this commits a serious loss of functionality: no symlink viewing, no hard links or blocks, or users or groups. Also, some of the code could now be optimised. I just wanted to commit this to sort out most of the 'teething problems' of having a different path system in advance.
Here's an example problem that took ages to fix for you, just because you read this far: when I first got exa to compile, it worked mostly fine, except calling `exa` by itself didn't list the current directory. I traced where the command-line options were being generated, to where files and directories were sorted, to where the threads were spawned... and the problem turned out to be that it was using the full path as the file name, rather than just the last component, and these paths happened to begin with `.`, so it thought they were dotfiles.
2015-04-23 12:00:34 +00:00
|
|
|
if let Ok(stat) = fs::metadata(target_path) {
|
2015-01-24 17:26:26 +00:00
|
|
|
Ok(File {
|
Use new io + path + fs libraries (LOTS OF CHANGES)
Exa now uses the new IO, Path, and Filesystem libraries that have been out for a while now.
Unfortunately, the new libraries don't *entirely* cover the range of the old libraries just yet: in particular, to become more cross-platform, the data in `UnstableFileStat` isn't available in the Unix `MetadataExt` yet. Much of this is contained in rust-lang/rfcs#1044 (which is due to be implemented in rust-lang/rust#14711), but it's not *entirely* there yet.
As such, this commits a serious loss of functionality: no symlink viewing, no hard links or blocks, or users or groups. Also, some of the code could now be optimised. I just wanted to commit this to sort out most of the 'teething problems' of having a different path system in advance.
Here's an example problem that took ages to fix for you, just because you read this far: when I first got exa to compile, it worked mostly fine, except calling `exa` by itself didn't list the current directory. I traced where the command-line options were being generated, to where files and directories were sorted, to where the threads were spawned... and the problem turned out to be that it was using the full path as the file name, rather than just the last component, and these paths happened to begin with `.`, so it thought they were dotfiles.
2015-04-23 12:00:34 +00:00
|
|
|
path: target_path.to_path_buf(),
|
2015-02-23 14:52:07 +00:00
|
|
|
dir: self.dir,
|
|
|
|
stat: stat,
|
|
|
|
ext: ext(&filename),
|
2015-03-26 00:37:12 +00:00
|
|
|
xattrs: Attribute::list(target_path).unwrap_or(Vec::new()),
|
2015-02-23 14:52:07 +00:00
|
|
|
name: filename.to_string(),
|
|
|
|
this: None,
|
2015-01-24 17:26:26 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
Err(filename.to_string())
|
2014-06-21 18:39:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-24 12:38:05 +00:00
|
|
|
/// This file's number of hard links as a coloured string.
|
2015-02-10 16:21:19 +00:00
|
|
|
fn hard_links(&self, locale: &locale::Numeric) -> Cell {
|
2015-01-24 12:38:05 +00:00
|
|
|
let style = if self.has_multiple_links() { Red.on(Yellow) } else { Red.normal() };
|
2015-05-03 11:46:05 +00:00
|
|
|
Cell::paint(style, &locale.format_int(self.stat.as_raw().nlink())[..])
|
2015-01-24 12:38:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Whether this is a regular file with more than one link.
|
|
|
|
///
|
|
|
|
/// This is important, because a file with multiple links is uncommon,
|
|
|
|
/// while you can come across directories and other types with multiple
|
|
|
|
/// links much more often.
|
|
|
|
fn has_multiple_links(&self) -> bool {
|
2015-05-03 11:46:05 +00:00
|
|
|
self.is_file() && self.stat.as_raw().nlink() > 1
|
2015-01-24 12:38:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// This file's inode as a coloured string.
|
2015-01-24 17:26:26 +00:00
|
|
|
fn inode(&self) -> Cell {
|
2015-05-03 11:46:05 +00:00
|
|
|
let inode = self.stat.as_raw().ino();
|
Use new io + path + fs libraries (LOTS OF CHANGES)
Exa now uses the new IO, Path, and Filesystem libraries that have been out for a while now.
Unfortunately, the new libraries don't *entirely* cover the range of the old libraries just yet: in particular, to become more cross-platform, the data in `UnstableFileStat` isn't available in the Unix `MetadataExt` yet. Much of this is contained in rust-lang/rfcs#1044 (which is due to be implemented in rust-lang/rust#14711), but it's not *entirely* there yet.
As such, this commits a serious loss of functionality: no symlink viewing, no hard links or blocks, or users or groups. Also, some of the code could now be optimised. I just wanted to commit this to sort out most of the 'teething problems' of having a different path system in advance.
Here's an example problem that took ages to fix for you, just because you read this far: when I first got exa to compile, it worked mostly fine, except calling `exa` by itself didn't list the current directory. I traced where the command-line options were being generated, to where files and directories were sorted, to where the threads were spawned... and the problem turned out to be that it was using the full path as the file name, rather than just the last component, and these paths happened to begin with `.`, so it thought they were dotfiles.
2015-04-23 12:00:34 +00:00
|
|
|
Cell::paint(Purple.normal(), &inode.to_string()[..])
|
2015-01-24 12:38:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// This file's number of filesystem blocks (if available) as a coloured string.
|
2015-02-10 16:21:19 +00:00
|
|
|
fn blocks(&self, locale: &locale::Numeric) -> Cell {
|
Use new io + path + fs libraries (LOTS OF CHANGES)
Exa now uses the new IO, Path, and Filesystem libraries that have been out for a while now.
Unfortunately, the new libraries don't *entirely* cover the range of the old libraries just yet: in particular, to become more cross-platform, the data in `UnstableFileStat` isn't available in the Unix `MetadataExt` yet. Much of this is contained in rust-lang/rfcs#1044 (which is due to be implemented in rust-lang/rust#14711), but it's not *entirely* there yet.
As such, this commits a serious loss of functionality: no symlink viewing, no hard links or blocks, or users or groups. Also, some of the code could now be optimised. I just wanted to commit this to sort out most of the 'teething problems' of having a different path system in advance.
Here's an example problem that took ages to fix for you, just because you read this far: when I first got exa to compile, it worked mostly fine, except calling `exa` by itself didn't list the current directory. I traced where the command-line options were being generated, to where files and directories were sorted, to where the threads were spawned... and the problem turned out to be that it was using the full path as the file name, rather than just the last component, and these paths happened to begin with `.`, so it thought they were dotfiles.
2015-04-23 12:00:34 +00:00
|
|
|
if self.is_file() || self.is_link() {
|
2015-05-03 11:46:05 +00:00
|
|
|
Cell::paint(Cyan.normal(), &locale.format_int(self.stat.as_raw().blocks())[..])
|
2015-01-24 12:38:05 +00:00
|
|
|
}
|
|
|
|
else {
|
2015-01-24 17:26:26 +00:00
|
|
|
Cell { text: GREY.paint("-").to_string(), length: 1 }
|
2015-01-24 12:38:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// This file's owner's username as a coloured string.
|
|
|
|
///
|
|
|
|
/// If the user is not present, then it formats the uid as a number
|
|
|
|
/// instead. This usually happens when a user is deleted, but still owns
|
|
|
|
/// files.
|
2015-01-24 17:26:26 +00:00
|
|
|
fn user<U: Users>(&self, users_cache: &mut U) -> Cell {
|
2015-05-03 11:46:05 +00:00
|
|
|
let uid = self.stat.as_raw().uid();
|
2015-01-24 12:38:05 +00:00
|
|
|
|
|
|
|
let user_name = match users_cache.get_user_by_uid(uid) {
|
|
|
|
Some(user) => user.name,
|
Use new io + path + fs libraries (LOTS OF CHANGES)
Exa now uses the new IO, Path, and Filesystem libraries that have been out for a while now.
Unfortunately, the new libraries don't *entirely* cover the range of the old libraries just yet: in particular, to become more cross-platform, the data in `UnstableFileStat` isn't available in the Unix `MetadataExt` yet. Much of this is contained in rust-lang/rfcs#1044 (which is due to be implemented in rust-lang/rust#14711), but it's not *entirely* there yet.
As such, this commits a serious loss of functionality: no symlink viewing, no hard links or blocks, or users or groups. Also, some of the code could now be optimised. I just wanted to commit this to sort out most of the 'teething problems' of having a different path system in advance.
Here's an example problem that took ages to fix for you, just because you read this far: when I first got exa to compile, it worked mostly fine, except calling `exa` by itself didn't list the current directory. I traced where the command-line options were being generated, to where files and directories were sorted, to where the threads were spawned... and the problem turned out to be that it was using the full path as the file name, rather than just the last component, and these paths happened to begin with `.`, so it thought they were dotfiles.
2015-04-23 12:00:34 +00:00
|
|
|
None => uid.to_string(),
|
2015-01-24 12:38:05 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
let style = if users_cache.get_current_uid() == uid { Yellow.bold() } else { Plain };
|
2015-01-24 17:26:26 +00:00
|
|
|
Cell::paint(style, &*user_name)
|
2015-01-24 12:38:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// This file's group name as a coloured string.
|
|
|
|
///
|
|
|
|
/// As above, if not present, it formats the gid as a number instead.
|
2015-01-24 17:26:26 +00:00
|
|
|
fn group<U: Users>(&self, users_cache: &mut U) -> Cell {
|
2015-05-03 11:46:05 +00:00
|
|
|
let gid = self.stat.as_raw().gid();
|
2015-01-24 12:38:05 +00:00
|
|
|
let mut style = Plain;
|
|
|
|
|
Use new io + path + fs libraries (LOTS OF CHANGES)
Exa now uses the new IO, Path, and Filesystem libraries that have been out for a while now.
Unfortunately, the new libraries don't *entirely* cover the range of the old libraries just yet: in particular, to become more cross-platform, the data in `UnstableFileStat` isn't available in the Unix `MetadataExt` yet. Much of this is contained in rust-lang/rfcs#1044 (which is due to be implemented in rust-lang/rust#14711), but it's not *entirely* there yet.
As such, this commits a serious loss of functionality: no symlink viewing, no hard links or blocks, or users or groups. Also, some of the code could now be optimised. I just wanted to commit this to sort out most of the 'teething problems' of having a different path system in advance.
Here's an example problem that took ages to fix for you, just because you read this far: when I first got exa to compile, it worked mostly fine, except calling `exa` by itself didn't list the current directory. I traced where the command-line options were being generated, to where files and directories were sorted, to where the threads were spawned... and the problem turned out to be that it was using the full path as the file name, rather than just the last component, and these paths happened to begin with `.`, so it thought they were dotfiles.
2015-04-23 12:00:34 +00:00
|
|
|
let group_name = match users_cache.get_group_by_gid(gid as u32) {
|
2015-01-24 12:38:05 +00:00
|
|
|
Some(group) => {
|
|
|
|
let current_uid = users_cache.get_current_uid();
|
|
|
|
if let Some(current_user) = users_cache.get_user_by_uid(current_uid) {
|
|
|
|
if current_user.primary_group == group.gid || group.members.contains(¤t_user.name) {
|
|
|
|
style = Yellow.bold();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
group.name
|
|
|
|
},
|
Use new io + path + fs libraries (LOTS OF CHANGES)
Exa now uses the new IO, Path, and Filesystem libraries that have been out for a while now.
Unfortunately, the new libraries don't *entirely* cover the range of the old libraries just yet: in particular, to become more cross-platform, the data in `UnstableFileStat` isn't available in the Unix `MetadataExt` yet. Much of this is contained in rust-lang/rfcs#1044 (which is due to be implemented in rust-lang/rust#14711), but it's not *entirely* there yet.
As such, this commits a serious loss of functionality: no symlink viewing, no hard links or blocks, or users or groups. Also, some of the code could now be optimised. I just wanted to commit this to sort out most of the 'teething problems' of having a different path system in advance.
Here's an example problem that took ages to fix for you, just because you read this far: when I first got exa to compile, it worked mostly fine, except calling `exa` by itself didn't list the current directory. I traced where the command-line options were being generated, to where files and directories were sorted, to where the threads were spawned... and the problem turned out to be that it was using the full path as the file name, rather than just the last component, and these paths happened to begin with `.`, so it thought they were dotfiles.
2015-04-23 12:00:34 +00:00
|
|
|
None => gid.to_string(),
|
2015-01-24 12:38:05 +00:00
|
|
|
};
|
|
|
|
|
2015-01-24 17:26:26 +00:00
|
|
|
Cell::paint(style, &*group_name)
|
2015-01-24 12:38:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// This file's size, formatted using the given way, as a coloured string.
|
|
|
|
///
|
|
|
|
/// For directories, no size is given. Although they do have a size on
|
|
|
|
/// some filesystems, I've never looked at one of those numbers and gained
|
|
|
|
/// any information from it, so by emitting "-" instead, the table is less
|
|
|
|
/// cluttered with numbers.
|
2015-02-10 16:08:10 +00:00
|
|
|
fn file_size(&self, size_format: SizeFormat, locale: &locale::Numeric) -> Cell {
|
2015-02-26 14:05:26 +00:00
|
|
|
if self.is_directory() {
|
2015-01-24 17:26:26 +00:00
|
|
|
Cell { text: GREY.paint("-").to_string(), length: 1 }
|
2014-11-25 20:50:23 +00:00
|
|
|
}
|
|
|
|
else {
|
2015-01-05 14:41:43 +00:00
|
|
|
let result = match size_format {
|
Use new io + path + fs libraries (LOTS OF CHANGES)
Exa now uses the new IO, Path, and Filesystem libraries that have been out for a while now.
Unfortunately, the new libraries don't *entirely* cover the range of the old libraries just yet: in particular, to become more cross-platform, the data in `UnstableFileStat` isn't available in the Unix `MetadataExt` yet. Much of this is contained in rust-lang/rfcs#1044 (which is due to be implemented in rust-lang/rust#14711), but it's not *entirely* there yet.
As such, this commits a serious loss of functionality: no symlink viewing, no hard links or blocks, or users or groups. Also, some of the code could now be optimised. I just wanted to commit this to sort out most of the 'teething problems' of having a different path system in advance.
Here's an example problem that took ages to fix for you, just because you read this far: when I first got exa to compile, it worked mostly fine, except calling `exa` by itself didn't list the current directory. I traced where the command-line options were being generated, to where files and directories were sorted, to where the threads were spawned... and the problem turned out to be that it was using the full path as the file name, rather than just the last component, and these paths happened to begin with `.`, so it thought they were dotfiles.
2015-04-23 12:00:34 +00:00
|
|
|
SizeFormat::DecimalBytes => decimal_prefix(self.stat.len() as f64),
|
|
|
|
SizeFormat::BinaryBytes => binary_prefix(self.stat.len() as f64),
|
|
|
|
SizeFormat::JustBytes => return Cell::paint(Green.bold(), &locale.format_int(self.stat.len())[..]),
|
2015-01-05 14:41:43 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
match result {
|
2015-01-24 17:26:26 +00:00
|
|
|
Standalone(bytes) => Cell::paint(Green.bold(), &*bytes.to_string()),
|
2015-01-05 14:41:43 +00:00
|
|
|
Prefixed(prefix, n) => {
|
2015-02-12 22:33:01 +00:00
|
|
|
let number = if n < 10f64 { locale.format_float(n, 1) } else { locale.format_int(n as isize) };
|
2015-01-24 17:26:26 +00:00
|
|
|
let symbol = prefix.symbol();
|
|
|
|
|
|
|
|
Cell {
|
2015-02-21 13:54:35 +00:00
|
|
|
text: ANSIStrings( &[ Green.bold().paint(&number[..]), Green.paint(symbol) ]).to_string(),
|
2015-01-24 17:26:26 +00:00
|
|
|
length: number.len() + symbol.len(),
|
|
|
|
}
|
2015-01-05 14:41:43 +00:00
|
|
|
}
|
|
|
|
}
|
2014-05-25 14:52:36 +00:00
|
|
|
}
|
2014-05-04 20:33:14 +00:00
|
|
|
}
|
|
|
|
|
2015-02-10 18:14:56 +00:00
|
|
|
fn timestamp(&self, time_type: TimeType, current_year: i64, locale: &locale::Time) -> Cell {
|
2015-02-09 16:33:27 +00:00
|
|
|
|
|
|
|
// Need to convert these values from milliseconds into seconds.
|
|
|
|
let time_in_seconds = match time_type {
|
Use new io + path + fs libraries (LOTS OF CHANGES)
Exa now uses the new IO, Path, and Filesystem libraries that have been out for a while now.
Unfortunately, the new libraries don't *entirely* cover the range of the old libraries just yet: in particular, to become more cross-platform, the data in `UnstableFileStat` isn't available in the Unix `MetadataExt` yet. Much of this is contained in rust-lang/rfcs#1044 (which is due to be implemented in rust-lang/rust#14711), but it's not *entirely* there yet.
As such, this commits a serious loss of functionality: no symlink viewing, no hard links or blocks, or users or groups. Also, some of the code could now be optimised. I just wanted to commit this to sort out most of the 'teething problems' of having a different path system in advance.
Here's an example problem that took ages to fix for you, just because you read this far: when I first got exa to compile, it worked mostly fine, except calling `exa` by itself didn't list the current directory. I traced where the command-line options were being generated, to where files and directories were sorted, to where the threads were spawned... and the problem turned out to be that it was using the full path as the file name, rather than just the last component, and these paths happened to begin with `.`, so it thought they were dotfiles.
2015-04-23 12:00:34 +00:00
|
|
|
TimeType::FileAccessed => self.stat.accessed(),
|
|
|
|
TimeType::FileModified => self.stat.modified(),
|
|
|
|
TimeType::FileCreated => 0 // self.stat.created(),
|
2015-02-09 16:33:27 +00:00
|
|
|
} as i64 / 1000;
|
|
|
|
|
2015-02-09 17:55:55 +00:00
|
|
|
let date = LocalDateTime::at(time_in_seconds);
|
2015-02-09 18:14:05 +00:00
|
|
|
|
|
|
|
let format = if date.year() == current_year {
|
2015-02-10 18:14:56 +00:00
|
|
|
DateFormat::parse("{2>:D} {:M} {2>:h}:{02>:m}").unwrap()
|
2015-02-09 18:14:05 +00:00
|
|
|
}
|
|
|
|
else {
|
2015-02-22 17:50:52 +00:00
|
|
|
DateFormat::parse("{2>:D} {:M} {5>:Y}").unwrap()
|
2015-02-09 18:14:05 +00:00
|
|
|
};
|
|
|
|
|
2015-02-22 17:11:33 +00:00
|
|
|
Cell::paint(Blue.normal(), &format.format(date, locale))
|
2015-02-09 16:33:27 +00:00
|
|
|
}
|
|
|
|
|
2015-01-24 12:38:05 +00:00
|
|
|
/// This file's type, represented by a coloured character.
|
|
|
|
///
|
|
|
|
/// Although the file type can usually be guessed from the colour of the
|
|
|
|
/// file, `ls` puts this character there, so people will expect it.
|
2014-11-26 07:36:09 +00:00
|
|
|
fn type_char(&self) -> ANSIString {
|
Use new io + path + fs libraries (LOTS OF CHANGES)
Exa now uses the new IO, Path, and Filesystem libraries that have been out for a while now.
Unfortunately, the new libraries don't *entirely* cover the range of the old libraries just yet: in particular, to become more cross-platform, the data in `UnstableFileStat` isn't available in the Unix `MetadataExt` yet. Much of this is contained in rust-lang/rfcs#1044 (which is due to be implemented in rust-lang/rust#14711), but it's not *entirely* there yet.
As such, this commits a serious loss of functionality: no symlink viewing, no hard links or blocks, or users or groups. Also, some of the code could now be optimised. I just wanted to commit this to sort out most of the 'teething problems' of having a different path system in advance.
Here's an example problem that took ages to fix for you, just because you read this far: when I first got exa to compile, it worked mostly fine, except calling `exa` by itself didn't list the current directory. I traced where the command-line options were being generated, to where files and directories were sorted, to where the threads were spawned... and the problem turned out to be that it was using the full path as the file name, rather than just the last component, and these paths happened to begin with `.`, so it thought they were dotfiles.
2015-04-23 12:00:34 +00:00
|
|
|
if self.is_file() {
|
|
|
|
Plain.paint(".")
|
|
|
|
}
|
|
|
|
else if self.is_directory() {
|
|
|
|
Blue.paint("d")
|
|
|
|
}
|
|
|
|
else if self.is_pipe() {
|
|
|
|
Yellow.paint("|")
|
|
|
|
}
|
|
|
|
else if self.is_link() {
|
|
|
|
Cyan.paint("l")
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
Purple.paint("?")
|
2014-05-04 20:33:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-22 12:26:52 +00:00
|
|
|
/// Marker indicating that the file contains extended attributes
|
|
|
|
///
|
Use new io + path + fs libraries (LOTS OF CHANGES)
Exa now uses the new IO, Path, and Filesystem libraries that have been out for a while now.
Unfortunately, the new libraries don't *entirely* cover the range of the old libraries just yet: in particular, to become more cross-platform, the data in `UnstableFileStat` isn't available in the Unix `MetadataExt` yet. Much of this is contained in rust-lang/rfcs#1044 (which is due to be implemented in rust-lang/rust#14711), but it's not *entirely* there yet.
As such, this commits a serious loss of functionality: no symlink viewing, no hard links or blocks, or users or groups. Also, some of the code could now be optimised. I just wanted to commit this to sort out most of the 'teething problems' of having a different path system in advance.
Here's an example problem that took ages to fix for you, just because you read this far: when I first got exa to compile, it worked mostly fine, except calling `exa` by itself didn't list the current directory. I traced where the command-line options were being generated, to where files and directories were sorted, to where the threads were spawned... and the problem turned out to be that it was using the full path as the file name, rather than just the last component, and these paths happened to begin with `.`, so it thought they were dotfiles.
2015-04-23 12:00:34 +00:00
|
|
|
/// Returns "@" or " ” depending on wheter the file contains an extented
|
2015-02-22 12:26:52 +00:00
|
|
|
/// attribute or not. Also returns “ ” in case the attributes cannot be read
|
|
|
|
/// for some reason.
|
|
|
|
fn attribute_marker(&self) -> ANSIString {
|
2015-02-22 12:55:13 +00:00
|
|
|
if self.xattrs.len() > 0 { Plain.paint("@") } else { Plain.paint(" ") }
|
2015-02-22 12:26:52 +00:00
|
|
|
}
|
|
|
|
|
2015-01-24 12:38:05 +00:00
|
|
|
/// Generate the "rwxrwxrwx" permissions string, like how ls does it.
|
|
|
|
///
|
|
|
|
/// Each character is given its own colour. The first three permission
|
|
|
|
/// bits are bold because they're the ones used most often, and executable
|
|
|
|
/// files are underlined to make them stand out more.
|
2015-01-24 17:26:26 +00:00
|
|
|
fn permissions_string(&self) -> Cell {
|
Use new io + path + fs libraries (LOTS OF CHANGES)
Exa now uses the new IO, Path, and Filesystem libraries that have been out for a while now.
Unfortunately, the new libraries don't *entirely* cover the range of the old libraries just yet: in particular, to become more cross-platform, the data in `UnstableFileStat` isn't available in the Unix `MetadataExt` yet. Much of this is contained in rust-lang/rfcs#1044 (which is due to be implemented in rust-lang/rust#14711), but it's not *entirely* there yet.
As such, this commits a serious loss of functionality: no symlink viewing, no hard links or blocks, or users or groups. Also, some of the code could now be optimised. I just wanted to commit this to sort out most of the 'teething problems' of having a different path system in advance.
Here's an example problem that took ages to fix for you, just because you read this far: when I first got exa to compile, it worked mostly fine, except calling `exa` by itself didn't list the current directory. I traced where the command-line options were being generated, to where files and directories were sorted, to where the threads were spawned... and the problem turned out to be that it was using the full path as the file name, rather than just the last component, and these paths happened to begin with `.`, so it thought they were dotfiles.
2015-04-23 12:00:34 +00:00
|
|
|
|
|
|
|
let bits = self.stat.permissions().mode();
|
|
|
|
let executable_colour = if self.is_file() { Green.bold().underline() }
|
|
|
|
else { Green.bold() };
|
2015-01-05 14:41:43 +00:00
|
|
|
|
2015-02-13 21:24:10 +00:00
|
|
|
let string = ANSIStrings(&[
|
2014-05-04 20:33:14 +00:00
|
|
|
self.type_char(),
|
2015-05-03 10:55:10 +00:00
|
|
|
File::permission_bit(bits, unix::fs::USER_READ, "r", Yellow.bold()),
|
|
|
|
File::permission_bit(bits, unix::fs::USER_WRITE, "w", Red.bold()),
|
|
|
|
File::permission_bit(bits, unix::fs::USER_EXECUTE, "x", executable_colour),
|
|
|
|
File::permission_bit(bits, unix::fs::GROUP_READ, "r", Yellow.normal()),
|
|
|
|
File::permission_bit(bits, unix::fs::GROUP_WRITE, "w", Red.normal()),
|
|
|
|
File::permission_bit(bits, unix::fs::GROUP_EXECUTE, "x", Green.normal()),
|
|
|
|
File::permission_bit(bits, unix::fs::OTHER_READ, "r", Yellow.normal()),
|
|
|
|
File::permission_bit(bits, unix::fs::OTHER_WRITE, "w", Red.normal()),
|
|
|
|
File::permission_bit(bits, unix::fs::OTHER_EXECUTE, "x", Green.normal()),
|
2015-02-22 12:26:52 +00:00
|
|
|
self.attribute_marker()
|
2015-02-13 21:24:10 +00:00
|
|
|
]).to_string();
|
2015-01-24 17:26:26 +00:00
|
|
|
|
2015-02-23 14:52:07 +00:00
|
|
|
Cell { text: string, length: 11 }
|
2014-05-04 20:33:14 +00:00
|
|
|
}
|
2014-05-26 10:50:46 +00:00
|
|
|
|
2015-01-24 12:38:05 +00:00
|
|
|
/// Helper method for the permissions string.
|
2015-05-03 10:55:10 +00:00
|
|
|
fn permission_bit(bits: u16, bit: u16, character: &'static str, style: Style) -> ANSIString<'static> {
|
2015-05-03 10:47:34 +00:00
|
|
|
let bi32 = bit as u16;
|
Use new io + path + fs libraries (LOTS OF CHANGES)
Exa now uses the new IO, Path, and Filesystem libraries that have been out for a while now.
Unfortunately, the new libraries don't *entirely* cover the range of the old libraries just yet: in particular, to become more cross-platform, the data in `UnstableFileStat` isn't available in the Unix `MetadataExt` yet. Much of this is contained in rust-lang/rfcs#1044 (which is due to be implemented in rust-lang/rust#14711), but it's not *entirely* there yet.
As such, this commits a serious loss of functionality: no symlink viewing, no hard links or blocks, or users or groups. Also, some of the code could now be optimised. I just wanted to commit this to sort out most of the 'teething problems' of having a different path system in advance.
Here's an example problem that took ages to fix for you, just because you read this far: when I first got exa to compile, it worked mostly fine, except calling `exa` by itself didn't list the current directory. I traced where the command-line options were being generated, to where files and directories were sorted, to where the threads were spawned... and the problem turned out to be that it was using the full path as the file name, rather than just the last component, and these paths happened to begin with `.`, so it thought they were dotfiles.
2015-04-23 12:00:34 +00:00
|
|
|
if bits & bi32 == bi32 {
|
2014-12-12 14:17:57 +00:00
|
|
|
style.paint(character)
|
2014-11-25 20:50:23 +00:00
|
|
|
}
|
|
|
|
else {
|
2014-12-12 14:17:57 +00:00
|
|
|
GREY.paint("-")
|
2014-05-26 10:50:46 +00:00
|
|
|
}
|
|
|
|
}
|
2015-01-24 12:38:05 +00:00
|
|
|
|
|
|
|
/// For this file, return a vector of alternate file paths that, if any of
|
|
|
|
/// them exist, mean that *this* file should be coloured as `Compiled`.
|
|
|
|
///
|
|
|
|
/// The point of this is to highlight compiled files such as `foo.o` when
|
|
|
|
/// their source file `foo.c` exists in the same directory. It's too
|
|
|
|
/// dangerous to highlight *all* compiled, so the paths in this vector
|
|
|
|
/// are checked for existence first: for example, `foo.js` is perfectly
|
|
|
|
/// valid without `foo.coffee`.
|
Use new io + path + fs libraries (LOTS OF CHANGES)
Exa now uses the new IO, Path, and Filesystem libraries that have been out for a while now.
Unfortunately, the new libraries don't *entirely* cover the range of the old libraries just yet: in particular, to become more cross-platform, the data in `UnstableFileStat` isn't available in the Unix `MetadataExt` yet. Much of this is contained in rust-lang/rfcs#1044 (which is due to be implemented in rust-lang/rust#14711), but it's not *entirely* there yet.
As such, this commits a serious loss of functionality: no symlink viewing, no hard links or blocks, or users or groups. Also, some of the code could now be optimised. I just wanted to commit this to sort out most of the 'teething problems' of having a different path system in advance.
Here's an example problem that took ages to fix for you, just because you read this far: when I first got exa to compile, it worked mostly fine, except calling `exa` by itself didn't list the current directory. I traced where the command-line options were being generated, to where files and directories were sorted, to where the threads were spawned... and the problem turned out to be that it was using the full path as the file name, rather than just the last component, and these paths happened to begin with `.`, so it thought they were dotfiles.
2015-04-23 12:00:34 +00:00
|
|
|
pub fn get_source_files(&self) -> Vec<PathBuf> {
|
2015-01-24 12:38:05 +00:00
|
|
|
if let Some(ref ext) = self.ext {
|
2015-02-22 17:11:33 +00:00
|
|
|
match &ext[..] {
|
2015-01-24 12:38:05 +00:00
|
|
|
"class" => vec![self.path.with_extension("java")], // Java
|
|
|
|
"css" => vec![self.path.with_extension("sass"), self.path.with_extension("less")], // SASS, Less
|
|
|
|
"elc" => vec![self.path.with_extension("el")], // Emacs Lisp
|
|
|
|
"hi" => vec![self.path.with_extension("hs")], // Haskell
|
|
|
|
"js" => vec![self.path.with_extension("coffee"), self.path.with_extension("ts")], // CoffeeScript, TypeScript
|
|
|
|
"o" => vec![self.path.with_extension("c"), self.path.with_extension("cpp")], // C, C++
|
|
|
|
"pyc" => vec![self.path.with_extension("py")], // Python
|
|
|
|
|
|
|
|
"aux" => vec![self.path.with_extension("tex")], // TeX: auxiliary file
|
|
|
|
"bbl" => vec![self.path.with_extension("tex")], // BibTeX bibliography file
|
|
|
|
"blg" => vec![self.path.with_extension("tex")], // BibTeX log file
|
|
|
|
"lof" => vec![self.path.with_extension("tex")], // TeX list of figures
|
|
|
|
"log" => vec![self.path.with_extension("tex")], // TeX log file
|
|
|
|
"lot" => vec![self.path.with_extension("tex")], // TeX list of tables
|
|
|
|
"toc" => vec![self.path.with_extension("tex")], // TeX table of contents
|
|
|
|
|
|
|
|
_ => vec![], // No source files if none of the above
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
vec![] // No source files if there's no extension, either!
|
|
|
|
}
|
|
|
|
}
|
2015-01-27 15:01:17 +00:00
|
|
|
|
|
|
|
fn git_status(&self) -> Cell {
|
2015-01-28 10:43:19 +00:00
|
|
|
let status = match self.dir {
|
|
|
|
None => GREY.paint("--").to_string(),
|
2015-04-03 22:14:49 +00:00
|
|
|
Some(d) => {
|
|
|
|
let cwd = match current_dir() {
|
|
|
|
Err(_) => Path::new(".").join(&self.path),
|
Use new io + path + fs libraries (LOTS OF CHANGES)
Exa now uses the new IO, Path, and Filesystem libraries that have been out for a while now.
Unfortunately, the new libraries don't *entirely* cover the range of the old libraries just yet: in particular, to become more cross-platform, the data in `UnstableFileStat` isn't available in the Unix `MetadataExt` yet. Much of this is contained in rust-lang/rfcs#1044 (which is due to be implemented in rust-lang/rust#14711), but it's not *entirely* there yet.
As such, this commits a serious loss of functionality: no symlink viewing, no hard links or blocks, or users or groups. Also, some of the code could now be optimised. I just wanted to commit this to sort out most of the 'teething problems' of having a different path system in advance.
Here's an example problem that took ages to fix for you, just because you read this far: when I first got exa to compile, it worked mostly fine, except calling `exa` by itself didn't list the current directory. I traced where the command-line options were being generated, to where files and directories were sorted, to where the threads were spawned... and the problem turned out to be that it was using the full path as the file name, rather than just the last component, and these paths happened to begin with `.`, so it thought they were dotfiles.
2015-04-23 12:00:34 +00:00
|
|
|
Ok(dir) => dir.join(&self.path),
|
2015-04-03 22:14:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
d.git_status(&cwd, self.is_directory())
|
|
|
|
},
|
2015-01-28 10:43:19 +00:00
|
|
|
};
|
|
|
|
|
2015-01-27 15:01:17 +00:00
|
|
|
Cell { text: status, length: 2 }
|
|
|
|
}
|
2015-01-24 12:38:05 +00:00
|
|
|
}
|
|
|
|
|
2015-02-23 11:32:35 +00:00
|
|
|
/// Extract the filename to display from a path, converting it from UTF-8
|
|
|
|
/// lossily, into a String.
|
|
|
|
///
|
|
|
|
/// The filename to display is the last component of the path. However,
|
|
|
|
/// the path has no components for `.`, `..`, and `/`, so in these
|
|
|
|
/// cases, the entire path is used.
|
|
|
|
fn path_filename(path: &Path) -> String {
|
Use new io + path + fs libraries (LOTS OF CHANGES)
Exa now uses the new IO, Path, and Filesystem libraries that have been out for a while now.
Unfortunately, the new libraries don't *entirely* cover the range of the old libraries just yet: in particular, to become more cross-platform, the data in `UnstableFileStat` isn't available in the Unix `MetadataExt` yet. Much of this is contained in rust-lang/rfcs#1044 (which is due to be implemented in rust-lang/rust#14711), but it's not *entirely* there yet.
As such, this commits a serious loss of functionality: no symlink viewing, no hard links or blocks, or users or groups. Also, some of the code could now be optimised. I just wanted to commit this to sort out most of the 'teething problems' of having a different path system in advance.
Here's an example problem that took ages to fix for you, just because you read this far: when I first got exa to compile, it worked mostly fine, except calling `exa` by itself didn't list the current directory. I traced where the command-line options were being generated, to where files and directories were sorted, to where the threads were spawned... and the problem turned out to be that it was using the full path as the file name, rather than just the last component, and these paths happened to begin with `.`, so it thought they were dotfiles.
2015-04-23 12:00:34 +00:00
|
|
|
match path.iter().last() {
|
|
|
|
Some(os_str) => os_str.to_string_lossy().to_string(),
|
|
|
|
None => ".".to_string(), // can this even be reached?
|
|
|
|
}
|
2015-02-23 11:32:35 +00:00
|
|
|
}
|
|
|
|
|
2015-01-26 01:16:19 +00:00
|
|
|
/// Extract an extension from a string, if one is present, in lowercase.
|
2015-01-24 12:38:05 +00:00
|
|
|
///
|
|
|
|
/// The extension is the series of characters after the last dot. This
|
|
|
|
/// deliberately counts dotfiles, so the ".git" folder has the extension "git".
|
2015-01-26 01:16:19 +00:00
|
|
|
///
|
|
|
|
/// ASCII lowercasing is used because these extensions are only compared
|
|
|
|
/// against a pre-compiled list of extensions which are known to only exist
|
|
|
|
/// within ASCII, so it's alright.
|
2015-01-24 12:38:05 +00:00
|
|
|
fn ext<'a>(name: &'a str) -> Option<String> {
|
2015-01-26 01:16:19 +00:00
|
|
|
name.rfind('.').map(|p| name[p+1..].to_ascii_lowercase())
|
2014-05-04 20:33:14 +00:00
|
|
|
}
|
2015-01-25 13:04:15 +00:00
|
|
|
|
2015-04-23 12:47:46 +00:00
|
|
|
#[cfg(broken_test)]
|
2015-01-26 01:16:19 +00:00
|
|
|
pub mod test {
|
2015-01-25 13:43:44 +00:00
|
|
|
pub use super::*;
|
2015-02-23 11:32:35 +00:00
|
|
|
|
2015-01-25 13:43:44 +00:00
|
|
|
pub use column::{Cell, Column};
|
2015-02-23 11:32:35 +00:00
|
|
|
pub use output::details::UserLocale;
|
|
|
|
|
2015-01-25 13:43:44 +00:00
|
|
|
pub use users::{User, Group};
|
|
|
|
pub use users::mock::MockUsers;
|
2015-01-25 13:04:15 +00:00
|
|
|
|
2015-01-25 13:43:44 +00:00
|
|
|
pub use ansi_term::Style::Plain;
|
|
|
|
pub use ansi_term::Colour::Yellow;
|
2015-01-25 13:04:15 +00:00
|
|
|
|
2015-01-25 13:47:07 +00:00
|
|
|
#[test]
|
|
|
|
fn extension() {
|
|
|
|
assert_eq!(Some("dat".to_string()), super::ext("fester.dat"))
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn dotfile() {
|
|
|
|
assert_eq!(Some("vimrc".to_string()), super::ext(".vimrc"))
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn no_extension() {
|
|
|
|
assert_eq!(None, super::ext("jarlsberg"))
|
|
|
|
}
|
|
|
|
|
2015-02-04 01:12:08 +00:00
|
|
|
pub fn new_file(stat: io::FileStat, path: &'static str) -> File {
|
|
|
|
File::with_stat(stat, &Path::new(path), None, false)
|
|
|
|
}
|
|
|
|
|
2015-02-13 21:24:29 +00:00
|
|
|
pub fn dummy_stat() -> io::FileStat {
|
|
|
|
io::FileStat {
|
2015-01-25 13:04:15 +00:00
|
|
|
size: 0,
|
|
|
|
kind: io::FileType::RegularFile,
|
|
|
|
created: 0,
|
|
|
|
modified: 0,
|
|
|
|
accessed: 0,
|
|
|
|
perm: io::USER_READ,
|
|
|
|
unstable: io::UnstableFileStat {
|
|
|
|
inode: 0,
|
|
|
|
device: 0,
|
|
|
|
rdev: 0,
|
|
|
|
nlink: 0,
|
|
|
|
uid: 0,
|
|
|
|
gid: 0,
|
|
|
|
blksize: 0,
|
|
|
|
blocks: 0,
|
|
|
|
flags: 0,
|
|
|
|
gen: 0,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-10 18:14:56 +00:00
|
|
|
pub fn dummy_locale() -> UserLocale {
|
|
|
|
UserLocale::default()
|
2015-02-10 16:42:25 +00:00
|
|
|
}
|
|
|
|
|
2015-01-25 13:43:44 +00:00
|
|
|
mod users {
|
|
|
|
use super::*;
|
2015-01-25 13:04:15 +00:00
|
|
|
|
2015-01-25 13:43:44 +00:00
|
|
|
#[test]
|
|
|
|
fn named() {
|
|
|
|
let mut stat = dummy_stat();
|
|
|
|
stat.unstable.uid = 1000;
|
2015-01-25 13:04:15 +00:00
|
|
|
|
2015-02-04 01:12:08 +00:00
|
|
|
let file = new_file(stat, "/hi");
|
2015-01-25 13:04:15 +00:00
|
|
|
|
2015-01-25 13:43:44 +00:00
|
|
|
let mut users = MockUsers::with_current_uid(1000);
|
|
|
|
users.add_user(User { uid: 1000, name: "enoch".to_string(), primary_group: 100 });
|
|
|
|
|
|
|
|
let cell = Cell::paint(Yellow.bold(), "enoch");
|
2015-02-10 16:42:25 +00:00
|
|
|
assert_eq!(cell, file.display(&Column::User, &mut users, &dummy_locale()))
|
2015-01-25 13:43:44 +00:00
|
|
|
}
|
2015-01-25 13:04:15 +00:00
|
|
|
|
2015-01-25 13:43:44 +00:00
|
|
|
#[test]
|
|
|
|
fn unnamed() {
|
|
|
|
let mut stat = dummy_stat();
|
|
|
|
stat.unstable.uid = 1000;
|
2015-01-25 13:04:15 +00:00
|
|
|
|
2015-02-04 01:12:08 +00:00
|
|
|
let file = new_file(stat, "/hi");
|
2015-01-25 13:04:15 +00:00
|
|
|
|
2015-01-25 13:43:44 +00:00
|
|
|
let mut users = MockUsers::with_current_uid(1000);
|
2015-01-25 13:04:15 +00:00
|
|
|
|
2015-01-25 13:43:44 +00:00
|
|
|
let cell = Cell::paint(Yellow.bold(), "1000");
|
2015-02-10 16:42:25 +00:00
|
|
|
assert_eq!(cell, file.display(&Column::User, &mut users, &dummy_locale()))
|
2015-01-25 13:43:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn different_named() {
|
|
|
|
let mut stat = dummy_stat();
|
|
|
|
stat.unstable.uid = 1000;
|
|
|
|
|
2015-02-04 01:12:08 +00:00
|
|
|
let file = new_file(stat, "/hi");
|
2015-01-25 13:04:15 +00:00
|
|
|
|
2015-01-25 13:43:44 +00:00
|
|
|
let mut users = MockUsers::with_current_uid(3);
|
|
|
|
users.add_user(User { uid: 1000, name: "enoch".to_string(), primary_group: 100 });
|
2015-01-25 13:04:15 +00:00
|
|
|
|
2015-01-25 13:43:44 +00:00
|
|
|
let cell = Cell::paint(Plain, "enoch");
|
2015-02-10 16:42:25 +00:00
|
|
|
assert_eq!(cell, file.display(&Column::User, &mut users, &dummy_locale()))
|
2015-01-25 13:43:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn different_unnamed() {
|
|
|
|
let mut stat = dummy_stat();
|
|
|
|
stat.unstable.uid = 1000;
|
2015-01-25 13:04:15 +00:00
|
|
|
|
2015-02-04 01:12:08 +00:00
|
|
|
let file = new_file(stat, "/hi");
|
2015-01-25 13:04:15 +00:00
|
|
|
|
2015-01-25 13:43:44 +00:00
|
|
|
let mut users = MockUsers::with_current_uid(3);
|
|
|
|
|
|
|
|
let cell = Cell::paint(Plain, "1000");
|
2015-02-10 16:42:25 +00:00
|
|
|
assert_eq!(cell, file.display(&Column::User, &mut users, &dummy_locale()))
|
2015-01-25 13:43:44 +00:00
|
|
|
}
|
2015-02-23 13:37:59 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn overflow() {
|
|
|
|
let mut stat = dummy_stat();
|
|
|
|
stat.unstable.uid = 2_147_483_648;
|
|
|
|
|
|
|
|
let file = new_file(stat, "/hi");
|
|
|
|
|
|
|
|
let mut users = MockUsers::with_current_uid(3);
|
|
|
|
|
|
|
|
let cell = Cell::paint(Plain, "2147483648");
|
|
|
|
assert_eq!(cell, file.display(&Column::User, &mut users, &dummy_locale()))
|
|
|
|
}
|
2015-01-25 13:04:15 +00:00
|
|
|
}
|
|
|
|
|
2015-01-25 13:43:44 +00:00
|
|
|
mod groups {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn named() {
|
|
|
|
let mut stat = dummy_stat();
|
|
|
|
stat.unstable.gid = 100;
|
|
|
|
|
2015-02-04 01:12:08 +00:00
|
|
|
let file = new_file(stat, "/hi");
|
2015-01-25 13:43:44 +00:00
|
|
|
|
|
|
|
let mut users = MockUsers::with_current_uid(3);
|
|
|
|
users.add_group(Group { gid: 100, name: "folk".to_string(), members: vec![] });
|
2015-01-25 13:04:15 +00:00
|
|
|
|
2015-01-25 13:43:44 +00:00
|
|
|
let cell = Cell::paint(Plain, "folk");
|
2015-02-10 16:42:25 +00:00
|
|
|
assert_eq!(cell, file.display(&Column::Group, &mut users, &dummy_locale()))
|
2015-01-25 13:43:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn unnamed() {
|
|
|
|
let mut stat = dummy_stat();
|
|
|
|
stat.unstable.gid = 100;
|
|
|
|
|
2015-02-04 01:12:08 +00:00
|
|
|
let file = new_file(stat, "/hi");
|
2015-01-25 13:43:44 +00:00
|
|
|
|
|
|
|
let mut users = MockUsers::with_current_uid(3);
|
|
|
|
|
|
|
|
let cell = Cell::paint(Plain, "100");
|
2015-02-10 16:42:25 +00:00
|
|
|
assert_eq!(cell, file.display(&Column::Group, &mut users, &dummy_locale()))
|
2015-01-25 13:43:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn primary() {
|
|
|
|
let mut stat = dummy_stat();
|
|
|
|
stat.unstable.gid = 100;
|
2015-01-25 13:04:15 +00:00
|
|
|
|
2015-02-04 01:12:08 +00:00
|
|
|
let file = new_file(stat, "/hi");
|
2015-01-25 13:04:15 +00:00
|
|
|
|
2015-01-25 13:43:44 +00:00
|
|
|
let mut users = MockUsers::with_current_uid(3);
|
|
|
|
users.add_user(User { uid: 3, name: "eve".to_string(), primary_group: 100 });
|
|
|
|
users.add_group(Group { gid: 100, name: "folk".to_string(), members: vec![] });
|
|
|
|
|
|
|
|
let cell = Cell::paint(Yellow.bold(), "folk");
|
2015-02-10 16:42:25 +00:00
|
|
|
assert_eq!(cell, file.display(&Column::Group, &mut users, &dummy_locale()))
|
2015-01-25 13:43:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn secondary() {
|
|
|
|
let mut stat = dummy_stat();
|
|
|
|
stat.unstable.gid = 100;
|
|
|
|
|
2015-02-04 01:12:08 +00:00
|
|
|
let file = new_file(stat, "/hi");
|
2015-01-25 13:43:44 +00:00
|
|
|
|
|
|
|
let mut users = MockUsers::with_current_uid(3);
|
|
|
|
users.add_user(User { uid: 3, name: "eve".to_string(), primary_group: 12 });
|
|
|
|
users.add_group(Group { gid: 100, name: "folk".to_string(), members: vec![ "eve".to_string() ] });
|
|
|
|
|
|
|
|
let cell = Cell::paint(Yellow.bold(), "folk");
|
2015-02-10 16:42:25 +00:00
|
|
|
assert_eq!(cell, file.display(&Column::Group, &mut users, &dummy_locale()))
|
2015-01-25 13:43:44 +00:00
|
|
|
}
|
2015-02-23 13:37:59 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn overflow() {
|
|
|
|
let mut stat = dummy_stat();
|
|
|
|
stat.unstable.gid = 2_147_483_648;
|
|
|
|
|
|
|
|
let file = new_file(stat, "/hi");
|
|
|
|
|
|
|
|
let mut users = MockUsers::with_current_uid(3);
|
|
|
|
|
|
|
|
let cell = Cell::paint(Plain, "2147483648");
|
|
|
|
assert_eq!(cell, file.display(&Column::Group, &mut users, &dummy_locale()))
|
|
|
|
}
|
2015-01-25 13:04:15 +00:00
|
|
|
}
|
|
|
|
}
|