Skip to main content

ephemeris_files/
entry.rs

1use std::fs::Metadata;
2use std::os::unix::fs::MetadataExt as _;
3
4/// The Git mode of a tracked file.
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub enum FileMode {
7    /// A regular file without the executable bit.
8    Regular,
9    /// A regular file with the executable bit.
10    Executable,
11    /// A symbolic link.
12    Symlink,
13}
14
15impl FileMode {
16    const REGULAR_BITS: u32 = 0o100_644;
17    const EXECUTABLE_BITS: u32 = 0o100_755;
18    const SYMLINK_BITS: u32 = 0o120_000;
19    const TYPE_MASK: u32 = 0o170_000;
20    const OWNER_EXECUTE: u32 = 0o100;
21
22    /// The mode for a raw Git mode.
23    pub(crate) const fn from_git(raw: u32) -> Self {
24        if raw & Self::TYPE_MASK == Self::SYMLINK_BITS {
25            Self::Symlink
26        } else if raw & Self::OWNER_EXECUTE != 0 {
27            Self::Executable
28        } else {
29            Self::Regular
30        }
31    }
32
33    /// The mode of a file on disk, read without following symlinks.
34    pub(crate) fn from_metadata(metadata: &Metadata) -> Self {
35        if metadata.file_type().is_symlink() {
36            Self::Symlink
37        } else if metadata.mode() & Self::OWNER_EXECUTE != 0 {
38            Self::Executable
39        } else {
40            Self::Regular
41        }
42    }
43
44    /// The raw Git mode.
45    #[must_use]
46    pub const fn bits(self) -> u32 {
47        match self {
48            Self::Regular => Self::REGULAR_BITS,
49            Self::Executable => Self::EXECUTABLE_BITS,
50            Self::Symlink => Self::SYMLINK_BITS,
51        }
52    }
53}
54
55/// The content and mode of one file.
56///
57/// A symlink holds its target as content.
58#[derive(Debug, Clone, PartialEq, Eq)]
59pub struct FileEntry {
60    /// The file content.
61    pub content: Vec<u8>,
62    /// The file mode.
63    pub mode: FileMode,
64}