sbuild options: unshare, build directory context: retrieve files
This commit is contained in:
@@ -18,6 +18,8 @@ pub trait CommandRunner {
|
|||||||
|
|
||||||
pub trait ContextDriver {
|
pub trait ContextDriver {
|
||||||
fn ensure_available(&self, src: &Path, dest_root: &str) -> io::Result<PathBuf>;
|
fn ensure_available(&self, src: &Path, dest_root: &str) -> io::Result<PathBuf>;
|
||||||
|
fn retrieve_path(&self, src: &Path, dest: &Path) -> io::Result<()>;
|
||||||
|
fn list_files(&self, path: &Path) -> io::Result<Vec<PathBuf>>;
|
||||||
fn create_runner(&self, program: String) -> Box<dyn CommandRunner>;
|
fn create_runner(&self, program: String) -> Box<dyn CommandRunner>;
|
||||||
fn prepare_work_dir(&self) -> io::Result<String>;
|
fn prepare_work_dir(&self) -> io::Result<String>;
|
||||||
}
|
}
|
||||||
@@ -60,6 +62,19 @@ impl Context {
|
|||||||
self.driver().prepare_work_dir()
|
self.driver().prepare_work_dir()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retrieve a file or directory from the context to the local filesystem.
|
||||||
|
///
|
||||||
|
/// The `src` path is on the context, `dest` is on the local machine.
|
||||||
|
/// If `src` is a directory, it is copied recursively.
|
||||||
|
pub fn retrieve_path(&self, src: &Path, dest: &Path) -> io::Result<()> {
|
||||||
|
self.driver().retrieve_path(src, dest)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// List files in a directory on the context.
|
||||||
|
pub fn list_files(&self, path: &Path) -> io::Result<Vec<PathBuf>> {
|
||||||
|
self.driver().list_files(path)
|
||||||
|
}
|
||||||
|
|
||||||
fn driver(&self) -> Box<dyn ContextDriver> {
|
fn driver(&self) -> Box<dyn ContextDriver> {
|
||||||
match self {
|
match self {
|
||||||
Context::Local => Box::new(LocalDriver),
|
Context::Local => Box::new(LocalDriver),
|
||||||
|
|||||||
@@ -21,7 +21,21 @@ impl ContextDriver for LocalDriver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn prepare_work_dir(&self) -> io::Result<String> {
|
fn prepare_work_dir(&self) -> io::Result<String> {
|
||||||
Ok(".".to_string())
|
// TODO: Fix that, we should not always use '..' as work directory locally
|
||||||
|
Ok("..".to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn retrieve_path(&self, _src: &Path, _dest: &Path) -> io::Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn list_files(&self, path: &Path) -> io::Result<Vec<PathBuf>> {
|
||||||
|
let mut entries = Vec::new();
|
||||||
|
for entry in std::fs::read_dir(path)? {
|
||||||
|
let entry = entry?;
|
||||||
|
entries.push(entry.path());
|
||||||
|
}
|
||||||
|
Ok(entries)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -77,6 +77,30 @@ impl ContextDriver for SshDriver {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn retrieve_path(&self, src: &Path, dest: &Path) -> io::Result<()> {
|
||||||
|
let sess = connect_ssh(&self.host, self.user.as_deref(), self.port)?;
|
||||||
|
let sftp = sess.sftp().map_err(io::Error::other)?;
|
||||||
|
|
||||||
|
debug!("Downloading remote {:?} to {:?}", src, dest);
|
||||||
|
Self::download_recursive(&sftp, src, dest)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn list_files(&self, path: &Path) -> io::Result<Vec<PathBuf>> {
|
||||||
|
let sess = connect_ssh(&self.host, self.user.as_deref(), self.port)?;
|
||||||
|
let sftp = sess.sftp().map_err(io::Error::other)?;
|
||||||
|
|
||||||
|
let mut files = Vec::new();
|
||||||
|
let entries = sftp.readdir(path).map_err(io::Error::other)?;
|
||||||
|
for (p, _) in entries {
|
||||||
|
let file_name = p.file_name().unwrap();
|
||||||
|
if file_name == "." || file_name == ".." {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
files.push(p);
|
||||||
|
}
|
||||||
|
Ok(files)
|
||||||
|
}
|
||||||
|
|
||||||
fn prepare_work_dir(&self) -> io::Result<String> {
|
fn prepare_work_dir(&self) -> io::Result<String> {
|
||||||
let sess = connect_ssh(&self.host, self.user.as_deref(), self.port)?;
|
let sess = connect_ssh(&self.host, self.user.as_deref(), self.port)?;
|
||||||
let mut channel = sess.channel_session().map_err(io::Error::other)?;
|
let mut channel = sess.channel_session().map_err(io::Error::other)?;
|
||||||
@@ -118,6 +142,30 @@ impl SshDriver {
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn download_recursive(sftp: &ssh2::Sftp, src: &Path, dest: &Path) -> io::Result<()> {
|
||||||
|
let stat = sftp
|
||||||
|
.stat(src)
|
||||||
|
.map_err(|e| io::Error::other(format!("Remote stat failed for {:?}: {}", src, e)))?;
|
||||||
|
|
||||||
|
if stat.is_dir() {
|
||||||
|
fs::create_dir_all(dest)?;
|
||||||
|
let entries = sftp.readdir(src).map_err(io::Error::other)?;
|
||||||
|
for (path, _) in entries {
|
||||||
|
let file_name = path.file_name().unwrap();
|
||||||
|
if file_name == "." || file_name == ".." {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let new_dest = dest.join(file_name);
|
||||||
|
Self::download_recursive(sftp, &path, &new_dest)?;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let mut remote_file = sftp.open(src).map_err(io::Error::other)?;
|
||||||
|
let mut local_file = fs::File::create(dest)?;
|
||||||
|
io::copy(&mut remote_file, &mut local_file)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SshRunner {
|
pub struct SshRunner {
|
||||||
|
|||||||
25
src/deb.rs
25
src/deb.rs
@@ -37,7 +37,24 @@ pub fn build_binary_package(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Run sbuild
|
// Run sbuild
|
||||||
run_sbuild(&ctx, &remote_dsc_path, arch, series)?;
|
run_sbuild(&ctx, &remote_dsc_path, arch, series, &build_root)?;
|
||||||
|
|
||||||
|
// Retrieve artifacts
|
||||||
|
// Always retrieve to the directory containing the .dsc file
|
||||||
|
let local_output_dir = dsc_path
|
||||||
|
.parent()
|
||||||
|
.ok_or("Could not determine parent directory of dsc file")?;
|
||||||
|
println!("Retrieving artifacts to {}...", local_output_dir.display());
|
||||||
|
|
||||||
|
// Only retrieve .deb files
|
||||||
|
let remote_files = ctx.list_files(Path::new(&build_root))?;
|
||||||
|
for remote_file in remote_files {
|
||||||
|
if remote_file.extension().is_some_and(|ext| ext == "deb") {
|
||||||
|
let file_name = remote_file.file_name().ok_or("Invalid remote filename")?;
|
||||||
|
let local_dest = local_output_dir.join(file_name);
|
||||||
|
ctx.retrieve_path(&remote_file, &local_dest)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -116,8 +133,11 @@ fn run_sbuild(
|
|||||||
dsc_path: &Path,
|
dsc_path: &Path,
|
||||||
arch: Option<&str>,
|
arch: Option<&str>,
|
||||||
series: Option<&str>,
|
series: Option<&str>,
|
||||||
|
output_dir: &str,
|
||||||
) -> Result<(), Box<dyn Error>> {
|
) -> Result<(), Box<dyn Error>> {
|
||||||
let mut cmd = ctx.command("sbuild");
|
let mut cmd = ctx.command("sbuild");
|
||||||
|
cmd.arg("--chroot-mode=unshare");
|
||||||
|
|
||||||
if let Some(a) = arch {
|
if let Some(a) = arch {
|
||||||
cmd.arg(format!("--arch={}", a));
|
cmd.arg(format!("--arch={}", a));
|
||||||
}
|
}
|
||||||
@@ -125,6 +145,9 @@ fn run_sbuild(
|
|||||||
cmd.arg(format!("--dist={}", s));
|
cmd.arg(format!("--dist={}", s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add output directory argument
|
||||||
|
cmd.arg(format!("--build-dir={}", output_dir));
|
||||||
|
|
||||||
let status = cmd.arg(dsc_path).status()?;
|
let status = cmd.arg(dsc_path).status()?;
|
||||||
|
|
||||||
if !status.success() {
|
if !status.success() {
|
||||||
|
|||||||
Reference in New Issue
Block a user