ex_cli/
file.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
use std::ffi::OsStr;
use std::hash::{Hash, Hasher};
use std::path::{Path, PathBuf};
use std::rc::Rc;
use std::time::UNIX_EPOCH;

use chrono::{DateTime, Utc};

use crate::config::FileKind;

pub struct File {
    pub abs_dir: PathBuf,
    pub rel_dir: PathBuf,
    pub file_depth: usize,
    pub file_name: String,
    pub file_ext: String,
    pub file_type: FileKind,
    pub file_mode: u32,
    pub owner_user: Option<Rc<String>>,
    pub owner_group: Option<Rc<String>>,
    pub file_size: u64,
    pub file_time: DateTime<Utc>,
    pub file_ver: Option<String>,
    pub link_data: Option<(PathBuf, FileKind)>,
}

// noinspection RsUnnecessaryReturn
impl File {
    pub fn new(
        abs_dir: PathBuf,
        rel_dir: PathBuf,
        file_depth: usize,
        file_name: String,
        file_ext: String,
        file_type: FileKind,
    ) -> File {
        Self {
            abs_dir,
            rel_dir,
            file_depth,
            file_name,
            file_ext,
            file_type,
            file_mode: 0,
            owner_user: None,
            owner_group: None,
            file_size: 0,
            file_time: DateTime::<Utc>::from(UNIX_EPOCH),
            file_ver: None,
            link_data: None,
        }
    }

    pub fn with_mode(mut self, file_mode: u32) -> File {
        self.file_mode = file_mode;
        return self;
    }

    pub fn with_owner(
        mut self,
        owner_user: Option<Rc<String>>,
        owner_group: Option<Rc<String>>,
    ) -> File {
        self.owner_user = owner_user;
        self.owner_group = owner_group;
        return self;
    }

    #[cfg(debug_assertions)]
    pub fn with_owner_ref(
        mut self,
        owner_user: &str,
        owner_group: &str,
    ) -> File {
        self.owner_user = Some(Rc::new(String::from(owner_user)));
        self.owner_group = Some(Rc::new(String::from(owner_group)));
        return self;
    }

    pub fn with_size(mut self, file_size: u64) -> File {
        self.file_size = file_size;
        return self;
    }

    pub fn with_time(mut self, file_time: DateTime<Utc>) -> File {
        self.file_time = file_time;
        return self;
    }

    #[cfg(test)]
    pub fn with_date(mut self, year: i32, month: u32, day: u32) -> File {
        use chrono::TimeZone;
        self.file_time = Utc.with_ymd_and_hms(year, month, day, 0, 0, 0).unwrap();
        return self;
    }

    pub fn with_version(mut self, file_ver: String) -> File {
        self.file_ver = Some(file_ver);
        return self;
    }

    pub fn with_link(mut self, link_path: PathBuf, link_type: FileKind) -> File {
        self.link_data = Some((link_path, link_type));
        return self;
    }

    pub fn get_path(&self) -> PathBuf {
        self.abs_dir.join(&self.file_name)
    }

    pub fn select_dir(&self, abs_path: bool) -> &Path {
        if abs_path {
            &self.abs_dir
        } else {
            &self.rel_dir
        }
    }

    pub fn select_parent_for_indent(&self) -> Option<&Path> {
        if self.file_type == FileKind::Dir {
            self.rel_dir.parent()
        } else {
            Some(&self.rel_dir)
        }
    }

    pub fn select_name_for_indent(&self) -> Option<&str> {
        if self.file_type == FileKind::Dir {
            self.rel_dir.file_name().and_then(OsStr::to_str)
        } else {
            Some(&self.file_name)
        }
    }

    pub fn group_dir_before_file(&self) -> u8 {
        if self.file_type == FileKind::Dir { 0 } else { 1 }
    }
}

impl PartialEq for File {
    fn eq(&self, other: &Self) -> bool {
        (self.abs_dir == other.abs_dir) && (self.file_name == other.file_name)
    }
}

impl Eq for File {
}

impl Hash for File {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.abs_dir.hash(state);
        self.file_name.hash(state);
    }
}