exa/src/fs/fields.rs

247 lines
7.0 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//! Wrapper types for the values returned from `File`s.
//!
//! The methods of `File` that return information about the entry on the
//! filesystem -- size, modification date, block count, or Git status -- used
//! to just return these as formatted strings, but this became inflexible once
//! customisable output styles landed.
//!
//! Instead, they will return a wrapper type from this module, which tags the
//! type with what field it is while containing the actual raw value.
//!
//! The `output::details` module, among others, uses these types to render and
//! display the information as formatted strings.
// C-style `blkcnt_t` types dont follow Rusts rules!
#![allow(non_camel_case_types)]
/// The type of a files block count.
pub type blkcnt_t = u64;
/// The type of a files group ID.
pub type gid_t = u32;
/// The type of a files inode.
pub type ino_t = u64;
/// The type of a files number of links.
pub type nlink_t = u64;
/// The type of a files timestamp (creation, modification, access, etc).
pub type time_t = i64;
/// The type of a files user ID.
pub type uid_t = u32;
/// The files base type, which gets displayed in the very first column of the
/// details output.
///
/// This type is set entirely by the filesystem, rather than relying on a
/// files contents. So “link” is a type, but “image” is just a type of
/// regular file. (See the `filetype` module for those checks.)
///
/// Its ordering is used when sorting by type.
#[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
pub enum Type {
Directory,
File,
Link,
Pipe,
Socket,
CharDevice,
BlockDevice,
Special,
}
impl Type {
pub fn is_regular_file(self) -> bool {
matches!(self, Self::File)
}
}
/// The files Unix permission bitfield, with one entry per bit.
#[derive(Copy, Clone)]
pub struct Permissions {
pub user_read: bool,
pub user_write: bool,
pub user_execute: bool,
pub group_read: bool,
pub group_write: bool,
pub group_execute: bool,
pub other_read: bool,
pub other_write: bool,
pub other_execute: bool,
pub sticky: bool,
pub setgid: bool,
pub setuid: bool,
}
/// The three pieces of information that are displayed as a single column in
/// the details view. These values are fused together to make the output a
/// little more compressed.
#[derive(Copy, Clone)]
pub struct PermissionsPlus {
pub file_type: Type,
pub permissions: Permissions,
pub xattrs: bool,
}
/// The permissions encoded as octal values
#[derive(Copy, Clone)]
pub struct OctalPermissions {
pub permissions: Permissions,
}
/// A files number of hard links on the filesystem.
///
/// Under Unix, a file can exist on the filesystem only once but appear in
/// multiple directories. However, its rare (but occasionally useful!) for a
/// regular file to have a link count greater than 1, so we highlight the
/// block count specifically for this case.
#[derive(Copy, Clone)]
pub struct Links {
/// The actual link count.
pub count: nlink_t,
/// Whether this file is a regular file with more than one hard link.
pub multiple: bool,
}
/// A files inode. Every directory entry on a Unix filesystem has an inode,
/// including directories and links, so this is applicable to everything exa
/// can deal with.
#[derive(Copy, Clone)]
pub struct Inode(pub ino_t);
/// The number of blocks that a file takes up on the filesystem, if any.
#[derive(Copy, Clone)]
pub enum Blocks {
/// This file has the given number of blocks.
Some(blkcnt_t),
/// This file isnt of a type that can take up blocks.
None,
}
/// The ID of the user that owns a file. This will only ever be a number;
/// looking up the username is done in the `display` module.
#[derive(Copy, Clone)]
pub struct User(pub uid_t);
/// The ID of the group that a file belongs to.
#[derive(Copy, Clone)]
pub struct Group(pub gid_t);
/// A files size, in bytes. This is usually formatted by the `number_prefix`
/// crate into something human-readable.
#[derive(Copy, Clone)]
pub enum Size {
/// This file has a defined size.
Some(u64),
/// This file has no size, or has a size but we arent interested in it.
///
/// Under Unix, directory entries that arent regular files will still
/// have a file size. For example, a directory will just contain a list of
/// its files as its “contents” and will be specially flagged as being a
/// directory, rather than a file. However, seeing the “file size” of this
/// data is rarely useful — I cant think of a time when Ive seen it and
/// learnt something. So we discard it and just output “-” instead.
///
/// See this answer for more: http://unix.stackexchange.com/a/68266
None,
/// This file is a block or character device, so instead of a size, print
/// out the files major and minor device IDs.
///
/// This is what ls does as well. Without it, the devices will just have
/// file sizes of zero.
DeviceIDs(DeviceIDs),
}
/// The major and minor device IDs that gets displayed for device files.
///
/// You can see what these device numbers mean:
/// - <http://www.lanana.org/docs/device-list/>
/// - <http://www.lanana.org/docs/device-list/devices-2.6+.txt>
#[derive(Copy, Clone)]
pub struct DeviceIDs {
pub major: u8,
pub minor: u8,
}
/// One of a files timestamps (created, accessed, or modified).
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Time {
pub seconds: time_t,
pub nanoseconds: time_t,
}
/// A files status in a Git repository. Whether a file is in a repository or
/// not is handled by the Git module, rather than having a “null” variant in
/// this enum.
#[derive(PartialEq, Copy, Clone)]
pub enum GitStatus {
/// This file hasnt changed since the last commit.
NotModified,
/// This file didnt exist for the last commit, and is not specified in
/// the ignored files list.
New,
/// A file thats been modified since the last commit.
Modified,
/// A deleted file. This cant ever be shown, but its here anyway!
Deleted,
/// A file that Git has tracked a rename for.
Renamed,
/// A file thats had its type (such as the file permissions) changed.
TypeChange,
/// A file thats ignored (that matches a line in .gitignore)
Ignored,
/// A file thats updated but unmerged.
Conflicted,
}
/// A files complete Git status. Its possible to make changes to a file, add
/// it to the staging area, then make *more* changes, so we need to list each
/// files status for both of these.
#[derive(Copy, Clone)]
pub struct Git {
pub staged: GitStatus,
pub unstaged: GitStatus,
}
impl Default for Git {
/// Create a Git status for a file with nothing done to it.
fn default() -> Self {
Self {
staged: GitStatus::NotModified,
unstaged: GitStatus::NotModified,
}
}
}