diff --git a/cli/src/command/chmod.rs b/cli/src/command/chmod.rs index cf2485f6e..bf69659b0 100644 --- a/cli/src/command/chmod.rs +++ b/cli/src/command/chmod.rs @@ -4,6 +4,7 @@ use crate::{ utils::{GlobPatterns, PathPartExt}, }; use clap::{Parser, ValueHint}; +use pna::RegularEntry; use std::{ io, path::PathBuf, @@ -43,14 +44,7 @@ fn archive_chmod(args: ChmodCommand) -> io::Result<()> { |entry| { let entry = entry?; if globs.matches_any(entry.header().path()) { - let metadata = entry.metadata().clone(); - let permission = metadata.permission().map(|p| { - let mode = args.mode.apply_to(p.permissions()); - pna::Permission::new(p.uid(), p.uname().into(), p.gid(), p.gname().into(), mode) - }); - Ok(Some( - entry.with_metadata(metadata.with_permission(permission)), - )) + Ok(Some(transform_entry(entry, args.mode))) } else { Ok(Some(entry)) } @@ -58,6 +52,16 @@ fn archive_chmod(args: ChmodCommand) -> io::Result<()> { ) } +#[inline] +fn transform_entry(entry: RegularEntry, mode: Mode) -> RegularEntry { + let metadata = entry.metadata().clone(); + let permission = metadata.permission().map(|p| { + let mode = mode.apply_to(p.permissions()); + pna::Permission::new(p.uid(), p.uname().into(), p.gid(), p.gname().into(), mode) + }); + entry.with_metadata(metadata.with_permission(permission)) +} + #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] pub(crate) enum Target { User, diff --git a/cli/src/command/chown.rs b/cli/src/command/chown.rs index b2af7f61a..f8456f2cc 100644 --- a/cli/src/command/chown.rs +++ b/cli/src/command/chown.rs @@ -6,6 +6,7 @@ use crate::{ utils::{GlobPatterns, PathPartExt}, }; use clap::{Parser, ValueHint}; +use pna::RegularEntry; use std::ops::Not; use std::{io, path::PathBuf, str::FromStr}; @@ -42,36 +43,7 @@ fn archive_chown(args: ChownCommand) -> io::Result<()> { |entry| { let entry = entry?; if globs.matches_any(entry.header().path()) { - let metadata = entry.metadata().clone(); - let permission = metadata.permission().map(|p| { - let user = args.owner.user(); - #[cfg(unix)] - let user = user.and_then(|it| { - User::from_name(it).map(|it| (it.as_raw().into(), it.name().into())) - }); - #[cfg(windows)] - let user = user - .and_then(|it| User::from_name(it).map(|it| (u64::MAX, it.name().into()))); - #[cfg(not(any(unix, windows)))] - let user = user.map(|_| (p.uid(), p.uname().into())); - let (uid, uname) = user.unwrap_or_else(|| (p.uid(), p.uname().into())); - - let group = args.owner.group(); - #[cfg(unix)] - let group = group.and_then(|it| { - Group::from_name(it).map(|it| (it.as_raw().into(), it.name().into())) - }); - #[cfg(windows)] - let group = group - .and_then(|it| Group::from_name(it).map(|it| (u64::MAX, it.name().into()))); - #[cfg(not(any(unix, windows)))] - let group = group.map(|_| (p.gid(), p.gname().into())); - let (gid, gname) = group.unwrap_or_else(|| (p.gid(), p.gname().into())); - pna::Permission::new(uid, uname, gid, gname, p.permissions()) - }); - Ok(Some( - entry.with_metadata(metadata.with_permission(permission)), - )) + Ok(Some(transform_entry(entry, &args.owner))) } else { Ok(Some(entry)) } @@ -79,6 +51,35 @@ fn archive_chown(args: ChownCommand) -> io::Result<()> { ) } +#[inline] +fn transform_entry(entry: RegularEntry, owner: &Owner) -> RegularEntry { + let metadata = entry.metadata().clone(); + let permission = metadata.permission().map(|p| { + let user = owner.user(); + #[cfg(unix)] + let user = user + .and_then(|it| User::from_name(it).map(|it| (it.as_raw().into(), it.name().into()))); + #[cfg(windows)] + let user = user.and_then(|it| User::from_name(it).map(|it| (u64::MAX, it.name().into()))); + #[cfg(not(any(unix, windows)))] + let user = user.map(|_| (p.uid(), p.uname().into())); + let (uid, uname) = user.unwrap_or_else(|| (p.uid(), p.uname().into())); + + let group = owner.group(); + #[cfg(unix)] + let group = group + .and_then(|it| Group::from_name(it).map(|it| (it.as_raw().into(), it.name().into()))); + #[cfg(windows)] + let group = + group.and_then(|it| Group::from_name(it).map(|it| (u64::MAX, it.name().into()))); + #[cfg(not(any(unix, windows)))] + let group = group.map(|_| (p.gid(), p.gname().into())); + let (gid, gname) = group.unwrap_or_else(|| (p.gid(), p.gname().into())); + pna::Permission::new(uid, uname, gid, gname, p.permissions()) + }); + entry.with_metadata(metadata.with_permission(permission)) +} + #[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] pub(crate) struct Owner { user: Option, diff --git a/cli/src/command/xattr.rs b/cli/src/command/xattr.rs index 4f12ca795..8171bfa31 100644 --- a/cli/src/command/xattr.rs +++ b/cli/src/command/xattr.rs @@ -10,6 +10,7 @@ use crate::{ use base64::Engine; use clap::{Parser, ValueHint}; use indexmap::IndexMap; +use pna::RegularEntry; use std::{ fmt::{Display, Formatter, Write}, io, @@ -177,23 +178,12 @@ fn archive_set_xattr(args: SetXattrCommand) -> io::Result<()> { |entry| { let entry = entry?; if globs.matches_any(entry.header().path()) { - let mut xattrs = entry - .xattrs() - .iter() - .map(|it| (it.name(), it.value())) - .collect::>(); - if let Some(name) = args.name.as_deref() { - let map_entry = xattrs.entry(name); - map_entry.or_insert(value); - } - if let Some(name) = args.name.as_deref() { - xattrs.shift_remove_entry(name); - } - let xattrs = xattrs - .into_iter() - .map(|(key, value)| pna::ExtendedAttribute::new(key.into(), value.into())) - .collect::>(); - Ok(Some(entry.with_xattrs(&xattrs))) + Ok(Some(transform_entry( + entry, + args.name.as_deref(), + value, + args.remove.as_deref(), + ))) } else { Ok(Some(entry)) } @@ -201,6 +191,32 @@ fn archive_set_xattr(args: SetXattrCommand) -> io::Result<()> { ) } +#[inline] +fn transform_entry( + entry: RegularEntry, + name: Option<&str>, + value: &[u8], + remove: Option<&str>, +) -> RegularEntry { + let mut xattrs = entry + .xattrs() + .iter() + .map(|it| (it.name(), it.value())) + .collect::>(); + if let Some(name) = name { + let map_entry = xattrs.entry(name); + map_entry.or_insert(value); + } + if let Some(name) = remove { + xattrs.shift_remove_entry(name); + } + let xattrs = xattrs + .into_iter() + .map(|(key, value)| pna::ExtendedAttribute::new(key.into(), value.into())) + .collect::>(); + entry.with_xattrs(&xattrs) +} + #[derive(Clone, Eq, PartialEq, Hash, Debug)] struct Value(Vec);