summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock11
-rw-r--r--Cargo.toml1
-rw-r--r--src/event_exec.rs6
-rw-r--r--src/fileinfo.rs85
-rw-r--r--src/preview.rs21
-rw-r--r--src/removable_devices.rs4
-rw-r--r--src/shortcut.rs6
-rw-r--r--src/status.rs25
-rw-r--r--src/tab.rs28
-rw-r--r--src/tree.rs23
-rw-r--r--src/users.rs19
-rw-r--r--src/utils.rs21
12 files changed, 120 insertions, 130 deletions
diff --git a/Cargo.lock b/Cargo.lock
index b296f14..06c4b63 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -833,7 +833,6 @@ dependencies = [
"ueberzug",
"unicode-segmentation",
"url-escape",
- "users",
"zip",
]
@@ -2776,16 +2775,6 @@ dependencies = [
]
[[package]]
-name = "users"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24cc0f6d6f267b73e5a2cadf007ba8f9bc39c6a6f9666f8cf25ea809a153b032"
-dependencies = [
- "libc 0.2.149",
- "log",
-]
-
-[[package]]
name = "utf8parse"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index 1f8ac77..53795c9 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -60,7 +60,6 @@ sysinfo = "0.29.0"
tar = "0.4.38"
tuikit = "0.5.0"
url-escape = "0.1.1"
-users = "0.11.0"
zip = "0.6.4"
tokio = "1"
ueberzug = "0.1.0"
diff --git a/src/event_exec.rs b/src/event_exec.rs
index 07eaa89..3b7e08d 100644
--- a/src/event_exec.rs
+++ b/src/event_exec.rs
@@ -299,7 +299,8 @@ impl EventAction {
pub fn toggle_hidden(status: &mut Status) -> Result<()> {
let tab = status.selected();
tab.show_hidden = !tab.show_hidden;
- tab.path_content.reset_files(&tab.filter, tab.show_hidden)?;
+ tab.path_content
+ .reset_files(&tab.filter, tab.show_hidden, &tab.users)?;
tab.window.reset(tab.path_content.content.len());
if let Mode::Tree = tab.mode {
tab.make_tree()?
@@ -1527,7 +1528,8 @@ impl LeaveMode {
let filter = FilterKind::from_input(&tab.input.string());
tab.set_filter(filter);
tab.input.reset();
- tab.path_content.reset_files(&tab.filter, tab.show_hidden)?;
+ tab.path_content
+ .reset_files(&tab.filter, tab.show_hidden, &tab.users)?;
if let Mode::Tree = tab.previous_mode {
tab.make_tree()?;
}
diff --git a/src/fileinfo.rs b/src/fileinfo.rs
index 881dcb7..66c0b79 100644
--- a/src/fileinfo.rs
+++ b/src/fileinfo.rs
@@ -8,7 +8,6 @@ use chrono::offset::Local;
use chrono::DateTime;
use log::info;
use tuikit::prelude::{Attr, Color, Effect};
-use users::{Groups, Users, UsersCache};
use crate::colors::extension_color;
use crate::constant_strings_paths::PERMISSIONS_STR;
@@ -16,6 +15,7 @@ use crate::filter::FilterKind;
use crate::git::git;
use crate::impl_selectable_content;
use crate::sort::SortKind;
+use crate::users::Users;
use crate::utils::filename_from_path;
type Valid = bool;
@@ -159,30 +159,26 @@ pub struct FileInfo {
impl FileInfo {
/// Reads every information about a file from its metadata and returs
/// a new `FileInfo` object if we can create one.
- pub fn new(direntry: &DirEntry, users_cache: &UsersCache) -> Result<FileInfo> {
+ pub fn new(direntry: &DirEntry, users: &Users) -> Result<FileInfo> {
let path = direntry.path();
let filename = extract_filename(direntry)?;
- Self::create_from_metadata_and_filename(&path, &filename, users_cache)
+ Self::create_from_metadata_and_filename(&path, &filename, users)
}
/// Creates a fileinfo from a path and a filename.
/// The filename is used when we create the fileinfo for "." and ".." in every folder.
- pub fn from_path_with_name(
- path: &path::Path,
- filename: &str,
- users_cache: &UsersCache,
- ) -> Result<Self> {
- Self::create_from_metadata_and_filename(path, filename, users_cache)
+ pub fn from_path_with_name(path: &path::Path, filename: &str, users: &Users) -> Result<Self> {
+ Self::create_from_metadata_and_filename(path, filename, users)
}
- pub fn from_path(path: &path::Path, users_cache: &UsersCache) -> Result<Self> {
+ pub fn from_path(path: &path::Path, users: &Users) -> Result<Self> {
let filename = path
.file_name()
.context("from path: couldn't read filenale")?
.to_str()
.context("from path: couldn't parse filenale")?;
- Self::create_from_metadata_and_filename(path, filename, users_cache)
+ Self::create_from_metadata_and_filename(path, filename, users)
}
fn metadata(&self) -> Result<std::fs::Metadata> {
@@ -196,13 +192,13 @@ impl FileInfo {
fn create_from_metadata_and_filename(
path: &path::Path,
filename: &str,
- users_cache: &UsersCache,
+ users: &Users,
) -> Result<Self> {
let filename = filename.to_owned();
let metadata = symlink_metadata(path)?;
let path = path.to_owned();
- let owner = extract_owner(&metadata, users_cache)?;
- let group = extract_group(&metadata, users_cache)?;
+ let owner = extract_owner(&metadata, users)?;
+ let group = extract_group(&metadata, users)?;
let system_time = extract_datetime(&metadata)?;
let is_selected = false;
let true_size = extract_file_size(&metadata);
@@ -313,7 +309,6 @@ pub struct PathContent {
/// The kind of sort used to display the files.
pub sort_kind: SortKind,
used_space: u64,
- pub users_cache: UsersCache,
}
impl PathContent {
@@ -322,12 +317,12 @@ impl PathContent {
/// Selects the first file if any.
pub fn new(
path: &path::Path,
- users_cache: UsersCache,
+ users: &Users,
filter: &FilterKind,
show_hidden: bool,
) -> Result<Self> {
let path = path.to_owned();
- let mut content = Self::files(&path, show_hidden, filter, &users_cache)?;
+ let mut content = Self::files(&path, show_hidden, filter, users)?;
let sort_kind = SortKind::default();
sort_kind.sort(&mut content);
let selected_index: usize = 0;
@@ -342,7 +337,6 @@ impl PathContent {
index: selected_index,
sort_kind,
used_space,
- users_cache,
})
}
@@ -351,8 +345,9 @@ impl PathContent {
path: &path::Path,
filter: &FilterKind,
show_hidden: bool,
+ users: &Users,
) -> Result<()> {
- self.content = Self::files(path, show_hidden, filter, &self.users_cache)?;
+ self.content = Self::files(path, show_hidden, filter, users)?;
self.sort_kind.sort(&mut self.content);
self.index = 0;
if !self.content.is_empty() {
@@ -367,24 +362,24 @@ impl PathContent {
path: &path::Path,
show_hidden: bool,
filter_kind: &FilterKind,
- users_cache: &UsersCache,
+ users: &Users,
) -> Result<Vec<FileInfo>> {
- let mut files: Vec<FileInfo> = Self::create_dot_dotdot(path, users_cache)?;
+ let mut files: Vec<FileInfo> = Self::create_dot_dotdot(path, users)?;
- let fileinfo = FileInfo::from_path_with_name(path, filename_from_path(path)?, users_cache)?;
+ let fileinfo = FileInfo::from_path_with_name(path, filename_from_path(path)?, users)?;
if let Some(true_files) =
- files_collection(&fileinfo, users_cache, show_hidden, filter_kind, false)
+ files_collection(&fileinfo, users, show_hidden, filter_kind, false)
{
files.extend(true_files);
}
Ok(files)
}
- fn create_dot_dotdot(path: &path::Path, users_cache: &UsersCache) -> Result<Vec<FileInfo>> {
- let current = FileInfo::from_path_with_name(path, ".", users_cache)?;
+ fn create_dot_dotdot(path: &path::Path, users: &Users) -> Result<Vec<FileInfo>> {
+ let current = FileInfo::from_path_with_name(path, ".", users)?;
match path.parent() {
Some(parent) => {
- let parent = FileInfo::from_path_with_name(parent, "..", users_cache)?;
+ let parent = FileInfo::from_path_with_name(parent, "..", users)?;
Ok(vec![current, parent])
}
None => Ok(vec![current]),
@@ -428,8 +423,13 @@ impl PathContent {
/// Reset the current file content.
/// Reads and sort the content with current key.
/// Select the first file if any.
- pub fn reset_files(&mut self, filter: &FilterKind, show_hidden: bool) -> Result<()> {
- self.content = Self::files(&self.path, show_hidden, filter, &self.users_cache)?;
+ pub fn reset_files(
+ &mut self,
+ filter: &FilterKind,
+ show_hidden: bool,
+ users: &Users,
+ ) -> Result<()> {
+ self.content = Self::files(&self.path, show_hidden, filter, users)?;
self.sort_kind = SortKind::default();
self.sort();
self.index = 0;
@@ -524,12 +524,11 @@ impl PathContent {
/// Refresh the existing users.
pub fn refresh_users(
&mut self,
- users_cache: UsersCache,
+ users: &Users,
filter: &FilterKind,
show_hidden: bool,
) -> Result<()> {
- self.users_cache = users_cache;
- self.reset_files(filter, show_hidden)
+ self.reset_files(filter, show_hidden, users)
}
/// Returns the correct index jump target to a flagged files.
@@ -623,13 +622,9 @@ fn convert_octal_mode(mode: usize) -> &'static str {
/// Reads the owner name and returns it as a string.
/// If it's not possible to get the owner name (happens if the owner exists on a remote machine but not on host),
/// it returns the uid as a `Result<String>`.
-fn extract_owner(metadata: &Metadata, users_cache: &UsersCache) -> Result<String> {
- match users_cache.get_user_by_uid(metadata.uid()) {
- Some(uid) => Ok(uid
- .name()
- .to_str()
- .context("extract owner: Couldn't parse owner name")?
- .to_owned()),
+fn extract_owner(metadata: &Metadata, users: &Users) -> Result<String> {
+ match users.get_user_by_uid(metadata.uid()) {
+ Some(name) => Ok(name),
None => Ok(format!("{}", metadata.uid())),
}
}
@@ -637,13 +632,9 @@ fn extract_owner(metadata: &Metadata, users_cache: &UsersCache) -> Result<String
/// Reads the group name and returns it as a string.
/// If it's not possible to get the group name (happens if the group exists on a remote machine but not on host),
/// it returns the gid as a `Result<String>`.
-fn extract_group(metadata: &Metadata, users_cache: &UsersCache) -> Result<String> {
- match users_cache.get_group_by_gid(metadata.gid()) {
- Some(gid) => Ok(gid
- .name()
- .to_str()
- .context("extract group: Couldn't parse group name")?
- .to_owned()),
+fn extract_group(metadata: &Metadata, users: &Users) -> Result<String> {
+ match users.get_group_by_gid(metadata.gid()) {
+ Some(name) => Ok(name),
None => Ok(format!("{}", metadata.gid())),
}
}
@@ -694,7 +685,7 @@ fn filekind_and_filename(filename: &str, file_kind: &FileKind<Valid>) -> String
/// Returns None if there's no file.
pub fn files_collection(
fileinfo: &FileInfo,
- users_cache: &UsersCache,
+ users: &Users,
show_hidden: bool,
filter_kind: &FilterKind,
keep_dir: bool,
@@ -704,7 +695,7 @@ pub fn files_collection(
read_dir
.filter_map(|direntry| direntry.ok())
.filter(|direntry| show_hidden || is_not_hidden(direntry).unwrap_or(true))
- .map(|direntry| FileInfo::new(&direntry, users_cache))
+ .map(|direntry| FileInfo::new(&direntry, users))
.filter_map(|fileinfo| fileinfo.ok())
.filter(|fileinfo| filter_kind.filter_by(fileinfo, keep_dir))
.collect(),
diff --git a/src/preview.rs b/src/preview.rs
index 29b07c2..c86ff61 100644
--- a/src/preview.rs
+++ b/src/preview.rs
@@ -14,7 +14,6 @@ use syntect::easy::HighlightLines;
use syntect::highlighting::{Style, ThemeSet};
use syntect::parsing::{SyntaxReference, SyntaxSet};
use tuikit::attr::{Attr, Color};
-use users::UsersCache;
use crate::constant_strings_paths::{
CALC_PDF_PATH, DIFF, FFMPEG, FONTIMAGE, ISOINFO, JUPYTER, LIBREOFFICE, LSBLK, LSOF, MEDIAINFO,
@@ -26,6 +25,7 @@ use crate::fileinfo::{FileInfo, FileKind};
use crate::filter::FilterKind;
use crate::opener::execute_and_capture_output_without_check;
use crate::tree::{ColoredString, Tree};
+use crate::users::Users;
use crate::utils::{clear_tmp_file, filename_from_path, is_program_in_path};
/// Different kind of extension for grouped by previewers.
@@ -116,13 +116,13 @@ impl Preview {
/// The recursive exploration is limited to depth 2.
pub fn directory(
file_info: &FileInfo,
- users_cache: &UsersCache,
+ users: &Users,
filter: &FilterKind,
show_hidden: bool,
) -> Result<Self> {
Ok(Self::Directory(Directory::new(
&file_info.path,
- users_cache,
+ users,
filter,
show_hidden,
Some(2),
@@ -1059,7 +1059,7 @@ impl Directory {
/// We only hold the result here, since the tree itself has now usage atm.
pub fn new(
path: &Path,
- users_cache: &UsersCache,
+ users: &Users,
filter_kind: &FilterKind,
show_hidden: bool,
max_depth: Option<usize>,
@@ -1069,14 +1069,7 @@ impl Directory {
None => Tree::MAX_DEPTH,
};
- let mut tree = Tree::from_path(
- path,
- max_depth,
- users_cache,
- filter_kind,
- show_hidden,
- vec![0],
- )?;
+ let mut tree = Tree::from_path(path, max_depth, users, filter_kind, show_hidden, vec![0])?;
tree.select_root();
let (selected_index, content) = tree.into_navigable_content();
Ok(Self {
@@ -1088,9 +1081,9 @@ impl Directory {
}
/// Creates an empty directory preview.
- pub fn empty(path: &Path, users_cache: &UsersCache) -> Result<Self> {
+ pub fn empty(path: &Path, users: &Users) -> Result<Self> {
Ok(Self {
- tree: Tree::empty(path, users_cache)?,
+ tree: Tree::empty(path, users)?,
len: 0,
content: vec![],
selected_index: 0,
diff --git a/src/removable_devices.rs b/src/removable_devices.rs
index 323bac1..7759c83 100644
--- a/src/removable_devices.rs
+++ b/src/removable_devices.rs
@@ -3,7 +3,7 @@ use anyhow::{anyhow, Result};
use crate::{
constant_strings_paths::GIO,
impl_selectable_content,
- utils::{is_dir_empty, is_program_in_path},
+ utils::{current_uid, is_dir_empty, is_program_in_path},
};
/// Holds info about removable devices.
@@ -83,7 +83,7 @@ impl Removable {
.replace('/', "")
.trim()
.to_owned();
- let uid = users::get_current_uid();
+ let uid = current_uid()?;
let path = format!("/run/user/{uid}/gvfs/mtp:host={device_name}");
let pb_path = std::path::Path::new(&path);
let is_mounted = pb_path.exists() && !is_dir_empty(pb_path)?;
diff --git a/src/shortcut.rs b/src/shortcut.rs
index 8129f19..f7e4506 100644
--- a/src/shortcut.rs
+++ b/src/shortcut.rs
@@ -5,6 +5,7 @@ use std::str::FromStr;
use crate::constant_strings_paths::{CONFIG_FOLDER, HARDCODED_SHORTCUTS};
use crate::git::git_root;
use crate::impl_selectable_content;
+use crate::utils::current_uid;
/// Holds the hardcoded and mountpoints shortcuts the user can jump to.
/// Also know which shortcut is currently selected by the user.
@@ -95,11 +96,14 @@ impl Shortcut {
/// Update the shortcuts with MTP mount points
fn extend_with_mtp(&mut self) {
- let uid = users::get_current_uid();
+ let Ok(uid) = current_uid() else {
+ return;
+ };
let mtp_mount_point = PathBuf::from(format!("/run/user/{uid}/gvfs/"));
if !mtp_mount_point.exists() || !mtp_mount_point.is_dir() {
return;
}
+
let mount_points: Vec<PathBuf> = match std::fs::read_dir(&mtp_mount_point) {
Ok(read_dir) => read_dir
.filter_map(|direntry| direntry.ok())
diff --git a/src/status.rs b/src/status.rs
index db78725..877c901 100644
--- a/src/status.rs
+++ b/src/status.rs
@@ -12,7 +12,6 @@ use skim::SkimItem;
use sysinfo::{Disk, DiskExt, RefreshKind, System, SystemExt};
use tuikit::prelude::{from_keyname, Event};
use tuikit::term::Term;
-use users::UsersCache;
use crate::args::Args;
use crate::bulkrename::Bulk;
@@ -43,6 +42,7 @@ use crate::skim::Skimer;
use crate::tab::Tab;
use crate::term_manager::MIN_WIDTH_FOR_DUAL_PANE;
use crate::trash::Trash;
+use crate::users::Users;
use crate::utils::{current_username, disk_space, filename_from_path, is_program_in_path};
/// Holds every mutable parameter of the application itself, except for
@@ -137,15 +137,15 @@ impl Status {
let index = 0;
// unsafe because of UsersCache::with_all_users
- let users_cache = unsafe { UsersCache::with_all_users() };
+ let users = Users::new();
// unsafe because of UsersCache::with_all_users
- let users_cache2 = unsafe { UsersCache::with_all_users() };
+ let users2 = users.clone();
let mount_points = Self::disks_mounts(sys.disks());
let tabs = [
- Tab::new(&args, height, users_cache, settings, &mount_points)?,
- Tab::new(&args, height, users_cache2, settings, &mount_points)?,
+ Tab::new(&args, height, users, settings, &mount_points)?,
+ Tab::new(&args, height, users2, settings, &mount_points)?,
];
let removable_devices = None;
Ok(Self {
@@ -549,18 +549,19 @@ impl Status {
/// Refresh the existing users.
pub fn refresh_users(&mut self) -> Result<()> {
- for tab in self.tabs.iter_mut() {
- let users_cache = unsafe { UsersCache::with_all_users() };
- tab.refresh_users(users_cache)?;
- }
+ let users = Users::new();
+ self.tabs[0].users = users.clone();
+ self.tabs[1].users = users;
+ self.tabs[0].refresh_view()?;
+ self.tabs[1].refresh_view()?;
Ok(())
}
/// Drop the current tree, replace it with an empty one.
pub fn remove_tree(&mut self) -> Result<()> {
let path = self.selected_non_mut().path_content.path.clone();
- let users_cache = &self.selected_non_mut().path_content.users_cache;
- self.selected().directory = Directory::empty(&path, users_cache)?;
+ let users = &self.selected_non_mut().users;
+ self.selected().directory = Directory::empty(&path, users)?;
Ok(())
}
@@ -631,7 +632,7 @@ impl Status {
let preview = match fileinfo.file_kind {
FileKind::Directory => Preview::directory(
fileinfo,
- &self.tabs[0].path_content.users_cache,
+ &self.tabs[0].users,
&self.tabs[0].filter,
self.tabs[0].show_hidden,
),
diff --git a/src/tab.rs b/src/tab.rs
index 6e1a6e6..3349c84 100644
--- a/src/tab.rs
+++ b/src/tab.rs
@@ -2,7 +2,6 @@ use std::cmp::min;
use std::path;
use anyhow::{Context, Result};
-use users::UsersCache;
use crate::args::Args;
use crate::completion::{Completion, InputCompleted};
@@ -17,6 +16,7 @@ use crate::opener::execute_in_child;
use crate::preview::{Directory, Preview};
use crate::selectable_content::SelectableContent;
use crate::shortcut::Shortcut;
+use crate::users::Users;
use crate::utils::{filename_from_path, row_to_window_index, set_clipboard};
/// Holds every thing about the current tab of the application.
@@ -54,6 +54,8 @@ pub struct Tab {
pub filter: FilterKind,
/// Visited directories
pub history: History,
+ /// Users & groups
+ pub users: Users,
}
impl Tab {
@@ -61,7 +63,7 @@ impl Tab {
pub fn new(
args: &Args,
height: usize,
- users_cache: UsersCache,
+ users: Users,
settings: &Settings,
mount_points: &[&path::Path],
) -> Result<Self> {
@@ -71,10 +73,10 @@ impl Tab {
} else {
path.parent().context("")?
};
- let directory = Directory::empty(start_dir, &users_cache)?;
+ let directory = Directory::empty(start_dir, &users)?;
let filter = FilterKind::All;
let show_hidden = args.all || settings.all;
- let mut path_content = PathContent::new(start_dir, users_cache, &filter, show_hidden)?;
+ let mut path_content = PathContent::new(start_dir, &users, &filter, show_hidden)?;
let mode = Mode::Normal;
let previous_mode = Mode::Normal;
let mut window = ContentWindow::new(path_content.content.len(), height);
@@ -104,6 +106,7 @@ impl Tab {
filter,
show_hidden,
history,
+ users,
})
}
@@ -153,7 +156,7 @@ impl Tab {
pub fn refresh_view(&mut self) -> Result<()> {
self.refresh_params()?;
self.path_content
- .reset_files(&self.filter, self.show_hidden)?;
+ .reset_files(&self.filter, self.show_hidden, &self.users)?;
self.window.reset(self.path_content.content.len());
Ok(())
}
@@ -229,7 +232,7 @@ impl Tab {
&self.path_content.selected().context("")?.path,
);
self.path_content
- .change_directory(path, &self.filter, self.show_hidden)?;
+ .change_directory(path, &self.filter, self.show_hidden, &self.users)?;
self.window.reset(self.path_content.content.len());
std::env::set_current_dir(path)?;
Ok(())
@@ -262,15 +265,6 @@ impl Tab {
self.window.scroll_to(index);
}
- /// Refresh the existing users.
- pub fn refresh_users(&mut self, users_cache: UsersCache) -> Result<()> {
- let last_pathcontent_index = self.path_content.index;
- self.path_content
- .refresh_users(users_cache, &self.filter, self.show_hidden)?;
- self.path_content.select_index(last_pathcontent_index);
- Ok(())
- }
-
/// Search in current directory for an file whose name contains `searched_name`,
/// from a starting position `next_index`.
/// We search forward from that position and start again from top if nothing is found.
@@ -432,8 +426,8 @@ impl Tab {
/// Makes a new tree of the current path.
pub fn make_tree(&mut self) -> Result<()> {
let path = self.path_content.path.clone();
- let users_cache = &self.path_content.users_cache;
- self.directory = Directory::new(&path, users_cache, &self.filter, self.show_hidden, None)?;
+ let users = &self.users;
+ self.directory = Directory::new(&path, users, &self.filter, self.show_hidden, None)?;
Ok(())
}
diff --git a/src/tree.rs b/src/tree.rs
index bd9f80d..f5c83a5 100644
--- a/src/tree.rs
+++ b/src/tree.rs
@@ -2,12 +2,12 @@ use std::path::Path;
use anyhow::{Context, Result};
use tuikit::attr::Attr;
-use users::UsersCache;
use crate::fileinfo::{fileinfo_attr, files_collection, FileInfo, FileKind};
use crate::filter::FilterKind;
use crate::preview::ColoredTriplet;
use crate::sort::SortKind;
+use crate::users::Users;
use crate::utils::filename_from_path;
/// Holds a string and its display attributes.
@@ -188,15 +188,15 @@ impl Tree {
pub fn from_path(
path: &Path,
max_depth: usize,
- users_cache: &UsersCache,
+ users: &Users,
filter_kind: &FilterKind,
show_hidden: bool,
parent_position: Vec<usize>,
) -> Result<Self> {
Self::create_tree_from_fileinfo(
- FileInfo::from_path_with_name(path, filename_from_path(path)?, users_cache)?,
+ FileInfo::from_path_with_name(path, filename_from_path(path)?, users)?,
max_depth,
- users_cache,
+ users,
filter_kind,
show_hidden,
parent_position,
@@ -218,7 +218,7 @@ impl Tree {
fn create_tree_from_fileinfo(
fileinfo: FileInfo,
max_depth: usize,
- users_cache: &UsersCache,
+ users: &Users,
filter_kind: &FilterKind,
display_hidden: bool,
parent_position: Vec<usize>,
@@ -227,7 +227,7 @@ impl Tree {
let leaves = Self::make_leaves(
&fileinfo,
max_depth,
- users_cache,
+ users,
display_hidden,
filter_kind,
&sort_kind,
@@ -249,7 +249,7 @@ impl Tree {
fn make_leaves(
fileinfo: &FileInfo,
max_depth: usize,
- users_cache: &UsersCache,
+ users: &Users,
display_hidden: bool,
filter_kind: &FilterKind,
sort_kind: &SortKind,
@@ -261,8 +261,7 @@ impl Tree {
let FileKind::Directory = fileinfo.file_kind else {
return Ok(vec![]);
};
- let Some(mut files) =
- files_collection(fileinfo, users_cache, display_hidden, filter_kind, true)
+ let Some(mut files) = files_collection(fileinfo, users, display_hidden, filter_kind, true)
else {
return Ok(vec![]);
};
@@ -276,7 +275,7 @@ impl Tree {
Self::create_tree_from_fileinfo(
fileinfo.to_owned(),
max_depth - 1,
- users_cache,
+ users,
filter_kind,
display_hidden,
position,
@@ -303,9 +302,9 @@ impl Tree {
/// Creates an empty tree. Used when the user changes the CWD and hasn't displayed
/// a tree yet.
- pub fn empty(path: &Path, users_cache: &UsersCache) -> Result<Self> {
+ pub fn empty(path: &Path, users: &Users) -> Result<Self> {
let filename = filename_from_path(path)?;
- let fileinfo = FileInfo::from_path_with_name(path, filename, users_cache)?;
+ let fileinfo = FileInfo::from_path_with_name(path, filename, users)?;
let node = Node::empty(fileinfo);
let leaves = vec![];
let position = vec![0];
diff --git a/src/users.rs b/src/users.rs
index 6b2aa62..38beaae 100644
--- a/src/users.rs
+++ b/src/users.rs
@@ -1,3 +1,14 @@
+/// Users and Groups of current Unix system.
+/// It requires `/etc/passwd` and `/etc/group` to be at their usual place.
+///
+/// Holds two vectors, one for users, one for group.
+/// Each vector is a pair of `(u32, String)`, for uid, username and gid, groupname respectively.
+/// Those vectors are read from `/etc/passwd` and from `/etc/group` directly.
+/// It also provides two methods allowing to access the name from uid or gid.
+///
+/// Both users and groups use vectors which are sorted by their first element (uid/gid).
+/// It allows use to use bisection (binary search) to find the correct name.
+/// Cloning should be easy.
#[derive(Clone, Debug, Default)]
pub struct Users {
users: Vec<(u32, String)>,
@@ -5,6 +16,7 @@ pub struct Users {
}
impl Users {
+ /// Name of the user from its uid.
pub fn get_user_by_uid(&self, uid: u32) -> Option<String> {
if let Ok(index) = self
.users
@@ -18,6 +30,7 @@ impl Users {
None
}
+ /// Name of the group from its gid.
pub fn get_group_by_gid(&self, gid: u32) -> Option<String> {
if let Ok(index) = self
.groups
@@ -53,11 +66,9 @@ impl Users {
self
}
+ /// Creates a default instance and update both users and groups from
+ /// `/etc/passwd` and `/etc/group` respectively.
pub fn new() -> Self {
Self::default().update_users().update_groups()
}
-
- pub fn update(mut self) {
- self = Self::new();
- }
}
diff --git a/src/utils.rs b/src/utils.rs
index 13bf17f..2563469 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -1,5 +1,7 @@
use std::borrow::Borrow;
+use std::fs::metadata;
use std::io::BufRead;
+use std::os::unix::fs::MetadataExt;
use std::path::Path;
use anyhow::{Context, Result};
@@ -7,12 +9,12 @@ use copypasta::{ClipboardContext, ClipboardProvider};
use rand::Rng;
use sysinfo::{Disk, DiskExt};
use tuikit::term::Term;
-use users::{get_current_uid, get_user_by_uid};
use crate::constant_strings_paths::{CALC_PDF_PATH, THUMBNAIL_PATH};
use crate::content_window::ContentWindow;
use crate::fileinfo::human_size;
use crate::nvim::nvim;
+use crate::users::Users;
/// Returns a `Display` instance after `tuikit::term::Term` creation.
pub fn init_term() -> Result<Term> {
@@ -88,14 +90,19 @@ pub fn filename_from_path(path: &std::path::Path) -> Result<&str> {
.context("couldn't parse the filename")
}
+/// Uid of the current user.
+/// Read from `/proc/self`.
+/// Should never fail.
+pub fn current_uid() -> Result<u32> {
+ Ok(metadata("/proc/self").map(|m| m.uid())?)
+}
+
/// Get the current username as a String.
+/// Read from `/proc/self` and then `/etc/passwd` and should never fail.
pub fn current_username() -> Result<String> {
- let user = get_user_by_uid(get_current_uid()).context("Couldn't read username")?;
- Ok(user
- .name()
- .to_str()
- .context("Couldn't read username")?
- .to_owned())
+ let uid = current_uid()?;
+ let user = Users::new().get_user_by_uid(uid);
+ user.context("Couldn't read my own name")
}
/// True iff the command is available in $PATH.