Add method to create an Installer struct from an archive path
This commit is contained in:
parent
c36b3b14ab
commit
7fe884cd3e
@ -13,7 +13,7 @@ use {
|
|||||||
ffi::OsStr,
|
ffi::OsStr,
|
||||||
fmt::Write as _,
|
fmt::Write as _,
|
||||||
fs::{self, DirBuilder, File},
|
fs::{self, DirBuilder, File},
|
||||||
io::{self, BufWriter, Write},
|
io::{self, BufReader, BufWriter, Write},
|
||||||
os::{
|
os::{
|
||||||
self,
|
self,
|
||||||
unix::{fs::DirBuilderExt, prelude::OpenOptionsExt},
|
unix::{fs::DirBuilderExt, prelude::OpenOptionsExt},
|
||||||
@ -56,17 +56,31 @@ pub enum InstallMessage {
|
|||||||
pub struct Installer<T: io::Read> {
|
pub struct Installer<T: io::Read> {
|
||||||
/// The filesystem root under which to install this package.
|
/// The filesystem root under which to install this package.
|
||||||
/// Normally this is "/".
|
/// Normally this is "/".
|
||||||
path: PathBuf,
|
root: PathBuf,
|
||||||
package: Package,
|
package: Package,
|
||||||
reader: T,
|
reader: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Installer<Decoder<'_, BufReader<File>>> {
|
||||||
|
/// creates a new installer from an archive path
|
||||||
|
pub fn new_for_file<P: AsRef<OsStr>>(
|
||||||
|
root: P,
|
||||||
|
package: Package,
|
||||||
|
archive: P,
|
||||||
|
) -> Result<Self, io::Error> {
|
||||||
|
let root = Path::new(&root).to_path_buf();
|
||||||
|
let fd = File::open(Path::new(&archive))?;
|
||||||
|
let decoder = Decoder::new(fd)?;
|
||||||
|
Ok(Self::new(root, package, decoder))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: io::Read> Installer<T> {
|
impl<T: io::Read> Installer<T> {
|
||||||
/// Creates a new installer from an open archive.
|
/// Creates a new installer from an open archive stream
|
||||||
pub fn new<P: AsRef<OsStr>>(path: P, package: Package, reader: T) -> Self {
|
pub fn new<P: AsRef<OsStr>>(root: P, package: Package, reader: T) -> Self {
|
||||||
let path = Path::new(&path).to_path_buf();
|
let root = Path::new(&root).to_path_buf();
|
||||||
Self {
|
Self {
|
||||||
path,
|
root,
|
||||||
package,
|
package,
|
||||||
reader,
|
reader,
|
||||||
}
|
}
|
||||||
@ -83,13 +97,13 @@ impl<T: io::Read> Installer<T> {
|
|||||||
};
|
};
|
||||||
let len = archive.nodes.len();
|
let len = archive.nodes.len();
|
||||||
sender.send(InstallMessage::ArchiveLen(len))?;
|
sender.send(InstallMessage::ArchiveLen(len))?;
|
||||||
let mut db_pkgdir = crate::get_dbdir(Some(self.path.clone()));
|
let mut db_pkgdir = crate::get_dbdir(Some(self.root.clone()));
|
||||||
db_pkgdir.push(&self.package.name);
|
db_pkgdir.push(&self.package.name);
|
||||||
if !db_pkgdir.exists() {
|
if !db_pkgdir.exists() {
|
||||||
fs::create_dir_all(&db_pkgdir)?;
|
fs::create_dir_all(&db_pkgdir)?;
|
||||||
}
|
}
|
||||||
pop_appstream(&mut archive, &db_pkgdir)?;
|
pop_appstream(&mut archive, &db_pkgdir)?;
|
||||||
pop_pinstall(&mut archive, &mut hooks, &self.package.name, &self.path)?;
|
pop_pinstall(&mut archive, &mut hooks, &self.package.name, &self.root)?;
|
||||||
let mut db_file = db_pkgdir;
|
let mut db_file = db_pkgdir;
|
||||||
db_file.push("package.ron");
|
db_file.push("package.ron");
|
||||||
if db_file.exists() {
|
if db_file.exists() {
|
||||||
@ -98,64 +112,67 @@ impl<T: io::Read> Installer<T> {
|
|||||||
let fd = File::create(&db_file)?;
|
let fd = File::create(&db_file)?;
|
||||||
let writer = BufWriter::new(fd);
|
let writer = BufWriter::new(fd);
|
||||||
pr_node.write(writer)?;
|
pr_node.write(writer)?;
|
||||||
let path = &self.path;
|
let root = &self.root;
|
||||||
let package = &self.package;
|
let package = &self.package;
|
||||||
let hooks = Mutex::new(hooks);
|
let hooks = Mutex::new(hooks);
|
||||||
let s = sender.clone();
|
let s = sender.clone();
|
||||||
archive.nodes.par_iter().try_for_each_with(s, |sender, node| {
|
archive
|
||||||
let mut path = path.clone();
|
.nodes
|
||||||
let fpath = node.header.file_path()?;
|
.par_iter()
|
||||||
if let Some(s) = node.header.prefix() {
|
.try_for_each_with(s, |sender, node| {
|
||||||
if s.contains("/share/man/") {
|
let mut path = root.clone();
|
||||||
let mut h = hooks.lock().unwrap();
|
let fpath = node.header.file_path()?;
|
||||||
if !h.contains(&Hooks::Man) {
|
if let Some(s) = node.header.prefix() {
|
||||||
h.push(Hooks::Man);
|
if s.contains("/share/man/") {
|
||||||
}
|
let mut h = hooks.lock().unwrap();
|
||||||
} else if s.contains("/share/info") {
|
if !h.contains(&Hooks::Man) {
|
||||||
hooks
|
h.push(Hooks::Man);
|
||||||
.lock()
|
}
|
||||||
.unwrap()
|
} else if s.contains("/share/info") {
|
||||||
.push(Hooks::Info(fpath.to_str().unwrap().to_string()))
|
hooks
|
||||||
} else if s.contains("/share/glib-2.0/schemas") {
|
.lock()
|
||||||
let mut h = hooks.lock().unwrap();
|
.unwrap()
|
||||||
if !h.contains(&Hooks::GlibSchema) {
|
.push(Hooks::Info(fpath.to_str().unwrap().to_string()))
|
||||||
h.push(Hooks::GlibSchema);
|
} else if s.contains("/share/glib-2.0/schemas") {
|
||||||
|
let mut h = hooks.lock().unwrap();
|
||||||
|
if !h.contains(&Hooks::GlibSchema) {
|
||||||
|
h.push(Hooks::GlibSchema);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
// Match up a package entry with a tar node
|
||||||
// Match up a package entry with a tar node
|
let entry = package
|
||||||
let entry = package
|
.plist
|
||||||
.plist
|
.entries
|
||||||
.entries
|
.iter()
|
||||||
.iter()
|
.find(|&x| match x {
|
||||||
.find(|&x| match x {
|
Entry::File {
|
||||||
Entry::File {
|
path,
|
||||||
path,
|
sha256sum: _,
|
||||||
sha256sum: _,
|
mode: _,
|
||||||
mode: _,
|
size: _,
|
||||||
size: _,
|
} => path == &fpath,
|
||||||
} => path == &fpath,
|
Entry::Link { path, target: _ } => path == &fpath,
|
||||||
Entry::Link { path, target: _ } => path == &fpath,
|
Entry::Directory { path, mode: _ } => path == &fpath,
|
||||||
Entry::Directory { path, mode: _ } => path == &fpath,
|
})
|
||||||
})
|
.unwrap();
|
||||||
.unwrap();
|
path = path.join(&fpath);
|
||||||
path = path.join(&fpath);
|
if let Some(parent) = path.parent() {
|
||||||
if let Some(parent) = path.parent() {
|
if !parent.exists() {
|
||||||
if !parent.exists() {
|
fs::create_dir_all(&parent)?;
|
||||||
fs::create_dir_all(&parent)?;
|
}
|
||||||
}
|
}
|
||||||
}
|
if path.exists() {
|
||||||
if path.exists() {
|
if path.is_dir() {
|
||||||
if path.is_dir() {
|
fs::remove_dir(&path)?;
|
||||||
fs::remove_dir(&path)?;
|
} else if path.is_symlink() || path.is_file() {
|
||||||
} else if path.is_symlink() || path.is_file() {
|
fs::remove_file(&path)?;
|
||||||
fs::remove_file(&path)?;
|
}
|
||||||
}
|
}
|
||||||
}
|
let msg = extract_entry(entry, node, path)?;
|
||||||
let msg = extract_entry(entry, node, path)?;
|
sender.send(msg)?;
|
||||||
sender.send(msg)?;
|
Ok::<(), InstallError>(())
|
||||||
Ok::<(), InstallError>(())
|
})?;
|
||||||
})?;
|
|
||||||
Ok(hooks.into_inner()?)
|
Ok(hooks.into_inner()?)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,12 +181,12 @@ impl<T: io::Read> Installer<T> {
|
|||||||
if let Some(ref users) = self.package.users {
|
if let Some(ref users) = self.package.users {
|
||||||
users
|
users
|
||||||
.iter()
|
.iter()
|
||||||
.for_each(|u| hooks.push((u.clone(), Some(self.path.clone())).into()));
|
.for_each(|u| hooks.push((u.clone(), Some(self.root.clone())).into()));
|
||||||
}
|
}
|
||||||
if let Some(ref groups) = self.package.groups {
|
if let Some(ref groups) = self.package.groups {
|
||||||
groups
|
groups
|
||||||
.iter()
|
.iter()
|
||||||
.for_each(|g| hooks.push((g.clone(), Some(self.path.clone())).into()));
|
.for_each(|g| hooks.push((g.clone(), Some(self.root.clone())).into()));
|
||||||
}
|
}
|
||||||
hooks
|
hooks
|
||||||
}
|
}
|
||||||
@ -252,6 +269,7 @@ fn pop_pinstall(
|
|||||||
}
|
}
|
||||||
|
|
||||||
mod error {
|
mod error {
|
||||||
|
use super::InstallMessage;
|
||||||
use crate::Hooks;
|
use crate::Hooks;
|
||||||
use hpk_package::tar;
|
use hpk_package::tar;
|
||||||
use std::{
|
use std::{
|
||||||
@ -263,7 +281,6 @@ mod error {
|
|||||||
PoisonError,
|
PoisonError,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use super::InstallMessage;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum InstallError {
|
pub enum InstallError {
|
||||||
|
Loading…
Reference in New Issue
Block a user