Skip to content

Commit

Permalink
Refactor into a library, use structopt for CLI handling (#172)
Browse files Browse the repository at this point in the history
  • Loading branch information
g-s-k authored and koute committed Feb 27, 2019
1 parent 2336e68 commit 6f1b72e
Show file tree
Hide file tree
Showing 10 changed files with 560 additions and 522 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ http = "0.1.13"
futures = "0.1.17"
open = "1"
failure = "0.1"
structopt = "0.2.14"

[dependencies.semver]
features = ["serde"]
Expand Down
175 changes: 86 additions & 89 deletions src/build.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use std::collections::HashMap;
use std::process::{Command, Stdio, exit};
use std::path::{Path, PathBuf};
use std::str::FromStr;
use std::env;

use clap;
use cargo_shim::{
Profile,
CargoPackage,
Expand All @@ -29,6 +29,10 @@ use wasm;

use wasm_runtime::RuntimeKind;

const ASMJS_UNKNOWN_EMSCRIPTEN: &str = "asmjs-unknown-emscripten";
const WASM32_UNKNOWN_EMSCRIPTEN: &str = "wasm32-unknown-emscripten";
const WASM32_UNKNOWN_UNKNOWN: &str = "wasm32-unknown-unknown";

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum PathKind {
File,
Expand All @@ -48,6 +52,22 @@ pub enum Backend {
WebAssembly
}

impl FromStr for Backend {
type Err = Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
WASM32_UNKNOWN_UNKNOWN => Ok(Backend::WebAssembly),
WASM32_UNKNOWN_EMSCRIPTEN => Ok(Backend::EmscriptenWebAssembly),
ASMJS_UNKNOWN_EMSCRIPTEN => Ok(Backend::EmscriptenAsmJs),
_ => Err(Error::ConfigurationError(format!(
"{} is not a valid target triple.",
s
))),
}
}
}

impl Backend {
pub fn is_emscripten_asmjs( self ) -> bool {
self == Backend::EmscriptenAsmJs
Expand All @@ -71,9 +91,9 @@ impl Backend {

pub fn triplet( &self ) -> &str {
match *self {
Backend::EmscriptenAsmJs => "asmjs-unknown-emscripten",
Backend::EmscriptenWebAssembly => "wasm32-unknown-emscripten",
Backend::WebAssembly => "wasm32-unknown-unknown"
Backend::EmscriptenAsmJs => ASMJS_UNKNOWN_EMSCRIPTEN,
Backend::EmscriptenWebAssembly => WASM32_UNKNOWN_EMSCRIPTEN,
Backend::WebAssembly => WASM32_UNKNOWN_UNKNOWN,
}
}
}
Expand All @@ -86,6 +106,28 @@ enum TargetName {
Bench( String )
}

impl TargetName {
pub fn from(t: super::Target) -> Option<Self> {
if t.lib {
return Some(TargetName::Lib);
}

if let Some(bin) = t.bin {
return Some(TargetName::Bin(bin));
}

if let Some(example) = t.example {
return Some(TargetName::Example(example));
}

if let Some(bench) = t.bench {
return Some(TargetName::Bench(bench));
}

None
}
}

#[derive(Clone)]
pub struct BuildArgs {
features: Vec< String >,
Expand All @@ -112,95 +154,50 @@ pub struct AggregatedConfig {
pub prepend_js: Vec< (PathBuf, String) >
}

impl BuildArgs {
pub fn new( matches: &clap::ArgMatches ) -> Result< Self, Error > {
let features = if let Some( features ) = matches.value_of( "features" ) {
features.split_whitespace().map( |feature| feature.to_owned() ).collect()
} else {
Vec::new()
};

let no_default_features = matches.is_present( "no-default-features" );
let enable_all_features = matches.is_present( "all-features" );

let build_type = if matches.is_present( "release" ) {
BuildType::Release
} else {
BuildType::Debug
};

let use_system_emscripten = matches.is_present( "use-system-emscripten" );
let is_verbose = matches.is_present( "verbose" );
let message_format = if let Some( name ) = matches.value_of( "message-format" ) {
match name {
"human" => MessageFormat::Human,
"json" => MessageFormat::Json,
_ => unreachable!()
}
} else {
MessageFormat::Human
};

let backend = if matches.is_present( "target-webasm-emscripten" ) {
eprintln!( "warning: `--target-webasm-emscripten` argument is deprecated; please use `--target wasm32-unknown-emscripten` instead" );
Some( Backend::EmscriptenWebAssembly )
} else if matches.is_present( "target-webasm" ) {
eprintln!( "warning: `--target-webasm` argument is deprecated; please use `--target wasm32-unknown-unknown` instead" );
Some( Backend::WebAssembly )
} else if matches.is_present( "target-asmjs-emscripten" ) {
eprintln!( "warning: `--target-asmjs-emscripten` argument is deprecated; please use `--target asmjs-unknown-emscripten` instead" );
Some( Backend::EmscriptenAsmJs )
} else if let Some( triplet ) = matches.value_of( "target" ) {
let backend = match triplet {
"asmjs-unknown-emscripten" => Backend::EmscriptenAsmJs,
"wasm32-unknown-emscripten" => Backend::EmscriptenWebAssembly,
"wasm32-unknown-unknown" => Backend::WebAssembly,
_ => unreachable!( "Unknown target: {:?}", triplet )
};

Some( backend )
} else {
None
};
impl From<super::Build> for BuildArgs {
fn from(b: super::Build) -> Self {
Self {
features: b.features.unwrap_or_default().split(' ').map(String::from).collect(),
no_default_features: b.no_default_features,
enable_all_features: b.all_features,
build_type: if b.release { BuildType::Release } else { BuildType::Debug },
use_system_emscripten: b.use_system_emscripten,
is_verbose: b.verbose,
message_format: MessageFormat::Human,
backend: b.target,
runtime: RuntimeKind::Standalone,
package_name: b.package,
target_name: None,
}
}
}

let runtime = if let Some( runtime ) = matches.value_of( "runtime" ) {
match runtime {
"standalone" => RuntimeKind::Standalone,
"library-es6" => RuntimeKind::LibraryEs6,
"web-extension" => RuntimeKind::WebExtension,
"experimental-only-loader" => RuntimeKind::OnlyLoader,
_ => unreachable!( "Unknown runtime: {:?}", runtime )
impl BuildArgs {
pub(crate) fn new(build: super::Build, ext: super::BuildExt, target: super::Target) -> Result<Self, Error> {
let mut out = Self::from(build).with_target(target);
out.message_format = ext.message_format;

if let Some(rt) = ext.runtime {
match out.backend {
None | Some(Backend::WebAssembly) => {
out.runtime = rt;
}
Some(be) => {
return Err(Error::ConfigurationError(format!(
"JavaScript runtime can only be specified for target `{}`. (Current target is `{}`)",
WASM32_UNKNOWN_UNKNOWN,
be.triplet()
)));
}
}
} else {
RuntimeKind::Standalone
};
}

let package_name = matches.value_of( "package" ).map( |name| name.to_owned() );
let target_name = if matches.is_present( "lib" ) {
Some( TargetName::Lib )
} else if let Some( name ) = matches.value_of( "bin" ) {
Some( TargetName::Bin( name.to_owned() ) )
} else if let Some( name ) = matches.value_of( "example" ) {
Some( TargetName::Example( name.to_owned() ) )
} else if let Some( name ) = matches.value_of( "bench" ) {
Some( TargetName::Bench( name.to_owned() ) )
} else {
None
};
Ok(out)
}

Ok( BuildArgs {
features,
no_default_features,
enable_all_features,
build_type,
use_system_emscripten,
is_verbose,
message_format,
backend,
runtime,
package_name,
target_name
})
pub(crate) fn with_target(mut self, target: super::Target) -> Self {
self.target_name = TargetName::from(target);
self
}

pub fn load_project( &self ) -> Result< Project, Error > {
Expand Down
24 changes: 22 additions & 2 deletions src/cargo_shim/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::ops::Deref;
use std::cell::Cell;
use std::env;
use std::thread;
use std::str;
use std::str::{self, FromStr};
use std::error;
use std::fmt;

Expand Down Expand Up @@ -525,7 +525,24 @@ impl BuildTarget {
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum MessageFormat {
Human,
Json
Json,
#[doc(hidden)]
__Nonexhaustive,
}

impl FromStr for MessageFormat {
type Err = super::Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"human" => Ok(MessageFormat::Human),
"json" => Ok(MessageFormat::Json),
_ => Err(super::Error::ConfigurationError(format!(
"{} is not a valid message format. Possible values are `human` and `json`.",
s
))),
}
}
}

#[derive(Clone, Debug)]
Expand Down Expand Up @@ -778,6 +795,7 @@ impl BuildConfig {
MessageFormat::Json => {
println!( "{}", serde_json::to_string( &message.to_json_value() ).unwrap() );
}
MessageFormat::__Nonexhaustive => unreachable!(),
}
},
CargoOutput::Artifact( artifact ) => {
Expand All @@ -793,6 +811,7 @@ impl BuildConfig {
MessageFormat::Json => {
println!( "{}", serde_json::to_string( &executed.to_json_value() ).unwrap() );
}
MessageFormat::__Nonexhaustive => unreachable!(),
}
}
}
Expand Down Expand Up @@ -877,6 +896,7 @@ impl BuildConfig {
MessageFormat::Json => {
println!( "{}", serde_json::to_string( &artifact.to_json_value() ).unwrap() );
}
MessageFormat::__Nonexhaustive => unreachable!(),
}

for filename in artifact.filenames {
Expand Down
13 changes: 5 additions & 8 deletions src/cmd_build.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use clap;

use cargo_shim::{
Profile,
TargetKind
Expand All @@ -8,8 +6,7 @@ use cargo_shim::{
use build::BuildArgs;
use error::Error;

fn command_build_or_check< 'a >( matches: &clap::ArgMatches< 'a >, should_build: bool ) -> Result< (), Error > {
let build_args = BuildArgs::new( matches )?;
pub fn command_build_or_check(build_args: BuildArgs, should_build: bool) -> Result<(), Error> {
let project = build_args.load_project()?;

let targets = project.target_or_select( |target| {
Expand All @@ -28,10 +25,10 @@ fn command_build_or_check< 'a >( matches: &clap::ArgMatches< 'a >, should_build:
Ok(())
}

pub fn command_build< 'a >( matches: &clap::ArgMatches< 'a > ) -> Result< (), Error > {
command_build_or_check( matches, true )
pub fn command_build(args: BuildArgs) -> Result<(), Error> {
command_build_or_check(args, true)
}

pub fn command_check< 'a >( matches: &clap::ArgMatches< 'a > ) -> Result< (), Error > {
command_build_or_check( matches, false )
pub fn command_check(args: BuildArgs) -> Result<(), Error> {
command_build_or_check(args, false)
}
6 changes: 1 addition & 5 deletions src/cmd_deploy.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
use std::fs;
use std::path::PathBuf;

use clap;

use cargo_shim::{
Profile,
TargetKind
Expand All @@ -12,8 +10,7 @@ use build::BuildArgs;
use deployment::Deployment;
use error::Error;

pub fn command_deploy< 'a >( matches: &clap::ArgMatches< 'a > ) -> Result< (), Error > {
let build_args = BuildArgs::new( matches )?;
pub fn command_deploy(build_args: BuildArgs, directory: Option<PathBuf>) -> Result<(), Error> {
let project = build_args.load_project()?;

let package = project.package();
Expand All @@ -35,7 +32,6 @@ pub fn command_deploy< 'a >( matches: &clap::ArgMatches< 'a > ) -> Result< (), E
let result = project.build( &config, target )?;

let deployment = Deployment::new( package, target, &result )?;
let directory = matches.value_of( "output" ).map( PathBuf::from );

let is_using_default_directory;
let directory = match directory {
Expand Down
Loading

0 comments on commit 6f1b72e

Please sign in to comment.