feat(package): complete archiver implementation
This commit is contained in:
parent
2c955198ff
commit
64350de3a9
espanso-package/src
|
@ -20,9 +20,11 @@
|
|||
use anyhow::{bail, Context, Result};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use crate::{ArchivedPackage, Archiver, Package, PackageSpecifier, SaveOptions};
|
||||
use crate::{
|
||||
manifest::Manifest, ArchivedPackage, Archiver, Package, PackageSpecifier, SaveOptions,
|
||||
};
|
||||
|
||||
use super::StoredPackage;
|
||||
use super::{LegacyPackage, PackageSource, StoredPackage, PACKAGE_SOURCE_FILE};
|
||||
|
||||
pub struct DefaultArchiver {
|
||||
package_dir: PathBuf,
|
||||
|
@ -92,16 +94,58 @@ impl Archiver for DefaultArchiver {
|
|||
Ok(archived_package)
|
||||
}
|
||||
|
||||
fn get(&self, name: &str) -> Result<ArchivedPackage> {
|
||||
todo!()
|
||||
fn get(&self, name: &str) -> Result<StoredPackage> {
|
||||
let target_dir = self.package_dir.join(name);
|
||||
|
||||
if !target_dir.is_dir() {
|
||||
bail!("package '{}' not found", name);
|
||||
}
|
||||
|
||||
let manifest_path = target_dir.join("_manifest.yml");
|
||||
if !manifest_path.is_file() {
|
||||
return Ok(StoredPackage::Legacy(LegacyPackage {
|
||||
name: name.to_string(),
|
||||
}));
|
||||
}
|
||||
|
||||
let manifest = Manifest::parse(&manifest_path).context("unable to parse package manifest")?;
|
||||
|
||||
let source_path = target_dir.join(PACKAGE_SOURCE_FILE);
|
||||
let source =
|
||||
PackageSource::parse(&source_path).context("unable to parse package source file")?;
|
||||
|
||||
Ok(StoredPackage::Modern(ArchivedPackage { manifest, source }))
|
||||
}
|
||||
|
||||
fn list(&self) -> Result<Vec<StoredPackage>> {
|
||||
todo!()
|
||||
let mut output = Vec::new();
|
||||
|
||||
for path in std::fs::read_dir(&self.package_dir)? {
|
||||
let path = path?.path();
|
||||
if !path.is_dir() {
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some(package_name) = path.file_name() {
|
||||
let package_name = package_name.to_string_lossy().to_string();
|
||||
|
||||
output.push(self.get(&package_name)?);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(output)
|
||||
}
|
||||
|
||||
fn delete(&self, name: &str) -> Result<()> {
|
||||
todo!()
|
||||
let target_dir = self.package_dir.join(name);
|
||||
|
||||
if !target_dir.is_dir() {
|
||||
bail!("package {} not found", name);
|
||||
}
|
||||
|
||||
std::fs::remove_dir_all(&target_dir).context("unable to remove package directory")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -232,4 +276,71 @@ matches:
|
|||
assert!(result.is_ok());
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_delete_package() {
|
||||
run_with_two_temp_dirs(|package_dir, dest_dir| {
|
||||
let package = create_fake_package(package_dir);
|
||||
|
||||
let archiver = DefaultArchiver::new(dest_dir);
|
||||
let result = archiver.save(
|
||||
&*package,
|
||||
&PackageSpecifier {
|
||||
name: "package1".to_string(),
|
||||
git_repo_url: Some("https://github.com/espanso/dummy-package".to_string()),
|
||||
git_branch: Some("main".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
&SaveOptions::default(),
|
||||
);
|
||||
|
||||
assert!(result.is_ok());
|
||||
|
||||
let package_out_dir = dest_dir.join("package1");
|
||||
assert!(package_out_dir.is_dir());
|
||||
|
||||
archiver.delete("package1").unwrap();
|
||||
|
||||
assert!(!package_out_dir.is_dir());
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_list_packages() {
|
||||
run_with_two_temp_dirs(|package_dir, dest_dir| {
|
||||
let package = create_fake_package(package_dir);
|
||||
|
||||
let archiver = DefaultArchiver::new(dest_dir);
|
||||
let result = archiver.save(
|
||||
&*package,
|
||||
&PackageSpecifier {
|
||||
name: "package1".to_string(),
|
||||
git_repo_url: Some("https://github.com/espanso/dummy-package".to_string()),
|
||||
git_branch: Some("main".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
&SaveOptions::default(),
|
||||
);
|
||||
|
||||
assert!(result.is_ok());
|
||||
|
||||
let package_out_dir = dest_dir.join("package1");
|
||||
assert!(package_out_dir.is_dir());
|
||||
|
||||
let legacy_package = dest_dir.join("z_legacypackage1");
|
||||
create_dir_all(&legacy_package).unwrap();
|
||||
|
||||
let package_list = archiver.list().unwrap();
|
||||
|
||||
assert!(package_list.iter().any(|package| *package
|
||||
== StoredPackage::Modern(ArchivedPackage {
|
||||
manifest: Manifest::parse(&package_out_dir.join("_manifest.yml")).unwrap(),
|
||||
source: PackageSource::parse(&package_out_dir.join(PACKAGE_SOURCE_FILE)).unwrap(),
|
||||
})));
|
||||
assert!(package_list.iter().any(|package| *package
|
||||
== StoredPackage::Legacy(LegacyPackage {
|
||||
name: "z_legacypackage1".to_string()
|
||||
})));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,10 +17,12 @@
|
|||
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
use anyhow::Result;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{Package, PackageSpecifier, manifest::Manifest};
|
||||
use crate::{manifest::Manifest, Package, PackageSpecifier};
|
||||
|
||||
pub mod default;
|
||||
mod read;
|
||||
|
@ -28,7 +30,7 @@ mod util;
|
|||
|
||||
pub const PACKAGE_SOURCE_FILE: &str = "_pkgsource.yml";
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct ArchivedPackage {
|
||||
// Metadata
|
||||
pub manifest: Manifest,
|
||||
|
@ -37,20 +39,25 @@ pub struct ArchivedPackage {
|
|||
pub source: PackageSource,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct LegacyPackage {
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum StoredPackage {
|
||||
Legacy(LegacyPackage),
|
||||
Modern(ArchivedPackage),
|
||||
}
|
||||
|
||||
pub trait Archiver {
|
||||
fn get(&self, name: &str) -> Result<ArchivedPackage>;
|
||||
fn save(&self, package: &dyn Package, specifier: &PackageSpecifier, save_options: &SaveOptions) -> Result<ArchivedPackage>;
|
||||
fn get(&self, name: &str) -> Result<StoredPackage>;
|
||||
fn save(
|
||||
&self,
|
||||
package: &dyn Package,
|
||||
specifier: &PackageSpecifier,
|
||||
save_options: &SaveOptions,
|
||||
) -> Result<ArchivedPackage>;
|
||||
fn list(&self) -> Result<Vec<StoredPackage>>;
|
||||
fn delete(&self, name: &str) -> Result<()>;
|
||||
}
|
||||
|
@ -60,7 +67,7 @@ pub struct SaveOptions {
|
|||
pub overwrite_existing: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum PackageSource {
|
||||
Hub,
|
||||
|
@ -71,6 +78,26 @@ pub enum PackageSource {
|
|||
},
|
||||
}
|
||||
|
||||
impl PackageSource {
|
||||
pub fn parse(source_path: &Path) -> Result<Self> {
|
||||
let source_str = std::fs::read_to_string(source_path)?;
|
||||
Ok(serde_yaml::from_str(&source_str)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for PackageSource {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
PackageSource::Hub => write!(f, "espanso-hub"),
|
||||
PackageSource::Git {
|
||||
repo_url,
|
||||
repo_branch: _,
|
||||
use_native_git: _,
|
||||
} => write!(f, "git: {}", repo_url),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&PackageSpecifier> for PackageSource {
|
||||
fn from(package: &PackageSpecifier) -> Self {
|
||||
if let Some(git_repo_url) = package.git_repo_url.as_deref() {
|
||||
|
|
|
@ -28,7 +28,7 @@ mod provider;
|
|||
mod resolver;
|
||||
mod util;
|
||||
|
||||
pub use archive::{ArchivedPackage, Archiver, SaveOptions};
|
||||
pub use archive::{ArchivedPackage, Archiver, SaveOptions, StoredPackage};
|
||||
pub use provider::{PackageSpecifier, PackageProvider};
|
||||
pub use package::Package;
|
||||
|
||||
|
@ -74,7 +74,7 @@ pub fn get_provider(package: &PackageSpecifier) -> Result<Box<dyn PackageProvide
|
|||
Ok(Box::new(provider::git::GitPackageProvider::new()))
|
||||
} else {
|
||||
// TODO: use espanso-hub method
|
||||
todo!();
|
||||
bail!("espanso hub method not yet implemented")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user