diff --git a/src/bin/installer.rs b/src/bin/installer.rs index 19adcd3c7c..3e95be5418 100644 --- a/src/bin/installer.rs +++ b/src/bin/installer.rs @@ -114,6 +114,7 @@ fn main() { version: None, git: None, path: None, + pkg_path: None, } => false, _ => true, }) @@ -143,7 +144,8 @@ fn main() { }; if let Some(path) = parser.args.get(0) { - if let Err(err) = redox_installer::install(config, path, cookbook, parser.found("live")) + if let Err(err) = + redox_installer::install(config, path, cookbook.as_deref(), parser.found("live")) { writeln!(stderr, "installer: failed to install: {}", err).unwrap(); process::exit(1); diff --git a/src/config/package.rs b/src/config/package.rs index bbbfdc57ce..46c222c948 100644 --- a/src/config/package.rs +++ b/src/config/package.rs @@ -3,10 +3,13 @@ pub enum PackageConfig { Empty, Build(String), + + // TODO: Sum type Spec { version: Option, git: Option, path: Option, + pkg_path: Option, }, } diff --git a/src/lib.rs b/src/lib.rs index 4059746f41..03773eeb0c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -79,7 +79,7 @@ fn prompt_password(prompt: &str, confirm_prompt: &str) -> Result { } //TODO: error handling -fn install_packages>(config: &Config, dest: &str, cookbook: Option) { +fn install_packages(config: &Config, dest: &str, cookbook: Option<&str>) { let target = &get_target(); let mut repo = Repo::new(target); @@ -93,63 +93,99 @@ fn install_packages>(config: &Config, dest: &str, cookbook: Option for (packagename, package) in &config.packages { let pkgar_path = format!( - "{}/{}/repo/{}/{}.pkgar", - env::current_dir().unwrap().to_string_lossy(), - cookbook.as_ref(), - target, - packagename + "{cwd}/{cookbook}/repo/{target}/{packagename}.pkgar", + cwd = env::current_dir().unwrap().to_string_lossy(), ); - let from_remote = match (config.general.repo_binary, package) { - (Some(true), PackageConfig::Empty) => true, + + enum Rule<'a> { + RemotePrebuilt, + LocalPrebuilt { pkg_path: &'a str }, + Build, + } + + let rule = match (config.general.repo_binary, package) { ( Some(true), - PackageConfig::Spec { + PackageConfig::Empty + | PackageConfig::Spec { version: None, git: None, path: None, + pkg_path: None, }, - ) => true, - (_, PackageConfig::Build(rule)) if rule == "binary" => true, - _ => false, - }; - if from_remote { - println!("Installing package from remote: {}", packagename); - repo.fetch(&packagename).unwrap().install(dest).unwrap(); - } else if Path::new(&pkgar_path).exists() { - println!("Installing package from local repo: {}", packagename); - let public_path = format!( - "{}/{}/build/id_ed25519.pub.toml", - env::current_dir().unwrap().to_string_lossy(), - cookbook.as_ref() - ); - pkgar::extract(&public_path, &pkgar_path, dest).unwrap(); + ) => { + // prebuilt + Rule::RemotePrebuilt + } + (_, PackageConfig::Build(rule)) if rule == "binary" => Rule::RemotePrebuilt, + ( + _, + PackageConfig::Spec { + pkg_path: Some(pkg_path), + .. + }, + ) => Rule::LocalPrebuilt { + pkg_path: &*pkg_path, + }, - let head_path = format!("{}/{}.pkgar_head", dest_pkg, packagename); - pkgar::split(&public_path, &pkgar_path, &head_path, Option::<&str>::None).unwrap(); - } else { - println!("Installing package tar.gz from local repo: {}", packagename); - let path = format!( - "{}/{}/repo/{}/{}.tar.gz", - env::current_dir().unwrap().to_string_lossy(), - cookbook.as_ref(), - target, - packagename - ); - Package::from_path(&path).unwrap().install(dest).unwrap(); + _ => Rule::Build, + }; + + match rule { + Rule::LocalPrebuilt { pkg_path } => { + println!( + "Installing package from local pkgar file: {packagename} <- `{pkg_path}`" + ); + Package::from_path(pkg_path).unwrap().install(dest).unwrap(); + } + Rule::RemotePrebuilt => { + println!("Installing package from remote: {packagename}"); + repo.fetch(&packagename).unwrap().install(dest).unwrap(); + } + Rule::Build if Path::new(&pkgar_path).exists() => { + println!("Installing package from local repo: {}", packagename); + let public_path = format!( + "{cwd}/{cookbook}/build/id_ed25519.pub.toml", + cwd = env::current_dir().unwrap().to_string_lossy(), + ); + pkgar::extract(&public_path, &pkgar_path, dest).unwrap(); + + let head_path = format!("{dest_pkg}/{packagename}.pkgar_head"); + pkgar::split(&public_path, &pkgar_path, &head_path, Option::<&str>::None) + .unwrap(); + } + Rule::Build => { + println!("Installing package tar.gz from local repo: {packagename}"); + let path = format!( + "{cwd}/{cookbook}/repo/{target}/{packagename}.tar.gz", + cwd = env::current_dir().unwrap().to_string_lossy(), + ); + Package::from_path(&path).unwrap().install(dest).unwrap(); + } } } } else { - for (packagename, _package) in &config.packages { - println!("Installing package from remote: {}", packagename); - repo.fetch(&packagename).unwrap().install(dest).unwrap(); + for (packagename, package) in &config.packages { + let mut package = if let PackageConfig::Spec { + pkg_path: Some(override_path), + .. + } = package + { + println!("Installing package from local file: {}", packagename); + Package::from_path(override_path).unwrap() + } else { + println!("Installing package from remote: {}", packagename); + repo.fetch(&packagename).unwrap() + }; + package.install(dest).unwrap(); } } } -pub fn install_dir, S: AsRef>( +pub fn install_dir( config: Config, - output_dir: P, - cookbook: Option, + output_dir: impl AsRef, + cookbook: Option<&str>, ) -> Result<()> { //let mut context = liner::Context::new(); @@ -237,13 +273,13 @@ pub fn install_dir, S: AsRef>( username )?; - println!("Adding user {}:", username); - println!("\tPassword: {}", password); - println!("\tUID: {}", uid); - println!("\tGID: {}", gid); - println!("\tName: {}", name); - println!("\tHome: {}", home); - println!("\tShell: {}", shell); + println!("Adding user {username}:"); + println!("\tPassword: {password}"); + println!("\tUID: {uid}"); + println!("\tGID: {gid}"); + println!("\tName: {name}"); + println!("\tHome: {home}"); + println!("\tShell: {shell}"); FileConfig { path: home.clone(), @@ -312,11 +348,8 @@ XDG_VIDEOS_DIR="$HOME/Videos" let password = hash_password(&password)?; - passwd.push_str(&format!( - "{};{};{};{};{};{}\n", - username, uid, gid, name, home, shell - )); - shadow.push_str(&format!("{};{}\n", username, password)); + passwd.push_str(&format!("{username};{uid};{gid};{name};{home};{shell}\n",)); + shadow.push_str(&format!("{username};{password}\n")); groups.push((username.clone(), gid, vec![username])); } @@ -368,8 +401,8 @@ XDG_VIDEOS_DIR="$HOME/Videos" use std::fmt::Write; writeln!(groups_data, "{name};x;{gid};{}", members.join(",")).unwrap(); - println!("Adding group {}:", name); - println!("\tGID: {}", gid); + println!("Adding group {name}:"); + println!("\tGID: {gid}"); println!("\tMembers: {}", members.join(", ")); } @@ -452,9 +485,9 @@ where res } -pub fn fetch_bootloaders>( +pub fn fetch_bootloaders( config: &Config, - cookbook: Option, + cookbook: Option<&str>, live: bool, ) -> Result<(Vec, Vec)> { let bootloader_dir = format!("/tmp/redox_installer_bootloader_{}", process::id()); @@ -470,7 +503,7 @@ pub fn fetch_bootloaders>( bootloader_config .packages .insert("bootloader".to_string(), PackageConfig::default()); - install_packages(&bootloader_config, &bootloader_dir, cookbook.as_ref()); + install_packages(&bootloader_config, &bootloader_dir, cookbook); let boot_dir = Path::new(&bootloader_dir).join("boot"); let bios_path = boot_dir.join(if live { @@ -562,8 +595,9 @@ where disk_file.write_all(&disk_option.bootloader_bios)?; // Replace MBR tables with protective MBR + // TODO: div_ceil let mbr_blocks = ((disk_size + block_size - 1) / block_size) - 1; - eprintln!("Writing protective MBR with disk blocks {:#x}", mbr_blocks); + eprintln!("Writing protective MBR with disk blocks {mbr_blocks:#x}"); gpt::mbr::ProtectiveMBR::with_lb_size(mbr_blocks as u32) .update_conservative(&mut disk_file)?; @@ -618,7 +652,7 @@ where }, ); - eprintln!("Writing GPT tables: {:#?}", partitions); + eprintln!("Writing GPT tables: {partitions:#?}"); // Initialize GPT table gpt_disk.update_partitions(partitions)?; @@ -675,18 +709,13 @@ where with_redoxfs(disk_redoxfs, disk_option.password_opt, callback) } -pub fn install(config: Config, output: P, cookbook: Option, live: bool) -> Result<()> -where - P: AsRef, - S: AsRef, -{ - println!("Install {:#?} to {}", config, output.as_ref().display()); +fn install_inner(config: Config, output: &Path, cookbook: Option<&str>, live: bool) -> Result<()> { + println!("Install {config:#?} to {}", output.display()); - if output.as_ref().is_dir() { + if output.is_dir() { install_dir(config, output, cookbook) } else { - let (bootloader_bios, bootloader_efi) = - fetch_bootloaders(&config, cookbook.as_ref(), live)?; + let (bootloader_bios, bootloader_efi) = fetch_bootloaders(&config, cookbook, live)?; let disk_option = DiskOption { bootloader_bios: &bootloader_bios, bootloader_efi: &bootloader_efi, @@ -698,3 +727,11 @@ where }) } } +pub fn install( + config: Config, + output: impl AsRef, + cookbook: Option<&str>, + live: bool, +) -> Result<()> { + install_inner(config, output.as_ref(), cookbook, live) +}