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:
parent
728185d960
commit
8b588c4ee8
3 changed files with 89 additions and 80 deletions
|
@ -333,15 +333,11 @@ invoke_replication() {
|
|||
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
|
||||
done
|
||||
|
||||
$CREATE_SCRIPT -Syu --create $REPLICATE_CMD --noconfirm
|
||||
}
|
||||
|
||||
replicate_instance() {
|
||||
|
@ -353,7 +349,7 @@ replicate_instance() {
|
|||
|
||||
local depend=
|
||||
local type=$(return_type)
|
||||
local params="c"
|
||||
local params="-"
|
||||
|
||||
[[ $SWITCH == *v* ]] && params+="v"
|
||||
[[ $type != BASE ]] && depend=$(return_dependency)
|
||||
|
@ -361,7 +357,7 @@ replicate_instance() {
|
|||
case $type in
|
||||
ROOT) params+="r";;
|
||||
BASE) params+="b";;
|
||||
DEP) params+="d";;
|
||||
DEP) params+="s";;
|
||||
LINK) ln -s "$INSTANCE_ROOT_DIR/$depend" "$INSTANCE_ROOT_DIR/$instance"
|
||||
mkdir -p "$INSTANCE_HOME_DIR/$instance"
|
||||
echo 'PS1="'$instance'> "' > "$INSTANCE_HOME_DIR/$instance/.bashrc"
|
||||
|
@ -375,16 +371,10 @@ replicate_instance() {
|
|||
local depend_params
|
||||
|
||||
for dep in $(return_dependencies); do
|
||||
depend_params+="-t $dep "
|
||||
depend_params+="--dep=$dep "
|
||||
done
|
||||
|
||||
$CREATE_SCRIPT -Syu$params -t $instance $(return_packages) $foreign_targets $depend_params --noconfirm
|
||||
|
||||
if [[ $? == 0 ]]; then
|
||||
printf " %s$RESET\n" "Replication of $BOLD$instance$RESET complete!"
|
||||
log_to_file "Replication of $instance complete!"
|
||||
fi
|
||||
|
||||
REPLICATE_CMD+="$params -t $instance $(return_packages) $foreign_targets $depend_params "
|
||||
completed[$instance]=1
|
||||
}
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@ fn ascertain_help<'a>(args: &mut Arguments) -> Result<(IndexSet<&'a HelpTopic>,
|
|||
=> topic.extend(HELP_ALL.iter()),
|
||||
Operand::ShortPos('h', 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())?,
|
||||
}
|
||||
}
|
||||
|
@ -323,7 +323,7 @@ fn sync(buf: &mut String, layout: &HelpLayout) -> Result<(), std::fmt::Error> {
|
|||
|
||||
{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}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}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}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}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}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,
|
||||
|
@ -351,13 +351,16 @@ fn sync(buf: &mut String, layout: &HelpLayout) -> Result<(), std::fmt::Error> {
|
|||
|
||||
{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}Requires a base dependency target, and optionally sliced dependency targets, in order to ascertain
|
||||
{tab}{tab}foreign packages and influence ordering of this target. These containers are ideal for installing
|
||||
{tab}{tab}software in with the least amount of filesystem and package synchronization overhead.
|
||||
{tab}{tab}Requires a base dependency be specified, and optionally one or more sliced dependencies, in order
|
||||
{tab}{tab}to ascertain foreign packages and influence ordering of this target. These containers are ideal
|
||||
{tab}{tab}for installing software in with the least amount of filesystem and package synchronization overhead.
|
||||
|
||||
{sub}-t, --target=TARGET{reset_bold}
|
||||
{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}
|
||||
{tab}{tab}Apply specified operation on the specified target only.
|
||||
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
use std::{collections::HashMap, fs::File};
|
||||
use std::io::Write;
|
||||
use std::process::exit;
|
||||
|
||||
use indexmap::IndexMap;
|
||||
use pacwrap_core::{ErrorKind,
|
||||
log::Logger,
|
||||
sync::transaction::TransactionType,
|
||||
utils::{arguments::{Arguments,
|
||||
utils::arguments::{Arguments,
|
||||
InvalidArgument,
|
||||
Operand},
|
||||
print_error},
|
||||
Operand},
|
||||
config::{self,
|
||||
InstanceType,
|
||||
InsVars,
|
||||
|
@ -37,7 +36,7 @@ pub fn synchronize(mut args: &mut Arguments) -> Result<(), ErrorKind> {
|
|||
|
||||
config::init::init();
|
||||
|
||||
if let Some(instype) = create(&mut args)? {
|
||||
if create(&mut args) {
|
||||
if let TransactionType::Upgrade(upgrade, refresh, _) = action {
|
||||
if ! refresh {
|
||||
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)
|
||||
}
|
||||
|
||||
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 create = false;
|
||||
|
||||
args.set_index(1);
|
||||
|
||||
while let Some(arg) = args.next() {
|
||||
match arg {
|
||||
Operand::Short('c') | Operand::Long("create") => create = true,
|
||||
Operand::Short('b') | Operand::Long("base") => match instype {
|
||||
None => instype = Some(InstanceType::BASE),
|
||||
Some(_) => Err(ErrorKind::DuplicateType)?,
|
||||
},
|
||||
Operand::Short('d') | Operand::Long("slice") => match instype {
|
||||
None => instype = Some(InstanceType::DEP),
|
||||
Some(_) => Err(ErrorKind::DuplicateType)?,
|
||||
},
|
||||
Operand::Short('r') | Operand::Long("root") => match instype {
|
||||
None => instype = Some(InstanceType::ROOT),
|
||||
Some(_) => Err(ErrorKind::DuplicateType)?,
|
||||
Operand::ShortPos('d', dep)
|
||||
| Operand::LongPos("dep", dep) => match deps.get_mut(current_target) {
|
||||
Some(d) => {
|
||||
if let Some(instype) = instype {
|
||||
if let InstanceType::BASE = instype {
|
||||
Err(ErrorKind::Message("Dependencies cannot be assigned to base containers."))?
|
||||
}
|
||||
}
|
||||
|
||||
d.1.push(dep);
|
||||
},
|
||||
None => Err(ErrorKind::Argument(InvalidArgument::TargetUnspecified))?
|
||||
},
|
||||
Operand::Short('b')
|
||||
| Operand::Long("base") => instype = Some(InstanceType::BASE),
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
if current_target.len() == 0 {
|
||||
Err(ErrorKind::Argument(InvalidArgument::TargetUnspecified))?
|
||||
}
|
||||
|
||||
Ok(deps)
|
||||
}
|
||||
|
||||
|
||||
fn create(args: &mut Arguments) -> bool {
|
||||
args.set_index(1);
|
||||
|
||||
while let Some(arg) = args.next() {
|
||||
match arg {
|
||||
Operand::Short('c') | Operand::Long("create") => return true,
|
||||
_ => continue,
|
||||
}
|
||||
}
|
||||
|
||||
match create {
|
||||
true => match instype {
|
||||
None => Err(ErrorKind::Message("Container type unspecified."))?, Some(_) => Ok(instype),
|
||||
},
|
||||
false => Ok(None)
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn instantiate(instype: InstanceType, mut targets: Vec<&str>) -> Result<(), ErrorKind> {
|
||||
if targets.len() == 0 {
|
||||
Err(ErrorKind::Argument(InvalidArgument::TargetUnspecified))?
|
||||
fn instantiate<'a>(targets: IndexMap<&'a str, (InstanceType, Vec<&'a str>)>) -> Result<(), ErrorKind> {
|
||||
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)?;
|
||||
}
|
||||
|
||||
let target = targets.remove(0);
|
||||
|
||||
if let InstanceType::ROOT | InstanceType::DEP = instype {
|
||||
if target.len() == 0 {
|
||||
Err(ErrorKind::Message("Dependencies not specified."))?
|
||||
}
|
||||
}
|
||||
|
||||
instantiate_container(target, targets, instype)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn instantiate_container(ins: &str, deps: Vec<&str>, instype: InstanceType) -> Result<(), ErrorKind> {
|
||||
println!("{} {}Instantiating container {ins}{}", *BAR_GREEN, *BOLD, *RESET);
|
||||
|
||||
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 mut logger = Logger::new("pacwrap").init().unwrap();
|
||||
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 std::io::ErrorKind::AlreadyExists = err.kind() {
|
||||
Err(ErrorKind::Message("Container root already exists."))?
|
||||
Err(ErrorKind::Message(format!("Container {ins} already exists.").leak()))?
|
||||
} else {
|
||||
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 Err(err) = std::fs::create_dir(instance.vars().home()) {
|
||||
if err.kind() != std::io::ErrorKind::AlreadyExists {
|
||||
print_error(format!("'{}': {}", instance.vars().root(), err));
|
||||
exit(1);
|
||||
Err(ErrorKind::IOError(instance.vars().root().into(), err.kind()))?
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -147,7 +165,7 @@ fn instantiate_container(ins: &str, deps: Vec<&str>, instype: InstanceType) -> R
|
|||
config::save_handle(&instance).ok();
|
||||
logger.log(format!("Configuration file created for {ins}")).unwrap();
|
||||
drop(instance);
|
||||
println!("{} Instantiation complete.", *ARROW_GREEN);
|
||||
println!("{} Instantiation of {ins} complete.", *ARROW_GREEN);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -167,8 +185,10 @@ fn engage_aggregator<'a>(
|
|||
|
||||
while let Some(arg) = args.next() {
|
||||
match arg {
|
||||
Operand::Short('d') | Operand::Long("slice")
|
||||
| Operand::Short('r') | Operand::Long("root")
|
||||
Operand::Short('d')
|
||||
| Operand::Long("dep") | Operand::LongPos("dep", _)
|
||||
| Operand::Short('s') | Operand::Long("slice")
|
||||
| Operand::Short('r') | Operand::Long("root")
|
||||
| Operand::Short('t') | Operand::Long("target")
|
||||
| Operand::Short('y') | Operand::Long("refresh")
|
||||
| Operand::Short('u') | Operand::Long("upgrade") => continue,
|
||||
|
@ -197,20 +217,16 @@ fn engage_aggregator<'a>(
|
|||
| Operand::LongPos("target", target) => {
|
||||
current_target = target;
|
||||
targets.push(target);
|
||||
|
||||
if base {
|
||||
queue.insert(current_target.into(), vec!("base", "pacwrap-base-dist"));
|
||||
base = false;
|
||||
}
|
||||
},
|
||||
Operand::Value(package) => if current_target != "" {
|
||||
match queue.get_mut(current_target.into()) {
|
||||
Some(vec) => vec.push(package.into()),
|
||||
None => {
|
||||
let packages = if base {
|
||||
base = false;
|
||||
vec!(package, "base", "pacwrap-base-dist")
|
||||
} else {
|
||||
vec!(package)
|
||||
};
|
||||
|
||||
queue.insert(current_target.into(), packages);
|
||||
},
|
||||
None => { queue.insert(current_target.into(), vec!(package)); },
|
||||
}
|
||||
},
|
||||
_ => Err(args.invalid_operand())?
|
||||
|
|
Loading…
Reference in a new issue