migrate: an unreadable applied flake.nix fails that repo's migration instead of being overwritten
Only a missing file counts as 'marker absent'; any other read error (EACCES, EIO, non-UTF-8) used to read as empty, so the agent's flake.nix was replaced and committed.
This commit is contained in:
parent
99785989b9
commit
ba1515aa5e
1 changed files with 34 additions and 5 deletions
|
|
@ -168,19 +168,29 @@ async fn enumerate_agents() -> Result<Vec<hive_types::Ident>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn migrate_applied_repo(name: &str) -> Result<()> {
|
async fn migrate_applied_repo(name: &str) -> Result<()> {
|
||||||
let dir = crate::paths::applied_dir(name);
|
migrate_applied_dir(name, &crate::paths::applied_dir(name)).await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Rewrites the applied repo at `dir` to the module-only flake. A missing
|
||||||
|
/// `flake.nix` counts as "marker absent"; any other read error fails the
|
||||||
|
/// migration so the agent's file is never overwritten unread.
|
||||||
|
async fn migrate_applied_dir(name: &str, dir: &Path) -> Result<()> {
|
||||||
if !dir.join(".git").exists() {
|
if !dir.join(".git").exists() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let flake_path = dir.join("flake.nix");
|
let flake_path = dir.join("flake.nix");
|
||||||
let cur = std::fs::read_to_string(&flake_path).unwrap_or_default();
|
let cur = match std::fs::read_to_string(&flake_path) {
|
||||||
|
Ok(cur) => cur,
|
||||||
|
Err(e) if e.kind() == std::io::ErrorKind::NotFound => String::new(),
|
||||||
|
Err(e) => return Err(e).with_context(|| format!("read {}", flake_path.display())),
|
||||||
|
};
|
||||||
if cur.contains(MODULE_FLAKE_MARKER) {
|
if cur.contains(MODULE_FLAKE_MARKER) {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let want = lifecycle::initial_flake_nix();
|
let want = lifecycle::initial_flake_nix();
|
||||||
std::fs::write(&flake_path, want).with_context(|| format!("write {}", flake_path.display()))?;
|
std::fs::write(&flake_path, want).with_context(|| format!("write {}", flake_path.display()))?;
|
||||||
raw_git(
|
raw_git(
|
||||||
&dir,
|
dir,
|
||||||
&[
|
&[
|
||||||
"-c",
|
"-c",
|
||||||
"user.name=c0re",
|
"user.name=c0re",
|
||||||
|
|
@ -192,7 +202,7 @@ async fn migrate_applied_repo(name: &str) -> Result<()> {
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
raw_git(
|
raw_git(
|
||||||
&dir,
|
dir,
|
||||||
&[
|
&[
|
||||||
"-c",
|
"-c",
|
||||||
"user.name=c0re",
|
"user.name=c0re",
|
||||||
|
|
@ -206,7 +216,7 @@ async fn migrate_applied_repo(name: &str) -> Result<()> {
|
||||||
.await?;
|
.await?;
|
||||||
// Relocate deployed/0 to the migration commit so
|
// Relocate deployed/0 to the migration commit so
|
||||||
// setup_applied's existence check passes.
|
// setup_applied's existence check passes.
|
||||||
raw_git(&dir, &["tag", "-f", "deployed/0", "HEAD"]).await?;
|
raw_git(dir, &["tag", "-f", "deployed/0", "HEAD"]).await?;
|
||||||
tracing::info!(%name, "migration: applied repo migrated to module-only flake");
|
tracing::info!(%name, "migration: applied repo migrated to module-only flake");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -241,3 +251,22 @@ async fn raw_git(dir: &Path, args: &[&str]) -> Result<()> {
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn unreadable_flake_is_left_untouched() {
|
||||||
|
let dir = tempfile::tempdir().expect("tempdir");
|
||||||
|
std::fs::create_dir(dir.path().join(".git")).expect("mkdir .git");
|
||||||
|
let flake = dir.path().join("flake.nix");
|
||||||
|
let bytes = [0xff_u8, 0xfe, b'x'];
|
||||||
|
std::fs::write(&flake, bytes).expect("write flake");
|
||||||
|
|
||||||
|
let res = migrate_applied_dir("t", dir.path()).await;
|
||||||
|
|
||||||
|
assert!(res.is_err(), "non-UTF-8 flake.nix must fail the migration");
|
||||||
|
assert_eq!(std::fs::read(&flake).expect("read back"), bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue