Repository: sharkdp/fd
Pull request #1402 (2023-10-22 05:38:00)

maint: Remove use of unmaintained users crate
The users crate is no longer maintained. There is a maintained fork called uzers, but we already have a dependency on nix, and that has the functionality we need.


Patch:
diff --git a/Cargo.lock b/Cargo.lock
index 8940686..64efc0a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -317,7 +317,6 @@ dependencies = [
  "regex-syntax 0.7.5",
  "tempfile",
  "test-case",
- "users",
  "version_check",
 ]
 
@@ -792,16 +791,6 @@ version = "1.0.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
 
-[[package]]
-name = "users"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24cc0f6d6f267b73e5a2cadf007ba8f9bc39c6a6f9666f8cf25ea809a153b032"
-dependencies = [
- "libc",
- "log",
-]
-
 [[package]]
 name = "utf8parse"
 version = "0.2.1"
diff --git a/Cargo.toml b/Cargo.toml
index 3f55f62..2eb133d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -66,8 +66,7 @@ default-features = false
 features = ["nu-ansi-term"]
 
 [target.'cfg(unix)'.dependencies]
-users = "0.11.0"
-nix = { version = "0.26.2", default-features = false, features = ["signal"] }
+nix = { version = "0.26.2", default-features = false, features = ["signal", "user"] }
 
 [target.'cfg(all(unix, not(target_os = "redox")))'.dependencies]
 libc = "0.2"
diff --git a/src/filter/owner.rs b/src/filter/owner.rs
index 842c711..3ee38d7 100644
--- a/src/filter/owner.rs
+++ b/src/filter/owner.rs
@@ -1,4 +1,5 @@
 use anyhow::{anyhow, Result};
+use nix::unistd::{Group, User};
 use std::fs;
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
@@ -35,16 +36,22 @@ impl OwnerFilter {
         }
 
         let uid = Check::parse(fst, |s| {
-            s.parse()
-                .ok()
-                .or_else(|| users::get_user_by_name(s).map(|user| user.uid()))
-                .ok_or_else(|| anyhow!("'{}' is not a recognized user name", s))
+            if let Ok(uid) = s.parse() {
+                Ok(uid)
+            } else {
+                User::from_name(s)?
+                    .map(|user| user.uid.as_raw())
+                    .ok_or_else(|| anyhow!("'{}' is not a recognized user name", s))
+            }
         })?;
         let gid = Check::parse(snd, |s| {
-            s.parse()
-                .ok()
-                .or_else(|| users::get_group_by_name(s).map(|group| group.gid()))
-                .ok_or_else(|| anyhow!("'{}' is not a recognized group name", s))
+            if let Ok(gid) = s.parse() {
+                Ok(gid)
+            } else {
+                Group::from_name(s)?
+                    .map(|group| group.gid.as_raw())
+                    .ok_or_else(|| anyhow!("'{}' is not a recognized group name", s))
+            }
         })?;
 
         Ok(OwnerFilter { uid, gid })


Test patch:
diff --git a/tests/tests.rs b/tests/tests.rs
index daad76f..87e8ed7 100644
--- a/tests/tests.rs
+++ b/tests/tests.rs
@@ -1,5 +1,7 @@
 mod testenv;
 
+#[cfg(unix)]
+use nix::unistd::{Gid, Group, Uid, User};
 use std::fs;
 use std::io::Write;
 use std::path::Path;
@@ -1302,7 +1304,7 @@ fn test_type_executable() {
     // This test assumes the current user isn't root
     // (otherwise if the executable bit is set for any level, it is executable for the current
     // user)
-    if users::get_current_uid() == 0 {
+    if Uid::current().is_root() {
         return;
     }
 
@@ -2261,10 +2263,10 @@ fn test_owner_ignore_all() {
 #[test]
 fn test_owner_current_user() {
     let te = TestEnv::new(DEFAULT_DIRS, DEFAULT_FILES);
-    let uid = users::get_current_uid();
+    let uid = Uid::current();
     te.assert_output(&["--owner", &uid.to_string(), "a.foo"], "a.foo");
-    if let Some(username) = users::get_current_username().map(|u| u.into_string().unwrap()) {
-        te.assert_output(&["--owner", &username, "a.foo"], "a.foo");
+    if let Ok(Some(user)) = User::from_uid(uid) {
+        te.assert_output(&["--owner", &user.name, "a.foo"], "a.foo");
     }
 }
 
@@ -2272,10 +2274,10 @@ fn test_owner_current_user() {
 #[test]
 fn test_owner_current_group() {
     let te = TestEnv::new(DEFAULT_DIRS, DEFAULT_FILES);
-    let gid = users::get_current_gid();
+    let gid = Gid::current();
     te.assert_output(&["--owner", &format!(":{}", gid), "a.foo"], "a.foo");
-    if let Some(groupname) = users::get_current_groupname().map(|u| u.into_string().unwrap()) {
-        te.assert_output(&["--owner", &format!(":{}", groupname), "a.foo"], "a.foo");
+    if let Ok(Some(group)) = Group::from_gid(gid) {
+        te.assert_output(&["--owner", &format!(":{}", group.name), "a.foo"], "a.foo");
     }
 }
 
@@ -2283,7 +2285,7 @@ fn test_owner_current_group() {
 #[test]
 fn test_owner_root() {
     // This test assumes the current user isn't root
-    if users::get_current_uid() == 0 || users::get_current_gid() == 0 {
+    if Uid::current().is_root() || Gid::current() == Gid::from_raw(0) {
         return;
     }
     let te = TestEnv::new(DEFAULT_DIRS, DEFAULT_FILES);