Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement notion shim command #100

Merged
merged 9 commits into from
Jul 26, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion crates/notion-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,11 @@ pub mod monitor;
mod package_info;
pub mod path;
mod plugin;
pub mod shell;
pub mod project;
pub mod serial;
pub mod session;
pub mod shell;
pub mod shim;
pub mod style;
pub mod tool;

Expand Down
7 changes: 6 additions & 1 deletion crates/notion-core/src/path/unix.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
//! Provides functions for determining the paths of files and directories
//! in a standard Notion layout in Unix-based operating systems.

use std::env;
use std::{env, io};
use std::path::PathBuf;
use std::os::unix;

use notion_fail::{Fallible, NotionFail};

Expand Down Expand Up @@ -157,3 +158,7 @@ pub fn user_config_file() -> Fallible<PathBuf> {
pub fn user_catalog_file() -> Fallible<PathBuf> {
Ok(notion_home()?.join("catalog.toml"))
}

pub fn create_file_symlink(src: PathBuf, dst: PathBuf) -> Result<(), io::Error> {
unix::fs::symlink(src, dst)
}
6 changes: 6 additions & 0 deletions crates/notion-core/src/path/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
//! in a standard Notion layout in Windows operating systems.

use std::path::PathBuf;
use std::os::windows;
use std::io;

use winfolder;

Expand Down Expand Up @@ -154,3 +156,7 @@ pub fn user_config_file() -> Fallible<PathBuf> {
pub fn user_catalog_file() -> Fallible<PathBuf> {
Ok(local_data_root()?.join("catalog.toml"))
}

pub fn create_file_symlink(src: PathBuf, dst: PathBuf) -> Result<(), io::Error> {
windows::fs::symlink_file(src, dst)
}
2 changes: 2 additions & 0 deletions crates/notion-core/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ pub enum ActivityKind {
Help,
Version,
Binary,
Shim,
}

impl Display for ActivityKind {
Expand All @@ -48,6 +49,7 @@ impl Display for ActivityKind {
&ActivityKind::Help => "help",
&ActivityKind::Version => "version",
&ActivityKind::Binary => "binary",
&ActivityKind::Shim => "shim",
};
f.write_str(s)
}
Expand Down
13 changes: 9 additions & 4 deletions crates/notion-core/src/shell/bash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::path::{Path, PathBuf};
use super::{Postscript, Shell};

pub(crate) struct Bash {
pub(crate) postscript_path: PathBuf
pub(crate) postscript_path: PathBuf,
}

impl Shell for Bash {
Expand All @@ -17,9 +17,14 @@ impl Shell for Bash {
// ISSUE(#99): proper escaping
format!("export PATH='{}'\n", s)
}
&Postscript::ToolVersion { ref tool, ref version } => {
format!("export NOTION_{}_VERSION={}\n", tool.to_ascii_uppercase(), version)
}
&Postscript::ToolVersion {
ref tool,
ref version,
} => format!(
"export NOTION_{}_VERSION={}\n",
tool.to_ascii_uppercase(),
version
),
}
}
}
20 changes: 13 additions & 7 deletions crates/notion-core/src/shell/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::str::FromStr;

use semver::Version;

use notion_fail::{NotionError, NotionFail, Fallible, ResultExt};
use notion_fail::{Fallible, NotionError, NotionFail, ResultExt};

use env;

Expand All @@ -15,7 +15,7 @@ pub(crate) use self::bash::Bash;

pub enum Postscript {
Path(String),
ToolVersion { tool: String, version: Version }
ToolVersion { tool: String, version: Version },
}

/// Thrown when the postscript file was not specified in the Notion environment.
Expand All @@ -39,7 +39,8 @@ pub trait Shell {

fn save_postscript(&self, postscript: &Postscript) -> Fallible<()> {
let mut file = File::create(self.postscript_path()).unknown()?;
file.write_all(self.compile_postscript(postscript).as_bytes()).unknown()?;
file.write_all(self.compile_postscript(postscript).as_bytes())
.unknown()?;
Ok(())
}
}
Expand All @@ -64,7 +65,9 @@ impl CurrentShell {
pub fn detect() -> Fallible<Self> {
match env::shell_name() {
Some(name) => Ok(name.parse()?),
None => { throw!(UnspecifiedShellError); }
None => {
throw!(UnspecifiedShellError);
}
}
}
}
Expand All @@ -81,12 +84,11 @@ impl Shell for CurrentShell {
}
}


/// Thrown when the shell name specified in the Notion environment is not supported.
#[derive(Fail, Debug)]
#[fail(display = "Unrecognized command shell name: {}", name)]
struct UnrecognizedShellError {
name: String
name: String,
}

impl NotionFail for UnrecognizedShellError {
Expand All @@ -106,7 +108,11 @@ impl FromStr for CurrentShell {

Ok(CurrentShell(match src {
"bash" => Box::new(Bash { postscript_path }),
_ => { throw!(UnrecognizedShellError { name: src.to_string() }); }
_ => {
throw!(UnrecognizedShellError {
name: src.to_string()
});
}
}))
}
}
80 changes: 80 additions & 0 deletions crates/notion-core/src/shim.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
//! Provides utilities for modifying shims for 3rd-party executables

use std::{fs, io};

use notion_fail::{FailExt, Fallible, NotionFail};
use path;

#[derive(Fail, Debug)]
#[fail(display = "{}", error)]
pub(crate) struct SymlinkError {
error: String,
}

impl NotionFail for SymlinkError {
fn is_user_friendly(&self) -> bool {
true
}
fn exit_code(&self) -> i32 {
4
}
}

impl SymlinkError {
pub(crate) fn from_io_error(error: &io::Error) -> Self {
if let Some(inner_err) = error.get_ref() {
SymlinkError {
error: inner_err.to_string(),
}
} else {
SymlinkError {
error: error.to_string(),
}
}
}
}

fn is_3p_shim(name: &str) -> bool {
match name {
"node" | "yarn" | "npm" | "npx" => false,
_ => true,
}
}

pub fn create(shim_name: &str) -> Fallible<()> {
let launchbin = path::launchbin_file()?;
let shim = path::shim_file(shim_name)?;
match path::create_file_symlink(launchbin, shim) {
Ok(_) => Ok(()),
Err(err) => {
if err.kind() == io::ErrorKind::AlreadyExists {
throw!(SymlinkError {
error: format!("shim `{}` already exists", shim_name),
});
} else {
throw!(err.with_context(SymlinkError::from_io_error));
}
}
}
}

pub fn delete(shim_name: &str) -> Fallible<()> {
if !is_3p_shim(shim_name) {
throw!(SymlinkError {
error: format!("cannot delete `{}`, not a 3rd-party executable", shim_name),
});
}
let shim = path::shim_file(shim_name)?;
match fs::remove_file(shim) {
Ok(_) => Ok(()),
Err(err) => {
if err.kind() == io::ErrorKind::NotFound {
throw!(SymlinkError {
error: format!("shim `{}` does not exist", shim_name),
});
} else {
throw!(err.with_context(SymlinkError::from_io_error));
}
}
}
}
4 changes: 2 additions & 2 deletions src/command/deactivate.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use notion_core::env;
use notion_core::shell::{CurrentShell, Postscript, Shell};
use notion_core::session::{ActivityKind, Session};
use notion_core::shell::{CurrentShell, Postscript, Shell};
use notion_fail::Fallible;

use Notion;
Expand Down Expand Up @@ -47,7 +47,7 @@ Options:

let postscript = match env::path_for_system_node().into_string() {
Ok(path) => Postscript::Path(path),
Err(_) => unimplemented!()
Err(_) => unimplemented!(),
};

shell.save_postscript(&postscript)?;
Expand Down
4 changes: 3 additions & 1 deletion src/command/help.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use notion_core::session::{ActivityKind, Session};
use notion_fail::Fallible;

use command::{Command, CommandName, Config, Current, Deactivate, Default, Install, Uninstall, Use, Version};
use command::{Command, CommandName, Config, Current, Deactivate, Default, Install, Shim,
Uninstall, Use, Version};
use {CliParseError, Notion};

#[derive(Debug, Deserialize)]
Expand Down Expand Up @@ -63,6 +64,7 @@ Options:
Help::Command(CommandName::Version) => Version::USAGE,
Help::Command(CommandName::Install) => Install::USAGE,
Help::Command(CommandName::Uninstall) => Uninstall::USAGE,
Help::Command(CommandName::Shim) => Shim::USAGE,
}
);
session.add_event_end(ActivityKind::Help, 0);
Expand Down
5 changes: 5 additions & 0 deletions src/command/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ mod deactivate;
mod default;
mod help;
mod install;
mod shim;
mod uninstall;
mod use_;
mod version;
Expand All @@ -14,6 +15,7 @@ pub(crate) use self::deactivate::Deactivate;
pub(crate) use self::default::Default;
pub(crate) use self::help::Help;
pub(crate) use self::install::Install;
pub(crate) use self::shim::Shim;
pub(crate) use self::uninstall::Uninstall;
pub(crate) use self::use_::Use;
pub(crate) use self::version::Version;
Expand All @@ -39,6 +41,7 @@ pub(crate) enum CommandName {
Current,
Deactivate,
Default,
Shim,
Help,
Version,
}
Expand All @@ -56,6 +59,7 @@ impl Display for CommandName {
CommandName::Deactivate => "deactivate",
CommandName::Default => "default",
CommandName::Current => "current",
CommandName::Shim => "shim",
CommandName::Help => "help",
CommandName::Version => "version",
}
Expand All @@ -75,6 +79,7 @@ impl FromStr for CommandName {
"current" => CommandName::Current,
"deactivate" => CommandName::Deactivate,
"default" => CommandName::Default,
"shim" => CommandName::Shim,
"help" => CommandName::Help,
"version" => CommandName::Version,
_ => {
Expand Down
Loading