Add support for installing AUR packages (#48)

This commit is contained in:
James McMurray 2020-05-10 18:31:40 +02:00 committed by GitHub
parent bc9969a0db
commit c8b151fe5f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 143 additions and 1 deletions

2
presets/aur_example.toml Normal file
View File

@ -0,0 +1,2 @@
packages = ["clang"]
aur_packages = ["bat-cat-git"]

View File

@ -1,3 +1,4 @@
use super::aur::AurHelper;
use byte_unit::Byte;
use std::path::PathBuf;
use structopt::StructOpt;
@ -41,6 +42,10 @@ pub struct CreateCommand {
#[structopt(short = "p", long = "extra-packages", value_name = "package")]
pub extra_packages: Vec<String>,
/// Additional packages to install
#[structopt(long = "aur-packages", value_name = "aurpackage")]
pub aur_packages: Vec<String>,
/// Enter interactive chroot before unmounting the drive
#[structopt(short = "i", long = "interactive")]
pub interactive: bool,
@ -72,6 +77,9 @@ pub struct CreateCommand {
/// show non-removable devices
#[structopt(long = "allow-non-removable")]
pub allow_non_removable: bool,
#[structopt(long = "aur-helper", possible_values=&["yay"], default_value="yay")]
pub aur_helper: AurHelper,
}
#[derive(StructOpt)]

38
src/aur.rs Normal file
View File

@ -0,0 +1,38 @@
use crate::error::ErrorKind;
use std::str::FromStr;
pub struct AurHelper {
pub name: String,
pub install_command: Vec<String>,
}
impl FromStr for AurHelper {
type Err = ErrorKind;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"yay" => Ok(AurHelper {
name: String::from("yay"),
install_command: vec![
String::from("yay"),
String::from("-S"),
String::from("--nocleanmenu"),
String::from("--nodiffmenu"),
String::from("--noeditmenu"),
String::from("--noupgrademenu"),
String::from("--useask"),
String::from("--removemake"),
String::from("--norebuild"),
String::from("--noconfirm"),
String::from("--answeredit"),
String::from("None"),
String::from("--answerclean"),
String::from("None"),
String::from("--mflags"),
String::from("--noconfirm"),
],
}),
_ => Err(ErrorKind::AurHelper {}),
}
}
}

View File

@ -17,3 +17,5 @@ pub const BASE_PACKAGES: [&str; 8] = [
"networkmanager",
"broadcom-wl",
];
pub const AUR_DEPENDENCIES: [&str; 3] = ["base-devel", "git", "sudo"];

View File

@ -86,6 +86,9 @@ pub enum ErrorKind {
#[fail(display = "Error executing preset script")]
PresetScript,
#[fail(display = "Error parsing AUR helper string")]
AurHelper,
#[fail(display = "Error creating the image")]
Image,

View File

@ -1,4 +1,5 @@
mod args;
mod aur;
mod constants;
mod error;
mod initcpio;
@ -240,6 +241,10 @@ fn create(command: args::CreateCommand) -> Result<(), Error> {
packages.extend(presets.packages);
if presets.aur_packages.len() > 0 {
packages.extend(constants::AUR_DEPENDENCIES.iter().map(|s| String::from(*s)));
}
info!("Bootstrapping system");
pacstrap
.execute()
@ -258,7 +263,77 @@ fn create(command: args::CreateCommand) -> Result<(), Error> {
);
debug!("fstab:\n{}", fstab);
fs::write(mount_point.path().join("etc/fstab"), fstab).context(ErrorKind::Fstab)?;
if presets.aur_packages.len() > 0 {
arch_chroot
.execute()
.arg(mount_point.path())
.args(&["useradd", "-m", "aur"])
.run(ErrorKind::PostInstallation)?;
arch_chroot
.execute()
.arg(mount_point.path())
.args(&[
"sed",
"-i",
"s/# %wheel ALL=(ALL) NOPASSWD: ALL/aur ALL=(ALL) NOPASSWD: ALL/g",
])
.arg("/etc/sudoers")
.run(ErrorKind::PostInstallation)?;
arch_chroot
.execute()
.arg(mount_point.path())
.args(&["sudo", "-u", "aur"])
.arg("git")
.arg("clone")
.arg(format!(
"https://aur.archlinux.org/{}.git",
&command.aur_helper.name
))
.arg(format!("/home/aur/{}", &command.aur_helper.name))
.run(ErrorKind::PostInstallation)?;
arch_chroot
.execute()
.arg(mount_point.path())
.args(&[
"bash",
"-c",
&format!(
"cd /home/aur/{} && sudo -u aur makepkg -s -i --noconfirm",
&command.aur_helper.name
),
])
.run(ErrorKind::PostInstallation)?;
arch_chroot
.execute()
.arg(mount_point.path())
.args(&["sudo", "-u", "aur"])
.args(&command.aur_helper.install_command)
.args(presets.aur_packages)
.args(&command.aur_packages)
.run(ErrorKind::PostInstallation)?;
// Clean up aur user:
arch_chroot
.execute()
.arg(mount_point.path())
.args(&["userdel", "-r", "aur"])
.run(ErrorKind::PostInstallation)?;
arch_chroot
.execute()
.arg(mount_point.path())
.args(&[
"sed",
"-i",
"s/aur ALL=(ALL) NOPASSWD: ALL/# %wheel ALL=(ALL) NOPASSWD: ALL/g",
])
.arg("/etc/sudoers")
.run(ErrorKind::PostInstallation)?;
}
if !presets.scripts.is_empty() {
info!("Running custom scripts");
}

View File

@ -13,6 +13,7 @@ struct Preset {
script: Option<String>,
environment_variables: Option<Vec<String>>,
shared_directories: Option<Vec<PathBuf>>,
aur_packages: Option<Vec<String>>,
}
fn visit_dirs(dir: &Path, filevec: &mut Vec<PathBuf>) -> Result<(), io::Error> {
@ -46,11 +47,16 @@ impl Preset {
scripts: &mut Vec<Script>,
environment_variables: &mut HashSet<String>,
path: &PathBuf,
aur_packages: &mut HashSet<String>,
) -> Result<(), ErrorKind> {
if let Some(preset_packages) = &self.packages {
packages.extend(preset_packages.clone());
}
if let Some(preset_aur_packages) = &self.aur_packages {
aur_packages.extend(preset_aur_packages.clone());
}
if let Some(preset_environment_variables) = &self.environment_variables {
environment_variables.extend(preset_environment_variables.clone());
}
@ -94,12 +100,14 @@ pub struct Script {
pub struct PresetsCollection {
pub packages: HashSet<String>,
pub aur_packages: HashSet<String>,
pub scripts: Vec<Script>,
}
impl PresetsCollection {
pub fn load(list: &[PathBuf]) -> Result<Self, Error> {
let mut packages = HashSet::new();
let mut aur_packages = HashSet::new();
let mut scripts: Vec<Script> = Vec::new();
let mut environment_variables = HashSet::new();
@ -121,6 +129,7 @@ impl PresetsCollection {
&mut scripts,
&mut environment_variables,
&path,
&mut aur_packages,
)?;
}
} else {
@ -129,6 +138,7 @@ impl PresetsCollection {
&mut scripts,
&mut environment_variables,
&preset,
&mut aur_packages,
)?;
}
}
@ -141,6 +151,10 @@ impl PresetsCollection {
return Err(ErrorKind::MissingEnvironmentVariables(missing_envrionments).into());
}
Ok(Self { packages, scripts })
Ok(Self {
packages,
scripts,
aur_packages,
})
}
}