Add wrapper scripts for mapped commands

feature/lookup-installed
trivernis 1 year ago
parent f517cd5469
commit 75e80ade99
WARNING! Although there is a key with this ID in the database it does not verify this commit! This commit is SUSPICIOUS.
GPG Key ID: DFFFCC2C7A02DB45

@ -1,3 +1,5 @@
use std::io;
use miette::Diagnostic;
use thiserror::Error;
@ -19,4 +21,7 @@ pub enum MapperError {
#[error("Failed to execute mapped command: {0}")]
Command(#[from] CommandError),
#[error("IO Error: {0}")]
Io(#[from] io::Error),
}

@ -0,0 +1,95 @@
use std::{
collections::HashSet,
path::{Path, PathBuf},
};
use tokio::fs::{self, DirEntry};
use crate::{consts::BIN_DIR, repository::node_path::NodePath};
use super::error::MapperResult;
struct NodeApp {
info: DirEntry,
}
impl NodeApp {
pub fn new(info: DirEntry) -> Self {
Self { info }
}
/// returns the name of the application
pub fn name(&self) -> String {
let name = self.info.file_name();
name.to_string_lossy().into_owned()
}
pub async fn unmap(&self) -> MapperResult<()> {
fs::remove_file(self.info.path()).await?;
Ok(())
}
/// creates wrappers to map this application
pub async fn map_executable(&self) -> MapperResult<()> {
let src_path = BIN_DIR.join(self.info.file_name());
let name = self.info.file_name();
let name = name.to_string_lossy();
self.write_wrapper_script(&name, &src_path).await
}
#[cfg(not(target_os = "windows"))]
async fn write_wrapper_script(&self, name: &str, path: &Path) -> MapperResult<()> {
fs::write(
path,
format!(
r#"#!/bin/sh
nenv exec {name} "$@""#
),
)
.await?;
let src_metadata = self.info.metadata().await?;
fs::set_permissions(&path, src_metadata.permissions()).await?;
Ok(())
}
#[cfg(target_os = "windows")]
async fn write_wrapper_script(&self, name: &str, path: &Path) -> MapperResult<()> {
fs::write(path, format!("nenv exec {name} %*")).await?;
fs::set_permissions(&path, src_metadata.permissions()).await?;
Ok(())
}
}
pub async fn map_node_bin(node_path: NodePath) -> MapperResult<()> {
let applications = get_applications(&node_path.bin()).await?;
let mapped_applications = get_applications(&*BIN_DIR).await?;
let mut new_mapped = HashSet::new();
for application in applications {
application.map_executable().await?;
new_mapped.insert(application.name());
}
for app in mapped_applications {
if !new_mapped.contains(&app.name()) {
app.unmap().await?;
}
}
Ok(())
}
async fn get_applications(path: &PathBuf) -> MapperResult<Vec<NodeApp>> {
let mut files = Vec::new();
let mut iter = fs::read_dir(path).await?;
while let Some(entry) = iter.next_entry().await? {
if entry.path().is_file() {
files.push(NodeApp::new(entry));
}
}
Ok(files)
}

@ -5,13 +5,11 @@ use crate::{
repository::{NodeVersion, Repository},
};
use self::{
error::{MapperError, MapperResult},
mapped_command::MappedCommand,
};
use self::{error::MapperError, mapped_command::MappedCommand, mapped_dir::map_node_bin};
pub mod error;
mod mapped_command;
mod mapped_dir;
/// Responsible for mapping to node executables
/// and managing node versions
pub struct Mapper {
@ -34,12 +32,13 @@ impl Mapper {
}
/// Sets the given version as the default one
pub async fn use_version(&mut self, version: &NodeVersion) -> MapperResult<()> {
pub async fn use_version(&mut self, version: &NodeVersion) -> LibResult<()> {
self.repo
.config
.set_default_version(version.clone())
.await?;
self.active_version = version.clone();
self.map_active_version().await?;
Ok(())
}
@ -50,6 +49,7 @@ impl Mapper {
/// Executes a mapped command with the given node environment
pub async fn exec(&self, command: String, args: Vec<OsString>) -> LibResult<ExitStatus> {
self.map_active_version().await?;
let node_path = self
.repo
.get_version_path(&self.active_version)
@ -69,4 +69,16 @@ impl Mapper {
.ok()
.and_then(|v| NodeVersion::from_str(&v).ok())
}
/// creates wrapper scripts for the current version
async fn map_active_version(&self) -> LibResult<()> {
let dir = self
.repo
.get_version_path(&self.active_version)
.await?
.expect("missing version");
map_node_bin(dir).await?;
Ok(())
}
}

@ -19,11 +19,11 @@ use crate::{
web_api::{VersionInfo, WebApi},
};
use self::{config::Config, node_paths::NodePath, versions::Versions};
use self::{config::Config, node_path::NodePath, versions::Versions};
pub mod config;
pub(crate) mod extract;
mod node_paths;
pub(crate) mod node_path;
pub mod versions;
#[derive(Clone, Debug)]

Loading…
Cancel
Save