deb: download keyring in cache directory for mmdebstrap
also avoid sudo if we are root
This commit is contained in:
@@ -7,7 +7,7 @@ use crate::context;
|
||||
use crate::distro_info;
|
||||
use serde::Deserialize;
|
||||
use std::error::Error;
|
||||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Launchpad API response structure for PPA information
|
||||
@@ -16,21 +16,36 @@ struct LaunchpadPpaResponse {
|
||||
signing_key_fingerprint: String,
|
||||
}
|
||||
|
||||
/// Download a keyring into apt trusted.gpg.d directory, trusting that keyring
|
||||
pub async fn download_trust_keyring(
|
||||
/// Download a keyring to the application cache directory and return the path
|
||||
///
|
||||
/// This function downloads the keyring to a user-writable cache directory
|
||||
/// instead of the system apt keyring directory, allowing non-root usage.
|
||||
/// The returned path can be passed to mmdebstrap via --keyring.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `ctx` - Optional context to use
|
||||
/// * `series` - The distribution series (e.g., "noble", "sid")
|
||||
///
|
||||
/// # Returns
|
||||
/// The path to the downloaded keyring file
|
||||
pub async fn download_cache_keyring(
|
||||
ctx: Option<Arc<context::Context>>,
|
||||
series: &str,
|
||||
) -> Result<(), Box<dyn Error>> {
|
||||
) -> Result<PathBuf, Box<dyn Error>> {
|
||||
let ctx = ctx.unwrap_or_else(context::current);
|
||||
|
||||
// Obtain keyring URL from distro_info
|
||||
let keyring_url = distro_info::get_keyring_url(series).await?;
|
||||
log::debug!("Downloading keyring from: {}", keyring_url);
|
||||
|
||||
// Create trusted.gpg.d directory if it doesn't exist
|
||||
let trusted_gpg_d = "/etc/apt/trusted.gpg.d";
|
||||
if !ctx.exists(Path::new(trusted_gpg_d))? {
|
||||
ctx.command("mkdir").arg("-p").arg(trusted_gpg_d).status()?;
|
||||
// Get the application cache directory
|
||||
let proj_dirs = directories::ProjectDirs::from("com", "pkh", "pkh")
|
||||
.ok_or("Could not determine project directories")?;
|
||||
let cache_dir = proj_dirs.cache_dir();
|
||||
|
||||
// Create cache directory if it doesn't exist
|
||||
if !ctx.exists(cache_dir)? {
|
||||
ctx.command("mkdir").arg("-p").arg(cache_dir).status()?;
|
||||
}
|
||||
|
||||
// Extract the original filename from the keyring URL
|
||||
@@ -39,9 +54,9 @@ pub async fn download_trust_keyring(
|
||||
.next_back()
|
||||
.unwrap_or("pkh-{}.gpg")
|
||||
.replace("{}", series);
|
||||
let keyring_path = format!("{}/{}", trusted_gpg_d, filename);
|
||||
let keyring_path = cache_dir.join(&filename);
|
||||
|
||||
// Download the keyring directly to the final location using curl
|
||||
// Download the keyring using curl
|
||||
let mut curl_cmd = ctx.command("curl");
|
||||
curl_cmd
|
||||
.arg("-s")
|
||||
@@ -57,11 +72,11 @@ pub async fn download_trust_keyring(
|
||||
}
|
||||
|
||||
log::info!(
|
||||
"Successfully downloaded and installed keyring for {} to {}",
|
||||
"Successfully downloaded keyring for {} to {}",
|
||||
series,
|
||||
keyring_path
|
||||
keyring_path.display()
|
||||
);
|
||||
Ok(())
|
||||
Ok(keyring_path)
|
||||
}
|
||||
|
||||
/// Download and import a PPA key using Launchpad API
|
||||
|
||||
@@ -143,22 +143,17 @@ impl EphemeralContextGuard {
|
||||
.arg(lockfile_path.to_string_lossy().to_string())
|
||||
.status()?;
|
||||
|
||||
// Make sure we have the right apt keyrings to mmdebstrap the chroot
|
||||
// Check for root privileges before downloading keyring
|
||||
if crate::utils::root::is_root()? {
|
||||
crate::apt::keyring::download_trust_keyring(Some(ctx.clone()), series).await?;
|
||||
} else {
|
||||
log::info!(
|
||||
"Lacking root privileges. Please ensure that the keyrings for the target distribution are present on your system."
|
||||
);
|
||||
}
|
||||
// Download the keyring to the cache directory
|
||||
let keyring_path =
|
||||
crate::apt::keyring::download_cache_keyring(Some(ctx.clone()), series).await?;
|
||||
|
||||
// Use mmdebstrap to download the tarball to the cache directory
|
||||
let mut cmd = ctx.command("mmdebstrap");
|
||||
cmd.arg("--variant=buildd")
|
||||
.arg("--mode=unshare")
|
||||
.arg("--include=mount,curl,ca-certificates")
|
||||
.arg("--format=tar");
|
||||
.arg("--format=tar")
|
||||
.arg(format!("--keyring={}", keyring_path.display()));
|
||||
|
||||
// Add architecture if specified
|
||||
if let Some(a) = arch {
|
||||
@@ -238,10 +233,15 @@ impl EphemeralContextGuard {
|
||||
.arg(dev_zero_path.to_string_lossy().to_string())
|
||||
.status();
|
||||
|
||||
// Create new device nodes using fakeroot and mknod
|
||||
let status_null = ctx
|
||||
.command("sudo")
|
||||
.arg("mknod")
|
||||
// Check if we're running as root
|
||||
let is_root = crate::utils::root::is_root()?;
|
||||
|
||||
// Create new device nodes using mknod (with sudo if not root)
|
||||
let mut cmd_null = ctx.command(if is_root { "mknod" } else { "sudo" });
|
||||
if !is_root {
|
||||
cmd_null.arg("mknod");
|
||||
}
|
||||
let status_null = cmd_null
|
||||
.arg("-m")
|
||||
.arg("666")
|
||||
.arg(dev_null_path.to_string_lossy().to_string())
|
||||
@@ -250,9 +250,11 @@ impl EphemeralContextGuard {
|
||||
.arg("3")
|
||||
.status()?;
|
||||
|
||||
let status_zero = ctx
|
||||
.command("sudo")
|
||||
.arg("mknod")
|
||||
let mut cmd_zero = ctx.command(if is_root { "mknod" } else { "sudo" });
|
||||
if !is_root {
|
||||
cmd_zero.arg("mknod");
|
||||
}
|
||||
let status_zero = cmd_zero
|
||||
.arg("-m")
|
||||
.arg("666")
|
||||
.arg(dev_zero_path.to_string_lossy().to_string())
|
||||
@@ -288,12 +290,24 @@ impl Drop for EphemeralContextGuard {
|
||||
"Build succeeded, removing chroot directory: {}",
|
||||
self.chroot_path.display()
|
||||
);
|
||||
let result = context::current()
|
||||
|
||||
// Check if we're running as root to avoid unnecessary sudo
|
||||
let is_root = crate::utils::root::is_root().unwrap_or(false);
|
||||
|
||||
let result = if is_root {
|
||||
context::current()
|
||||
.command("rm")
|
||||
.arg("-rf")
|
||||
.arg(&self.chroot_path)
|
||||
.status()
|
||||
} else {
|
||||
context::current()
|
||||
.command("sudo")
|
||||
.arg("rm")
|
||||
.arg("-rf")
|
||||
.arg(&self.chroot_path)
|
||||
.status();
|
||||
.status()
|
||||
};
|
||||
|
||||
match result {
|
||||
Ok(status) => {
|
||||
|
||||
Reference in New Issue
Block a user