pkh context allows to manage contexts (local, ssh) and run contextualized commands (deb) in other words, this allows building binary packages over ssh
This commit is contained in:
115
src/deb.rs
115
src/deb.rs
@@ -1,6 +1,6 @@
|
||||
use crate::context::{Context, current_context};
|
||||
use std::error::Error;
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
pub fn build_binary_package(
|
||||
arch: Option<&str>,
|
||||
@@ -13,29 +13,122 @@ pub fn build_binary_package(
|
||||
let changelog_path = cwd.join("debian/changelog");
|
||||
let (package, version, _series) = crate::changelog::parse_changelog_header(&changelog_path)?;
|
||||
|
||||
// Construct dsc file name
|
||||
// Find .dsc file
|
||||
let dsc_path = find_dsc_file(cwd, &package, &version)?;
|
||||
println!("Building {} using sbuild...", dsc_path.display());
|
||||
|
||||
// Identify all related files from .dsc
|
||||
let mut files_to_ensure = get_dsc_related_files(&dsc_path)?;
|
||||
// Ensure dsc itself is included (usually first)
|
||||
if !files_to_ensure.contains(&dsc_path) {
|
||||
files_to_ensure.insert(0, dsc_path.clone());
|
||||
}
|
||||
|
||||
// Prepare Environment
|
||||
let ctx = current_context();
|
||||
let build_root = ctx.prepare_work_dir()?;
|
||||
|
||||
// Ensure availability of all needed files for the build
|
||||
let remote_dsc_path = upload_package_files(&ctx, &files_to_ensure, &build_root, &dsc_path)?;
|
||||
println!(
|
||||
"Building {} on {}...",
|
||||
remote_dsc_path.display(),
|
||||
build_root
|
||||
);
|
||||
|
||||
// Run sbuild
|
||||
run_sbuild(&ctx, &remote_dsc_path, arch, series)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn find_dsc_file(cwd: &Path, package: &str, version: &str) -> Result<PathBuf, Box<dyn Error>> {
|
||||
let parent = cwd.parent().ok_or("Cannot find parent directory")?;
|
||||
let dsc_name = format!("{}_{}.dsc", package, version);
|
||||
let dsc_path = parent.join(&dsc_name);
|
||||
|
||||
if !dsc_path.exists() {
|
||||
return Err(format!("Could not find .dsc file at {}", dsc_path.display()).into());
|
||||
}
|
||||
Ok(dsc_path)
|
||||
}
|
||||
|
||||
println!("Building {} using sbuild...", dsc_path.display());
|
||||
fn get_dsc_related_files(dsc_path: &Path) -> Result<Vec<PathBuf>, Box<dyn Error>> {
|
||||
let content = std::fs::read_to_string(dsc_path)?;
|
||||
let parent = dsc_path.parent().unwrap(); // dsc_path exists so parent exists
|
||||
let mut files = Vec::new();
|
||||
|
||||
let mut status = Command::new("sbuild");
|
||||
if let Some(arch) = arch {
|
||||
status.arg(format!("--arch={}", arch));
|
||||
let mut in_files = false;
|
||||
for line in content.lines() {
|
||||
if line.starts_with("Files:") {
|
||||
in_files = true;
|
||||
continue;
|
||||
}
|
||||
if in_files {
|
||||
if line.starts_with(' ') {
|
||||
let parts: Vec<&str> = line.split_whitespace().collect();
|
||||
if parts.len() >= 3 {
|
||||
let filename = parts[2];
|
||||
let filepath = parent.join(filename);
|
||||
if filepath.exists() {
|
||||
files.push(filepath);
|
||||
} else {
|
||||
return Err(
|
||||
format!("Referenced file {} not found", filepath.display()).into()
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
in_files = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(series) = series {
|
||||
status.arg(format!("--dist={}", series));
|
||||
Ok(files)
|
||||
}
|
||||
|
||||
fn upload_package_files(
|
||||
ctx: &Context,
|
||||
files: &[PathBuf],
|
||||
dest_root: &str,
|
||||
local_dsc_path: &Path,
|
||||
) -> Result<PathBuf, Box<dyn Error>> {
|
||||
let mut remote_dsc_path = PathBuf::new();
|
||||
|
||||
for file in files {
|
||||
let remote_path = ctx.ensure_available(file, dest_root)?;
|
||||
// Check if this is the dsc file by comparing file names
|
||||
if let (Some(f_name), Some(dsc_name)) = (file.file_name(), local_dsc_path.file_name())
|
||||
&& f_name == dsc_name
|
||||
{
|
||||
remote_dsc_path = remote_path;
|
||||
}
|
||||
}
|
||||
|
||||
let status = status.arg(dsc_path).status()?;
|
||||
if remote_dsc_path.as_os_str().is_empty() {
|
||||
return Err("Failed to determine remote path for .dsc file".into());
|
||||
}
|
||||
|
||||
Ok(remote_dsc_path)
|
||||
}
|
||||
|
||||
fn run_sbuild(
|
||||
ctx: &Context,
|
||||
dsc_path: &Path,
|
||||
arch: Option<&str>,
|
||||
series: Option<&str>,
|
||||
) -> Result<(), Box<dyn Error>> {
|
||||
let mut cmd = ctx.command("sbuild");
|
||||
if let Some(a) = arch {
|
||||
cmd.arg(format!("--arch={}", a));
|
||||
}
|
||||
if let Some(s) = series {
|
||||
cmd.arg(format!("--dist={}", s));
|
||||
}
|
||||
|
||||
let status = cmd.arg(dsc_path).status()?;
|
||||
|
||||
if !status.success() {
|
||||
return Err(format!("sbuild failed with status: {}", status).into());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user