provenant/parsers/debian/
tarball.rs1use std::path::Path;
5
6use crate::models::{DatasourceId, PackageData, PackageType};
7use crate::parsers::utils::truncate_field;
8
9use super::super::metadata::ParserMetadata;
10use super::utils::build_debian_purl;
11use super::{PACKAGE_TYPE, default_package_data};
12use crate::parsers::PackageParser;
13
14pub struct DebianOrigTarParser;
16
17impl PackageParser for DebianOrigTarParser {
18 const PACKAGE_TYPE: PackageType = PACKAGE_TYPE;
19
20 fn metadata() -> Vec<ParserMetadata> {
21 vec![ParserMetadata {
22 description: "Debian original source tarball",
23 file_patterns: &["**/*.orig.tar.*"],
24 package_type: "deb",
25 primary_language: "",
26 documentation_url: Some("https://www.debian.org/doc/debian-policy/ch-source.html"),
27 }]
28 }
29
30 fn is_match(path: &Path) -> bool {
31 path.file_name()
32 .and_then(|n| n.to_str())
33 .map(|name| name.contains(".orig.tar."))
34 .unwrap_or(false)
35 }
36
37 fn extract_packages(path: &Path) -> Vec<PackageData> {
38 let filename = match path.file_name().and_then(|n| n.to_str()) {
39 Some(f) => f,
40 None => {
41 return vec![default_package_data(
42 DatasourceId::DebianOriginalSourceTarball,
43 )];
44 }
45 };
46
47 vec![parse_source_tarball_filename(
48 filename,
49 DatasourceId::DebianOriginalSourceTarball,
50 )]
51 }
52}
53
54pub struct DebianDebianTarParser;
56
57impl PackageParser for DebianDebianTarParser {
58 const PACKAGE_TYPE: PackageType = PACKAGE_TYPE;
59
60 fn metadata() -> Vec<ParserMetadata> {
61 vec![ParserMetadata {
62 description: "Debian source metadata tarball",
63 file_patterns: &["**/*.debian.tar.*"],
64 package_type: "deb",
65 primary_language: "",
66 documentation_url: Some("https://www.debian.org/doc/debian-policy/ch-source.html"),
67 }]
68 }
69
70 fn is_match(path: &Path) -> bool {
71 path.file_name()
72 .and_then(|n| n.to_str())
73 .map(|name| name.contains(".debian.tar."))
74 .unwrap_or(false)
75 }
76
77 fn extract_packages(path: &Path) -> Vec<PackageData> {
78 let filename = match path.file_name().and_then(|n| n.to_str()) {
79 Some(f) => f,
80 None => {
81 return vec![default_package_data(
82 DatasourceId::DebianSourceMetadataTarball,
83 )];
84 }
85 };
86
87 vec![parse_source_tarball_filename(
88 filename,
89 DatasourceId::DebianSourceMetadataTarball,
90 )]
91 }
92}
93
94fn parse_source_tarball_filename(filename: &str, datasource_id: DatasourceId) -> PackageData {
95 let without_tar_ext = filename
96 .trim_end_matches(".gz")
97 .trim_end_matches(".xz")
98 .trim_end_matches(".bz2")
99 .trim_end_matches(".tar");
100
101 let parts: Vec<&str> = without_tar_ext.splitn(2, '_').collect();
102 if parts.len() < 2 {
103 return default_package_data(datasource_id);
104 }
105
106 let name = truncate_field(parts[0].to_string());
107 let version_with_suffix = parts[1];
108
109 let version = version_with_suffix
110 .trim_end_matches(".orig")
111 .trim_end_matches(".debian")
112 .to_string();
113 let version = truncate_field(version);
114
115 let namespace = Some("debian".to_string());
116
117 PackageData {
118 datasource_id: Some(datasource_id),
119 package_type: Some(PACKAGE_TYPE),
120 namespace: namespace.clone(),
121 name: Some(name.clone()),
122 version: Some(version.clone()),
123 purl: build_debian_purl(&name, Some(&version), namespace.as_deref(), None),
124 ..Default::default()
125 }
126}
127
128#[cfg(test)]
129mod tests {
130 use super::*;
131 use crate::models::DatasourceId;
132 use std::path::PathBuf;
133
134 #[test]
135 fn test_orig_tar_parser_is_match() {
136 assert!(DebianOrigTarParser::is_match(&PathBuf::from(
137 "package_1.0.orig.tar.gz"
138 )));
139 assert!(DebianOrigTarParser::is_match(&PathBuf::from(
140 "abseil_0~20200923.3.orig.tar.xz"
141 )));
142 assert!(!DebianOrigTarParser::is_match(&PathBuf::from(
143 "package.debian.tar.gz"
144 )));
145 assert!(!DebianOrigTarParser::is_match(&PathBuf::from("control")));
146 }
147
148 #[test]
149 fn test_debian_tar_parser_is_match() {
150 assert!(DebianDebianTarParser::is_match(&PathBuf::from(
151 "package_1.0-1.debian.tar.xz"
152 )));
153 assert!(DebianDebianTarParser::is_match(&PathBuf::from(
154 "abseil_20220623.1-1.debian.tar.gz"
155 )));
156 assert!(!DebianDebianTarParser::is_match(&PathBuf::from(
157 "package.orig.tar.gz"
158 )));
159 assert!(!DebianDebianTarParser::is_match(&PathBuf::from("control")));
160 }
161
162 #[test]
163 fn test_parse_orig_tar_filename() {
164 let pkg = parse_source_tarball_filename(
165 "abseil_0~20200923.3.orig.tar.gz",
166 DatasourceId::DebianOriginalSourceTarball,
167 );
168 assert_eq!(pkg.name, Some("abseil".to_string()));
169 assert_eq!(pkg.version, Some("0~20200923.3".to_string()));
170 assert_eq!(pkg.namespace, Some("debian".to_string()));
171 assert_eq!(
172 pkg.purl,
173 Some("pkg:deb/debian/abseil@0~20200923.3".to_string())
174 );
175 assert_eq!(
176 pkg.datasource_id,
177 Some(DatasourceId::DebianOriginalSourceTarball)
178 );
179 }
180
181 #[test]
182 fn test_parse_debian_tar_filename() {
183 let pkg = parse_source_tarball_filename(
184 "abseil_20220623.1-1.debian.tar.xz",
185 DatasourceId::DebianSourceMetadataTarball,
186 );
187 assert_eq!(pkg.name, Some("abseil".to_string()));
188 assert_eq!(pkg.version, Some("20220623.1-1".to_string()));
189 assert_eq!(pkg.namespace, Some("debian".to_string()));
190 assert_eq!(
191 pkg.purl,
192 Some("pkg:deb/debian/abseil@20220623.1-1".to_string())
193 );
194 }
195
196 #[test]
197 fn test_parse_source_tarball_various_compressions() {
198 let pkg_gz = parse_source_tarball_filename(
199 "test_1.0.orig.tar.gz",
200 DatasourceId::DebianOriginalSourceTarball,
201 );
202 let pkg_xz = parse_source_tarball_filename(
203 "test_1.0.orig.tar.xz",
204 DatasourceId::DebianOriginalSourceTarball,
205 );
206 let pkg_bz2 = parse_source_tarball_filename(
207 "test_1.0.orig.tar.bz2",
208 DatasourceId::DebianOriginalSourceTarball,
209 );
210
211 assert_eq!(pkg_gz.version, Some("1.0".to_string()));
212 assert_eq!(pkg_xz.version, Some("1.0".to_string()));
213 assert_eq!(pkg_bz2.version, Some("1.0".to_string()));
214 }
215
216 #[test]
217 fn test_parse_source_tarball_invalid_format() {
218 let pkg = parse_source_tarball_filename(
219 "invalid-no-underscore.tar.gz",
220 DatasourceId::DebianOriginalSourceTarball,
221 );
222 assert!(pkg.name.is_none());
223 assert!(pkg.version.is_none());
224 }
225}