Created
May 30, 2025 16:21
-
-
Save cgwalters/e99607673f515b4e27413a17c4f22b6b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
``` | |
diff --git i/ostree-ext/src/tar/export.rs w/ostree-ext/src/tar/export.rs | |
index 13f4f4ac..8b4c1c8a 100644 | |
--- i/ostree-ext/src/tar/export.rs | |
+++ w/ostree-ext/src/tar/export.rs | |
@@ -12,6 +12,7 @@ use gvariant::{Marker, Structure}; | |
use ostree::gio; | |
use std::borrow::Borrow; | |
use std::borrow::Cow; | |
+use std::collections::HashMap; | |
use std::collections::HashSet; | |
use std::ffi::CStr; | |
use std::io::BufReader; | |
@@ -615,6 +616,40 @@ impl<'a, W: std::io::Write> OstreeTarWriter<'a, W> { | |
.append_data(&mut header, "var/tmp", std::io::empty())?; | |
Ok(()) | |
} | |
+ | |
+ fn write_parents_of<W: std::io::Write>( | |
+ &self, | |
+ path: &str, | |
+ cache: &mut HashSet<Utf8PathBuf>, | |
+ ) -> Result<()> { | |
+ let path = Utf8Path::new(path); | |
+ let Some(parent) = path.parent() else { | |
+ return Ok(()); | |
+ }; | |
+ if cache.contains(parent) { | |
+ return Ok(()); | |
+ } | |
+ let inserted = cache.insert(parent.to_owned()); | |
+ debug_assert!(inserted); | |
+ let root = self | |
+ .repo | |
+ .read_commit(&self.commit_checksum, gio::Cancellable::NONE)? | |
+ .0; | |
+ let parent = root.resolve_relative_path(parent); | |
+ let queryattrs = "standard::*"; | |
+ let stat = parent.query_info("standard::*", queryflags, gio::Cancellable::NONE)?; | |
+ let uid = stat.attribute_uint32("standard::uid"); | |
+ let gid = stat.attribute_uint32("standard::gid"); | |
+ let mode = stat.attribute_uint32("standard::mode"); | |
+ let mut header = tar::Header::new_gnu(); | |
+ header.set_entry_type(tar::EntryType::Directory); | |
+ header.set_size(0); | |
+ header.set_uid(uid as u64); | |
+ header.set_gid(gid as u64); | |
+ header.set_mode(self.filter_mode(mode)); | |
+ self.out.append_data(&mut header, path, std::io::empty())?; | |
+ Ok(()) | |
+ } | |
} | |
/// Recursively walk an OSTree commit and generate data into a `[tar::Builder]` | |
@@ -664,11 +699,13 @@ fn write_chunk<W: std::io::Write>( | |
writer: &mut OstreeTarWriter<W>, | |
chunk: chunking::ChunkMapping, | |
) -> Result<()> { | |
+ let cache = std::collections::HashMap::new(); | |
for (checksum, (_size, paths)) in chunk.into_iter() { | |
let (objpath, h) = writer.append_content(checksum.borrow())?; | |
for path in paths.iter() { | |
let path = path_for_tar_v1(path); | |
let h = h.clone(); | |
+ writer.write_parents_of(&path, &mut cache); | |
writer.append_content_hardlink(&objpath, h, path)?; | |
} | |
} | |
``` |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment