Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save cgwalters/e99607673f515b4e27413a17c4f22b6b to your computer and use it in GitHub Desktop.
Save cgwalters/e99607673f515b4e27413a17c4f22b6b to your computer and use it in GitHub Desktop.
```
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