Watch
0
0
Fork
You've already forked hyperhive
0

keep the knowledge .git overlay unconditional

This commit is contained in:
atlas 2026-11-01 13:34:26 +01:00 • committed by mara
commit 35a49aaf42

View file

@ -346,20 +346,25 @@ fn validate_bind_path(path: &str) -> Result<()> {
/// Config mounts are matched by shape, not by a name list: the set is
/// dynamic, growing with each child bound into a parent.
///
/// Only a bind whose host source has a `.git` entry gets the overlay: nspawn
/// must create the mount point inside the read-only bind, which fails
/// (`EROFS`) where there is nothing to mount over. An archetype agent's
/// config is an empty directory. The entry is looked up without following a
/// symlink, and a symlink named `.git` counts as present, so a path that
/// leads somewhere else is still hidden.
/// `/knowledge` is overlaid unconditionally: its directory is created empty
/// and cloned into later, so a container started before the clone must
/// already hide the `.git` that arrives. A config mount gets the overlay only
/// when its host source has a `.git` entry: nspawn must create the mount
/// point inside the read-only bind, which fails (`EROFS`) where there is
/// nothing to mount over, as in an archetype agent's empty config directory.
/// The entry is looked up without following a symlink, and a symlink named
/// `.git` counts as present, so a path that leads somewhere else is still
/// hidden.
fn git_overlay_flags(binds: &[BindMount]) -> Vec<String> {
binds
.iter()
.filter(|b| {
let p = b.container_path.as_str();
p == "/knowledge" || (p.starts_with("/agents/") && p.ends_with("/config"))
p == "/knowledge"
|| (p.starts_with("/agents/")
&& p.ends_with("/config")
&& std::fs::symlink_metadata(Path::new(&b.host_path).join(".git")).is_ok())
})
.filter(|b| std::fs::symlink_metadata(Path::new(&b.host_path).join(".git")).is_ok())
.map(|b| format!("--tmpfs={}/.git", b.container_path))
.collect()
}
@ -712,12 +717,20 @@ mod tests {
let empty = scratch().to_string_lossy().into_owned();
let flags = git_overlay_flags(&[
bind_from(&empty, "/agents/updo/config"),
bind_from(&empty, "/knowledge"),
bind_from(&repo_source(), "/agents/atlas/config"),
]);
assert_eq!(flags, ["--tmpfs=/agents/atlas/config/.git"]);
}
/// `/knowledge` is cloned into after the container may have started, so
/// its overlay does not wait for a `.git` to exist.
#[test]
fn an_empty_knowledge_source_still_gets_the_overlay() {
let empty = scratch().to_string_lossy().into_owned();
let flags = git_overlay_flags(&[bind_from(&empty, "/knowledge")]);
assert_eq!(flags, ["--tmpfs=/knowledge/.git"]);
}
/// A symlink named `.git` is not followed: it counts as present, even
/// dangling, so the path it leads to is hidden rather than skipped.
#[test]