Updated creation code with new --dep parameter.

- New --dep parameter to be used in place of --target to specify
container dependencies to configure a container on creation, allowing
for multiple containers to be created in one invocation.
- Bug fix applied to creation of base containers
- pacwrap-utils updated to be compatible with the proceeding changes.
This commit is contained in:
Xavier Moffett 2023-11-29 13:23:52 -05:00
parent 728185d960
commit 8b588c4ee8
3 changed files with 89 additions and 80 deletions

View file

@ -334,14 +334,10 @@ invoke_replication() {
for dep in ${deps[@]}; do replicate_instance $dep; done for dep in ${deps[@]}; do replicate_instance $dep; done
for depr in $deps_return; do
[[ ! -d "$INSTANCE_ROOT_DIR/$depr" ]] &&
log_error "Dependency $depr not fulfilled for $instance." 1
done
replicate_instance $instance replicate_instance $instance
done done
$CREATE_SCRIPT -Syu --create $REPLICATE_CMD --noconfirm
} }
replicate_instance() { replicate_instance() {
@ -353,7 +349,7 @@ replicate_instance() {
local depend= local depend=
local type=$(return_type) local type=$(return_type)
local params="c" local params="-"
[[ $SWITCH == *v* ]] && params+="v" [[ $SWITCH == *v* ]] && params+="v"
[[ $type != BASE ]] && depend=$(return_dependency) [[ $type != BASE ]] && depend=$(return_dependency)
@ -361,7 +357,7 @@ replicate_instance() {
case $type in case $type in
ROOT) params+="r";; ROOT) params+="r";;
BASE) params+="b";; BASE) params+="b";;
DEP) params+="d";; DEP) params+="s";;
LINK) ln -s "$INSTANCE_ROOT_DIR/$depend" "$INSTANCE_ROOT_DIR/$instance" LINK) ln -s "$INSTANCE_ROOT_DIR/$depend" "$INSTANCE_ROOT_DIR/$instance"
mkdir -p "$INSTANCE_HOME_DIR/$instance" mkdir -p "$INSTANCE_HOME_DIR/$instance"
echo 'PS1="'$instance'> "' > "$INSTANCE_HOME_DIR/$instance/.bashrc" echo 'PS1="'$instance'> "' > "$INSTANCE_HOME_DIR/$instance/.bashrc"
@ -375,16 +371,10 @@ replicate_instance() {
local depend_params local depend_params
for dep in $(return_dependencies); do for dep in $(return_dependencies); do
depend_params+="-t $dep " depend_params+="--dep=$dep "
done done
$CREATE_SCRIPT -Syu$params -t $instance $(return_packages) $foreign_targets $depend_params --noconfirm REPLICATE_CMD+="$params -t $instance $(return_packages) $foreign_targets $depend_params "
if [[ $? == 0 ]]; then
printf " %s$RESET\n" "Replication of $BOLD$instance$RESET complete!"
log_to_file "Replication of $instance complete!"
fi
completed[$instance]=1 completed[$instance]=1
} }

View file

@ -105,7 +105,7 @@ fn ascertain_help<'a>(args: &mut Arguments) -> Result<(IndexSet<&'a HelpTopic>,
=> topic.extend(HELP_ALL.iter()), => topic.extend(HELP_ALL.iter()),
Operand::ShortPos('h', topic) Operand::ShortPos('h', topic)
| Operand::LongPos("help", topic) | Operand::LongPos("help", topic)
=> Err(ErrorKind::TopicUnavailable(topic.to_string()))?, => Err(ErrorKind::Message(format!("Topic '{topic}' is not available.").leak()))?,
_ => Err(args.invalid_operand())?, _ => Err(args.invalid_operand())?,
} }
} }
@ -323,7 +323,7 @@ fn sync(buf: &mut String, layout: &HelpLayout) -> Result<(), std::fmt::Error> {
{sub}-u, --upgrade{reset_bold} {sub}-u, --upgrade{reset_bold}
{tab}{tab}Execute aggregate upgrade routine on all or specified containers. Use {bold}-t, --target=TARGET{reset_bold} to limit {tab}{tab}Execute aggregate upgrade routine on all or specified containers. Use {bold}-t, --target=TARGET{reset_bold} to limit
{tab}{tab}package synhronization operations to the specified target containers. Packages applicable to {tab}{tab}package synchronization operations to the specified target containers. Packages applicable to
{tab}{tab}a target {bold}must{reset_bold} be specified only after the target operand. {tab}{tab}a target {bold}must{reset_bold} be specified only after the target operand.
{tab}{tab}e.g. '-t electron element-desktop -t mozilla firefox thunderbird' {tab}{tab}e.g. '-t electron element-desktop -t mozilla firefox thunderbird'
@ -341,9 +341,9 @@ fn sync(buf: &mut String, layout: &HelpLayout) -> Result<(), std::fmt::Error> {
{tab}{tab}dependency per slice or per root is supported. Filesystem and package deduplication via slices {tab}{tab}dependency per slice or per root is supported. Filesystem and package deduplication via slices
{tab}{tab}and root containers is recommended, but optional. {tab}{tab}and root containers is recommended, but optional.
{sub}-d, --slice{reset_bold} {sub}-s, --slice{reset_bold}
{tab}{tab}Slice container type. Specify alongside {bold}-c, --create{reset_bold} to assign this container type during creation. {tab}{tab}Slice container type. Specify alongside {bold}-c, --create{reset_bold} to assign this container type during creation.
{tab}{tab}Requires a base dependency target, and optionally sliced dependency target(s), in order to ascertain {tab}{tab}Requires a base dependency be specified, and one or more sliced dependencies, in order to ascertain
{tab}{tab}foreign packages and influence ordering of downstream synchronization target(s). Container slicing {tab}{tab}foreign packages and influence ordering of downstream synchronization target(s). Container slicing
{tab}{tab}provides the ability to install packages in a lightweight, sliced filesytem, which aid in the {tab}{tab}provides the ability to install packages in a lightweight, sliced filesytem, which aid in the
{tab}{tab}deduplication of common downstream package and filesystem dependencies e.g. graphics drivers, {tab}{tab}deduplication of common downstream package and filesystem dependencies e.g. graphics drivers,
@ -351,13 +351,16 @@ fn sync(buf: &mut String, layout: &HelpLayout) -> Result<(), std::fmt::Error> {
{sub}-r, --root{reset_bold} {sub}-r, --root{reset_bold}
{tab}{tab}Root container type. Specify alongside {bold}-c, --create{reset_bold} to this assign container type during creation. {tab}{tab}Root container type. Specify alongside {bold}-c, --create{reset_bold} to this assign container type during creation.
{tab}{tab}Requires a base dependency target, and optionally sliced dependency targets, in order to ascertain {tab}{tab}Requires a base dependency be specified, and optionally one or more sliced dependencies, in order
{tab}{tab}foreign packages and influence ordering of this target. These containers are ideal for installing {tab}{tab}to ascertain foreign packages and influence ordering of this target. These containers are ideal
{tab}{tab}software in with the least amount of filesystem and package synchronization overhead. {tab}{tab}for installing software in with the least amount of filesystem and package synchronization overhead.
{sub}-t, --target=TARGET{reset_bold} {sub}-t, --target=TARGET{reset_bold}
{tab}{tab}Specify a target container for the specified operation. {tab}{tab}Specify a target container for the specified operation.
{sub}-d, --dep=DEPEND{reset_bold}
{tab}{tab}Specify a dependency container for the specified operation.
{sub}-o, --target-only{reset_bold} {sub}-o, --target-only{reset_bold}
{tab}{tab}Apply specified operation on the specified target only. {tab}{tab}Apply specified operation on the specified target only.

View file

@ -1,14 +1,13 @@
use std::{collections::HashMap, fs::File}; use std::{collections::HashMap, fs::File};
use std::io::Write; use std::io::Write;
use std::process::exit;
use indexmap::IndexMap;
use pacwrap_core::{ErrorKind, use pacwrap_core::{ErrorKind,
log::Logger, log::Logger,
sync::transaction::TransactionType, sync::transaction::TransactionType,
utils::{arguments::{Arguments, utils::arguments::{Arguments,
InvalidArgument, InvalidArgument,
Operand}, Operand},
print_error},
config::{self, config::{self,
InstanceType, InstanceType,
InsVars, InsVars,
@ -37,7 +36,7 @@ pub fn synchronize(mut args: &mut Arguments) -> Result<(), ErrorKind> {
config::init::init(); config::init::init();
if let Some(instype) = create(&mut args)? { if create(&mut args) {
if let TransactionType::Upgrade(upgrade, refresh, _) = action { if let TransactionType::Upgrade(upgrade, refresh, _) = action {
if ! refresh { if ! refresh {
Err(ErrorKind::Argument(InvalidArgument::UnsuppliedOperand("--refresh", "Required for container creation.")))? Err(ErrorKind::Argument(InvalidArgument::UnsuppliedOperand("--refresh", "Required for container creation.")))?
@ -46,64 +45,84 @@ pub fn synchronize(mut args: &mut Arguments) -> Result<(), ErrorKind> {
} }
} }
instantiate(instype, args.targets())? instantiate(acquire_depends(args)?)?
} }
engage_aggregator(action, &mut args, &mut logger) engage_aggregator(action, &mut args, &mut logger)
} }
fn create<'a>(args: &mut Arguments) -> Result<Option<InstanceType>, ErrorKind> { fn acquire_depends<'a>(args: &'a mut Arguments) -> Result<IndexMap<&'a str, (InstanceType, Vec<&'a str>)>, ErrorKind> {
let mut deps: IndexMap<&'a str, (InstanceType, Vec<&'a str>)> = IndexMap::new();
let mut current_target = "";
let mut instype = None; let mut instype = None;
let mut create = false;
args.set_index(1); args.set_index(1);
while let Some(arg) = args.next() { while let Some(arg) = args.next() {
match arg { match arg {
Operand::Short('c') | Operand::Long("create") => create = true, Operand::ShortPos('d', dep)
Operand::Short('b') | Operand::Long("base") => match instype { | Operand::LongPos("dep", dep) => match deps.get_mut(current_target) {
None => instype = Some(InstanceType::BASE), Some(d) => {
Some(_) => Err(ErrorKind::DuplicateType)?, if let Some(instype) = instype {
if let InstanceType::BASE = instype {
Err(ErrorKind::Message("Dependencies cannot be assigned to base containers."))?
}
}
d.1.push(dep);
}, },
Operand::Short('d') | Operand::Long("slice") => match instype { None => Err(ErrorKind::Argument(InvalidArgument::TargetUnspecified))?
None => instype = Some(InstanceType::DEP),
Some(_) => Err(ErrorKind::DuplicateType)?,
}, },
Operand::Short('r') | Operand::Long("root") => match instype { Operand::Short('b')
None => instype = Some(InstanceType::ROOT), | Operand::Long("base") => instype = Some(InstanceType::BASE),
Some(_) => Err(ErrorKind::DuplicateType)?, Operand::Short('s')
| Operand::Long("slice") => instype = Some(InstanceType::DEP),
Operand::Short('r')
| Operand::Long("root") => instype = Some(InstanceType::ROOT),
Operand::ShortPos('t', target)
| Operand::LongPos("target", target) => match instype {
Some(instype) => {
current_target = target;
deps.insert(current_target, (instype, vec!()));
},
None => Err(ErrorKind::Message("Container type not specified."))?,
}, },
_ => continue, _ => continue,
} }
} }
match create { if current_target.len() == 0 {
true => match instype {
None => Err(ErrorKind::Message("Container type unspecified."))?, Some(_) => Ok(instype),
},
false => Ok(None)
}
}
fn instantiate(instype: InstanceType, mut targets: Vec<&str>) -> Result<(), ErrorKind> {
if targets.len() == 0 {
Err(ErrorKind::Argument(InvalidArgument::TargetUnspecified))? Err(ErrorKind::Argument(InvalidArgument::TargetUnspecified))?
} }
let target = targets.remove(0); Ok(deps)
}
if let InstanceType::ROOT | InstanceType::DEP = instype {
if target.len() == 0 { fn create(args: &mut Arguments) -> bool {
Err(ErrorKind::Message("Dependencies not specified."))? args.set_index(1);
while let Some(arg) = args.next() {
match arg {
Operand::Short('c') | Operand::Long("create") => return true,
_ => continue,
} }
} }
instantiate_container(target, targets, instype) false
} }
fn instantiate_container(ins: &str, deps: Vec<&str>, instype: InstanceType) -> Result<(), ErrorKind> { fn instantiate<'a>(targets: IndexMap<&'a str, (InstanceType, Vec<&'a str>)>) -> Result<(), ErrorKind> {
println!("{} {}Instantiating container {ins}{}", *BAR_GREEN, *BOLD, *RESET); println!("{} {}Instantiating container{}{}", *BAR_GREEN, *BOLD, if targets.len() > 1 { "s" } else { "" }, *RESET);
for target in targets {
instantiate_container(target.0, target.1.0, target.1.1)?;
}
Ok(())
}
fn instantiate_container(ins: &str, instype: InstanceType, deps: Vec<&str>) -> Result<(), ErrorKind> {
let deps = deps.iter().map(|a| { let a = *a; a.into() }).collect(); let deps = deps.iter().map(|a| { let a = *a; a.into() }).collect();
let mut logger = Logger::new("pacwrap").init().unwrap(); let mut logger = Logger::new("pacwrap").init().unwrap();
let instance = match config::provide_new_handle(ins) { let instance = match config::provide_new_handle(ins) {
@ -120,7 +139,7 @@ fn instantiate_container(ins: &str, deps: Vec<&str>, instype: InstanceType) -> R
if let Err(err) = std::fs::create_dir(instance.vars().root()) { if let Err(err) = std::fs::create_dir(instance.vars().root()) {
if let std::io::ErrorKind::AlreadyExists = err.kind() { if let std::io::ErrorKind::AlreadyExists = err.kind() {
Err(ErrorKind::Message("Container root already exists."))? Err(ErrorKind::Message(format!("Container {ins} already exists.").leak()))?
} else { } else {
Err(ErrorKind::IOError(instance.vars().root().into(), err.kind()))? Err(ErrorKind::IOError(instance.vars().root().into(), err.kind()))?
} }
@ -129,8 +148,7 @@ fn instantiate_container(ins: &str, deps: Vec<&str>, instype: InstanceType) -> R
if let InstanceType::ROOT | InstanceType::BASE = instype { if let InstanceType::ROOT | InstanceType::BASE = instype {
if let Err(err) = std::fs::create_dir(instance.vars().home()) { if let Err(err) = std::fs::create_dir(instance.vars().home()) {
if err.kind() != std::io::ErrorKind::AlreadyExists { if err.kind() != std::io::ErrorKind::AlreadyExists {
print_error(format!("'{}': {}", instance.vars().root(), err)); Err(ErrorKind::IOError(instance.vars().root().into(), err.kind()))?
exit(1);
} }
} }
@ -147,7 +165,7 @@ fn instantiate_container(ins: &str, deps: Vec<&str>, instype: InstanceType) -> R
config::save_handle(&instance).ok(); config::save_handle(&instance).ok();
logger.log(format!("Configuration file created for {ins}")).unwrap(); logger.log(format!("Configuration file created for {ins}")).unwrap();
drop(instance); drop(instance);
println!("{} Instantiation complete.", *ARROW_GREEN); println!("{} Instantiation of {ins} complete.", *ARROW_GREEN);
Ok(()) Ok(())
} }
@ -167,7 +185,9 @@ fn engage_aggregator<'a>(
while let Some(arg) = args.next() { while let Some(arg) = args.next() {
match arg { match arg {
Operand::Short('d') | Operand::Long("slice") Operand::Short('d')
| Operand::Long("dep") | Operand::LongPos("dep", _)
| Operand::Short('s') | Operand::Long("slice")
| Operand::Short('r') | Operand::Long("root") | Operand::Short('r') | Operand::Long("root")
| Operand::Short('t') | Operand::Long("target") | Operand::Short('t') | Operand::Long("target")
| Operand::Short('y') | Operand::Long("refresh") | Operand::Short('y') | Operand::Long("refresh")
@ -197,20 +217,16 @@ fn engage_aggregator<'a>(
| Operand::LongPos("target", target) => { | Operand::LongPos("target", target) => {
current_target = target; current_target = target;
targets.push(target); targets.push(target);
if base {
queue.insert(current_target.into(), vec!("base", "pacwrap-base-dist"));
base = false;
}
}, },
Operand::Value(package) => if current_target != "" { Operand::Value(package) => if current_target != "" {
match queue.get_mut(current_target.into()) { match queue.get_mut(current_target.into()) {
Some(vec) => vec.push(package.into()), Some(vec) => vec.push(package.into()),
None => { None => { queue.insert(current_target.into(), vec!(package)); },
let packages = if base {
base = false;
vec!(package, "base", "pacwrap-base-dist")
} else {
vec!(package)
};
queue.insert(current_target.into(), packages);
},
} }
}, },
_ => Err(args.invalid_operand())? _ => Err(args.invalid_operand())?