exa/src/fs/fields.rs

262 lines
7.4 KiB
Rust
Raw Normal View History

2016-04-16 18:56:44 +00:00
//! 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)]
#![allow(clippy::struct_excessive_bools)]
2016-04-16 18:56:44 +00:00
/// The type of a files block count.
pub type blkcnt_t = u64;
2016-04-16 18:56:44 +00:00
/// The type of a files group ID.
pub type gid_t = u32;
2016-04-16 18:56:44 +00:00
/// The type of a files inode.
pub type ino_t = u64;
2016-04-16 18:56:44 +00:00
/// The type of a files number of links.
pub type nlink_t = u64;
2016-04-16 18:56:44 +00:00
/// The type of a files timestamp (creation, modification, access, etc).
pub type time_t = i64;
2016-04-16 18:56:44 +00:00
/// The type of a files user ID.
pub type uid_t = u32;
2016-04-16 18:56:44 +00:00
/// 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)
}
}
2016-04-16 18:56:44 +00:00
/// 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,
2016-04-16 18:56:44 +00:00
pub group_read: bool,
pub group_write: bool,
pub group_execute: bool,
2016-04-16 18:56:44 +00:00
pub other_read: bool,
pub other_write: bool,
pub other_execute: bool,
pub sticky: bool,
pub setgid: bool,
pub setuid: bool,
}
2021-03-30 09:13:00 +00:00
/// The file's FileAttributes field, available only on Windows.
#[derive(Copy, Clone)]
pub struct Attributes {
pub archive: bool,
pub directory: bool,
pub readonly: bool,
pub hidden: bool,
pub system: bool,
pub reparse_point: 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,
2020-05-02 04:15:50 +00:00
#[cfg(unix)]
pub permissions: Permissions,
2021-03-30 09:13:00 +00:00
#[cfg(windows)]
pub attributes: Attributes,
pub xattrs: bool,
}
2016-04-16 18:56:44 +00:00
/// The permissions encoded as octal values
#[derive(Copy, Clone)]
pub struct OctalPermissions {
pub permissions: Permissions,
}
2016-04-16 18:56:44 +00:00
/// 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 {
2016-04-16 18:56:44 +00:00
/// The actual link count.
pub count: nlink_t,
2016-04-16 18:56:44 +00:00
/// Whether this file is a regular file with more than one hard link.
pub multiple: bool,
}
2016-04-16 18:56:44 +00:00
/// 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);
2016-04-16 18:56:44 +00:00
/// The number of blocks that a file takes up on the filesystem, if any.
#[derive(Copy, Clone)]
pub enum Blocks {
2016-04-16 18:56:44 +00:00
/// This file has the given number of blocks.
Some(blkcnt_t),
2016-04-16 18:56:44 +00:00
/// This file isnt of a type that can take up blocks.
None,
}
2016-04-16 18:56:44 +00:00
/// 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);
2016-04-16 18:56:44 +00:00
/// The ID of the group that a file belongs to.
#[derive(Copy, Clone)]
pub struct Group(pub gid_t);
2016-04-16 18:56:44 +00:00
/// A files size, in bytes. This is usually formatted by the `number_prefix`
/// crate into something human-readable.
#[derive(Copy, Clone)]
pub enum Size {
2016-04-16 18:56:44 +00:00
/// This file has a defined size.
Some(u64),
2016-04-16 18:56:44 +00:00
/// 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
2016-04-16 18:56:44 +00:00
/// learnt something. So we discard it and just output “-” instead.
///
/// See this answer for more: <https://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:
2020-10-10 14:57:40 +00:00
/// - <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,
}
2016-04-16 18:56:44 +00:00
/// 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,
}
2016-04-16 18:56:44 +00:00
/// 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, Eq, Copy, Clone)]
pub enum GitStatus {
2016-04-16 18:56:44 +00:00
/// This file hasnt changed since the last commit.
NotModified,
2016-04-16 18:56:44 +00:00
/// This file didnt exist for the last commit, and is not specified in
/// the ignored files list.
New,
2016-04-16 18:56:44 +00:00
/// A file thats been modified since the last commit.
Modified,
2016-04-16 18:56:44 +00:00
/// A deleted file. This cant ever be shown, but its here anyway!
Deleted,
2016-04-16 18:56:44 +00:00
/// A file that Git has tracked a rename for.
Renamed,
2016-04-16 18:56:44 +00:00
/// A file thats had its type (such as the file permissions) changed.
TypeChange,
2018-11-20 17:12:38 +00:00
/// A file thats ignored (that matches a line in .gitignore)
Ignored,
/// A file thats updated but unmerged.
Conflicted,
}
2016-04-16 18:56:44 +00:00
/// 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 {
2016-04-16 18:56:44 +00:00
/// Create a Git status for a file with nothing done to it.
fn default() -> Self {
Self {
staged: GitStatus::NotModified,
unstaged: GitStatus::NotModified,
}
}
}