Creating packages with the cli now working;
This commit is contained in:
parent
ffcd6820d0
commit
b9116951d5
@ -78,7 +78,7 @@ Perusing the cli options will show much of the intended functionality.
|
|||||||
|
|
||||||
### What's already working
|
### What's already working
|
||||||
- [x] initializing a package specs file on the command line
|
- [x] initializing a package specs file on the command line
|
||||||
- [ ] creating a package archive from a directory of files
|
- [x] creating a package archive from a directory of files
|
||||||
- [ ] installing local packages
|
- [ ] installing local packages
|
||||||
- [ ] installing remote packages
|
- [ ] installing remote packages
|
||||||
- [ ] resolving dependencies
|
- [ ] resolving dependencies
|
||||||
|
@ -23,7 +23,15 @@ fn create() -> Command {
|
|||||||
.about("Create a new package from a directory of files")
|
.about("Create a new package from a directory of files")
|
||||||
.args([
|
.args([
|
||||||
Arg::new("directory")
|
Arg::new("directory")
|
||||||
.help("the directory where the files are located [default: current working directory]")
|
.help("the directory where the files are located")
|
||||||
|
.required(true)
|
||||||
|
.num_args(1),
|
||||||
|
Arg::new("output")
|
||||||
|
.help("the location to save the package archive and package.ron [default: current working directory]")
|
||||||
|
.short('o')
|
||||||
|
.long("output")
|
||||||
|
.value_name("directory")
|
||||||
|
.value_hint(ValueHint::DirPath)
|
||||||
.num_args(1),
|
.num_args(1),
|
||||||
Arg::new("specs")
|
Arg::new("specs")
|
||||||
.help("path to the package specs file in `ron` format")
|
.help("path to the package specs file in `ron` format")
|
||||||
|
41
src/hpk.rs
41
src/hpk.rs
@ -1,9 +1,9 @@
|
|||||||
use {
|
use {
|
||||||
clap::ArgMatches,
|
clap::ArgMatches,
|
||||||
cli::cli,
|
cli::cli,
|
||||||
hpk::Specs,
|
hpk::{Dependency, Specs, Version},
|
||||||
ron::ser::{to_writer_pretty, PrettyConfig},
|
ron::ser::{to_writer_pretty, PrettyConfig},
|
||||||
std::{error::Error, fs::File, io::BufWriter, path::PathBuf},
|
std::{error::Error, env, fs::File, io::BufWriter, path::PathBuf},
|
||||||
};
|
};
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn Error>> {
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
@ -23,8 +23,41 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create(_matches: &ArgMatches) -> Result<(), Box<dyn Error>> {
|
fn create(matches: &ArgMatches) -> Result<(), Box<dyn Error>> {
|
||||||
unimplemented!();
|
let dir = PathBuf::from(matches.get_one::<String>("directory").unwrap().to_string());
|
||||||
|
let outdir = if let Some(d) = matches.get_one::<String>("output") {
|
||||||
|
PathBuf::from(&d.to_string())
|
||||||
|
} else {
|
||||||
|
env::current_dir()?
|
||||||
|
};
|
||||||
|
let mut specs = if let Some(s) = matches.get_one::<String>("specs") {
|
||||||
|
let path = PathBuf::from(s.to_string());
|
||||||
|
let fd = File::open(path)?;
|
||||||
|
let specs = ron::de::from_reader(fd)?;
|
||||||
|
specs
|
||||||
|
} else {
|
||||||
|
Specs::default()
|
||||||
|
};
|
||||||
|
if let Some(n) = matches.get_one::<String>("name") {
|
||||||
|
specs.name = n.to_string();
|
||||||
|
}
|
||||||
|
if let Some(v) = matches.get_one::<String>("package-version") {
|
||||||
|
specs.version = v.to_string().parse::<Version>()?;
|
||||||
|
}
|
||||||
|
if let Some(r) = matches.get_one::<u8>("release") {
|
||||||
|
specs.release = *r;
|
||||||
|
}
|
||||||
|
if let Some(deps) = matches.get_many::<String>("dependencies") {
|
||||||
|
for d in deps {
|
||||||
|
let d = Dependency {
|
||||||
|
name: d.to_string(),
|
||||||
|
version: (None, None),
|
||||||
|
};
|
||||||
|
specs.dependencies.push(d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hpk::create_package(&dir, specs, &outdir)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init(matches: &ArgMatches) -> Result<PathBuf, Box<dyn Error>> {
|
fn init(matches: &ArgMatches) -> Result<PathBuf, Box<dyn Error>> {
|
||||||
|
@ -66,6 +66,11 @@ impl Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn fix_path(path: &Path) -> PathBuf {
|
fn fix_path(path: &Path) -> PathBuf {
|
||||||
|
let path = if let Ok(p) = path.strip_prefix("./") {
|
||||||
|
&p
|
||||||
|
} else {
|
||||||
|
path
|
||||||
|
};
|
||||||
if path.is_file() || path.is_symlink() {
|
if path.is_file() || path.is_symlink() {
|
||||||
match path.ancestors().last().and_then(Path::to_str) {
|
match path.ancestors().last().and_then(Path::to_str) {
|
||||||
Some("etc" | "var") => {
|
Some("etc" | "var") => {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::Item;
|
use crate::Item;
|
||||||
use std::path::PathBuf;
|
use std::{path::PathBuf, fs};
|
||||||
use zstd::Encoder;
|
use zstd::Encoder;
|
||||||
|
|
||||||
mod dependency;
|
mod dependency;
|
||||||
@ -11,6 +11,7 @@ use {
|
|||||||
ron::ser::{to_string_pretty, PrettyConfig},
|
ron::ser::{to_string_pretty, PrettyConfig},
|
||||||
serde::{Deserialize, Serialize},
|
serde::{Deserialize, Serialize},
|
||||||
std::{
|
std::{
|
||||||
|
env,
|
||||||
error::Error,
|
error::Error,
|
||||||
fs::File,
|
fs::File,
|
||||||
io::{BufWriter, Write},
|
io::{BufWriter, Write},
|
||||||
@ -88,13 +89,22 @@ impl Package {
|
|||||||
to_string_pretty(self, cfg)
|
to_string_pretty(self, cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn save_ron_and_create_tar_node(&self) -> Result<Node, Box<dyn Error>> {
|
pub fn save_ron_and_create_tar_node(&self, outdir: &Path) -> Result<Node, Box<dyn Error>> {
|
||||||
let buf = File::open("package.ron")?;
|
if !outdir.exists() {
|
||||||
let meta = buf.metadata()?;
|
fs::create_dir_all(outdir)?;
|
||||||
|
}
|
||||||
|
let mut outfile = outdir.to_path_buf();
|
||||||
|
outfile.push("package.ron");
|
||||||
|
let fd = File::create(&outfile)?;
|
||||||
let s = self.as_ron()?;
|
let s = self.as_ron()?;
|
||||||
let mut writer = BufWriter::new(buf);
|
let mut writer = BufWriter::new(&fd);
|
||||||
writer.write_all(s.as_bytes())?;
|
writer.write_all(s.as_bytes())?;
|
||||||
let node = Node::read_data_to_tar(s.as_bytes(), "package.ron", &meta, None)?;
|
writer.flush()?;
|
||||||
|
println!("{} written", outfile.display());
|
||||||
|
let dir = env::current_dir()?;
|
||||||
|
env::set_current_dir(outdir)?;
|
||||||
|
let node = Node::read_file_to_tar("package.ron")?;
|
||||||
|
env::set_current_dir(dir)?;
|
||||||
Ok(node)
|
Ok(node)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,8 +113,13 @@ impl Package {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create(path: &Path, specs: Specs) -> Result<(), Box<dyn Error>> {
|
pub fn create(path: &Path, specs: Specs, outdir: &Path) -> Result<(), Box<dyn Error>> {
|
||||||
let mut items = WalkDir::new(path)
|
if !outdir.exists() {
|
||||||
|
fs::create_dir_all(outdir)?;
|
||||||
|
}
|
||||||
|
let outdir = outdir.canonicalize()?;
|
||||||
|
env::set_current_dir(path)?;
|
||||||
|
let mut items = WalkDir::new(".")
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.par_iter()
|
.par_iter()
|
||||||
@ -132,15 +147,19 @@ pub fn create(path: &Path, specs: Specs) -> Result<(), Box<dyn Error>> {
|
|||||||
let mut package: Package = specs.into();
|
let mut package: Package = specs.into();
|
||||||
package.plist = plist;
|
package.plist = plist;
|
||||||
package.size = totalsize;
|
package.size = totalsize;
|
||||||
let node = package.save_ron_and_create_tar_node()?.to_vec()?;
|
println!("creating package.ron");
|
||||||
|
let node = package.save_ron_and_create_tar_node(&outdir)?.to_vec()?;
|
||||||
archive.extend(node);
|
archive.extend(node);
|
||||||
archive.write_all(&[0; 9216])?;
|
//archive.write_all(&[0; 9216])?;
|
||||||
let name = package.fullname();
|
let name = package.fullname();
|
||||||
let mut path = PathBuf::from(&name);
|
let mut path = PathBuf::from(&name);
|
||||||
path.set_extension("tar.zst");
|
path.set_extension("tar.zst");
|
||||||
let fd = File::open(&path)?;
|
let mut outfile = outdir.to_path_buf();
|
||||||
|
outfile.push(path);
|
||||||
|
let fd = File::create(&outfile)?;
|
||||||
let mut writer = Encoder::new(fd, 0)?;
|
let mut writer = Encoder::new(fd, 0)?;
|
||||||
writer.write_all(&archive)?;
|
writer.write_all(&archive)?;
|
||||||
let _fd = writer.finish()?;
|
let _fd = writer.finish()?;
|
||||||
|
println!("{} saved", outfile.display());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Owner {
|
pub struct Owner {
|
||||||
pub uid: u32,
|
pub uid: u32,
|
||||||
pub gid: u32,
|
pub gid: u32,
|
||||||
@ -281,8 +282,7 @@ impl Header {
|
|||||||
header.device_minor[..minor.len()].copy_from_slice(minor.as_bytes());
|
header.device_minor[..minor.len()].copy_from_slice(minor.as_bytes());
|
||||||
}
|
}
|
||||||
header.username[..owner.username.len()].copy_from_slice(owner.username.as_bytes());
|
header.username[..owner.username.len()].copy_from_slice(owner.username.as_bytes());
|
||||||
let group = "root";
|
header.groupname[..owner.groupname.len()].copy_from_slice(owner.groupname.as_bytes());
|
||||||
header.groupname[..group.len()].copy_from_slice(owner.groupname.as_bytes());
|
|
||||||
header.update_checksum()?;
|
header.update_checksum()?;
|
||||||
Ok(header)
|
Ok(header)
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ impl Archive {
|
|||||||
///
|
///
|
||||||
/// let data = Archive::new("test/1.txt".to_string()).unwrap();
|
/// let data = Archive::new("test/1.txt".to_string()).unwrap();
|
||||||
/// ```
|
/// ```
|
||||||
pub fn new(filename: String) -> Result<Self, Error> {
|
pub fn new(filename: &str) -> Result<Self, Error> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
nodes: vec![Node::read_file_to_tar(filename)?],
|
nodes: vec![Node::read_file_to_tar(filename)?],
|
||||||
})
|
})
|
||||||
@ -81,7 +81,7 @@ impl Archive {
|
|||||||
/// let mut data = Archive::new("test/1.txt".to_string()).unwrap();
|
/// let mut data = Archive::new("test/1.txt".to_string()).unwrap();
|
||||||
/// data.append("test/1.txt".to_string()).unwrap();
|
/// data.append("test/1.txt".to_string()).unwrap();
|
||||||
/// ```
|
/// ```
|
||||||
pub fn append(&mut self, filename: String) -> Result<(), Error> {
|
pub fn append(&mut self, filename: &str) -> Result<(), Error> {
|
||||||
self.nodes.push(Node::read_file_to_tar(filename)?);
|
self.nodes.push(Node::read_file_to_tar(filename)?);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -57,8 +57,8 @@ impl Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Open and read a file from the ``filename`` argument to a TarNode.
|
/// Open and read a file from the ``filename`` argument to a TarNode.
|
||||||
pub fn read_file_to_tar(filename: String) -> Result<Self, Error> {
|
pub fn read_file_to_tar(filename: &str) -> Result<Self, Error> {
|
||||||
let header = Header::new(&filename)?;
|
let header = Header::new(filename)?;
|
||||||
if header.link_indicator[0] != FileType::Normal as u8 {
|
if header.link_indicator[0] != FileType::Normal as u8 {
|
||||||
return Ok(Node {
|
return Ok(Node {
|
||||||
header,
|
header,
|
||||||
@ -66,7 +66,7 @@ impl Node {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let file = File::open(&filename)?;
|
let file = File::open(filename)?;
|
||||||
let mut reader = BufReader::new(file);
|
let mut reader = BufReader::new(file);
|
||||||
Ok(Node {
|
Ok(Node {
|
||||||
header,
|
header,
|
||||||
|
Loading…
Reference in New Issue
Block a user