diff --git a/.ci_helper.sh b/.ci_helper.sh deleted file mode 100755 index feaddfc..0000000 --- a/.ci_helper.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -set -e - -PROJECT_NAME="hatch"; - -cd $PROJECT_NAME; - -cargo build --verbose --all -cargo test --verbose --all diff --git a/.ci_helpers/appveyor_helper.bat b/.ci_helpers/appveyor_helper.bat new file mode 100644 index 0000000..df54af1 --- /dev/null +++ b/.ci_helpers/appveyor_helper.bat @@ -0,0 +1,4 @@ +cd "hatch" + +cargo build --verbose --all +cargo test --verbose --all diff --git a/.coveralls.yml b/.coveralls.yml new file mode 100644 index 0000000..e69de29 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9f11b75 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea/ diff --git a/.travis.yml b/.travis.yml index e611baf..ed95e5d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,45 @@ -lanugage: rust +sudo: required + +language: rust + +addons: + apt: + packages: + - libssl-dev + cache: cargo + +rust: + - stable + - nightly + +# load travis-cargo +before_script: + - export PATH=$HOME/.cargo/bin:$PATH + - cargo install cargo-update || echo "cargo-update already installed" + - cargo install-update -a # update outdated cached binaries + +os: + - linux + - osx + script: - - ./.ci_helper.sh + - | + cd hatch && + cargo clean && + cargo build && + cargo test + +after_success: + - | + if [[ "$TRAVIS_OS_NAME" == "linux" && "$TRAVIS_RUST_VERSION" == "stable" ]]; then + bash <(curl https://raw.githubusercontent.com/xd009642/tarpaulin/master/travis-install.sh) + cargo tarpaulin --ciserver travis-ci --coveralls $TRAVIS_JOB_ID; + fi + branches: # This is where pull requests from "bors r+" are built. - staging # This is where pull requests from "bors try" are built. - trying + - dev diff --git a/README.md b/README.md index 3438bd3..c62d991 100644 --- a/README.md +++ b/README.md @@ -3,12 +3,35 @@

Hatch

The project manager for CachedNerds/Toolbox et;al

+

+ +
+ + + + + + + + + + + + + +
Master
Dev
+
+ +# [Workflow Standards](https://github.com/CachedNerds/Hatch/blob/master/WORKFLOW.md) + # Usage # Technologies # Contributing +Please follow the [Style Guide](STYLE.md) when contributing. + # Code of conduct # License diff --git a/STYLE.md b/STYLE.md new file mode 100644 index 0000000..39dafec --- /dev/null +++ b/STYLE.md @@ -0,0 +1,94 @@ +

Rust Style Guide

+ +*Please write good Rust.* + +## Table of Contents + +1. [Unsafe](#unsafe) +2. [Whitespace](#whitespace) +3. [Dereferences](#dereferences) +4. [Use Statements](#use_statements) + + +## Unsafe + +No use of the `unsafe` keyword is allowed. This guideline is statically enforced. + +## Whitespace + +All curly brace blocks will have at least one line return between the opening brace and the closing brace. The opening +curly brace of keyword blocks (e.g. `impl`) will be placed on the same line as the keyword. + +##### Bad +```rust +impl Project { pub fn new() -> Project { ... } } +``` + +##### Good +```rust +impl Project { + pub fn new() -> Project { + ... + } +} +``` + +All `else` and `else if` blocks will begin on the same line as the previous closing curly brace. + +##### Bad +```rust +if arg.is_present("bin") { ... } +else if arg.is_present("static") { ... } +else { ... } +``` + +##### Good +```rust +if arg.is_present("bin") { + ... +} else if arg.is_present("static") { + ... +} else { + ... +} +``` + +## Dereferences + +When `y` is a reference, the asterisk operator used to _dereference_ `y` should +contain no whitespace between the operator and the reference. + +##### Bad + +```rust +match * y { + ... +} +``` + +##### Good + +```rust +match *y { + ... +} +``` + +When `*y` is a reference the same styling as above should be used. + +## Use Statements + +When importing names from a module, only use the bracket notation when importing multiple names. + +##### Bad + +```rust +use project::{ Project }; +``` + +##### Good + +```rust +use project::Project; +use Foo::{ Bar, Baz }; +``` diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..c1a99f5 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,69 @@ +# Appveyor configuration template for Rust using rustup for Rust installation +# https://github.com/starkat99/appveyor-rust + +## Operating System (VM environment) ## + +# Rust needs at least Visual Studio 2013 Appveyor OS for MSVC targets. +os: Visual Studio 2015 + +## Build Matrix ## + +# This configuration will setup a build for each channel & target combination (12 windows +# combinations in all). +# +# There are 3 channels: stable, beta, and nightly. +# +# Alternatively, the full version may be specified for the channel to build using that specific +# version (e.g. channel: 1.5.0) +# +# The values for target are the set of windows Rust build targets. Each value is of the form +# +# ARCH-pc-windows-TOOLCHAIN +# +# Where ARCH is the target architecture, either x86_64 or i686, and TOOLCHAIN is the linker +# toolchain to use, either msvc or gnu. See https://www.rust-lang.org/downloads.html#win-foot for +# a description of the toolchain differences. +# See https://github.com/rust-lang-nursery/rustup.rs/#toolchain-specification for description of +# toolchains and host triples. +# +# Comment out channel/target combos you do not wish to build in CI. +# +# You may use the `cargoflags` and `RUSTFLAGS` variables to set additional flags for cargo commands +# and rustc, respectively. For instance, you can uncomment the cargoflags lines in the nightly +# channels to enable unstable features when building for nightly. Or you could add additional +# matrix entries to test different combinations of features. +environment: + matrix: + +### MSVC Toolchains ### + + # Stable 64-bit MSVC + - channel: stable + target: x86_64-pc-windows-msvc + +## Install Script ## + +# This is the most important part of the Appveyor configuration. This installs the version of Rust +# specified by the 'channel' and 'target' environment variables from the build matrix. This uses +# rustup to install Rust. +# +# For simple configurations, instead of using the build matrix, you can simply set the +# default-toolchain and default-host manually here. +install: + - appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe + - rustup-init -yv --default-toolchain %channel% --default-host %target% + - set PATH=%PATH%;%USERPROFILE%\.cargo\bin + - rustc -vV + - cargo -vV + +## Build Script ## + +# 'cargo test' takes care of building for us, so disable Appveyor's build stage. This prevents +# the "directory does not contain a project or solution file" error. +build: false + +# Uses 'cargo test' to run tests and build. Alternatively, the project may call compiled programs +#directly or perform other testing commands. Rust will automatically be placed in the PATH +# environment variable. +test_script: + - .ci_helpers/appveyor_helper.bat diff --git a/hatch/Cargo.lock b/hatch/Cargo.lock index 317da18..1a89bac 100644 --- a/hatch/Cargo.lock +++ b/hatch/Cargo.lock @@ -1,63 +1,616 @@ -[root] +[[package]] +name = "adler32" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "aho-corasick" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ansi_term" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "atty" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", + "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "backtrace" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "backtrace-sys" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "base64" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bitflags" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "bitflags" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "build_const" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "byteorder" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "bytes" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cc" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cfg-if" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "clap" +version = "2.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cmake" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "core-foundation" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "core-foundation-sys" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crc" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "build_const 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "curl-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", + "libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.23 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "dtoa" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "failure" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "failure_derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "fuchsia-zircon" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fuchsia-zircon-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-cpupool" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "git2" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", + "libgit2-sys 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.23 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "hatch" version = "0.1.0" dependencies = [ - "clap 2.26.2 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "git2 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "os_info 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", + "yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "httparse" +version = "1.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "hyper" +version = "0.11.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "base64 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "relay 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-proto 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hyper-tls" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.11.15 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tls 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "idna" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "iovec" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "itoa" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "language-tags" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "lazy_static" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "lazy_static" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "lazycell" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.2.35" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libflate" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "adler32 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crc 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libgit2-sys" +version = "0.6.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "curl-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", + "libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.23 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libssh2-sys" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", + "libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.23 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libz-sys" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "log" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "log" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "matches" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "memchr" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "mime" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "mime_guess" +version = "2.0.0-alpha.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "mime 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "mio" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "miow" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "native-tls" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.9.23 (registry+https://github.com/rust-lang/crates.io-index)", + "schannel 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "net2" +version = "0.2.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-traits" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "num_cpus" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "openssl" +version = "0.9.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.23 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "ansi_term" -version = "0.9.0" +name = "openssl-probe" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "atty" -version = "0.2.3" +name = "openssl-sys" +version = "0.9.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "os_info" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", - "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "bitflags" -version = "0.9.1" +name = "percent-encoding" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "clap" -version = "2.26.2" +name = "phf" +version = "0.7.21" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "textwrap 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "kernel32-sys" -version = "0.2.2" +name = "phf_codegen" +version = "0.7.21" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "libc" -version = "0.2.32" +name = "phf_generator" +version = "0.7.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "phf_shared" +version = "0.7.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pkg-config" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "quote" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rand" +version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "redox_syscall" -version = "0.1.31" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -65,22 +618,191 @@ name = "redox_termios" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex-syntax" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "relay" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "reqwest" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.11.15 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libflate 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "mime_guess 2.0.0-alpha.3 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_urlencoded 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tls 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "safemem" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "schannel" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "scoped-tls" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "security-framework" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "core-foundation 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "security-framework-sys" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde_json" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "serde_urlencoded" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "siphasher" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "slab" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "slab" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "smallvec" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "strsim" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "term_size" -version = "0.3.0" +name = "syn" +version = "0.11.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "synom" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "synstructure" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "take" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "tempdir" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -88,54 +810,365 @@ name = "termion" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "textwrap" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "thread_local" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "time" +version = "0.1.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-core" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-io" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-proto" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-service" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-tls" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicase" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicase" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-normalization" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "unicode-width" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "unicode-xid" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unreachable" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "url" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "user32-sys" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "utf8-ranges" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "uuid" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "vcpkg" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "vec_map" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "version_check" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "winapi" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "winapi" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "winapi-build" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "ws2_32-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "yaml-rust" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + [metadata] -"checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6" -"checksum atty 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21e50800ec991574876040fff8ee46b136a53e985286fbe6a3bdfe6421b78860" +"checksum adler32 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6cbd0b9af8587c72beadc9f72d35b9fbb070982c9e6203e46e93f10df25f8f45" +"checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4" +"checksum ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b3568b48b7cefa6b8ce125f9bb4989e52fbcc29ebea88df04cc7c5f12f70455" +"checksum atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8352656fd42c30a0c3c89d26dea01e3b77c0ab2af18230835c15e2e13cd51859" +"checksum backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbbf59b1c43eefa8c3ede390fcc36820b4999f7914104015be25025e0d62af2" +"checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661" +"checksum base64 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "229d032f1a99302697f10b27167ae6d03d49d032e6a8e2550e8d3fc13356d2b4" "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" -"checksum clap 2.26.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3451e409013178663435d6f15fdb212f14ee4424a3d74f979d081d0a66b6f1f2" +"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" +"checksum build_const 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e90dc84f5e62d2ebe7676b83c22d33b6db8bd27340fb6ffbff0a364efa0cb9c9" +"checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23" +"checksum bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1b7db437d718977f6dc9b2e3fd6fc343c02ac6b899b73fdd2179163447bd9ce9" +"checksum cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "deaf9ec656256bb25b404c51ef50097207b9cbb29c933d31f92cae5a8a0ffee0" +"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" +"checksum clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "110d43e343eb29f4f51c1db31beb879d546db27998577e5715270a54bcf41d3f" +"checksum cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "56d741ea7a69e577f6d06b36b7dff4738f680593dc27a701ffa8506b73ce28bb" +"checksum core-foundation 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25bfd746d203017f7d5cbd31ee5d8e17f94b6521c7af77ece6c9e4b2d4b16c67" +"checksum core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "065a5d7ffdcbc8fa145d6f0746f3555025b9097a9e9cda59f7467abae670c78d" +"checksum crc 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd5d02c0aac6bd68393ed69e00bbc2457f3e89075c6349db7189618dc4ddc1d7" +"checksum curl-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46e49c7125131f5afaded06944d6888b55cbdf8eba05dae73c954019b907961" +"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" +"checksum failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "934799b6c1de475a012a02dab0ace1ace43789ee4b99bcfbf1a2e3e8ced5de82" +"checksum failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c7cdda555bb90c9bb67a3b670a0f42de8e73f5981524123ad8578aafec8ddb8b" +"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +"checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" +"checksum futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0bab5b5e94f5c31fc764ba5dd9ad16568aae5d4825538c01d6bca680c9bf94a7" +"checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" +"checksum git2 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ee5b4bb7cd2a44e6e5ee3a26ba6a9ca10d4ce2771cdc3839bbc54b47b7d1be84" +"checksum httparse 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2f407128745b78abc95c0ffbe4e5d37427fdc0d45470710cfef8c44522a2e37" +"checksum hyper 0.11.15 (registry+https://github.com/rust-lang/crates.io-index)" = "4d6105c5eeb03068b10ff34475a0d166964f98e7b9777cc34b342a225af9b87c" +"checksum hyper-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c81fa95203e2a6087242c38691a0210f23e9f3f8f944350bd676522132e2985" +"checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d" +"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" +"checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum libc 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)" = "56cce3130fd040c28df6f495c8492e5ec5808fb4c9093c310df02b0c8f030148" -"checksum redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "8dde11f18c108289bef24469638a04dce49da56084f2d50618b226e47eb04509" +"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" +"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" +"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" +"checksum lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a6f08839bc70ef4a3fe1d566d5350f519c5912ea86be0df1740a7d247c7fc0ef" +"checksum libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)" = "96264e9b293e95d25bfcbbf8a88ffd1aedc85b754eba8b7d78012f638ba220eb" +"checksum libflate 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "1a429b86418868c7ea91ee50e9170683f47fd9d94f5375438ec86ec3adb74e8e" +"checksum libgit2-sys 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6eeae66e7b1c995de45cb4e65c5ab438a96a7b4077e448645d4048dc753ad357" +"checksum libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0db4ec23611747ef772db1c4d650f8bd762f07b461727ec998f953c614024b75" +"checksum libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "87f737ad6cc6fd6eefe3d9dc5412f1573865bded441300904d2f42269e140f16" +"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" +"checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2" +"checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" +"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" +"checksum mime 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e2e00e17be181010a91dbfefb01660b17311059dc8c7f48b9017677721e732bd" +"checksum mime_guess 2.0.0-alpha.3 (registry+https://github.com/rust-lang/crates.io-index)" = "013572795763289e14710c7b279461295f2673b2b338200c235082cd7ca9e495" +"checksum mio 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "75f72a93f046f1517e3cfddc0a096eb756a2ba727d36edc8227dee769a50a9b0" +"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" +"checksum native-tls 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f74dbadc8b43df7864539cedb7bc91345e532fdd913cfdc23ad94f4d2d40fbc0" +"checksum net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "3a80f842784ef6c9a958b68b7516bc7e35883c614004dd94959a4dca1b716c09" +"checksum num-traits 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "9936036cc70fe4a8b2d338ab665900323290efb03983c86cbe235ae800ad8017" +"checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" +"checksum openssl 0.9.23 (registry+https://github.com/rust-lang/crates.io-index)" = "169a4b9160baf9b9b1ab975418c673686638995ba921683a7f1e01470dcb8854" +"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" +"checksum openssl-sys 0.9.23 (registry+https://github.com/rust-lang/crates.io-index)" = "2200ffec628e3f14c39fc0131a301db214f1a7d584e36507ee8700b0c7fb7a46" +"checksum os_info 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "476978c9c7ae859d53a97fbbbdb7e7097b823c43c6abc8f33bf262249f41f617" +"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" +"checksum phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "cb325642290f28ee14d8c6201159949a872f220c62af6e110a56ea914fbe42fc" +"checksum phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d62594c0bb54c464f633175d502038177e90309daf2e0158be42ed5f023ce88f" +"checksum phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6b07ffcc532ccc85e3afc45865469bf5d9e4ef5bfcf9622e3cfe80c2d275ec03" +"checksum phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "07e24b0ca9643bdecd0632f2b3da6b1b89bbb0030e0b992afc1113b23a7bc2f2" +"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903" +"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" +"checksum rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)" = "512870020642bb8c221bf68baa1b2573da814f6ccfe5c9699b1c303047abe9b1" +"checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" +"checksum regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "744554e01ccbd98fff8c457c3b092cd67af62a555a43bfe97ae8a0451f7799fa" +"checksum regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8e931c58b93d86f080c734bfd2bce7dd0079ae2331235818133c8be7f422e20e" +"checksum relay 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f301bafeb60867c85170031bdb2fcf24c8041f33aee09e7b116a58d4e9f781c5" +"checksum reqwest 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)" = "449c45f593ce9af9417c91e22f274fb8cea013bcf3d37ec1b5fb534b623bc708" +"checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e" +"checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" +"checksum schannel 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "acece75e0f987c48863a6c792ec8b7d6c4177d4a027f8ccc72f849794f437016" +"checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d" +"checksum security-framework 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "dfa44ee9c54ce5eecc9de7d5acbad112ee58755239381f687e564004ba4a2332" +"checksum security-framework-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "5421621e836278a0b139268f36eee0dc7e389b784dc3f79d8f11aabadf41bead" +"checksum serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "db99f3919e20faa51bb2996057f5031d8685019b5a06139b1ce761da671b8526" +"checksum serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c9db7266c7d63a4c4b7fe8719656ccdd51acf1bed6124b174f933b009fb10bcb" +"checksum serde_urlencoded 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce0fd303af908732989354c6f02e05e2e6d597152870f2c6990efb0577137480" +"checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537" +"checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" +"checksum slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdeff4cd9ecff59ec7e3744cbca73dfe5ac35c2aedb2cfba8a1c715a18912e9d" +"checksum smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c8cbcd6df1e117c2210e13ab5109635ad68a929fcbb8964dc965b76cb5ee013" "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694" -"checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209" +"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" +"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" +"checksum synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a761d12e6d8dcb4dcf952a7a89b475e3a9d69e4a69307e01a470977642914bd" +"checksum take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b157868d8ac1f56b64604539990685fa7611d8fa9e5476cf0c02cf34d32917c5" +"checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" -"checksum textwrap 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df8e08afc40ae3459e4838f303e465aa50d823df8d7f83ca88108f6d3afe7edd" +"checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693" +"checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" +"checksum time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "a15375f1df02096fb3317256ce2cee6a1f42fc84ea5ad5fc8c421cfe40c73098" +"checksum tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "52b4e32d8edbf29501aabb3570f027c6ceb00ccef6538f4bddba0200503e74e8" +"checksum tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "514aae203178929dbf03318ad7c683126672d4d96eccb77b29603d33c9e25743" +"checksum tokio-proto 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fbb47ae81353c63c487030659494b295f6cb6576242f907f203473b191b0389" +"checksum tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24da22d077e0f15f55162bdbdc661228c1581892f52074fb242678d015b45162" +"checksum tokio-tls 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "772f4b04e560117fe3b0a53e490c16ddc8ba6ec437015d91fa385564996ed913" +"checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" +"checksum unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "284b6d3db520d67fbe88fd778c21510d1b0ba4a551e5d0fbb023d33405f6de8a" +"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" +"checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f" "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" +"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" +"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +"checksum url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa35e768d4daf1d85733418a49fb42e10d7f633e394fccab4ab7aba897053fe2" +"checksum user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ef4711d107b21b410a3a974b1204d9accc8b10dad75d8324b5d755de1617d47" +"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" +"checksum uuid 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcc7e3b898aa6f6c08e5295b6c89258d1331e9ac578cc992fb818759951bdc22" +"checksum vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9e0a7d8bed3178a8fb112199d466eeca9ed09a14ba8ad67718179b4fd5487d0b" "checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c" +"checksum version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6b772017e347561807c1aa192438c5fd74242a670a6cffacc40f2defd1dc069d" +"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" +"checksum winapi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b09fb3b6f248ea4cd42c9a65113a847d612e17505d6ebd1f7357ad68a8bf8693" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" +"checksum winapi-i686-pc-windows-gnu 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ec6667f60c23eca65c561e63a13d81b44234c2e38a6b6c959025ee907ec614cc" +"checksum winapi-x86_64-pc-windows-gnu 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "98f12c52b2630cd05d2c3ffd8e008f7f48252c042b4871c72aed9dc733b96668" +"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +"checksum yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992" diff --git a/hatch/Cargo.toml b/hatch/Cargo.toml index 251da4c..ae44237 100644 --- a/hatch/Cargo.toml +++ b/hatch/Cargo.toml @@ -5,3 +5,8 @@ authors = ["technetos "] [dependencies] clap = "2" +yaml-rust = "0.3" +git2 = "0.6" +failure = "0.1.1" +os_info = "0.7.0" +reqwest = "0.8.4" diff --git a/hatch/src/asset.rs b/hatch/src/asset.rs deleted file mode 100644 index bfda86a..0000000 --- a/hatch/src/asset.rs +++ /dev/null @@ -1,15 +0,0 @@ -use dtl::asset as asset_imp; -use dtl::asset::{ AssetKind }; - -#[derive(Debug)] -pub struct Asset(asset_imp::AssetBuilder); - -impl Asset { - pub fn new() -> Asset { - Asset(asset_imp::AssetBuilder::new()) - } - - pub fn assets(&mut self) -> &Vec { - self.0.assets() - } -} diff --git a/hatch/src/assets/builder.rs b/hatch/src/assets/builder.rs new file mode 100644 index 0000000..78fe6c8 --- /dev/null +++ b/hatch/src/assets/builder.rs @@ -0,0 +1,160 @@ +use assets::{ TupKind, PlatformKind, ProjectAsset }; +use assets::config::Config; +use assets::tuprules::Tuprules; +use assets::test_tupfile::Tupfile as TestTupfile; +use assets::tupfile::Tupfile; +use assets::platform::{ Linux, MacOS, Windows }; +use assets::tupfile_ini::TupfileIni; +use assets::catch_header::CatchHeader; +use assets::catch_definition::CatchDefinition; +use hatch_error::{ HatchResult, ResultExt, NullError }; +use project::Project; +use platform::os; +use reqwest; + +static CATCH_HEADER_URL: &str = "https://github.com/catchorg/Catch2/releases/download/v2.1.1/catch.hpp"; + +pub struct Builder { + assets: Vec, +} + +impl Builder { + pub fn new() -> Builder { + Builder { assets: Vec::new() } + } + + pub fn from(project: &Project) -> Builder { + let mut builder = Builder::new(); + + builder.project(&TupKind::Config, project); + builder.project(&TupKind::TestTupfile, project); + builder.project(&TupKind::Tuprules, project); + builder.project(&TupKind::Tupfile, project); + builder.project(&TupKind::TupfileIni, project); + + let platform_type = os::platform_type(); + builder.platform(&platform_type, project); + + if let Ok(catch_header) = builder.catch_header(project) { + builder.add_asset(catch_header); + } + + let catch_definition = builder.catch_definition(project); + builder.add_asset(catch_definition); + + builder + } + + pub fn assets(&mut self) -> &Vec { + &self.assets.as_ref() + } + + pub fn add_asset(&mut self, asset: ProjectAsset) { + self.assets.push(asset); + } + + pub fn project(&mut self, asset_kind: &TupKind, project: &Project) { + let asset = match *asset_kind { + TupKind::Config => self.config(project), + TupKind::TestTupfile => self.test_tupfile(project), + TupKind::Tuprules => self.tuprules(project), + TupKind::Tupfile => self.tupfile(project), + TupKind::TupfileIni => self.tupfile_ini(project), + }; + + self.assets.push(asset); + } + + pub fn platform(&mut self, asset_kind: &PlatformKind, project: &Project) { + let asset = match *asset_kind { + PlatformKind::Linux => self.linux(project), + PlatformKind::MacOS => self.macos(project), + PlatformKind::Windows => self.windows(project) + }; + + self.assets.push(asset); + } + + pub fn config(&self, project: &Project) -> ProjectAsset { + let project_path = project.path(); + let contents = Config::new(project.name(), project.config().kind()).to_string(); + + ProjectAsset::new(project_path.to_path_buf(), Config::name(), contents) + } + + pub fn test_tupfile(&self, project: &Project) -> ProjectAsset { + let asset_path = project.path().join("test"); + let contents = TestTupfile::new().to_string(); + + ProjectAsset::new(asset_path, TestTupfile::name(), contents) + } + + pub fn tuprules(&self, project: &Project) -> ProjectAsset { + let project_path = project.path(); + let config = project.config(); + let contents = Tuprules::new(config).to_string(); + + ProjectAsset::new(project_path.to_path_buf(), Tuprules::name(), contents) + } + + pub fn tupfile(&self, project: &Project) -> ProjectAsset { + let project_path = project.path(); + let contents = Tupfile::new(project.config().kind()).to_string(); + + ProjectAsset::new(project_path.to_path_buf(), Tupfile::name(), contents) + } + + pub fn tupfile_ini(&self, project: &Project) -> ProjectAsset { + let project_path = project.path(); + let contents = TupfileIni::new().to_string(); + + ProjectAsset::new(project_path.to_path_buf(), TupfileIni::name(), contents) + } + + pub fn linux(&self, project: &Project) -> ProjectAsset { + let project_path = project.path(); + let contents = Linux::new().to_string(); + + ProjectAsset::new(project_path.to_path_buf(), Linux::name(), contents) + } + + pub fn macos(&self, project: &Project) -> ProjectAsset { + let project_path = project.path(); + let contents = MacOS::new().to_string(); + + ProjectAsset::new(project_path.to_path_buf(), MacOS::name(), contents) + } + + pub fn windows(&self, project: &Project) -> ProjectAsset { + let project_path = project.path(); + let contents = Windows::new().to_string(); + + ProjectAsset::new(project_path.to_path_buf(), Windows::name(), contents) + } + + pub fn catch_header(&self, project: &Project) -> HatchResult { + let test_src_path = project.path().join("test/src"); + let file_name = CatchHeader::name(); + if !test_src_path.join(file_name).exists() { + let res = (|| -> HatchResult { + let mut resp = reqwest::get(CATCH_HEADER_URL)?; + let content = resp.text()?; + + Ok(ProjectAsset::new(test_src_path, CatchHeader::name(), content)) + })().with_context(|e| { + format!("failed to generate catch.hpp : {}", e) + })?; + + Ok(res) + } else { + Err(NullError)? + } + } + + pub fn catch_definition(&self, project: &Project) -> ProjectAsset { + let test_src_path = project.path().join("test/src"); + let contents = CatchDefinition::new().to_string(); + + ProjectAsset::new(test_src_path, CatchDefinition::name(), contents) + } +} diff --git a/hatch/src/assets/catch_definition.rs b/hatch/src/assets/catch_definition.rs new file mode 100644 index 0000000..bcce0bb --- /dev/null +++ b/hatch/src/assets/catch_definition.rs @@ -0,0 +1,17 @@ +pub struct CatchDefinition; + +impl CatchDefinition { + pub fn new() -> CatchDefinition { + CatchDefinition + } + + pub fn name() -> String { + String::from("catch.cpp") + } +} + +impl ToString for CatchDefinition { + fn to_string(&self) -> String { + String::from("#define CATCH_CONFIG_MAIN\n#include \"catch.hpp\"") + } +} diff --git a/hatch/src/assets/catch_header.rs b/hatch/src/assets/catch_header.rs new file mode 100644 index 0000000..788dda1 --- /dev/null +++ b/hatch/src/assets/catch_header.rs @@ -0,0 +1,11 @@ +pub struct CatchHeader; + +impl CatchHeader { + pub fn new() -> CatchHeader { + CatchHeader + } + + pub fn name() -> String { + String::from("catch.hpp") + } +} diff --git a/hatch/src/assets/config.rs b/hatch/src/assets/config.rs new file mode 100644 index 0000000..ecad99c --- /dev/null +++ b/hatch/src/assets/config.rs @@ -0,0 +1,36 @@ +use project::{ LibraryKind, ProjectKind }; + +pub struct Config { + project: String, + lib_type: String, +} + +impl Config { + pub fn new(name: &str, project_kind: &ProjectKind) -> Config { + Config { project: Config::project(name), lib_type: Config::lib_type(project_kind) } + } + + pub fn name() -> String { + String::from("config.tup") + } + + pub fn project(name: &str) -> String { + format!("PROJECT = {}", name) + } + + pub fn lib_type(project_kind: &ProjectKind) -> String { + let kind = match *project_kind { + ProjectKind::Binary => "binary", + ProjectKind::Library(LibraryKind::Static) => "static", + ProjectKind::Library(LibraryKind::Shared) => "shared" + }; + + format!("LIB_TYPE = {}", kind) + } +} + +impl ToString for Config { + fn to_string(&self) -> String { + [self.project.as_str(), self.lib_type.as_str()].join("\n") + } +} diff --git a/hatch/src/assets/generator.rs b/hatch/src/assets/generator.rs new file mode 100644 index 0000000..97e274e --- /dev/null +++ b/hatch/src/assets/generator.rs @@ -0,0 +1,33 @@ +use assets::{ Asset, ProjectAsset }; +use hatch_error::{ HatchResult, ResultExt }; +use std::fs; +use std::io::Write; + +pub fn generate_one(asset: &ProjectAsset) -> HatchResult<()> { + let path = asset.path(); + fs::create_dir_all(&path).with_context(|e| { + format!("Failed to create directory: `{}` : {}", path.display(), e) + })?; + + let file_path = path.join(asset.name()); + let mut file = fs::File::create(&file_path).with_context(|e| { + format!("Failed to create file: `{}` : {}", file_path.display(), e) + })?; + + let contents = asset.contents(); + file.write_all(contents.as_bytes()).with_context(|e| { + format!("Failed to write contents to file: `{}` : {}", file_path.display(), e) + })?; + + Ok(()) +} + +pub fn generate_all(assets: &Vec) -> HatchResult<()> { + for asset in assets { + generate_one(asset).with_context(|e| { + format!("Failed to generate asset: `{}` : {}", asset.path().display(), e) + })?; + } + + Ok(()) +} diff --git a/hatch/src/assets/mod.rs b/hatch/src/assets/mod.rs new file mode 100644 index 0000000..f4c0a51 --- /dev/null +++ b/hatch/src/assets/mod.rs @@ -0,0 +1,79 @@ +pub mod builder; +pub mod generator; +pub mod config; +pub mod tupfile; +pub mod platform; +pub mod tuprules; +pub mod test_tupfile; +pub mod tupfile_ini; +pub mod catch_header; +pub mod catch_definition; + +#[cfg(test)] +mod tests; + +use std::fmt; +use std::cmp; +use std::path::{ Path, PathBuf }; + +pub trait Asset { + fn path(&self) -> &Path; + fn name(&self) -> &str; + fn contents(&self) -> &str; +} + +pub fn print_file_path(asset: T) where T: Asset { + println!("{}", asset.path().display()); +} + +pub fn print_file_name(asset: T) where T: Asset { + println!("{}", asset.name()); +} + +pub fn print_file_contents(asset: T) where T: Asset { + println!("{}", asset.contents()); +} + +#[derive(Debug)] +pub enum TupKind { Tuprules, Config, Tupfile, TestTupfile, TupfileIni } + +#[derive(Debug)] +pub enum PlatformKind { Linux, MacOS, Windows } + +pub struct ProjectAsset { + path: PathBuf, + name: String, + contents: String, +} + +impl ProjectAsset { + pub fn new(path: PathBuf, name: String, contents: String) -> ProjectAsset { + ProjectAsset { path, name, contents } + } +} + +impl Asset for ProjectAsset { + fn path(&self) -> &Path { + self.path.as_path() + } + + fn name(&self) -> &str { + &self.name.as_str() + } + + fn contents(&self) -> &str { + &self.contents.as_str() + } +} + +impl fmt::Debug for ProjectAsset { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "path: {}, name: {}, contents: {}", self.path.display(), self.name, self.contents) + } +} + +impl cmp::PartialEq for ProjectAsset { + fn eq(&self, other: &ProjectAsset) -> bool { + self.name == other.name && self.contents == other.contents + } +} diff --git a/hatch/src/assets/platform.rs b/hatch/src/assets/platform.rs new file mode 100644 index 0000000..f8ad853 --- /dev/null +++ b/hatch/src/assets/platform.rs @@ -0,0 +1,96 @@ +pub struct Linux { + static_extension: String, + shared_extension: String, +} + +impl Linux { + pub fn new() -> Linux { + Linux { static_extension: Linux::static_extension(), shared_extension: Linux::shared_extension() } + } + + pub fn name() -> String { + String::from("linux.tup") + } + + pub fn static_extension() -> String { + String::from("STATIC = a") + } + + pub fn shared_extension() -> String { + String::from("SHARED = so") + } +} + +impl ToString for Linux { + fn to_string(&self) -> String { + [self.static_extension.as_str(), self.shared_extension.as_str()].join("\n") + } +} + +pub struct MacOS { + static_extension: String, + shared_extension: String, +} + +impl MacOS { + pub fn new() -> MacOS { + MacOS { static_extension: MacOS::static_extension(), shared_extension: MacOS::shared_extension() } + } + + pub fn name() -> String { + String::from("macosx.tup") + } + + pub fn static_extension() -> String { + String::from("STATIC = a") + } + + pub fn shared_extension() -> String { + String::from("SHARED = so") + } +} + +impl ToString for MacOS { + fn to_string(&self) -> String { + [self.static_extension.as_str(), self.shared_extension.as_str()].join("\n") + } +} + +pub struct Windows { + static_extension: String, + shared_extension: String, +} + +impl Windows { + pub fn new() -> Windows { + Windows { static_extension: Windows::static_extension(), shared_extension: Windows::shared_extension() } + } + + pub fn name() -> String { + String::from("win32.tup") + } + + pub fn static_extension() -> String { + String::from("STATIC = lib") + } + + pub fn shared_extension() -> String { + String::from("SHARED = dll") + } +} + +impl ToString for Windows { + fn to_string(&self) -> String { + let clang_comment = "# Use clang for front-end"; + let clang = "CC = clang++.exe"; + let llvm_comment = "# Use llvm-lib for static libraries"; + let archive_macro = "!archive = |> llvm-lib /MACHINE:X64 /OUT:%o %f |>"; + + [self.static_extension.as_str(), + self.shared_extension.as_str(), + clang_comment, + clang, + llvm_comment, + archive_macro].join("\n") + } +} diff --git a/hatch/src/assets/test_tupfile.rs b/hatch/src/assets/test_tupfile.rs new file mode 100644 index 0000000..bb744b4 --- /dev/null +++ b/hatch/src/assets/test_tupfile.rs @@ -0,0 +1,17 @@ +pub struct Tupfile; + +impl Tupfile { + pub fn new() -> Tupfile { + Tupfile + } + + pub fn name() -> String { + String::from("Tupfile") + } +} + +impl ToString for Tupfile { + fn to_string(&self) -> String { + String::from(".gitignore") + } +} diff --git a/hatch/src/assets/tests/builder.rs b/hatch/src/assets/tests/builder.rs new file mode 100644 index 0000000..ece6f88 --- /dev/null +++ b/hatch/src/assets/tests/builder.rs @@ -0,0 +1,187 @@ +use assets::builder::Builder as AssetBuilder; +use assets::{ Asset, ProjectAsset }; +use std::path::PathBuf; +use assets::tests::fixtures; +use project::{ ProjectKind, LibraryKind }; + +#[test] +fn add_asset() { + let mut asset_builder = AssetBuilder::new(); + let asset = ProjectAsset::new(PathBuf::from("./"), String::from("test"), String::from("test")); + asset_builder.add_asset(asset); + + let assets = asset_builder.assets(); + + assert_eq!(assets.len(), 1); + + assert_eq!(assets[0].name(), "test"); +} + +#[test] +fn build_config_asset() { + let project = fixtures::project(ProjectKind::Library(LibraryKind::Static)); + + let asset_builder = AssetBuilder::new(); + let actual_asset = asset_builder.config(&project); + + let expected_contents = String::from("PROJECT = test\nLIB_TYPE = static"); + let expected_asset = ProjectAsset::new(PathBuf::from("./"), String::from("config.tup"), expected_contents); + + assert_eq!(actual_asset, expected_asset); +} + +#[test] +fn build_test_tupfile_asset() { + let project = fixtures::project(ProjectKind::Library(LibraryKind::Static)); + + let asset_builder = AssetBuilder::new(); + let actual_asset = asset_builder.test_tupfile(&project); + + let expected_contents = String::from(".gitignore"); + let expected_asset = ProjectAsset::new(PathBuf::from("./test/"), String::from("Tupfile"), expected_contents); + + assert_eq!(actual_asset, expected_asset); +} + +#[test] +fn build_tuprules_asset() { + let project = fixtures::project(ProjectKind::Library(LibraryKind::Static)); + + let asset_builder = AssetBuilder::new(); + let actual_asset = asset_builder.tuprules(&project); + + let expected_contents = String::from( +".gitignore +CC = g++ +ARCH = -m64 +CFLAGS += $(ARCH) +CFLAGS += -c --std=c++1z +LINKFLAGS += $(ARCH) +LINKFLAGS += -v +ifneq (@(TUP_PLATFORM),macosx) + LINKFLAGS += -static +endif +SOURCE = src +TARGET = target +SOURCE_TARGET = $(TARGET) +SOURCE_FILES = $(SOURCE)/*.cpp +SOURCE_OBJ_FILES = $(SOURCE_TARGET)/*.o + +TEST = test +TEST_TARGET = $(TEST)/$(TARGET) +TEST_FILES = $(TEST)/$(SOURCE)/*.cpp +TEST_OBJ_FILES = $(TEST_TARGET)/*.o + +# macros +!compile = |> $(CC) $(CFLAGS) %f -o %o |> +!archive = |> ar crs %o %f |> +!link = |> $(CC) $(LINKFLAGS) %f -o %o |> + +# includes the STATIC and SHARED variables for the target platform +include @(TUP_PLATFORM).tup +ifeq ($(LIB_TYPE),static) + EXTENSION = $(STATIC) +else + ifeq ($(LIB_TYPE),shared) + EXTENSION = $(SHARED) + endif +endif +PROJECT_LIB = $(PROJECT).$(EXTENSION)"); + let expected_asset = ProjectAsset::new(PathBuf::from("./"), String::from("Tuprules.tup"), expected_contents); + + assert_eq!(actual_asset, expected_asset); +} + +#[test] +fn build_tupfile_asset() { + let project = fixtures::project(ProjectKind::Library(LibraryKind::Shared)); + + let asset_builder = AssetBuilder::new(); + let actual_asset = asset_builder.tupfile(&project); + + let expected_contents = String::from( +"include config.tup +include_rules + +: foreach $(SOURCE_FILES) |> !compile |> $(SOURCE_TARGET)/%B.o + +: $(SOURCE_OBJ_FILES) |> !archive |> $(SOURCE_TARGET)/$(PROJECT_LIB) <$(PROJECT)> + +: foreach $(TEST_FILES) |> !compile |> $(TEST_TARGET)/%B.o + +: $(TEST_OBJ_FILES) $(SOURCE_TARGET)/$(PROJECT_LIB) |> !link |> $(TEST_TARGET)/$(PROJECT).test"); + let expected_asset = ProjectAsset::new(PathBuf::from("./"), String::from("Tupfile"), expected_contents); + + assert_eq!(actual_asset, expected_asset); +} + +#[test] +fn build_tupfile_ini_asset() { + let project = fixtures::project(ProjectKind::Library(LibraryKind::Static)); + + let asset_builder = AssetBuilder::new(); + let actual_asset = asset_builder.tupfile_ini(&project); + + let expected_contents = String::from(""); + let expected_asset = ProjectAsset::new(PathBuf::from("./"), String::from("Tupfile.ini"), expected_contents); + + assert_eq!(actual_asset, expected_asset); +} + +#[test] +fn build_linux_asset() { + let project = fixtures::project(ProjectKind::Library(LibraryKind::Static)); + + let asset_builder = AssetBuilder::new(); + let actual_asset = asset_builder.linux(&project); + + let expected_contents = String::from("STATIC = a\nSHARED = so"); + let expected_asset = ProjectAsset::new(PathBuf::from("./"), String::from("linux.tup"), expected_contents); + + assert_eq!(actual_asset, expected_asset); +} + +#[test] +fn build_macos_asset() { + let project = fixtures::project(ProjectKind::Library(LibraryKind::Static)); + + let asset_builder = AssetBuilder::new(); + let actual_asset = asset_builder.macos(&project); + + let expected_contents = String::from("STATIC = a\nSHARED = so"); + let expected_asset = ProjectAsset::new(PathBuf::from("./"), String::from("macosx.tup"), expected_contents); + + assert_eq!(actual_asset, expected_asset); +} + +#[test] +fn build_windows_asset() { + let project = fixtures::project(ProjectKind::Library(LibraryKind::Static)); + + let asset_builder = AssetBuilder::new(); + let actual_asset = asset_builder.windows(&project); + + let expected_contents = String::from( +"STATIC = lib +SHARED = dll +# Use clang for front-end +CC = clang++.exe +# Use llvm-lib for static libraries +!archive = |> llvm-lib /MACHINE:X64 /OUT:%o %f |>"); + let expected_asset = ProjectAsset::new(PathBuf::from("./"), String::from("win32.tup"), expected_contents); + + assert_eq!(actual_asset, expected_asset); +} + +#[test] +fn build_catch_definition() { + let project = fixtures::project(ProjectKind::Library(LibraryKind::Static)); + + let asset_builder = AssetBuilder::new(); + let actual_asset = asset_builder.catch_definition(&project); + + let expected_contents = String::from("#define CATCH_CONFIG_MAIN\n#include \"catch.hpp\""); + let expected_asset = ProjectAsset::new(PathBuf::from("./"), String::from("catch.cpp"), expected_contents); + + assert_eq!(actual_asset, expected_asset); +} diff --git a/hatch/src/assets/tests/catch_definition.rs b/hatch/src/assets/tests/catch_definition.rs new file mode 100644 index 0000000..58afede --- /dev/null +++ b/hatch/src/assets/tests/catch_definition.rs @@ -0,0 +1,6 @@ +use assets::catch_definition::CatchDefinition; + +#[test] +fn build_catch_definition() { + assert_eq!("#define CATCH_CONFIG_MAIN\n#include \"catch.hpp\"", CatchDefinition::new().to_string()); +} \ No newline at end of file diff --git a/hatch/src/assets/tests/catch_header.rs b/hatch/src/assets/tests/catch_header.rs new file mode 100644 index 0000000..413e42c --- /dev/null +++ b/hatch/src/assets/tests/catch_header.rs @@ -0,0 +1,6 @@ +use assets::catch_header::CatchHeader; + +#[test] +fn build_catch_header() { + assert_eq!("catch.hpp", CatchHeader::name()); +} diff --git a/hatch/src/assets/tests/config.rs b/hatch/src/assets/tests/config.rs new file mode 100644 index 0000000..b25cecd --- /dev/null +++ b/hatch/src/assets/tests/config.rs @@ -0,0 +1,23 @@ +use assets::config::Config; +use project::{ LibraryKind, ProjectKind }; + +#[test] +fn build_shared_config() { + let config = Config::new("Test", &ProjectKind::Library(LibraryKind::Shared)); + + assert_eq!("PROJECT = Test\nLIB_TYPE = shared", config.to_string()); +} + +#[test] +fn build_static_config() { + let config = Config::new("Test", &ProjectKind::Library(LibraryKind::Static)); + + assert_eq!("PROJECT = Test\nLIB_TYPE = static", config.to_string()); +} + +#[test] +fn build_binary_config() { + let config = Config::new("Test", &ProjectKind::Binary); + + assert_eq!("PROJECT = Test\nLIB_TYPE = binary", config.to_string()); +} diff --git a/hatch/src/assets/tests/fixtures.rs b/hatch/src/assets/tests/fixtures.rs new file mode 100644 index 0000000..47313e8 --- /dev/null +++ b/hatch/src/assets/tests/fixtures.rs @@ -0,0 +1,21 @@ +use project::{ Project, ProjectKind }; +use project::build::{ Config, Target }; +use platform::arch::Arch; +use std::path::PathBuf; + +pub fn project(kind: ProjectKind) -> Project { + let config = Config::new(kind, + String::from("g++"), + vec![String::from("-c"), String::from("--std=c++1z")], + vec![String::from("-v")], + Arch::X64, + Target::Release); + + let project = Project::new(String::from("test"), + String::from("0.1.0"), + config, + Vec::new(), + PathBuf::from("./")); + + project +} diff --git a/hatch/src/assets/tests/generator.rs b/hatch/src/assets/tests/generator.rs new file mode 100644 index 0000000..1800d42 --- /dev/null +++ b/hatch/src/assets/tests/generator.rs @@ -0,0 +1,165 @@ +use assets::generator::*; +use assets::ProjectAsset; +use std::fs; +use std::io::prelude::*; +use std::path::PathBuf; + +#[test] +fn generate_one_without_directories() { + let test_asset = ProjectAsset::new(PathBuf::from("./"), String::from("test.test"), String::from("test")); + + if let Err(e) = generate_one(&test_asset) { + panic!(e); + } + + match fs::File::open("./test.test") { + Ok(mut file) => { + let mut contents = String::new(); + let result = file.read_to_string(&mut contents); + fs::remove_file("./test.test"); + + if let Err(e) = result { + panic!(e) + } + + assert_eq!(contents, "test"); + }, + Err(e) => { + fs::remove_file("./test.test"); + panic!(e) + } + } +} + +#[test] +fn generate_one_with_directories() { + let test_asset = ProjectAsset::new(PathBuf::from("./foo/"), String::from("test.test"), String::from("test")); + + if let Err(e) = generate_one(&test_asset) { + panic!(e); + } + + match fs::File::open("./foo/test.test") { + Ok(mut file) => { + let mut contents = String::new(); + let result = file.read_to_string(&mut contents); + fs::remove_file("./foo/test.test"); + fs::remove_dir("./foo/"); + + if let Err(e) = result { + panic!(e) + } + }, + Err(e) => { + fs::remove_file("./foo/test.test"); + fs::remove_dir("./foo/"); + panic!(e) + } + } +} + +#[test] +fn generate_one_overwrites_file() { + let test_asset = ProjectAsset::new(PathBuf::from("./"), String::from("test2.test"), String::from("old")); + + if let Err(e) = generate_one(&test_asset) { + panic!(e); + } + + // verify that the old content is there + match fs::File::open("./test2.test") { + Ok(mut file) => { + let mut contents = String::new(); + let result = file.read_to_string(&mut contents); + fs::remove_file("./test2.test"); + + if let Err(e) = result { + panic!(e) + } + + assert_eq!(contents, "old"); + }, + Err(e) => { + fs::remove_file("./test2.test"); + panic!(e) + } + } + + let test_asset = ProjectAsset::new(PathBuf::from("./"), String::from("test2.test"), String::from("new")); + + if let Err(e) = generate_one(&test_asset) { + fs::remove_file("./test2.test"); + panic!(e); + } + + // verify that the new content overwrites the old content + match fs::File::open("./test2.test") { + Ok(mut file) => { + let mut contents = String::new(); + let result = file.read_to_string(&mut contents); + fs::remove_file("./test2.test"); + + if let Err(e) = result { + panic!(e) + } + + assert_eq!(contents, "new"); + }, + Err(e) => { + fs::remove_file("./test2.test"); + panic!(e) + } + } +} + +#[test] +fn generate_all_assets() { + let test_asset_one = ProjectAsset::new(PathBuf::from("./"), String::from("one.test"), String::from("one")); + let test_asset_two = ProjectAsset::new(PathBuf::from("./"), String::from("two.test"), String::from("two")); + + let test_assets = vec![test_asset_one, test_asset_two]; + + if let Err(e) = generate_all(&test_assets) { + fs::remove_file("./one.test"); + fs::remove_file("./two.test"); + panic!(e); + } + + match fs::File::open("./one.test") { + Ok(mut file) => { + let mut contents = String::new(); + let result = file.read_to_string(&mut contents); + fs::remove_file("./one.test"); + + if let Err(e) = result { + fs::remove_file("./two.test"); + panic!(e) + } + + assert_eq!(contents, "one"); + }, + Err(e) => { + fs::remove_file("./one.test"); + fs::remove_file("./two.test"); + panic!(e) + } + } + + match fs::File::open("./two.test") { + Ok(mut file) => { + let mut contents = String::new(); + let result = file.read_to_string(&mut contents); + fs::remove_file("./two.test"); + + if let Err(e) = result { + panic!(e) + } + + assert_eq!(contents, "two"); + }, + Err(e) => { + fs::remove_file("./two.test"); + panic!(e) + } + } +} diff --git a/hatch/src/assets/tests/mod.rs b/hatch/src/assets/tests/mod.rs new file mode 100644 index 0000000..8234966 --- /dev/null +++ b/hatch/src/assets/tests/mod.rs @@ -0,0 +1,21 @@ +mod builder; +mod generator; +mod config; +mod platform; +mod test_tupfile; +mod tupfile; +mod tuprules; +mod catch_header; +mod catch_definition; +mod fixtures; + +use assets::ProjectAsset; +use std::path::PathBuf; + +#[test] +fn fmt_project_asset() { + let asset = ProjectAsset::new(PathBuf::from("./"), String::from("test"), String::from("test")); + + let result = format!("{:?}", asset); + assert_eq!(result, "path: ./, name: test, contents: test"); +} \ No newline at end of file diff --git a/hatch/src/assets/tests/platform.rs b/hatch/src/assets/tests/platform.rs new file mode 100644 index 0000000..21b580f --- /dev/null +++ b/hatch/src/assets/tests/platform.rs @@ -0,0 +1,23 @@ +use assets::platform::{ Linux, MacOS, Windows }; + +#[test] +fn build_linux() { + assert_eq!("STATIC = a\nSHARED = so", Linux::new().to_string()); +} + +#[test] +fn build_macos() { + assert_eq!("STATIC = a\nSHARED = so", MacOS::new().to_string()); +} + +#[test] +fn build_windows() { + let windows_content = String::from( +"STATIC = lib +SHARED = dll +# Use clang for front-end +CC = clang++.exe +# Use llvm-lib for static libraries +!archive = |> llvm-lib /MACHINE:X64 /OUT:%o %f |>"); + assert_eq!(windows_content, Windows::new().to_string()); +} diff --git a/hatch/src/assets/tests/test_tupfile.rs b/hatch/src/assets/tests/test_tupfile.rs new file mode 100644 index 0000000..334cc9b --- /dev/null +++ b/hatch/src/assets/tests/test_tupfile.rs @@ -0,0 +1,6 @@ +use assets::test_tupfile::Tupfile; + +#[test] +fn build_test_tupfile() { + assert_eq!(".gitignore", Tupfile::new().to_string()); +} diff --git a/hatch/src/assets/tests/tupfile.rs b/hatch/src/assets/tests/tupfile.rs new file mode 100644 index 0000000..0cf8b69 --- /dev/null +++ b/hatch/src/assets/tests/tupfile.rs @@ -0,0 +1,41 @@ +use assets::tupfile::Tupfile; +use assets::tests::fixtures; +use project::{ ProjectKind, LibraryKind }; + +#[test] +fn build_library_tupfile() { + let project = fixtures::project(ProjectKind::Library(LibraryKind::Static)); + + let contents = String::from( +"include config.tup +include_rules + +: foreach $(SOURCE_FILES) |> !compile |> $(SOURCE_TARGET)/%B.o + +: $(SOURCE_OBJ_FILES) |> !archive |> $(SOURCE_TARGET)/$(PROJECT_LIB) <$(PROJECT)> + +: foreach $(TEST_FILES) |> !compile |> $(TEST_TARGET)/%B.o + +: $(TEST_OBJ_FILES) $(SOURCE_TARGET)/$(PROJECT_LIB) |> !link |> $(TEST_TARGET)/$(PROJECT).test"); + + assert_eq!(contents, Tupfile::new(project.config().kind()).to_string()); +} + +#[test] +fn build_binary_tupfile() { + let project = fixtures::project(ProjectKind::Binary); + + let contents = String::from( +"include config.tup +include_rules + +: foreach $(SOURCE_FILES) |> !compile |> $(SOURCE_TARGET)/%B.o + +: $(SOURCE_OBJ_FILES) |> !link |> $(SOURCE_TARGET)/$(PROJECT) + +: foreach $(TEST_FILES) |> !compile |> $(TEST_TARGET)/%B.o + +: $(TEST_OBJ_FILES) |> !link |> $(TEST_TARGET)/$(PROJECT).test"); + + assert_eq!(contents, Tupfile::new(project.config().kind()).to_string()); +} \ No newline at end of file diff --git a/hatch/src/assets/tests/tuprules.rs b/hatch/src/assets/tests/tuprules.rs new file mode 100644 index 0000000..176a8cd --- /dev/null +++ b/hatch/src/assets/tests/tuprules.rs @@ -0,0 +1,388 @@ +use assets::tuprules::Tuprules; +use project::{ ProjectKind, LibraryKind }; +use project::build::{ Target, Config }; +use platform::arch::Arch; + +/** + * These tests were created using All-Pairs testing. + * + * Note that I am not including the Compiler field as it is required and we are simply doing a + * string replace as opposed to an enumeration. + * + * the tests are following this table: + * (Kind, Arch, Target, Compiler Flags, Linker Flags) + * (Static, X64, Release, Present, Present) + * (Static, X86, Debug, None, None) + * (Shared, X64, Debug, None, None) + * (Shared, X86, Release, Present, Present) + * (Binary, X64, Release, None, None) + * (Binary, X86, Debug, Present, Present) + * (Binary, X64, Release, Present, None) + * (Binary, X86, Debug, None, Present) + */ + +#[test] +fn build_static_x64_release_with_flags_tuprules() { + let contents = String::from( +".gitignore +CC = g++ +ARCH = -m64 +CFLAGS += $(ARCH) +CFLAGS += -c --std=c++1z +LINKFLAGS += $(ARCH) +LINKFLAGS += -v +ifneq (@(TUP_PLATFORM),macosx) + LINKFLAGS += -static +endif +SOURCE = src +TARGET = target +SOURCE_TARGET = $(TARGET) +SOURCE_FILES = $(SOURCE)/*.cpp +SOURCE_OBJ_FILES = $(SOURCE_TARGET)/*.o + +TEST = test +TEST_TARGET = $(TEST)/$(TARGET) +TEST_FILES = $(TEST)/$(SOURCE)/*.cpp +TEST_OBJ_FILES = $(TEST_TARGET)/*.o + +# macros +!compile = |> $(CC) $(CFLAGS) %f -o %o |> +!archive = |> ar crs %o %f |> +!link = |> $(CC) $(LINKFLAGS) %f -o %o |> + +# includes the STATIC and SHARED variables for the target platform +include @(TUP_PLATFORM).tup +ifeq ($(LIB_TYPE),static) + EXTENSION = $(STATIC) +else + ifeq ($(LIB_TYPE),shared) + EXTENSION = $(SHARED) + endif +endif +PROJECT_LIB = $(PROJECT).$(EXTENSION)"); + + let config = Config::new(ProjectKind::Library(LibraryKind::Static), + String::from("g++"), + vec![String::from("-c"), String::from("--std=c++1z")], + vec![String::from("-v")], + Arch::X64, + Target::Release); + + let tuprules = Tuprules::new(&config); + + assert_eq!(contents, tuprules.to_string()); +} + +#[test] +fn build_static_x86_debug_without_flags_tuprules() { + let contents = String::from( +".gitignore +CC = g++ +CFLAGS += -g +ARCH = -m32 +CFLAGS += $(ARCH) +LINKFLAGS += $(ARCH) +ifneq (@(TUP_PLATFORM),macosx) + LINKFLAGS += -static +endif +SOURCE = src +TARGET = target +SOURCE_TARGET = $(TARGET) +SOURCE_FILES = $(SOURCE)/*.cpp +SOURCE_OBJ_FILES = $(SOURCE_TARGET)/*.o + +TEST = test +TEST_TARGET = $(TEST)/$(TARGET) +TEST_FILES = $(TEST)/$(SOURCE)/*.cpp +TEST_OBJ_FILES = $(TEST_TARGET)/*.o + +# macros +!compile = |> $(CC) $(CFLAGS) %f -o %o |> +!archive = |> ar crs %o %f |> +!link = |> $(CC) $(LINKFLAGS) %f -o %o |> + +# includes the STATIC and SHARED variables for the target platform +include @(TUP_PLATFORM).tup +ifeq ($(LIB_TYPE),static) + EXTENSION = $(STATIC) +else + ifeq ($(LIB_TYPE),shared) + EXTENSION = $(SHARED) + endif +endif +PROJECT_LIB = $(PROJECT).$(EXTENSION)"); + let config = Config::new(ProjectKind::Library(LibraryKind::Static), + String::from("g++"), + Vec::new(), + Vec::new(), + Arch::X86, + Target::Debug); + + let tuprules = Tuprules::new(&config); + + assert_eq!(contents, tuprules.to_string()); +} + +#[test] +fn build_shared_x64_debug_without_flags_tuprules() { + let contents = String::from( +".gitignore +CC = g++ +CFLAGS += -g +ARCH = -m64 +CFLAGS += $(ARCH) +LINKFLAGS += $(ARCH) +ifneq (@(TUP_PLATFORM),macosx) + LINKFLAGS += -dynamic +endif +SOURCE = src +TARGET = target +SOURCE_TARGET = $(TARGET) +SOURCE_FILES = $(SOURCE)/*.cpp +SOURCE_OBJ_FILES = $(SOURCE_TARGET)/*.o + +TEST = test +TEST_TARGET = $(TEST)/$(TARGET) +TEST_FILES = $(TEST)/$(SOURCE)/*.cpp +TEST_OBJ_FILES = $(TEST_TARGET)/*.o + +# macros +!compile = |> $(CC) $(CFLAGS) %f -o %o |> +!archive = |> ar crs %o %f |> +!link = |> $(CC) $(LINKFLAGS) %f -o %o |> + +# includes the STATIC and SHARED variables for the target platform +include @(TUP_PLATFORM).tup +ifeq ($(LIB_TYPE),static) + EXTENSION = $(STATIC) +else + ifeq ($(LIB_TYPE),shared) + EXTENSION = $(SHARED) + endif +endif +PROJECT_LIB = $(PROJECT).$(EXTENSION)"); + + let config = Config::new(ProjectKind::Library(LibraryKind::Shared), + String::from("g++"), + Vec::new(), + Vec::new(), + Arch::X64, + Target::Debug); + + let tuprules = Tuprules::new(&config); + + assert_eq!(contents, tuprules.to_string()); +} + +#[test] +fn build_shared_x86_release_with_flags_tuprules() { + let contents = String::from( +".gitignore +CC = g++ +ARCH = -m32 +CFLAGS += $(ARCH) +CFLAGS += -c --std=c++1z +LINKFLAGS += $(ARCH) +LINKFLAGS += -v +ifneq (@(TUP_PLATFORM),macosx) + LINKFLAGS += -dynamic +endif +SOURCE = src +TARGET = target +SOURCE_TARGET = $(TARGET) +SOURCE_FILES = $(SOURCE)/*.cpp +SOURCE_OBJ_FILES = $(SOURCE_TARGET)/*.o + +TEST = test +TEST_TARGET = $(TEST)/$(TARGET) +TEST_FILES = $(TEST)/$(SOURCE)/*.cpp +TEST_OBJ_FILES = $(TEST_TARGET)/*.o + +# macros +!compile = |> $(CC) $(CFLAGS) %f -o %o |> +!archive = |> ar crs %o %f |> +!link = |> $(CC) $(LINKFLAGS) %f -o %o |> + +# includes the STATIC and SHARED variables for the target platform +include @(TUP_PLATFORM).tup +ifeq ($(LIB_TYPE),static) + EXTENSION = $(STATIC) +else + ifeq ($(LIB_TYPE),shared) + EXTENSION = $(SHARED) + endif +endif +PROJECT_LIB = $(PROJECT).$(EXTENSION)"); + + let config = Config::new(ProjectKind::Library(LibraryKind::Shared), + String::from("g++"), + vec![String::from("-c"), String::from("--std=c++1z")], + vec![String::from("-v")], + Arch::X86, + Target::Release); + + let tuprules = Tuprules::new(&config); + + assert_eq!(contents, tuprules.to_string()); +} + +#[test] +fn build_binary_x64_release_without_flags_tuprules() { + let contents = String::from( +".gitignore +CC = g++ +ARCH = -m64 +CFLAGS += $(ARCH) +LINKFLAGS += $(ARCH) +SOURCE = src +TARGET = target +SOURCE_TARGET = $(TARGET) +SOURCE_FILES = $(SOURCE)/*.cpp +SOURCE_OBJ_FILES = $(SOURCE_TARGET)/*.o + +TEST = test +TEST_TARGET = $(TEST)/$(TARGET) +TEST_FILES = $(TEST)/$(SOURCE)/*.cpp +TEST_OBJ_FILES = $(TEST_TARGET)/*.o + +# macros +!compile = |> $(CC) $(CFLAGS) %f -o %o |> +!archive = |> ar crs %o %f |> +!link = |> $(CC) $(LINKFLAGS) %f -o %o |> + +# includes the STATIC and SHARED variables for the target platform +include @(TUP_PLATFORM).tup"); + + let config = Config::new(ProjectKind::Binary, + String::from("g++"), + Vec::new(), + Vec::new(), + Arch::X64, + Target::Release); + + let tuprules = Tuprules::new(&config); + + assert_eq!(contents, tuprules.to_string()); +} + +#[test] +fn build_binary_x86_debug_with_flags_tuprules() { + let contents = String::from( +".gitignore +CC = g++ +CFLAGS += -g +ARCH = -m32 +CFLAGS += $(ARCH) +CFLAGS += -c --std=c++1z +LINKFLAGS += $(ARCH) +LINKFLAGS += -v +SOURCE = src +TARGET = target +SOURCE_TARGET = $(TARGET) +SOURCE_FILES = $(SOURCE)/*.cpp +SOURCE_OBJ_FILES = $(SOURCE_TARGET)/*.o + +TEST = test +TEST_TARGET = $(TEST)/$(TARGET) +TEST_FILES = $(TEST)/$(SOURCE)/*.cpp +TEST_OBJ_FILES = $(TEST_TARGET)/*.o + +# macros +!compile = |> $(CC) $(CFLAGS) %f -o %o |> +!archive = |> ar crs %o %f |> +!link = |> $(CC) $(LINKFLAGS) %f -o %o |> + +# includes the STATIC and SHARED variables for the target platform +include @(TUP_PLATFORM).tup"); + + let config = Config::new(ProjectKind::Binary, String::from("g++"), + vec![String::from("-c"), String::from("--std=c++1z")], + vec![String::from("-v")], + Arch::X86, + Target::Debug); + + let tuprules = Tuprules::new(&config); + + assert_eq!(contents, tuprules.to_string()); +} + +#[test] +fn build_binary_x64_release_with_cflags_without_lflags_tuprules() { + let contents = String::from( + ".gitignore +CC = g++ +ARCH = -m64 +CFLAGS += $(ARCH) +CFLAGS += -c --std=c++1z +LINKFLAGS += $(ARCH) +SOURCE = src +TARGET = target +SOURCE_TARGET = $(TARGET) +SOURCE_FILES = $(SOURCE)/*.cpp +SOURCE_OBJ_FILES = $(SOURCE_TARGET)/*.o + +TEST = test +TEST_TARGET = $(TEST)/$(TARGET) +TEST_FILES = $(TEST)/$(SOURCE)/*.cpp +TEST_OBJ_FILES = $(TEST_TARGET)/*.o + +# macros +!compile = |> $(CC) $(CFLAGS) %f -o %o |> +!archive = |> ar crs %o %f |> +!link = |> $(CC) $(LINKFLAGS) %f -o %o |> + +# includes the STATIC and SHARED variables for the target platform +include @(TUP_PLATFORM).tup"); + + let config = Config::new(ProjectKind::Binary, + String::from("g++"), + vec![String::from("-c"), String::from("--std=c++1z")], + Vec::new(), + Arch::X64, + Target::Release); + + let tuprules = Tuprules::new(&config); + + assert_eq!(contents, tuprules.to_string()); +} + +#[test] +fn build_binary_x86_debug_without_cflags_with_lflags_tuprules() { + let contents = String::from( + ".gitignore +CC = g++ +CFLAGS += -g +ARCH = -m32 +CFLAGS += $(ARCH) +LINKFLAGS += $(ARCH) +LINKFLAGS += -v +SOURCE = src +TARGET = target +SOURCE_TARGET = $(TARGET) +SOURCE_FILES = $(SOURCE)/*.cpp +SOURCE_OBJ_FILES = $(SOURCE_TARGET)/*.o + +TEST = test +TEST_TARGET = $(TEST)/$(TARGET) +TEST_FILES = $(TEST)/$(SOURCE)/*.cpp +TEST_OBJ_FILES = $(TEST_TARGET)/*.o + +# macros +!compile = |> $(CC) $(CFLAGS) %f -o %o |> +!archive = |> ar crs %o %f |> +!link = |> $(CC) $(LINKFLAGS) %f -o %o |> + +# includes the STATIC and SHARED variables for the target platform +include @(TUP_PLATFORM).tup"); + + let config = Config::new(ProjectKind::Binary, + String::from("g++"), + Vec::new(), + vec![String::from("-v")], + Arch::X86, + Target::Debug); + + let tuprules = Tuprules::new(&config); + + assert_eq!(contents, tuprules.to_string()); +} diff --git a/hatch/src/assets/tupfile.rs b/hatch/src/assets/tupfile.rs new file mode 100644 index 0000000..83123b8 --- /dev/null +++ b/hatch/src/assets/tupfile.rs @@ -0,0 +1,56 @@ +use project::{ ProjectKind, LibraryKind }; + +pub struct Tupfile { + kind: ProjectKind +} + +impl Tupfile { + pub fn new(kind: &ProjectKind) -> Tupfile { + let copy_kind = match *kind { + ProjectKind::Binary => ProjectKind::Binary, + ProjectKind::Library(LibraryKind::Static) => ProjectKind::Library(LibraryKind::Static), + ProjectKind::Library(LibraryKind::Shared) => ProjectKind::Library(LibraryKind::Shared) + }; + + Tupfile { kind: copy_kind } + } + + pub fn name() -> String { + String::from("Tupfile") + } +} + +impl ToString for Tupfile { + fn to_string(&self) -> String { + let mut tokens = Vec::new(); + + let includes = String::from("include config.tup\ninclude_rules\n"); + let compile_source = String::from(": foreach $(SOURCE_FILES) |> !compile |> $(SOURCE_TARGET)/%B.o\n"); + let compile_tests = String::from(": foreach $(TEST_FILES) |> !compile |> $(TEST_TARGET)/%B.o\n"); + + tokens.push(includes); + tokens.push(compile_source); + + match self.kind { + ProjectKind::Binary => { + tokens.push(String::from(": $(SOURCE_OBJ_FILES) |> !link |> $(SOURCE_TARGET)/$(PROJECT)\n")); + }, + ProjectKind::Library(_) => { + tokens.push(String::from(": $(SOURCE_OBJ_FILES) |> !archive |> $(SOURCE_TARGET)/$(PROJECT_LIB) <$(PROJECT)>\n")); + } + } + + tokens.push(compile_tests); + + match self.kind { + ProjectKind::Binary => { + tokens.push(String::from(": $(TEST_OBJ_FILES) |> !link |> $(TEST_TARGET)/$(PROJECT).test")); + }, + ProjectKind::Library(_) => { + tokens.push(String::from(": $(TEST_OBJ_FILES) $(SOURCE_TARGET)/$(PROJECT_LIB) |> !link |> $(TEST_TARGET)/$(PROJECT).test")); + } + } + + tokens.iter().map(|token| token.as_str()).collect::>().join("\n") + } +} diff --git a/hatch/src/assets/tupfile_ini.rs b/hatch/src/assets/tupfile_ini.rs new file mode 100644 index 0000000..ec4e8e3 --- /dev/null +++ b/hatch/src/assets/tupfile_ini.rs @@ -0,0 +1,17 @@ +pub struct TupfileIni; + +impl TupfileIni { + pub fn new() -> TupfileIni { + TupfileIni + } + + pub fn name() -> String { + String::from("Tupfile.ini") + } +} + +impl ToString for TupfileIni { + fn to_string(&self) -> String { + String::from("") + } +} diff --git a/hatch/src/assets/tuprules.rs b/hatch/src/assets/tuprules.rs new file mode 100644 index 0000000..396ab3d --- /dev/null +++ b/hatch/src/assets/tuprules.rs @@ -0,0 +1,146 @@ +use project::{ ProjectKind, LibraryKind }; +use project::build::{ Config, Target }; +use platform::arch::Arch; + +pub struct Tuprules { + kind: ProjectKind, + compiler: String, + compiler_flags: String, + linker_flags: String, + arch: Arch, + target: Target +} + +impl Tuprules { + pub fn new(config: &Config) -> Tuprules { + let copy_kind = match *config.kind() { + ProjectKind::Binary => ProjectKind::Binary, + ProjectKind::Library(LibraryKind::Static) => ProjectKind::Library(LibraryKind::Static), + ProjectKind::Library(LibraryKind::Shared) => ProjectKind::Library(LibraryKind::Shared) + }; + + let copy_arch = match *config.arch() { + Arch::X64 => Arch::X64, + Arch::X86 => Arch::X86 + }; + + let copy_target = match *config.target() { + Target::Debug => Target::Debug, + Target::Release => Target::Release + }; + + Tuprules { + kind: copy_kind, + compiler: String::from(config.compiler()), + compiler_flags: config.compiler_flags().join(" "), + linker_flags: config.linker_flags().join(" "), + arch: copy_arch, + target: copy_target + } + } + + pub fn name() -> String { + String::from("Tuprules.tup") + } + + fn arch_flag(arch: &Arch) -> String { + match *arch { + Arch::X64 => String::from("-m64"), + Arch::X86 => String::from("-m32"), + } + } + + fn type_flag(lib_type: &LibraryKind) -> String { + match *lib_type { + LibraryKind::Static => String::from("-static"), + LibraryKind::Shared => String::from("-dynamic"), + } + } +} + +impl ToString for Tuprules { + fn to_string(&self) -> String { + let mut tokens = Vec::new(); + tokens.push(String::from(".gitignore")); + + let compiler_token = format!("CC = {}", self.compiler); + tokens.push(compiler_token); + + match self.target { + Target::Debug => { + let debug_token = String::from("CFLAGS += -g"); + tokens.push(debug_token); + }, + _ => {} + } + + let arch_flag = Tuprules::arch_flag(&self.arch); + let arch_token = format!("ARCH = {}", arch_flag); + tokens.push(arch_token); + + tokens.push(String::from("CFLAGS += $(ARCH)")); + + if !self.compiler_flags.is_empty() { + let compiler_flags = format!("CFLAGS += {}", self.compiler_flags); + tokens.push(compiler_flags); + } + + tokens.push(String::from("LINKFLAGS += $(ARCH)")); + + if !self.linker_flags.is_empty() { + let linker_flags = format!("LINKFLAGS += {}", self.linker_flags); + tokens.push(linker_flags); + } + + match self.kind { + ProjectKind::Library(ref lib_kind) => { + let link_flags_type = format!( +"ifneq (@(TUP_PLATFORM),macosx) + LINKFLAGS += {} +endif", Tuprules::type_flag(lib_kind)); + + tokens.push(link_flags_type); + }, + ProjectKind::Binary => { + + } + } + + tokens.push(String::from( +"SOURCE = src +TARGET = target +SOURCE_TARGET = $(TARGET) +SOURCE_FILES = $(SOURCE)/*.cpp +SOURCE_OBJ_FILES = $(SOURCE_TARGET)/*.o + +TEST = test +TEST_TARGET = $(TEST)/$(TARGET) +TEST_FILES = $(TEST)/$(SOURCE)/*.cpp +TEST_OBJ_FILES = $(TEST_TARGET)/*.o + +# macros +!compile = |> $(CC) $(CFLAGS) %f -o %o |> +!archive = |> ar crs %o %f |> +!link = |> $(CC) $(LINKFLAGS) %f -o %o |> + +# includes the STATIC and SHARED variables for the target platform +include @(TUP_PLATFORM).tup")); + + match self.kind { + ProjectKind::Library(ref _lib_kind) => { + tokens.push(String::from( +"ifeq ($(LIB_TYPE),static) + EXTENSION = $(STATIC) +else + ifeq ($(LIB_TYPE),shared) + EXTENSION = $(SHARED) + endif +endif +PROJECT_LIB = $(PROJECT).$(EXTENSION)")); + }, + _ => {} + } + + tokens.iter().map(|token| token.as_str()).collect::>().join("\n") + } +} diff --git a/hatch/src/bin/hatch.rs b/hatch/src/bin/hatch.rs index 6331855..8ab8fae 100644 --- a/hatch/src/bin/hatch.rs +++ b/hatch/src/bin/hatch.rs @@ -1,8 +1,42 @@ extern crate hatch; -use hatch::manifest::Manifest; -use hatch::project::Project; +use std::collections::HashMap; + +use hatch::cli::Cli; +use hatch::cli::commands::Command; +use hatch::cli::commands::new::New; +use hatch::cli::commands::update::Update; +use hatch::cli::commands::build::Build; +use hatch::cli::commands::test::Test; +use hatch::cli::commands::run::Run; fn main() { - let manifest = Manifest::new(); + // create the subcommand to command map + let mut subcommands: HashMap<&'static str, Box> = HashMap::new(); + + let new_command = Box::new(New::new()); + subcommands.insert(new_command.subcommand_name(), new_command); + + let update_command = Box::new(Update::new()); + subcommands.insert(update_command.subcommand_name(), update_command); + + let build_command = Box::new(Build::new()); + subcommands.insert(build_command.subcommand_name(), build_command); + + let test_command = Box::new(Test::new()); + subcommands.insert(test_command.subcommand_name(), test_command); + + let run_command = Box::new(Run::new()); + subcommands.insert(run_command.subcommand_name(), run_command); + + // initialize cli with the set of subcommand + let cli = Cli::new(subcommands.values().map(|v| v.cli_subcommand()).collect::>()); + + // execute selected subcommand + let (name, args) = cli.subcommand(); + if let Some(cmd) = subcommands.get(name) { + if let Err(e) = cmd.execute(args.unwrap()) { + println!("{}", e); + } + } } diff --git a/hatch/src/cli.rs b/hatch/src/cli.rs deleted file mode 100644 index 7bfe01c..0000000 --- a/hatch/src/cli.rs +++ /dev/null @@ -1,22 +0,0 @@ -use dtl::cli as cli_imp; -use project::{ ProjectKind }; - -pub struct Cli<'cli>(cli_imp::Cli<'cli>); - -impl<'cli>Cli<'cli> { - pub fn new() -> Cli<'cli> { - Cli(cli_imp::Cli::new()) - } - - pub fn kind(&self) -> ProjectKind { - self.0.build_type() - } - - pub fn name(&self) -> String { - self.0.name() - } - - pub fn path(&self) -> String { - self.0.path() - } -} diff --git a/hatch/src/cli/commands/build.rs b/hatch/src/cli/commands/build.rs new file mode 100644 index 0000000..059a655 --- /dev/null +++ b/hatch/src/cli/commands/build.rs @@ -0,0 +1,76 @@ +use hatch_error::{ HatchResult, ResultExt, InvalidPathError }; +use clap::{ App, SubCommand, ArgMatches }; +use cli::commands::Command; +use platform::os; +use project::Project; +use assets::PlatformKind; +use task; +use std::process; + +pub struct Build { + name: &'static str +} + +impl<'build> Build { + pub fn new() -> Build { + Build { + name: "build" + } + } + + pub fn execute(&self, project: &Project) -> HatchResult<()> { + if let Some(path) = project.path().to_str() { + let command = format!("cd {} && tup", path); + let mut shell: String; + let mut args: Vec; + match os::platform_type() { + PlatformKind::Windows => { + shell = String::from("cmd"); + args = vec![String::from("/C"), command]; + }, + _ => { + shell = String::from("sh"); + args = vec![String::from("-c"), command]; + } + } + + let mut child = process::Command::new(shell).args(args).spawn()?; + child.wait()?; + + Ok(()) + } else { + Err(InvalidPathError)? + } + } +} + +impl<'command> Command<'command> for Build { + fn cli_subcommand(&self) -> App<'command, 'command> { + SubCommand::with_name(&self.name) + .about("Builds a project.") + .author("Josh Gould ") + } + + fn subcommand_name(&self) -> &'static str { + self.name + } + + fn execute(&self, args: &ArgMatches<'command>) -> HatchResult<()> { + let res = (|| -> HatchResult<()> { + let project_path = self.project_path(args); + let project = task::read_project(&project_path)?; + + println!("Generating assets...\n"); + + task::generate_assets(&project)?; + + println!("Building project...\n"); + + self.execute(&project) + })().with_context(|e| { + format!("Failed to build project : {}", e) + })?; + + Ok(res) + } +} diff --git a/hatch/src/cli/commands/mod.rs b/hatch/src/cli/commands/mod.rs new file mode 100644 index 0000000..5795044 --- /dev/null +++ b/hatch/src/cli/commands/mod.rs @@ -0,0 +1,48 @@ +pub mod new; +pub mod update; +pub mod build; +pub mod test; +pub mod run; + +use hatch_error::HatchResult; +use clap::{ ArgMatches, App }; +use std::path::PathBuf; + +static ARGS: &str = "ARGS"; +static INCLUDE: &str = "INCLUDE"; +static VERSION: &str = "VERSION"; +static TYPE: &str = "TYPE"; +static BIN: &str = "bin"; +static STATIC: &str = "static"; +static SHARED: &str = "shared"; +static PROJECT_NAME: &str = "PROJECT_NAME"; +static PROJECT_NAMES: &str = "PROJECT_NAMES"; +static PROJECT_PATH: &str = "PROJECT_PATH"; + +pub trait Command<'command> { + fn cli_subcommand(&self) -> App<'command, 'command>; + + fn subcommand_name(&self) -> &'static str; + + fn execute(&self, args: &ArgMatches<'command>) -> HatchResult<()>; + + fn project_name(&self, args: &ArgMatches<'command>) -> Option { + value_t!(args, PROJECT_NAME, String).ok() + } + + fn project_path(&self, args: &ArgMatches<'command>) -> PathBuf { + if args.is_present(PROJECT_PATH) { + PathBuf::from(value_t!(args, PROJECT_PATH, String).unwrap().as_str()) + } else { + PathBuf::from("./") + } + } +} + +fn parse_deps_from_cli<'func>(args: &ArgMatches<'func>) -> Vec { + if let Some(values) = args.values_of(INCLUDE) { + values.map(String::from).collect::>() + } else { + Vec::new() + } +} diff --git a/hatch/src/cli/commands/new.rs b/hatch/src/cli/commands/new.rs new file mode 100644 index 0000000..63b1446 --- /dev/null +++ b/hatch/src/cli/commands/new.rs @@ -0,0 +1,201 @@ +use std::fs; +use clap::{ App, SubCommand, Arg, ArgMatches }; +use cli::commands::{ Command, parse_deps_from_cli }; +use deps::clone_project_deps; +use project::{ Project, ProjectKind, LibraryKind }; +use project::build::{ Target, Config }; +use platform::arch::Arch; +use deps::dependency::Dependency; +use locations::{ hatchfile_path, modules_path }; +use hatch_error::{ HatchResult, ResultExt }; +use task; + +// Must use qualified names to avoid conflict. +use std::fmt::Write as FmtWrite; +use std::io::Write as IoWrite; + +use cli::commands::{ INCLUDE, VERSION, TYPE, BIN, STATIC, SHARED, PROJECT_NAME }; + +pub struct New { + name: &'static str, +} + +impl<'new> New { + pub fn new() -> New { + New { + name: "new", + } + } + + fn project_version(&self, args: &ArgMatches<'new>) -> String { + if args.is_present(VERSION) { + value_t!(args, VERSION, String).unwrap() + } else { + "0.0.1".to_owned() + } + } + + fn project_kind(&self, args: &ArgMatches<'new>) -> ProjectKind { + if args.is_present(TYPE) { + let type_arg: String = value_t!(args, TYPE, String).unwrap(); + + // we cannot use the static variables BIN, STATIC, or SHARED directly because it is illegal in + // Rust to pattern match on a static variable + match type_arg.as_str() { + arg if arg == BIN => ProjectKind::Binary, + arg if arg == STATIC => ProjectKind::Library(LibraryKind::Static), + arg if arg == SHARED => ProjectKind::Library(LibraryKind::Shared), + _ => ProjectKind::Library(LibraryKind::Static) + } + } else { + ProjectKind::Library(LibraryKind::Static) + } + } + + fn construct_deps_string(&self, project_deps: &Vec) -> String { + if project_deps.is_empty() { + String::new() + } else { + String::from("deps:\n") + project_deps.iter().map(|d| { + format!(" {}: {}\n", d.name(), d.url()) + }).collect::().as_str() + } + } + + fn construct_config(&self, kind: ProjectKind) -> Config { + let compiler: String = String::from("g++"); + let compiler_flags: Vec = vec![String::from("-c")]; + let linker_flags: Vec = vec![String::from("-v")]; + let mut arch: Arch = Arch::X64; + if let Some(architecture) = Arch::architecture() { + arch = architecture; + } + let target: Target = Target::Debug; + + Config::new(kind, compiler, compiler_flags, linker_flags, arch, target) + } + + fn hatch_yml_contents(&self, + name: &str, + version: &str, + config: &Config, + includes: &str) -> String + { + let mut yaml_output = String::new(); + + let _ = write!(&mut yaml_output, +"name: {} +version: {} +build: + kind: {} + compiler: {} + compiler_flags: {} + linker_flags: {} + arch: {} + target: {} +{}", + &name, + &version, + config.kind(), + config.compiler(), + config.compiler_flags().join(" "), + config.linker_flags().join(" "), + config.arch(), + config.target(), + &includes); + yaml_output + } +} + +impl<'command> Command<'command> for New { + fn cli_subcommand(&self) -> App<'command, 'command> { + SubCommand::with_name(&self.name) + .about("Creates a new project. (default = static library)") + + .arg(Arg::with_name(PROJECT_NAME) + .help("Name of project") + .takes_value(true) + .required(true)) + + .arg(Arg::with_name(TYPE) + .help("Determines the type of the project") + .long("type").short("t") + .takes_value(true) + .possible_values(&[BIN, STATIC, SHARED]) + .required(true)) + + .arg(Arg::with_name(VERSION) + .help("Set the project version") + .long("version").short("v").takes_value(true) + .required(false)) + + .arg(Arg::with_name(INCLUDE) + .help("List URLs to git repositories") + .long("include").short("i").multiple(true).number_of_values(1).takes_value(true) + .required(false)) + } + + fn subcommand_name(&self) -> &'static str { + self.name + } + + fn execute(&self, args: &ArgMatches<'command>) -> HatchResult<()> { + let name = self.project_name(args).unwrap(); + let version = self.project_version(args); + let kind = self.project_kind(args); + + let dir_path = self.project_path(args).join(&name); + let hatch_file = hatchfile_path(&dir_path); + + let deps_from_cli = parse_deps_from_cli(args); + + let res = (|| -> HatchResult<()> { + println!("Creating directory structure..."); + + // create the hatch project file structure + fs::create_dir(&dir_path)?; + fs::create_dir(modules_path(&dir_path))?; + fs::create_dir(dir_path.join("src"))?; + fs::create_dir(dir_path.join("target"))?; + fs::create_dir_all(dir_path.join("test").join("src"))?; + fs::create_dir(dir_path.join("test").join("target"))?; + + let project_deps = deps_from_cli.into_iter().map(|repo| { + Dependency::new(repo) + }).collect::>(); + + if !project_deps.is_empty() { + println!("Installing project dependencies..."); + clone_project_deps(modules_path(&dir_path).as_path(), &project_deps)?; + } + + let includes = self.construct_deps_string(&project_deps); + let config = self.construct_config(kind); + let yaml_output = self.hatch_yml_contents(&name, + &version, + config.as_ref(), + &includes); + + println!("Creating Hatch.yml file..."); + let mut file = fs::File::create(hatch_file)?; + file.write_all(yaml_output.as_bytes())?; + + let project = Project::new(name, + version, + config, + project_deps, + dir_path.to_owned()); + + println!("Generating assets..."); + task::generate_assets(&project)?; + + println!("Finished"); + + Ok(()) + })().with_context(|e| { + format!("Failed to create project at: `{}` : {}", dir_path.display(), e) + })?; + + Ok(res) + } +} diff --git a/hatch/src/cli/commands/run.rs b/hatch/src/cli/commands/run.rs new file mode 100644 index 0000000..93679a4 --- /dev/null +++ b/hatch/src/cli/commands/run.rs @@ -0,0 +1,83 @@ +use std::process::Command as ProcessCommand; +use cli::commands::Command; +use cli::commands::build::Build; +use cli::commands::ARGS; +use hatch_error::{ HatchResult, ResultExt, NullError }; +use task; +use clap::{ App, SubCommand, Arg, ArgMatches }; +use project::ProjectKind; + +pub struct Run { + name: &'static str, +} + +impl<'run> Run { + pub fn new() -> Run { + Run { + name: "run", + } + } +} + +fn parse_run_arguments_from_cli<'command>(cli_args: &ArgMatches<'command>) -> Vec { + if let Some(arguments) = cli_args.values_of(ARGS) { + arguments.map(String::from).collect() + } else { + Vec::new() + } +} + +impl<'command> Command<'command> for Run { + fn cli_subcommand(&self) -> App<'command, 'command> { + SubCommand::with_name(&self.name) + .about("Executes a project.") + .author("Danny Peck ") + + .arg(Arg::with_name(ARGS) + .help("The arguments forwarded to the executable.") + .min_values(0).value_delimiter(" ") + .required(false)) + } + + fn subcommand_name(&self) -> &'static str { + self.name + } + + fn execute(&self, args: &ArgMatches<'command>) -> HatchResult<()> { + let res = (|| -> HatchResult<()> { + let project_path = self.project_path(args); + let project = task::read_project(&project_path)?; + + match *project.config().kind() { + ProjectKind::Binary => { + println!("Generating assets...\n"); + + task::generate_assets(&project)?; + + println!("Building project...\n"); + + Build::new().execute(&project).with_context(|e| { + format!("Failed to build project : {}", e) + })?; + + println!("Executing...\n"); + + let executable_path = format!("{}target/{}", project_path.display(), project.name()); + let run_arguments = parse_run_arguments_from_cli(args); + + let mut child = ProcessCommand::new(&executable_path).args(run_arguments).spawn()?; + child.wait()?; + + Ok(()) + }, + _ => { + Err(NullError).context(format!("Project must be a Binary project."))? + } + } + })().with_context(|e| { + format!("Execution has failed : {}", e) + })?; + + Ok(res) + } +} diff --git a/hatch/src/cli/commands/test.rs b/hatch/src/cli/commands/test.rs new file mode 100644 index 0000000..d8d4ab6 --- /dev/null +++ b/hatch/src/cli/commands/test.rs @@ -0,0 +1,75 @@ +use std::process::Command as ProcessCommand; +use cli::commands::Command; +use cli::commands::build::Build; +use cli::commands::ARGS; +use hatch_error::{ HatchResult, ResultExt }; +use task; +use clap::{ App, SubCommand, Arg, ArgMatches }; + +pub struct Test { + name: &'static str, +} + +impl<'test> Test { + pub fn new() -> Test { + Test { + name: "test", + } + } +} + +fn parse_test_arguments_from_cli<'command>(cli_args: &ArgMatches<'command>) -> Vec { + if let Some(arguments) = cli_args.values_of(ARGS) { + arguments.map(String::from).collect() + } else { + Vec::new() + } +} + +impl<'command> Command<'command> for Test { + fn cli_subcommand(&self) -> App<'command, 'command> { + SubCommand::with_name(&self.name) + .about("Tests a project.") + .author("Danny Peck ") + + .arg(Arg::with_name(ARGS) + .help("The arguments forwarded to the test executable.") + .min_values(0).value_delimiter(" ") + .required(false)) + } + + fn subcommand_name(&self) -> &'static str { + self.name + } + + fn execute(&self, args: &ArgMatches<'command>) -> HatchResult<()> { + let res = (|| -> HatchResult<()> { + let project_path = self.project_path(args); + let project = task::read_project(&project_path)?; + + println!("Generating assets...\n"); + + task::generate_assets(&project)?; + + println!("Building project...\n"); + + Build::new().execute(&project).with_context(|e| { + format!("Failed to build project : {}", e) + })?; + + println!("Executing tests...\n"); + + let test_executable_path = format!("{}test/target/{}.test", project_path.display(), project.name()); + let test_arguments = parse_test_arguments_from_cli(args); + + let mut child = ProcessCommand::new(&test_executable_path).args(test_arguments).spawn()?; + child.wait()?; + + Ok(()) + })().with_context(|e| { + format!("Test execution has failed : {}", e) + })?; + + Ok(res) + } +} diff --git a/hatch/src/cli/commands/update.rs b/hatch/src/cli/commands/update.rs new file mode 100644 index 0000000..ea60727 --- /dev/null +++ b/hatch/src/cli/commands/update.rs @@ -0,0 +1,44 @@ +use hatch_error::HatchResult; +use clap::{ App, SubCommand, Arg, ArgMatches }; +use cli::commands::Command; +use task; + +use cli::commands::PROJECT_NAMES; + +pub struct Update { + name: &'static str +} + +impl<'update> Update { + pub fn new() -> Update { + Update { + name: "update" + } + } +} + +impl<'command> Command<'command> for Update { + fn cli_subcommand(&self) -> App<'command, 'command> { + SubCommand::with_name(&self.name) + .about("Updates project dependencies.") + .version("0.1.0") + .author("Josh Gould ") + + .arg(Arg::with_name(PROJECT_NAMES) + .help("The projects to be updated.") + .min_values(0).value_delimiter(" ") + .required(false)) + } + + fn subcommand_name(&self) -> &'static str { + self.name + } + + fn execute(&self, args: &ArgMatches<'command>) -> HatchResult<()> { + let project = task::read_project(&self.project_path(args))?; + + task::generate_assets(&project)?; + + Ok(()) + } +} diff --git a/hatch/src/cli/mod.rs b/hatch/src/cli/mod.rs new file mode 100644 index 0000000..a8a6664 --- /dev/null +++ b/hatch/src/cli/mod.rs @@ -0,0 +1,31 @@ +pub mod commands; + +#[cfg(test)] +mod tests; + +use clap::{ App, AppSettings, ArgMatches, Arg }; + +pub struct Cli<'cli>(ArgMatches<'cli>); + +impl<'cli> Cli<'cli> { + pub fn new(subcommands: I) -> Cli<'cli> + where I: IntoIterator> { + Cli(App::new("hatch") + .setting(AppSettings::SubcommandRequiredElseHelp) + .setting(AppSettings::DisableVersion) + .subcommands(subcommands.into_iter().map(|s| { + + s.arg(Arg::with_name("PROJECT_PATH") + .help("Path to the project. (default = ./)") + .long("path").short("p") + .required(false) + .takes_value(true)) + + }).collect::>()) + .get_matches()) + } + + pub fn subcommand(&self) -> (&str, Option<&ArgMatches<'cli>>) { + self.0.subcommand() + } +} diff --git a/hatch/src/cli/tests/build.rs b/hatch/src/cli/tests/build.rs new file mode 100644 index 0000000..ed316b3 --- /dev/null +++ b/hatch/src/cli/tests/build.rs @@ -0,0 +1,10 @@ +use cli::commands::build::Build as Build; +use cli::commands::Command; + +#[test] +fn create_build_command() { + let command = Build::new(); + let actual_name = command.subcommand_name().to_owned(); + let expected_name = String::from("build"); + assert_eq!(actual_name, expected_name); +} diff --git a/hatch/src/cli/tests/mod.rs b/hatch/src/cli/tests/mod.rs new file mode 100644 index 0000000..af0168a --- /dev/null +++ b/hatch/src/cli/tests/mod.rs @@ -0,0 +1 @@ +mod build; diff --git a/hatch/src/deps/dependency.rs b/hatch/src/deps/dependency.rs new file mode 100644 index 0000000..1c2b0dc --- /dev/null +++ b/hatch/src/deps/dependency.rs @@ -0,0 +1,42 @@ +use std::path::PathBuf; +use std::ffi::OsStr; +use std::fmt; + +#[derive(Debug)] +pub struct Dependency { + url: String, + name: String, +} + +impl Dependency { + pub fn new(url: String) -> Dependency { + Dependency { + name: Dependency::without_dot_git(Dependency::extract_name(url.clone())), + url, + } + } + + fn without_dot_git(name: String) -> String { + name[..].replace(".git", "") + } + + fn extract_name(url: String) -> String { + let url_path = PathBuf::from(url); + let last_element = url_path.iter().last().unwrap(); + last_element.to_string_lossy().into() + } + + pub fn name(&self) -> &str { + self.name.as_ref() + } + + pub fn url(&self) -> &str { + self.url.as_ref() + } +} + +impl fmt::Display for Dependency { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}: {}", self.name, self.url) + } +} diff --git a/hatch/src/deps/mod.rs b/hatch/src/deps/mod.rs new file mode 100644 index 0000000..9e32fb7 --- /dev/null +++ b/hatch/src/deps/mod.rs @@ -0,0 +1,95 @@ +#[cfg(test)] +mod tests; + +pub mod dependency; + +use hatch_error::{ HatchResult, HatchError }; +use git2::Repository; +use std::collections::HashSet; +use std::fs; +use std::path::{ PathBuf, Path }; +use task; +use self::dependency::Dependency; +use locations::hatchfile_path; + +pub fn clone_dep(url: &str, path: &Path) { + Repository::clone(url, path); +} + +fn walk(path: &Path, + callback: &mut FnMut(&Path) -> HatchResult) -> HatchResult<()> +{ + if !callback(path)? { + return Ok(()) + } + + let dirs = fs::read_dir(path)?; + + for dir in dirs { + let dir = dir?; + if dir.file_type()?.is_dir() { + walk(&dir.path(), callback)?; + } + } + Ok(()) +} + +pub fn clone_project_deps(path: &Path, + user_defined_deps: &Vec) -> HatchResult<()> +{ + let mut visited: HashSet = HashSet::new(); + let mut errored: Vec = Vec::new(); + + // All dependencies are cloned into here + let registry = &path; + + // Clone the dependencies specified on the command line + user_defined_deps.iter().for_each(|dep| { + clone_dep(&dep.url(), &path.join(&dep.name())); + }); + + // Clone the dependencies dependencies + walk(path, &mut |dir| { + // ignore hidden directories and .. + let name = dir.file_name().and_then(|s| s.to_str()); + if name.map(|s| s.starts_with('.')) == Some(true) { + return Ok(false) + } + + // Grab the path to the Hatch.yml starting at `dir` + let hatchfile = hatchfile_path(dir); + + if hatchfile.exists() { + clone_nested_project_deps(®istry, &dir, &mut errored, &mut visited); + } + Ok(true) + })?; + + if !errored.is_empty() { + errored.into_iter().for_each(|e| { + println!("ERROR: {}", e) + }); + } + + Ok(()) +} + +fn clone_nested_project_deps(registry: &Path, + path: &Path, + errored: &mut Vec, + visited: &mut HashSet) +{ + match task::read_project(path) { + Err(e) => { + errored.push(e); + }, + Ok(current_project) => { + if !visited.contains(¤t_project.name().to_owned()) { + current_project.deps().iter().for_each(|dep| { + clone_dep(&dep.url(), ®istry.join(dep.name()).as_path()); + }); + let _ = visited.insert(current_project.name().to_owned()); + } + } + } +} diff --git a/hatch/src/deps/tests/clone_one_dep.rs b/hatch/src/deps/tests/clone_one_dep.rs new file mode 100644 index 0000000..cbef7f5 --- /dev/null +++ b/hatch/src/deps/tests/clone_one_dep.rs @@ -0,0 +1,7 @@ +use deps; +use project::Dependency; + +#[test] +fn clone_one_dep() { + let registry = Path::new("TestProject/hatch_modules"); +} diff --git a/hatch/src/deps/tests/dependency.rs b/hatch/src/deps/tests/dependency.rs new file mode 100644 index 0000000..68c57ff --- /dev/null +++ b/hatch/src/deps/tests/dependency.rs @@ -0,0 +1,23 @@ +use deps::dependency::Dependency; + +#[test] +fn dependency_name() { + let dep = + Dependency::new("https://github.com/CachedNerds/TestProject.git".to_owned()); + + let expected_name = "TestProject"; + let actual_name = dep.name(); + + assert_eq!(expected_name, actual_name); +} + +#[test] +fn dependency_url() { + let dep = + Dependency::new("https://github.com/CachedNerds/TestProject.git".to_owned()); + + let expected_url = "https://github.com/CachedNerds/TestProject.git"; + let actual_url = dep.url(); + + assert_eq!(expected_url, actual_url); +} diff --git a/hatch/src/deps/tests/mod.rs b/hatch/src/deps/tests/mod.rs new file mode 100644 index 0000000..bb1df77 --- /dev/null +++ b/hatch/src/deps/tests/mod.rs @@ -0,0 +1 @@ +mod dependency; diff --git a/hatch/src/dtl/asset.rs b/hatch/src/dtl/asset.rs deleted file mode 100644 index b6ffad1..0000000 --- a/hatch/src/dtl/asset.rs +++ /dev/null @@ -1,62 +0,0 @@ -use project::Project; -use dtl::tup::{ Assets }; - -use dtl::tup::build_system::BuildAssets; -use dtl::tup::project::ProjectAssets; -use dtl::tup::platform::PlatformAssets; -use dtl::tup::test::TestAssets; - -pub fn print_file_path(asset: T) where T: Assets { - println!("{}", asset.path()); -} - -pub fn print_file_contents(asset: T) where T: Assets { - println!("{}", asset.path()); -} - -#[derive(Debug)] -pub enum TupKind { Tuprules, ProjectConfig, ProjectTupfile, ProjectTestTupfile } - -#[derive(Debug)] -pub enum PlatformKind { Linux, Darwin, Win32 } - -#[derive(Debug)] -pub enum AssetKind { Os(PlatformKind), Tup(TupKind) } - -#[derive(Debug)] -pub struct AssetBuilder { - assets: Vec, -} - -impl AssetBuilder { - pub fn new() -> AssetBuilder { - AssetBuilder { - assets: Vec::new(), - } - } - - pub fn assets(&mut self) -> &Vec { - &self.assets.as_ref() - } - - pub fn paths() -> &'static str { - "/C++/libs\n/C++/Toolbox\n/test" - } - - fn generate_tupkind_assets(&self, asset: &TupKind, project: &Project) { - match asset { - Tuprules => print_file_path(BuildAssets::tuprules(&project)), - ProjectConfig => print_file_path(ProjectAssets::config(&project)), - ProjectTupfile => print_file_path(ProjectAssets::tupfile(&project)), - ProjectTestTupfile => print_file_path(TestAssets::tupfile(&project)), - } - } - - fn generate_platformkind_assets(&self, asset: &PlatformKind, project: &Project) { - match asset { - Linux => print_file_path(PlatformAssets::linux(project.path())), - Darwin => print_file_path(PlatformAssets::darwin(project.path())), - Win32 => print_file_path(PlatformAssets::win32(project.path())), - } - } -} diff --git a/hatch/src/dtl/cli.rs b/hatch/src/dtl/cli.rs deleted file mode 100644 index aec1258..0000000 --- a/hatch/src/dtl/cli.rs +++ /dev/null @@ -1,70 +0,0 @@ -use project::{ ProjectKind, LibraryKind }; -use clap::{ App, SubCommand, Arg, AppSettings, ArgMatches }; - -pub struct Cli<'cli>(ArgMatches<'cli>); - -impl<'cli> Cli<'cli> { - pub fn new() -> Cli<'cli> { - - let new_command = SubCommand::with_name("new") - .about("Creates a new project. (default = shared library)") - - .arg(Arg::with_name("TOOLBOX_PATH") - .help("Path to toolbox. (default = ./)") - .long("path").short("p").required(false).takes_value(true)) - - .arg(Arg::with_name("PROJECT_NAME") - .help("Name of project") - .required(true).takes_value(true)) - - .arg(Arg::with_name("bin") - .help("Generate a stand alone executable") - .long("bin").short("b").required(false)) - - .arg(Arg::with_name("static") - .help("Generate a static library") - .long("static").short("s").conflicts_with("bin").required(false)); - - Cli(App::new("hatch") - .setting(AppSettings::SubcommandRequiredElseHelp) - .subcommand(new_command) - .get_matches()) - } - - pub fn build_type(&self) -> ProjectKind { - let arg = self.0.subcommand_matches("new").unwrap(); - - if arg.is_present("bin") { - ProjectKind::Binary - } else if arg.is_present("static") { - ProjectKind::Library(LibraryKind::Static) - } else { - ProjectKind::Library(LibraryKind::Shared) - } - } - - pub fn name(&self) -> String { - let arg = self.0.subcommand_matches("new").unwrap(); - let name = value_t!(arg, "PROJECT_NAME", String).unwrap(); - name - } - - pub fn path(&self) -> String { - let arg = self.0.subcommand_matches("new").unwrap(); - let mut path = String::new(); - - if arg.is_present("TOOLBOX_PATH") { - path.push_str(value_t!(arg, "TOOLBOX_PATH", String).unwrap().as_str()); - } else { - path.push_str("./"); - } - - match path.as_str().chars().last().unwrap() { - '/' => path, - _ => { - path.push_str("/"); - path - } - } - } -} diff --git a/hatch/src/dtl/mod.rs b/hatch/src/dtl/mod.rs deleted file mode 100644 index 16d86d8..0000000 --- a/hatch/src/dtl/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod project; -pub mod asset; -pub mod cli; -pub mod tup; diff --git a/hatch/src/dtl/project.rs b/hatch/src/dtl/project.rs deleted file mode 100644 index 1ce80d6..0000000 --- a/hatch/src/dtl/project.rs +++ /dev/null @@ -1,27 +0,0 @@ -use project::ProjectKind; -use cli::Cli; - -pub struct Project { - name: String, - kind: ProjectKind, - path: String, -} - -impl Project { - pub fn new() -> Project { - let cli = Cli::new(); - Project { name: cli.name(), kind: cli.kind(), path: cli.path() } - } - - pub fn name(&self) -> &str { - self.name.as_ref() - } - - pub fn kind(&self) -> &ProjectKind { - self.kind.as_ref() - } - - pub fn path(&self) -> &str { - self.path.as_ref() - } -} diff --git a/hatch/src/dtl/tup/build_system.rs b/hatch/src/dtl/tup/build_system.rs deleted file mode 100644 index 6a5a989..0000000 --- a/hatch/src/dtl/tup/build_system.rs +++ /dev/null @@ -1,64 +0,0 @@ -use dtl::tup::{ Assets }; -use project::{ Project }; - -pub struct BuildAssets { - file_path: String, - file_contents: String, -} - -impl Assets for BuildAssets { - fn path(&self) -> &str { - &self.file_path.as_str() - } - - fn contents(&self) -> &str { - &self.file_contents.as_str() - } -} - -impl BuildAssets { - pub fn tuprules(project: &Project) -> BuildAssets { - let file_path = project.path().to_string() + "/Tuprules.tup"; - let file_contents = -".gitignore -CC = g++ -# Uncomment to build with debug symbols -#CFLAGS += -g -ARCH = -m64 -#ARCH = -m32 -CFLAGS += $(ARCH) -CFLAGS += -std=c++1z -CFLAGS += -c -CFLAGS += -I ../../ -LINKFLAGS += $(ARCH) -LINKFLAGS += -static -LINKFLAGS += -v -SOURCE = src -SOURCE_OUT = build -SOURCE_FILES = $(SOURCE)/*.cpp -SOURCE_OBJ_FILES = $(SOURCE_OUT)/*.o -TEST = test -TEST_OUT = $(TEST)/build -TEST_FILES = $(TEST)/$(SOURCE)/*.cpp -TEST_OBJ_FILES = $(TEST_OUT)/*.o -# macros -!compile = |> $(CC) $(CFLAGS) %f -o %o |> -!archive = |> ar crs %o %f |> -!link = |> $(CC) $(LINKFLAGS) %f -o %o |> -# includes the STATIC and SHARED variables for the target platform -include @(TUP_PLATFORM).tup -ifeq ($(LIB_TYPE),static) - EXTENSION = $(STATIC) -else - ifeq ($(LIB_TYPE),shared) - EXTENSION = $(SHARED) - else - ifeq ($(LIB_TYPE),both) - EXTENSION = both - endif - endif -endif -PROJECT_LIB = $(PROJECT).$(EXTENSION)".to_string(); - BuildAssets { file_path, file_contents } - } -} diff --git a/hatch/src/dtl/tup/mod.rs b/hatch/src/dtl/tup/mod.rs deleted file mode 100644 index 2d3e71a..0000000 --- a/hatch/src/dtl/tup/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -pub mod build_system; -pub mod project; -pub mod platform; -pub mod test; - -pub trait Assets { - fn contents(&self) -> &str; - fn path(&self) -> &str; -} diff --git a/hatch/src/dtl/tup/platform.rs b/hatch/src/dtl/tup/platform.rs deleted file mode 100644 index 14873a7..0000000 --- a/hatch/src/dtl/tup/platform.rs +++ /dev/null @@ -1,49 +0,0 @@ -use dtl::tup::{ Assets }; - -pub struct PlatformAssets { - file_path: String, - file_contents: String, -} - -impl Assets for PlatformAssets { - fn path(&self) -> &str { - &self.file_path.as_str() - } - - fn contents(&self) -> &str { - &self.file_contents.as_str() - } -} - -impl PlatformAssets { - // Expects path to be /xxxx/xxxx/Toolbox - pub fn linux(path: &str) -> PlatformAssets { - let file_path = path.to_string() + "/linux.tup"; - let file_contents = -"STATIC = a -SHARED = so".to_string(); - PlatformAssets { file_path, file_contents } - } - - // Expects path to be /xxxx/xxxx/Toolbox - pub fn darwin(path: &str) -> PlatformAssets { - let file_path = path.to_string() + "/macosx.tup"; - let file_contents = -"STATIC = a -SHARED = so".to_string(); - PlatformAssets { file_path, file_contents } - } - - // Expects path to be /xxxx/xxxx/Toolbox - pub fn win32(path: &str) -> PlatformAssets { - let file_path = path.to_string() + "/win32.tup"; - let file_contents = -"STATIC = lib -SHARED = dll -# Use clang for front-end -CC = clang++.exe -# Use llvm-lib for static libraries -!archive = |> llvm-lib /MACHINE:X64 /OUT:%o %f |>".to_string(); - PlatformAssets { file_path, file_contents } - } -} diff --git a/hatch/src/dtl/tup/project.rs b/hatch/src/dtl/tup/project.rs deleted file mode 100644 index 4a5f2eb..0000000 --- a/hatch/src/dtl/tup/project.rs +++ /dev/null @@ -1,62 +0,0 @@ -use dtl::tup::{ Assets }; -use project::{ ProjectKind, Project }; - -pub struct ProjectAssets { - file_path: String, - file_contents: String, -} - -impl Assets for ProjectAssets { - fn path(&self) -> &str { - &self.file_path.as_str() - } - - fn contents(&self) -> &str { - &self.file_contents.as_str() - } -} - -impl ProjectAssets { - pub fn config(project: &Project) -> ProjectAssets { - let file_path = project.path().to_string() + "/" + project.name() + "/config.tup"; - - let file_contents = match project.kind() { - &ProjectKind::Library(ref shared_lib) => format!( // {{{ -"PROJECT = {} -LIB_TYPE = shared", // }}} - project.name()).to_string(), - - &ProjectKind::Library(ref static_lib) => format!( // {{{ -"PROJECT = {} -LIB_TYPE = static", // }}} - project.name()).to_string(), - - &ProjectKind::Binary => format!( // {{{ -"PROJECT = {}", // }}} - project.name()).to_string(), - }; - - ProjectAssets { file_path, file_contents } - } - - pub fn tupfile(project: &Project) -> ProjectAssets { - let file_path = project.path().to_string() + "/" + project.name() + "/Tupfile"; - let file_contents = // {{{ -"# order matters -include config.tup -include_rules -# override build variables -# VARIABLE = new_value -# define custom build variables -# Compile Source -: foreach $(SOURCE_FILES) |> !compile |> $(SOURCE_OUT)/%B.o -# Archive Source -: $(SOURCE_OBJ_FILES) |> !archive |> $(SOURCE_OUT)/$(PROJECT_LIB) ../<$(PROJECT)> -# Compile Tests -: foreach $(TEST_FILES) |> !compile |> $(TEST_OUT)/%B.o -# Create Link Executable -: $(TEST_OBJ_FILES) $(SOURCE_OUT)/$(PROJECT_LIB) |> !link |> $(TEST_OUT)/$(PROJECT).test".to_string(); // }}} - - ProjectAssets { file_path, file_contents } - } -} diff --git a/hatch/src/dtl/tup/test.rs b/hatch/src/dtl/tup/test.rs deleted file mode 100644 index 0a7e36f..0000000 --- a/hatch/src/dtl/tup/test.rs +++ /dev/null @@ -1,27 +0,0 @@ -use project::{ Project }; -use dtl::tup::{ Assets }; - -pub struct TestAssets { - file_path: String, - file_contents: String, -} - -impl Assets for TestAssets { - fn path(&self) -> &str { - &self.file_path.as_str() - } - - fn contents(&self) -> &str { - &self.file_contents.as_str() - } -} - -impl TestAssets { - pub fn tupfile(project: &Project) -> TestAssets { - let file_path = project.path().to_string() + "/" + project.name() + "/test/Tupfile"; - let file_contents = -".gitignore".to_string(); - - TestAssets { file_path, file_contents } - } -} diff --git a/hatch/src/hatch_error/mod.rs b/hatch/src/hatch_error/mod.rs new file mode 100644 index 0000000..8bdcd97 --- /dev/null +++ b/hatch/src/hatch_error/mod.rs @@ -0,0 +1,28 @@ +pub use failure::ResultExt; +pub use failure::Error as HatchError; + +pub type HatchResult = Result; + +#[derive(Fail, Debug)] +#[fail(display = "No content in Hatch.yml")] +pub struct EmptyConfigError; + +#[derive(Fail, Debug)] +#[fail(display = "No build field found in Hatch.yml")] +pub struct MissingBuildError; + +#[derive(Fail, Debug)] +#[fail(display = "No name field found in Hatch.yml")] +pub struct MissingNameError; + +#[derive(Fail, Debug)] +#[fail(display = "No version field found in Hatch.yml")] +pub struct MissingVersionError; + +#[derive(Fail, Debug)] +#[fail(display = "Invalid path")] +pub struct InvalidPathError; + +#[derive(Fail, Debug)] +#[fail(display = "")] +pub struct NullError; diff --git a/hatch/src/lib.rs b/hatch/src/lib.rs index ec6961e..825a492 100644 --- a/hatch/src/lib.rs +++ b/hatch/src/lib.rs @@ -1,13 +1,24 @@ #![forbid(unsafe_code)] + #[macro_use] pub extern crate clap; +pub extern crate yaml_rust; +pub extern crate git2; +#[macro_use] +pub extern crate failure; +pub extern crate os_info; +pub extern crate reqwest; pub mod project; pub mod cli; -pub mod asset; -pub mod manifest; -mod dtl; +pub mod hatch_error; +pub mod yaml; +pub mod assets; +pub mod task; +pub mod deps; +pub mod platform; +pub mod locations; #[cfg(test)] mod tests { diff --git a/hatch/src/locations/mod.rs b/hatch/src/locations/mod.rs new file mode 100644 index 0000000..d3529b8 --- /dev/null +++ b/hatch/src/locations/mod.rs @@ -0,0 +1,10 @@ +use std::path::{ Path, PathBuf }; + +pub fn modules_path(base: &Path) -> PathBuf { + base.join("hatch_modules") +} + +pub fn hatchfile_path(base: &Path) -> PathBuf { + base.join("Hatch.yml") +} + diff --git a/hatch/src/locations/tests/hatchfile_path.rs b/hatch/src/locations/tests/hatchfile_path.rs new file mode 100644 index 0000000..980550b --- /dev/null +++ b/hatch/src/locations/tests/hatchfile_path.rs @@ -0,0 +1,12 @@ +use deps; +use std::path::{ Path, PathBuf }; + +#[test] +fn hatchfile_path() { + let path = Path::new("TestProject"); + + let expected_path = PathBuf::from("TestProject").join("Hatch.yml"); + let actual_path = deps::hatchfile_path(path); + + assert_eq!(expected_path, actual_path); +} diff --git a/hatch/src/locations/tests/mod.rs b/hatch/src/locations/tests/mod.rs new file mode 100644 index 0000000..5046955 --- /dev/null +++ b/hatch/src/locations/tests/mod.rs @@ -0,0 +1,2 @@ +mod hatchfile_path; +mod modules_path; diff --git a/hatch/src/locations/tests/modules_path.rs b/hatch/src/locations/tests/modules_path.rs new file mode 100644 index 0000000..47c5da9 --- /dev/null +++ b/hatch/src/locations/tests/modules_path.rs @@ -0,0 +1,12 @@ +use deps; +use std::path::{ Path, PathBuf }; + +#[test] +fn modules_path() { + let path = Path::new("TestProject"); + + let expected_path = PathBuf::from("TestProject").join("hatch_modules"); + let actual_path = deps::modules_path(path); + + assert_eq!(expected_path, actual_path); +} diff --git a/hatch/src/manifest.rs b/hatch/src/manifest.rs deleted file mode 100644 index 252e5ec..0000000 --- a/hatch/src/manifest.rs +++ /dev/null @@ -1,16 +0,0 @@ -use asset::Asset; -use project::Project; - -pub struct Manifest { - project: Project, - assets: Asset, -} - -impl Manifest { - pub fn new() -> Manifest { - Manifest { - project: Project::new(), - assets: Asset::new(), - } - } -} diff --git a/hatch/src/platform/arch.rs b/hatch/src/platform/arch.rs new file mode 100644 index 0000000..fdf7d5a --- /dev/null +++ b/hatch/src/platform/arch.rs @@ -0,0 +1,30 @@ +use std::mem::size_of; +use std::fmt; + +#[derive(Debug)] +pub enum Arch { X64, X86 } + +impl AsRef for Arch { + fn as_ref(&self) -> &Arch { + &self + } +} + +impl fmt::Display for Arch { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Arch::X64 => write!(f, "x64"), + Arch::X86 => write!(f, "x86"), + } + } +} + +impl Arch { + pub fn architecture() -> Option { + match size_of::<&char>() { + 32 => Some(Arch::X86), + 64 => Some(Arch::X64), + _ => None + } + } +} diff --git a/hatch/src/platform/mod.rs b/hatch/src/platform/mod.rs new file mode 100644 index 0000000..dfa15f5 --- /dev/null +++ b/hatch/src/platform/mod.rs @@ -0,0 +1,2 @@ +pub mod arch; +pub mod os; diff --git a/hatch/src/platform/os.rs b/hatch/src/platform/os.rs new file mode 100644 index 0000000..470626d --- /dev/null +++ b/hatch/src/platform/os.rs @@ -0,0 +1,11 @@ +use assets::PlatformKind; +use os_info; +use os_info::Type::{ Macos, Windows }; + +pub fn platform_type() -> PlatformKind { + match *os_info::get().os_type() { + Macos => PlatformKind::MacOS, + Windows => PlatformKind::Windows, + _ => PlatformKind::Linux + } +} diff --git a/hatch/src/project.rs b/hatch/src/project.rs deleted file mode 100644 index 49e45ca..0000000 --- a/hatch/src/project.rs +++ /dev/null @@ -1,31 +0,0 @@ -use dtl::project as project_imp; - -pub struct Project (project_imp::Project); - -impl Project { - pub fn new() -> Project { - Project(project_imp::Project::new()) - } - - pub fn name(&self) -> &str { - self.0.name() - } - - pub fn kind(&self) -> &ProjectKind { - self.0.kind() - } - - pub fn path(&self) -> &str { - self.0.path() - } -} - -pub enum LibraryKind { Shared, Static } - -pub enum ProjectKind { Binary, Library(LibraryKind) } - -impl AsRef for ProjectKind { - fn as_ref(&self) -> &ProjectKind { - &self - } -} diff --git a/hatch/src/project/build.rs b/hatch/src/project/build.rs new file mode 100644 index 0000000..22f3edc --- /dev/null +++ b/hatch/src/project/build.rs @@ -0,0 +1,81 @@ +use std::fmt; +use project::ProjectKind; +use platform::arch::Arch; + +#[derive(Debug)] +pub struct Config { + kind: ProjectKind, + compiler: String, + compiler_flags: Vec, + linker_flags: Vec, + arch: Arch, + target: Target +} + +impl Config { + pub fn new(kind: ProjectKind, + compiler: String, + compiler_flags: Vec, + linker_flags: Vec, + arch: Arch, + target: Target) -> Config + { + Config { + kind, + compiler, + compiler_flags, + linker_flags, + arch, + target + } + } + + pub fn kind(&self) -> &ProjectKind { + self.kind.as_ref() + } + + pub fn compiler(&self) -> &str { + self.compiler.as_ref() + } + + pub fn compiler_flags(&self) -> &Vec { + self.compiler_flags.as_ref() + } + + pub fn linker_flags(&self) -> &Vec { + self.linker_flags.as_ref() + } + + pub fn arch(&self) -> &Arch { + self.arch.as_ref() + } + + pub fn target(&self) -> &Target { + self.target.as_ref() + } +} + +impl AsRef for Config { + fn as_ref(&self) -> &Config { + &self + } +} + +#[derive(Debug)] +pub enum Target { Debug, Release } + +impl AsRef for Target { + fn as_ref(&self) -> &Target { + &self + } +} + +impl fmt::Display for Target { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Target::Debug => write!(f, "debug"), + Target::Release => write!(f, "release"), + } + } +} + diff --git a/hatch/src/project/mod.rs b/hatch/src/project/mod.rs new file mode 100644 index 0000000..bed6fd2 --- /dev/null +++ b/hatch/src/project/mod.rs @@ -0,0 +1,74 @@ +pub mod build; + +use std::fmt; +use std::path::PathBuf; +use self::build::Config; +use deps::dependency::Dependency; + +#[derive(Debug)] +pub struct Project { + name: String, + version: String, + config: Config, + deps: Vec, + path: PathBuf +} + +impl Project { + pub fn new(name: String, + version: String, + config: Config, + deps: Vec, + path: PathBuf) -> Project + { + Project { + name, + version, + config, + deps, + path + } + } + + pub fn name(&self) -> &str { + self.name.as_ref() + } + + pub fn version(&self) -> &str { + self.version.as_ref() + } + + pub fn config(&self) -> &Config { + self.config.as_ref() + } + + pub fn deps(&self) -> &Vec { + self.deps.as_ref() + } + + pub fn path(&self) -> &PathBuf { + &self.path + } +} + +#[derive(Debug)] +pub enum LibraryKind { Shared, Static } + +#[derive(Debug)] +pub enum ProjectKind { Binary, Library(LibraryKind) } + +impl AsRef for ProjectKind { + fn as_ref(&self) -> &ProjectKind { + &self + } +} + +impl fmt::Display for ProjectKind { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + ProjectKind::Library(LibraryKind::Shared) => write!(f, "shared-lib"), + ProjectKind::Library(LibraryKind::Static) => write!(f, "static-lib"), + ProjectKind::Binary => write!(f, "binary"), + } + } +} diff --git a/hatch/src/task/mod.rs b/hatch/src/task/mod.rs new file mode 100644 index 0000000..c1dec3e --- /dev/null +++ b/hatch/src/task/mod.rs @@ -0,0 +1,25 @@ +#[cfg(test)] +pub mod tests; + +use project::Project; +use assets::builder::Builder as AssetBuilder; +use std::path::Path; +use hatch_error::{ HatchResult, ResultExt }; +use assets::generator; +use yaml; + +pub fn read_project(path: &Path) -> HatchResult { + let project = yaml::parse(path, String::from("Hatch.yml")).with_context(|e| { + format!("failed to read project at `{}` : {}", path.display(), e) + })?; + + Ok(project) +} + +pub fn generate_assets(project: &Project) -> HatchResult<()> { + generator::generate_all(AssetBuilder::from(project).assets()).with_context(|e| { + format!("asset generation failed : `{}`", e) + })?; + + Ok(()) +} diff --git a/hatch/src/task/tests.rs b/hatch/src/task/tests.rs new file mode 100644 index 0000000..924c531 --- /dev/null +++ b/hatch/src/task/tests.rs @@ -0,0 +1,58 @@ +use task; +use project::{ Project, ProjectKind }; +use project::build::{ Target, Config }; +use platform::arch::Arch; +use platform::os; +use assets::PlatformKind; +use std::fs; +use std::path::{ Path, PathBuf }; + +fn assets_exist(path: &Path) -> bool { + let file_path = match os::platform_type() { + PlatformKind::MacOS => path.join("macosx.tup"), + PlatformKind::Windows => path.join("win32.tup"), + PlatformKind::Linux => path.join("linux.tup") + }; + + path.join("Tupfile").exists() && + path.join("config.tup").exists() && + path.join("Tuprules.tup").exists() && + path.join("Tupfile.ini").exists() && + path.join("test").join("Tupfile").exists() && + path.join("test/src").join("catch.hpp").exists() && + path.join("test/src").join("catch.cpp").exists() && + file_path.exists() +} + +fn remove_assets(path: &Path) { + fs::remove_dir_all(&path); +} + +#[test] +fn generate_assets_success() { + let path = PathBuf::from("./temp/"); + fs::create_dir_all(&path); + + let config = Config::new(ProjectKind::Binary, + String::from("g++"), + vec![String::from("-c"), String::from("--std=c++1z")], + vec![String::from("-v")], + Arch::X64, + Target::Release); + + let project = Project::new(String::from("test"), + String::from("0.1.0"), + config, + Vec::new(), + PathBuf::from(&path)); + + if let Err(e) = task::generate_assets(&project) { + remove_assets(&path); + panic!(e) + } + + let exists = assets_exist(&path); + remove_assets(&path); + + assert!(exists); +} diff --git a/hatch/src/yaml.rs b/hatch/src/yaml.rs new file mode 100644 index 0000000..d6d5bd4 --- /dev/null +++ b/hatch/src/yaml.rs @@ -0,0 +1,159 @@ +use std::fs; +use std::io::Read; +use std::path::{ Path, PathBuf }; +use yaml_rust::{ Yaml, YamlLoader }; +use project::{ Project, LibraryKind, ProjectKind }; +use project::build::{ Target, Config }; +use deps::dependency::Dependency; +use platform::arch::Arch; + +use hatch_error::{ + HatchResult, + ResultExt, + MissingNameError, + MissingBuildError, + MissingVersionError, + EmptyConfigError, +}; + +pub fn parse(path: &Path, name: String) -> HatchResult { + let yml_vec = from_file(path.join(name).as_path())?; + + if yml_vec.is_empty() { + return Err(EmptyConfigError)?; + } + + let name: String; + let version: String; + let mut kind: ProjectKind = ProjectKind::Library(LibraryKind::Static); + let mut compiler: String = String::from("g++"); + let mut compiler_flags: Vec = vec![String::from("-c")]; + let mut linker_flags: Vec = vec![String::from("-v")]; + let mut arch: Arch = Arch::X64; + if let Some(architecture) = Arch::architecture() { + arch = architecture; + } + let mut target: Target = Target::Debug; + let deps: Vec; + + if let Some(n) = yml_vec[0]["name"].as_str() { + name = n.to_owned(); + } else { + return Err(MissingNameError)?; + } + + if let Some(v) = yml_vec[0]["version"].as_str() { + version = v.to_owned(); + } else { + return Err(MissingVersionError)?; + } + + if let Some(configurations) = yml_vec[0]["build"].as_hash() { + let items = configurations + .iter() + .map(|(k, v)| { + (k.as_str(), v.as_str()) + }) + .filter(|&(k, v)| { + k.is_some() && v.is_some() + }) + .map(|(k, v)| { + (k.unwrap(), v.unwrap()) + }).collect::>(); + + for (key, value) in items { + match key { + "kind" => { + kind = match value { + "static-lib" => ProjectKind::Library(LibraryKind::Static), + "shared-lib" => ProjectKind::Library(LibraryKind::Shared), + _ => ProjectKind::Binary + } + }, + "compiler" => { + compiler = String::from(value); + }, + "compiler_flags" => { + compiler_flags = + String::from(value) + .split_whitespace() + .map(String::from) + .collect(); + }, + "linker_flags" => { + linker_flags = + String::from(value) + .split_whitespace() + .map(String::from) + .collect(); + }, + "arch" => { + match value { + "x64" => { + arch =Arch::X64 + }, + "x86" => { + arch = Arch::X86 + }, + _ => { + // use default + } + } + }, + "target" => { + match value { + "debug" => { + target = Target::Debug + }, + "release" => { + target = Target::Release + }, + _ => { + // use default + } + } + }, + _ => {} + } + } + } else { + return Err(MissingBuildError)?; + } + + if let Some(d) = yml_vec[0]["deps"].as_hash() { + deps = d + .iter() + .filter_map(|(_k, v)| v.as_str()) + .map(|v| Dependency::new(v.to_owned())) + .collect(); + } else { + deps = Vec::new(); + } + + let config = Config::new(kind, compiler, compiler_flags, linker_flags, arch, target); + Ok(Project::new(name, version, config, deps, PathBuf::from(path))) +} + +fn from_file(file_name: &Path) -> HatchResult> { + let mut file = fs::File::open(&file_name).with_context(|_| { + format!("failed to open file: `{}`", &file_name.display()) + })?; + + let mut contents = String::new(); + file.read_to_string(&mut contents).with_context(|_| { + format!("failed to read contents of: `{}`", file_name.display()) + })?; + + let res = YamlLoader::load_from_str(&contents).compat().with_context(|e| { + format!("Parsing error: `{}`", e) + })?; + + Ok(res) +} + +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + } +}