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
use camino::Utf8PathBuf;
use globset::GlobSet;
use serde::Serialize;
use crate::progress::{NoProgress, ProgressReport};
pub mod cmd;
pub mod error;
pub mod filter;
pub mod format;
pub mod modify;
pub mod progress;
pub mod seven_z;
pub mod tar;
pub mod tar_raw;
#[cfg(feature = "bzip2")]
pub mod tar_bz2;
pub mod tar_gz;
pub mod tar_xz;
pub mod tar_zst;
pub mod zip;
/// Metadata for a single entry within an archive.
#[derive(Serialize)]
pub struct Entry {
pub path: Utf8PathBuf,
pub size: u64,
pub mtime: u64,
pub mode: u32,
pub is_dir: bool,
/// Symlink/hardlink target, where the format exposes it without reading
/// entry data blocks: tar always, zip for unencrypted symlink entries,
/// 7z never (targets live inside the solid stream). Lossy-decoded —
/// used for display and for dry-run's structural traversal check, never
/// for extraction itself.
#[serde(skip_serializing_if = "Option::is_none")]
pub link_target: Option<String>,
}
/// Summary metadata for an archive.
#[derive(Serialize)]
pub struct ArchiveInfo {
pub format: &'static str,
pub entry_count: usize,
pub total_uncompressed: u64,
pub compressed_size: u64,
}
/// Options for compress operations.
pub struct CompressOpts<'a> {
pub level: Option<u32>,
pub excludes: GlobSet,
pub follow_symlinks: bool,
pub exclude_vcs_ignores: bool,
pub no_recursion: bool,
pub progress: &'a dyn ProgressReport,
/// Override mtime on all entries (unix timestamp).
pub fixed_mtime: Option<u64>,
/// Override uid on all entries.
pub fixed_uid: Option<u64>,
/// Override gid on all entries.
pub fixed_gid: Option<u64>,
/// Override permission mode on all entries (low 12 bits).
pub fixed_mode: Option<u32>,
/// Include only entries with mtime strictly greater than this (unix seconds).
pub newer_than: Option<i64>,
/// Include only entries with mtime strictly less than this (unix seconds).
pub older_than: Option<i64>,
/// When `true`, top-level inputs that fail to stat are warned about and
/// skipped instead of aborting the whole archive. An empty result still
/// errors out — we never produce an empty archive.
pub ignore_failed_read: bool,
/// Password for encrypting the archive (zip and 7z only).
pub password: Option<String>,
}
/// Options for decompress operations.
pub struct DecompressOpts<'a> {
pub force: bool,
pub no_overwrite: bool,
pub keep_newer: bool,
pub no_directory: bool,
pub strip_components: u32,
pub includes: GlobSet,
pub excludes: GlobSet,
pub backup_suffix: Option<String>,
pub preserve_permissions: bool,
/// Restore owner/group on extracted entries (tar-family only).
pub same_owner: bool,
/// Extract only entries with mtime strictly greater than this (unix seconds).
pub newer_than: Option<i64>,
/// Extract only entries with mtime strictly less than this (unix seconds).
pub older_than: Option<i64>,
/// Substring rename rules applied to each entry path after strip_components.
/// Each `(old, new)` is applied in order; all occurrences of `old` are replaced.
pub renames: Vec<(String, String)>,
/// Prefix prepended to every entry path after renames.
pub prefix: Option<Utf8PathBuf>,
pub progress: &'a dyn ProgressReport,
/// Password for decrypting the archive (zip and 7z only).
pub password: Option<String>,
}
impl CompressOpts<'_> {
/// Construct opts with no progress reporting (for tests / programmatic use).
pub fn new(level: Option<u32>, excludes: GlobSet) -> CompressOpts<'static> {
CompressOpts {
level,
excludes,
follow_symlinks: false,
exclude_vcs_ignores: false,
no_recursion: false,
progress: &NoProgress,
fixed_mtime: None,
fixed_uid: None,
fixed_gid: None,
fixed_mode: None,
newer_than: None,
older_than: None,
ignore_failed_read: false,
password: None,
}
}
}
impl DecompressOpts<'_> {
/// Construct opts with no progress reporting (for tests / programmatic use).
pub fn new(
force: bool,
strip_components: u32,
includes: GlobSet,
excludes: GlobSet,
) -> DecompressOpts<'static> {
DecompressOpts {
force,
no_overwrite: false,
keep_newer: false,
no_directory: false,
strip_components,
includes,
excludes,
backup_suffix: None,
preserve_permissions: false,
same_owner: false,
newer_than: None,
older_than: None,
renames: Vec::new(),
prefix: None,
progress: &NoProgress,
password: None,
}
}
}