Skip to content

Commit

Permalink
feat: paket events definition support using manifest file
Browse files Browse the repository at this point in the history
a new `[events]` section defines the Paket events and the values the
Fish event names of a package which Paket will emit.

nomenclature: package_event

example:

```toml
[events]
after-install = "gitnow_install"
\# Note that we using a underscore (_) to divide the package name and the Fish event name
```

resolves #8
  • Loading branch information
joseluisq committed Feb 20, 2021
1 parent 4a102f7 commit cdbb50a
Show file tree
Hide file tree
Showing 5 changed files with 196 additions and 97 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

154 changes: 81 additions & 73 deletions src/cli/actions.rs
Original file line number Diff line number Diff line change
@@ -1,33 +1,34 @@
use std::fs;

use crate::git::Git;
use crate::helpers::Command;
use crate::paket::Paket;
use crate::paket::{Paket, PaketEvents};
use crate::pkg::fmt::PkgNameFmt;
use crate::result::{Context, Result};

/// Define actions for every `Paket` command.
pub struct Actions<'a> {
pkt: &'a Paket,
paket: &'a Paket,
git: Git,
}

impl<'a> Actions<'a> {
/// Create a new `Action` instance based on `Paket` object.
pub fn new(pkt: &'a Paket) -> Result<Self> {
let git = Git::new(pkt.paths.paket_dir.clone())?;
Ok(Self { pkt, git })
pub fn new(paket: &'a Paket) -> Result<Self> {
let git = Git::new(paket.paths.paket_dir.clone())?;
Ok(Self { paket, git })
}

/// Command action to install a new package and invoke a `paket_install` Fish shell event.
pub fn install(&self, pkg_name: &str, git_provider: &str) -> Result {
let pkgfmt = PkgNameFmt::from(&pkg_name)?;
let pkg_name = &pkgfmt.get_short_name();
let pkg_tag = Some(pkgfmt.pkg_tag.as_ref());
pub fn install(&mut self, pkg_name: &str, git_provider: &str) -> Result {
let pkg_fmt = PkgNameFmt::from(&pkg_name)?;
let pkg_name = &pkg_fmt.get_short_name();
let pkg_tag = Some(pkg_fmt.pkg_tag.as_ref());
let branch_tag = pkg_tag.unwrap_or("");
let mut is_pkg_local = false;

// Check for a local package (directory path) or a remote one
let pkg_dir = if let Some(pkg_path) = pkgfmt.get_pkg_path() {
let pkg_dir = if let Some(pkg_path) = pkg_fmt.get_pkg_path() {
is_pkg_local = true;
println!(
"Installing package from directory `{}`...",
pkg_path.display()
Expand All @@ -36,7 +37,7 @@ impl<'a> Actions<'a> {
} else {
println!("Installing package `{}@{}`...", &pkg_name, branch_tag);

if self.pkt.pkg_exists(pkg_name) {
if self.paket.pkg_exists(pkg_name) {
bail!(
"package `{}` is already installed. Try to use the `up` command to upgrade it.",
pkg_name
Expand All @@ -47,28 +48,29 @@ impl<'a> Actions<'a> {
self.git.clone(pkg_name, pkg_tag, git_provider)?;

let pkg_dir = self.git.base_dir.join(&pkg_name);
if !self.pkt.pkg_exists(pkg_name) {
if !self.paket.pkg_exists(pkg_name) {
bail!("package `{}` was not cloned with success.", pkg_name);
}
pkg_dir
};

// Process Fish shell package structure
self.pkt
.read_pkg_dir(&pkg_dir, &pkg_name, |src_path, dest_path| {
fs::copy(src_path, dest_path)?;
Ok(())
})?;

// Dispatch the Fish shell `paket_install` event
let out = Command::new("fish", None)
.arg("-c")
.arg("emit paket_install")
.execute()?;

if !out.is_empty() {
print!("{}", out);
}
// Process Fish shell package structure and read the Packet manifest
let manifest = self
.paket
.read_pkg_dir_with_manifest(&pkg_dir, &pkg_name, is_pkg_local)?;

if let (Some(toml_pkg), Some(toml_events)) = (manifest.package, manifest.events) {
// Copy all corresponding package files to Fish shell directories
self.paket
.scan_pkg_dir(&pkg_dir, &toml_pkg.include, |src, dest| {
fs::copy(src, dest)?;
Ok(())
})?;

// Emit an `after_install` Fish shell event if there is an associated Paket event
self.paket
.emit_event(&toml_pkg.name, &toml_events, PaketEvents::AfterInstall)?;
};

println!("Package was installed successfully.");
println!("Now just reload your current Fish shell session.");
Expand All @@ -78,13 +80,15 @@ impl<'a> Actions<'a> {

/// Command action to update an existing package
pub fn update(&mut self, pkg_name: &str) -> Result {
let pkgfmt = PkgNameFmt::from(&pkg_name)?;
let pkg_name = &pkgfmt.get_short_name();
let pkg_tag = Some(pkgfmt.pkg_tag.as_ref());
let pkg_fmt = PkgNameFmt::from(&pkg_name)?;
let pkg_name = &pkg_fmt.get_short_name();
let pkg_tag = Some(pkg_fmt.pkg_tag.as_ref());
let branch_tag = pkg_tag.unwrap_or("");
let mut is_pkg_local = false;

// Check for a local package (directory path) or a remote one
let pkg_dir = if let Some(pkg_path) = pkgfmt.get_pkg_path() {
let pkg_dir = if let Some(pkg_path) = pkg_fmt.get_pkg_path() {
is_pkg_local = true;
println!(
"Updating package from directory `{}`...",
pkg_path.display()
Expand All @@ -93,7 +97,7 @@ impl<'a> Actions<'a> {
} else {
println!("Updating package `{}@{}`...", &pkg_name, branch_tag);

if !self.pkt.pkg_exists(pkg_name) {
if !self.paket.pkg_exists(pkg_name) {
bail!(
"package `{}` is not installed. Try to use the `add` command to install it first.",
pkg_name
Expand All @@ -111,22 +115,23 @@ impl<'a> Actions<'a> {
.with_context(|| format!("package `{}` was not updated properly.", pkg_name))?
};

// Process Fish shell package structure
self.pkt
.read_pkg_dir(&pkg_dir, &pkg_name, |src_path, dest_path| {
fs::copy(src_path, dest_path)?;
Ok(())
})?;

// Dispatch the Fish shell `paket_update` event
let out = Command::new("fish", None)
.arg("-c")
.arg("emit paket_update")
.execute()?;

if !out.is_empty() {
print!("{}", out);
}
// Process Fish shell package structure and read the Packet manifest
let manifest = self
.paket
.read_pkg_dir_with_manifest(&pkg_dir, &pkg_name, is_pkg_local)?;

if let (Some(toml_pkg), Some(toml_events)) = (manifest.package, manifest.events) {
// Copy all corresponding package files to Fish shell directories
self.paket
.scan_pkg_dir(&pkg_dir, &toml_pkg.include, |src, dest| {
fs::copy(src, dest)?;
Ok(())
})?;

// Emit an `after_update` Fish shell event if there is an associated Paket event
self.paket
.emit_event(&toml_pkg.name, &toml_events, PaketEvents::AfterUpdate)?;
};

println!("Package was updated successfully.");
println!("Now just reload your current Fish shell session.");
Expand All @@ -135,17 +140,17 @@ impl<'a> Actions<'a> {
}

/// Command action to remove an existing package and invoke a `paket_uninstall` Fish shell event.
pub fn remove(&self, pkg_name: &str) -> Result {
let pkgfmt = PkgNameFmt::from(&pkg_name)?;
let pkg_name = &pkgfmt.get_short_name();
let pkg_path = pkgfmt.get_pkg_path();
pub fn remove(&mut self, pkg_name: &str) -> Result {
let pkg_fmt = PkgNameFmt::from(&pkg_name)?;
let pkg_name = &pkg_fmt.get_short_name();
let pkg_path = pkg_fmt.get_pkg_path();
let is_pkg_path = pkg_path.is_some();

// Check for a local package (directory path) or a remote one
let pkg_dir = if is_pkg_path {
let pkg_path = pkg_path.unwrap_or_default();
println!(
"Removing installed package using as reference directory `{}`...",
"Removing installed package using directory `{}` as reference...",
pkg_path.display()
);
pkg_path
Expand All @@ -154,7 +159,7 @@ impl<'a> Actions<'a> {

// Process Fish shell package structure
let pkg_dir = self.git.base_dir.join(&pkg_name);
if !self.pkt.pkg_exists(pkg_name) {
if !self.paket.pkg_exists(pkg_name) {
bail!(
"package `{}` is not installed or was already removed.",
pkg_name
Expand All @@ -164,22 +169,25 @@ impl<'a> Actions<'a> {
pkg_dir.canonicalize()?
};

// Dispatch the Fish shell `paket_uninstall` event
let out = Command::new("fish", None)
.arg("-c")
.arg("emit paket_uninstall")
.execute()?;

if !out.is_empty() {
print!("{}", out);
}

self.pkt.read_pkg_dir(&pkg_dir, &pkg_name, |_, dest_path| {
if dest_path.exists() {
fs::remove_file(dest_path)?;
}
Ok(())
})?;
// Process Fish shell package structure and read the Packet manifest
let manifest = self
.paket
.read_pkg_dir_with_manifest(&pkg_dir, &pkg_name, is_pkg_path)?;

if let (Some(toml_pkg), Some(toml_events)) = (manifest.package, manifest.events) {
// Emit a `before_uninstall` Fish shell event if there is an associated Paket event
self.paket
.emit_event(&toml_pkg.name, &toml_events, PaketEvents::BeforeUninstall)?;

// Remove all corresponding package files from Fish shell directories
self.paket
.scan_pkg_dir(&pkg_dir, &toml_pkg.include, |_, dest| {
if dest.exists() {
fs::remove_file(dest)?;
}
Ok(())
})?;
};

if !is_pkg_path {
// TODO: Prevent unnecessary clones for same versions (using cache)
Expand All @@ -190,7 +198,7 @@ impl<'a> Actions<'a> {
fs::remove_dir_all(pkg_dir)?;
}

println!("Package was removed successfully.");
println!("Package was uninstalled successfully.");
println!("Now just reload your current Fish shell session.");

Ok(())
Expand Down
13 changes: 7 additions & 6 deletions src/cli/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@ use crate::result::Result;

pub struct App {}

impl App {
pub fn run(pk: &Paket) -> Result {
impl<'a> App {
pub fn run(pk: &mut Paket) -> Result {
let mut actions = Actions::new(pk)?;

if let Some(commands) = &pk.opts.commands {
match commands {
Commands::Add { pkg_name, provider } => actions.install(pkg_name, provider),
Commands::Update { pkg_name } => actions.update(pkg_name),
Commands::Remove { pkg_name } => actions.remove(pkg_name),
Commands::Add { pkg_name, provider } => {
actions.install(pkg_name.as_str(), provider.as_str())
}
Commands::Update { pkg_name } => actions.update(pkg_name.as_str()),
Commands::Remove { pkg_name } => actions.remove(pkg_name.as_str()),
}?
}

Expand Down
Loading

0 comments on commit cdbb50a

Please sign in to comment.