Files
depot/src/builder/bin.rs
T
SFG545 167467d169 feat: add support for renamed package updates and ABI-breaking flags
- Introduced `real_name` field in `InstalledPackageRecord` and `PackageInfo` to handle renamed packages.
- Added `abi_breaking` field to manage versioned shared libraries during renamed updates.
- Updated database schema to include `real_name` and `abi_breaking` columns.
- Enhanced package registration logic to support replacement of renamed packages while retaining specified files and directories.
- Modified various functions and tests to accommodate the new fields and ensure backward compatibility.
- Updated TOML serialization to include `real_name` and `abi_breaking` in package metadata.
2026-03-15 16:31:44 -05:00

129 lines
4.1 KiB
Rust

//! Binary package "build" system — used when package supplies a prebuilt binary installer
use crate::cross::CrossConfig;
use crate::package::PackageSpec;
use anyhow::{Context, Result};
use std::fs;
use std::os::unix::fs as unix_fs;
use std::path::Path;
use walkdir::WalkDir;
/// For binary packages we simply copy the extracted files into DESTDIR (preserving
/// directory structure). This is useful for .deb packages where extract step
/// already unpacked the data payload into the source directory.
pub fn build(
_spec: &PackageSpec,
src_dir: &Path,
destdir: &Path,
_cross: Option<&CrossConfig>,
_export_compiler_flags: bool,
) -> Result<()> {
crate::log_info!(
"Binary install: copying files from {} to {} (pkg type={})",
src_dir.display(),
destdir.display(),
_spec.build.flags.binary_type
);
fs::create_dir_all(destdir)
.with_context(|| format!("Failed to create destdir: {}", destdir.display()))?;
for entry in WalkDir::new(src_dir) {
let entry = entry?;
let rel = entry.path().strip_prefix(src_dir).unwrap();
let target = destdir.join(rel);
if entry.file_type().is_dir() {
fs::create_dir_all(&target)?;
} else if entry.file_type().is_symlink() {
let link_target = fs::read_link(entry.path())?;
if let Some(parent) = target.parent() {
fs::create_dir_all(parent)?;
}
// overwrite existing links/files
if target.exists() {
let _ = fs::remove_file(&target);
}
unix_fs::symlink(link_target, &target)?;
} else {
if let Some(parent) = target.parent() {
fs::create_dir_all(parent)?;
}
fs::copy(entry.path(), &target)?;
}
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use crate::package::{Build, BuildFlags, BuildType, Dependencies, PackageInfo};
use std::fs;
use std::os::unix::fs as unix_fs;
use tempfile::tempdir;
fn mk_spec(name: &str, version: &str) -> PackageSpec {
PackageSpec {
package: PackageInfo {
name: name.into(),
real_name: None,
version: version.into(),
revision: 1,
description: "d".into(),
homepage: "h".into(),
abi_breaking: false,
license: vec!["MIT".into()],
},
packages: Vec::new(),
alternatives: Default::default(),
manual_sources: Vec::new(),
source: vec![crate::package::Source {
url: "h".into(),
sha256: "s".into(),
extract_dir: "e".into(),
patches: Vec::new(),
post_extract: Vec::new(),
cherry_pick: Vec::new(),
}],
build: Build {
build_type: BuildType::Bin,
flags: BuildFlags::default(),
},
dependencies: Dependencies::default(),
package_alternatives: Default::default(),
package_dependencies: Default::default(),
spec_dir: std::path::PathBuf::from("."),
}
}
#[test]
fn test_bin_build_copies_files_and_symlinks() -> Result<()> {
let tmp_src = tempdir()?;
let tmp_dest = tempdir()?;
let src = tmp_src.path();
let dest = tmp_dest.path();
// Create a directory and files
fs::create_dir_all(src.join("usr/bin"))?;
fs::write(src.join("usr/bin/hello"), b"hi")?;
// Create a symlink
let target = src.join("usr/lib/libdummy.so");
fs::create_dir_all(target.parent().unwrap())?;
fs::write(&target, b"lib")?;
unix_fs::symlink(&target, src.join("usr/lib/libdummy.so.link"))?;
let spec = mk_spec("bin-test", "1.0");
build(&spec, src, dest, None, true)?;
// Check copied file
assert!(dest.join("usr/bin/hello").exists());
// Check symlink target exists at dest
let link_path = dest.join("usr/lib/libdummy.so.link");
assert!(link_path.exists());
Ok(())
}
}