apt: round-trip sources in place instead of consolidating them into sources.list

Saving the modified source entries with save_legacy rewrote every entry
into /etc/apt/sources.list in legacy format, destroying deb-src entries
and signed-by/trusted options, duplicating every distro entry that came
from a deb822 file (which stayed in place), and hardcoding the Ubuntu
keyring on cross builds. Entries now remember the file and format they
were loaded from and are written back there; new entries (PPAs, ports)
go to a pkh-owned /etc/apt/sources.list.d/pkh-added.list, and a one-time
<path>.pkh-backup copy is made before overwriting an existing file.

Also fixes: 'Types: deb deb-src' stanzas are split instead of being
treated as binary-only, commented-out legacy entries are kept disabled
instead of deleted, debian.sources is actually read on Debian (the old
else-if never fired), and the double blank lines save_legacy emitted.
This commit is contained in:
2026-09-16 00:10:45 +02:00
parent ea70ddc10d
commit 685538e637
3 changed files with 564 additions and 151 deletions
+9 -32
View File
@@ -117,6 +117,7 @@ pub fn ensure_repositories(
}
let ports_entry = crate::apt::sources::SourceEntry {
enabled: true,
kind: crate::apt::sources::SourceKind::Deb,
components: vec![
"main".to_string(),
"restricted".to_string(),
@@ -125,43 +126,19 @@ pub fn ensure_repositories(
],
architectures: vec![arch.to_string()],
uri: "http://ports.ubuntu.com/ubuntu-ports".to_string(),
signed_by: None,
trusted: None,
suite: ports_suites,
// No origin: saved to the pkh-owned added-sources file
origin: None,
};
sources.push(ports_entry);
}
// Save the updated sources
// Try to save in DEB822 format first, fall back to legacy format
let deb822_path = "/etc/apt/sources.list.d/ubuntu.sources";
if ctx
.command("test")
.arg("-f")
.arg(deb822_path)
.status()?
.success()
{
// For DEB822 format, we need to reconstruct the file content
let mut content = String::new();
for source in &sources {
if !source.enabled {
continue;
}
content.push_str("Types: deb\n");
content.push_str(&format!("URIs: {}\n", source.uri));
content.push_str(&format!("Suites: {}\n", source.suite.join(" ")));
content.push_str(&format!("Components: {}\n", source.components.join(" ")));
content.push_str("Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg\n");
content.push_str(&format!(
"Architectures: {}\n",
source.architectures.join(" ")
));
content.push('\n');
}
ctx.write_file(std::path::Path::new(deb822_path), &content)?;
} else {
// Fall back to legacy format
crate::apt::sources::save_legacy(Some(ctx.clone()), sources, "/etc/apt/sources.list")?;
}
// Save the updated sources: each entry is written back to its origin
// file in its own format (keeping its own Signed-By and Enabled state),
// and the new ports entry goes to the pkh-owned added-sources file
crate::apt::sources::save(Some(ctx.clone()), sources)?;
Ok(())
}
+8 -1
View File
@@ -107,10 +107,15 @@ pub async fn build(
let new_source = crate::apt::sources::SourceEntry {
enabled: true,
kind: crate::apt::sources::SourceKind::Deb,
components: vec!["main".to_string()],
architectures: architectures.clone(),
signed_by: None,
trusted: None,
suite: suites,
uri: base_url,
// No origin: saved to the pkh-owned added-sources file
origin: None,
};
sources.push(new_source);
modified = true;
@@ -159,7 +164,9 @@ pub async fn build(
}
if modified {
apt::sources::save_legacy(Some(ctx.clone()), sources, "/etc/apt/sources.list")?;
// Each entry is written back to its origin file in its own format;
// new PPA entries go to the pkh-owned added-sources file
apt::sources::save(Some(ctx.clone()), sources)?;
// Download and import PPA keys for all added PPAs
for (user, ppa_name) in added_ppas {