Skip to content

Commit 92e5fa5

Browse files
committed
🐛 Fix contains unnecessary control character in result of list subcommand with --format jsonl
1 parent cd0e9e2 commit 92e5fa5

File tree

1 file changed

+61
-20
lines changed

1 file changed

+61
-20
lines changed

cli/src/command/list.rs

Lines changed: 61 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ use clap::{
2020
ArgGroup, Parser,
2121
};
2222
use pna::{
23-
prelude::*, Compression, DataKind, Encryption, ExtendedAttribute, NormalEntry, Permission,
24-
RawChunk, ReadEntry, ReadOptions, SolidHeader,
23+
prelude::*, Compression, DataKind, Encryption, ExtendedAttribute, NormalEntry, RawChunk,
24+
ReadEntry, ReadOptions, SolidHeader,
2525
};
2626
use rayon::prelude::*;
2727
use serde::{Deserialize, Serialize};
@@ -118,9 +118,10 @@ impl FromStr for Format {
118118
}
119119

120120
struct TableRow {
121+
data_kind: DataKind,
121122
encryption: String,
122123
compression: String,
123-
permissions: String,
124+
permission_mode: u16,
124125
raw_size: Option<u128>,
125126
compressed_size: usize,
126127
user: Option<Subject>,
@@ -163,9 +164,8 @@ where
163164
let header = entry.header();
164165
let metadata = entry.metadata();
165166
let acl = entry.acl()?;
166-
let has_acl = !acl.is_empty();
167-
let has_xattr = !entry.xattrs().is_empty();
168167
Ok(Self {
168+
data_kind: header.data_kind(),
169169
encryption: match solid
170170
.map(|s| (s.encryption(), s.cipher_mode()))
171171
.unwrap_or_else(|| (header.encryption(), header.cipher_mode()))
@@ -186,12 +186,7 @@ where
186186
(method, None) => format!("{:?}", method).to_ascii_lowercase(),
187187
(method, Some(_)) => format!("{:?}(solid)", method).to_ascii_lowercase(),
188188
},
189-
permissions: paint_permission(
190-
header.data_kind(),
191-
metadata.permission(),
192-
has_xattr,
193-
has_acl,
194-
),
189+
permission_mode: metadata.permission().map_or(0, |it| it.permissions()),
195190
raw_size: metadata.raw_file_size(),
196191
compressed_size: metadata.compressed_size(),
197192
user: metadata.permission().map(|p| Subject {
@@ -406,10 +401,17 @@ fn detail_list_entries(entries: impl Iterator<Item = TableRow>, options: ListOpt
406401
builder.push_record(header);
407402
}
408403
for content in entries {
404+
let has_acl = !content.acl.is_empty();
405+
let has_xattr = !content.xattrs.is_empty();
409406
builder.push_record([
410407
content.encryption,
411408
content.compression,
412-
content.permissions,
409+
paint_permission(
410+
content.data_kind,
411+
content.permission_mode,
412+
has_xattr,
413+
has_acl,
414+
),
413415
content
414416
.raw_size
415417
.map_or_else(|| "-".into(), |size| size.to_string()),
@@ -564,13 +566,7 @@ fn kind_paint(kind: DataKind) -> impl Display + 'static {
564566
}
565567
}
566568

567-
fn paint_permission(
568-
kind: DataKind,
569-
permission: Option<&Permission>,
570-
has_xattr: bool,
571-
has_acl: bool,
572-
) -> String {
573-
let permission = permission.map(|p| p.permissions()).unwrap_or_default();
569+
fn paint_permission(kind: DataKind, permission: u16, has_xattr: bool, has_acl: bool) -> String {
574570
let paint = |style: &'static Style, c: char, bit: u16| {
575571
if permission & bit != 0 {
576572
style.paint(c)
@@ -601,6 +597,46 @@ fn paint_permission(
601597
)
602598
}
603599

600+
fn kind_char(kind: DataKind) -> char {
601+
match kind {
602+
DataKind::File | DataKind::HardLink => '.',
603+
DataKind::Directory => 'd',
604+
DataKind::SymbolicLink => 'l',
605+
}
606+
}
607+
608+
fn permission_string(kind: DataKind, permission: u16, has_xattr: bool, has_acl: bool) -> String {
609+
#[inline(always)]
610+
fn paint(permission: u16, c: char, bit: u16) -> char {
611+
if permission & bit != 0 {
612+
c
613+
} else {
614+
'-'
615+
}
616+
}
617+
618+
format!(
619+
"{}{}{}{}{}{}{}{}{}{}{}",
620+
kind_char(kind),
621+
paint(permission, 'r', 0b100000000), // owner_read
622+
paint(permission, 'w', 0b010000000), // owner_write
623+
paint(permission, 'x', 0b001000000), // owner_exec
624+
paint(permission, 'r', 0b000100000), // group_read
625+
paint(permission, 'w', 0b000010000), // group_write
626+
paint(permission, 'x', 0b000001000), // group_exec
627+
paint(permission, 'r', 0b000000100), // other_read
628+
paint(permission, 'w', 0b000000010), // other_write
629+
paint(permission, 'x', 0b000000001), // other_exec
630+
if has_xattr {
631+
'@'
632+
} else if has_acl {
633+
'+'
634+
} else {
635+
' '
636+
},
637+
)
638+
}
639+
604640
#[derive(Serialize, Deserialize, Debug)]
605641
struct FileInfo {
606642
filename: String,
@@ -634,7 +670,12 @@ fn json_line_entries(entries: impl Iterator<Item = TableRow>) {
634670
let mut stdout = io::stdout().lock();
635671
for line in entries.map(|it| FileInfo {
636672
filename: it.name,
637-
permissions: it.permissions,
673+
permissions: permission_string(
674+
it.data_kind,
675+
it.permission_mode,
676+
!it.xattrs.is_empty(),
677+
!it.acl.is_empty(),
678+
),
638679
owner: it.user.map_or_else(|| "".into(), |it| it.name),
639680
group: it.group.map_or_else(|| "".into(), |it| it.name),
640681
raw_size: it.raw_size.unwrap_or_default(),

0 commit comments

Comments
 (0)