Skip to content

Commit

Permalink
supports overriding package arch
Browse files Browse the repository at this point in the history
  • Loading branch information
mariotaku committed Sep 15, 2023
1 parent ec70c3e commit d69375e
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 13 deletions.
4 changes: 2 additions & 2 deletions ares-package/src/input/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use regex::Regex;

use crate::input::app::AppInfo;
use crate::input::service::ServiceInfo;
use crate::input::validation::{Validation, ValidationInfo};
use crate::input::validation::{PackageArch, Validation, ValidationInfo};
use crate::{PackageInfo, ParseFrom};

#[derive(Debug)]
Expand Down Expand Up @@ -90,7 +90,7 @@ impl DataInfo {
impl Validation for DataInfo {
fn validate(&self) -> Result<ValidationInfo> {
let app_validation = self.app.validate()?;
let mut archs = HashSet::<String>::new();
let mut archs = HashSet::<PackageArch>::new();
let mut size_sum = self.package_data.len() as u64;
if let Some(arch) = &app_validation.arch {
archs.insert(arch.clone());
Expand Down
47 changes: 40 additions & 7 deletions ares-package/src/input/validation.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,26 @@
use std::fs::File;
use std::io::{Error, ErrorKind, Result};
use std::path::Path;
use std::str::FromStr;

use elf::ElfStream;
use elf::endian::AnyEndian;
use elf::to_str::e_machine_to_string;
use elf::ElfStream;

use crate::input::app::AppInfo;
use crate::input::data::ComponentInfo;
use crate::input::dir_size;
use crate::input::service::ServiceInfo;

#[derive(Eq, Hash, PartialEq, Debug, Clone)]
pub enum PackageArch {
ARM,
X86(String),
ALL,
}

pub struct ValidationInfo {
pub arch: Option<String>,
pub arch: Option<PackageArch>,
pub size: u64,
}

Expand All @@ -23,7 +31,7 @@ pub trait Validation {
impl Validation for ComponentInfo<AppInfo> {
fn validate(&self) -> Result<ValidationInfo> {
let size = dir_size(&self.path, self.excludes.as_ref())?;
let mut arch: Option<String> = None;
let mut arch: Option<PackageArch> = None;
if self.info.r#type == "native" {
arch = infer_arch(self.path.join(&self.info.main))?;
}
Expand All @@ -34,7 +42,7 @@ impl Validation for ComponentInfo<AppInfo> {
impl Validation for ComponentInfo<ServiceInfo> {
fn validate(&self) -> Result<ValidationInfo> {
let size = dir_size(&self.path, self.excludes.as_ref())?;
let mut arch: Option<String> = None;
let mut arch: Option<PackageArch> = None;
if let (Some(engine), Some(executable)) = (&self.info.engine, &self.info.executable) {
if engine == "native" {
arch = infer_arch(self.path.join(executable))?;
Expand All @@ -44,12 +52,37 @@ impl Validation for ComponentInfo<ServiceInfo> {
}
}

fn infer_arch<P: AsRef<Path>>(path: P) -> Result<Option<String>> {
impl ToString for PackageArch {
fn to_string(&self) -> String {
match self {
PackageArch::ARM => String::from("arm"),
PackageArch::ALL => String::from("all"),
PackageArch::X86(s) => s.clone(),
}
}
}

impl FromStr for PackageArch {
type Err = String;

fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
match s {
"arm" => Ok(PackageArch::ARM),
"all" => Ok(PackageArch::ALL),
"i386" | "i486" | "i586" | "i686" | "x86" => Ok(PackageArch::X86(String::from(s))),
_ => Err(format!("Invalid architecture {s}")),
}
}
}



fn infer_arch<P: AsRef<Path>>(path: P) -> Result<Option<PackageArch>> {
let elf = ElfStream::<AnyEndian, _>::open_stream(File::open(path.as_ref())?)
.map_err(|e| Error::new(ErrorKind::InvalidData, format!("Bad binary: {e:?}")))?;
return match elf.ehdr.e_machine {
elf::abi::EM_ARM => Ok(Some(String::from("arm"))),
elf::abi::EM_386 => Ok(Some(String::from("x86"))),
elf::abi::EM_ARM => Ok(Some(PackageArch::ARM)),
elf::abi::EM_386 => Ok(Some(PackageArch::X86(String::from("x86")))),
e => Err(Error::new(
ErrorKind::InvalidData,
format!("Unsupported binary machine type {}", e_machine_to_string(e)),
Expand Down
28 changes: 24 additions & 4 deletions ares-package/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use clap::Parser;
use serde::Serialize;

use crate::input::data::DataInfo;
use crate::input::validation::Validation;
use crate::input::validation::{PackageArch, Validation};
use crate::packaging::control::{AppendControl, ControlInfo};
use crate::packaging::data::AppendData;
use crate::packaging::header::AppendHeader;
Expand All @@ -34,6 +34,13 @@ struct Cli {
help = "Exclude files, given as a PATTERN"
)]
app_exclude: Vec<String>,
#[arg(
short = 'A',
long,
value_name = "ARCH",
help = "Explicitly specify the architecture"
)]
force_arch: Option<PackageArch>,
#[arg(help = "App directory containing a valid appinfo.json file.")]
app_dir: PathBuf,
#[arg(help = "Directory containing a valid services.json file")]
Expand Down Expand Up @@ -64,11 +71,24 @@ fn main() {
let data = DataInfo::from_input(&app_dir, &cli.service_dir, &cli.app_exclude).unwrap();
let package_info = &data.package;
let validation = data.validate().unwrap();
let arch = validation.arch.unwrap_or_else(|| String::from("all"));
let arch = cli
.force_arch
.or_else(|| validation.arch.clone())
.unwrap_or_else(|| PackageArch::ALL);
if let Some(validation_arch) = &validation.arch {
if std::mem::discriminant(&arch) != std::mem::discriminant(validation_arch) {
eprintln!(
"Incompatible architecture: {} != {}",
arch.to_string(),
validation_arch.to_string()
);
return;
}
}

let path = outdir.join(format!(
"{}_{}_{}.ipk",
package_info.id, package_info.version, arch
package_info.id, package_info.version, arch.to_string()
));
println!("Packaging {}...", path.to_string_lossy());
let ipk_file = File::create(path).unwrap();
Expand All @@ -84,7 +104,7 @@ fn main() {
package: package_info.id.clone(),
version: package_info.version.clone(),
installed_size: validation.size,
architecture: arch,
architecture: arch.to_string(),
};
ar.append_control(&control, mtime).unwrap();
ar.append_data(&data, mtime).unwrap();
Expand Down

0 comments on commit d69375e

Please sign in to comment.