summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/manifest.rs11
-rw-r--r--tests/compare.rs62
2 files changed, 73 insertions, 0 deletions
diff --git a/src/manifest.rs b/src/manifest.rs
index 57e57c5..c25f0a8 100644
--- a/src/manifest.rs
+++ b/src/manifest.rs
@@ -96,6 +96,9 @@ impl ArtifactManifest {
let mut entry = entry
.with_context(|| format!("read archive member from {}", archive_path.display()))?;
let path = portable_path(&entry.path()?)?;
+ if is_archive_root_path(&path) || is_internal_metadata_path(&path) {
+ continue;
+ }
let entry_type = entry.header().entry_type();
let kind = match entry_type {
EntryType::Regular => "file",
@@ -235,6 +238,14 @@ fn is_enabled_service(path: &str) -> bool {
&& path.ends_with(".service")
}
+fn is_internal_metadata_path(path: &str) -> bool {
+ matches!(path.split('/').next(), Some(".host" | ".fakedata"))
+}
+
+fn is_archive_root_path(path: &str) -> bool {
+ path == "." || path == "./"
+}
+
fn service_name(path: &str) -> Result<&str> {
path.rsplit('/')
.next()
diff --git a/tests/compare.rs b/tests/compare.rs
index 0853572..6dd7317 100644
--- a/tests/compare.rs
+++ b/tests/compare.rs
@@ -4,6 +4,7 @@ use alt_controller_image::manifest::{
ArchiveMemberRecord, ArtifactManifest, FileRecord, InitrdRecord, PackageRecord, ServiceRecord,
};
use std::fs;
+use std::io::Cursor;
use std::os::unix::fs::symlink;
use tempfile::tempdir;
@@ -183,3 +184,64 @@ fn collects_comparable_semantic_facts_directly_from_a_tar_artifact() {
);
assert_eq!(manifest.services, vec![ServiceRecord::new("controller.service", true)]);
}
+
+#[test]
+fn normalizes_legacy_dot_prefixed_archive_paths_before_comparison() {
+ let fixture = tempdir().expect("temporary directory");
+ let artifact = fixture.path().join("legacy.tar");
+ let file = fs::File::create(&artifact).expect("create legacy archive");
+ let mut archive = tar::Builder::new(file);
+ let mut header = tar::Header::new_gnu();
+ header.set_size(11);
+ header.set_mode(0o644);
+ header.set_cksum();
+ archive
+ .append_data(&mut header, "./etc/controller.conf", Cursor::new(b"controller\n"))
+ .expect("append legacy-style member");
+ archive.finish().expect("finish legacy archive");
+
+ let manifest = ArtifactManifest::collect_archive(&artifact).expect("collect legacy archive facts");
+ let expected = ArtifactManifest::new(
+ vec![],
+ vec![FileRecord::file(
+ "etc/controller.conf",
+ "2d5c759b2b539229e09d362e8dbe0ae410ff8c9ece6038624458724520683f5b",
+ )],
+ None,
+ vec![],
+ vec![ArchiveMemberRecord::new("etc/controller.conf", "file")],
+ )
+ .expect("valid normalized manifest");
+
+ assert!(compare(&manifest, &expected).is_equivalent());
+}
+
+#[test]
+fn excludes_legacy_internal_host_and_fakedata_archive_members() {
+ let fixture = tempdir().expect("temporary directory");
+ let rootfs = fixture.path().join("rootfs");
+ fs::create_dir_all(rootfs.join(".host/private")).expect("create host metadata");
+ fs::create_dir_all(rootfs.join(".fakedata")).expect("create fakeroot metadata");
+ fs::write(rootfs.join(".host/private/secret"), "metadata").expect("write host metadata");
+ fs::write(rootfs.join(".fakedata/owner"), "metadata").expect("write fakeroot metadata");
+ fs::create_dir_all(rootfs.join("etc")).expect("create visible directory");
+ fs::write(rootfs.join("etc/controller.conf"), "controller\n").expect("write visible file");
+ let legacy = fixture.path().join("legacy.tar");
+ let native = fixture.path().join("native.tar");
+ let mut legacy_writer = tar::Builder::new(fs::File::create(&legacy).expect("create legacy archive"));
+ legacy_writer
+ .append_dir_all(".", &rootfs)
+ .expect("write legacy archive with internal metadata");
+ legacy_writer.finish().expect("finish legacy archive");
+ NativeTarWriter::new().write(&rootfs, &native).expect("write native archive");
+
+ let legacy_manifest = ArtifactManifest::collect_archive(&legacy).expect("collect legacy facts");
+ let native_manifest = ArtifactManifest::collect_archive(&native).expect("collect native facts");
+
+ assert!(legacy_manifest
+ .archive_members
+ .iter()
+ .all(|record| !record.path.starts_with(".host/") && !record.path.starts_with(".fakedata/")));
+ let report = compare(&legacy_manifest, &native_manifest);
+ assert!(report.is_equivalent(), "{}", report.render());
+}