Creating packages with the cli now working;

This commit is contained in:
Nathan Fisher 2023-03-25 15:15:13 -04:00
parent ffcd6820d0
commit b9116951d5
8 changed files with 89 additions and 24 deletions

View File

@ -78,7 +78,7 @@ Perusing the cli options will show much of the intended functionality.
### What's already working
- [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 remote packages
- [ ] resolving dependencies

View File

@ -23,7 +23,15 @@ fn create() -> Command {
.about("Create a new package from a directory of files")
.args([
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),
Arg::new("specs")
.help("path to the package specs file in `ron` format")

View File

@ -1,9 +1,9 @@
use {
clap::ArgMatches,
cli::cli,
hpk::Specs,
hpk::{Dependency, Specs, Version},
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>> {
@ -23,8 +23,41 @@ fn main() -> Result<(), Box<dyn Error>> {
Ok(())
}
fn create(_matches: &ArgMatches) -> Result<(), Box<dyn Error>> {
unimplemented!();
fn create(matches: &ArgMatches) -> Result<(), Box<dyn Error>> {
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>> {

View File

@ -66,6 +66,11 @@ impl Item {
}
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() {
match path.ancestors().last().and_then(Path::to_str) {
Some("etc" | "var") => {

View File

@ -1,5 +1,5 @@
use crate::Item;
use std::path::PathBuf;
use std::{path::PathBuf, fs};
use zstd::Encoder;
mod dependency;
@ -11,6 +11,7 @@ use {
ron::ser::{to_string_pretty, PrettyConfig},
serde::{Deserialize, Serialize},
std::{
env,
error::Error,
fs::File,
io::{BufWriter, Write},
@ -88,13 +89,22 @@ impl Package {
to_string_pretty(self, cfg)
}
pub fn save_ron_and_create_tar_node(&self) -> Result<Node, Box<dyn Error>> {
let buf = File::open("package.ron")?;
let meta = buf.metadata()?;
pub fn save_ron_and_create_tar_node(&self, outdir: &Path) -> Result<Node, Box<dyn Error>> {
if !outdir.exists() {
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 mut writer = BufWriter::new(buf);
let mut writer = BufWriter::new(&fd);
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)
}
@ -103,8 +113,13 @@ impl Package {
}
}
pub fn create(path: &Path, specs: Specs) -> Result<(), Box<dyn Error>> {
let mut items = WalkDir::new(path)
pub fn create(path: &Path, specs: Specs, outdir: &Path) -> Result<(), Box<dyn Error>> {
if !outdir.exists() {
fs::create_dir_all(outdir)?;
}
let outdir = outdir.canonicalize()?;
env::set_current_dir(path)?;
let mut items = WalkDir::new(".")
.into_iter()
.collect::<Vec<_>>()
.par_iter()
@ -132,15 +147,19 @@ pub fn create(path: &Path, specs: Specs) -> Result<(), Box<dyn Error>> {
let mut package: Package = specs.into();
package.plist = plist;
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.write_all(&[0; 9216])?;
//archive.write_all(&[0; 9216])?;
let name = package.fullname();
let mut path = PathBuf::from(&name);
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)?;
writer.write_all(&archive)?;
let _fd = writer.finish()?;
println!("{} saved", outfile.display());
Ok(())
}

View File

@ -49,6 +49,7 @@ where
}
}
#[derive(Clone)]
pub struct Owner {
pub uid: u32,
pub gid: u32,
@ -281,8 +282,7 @@ impl Header {
header.device_minor[..minor.len()].copy_from_slice(minor.as_bytes());
}
header.username[..owner.username.len()].copy_from_slice(owner.username.as_bytes());
let group = "root";
header.groupname[..group.len()].copy_from_slice(owner.groupname.as_bytes());
header.groupname[..owner.groupname.len()].copy_from_slice(owner.groupname.as_bytes());
header.update_checksum()?;
Ok(header)
}

View File

@ -65,7 +65,7 @@ impl Archive {
///
/// 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 {
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();
/// 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)?);
Ok(())

View File

@ -57,8 +57,8 @@ impl Node {
}
/// Open and read a file from the ``filename`` argument to a TarNode.
pub fn read_file_to_tar(filename: String) -> Result<Self, Error> {
let header = Header::new(&filename)?;
pub fn read_file_to_tar(filename: &str) -> Result<Self, Error> {
let header = Header::new(filename)?;
if header.link_indicator[0] != FileType::Normal as u8 {
return Ok(Node {
header,
@ -66,7 +66,7 @@ impl Node {
});
}
let file = File::open(&filename)?;
let file = File::open(filename)?;
let mut reader = BufReader::new(file);
Ok(Node {
header,