1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
use libflate::gzip::Decoder; use std::fs::File; use std::path::Path; use std::path::PathBuf; use std::io::{self, Error, ErrorKind, Read}; use tar::{Archive, EntryType}; use std::io::BufReader; use packagemeta::PackageMeta; pub struct Package { archive: Archive<Decoder<BufReader<File>>>, path: PathBuf, meta: Option<PackageMeta>, } impl Package { pub fn from_path<P: AsRef<Path>>(path: P) -> io::Result<Self> { let file = File::open(&path)?; let decoder = Decoder::new(BufReader::new(file))?; let mut ar = Archive::new(decoder); ar.set_preserve_permissions(true); Ok(Package{archive: ar, path: path.as_ref().to_path_buf(), meta: None}) } pub fn install<P: AsRef<Path>>(&mut self, dest: P)-> io::Result<()> { self.archive.unpack(dest)?; Ok(()) } pub fn list(&mut self) -> io::Result<()> { for i in self.archive.entries()? { println!("{}", i?.path()?.display()); } Ok(()) } pub fn archive(&self) -> &Archive<Decoder<BufReader<File>>> { &self.archive } pub fn path(&self) -> &Path { &self.path } pub fn meta(&mut self) -> io::Result<&PackageMeta> { if self.meta.is_none() { let mut toml = None; for entry in self.archive.entries()? { let mut entry = entry?; if entry.header().entry_type() != EntryType::Directory && entry.path()?.starts_with("pkg") { if toml.is_none() { let mut text = String::new(); entry.read_to_string(&mut text)?; toml = Some(text); } else { return Err(Error::new(ErrorKind::Other, "Multiple metadata files in package")); } } } if let Some(toml) = toml { self.meta = Some(PackageMeta::from_toml(&toml).map_err(|e| Error::new(ErrorKind::Other, e))?); } else { return Err(Error::new(ErrorKind::NotFound, "Package metadata not found")); } } Ok(self.meta.as_ref().unwrap()) } }