diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..c980350f8 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,23 @@ +# How to Contribute + +We'd love to accept your patches and contributions to this project. There are +just a few small guidelines you need to follow. + +## Contributor License Agreement + +Contributions to this project must be accompanied by a Contributor License +Agreement. You (or your employer) retain the copyright to your contribution; +this simply gives us permission to use and redistribute your contributions as +part of the project. Head over to to see +your current agreements on file or to sign a new one. + +You generally only need to submit a CLA once, so if you've already submitted one +(even if it was for a different project), you probably don't need to do it +again. + +## Code reviews + +All submissions, including submissions by project members, require review. We +use GitHub pull requests for this purpose. Consult +[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more +information on using pull requests. diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 000000000..b4b76e523 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1064 @@ +[[package]] +name = "advapi32-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 = "aho-corasick" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "aho-corasick" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "backtrace" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace-sys 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "dbghelp-sys 0.2.0 (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.24 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "backtrace-sys" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (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 = "cargo" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "advapi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crates-io 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "curl 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "docopt 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", + "fs2 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "git2 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "git2-curl 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "jobserver 0.1.6 (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.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libgit2-sys 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)", + "psapi-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_ignored 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cargo-raze" +version = "0.0.14" +dependencies = [ + "cargo 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hamcrest 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tera 0.11.0-beta.4 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cfg-if" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "chrono" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cmake" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crates-io" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "curl 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "curl" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "curl-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "curl-sys" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.14 (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.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "dbghelp-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 = "docopt" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "dtoa" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "either" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "env_logger" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "error-chain" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "error-chain" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "filetime" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "flate2" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "miniz-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "foreign-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "fs2" +version = "0.4.2" +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.24 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "gcc" +version = "0.3.51" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "git2" +version = "0.6.6" +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.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libgit2-sys 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "git2-curl" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "curl 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "git2 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "glob" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "hamcrest" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "humansize" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "idna" +version = "0.1.2" +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.3 (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 = "itertools" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "itoa" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "jobserver" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.15 (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 = "lazy_static" +version = "0.2.8" +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 = "libc" +version = "0.2.24" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libgit2-sys" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", + "curl-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (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.16 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.14 (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.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.14 (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.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (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.8" +source = "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 = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "memchr" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "miniz-sys" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (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.29 (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 = "net2" +version = "0.2.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.1 (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.24 (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" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-bigint 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "num-complex 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", + "num-rational 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-bigint" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-complex" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-integer" +version = "0.1.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-iter" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-rational" +version = "0.1.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-bigint 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-traits" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "num_cpus" +version = "1.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "openssl" +version = "0.9.14" +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.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "openssl-probe" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "openssl-sys" +version = "0.9.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (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 = "percent-encoding" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "pest" +version = "1.0.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "pest_derive" +version = "1.0.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "pest 1.0.0-rc.1 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.10.8 (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 = "psapi-sys" +version = "0.1.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 = "quote" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rand" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "redox_syscall" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "regex" +version = "0.1.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.4 (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.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "regex-syntax" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rustc-demangle" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rustc-serialize" +version = "0.3.24" +source = "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 = "semver" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde_derive" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_derive_internals" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", + "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_ignored" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_json" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "shell-escape" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "slug" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unidecode 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "socket2" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.1 (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.24 (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 = "strsim" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "syn" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (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 = "syn" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "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 = "tar" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (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.15 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tera" +version = "0.11.0-beta.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "chrono 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "humansize 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pest 1.0.0-rc.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pest_derive 1.0.0-rc.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "slug 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "term" +version = "0.4.6" +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)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "thread-id" +version = "2.0.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.24 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "thread_local" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "thread_local" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 0.2.8 (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.38" +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.24 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "toml" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.3" +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-xid" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unidecode" +version = "0.2.0" +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.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "idna 0.1.2 (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.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "utf8-ranges" +version = "0.1.3" +source = "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 = "vcpkg" +version = "0.2.2" +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-build" +version = "0.1.1" +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)", +] + +[metadata] +"checksum advapi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e06588080cb19d0acb6739808aafa5f26bfb2ca015b2b6370028b44cf7cb8a9a" +"checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66" +"checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699" +"checksum backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "72f9b4182546f4b04ebc4ab7f84948953a118bd6021a1b6a6c909e3e94f6be76" +"checksum backtrace-sys 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "afccc5772ba333abccdf60d55200fa3406f8c59dcf54d5f7998c9107d3799c7c" +"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" +"checksum cargo 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "594a86eae348b57fdebbe894fb60c070b46ff673386901779d85f3b5418fd8c0" +"checksum cfg-if 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c47d456a36ebf0536a6705c83c1cbbcb9255fbc1d905a6ded104f479268a29" +"checksum chrono 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7c20ebe0b2b08b0aeddba49c609fe7957ba2e33449882cb186a180bc60682fa9" +"checksum cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b8ebbb35d3dc9cd09497168f33de1acb79b265d350ab0ac34133b98f8509af1f" +"checksum crates-io 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "341e08bc12f50de704649e7472d39bb55dea3ef1ff65dc4301257ea41a048a5f" +"checksum crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5ea215664ca264da8a9d9c3be80d2eaf30923c259d03e870388eb927508f97" +"checksum curl 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6689276ab61f97c660669a5ecc117c36875dfc1ba301c986b16c653415bdf9d7" +"checksum curl-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d5481162dc4f424d088581db2f979fa7d4c238fe9794595de61d8d7522e277de" +"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850" +"checksum docopt 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab32ea6e284d87987066f21a9e809a73c14720571ef34516f0890b3d355ccfd8" +"checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90" +"checksum either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18785c1ba806c258137c937e44ada9ee7e69a37e3c72077542cd2f069d78562a" +"checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b" +"checksum error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9435d864e017c3c6afeac1654189b06cdb491cf2ff73dbf0d73b0f292f42ff8" +"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" +"checksum filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5363ab8e4139b8568a6237db5248646e5a8a2f89bd5ccb02092182b11fd3e922" +"checksum flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)" = "36df0166e856739905cd3d7e0b210fe818592211a008862599845e012d8d304c" +"checksum foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e4056b9bd47f8ac5ba12be771f77a0dae796d1bbaaf5fd0b9c2d38b69b8a29d" +"checksum fs2 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9ab76cfd2aaa59b7bf6688ad9ba15bbae64bff97f04ea02144cfd3443e5c2866" +"checksum gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)" = "120d07f202dcc3f72859422563522b66fe6463a4c513df062874daad05f85f0a" +"checksum git2 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aa01936ac96555c083c0e8553f672616274408d9d3fc5b8696603fbf63ff43ee" +"checksum git2-curl 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "68676bc784bf0bef83278898929bf64a251e87c0340723d0b93fa096c9c5bf8e" +"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" +"checksum hamcrest 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d9e7f519847c8937313ee2f5c9caf3cbe724cca6169ad59258b9fb86813b53" +"checksum humansize 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "92d211e6e70b05749dce515b47684f29a3c8c38bbbb21c50b30aff9eca1b0bd3" +"checksum idna 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2233d4940b1f19f0418c158509cd7396b8d70a5db5705ce410914dc8fa603b37" +"checksum itertools 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e58359414720377f59889192f1ec0e726049ce5735bc21fdb0c4c8ae638305bb" +"checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c" +"checksum jobserver 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "443ae8bc0af6c106e6e8b77e04684faecc1a5ce94e058f4c2b0a037b0ea1b133" +"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +"checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf" +"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" +"checksum libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)" = "38f5c2b18a287cf78b4097db62e20f43cace381dc76ae5c0a3073067f78b7ddc" +"checksum libgit2-sys 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "df18a822100352d9863b302faf6f8f25c0e77f0e60feb40e5dbe1238b7f13b1d" +"checksum libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0db4ec23611747ef772db1c4d650f8bd762f07b461727ec998f953c614024b75" +"checksum libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "3fdd64ef8ee652185674455c1d450b83cbc8ad895625d543b5324d923f82e4d8" +"checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b" +"checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" +"checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" +"checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4" +"checksum miniz-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "28eaee17666671fa872e567547e8428e83308ebe5808cdf6a0e28397dbe2c726" +"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" +"checksum net2 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)" = "bc01404e7568680f1259aa5729539f221cb1e6d047a0d9053cab4be8a73b5d67" +"checksum num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "a311b77ebdc5dd4cf6449d81e4135d9f0e3b153839ac90e648a8ef538f923525" +"checksum num-bigint 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "8fd0f8dbb4c0960998958a796281d88c16fbe68d87b1baa6f31e2979e81fd0bd" +"checksum num-complex 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "503e668405c5492d67cf662a81e05be40efe2e6bcf10f7794a07bd9865e704e6" +"checksum num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "d1452e8b06e448a07f0e6ebb0bb1d92b8890eea63288c0b627331d53514d0fba" +"checksum num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "7485fcc84f85b4ecd0ea527b14189281cf27d60e583ae65ebc9c088b13dffe01" +"checksum num-rational 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "288629c76fac4b33556f4b7ab57ba21ae202da65ba8b77466e6d598e31990790" +"checksum num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "99843c856d68d8b4313b03a17e33c4bb42ae8f6610ea81b28abe076ac721b9b0" +"checksum num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aec53c34f2d0247c5ca5d32cca1478762f301740468ee9ee6dcb7a0dd7a0c584" +"checksum openssl 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)" = "11ba043cb65fc9af71a431b8a36ffe8686cd4751cdf70a473ec1d01066ac7e41" +"checksum openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d98df0270d404ccd3c050a41d579c52d1db15375168bb3471e04ec0f5f378daf" +"checksum openssl-sys 0.9.14 (registry+https://github.com/rust-lang/crates.io-index)" = "236c718c2e2c2b58a546d86ffea5194400bb15dbe01ca85325ffd357b03cf66c" +"checksum percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de154f638187706bde41d9b4738748933d64e6b37bdbffc0b47a97d16a6ae356" +"checksum pest 1.0.0-rc.1 (registry+https://github.com/rust-lang/crates.io-index)" = "db7f3627b99404d593124b61af5f7b73d1d4b1cd8c606380242baca93a6c51f9" +"checksum pest_derive 1.0.0-rc.1 (registry+https://github.com/rust-lang/crates.io-index)" = "285cc1fdf6173ba839d355fa61ff7a41bf69d0ffa45ca4ee9aa2125ce85c2b13" +"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903" +"checksum psapi-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "abcd5d1a07d360e29727f757a9decb3ce8bc6e0efa8969cfaad669a8317a2478" +"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" +"checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d" +"checksum redox_syscall 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "3c9309631a35303bffb47e397198e3668cb544fe8834cd3da2a744441e70e524" +"checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f" +"checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b" +"checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" +"checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db" +"checksum rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3058a43ada2c2d0b92b3ae38007a2d0fa5e9db971be260e0171408a4ff471c95" +"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" +"checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d" +"checksum semver 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fdd61b85a0fa777f7fb7c454b9189b2941b110d1385ce84d7f76efdf1606a85" +"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +"checksum serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f7726f29ddf9731b17ff113c461e362c381d9d69433f79de4f3dd572488823e9" +"checksum serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cf823e706be268e73e7747b147aa31c8f633ab4ba31f115efb57e5047c3a76dd" +"checksum serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37aee4e0da52d801acfbc0cc219eb1eda7142112339726e427926a6f6ee65d3a" +"checksum serde_ignored 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c10e798e4405d7dcec3658989e35ee6706f730a9ed7c1184d5ebd84317e82f46" +"checksum serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "48b04779552e92037212c3615370f6bd57a40ebba7f20e554ff9f55e41a69a7b" +"checksum shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dd5cc96481d54583947bfe88bf30c23d53f883c6cd0145368b69989d97b84ef8" +"checksum slug 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f5ff4b43cb07b86c5f9236c92714a22cdf9e5a27a7d85e398e2c9403328cb8" +"checksum socket2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "12cdbddbaa27bf94cc194b8e37f5811db6fe83cea96cf99cf1f8e92b65a41371" +"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694" +"checksum syn 0.10.8 (registry+https://github.com/rust-lang/crates.io-index)" = "58fd09df59565db3399efbba34ba8a2fec1307511ebd245d0061ff9d42691673" +"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 tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "281285b717926caa919ad905ef89c63d75805c7d89437fb873100925a53f2b1b" +"checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6" +"checksum tera 0.11.0-beta.4 (registry+https://github.com/rust-lang/crates.io-index)" = "dc20257da631478e47a94e6e69e200fc28f39ed0426548759d28c766ca9d3994" +"checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" +"checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" +"checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" +"checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14" +"checksum time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "d5d788d3aa77bc0ef3e9621256885555368b47bd495c13dd2e7413c89f845520" +"checksum toml 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3e5e16033aacf7eead46cbcb62d06cf9d1c2aa1b12faa4039072f7ae5921103b" +"checksum unicode-bidi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a6a2c4e3710edd365cd7e78383153ed739fa31af19f9172f72d3575060f5a43a" +"checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f" +"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" +"checksum unidecode 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d2adb95ee07cd579ed18131f2d9e7a17c25a4b76022935c7f2460d2bfae89fd2" +"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +"checksum url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb819346883532a271eb626deb43c4a1bb4c4dd47c519bd78137c3e72a4fe27" +"checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" +"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" +"checksum vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9e0a7d8bed3178a8fb112199d466eeca9ed09a14ba8ad67718179b4fd5487d0b" +"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-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" +"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 000000000..108d5713d --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "cargo-raze" +version = "0.0.16" +authors = ["Alex McArther "] +readme = "README.md" +keywords = ["subcommand"] +license = "Apache-2.0" +description = """ +A Cargo subcommand to generate Bazel BUILD files +""" + +[dependencies] +rustc-serialize = "0.3" +cargo = "0.20.0" +itertools = "0.6.0" +tera = "0.11.0-beta.4" +serde_derive = "1.0.11" +serde = "1.0.11" +toml = "0.4.4" + +[dev-dependencies] +tempdir = "0.3.5" +lazy_static = "0.2.8" +hamcrest = "0.1.3" diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md new file mode 100644 index 000000000..6a21321ae --- /dev/null +++ b/README.md @@ -0,0 +1,10 @@ +# cargo-raze: Bazel BUILD generation for Rust Crates + +A support Cargo plugin for distilling a workspace-level Cargo.toml into BUILD +targets that code using [rules_rust](https://github.com/bazelbuild/rules_rust) +can depend on directly. + +### Disclaimer + +This is not an official Google product (experimental or otherwise), it is just code that happens to be owned by Google. + diff --git a/src/bazel.rs b/src/bazel.rs new file mode 100644 index 000000000..b7f874d1b --- /dev/null +++ b/src/bazel.rs @@ -0,0 +1,271 @@ +use cargo::util::CargoResult; +use cargo::CargoError; +use context::CrateContext; +use context::WorkspaceContext; +use planning::PlannedBuild; +use rendering::BuildRenderer; +use rendering::FileOutputs; +use rendering::RenderDetails; +use tera::Context; +use tera::Tera; +use tera; + +pub struct BazelRenderer { + internal_renderer: Tera, +} + +impl BazelRenderer { + pub fn new() -> BazelRenderer { + // Configure tera with a bogus template dir: We don't want any runtime template support + let mut renderer = Tera::new("src/not/a/dir/*").unwrap(); + renderer.add_raw_templates(vec![ + ("templates/partials/build_script.template", include_str!("templates/partials/build_script.template")), + ("templates/partials/remote_build_script.template", include_str!("templates/partials/remote_build_script.template")), + ("templates/partials/rust_binary.template", include_str!("templates/partials/rust_binary.template")), + ("templates/partials/remote_rust_binary.template", include_str!("templates/partials/remote_rust_binary.template")), + ("templates/partials/rust_library.template", include_str!("templates/partials/rust_library.template")), + ("templates/partials/remote_rust_library.template", include_str!("templates/partials/remote_rust_library.template")), + ("templates/workspace.BUILD.template", include_str!("templates/workspace.BUILD.template")), + ("templates/remote_workspace.BUILD.template", include_str!("templates/remote_workspace.BUILD.template")), + ("templates/crate.BUILD.template", include_str!("templates/crate.BUILD.template")), + ("templates/remote_crates.bzl.template", include_str!("templates/remote_crates.bzl.template")), + ("templates/remote_crate.BUILD.template", include_str!("templates/remote_crate.BUILD.template"))]).unwrap(); + + BazelRenderer { + internal_renderer: renderer, + } + } + + pub fn render_crate(&self, workspace_context: &WorkspaceContext, package: &CrateContext) -> Result { + let mut context = Context::new(); + context.add("workspace", &workspace_context); + context.add("crate", &package); + self.internal_renderer.render("templates/crate.BUILD.template", &context) + } + + pub fn render_aliases(&self, workspace_context: &WorkspaceContext, all_packages: &Vec) -> Result { + let mut context = Context::new(); + context.add("workspace", &workspace_context); + context.add("crates", &all_packages); + self.internal_renderer.render("templates/workspace.BUILD.template", &context) + } + + pub fn render_remote_crate(&self, workspace_context: &WorkspaceContext, package: &CrateContext) -> Result { + let mut context = Context::new(); + context.add("workspace", &workspace_context); + context.add("crate", &package); + self.internal_renderer.render("templates/remote_crate.BUILD.template", &context) + } + + pub fn render_remote_aliases(&self, workspace_context: &WorkspaceContext, all_packages: &Vec) -> Result { + let mut context = Context::new(); + context.add("workspace", &workspace_context); + context.add("crates", &all_packages); + self.internal_renderer.render("templates/remote_workspace.BUILD.template", &context) + } + + pub fn render_bzl_fetch(&self, workspace_context: &WorkspaceContext, all_packages: &Vec) -> Result { + let mut context = Context::new(); + context.add("workspace", &workspace_context); + context.add("crates", &all_packages); + self.internal_renderer.render("templates/remote_crates.bzl.template", &context) + } +} + +impl BuildRenderer for BazelRenderer { + fn render_planned_build(&mut self, render_details: &RenderDetails, planned_build: &PlannedBuild) -> CargoResult> { + let &RenderDetails { ref path_prefix, .. } = render_details; + let &PlannedBuild { ref workspace_context, ref crate_contexts, .. } = planned_build; + let mut file_outputs = Vec::new(); + + for package in crate_contexts { + let build_file_path = format!("{}/{}BUILD", &path_prefix, &package.path); + let rendered_crate_build_file = try!(self.render_crate(&workspace_context, &package).map_err(|e| CargoError::from(e.to_string()))); + file_outputs.push(FileOutputs { path: build_file_path, contents: rendered_crate_build_file }) + } + + let build_file_path = format!("{}/vendor/BUILD", &path_prefix); + let rendered_alias_build_file = try!(self.render_aliases(&workspace_context, &crate_contexts).map_err(|e| CargoError::from(e.to_string()))); + file_outputs.push(FileOutputs { path: build_file_path, contents: rendered_alias_build_file }); + Ok(file_outputs) + } + + fn render_remote_planned_build(&mut self, render_details: &RenderDetails, planned_build: &PlannedBuild) -> CargoResult> { + let &RenderDetails { ref path_prefix, .. } = render_details; + let &PlannedBuild { ref workspace_context, ref crate_contexts, .. } = planned_build; + let mut file_outputs = Vec::new(); + + for package in crate_contexts { + let build_file_path = format!("{}-{}.BUILD", &package.pkg_name, &package.pkg_version); + let rendered_crate_build_file = try!(self.render_remote_crate(&workspace_context, &package).map_err(|e| CargoError::from(e.to_string()))); + file_outputs.push(FileOutputs { path: build_file_path, contents: rendered_crate_build_file }) + } + + let alias_file_path = format!("{}/BUILD", &path_prefix); + let rendered_alias_build_file = try!(self.render_remote_aliases(&workspace_context, &crate_contexts).map_err(|e| CargoError::from(e.to_string()))); + file_outputs.push(FileOutputs { path: alias_file_path, contents: rendered_alias_build_file }); + + let bzl_fetch_file_path = format!("{}/crates.bzl", &path_prefix); + let rendered_bzl_fetch_file = try!(self.render_bzl_fetch(&workspace_context, &crate_contexts).map_err(|e| CargoError::from(e.to_string()))); + file_outputs.push(FileOutputs { path: bzl_fetch_file_path, contents: rendered_bzl_fetch_file }); + + Ok(file_outputs) + } +} + +#[cfg(test)] +mod tests { + pub use super::*; + pub use planning::PlannedBuild; + pub use rendering::RenderDetails; + pub use rendering::FileOutputs; + pub use context::*; + pub use hamcrest::prelude::*; + pub use hamcrest::core::expect; + + fn dummy_render_details() -> RenderDetails { + RenderDetails { + path_prefix: "./some_render_prefix".to_owned(), + } + } + + fn dummy_planned_build(crate_contexts: Vec) -> PlannedBuild { + PlannedBuild { + workspace_context: WorkspaceContext { + workspace_path: "//workspace/prefix".to_owned(), + platform_triple: "irrelevant".to_owned(), + gen_workspace_prefix: "".to_owned() + }, + crate_contexts: crate_contexts, + } + } + + fn dummy_binary_crate() -> CrateContext { + CrateContext { + pkg_name: "test-binary".to_owned(), + pkg_version: "1.1.1".to_owned(), + features: vec!["feature1".to_owned(), "feature2".to_owned()].to_owned(), + path: "vendor/test-binary-1.1.1/".to_owned(), + dependencies: Vec::new(), + build_dependencies: Vec::new(), + dev_dependencies: Vec::new(), + is_root_dependency: true, + metadeps: Vec::new(), + platform_triple: "irrelevant".to_owned(), + targets: vec![ + BuildTarget { + name: "some_binary".to_owned(), + kind: "bin".to_owned(), + path: "bin/main.rs".to_owned() + } + ], + build_script_target: None, + additional_deps: Vec::new(), + additional_flags: Vec::new(), + extra_aliased_targets: Vec::new(), + } + } + + fn dummy_library_crate() -> CrateContext { + CrateContext { + pkg_name: "test-library".to_owned(), + pkg_version: "1.1.1".to_owned(), + features: vec!["feature1".to_owned(), "feature2".to_owned()].to_owned(), + path: "vendor/test-library-1.1.1/".to_owned(), + dependencies: Vec::new(), + build_dependencies: Vec::new(), + dev_dependencies: Vec::new(), + is_root_dependency: true, + metadeps: Vec::new(), + platform_triple: "irrelevant".to_owned(), + targets: vec![ + BuildTarget { + name: "some_library".to_owned(), + kind: "lib".to_owned(), + path: "path/lib.rs".to_owned() + } + ], + build_script_target: None, + additional_deps: Vec::new(), + additional_flags: Vec::new(), + extra_aliased_targets: Vec::new(), + } + } + + fn extract_contents_matching_path(file_outputs: &Vec, crate_name: &str) -> String { + let mut matching_files_contents = file_outputs + .iter() + .filter(|output| output.path.contains(crate_name)) + .map(|output| output.contents.to_owned()) + .collect::>(); + + assert_that!(matching_files_contents.len(), equal_to(1)); + matching_files_contents.pop().unwrap() + } + + fn render_crates_for_test(contexts: Vec) -> Vec { + BazelRenderer::new().render_planned_build( + &dummy_render_details(), + &dummy_planned_build(contexts)) .unwrap() + } + + #[test] + fn all_plans_contain_root_build_file() { + let file_outputs = render_crates_for_test(Vec::new()); + let file_names = file_outputs.iter().map(|output| output.path.as_ref()).collect::>(); + + assert_that!(&file_names, contains(vec!["./some_render_prefix/vendor/BUILD"]).exactly()); + } + + #[test] + fn crates_generate_build_files() { + let file_outputs = render_crates_for_test(vec![dummy_library_crate()]); + let file_names = file_outputs.iter().map(|output| output.path.as_ref()).collect::>(); + + assert_that!(&file_names, + contains(vec!["./some_render_prefix/vendor/BUILD", "./some_render_prefix/vendor/test-library-1.1.1/BUILD"]).exactly()); + } + + #[test] + fn root_crates_get_build_aliases() { + let file_outputs = render_crates_for_test(vec![dummy_library_crate()]); + let root_build_contents = extract_contents_matching_path(&file_outputs, "vendor/BUILD"); + + expect(root_build_contents.contains("alias"), + format!("expected root build contents to contain an alias \ + for test-library crate, but it just contained [{}]", root_build_contents)).unwrap(); + } + + #[test] + fn non_root_crates_dont_get_build_aliases() { + let mut non_root_crate = dummy_library_crate(); + non_root_crate.is_root_dependency = false; + + let file_outputs = render_crates_for_test(vec![non_root_crate]); + let root_build_contents = extract_contents_matching_path(&file_outputs, "vendor/BUILD"); + + expect(!root_build_contents.contains("alias"), + format!("expected root build contents not to contain an alias \ + for test-library crate, but it just contained [{}]", root_build_contents)).unwrap(); + } + + #[test] + fn binaries_get_rust_binary_rules() { + let file_outputs = render_crates_for_test(vec![dummy_binary_crate()]); + let crate_build_contents = extract_contents_matching_path(&file_outputs, "vendor/test-binary-1.1.1/BUILD"); + + expect(crate_build_contents.contains("rust_binary("), + format!("expected crate build contents to contain rust_binary, \ + but it just contained [{}]", crate_build_contents)).unwrap(); + } + + #[test] + fn libraries_get_rust_library_rules() { + let file_outputs = render_crates_for_test(vec![dummy_library_crate()]); + let crate_build_contents = extract_contents_matching_path(&file_outputs, "vendor/test-library-1.1.1/BUILD"); + + expect(crate_build_contents.contains("rust_library("), + format!("expected crate build contents to contain rust_library, \ + but it just contained [{}]", crate_build_contents)).unwrap(); + } +} diff --git a/src/context.rs b/src/context.rs new file mode 100644 index 000000000..4e3728ce1 --- /dev/null +++ b/src/context.rs @@ -0,0 +1,54 @@ +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize)] +pub struct BuildDependency { + pub name: String, + pub version: String, +} + +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize)] +pub struct BuildTarget { + pub name: String, + pub kind: String, + pub path: String, +} + +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize)] +pub struct Metadep { + pub name: String, + pub min_version: String, +} + +#[derive(Debug, Clone, Serialize)] +pub struct CrateContext { + pub pkg_name: String, + pub pkg_version: String, + pub features: Vec, + pub path: String, + pub dependencies: Vec, + pub build_dependencies: Vec, + pub dev_dependencies: Vec, + pub is_root_dependency: bool, + pub metadeps: Vec, + pub platform_triple: String, + pub targets: Vec, + pub build_script_target: Option, + pub additional_deps: Vec, + pub additional_flags: Vec, + pub extra_aliased_targets: Vec, + // TODO(acmcarther): Consider plugin topic +} + +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize)] +pub struct WorkspaceContext { + /** The bazel path prefix to the vendor directory */ + pub workspace_path: String, + + /** The compilation target triple */ + pub platform_triple: String, + + /** + * The generated new_http_library Bazel workspace prefix. + * + * This has no effect unless the GenMode setting is Remote. + */ + pub gen_workspace_prefix: String +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 000000000..6c5b3d1b9 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,161 @@ +#[macro_use] +extern crate serde_derive; +extern crate serde; +extern crate cargo; +extern crate rustc_serialize; +extern crate itertools; +extern crate tera; +extern crate toml; + +#[cfg(test)] +#[macro_use] +extern crate hamcrest; + +mod context; +mod planning; +mod rendering; +mod settings; +mod util; +mod bazel; + +use bazel::BazelRenderer; +use cargo::CargoError; +use cargo::CliResult; +use cargo::util::CargoResult; +use cargo::util::Config; +use planning::BuildPlanner; +use rendering::FileOutputs; +use rendering::BuildRenderer; +use rendering::RenderDetails; +use settings::RazeSettings; +use settings::GenMode; +use std::env; +use std::fs::File; +use std::path::Path; +use std::io::Read; +use std::io::Write; + +#[derive(Debug, RustcDecodable)] +struct Options { + arg_buildprefix: Option, + flag_verbose: u32, + flag_quiet: Option, + flag_host: Option, + flag_color: Option, + flag_target: Option, + flag_dryrun: Option, +} + +const USAGE: &'static str = r#" +Generate BUILD files for your pre-vendored Cargo dependencies. + +Usage: + cargo raze + +Options: + -h, --help Print this message + -v, --verbose Use verbose output + --host HOST Registry index to sync with + -q, --quiet No output printed to stdout + --color WHEN Coloring: auto, always, never + -d, --dryrun Do not emit any files +"#; + +fn main() { + let cargo_config = Config::default().unwrap(); + let args = env::args().collect::>(); + let result = cargo::call_main_without_stdin(real_main, &cargo_config, USAGE, &args, false); + + if let Err(e) = result { + cargo::exit_with_error(e, &mut *cargo_config.shell()); + } +} + +fn real_main(options: Options, cargo_config: &Config) -> CliResult { + try!(cargo_config.configure(options.flag_verbose, + options.flag_quiet, + &options.flag_color, + /* frozen = */ false, + /* locked = */ false)); + let mut settings = try!(load_settings("Cargo.toml")); + println!("Loaded override settings: {:#?}", settings); + + try!(validate_settings(&mut settings)); + + let mut planner = try!(BuildPlanner::new(settings.clone(), cargo_config)); + + if let Some(host) = options.flag_host { + try!(planner.set_registry_from_url(host)); + } + + + let planned_build = try!(planner.plan_build()); + let mut bazel_renderer = BazelRenderer::new(); + let render_details = RenderDetails { + path_prefix: "./".to_owned(), + }; + + let bazel_file_outputs = match settings.genmode { + GenMode::Vendored => try!(bazel_renderer.render_planned_build(&render_details, &planned_build)), + GenMode::Remote => try!(bazel_renderer.render_remote_planned_build(&render_details, &planned_build)), + /* exhaustive, we control the definition */ + }; + + let dry_run = options.flag_dryrun.unwrap_or(false); + for FileOutputs { path, contents } in bazel_file_outputs { + if !dry_run { + try!(write_to_file_loudly(&path, &contents)); + } else { + println!("{}:\n{}", path, contents); + } + } + + Ok(()) +} + +/** Verifies that the provided settings make sense. */ +fn validate_settings(settings: &mut RazeSettings) -> CargoResult<()> { + if !settings.workspace_path.starts_with("//") { + return Err(CargoError::from("raze.workspace_path must start with \"//\". Paths into local repositories (such as @local//path) are currently unsupported.")) + } + + if settings.workspace_path == "//" { + return Err(CargoError::from("raze.workspace_path must not be '//' (it is currently unsupported). Its probably not what you want anyway, as this would vendor the crates directly into //vendor.")); + } + + if settings.workspace_path.ends_with("/") { + settings.workspace_path.pop(); + } + + return Ok(()) +} + +fn write_to_file_loudly(path: &str, contents: &str) -> CargoResult<()> { + try!(File::create(&path) + .and_then(|mut f| f.write_all(contents.as_bytes())) + .map_err(|_| CargoError::from(format!("failed to create {}", path)))); + println!("Generated {} successfully", path); + Ok(()) +} + + +fn load_settings>(cargo_toml_path: T) -> Result { + let path = cargo_toml_path.as_ref(); + let mut toml = try!(File::open(path) + .map_err(|e| { + println!("{:?}", e); + CargoError::from(format!("Could not load {:?}", path)) + })); + let mut toml_contents = String::new(); + try!(toml.read_to_string(&mut toml_contents) + .map_err(|e| { + println!("{:?}", e); + CargoError::from(format!("failed to read {:?}", path)) + })); + toml::from_str::(&toml_contents) + .map_err(|e| { + println!("{:?}", e); + CargoError::from(format!("failed to parse {:?}", path)) + }) + .map(|toml| toml.raze) +} diff --git a/src/planning.rs b/src/planning.rs new file mode 100644 index 000000000..171473831 --- /dev/null +++ b/src/planning.rs @@ -0,0 +1,298 @@ +use cargo::CargoError; +use cargo::core::Dependency; +use cargo::core::Package as CargoPackage; +use cargo::core::PackageId; +use cargo::core::PackageSet; +use cargo::core::Resolve; +use cargo::core::SourceId; +use cargo::core::Workspace; +use cargo::core::dependency::Kind; +use cargo::ops::Packages; +use cargo::ops; +use cargo::util::CargoResult; +use cargo::util::Cfg; +use cargo::util::Config; +use cargo::util::ToUrl; +use context::BuildDependency; +use context::BuildTarget; +use context::CrateContext; +use context::WorkspaceContext; +use settings::RazeSettings; +use settings::GenMode; +use std::collections::HashSet; +use std::env; +use std::fs; +use std::ops::Deref; +use std::path::Path; +use std::str; +use util; + +pub struct PlannedBuild { + pub workspace_context: WorkspaceContext, + pub crate_contexts: Vec, +} + +pub struct BuildPlanner<'a> { + settings: RazeSettings, + cargo_config: &'a Config, + platform_attrs: Vec, + registry: Option, +} + +impl <'a> BuildPlanner<'a> { + pub fn new(settings: RazeSettings, + cargo_config: &'a Config) -> CargoResult> { + Ok(BuildPlanner { + platform_attrs: try!(util::fetch_attrs(&settings.target)), + cargo_config: cargo_config, + registry: None, + settings: settings, + }) + } + + pub fn set_registry_from_url(&mut self, host: String) -> CargoResult<()> { + match host.to_url().map(|url| SourceId::for_registry(&url)) { + Ok(registry_id) => { + self.registry = Some(registry_id); + Ok(()) + }, + Err(value) => Err(CargoError::from(value)) + } + } + + pub fn plan_build(&self) -> CargoResult { + let ResolvedPlan {root_name, packages, resolve} = + try!(ResolvedPlan::resolve_from_files(&self.cargo_config)); + + let root_package_id = try!(resolve.iter() + .filter(|dep| dep.name() == root_name) + .next() + .ok_or(CargoError::from("root crate should be in cargo resolve"))); + let root_direct_deps = resolve.deps(&root_package_id).cloned().collect::>(); + + let mut crate_contexts = Vec::new(); + + let source_id = match self.registry.clone() { + Some(v) => v, + None => try!(SourceId::crates_io(&self.cargo_config)), + }; + + for id in try!(find_all_package_ids(source_id, &resolve)) { + let package = packages.get(&id).unwrap().clone(); + let mut features = resolve.features(&id).clone().into_iter().collect::>(); + features.sort(); + let full_name = format!("{}-{}", id.name(), id.version()); + let path = format!("./vendor/{}-{}/", id.name(), id.version()); + + // Verify that package is really vendored + if self.settings.genmode == GenMode::Vendored { + try!(fs::metadata(&path).map_err(|_| { + CargoError::from(format!("failed to find {}. Either switch to \"Remote\" genmode, or run `cargo vendor -x` first.", &path)) + })); + } + + // Identify all possible dependencies + let PlannedDeps { mut build_deps, mut dev_deps, mut normal_deps } = + PlannedDeps::find_all_deps(&id, &package, &resolve, &self.settings.target, &self.platform_attrs); + build_deps.sort(); + dev_deps.sort(); + normal_deps.sort(); + + let mut targets = try!(identify_targets(&full_name, &package)); + targets.sort(); + + let possible_crate_settings = + self.settings.crates + .get(id.name()) + .and_then(|c| c.get(&id.version().to_string())); + + let should_gen_buildrs = + possible_crate_settings.map(|s| s.gen_buildrs.clone()).unwrap_or(false); + let build_script_target = if should_gen_buildrs { + targets.iter().find(|t| t.kind.deref() == "custom-build").cloned() + } else { + None + }; + + let targets_sans_build_script = + targets.into_iter().filter(|t| t.kind.deref() != "custom-build").collect::>(); + + let additional_deps = + possible_crate_settings.map(|s| s.additional_deps.clone()).unwrap_or(Vec::new()); + + let additional_flags = + possible_crate_settings.map(|s| s.additional_flags.clone()).unwrap_or(Vec::new()); + + let extra_aliased_targets = + possible_crate_settings.map(|s| s.extra_aliased_targets.clone()).unwrap_or(Vec::new()); + + // Skip generated dependencies explicitly designated to be skipped (potentially due to + // being replaced or customized as part of additional_deps) + let non_skipped_normal_deps = if let Some(s) = possible_crate_settings { + normal_deps.into_iter() + .filter(|d| !s.skipped_deps.contains(&format!("{}-{}", d.name, d.version))) + .collect::>() + } else { + normal_deps + }; + + crate_contexts.push(CrateContext { + pkg_name: id.name().to_owned(), + pkg_version: id.version().to_string(), + features: features, + is_root_dependency: root_direct_deps.contains(&id), + metadeps: Vec::new() /* TODO(acmcarther) */, + dependencies: non_skipped_normal_deps, + build_dependencies: build_deps, + dev_dependencies: dev_deps, + path: path, + build_script_target: build_script_target, + targets: targets_sans_build_script, + platform_triple: self.settings.target.to_owned(), + additional_deps: additional_deps, + additional_flags: additional_flags, + extra_aliased_targets: extra_aliased_targets, + }) + } + + let workspace_context = WorkspaceContext { + workspace_path: self.settings.workspace_path.clone(), + platform_triple: self.settings.target.clone(), + gen_workspace_prefix: self.settings.gen_workspace_prefix.clone(), + }; + + crate_contexts.sort_by_key(|context| format!("{}-{}", context.pkg_name, context.pkg_version)); + + Ok(PlannedBuild{ + workspace_context: workspace_context, + crate_contexts: crate_contexts + }) + } +} + +/** The set of all included dependencies for Cargo's dependency categories. */ +pub struct PlannedDeps { + pub build_deps: Vec, + pub dev_deps: Vec, + pub normal_deps: Vec, +} + +impl PlannedDeps { + /** + * Identifies the full set of cargo dependencies for the provided package id using cargo's + * resolution details. + */ + pub fn find_all_deps(id: &PackageId, + package: &CargoPackage, + resolve: &Resolve, + platform_triple: &str, + platform_attrs: &Vec) -> PlannedDeps { + let platform_deps = package + .dependencies() + .iter() + .filter(|dep| { + dep.platform() + .map(|p| p.matches(&platform_triple, Some(&platform_attrs))) + .unwrap_or(true) + }) + .cloned() + .collect::>(); + let build_deps = util::take_kinded_dep_names(&platform_deps, Kind::Build); + let dev_deps = util::take_kinded_dep_names(&platform_deps, Kind::Development); + let normal_deps = util::take_kinded_dep_names(&platform_deps, Kind::Normal); + let resolved_deps = resolve.deps(&id).into_iter() + .map(|dep| BuildDependency { + name: dep.name().to_owned(), + version: dep.version().to_string(), + }) + .collect::>(); + + PlannedDeps { + normal_deps: + resolved_deps.iter().filter(|d| normal_deps.contains(&d.name)).cloned().collect(), + build_deps: + resolved_deps.iter().filter(|d| build_deps.contains(&d.name)).cloned().collect(), + dev_deps: + resolved_deps.into_iter().filter(|d| dev_deps.contains(&d.name)).collect(), + } + } +} + +/** A synthesized Cargo dependency resolution. */ +pub struct ResolvedPlan<'a> { + pub root_name: String, + pub packages: PackageSet<'a>, + pub resolve: Resolve, +} + +impl<'a> ResolvedPlan<'a> { + /** + * Performs Cargo's own build plan resolution, yielding the root crate, the set of packages, and + * the resolution graph. + */ + pub fn resolve_from_files(cargo_config: &Config) -> CargoResult { + let lockfile = Path::new("Cargo.lock"); + let manifest_path = lockfile.parent().unwrap().join("Cargo.toml"); + let manifest = env::current_dir().unwrap().join(&manifest_path); + let ws = try!(Workspace::new(&manifest, cargo_config)); + let specs = Packages::All.into_package_id_specs(&ws)?; + let root_name = specs.iter().next().unwrap().name().to_owned(); + + let (packages, resolve) = ops::resolve_ws_precisely( + &ws, + None, + &[], + false, + false, + &specs)?; + + Ok(ResolvedPlan { + root_name: root_name, + packages: packages, + resolve: resolve, + }) + } +} + +/** Enumerates the set of all possibly relevant packages for the Cargo dependencies */ +fn find_all_package_ids(registry_id: SourceId, resolve: &Resolve) -> CargoResult> { + try!(fs::metadata("Cargo.lock").map_err(|_| { + CargoError::from("failed to find Cargo.lock. Please run `cargo generate-lockfile` first.") + })); + + let mut package_ids = resolve.iter() + .filter(|id| *id.source_id() == registry_id) + .cloned() + .collect::>(); + package_ids.sort_by_key(|id| id.name().to_owned()); + Ok(package_ids) +} + + +/** Derives target objects from Cargo's target information. */ +fn identify_targets(full_name: &str, package: &CargoPackage) -> CargoResult> { + let partial_path = format!("{}/", full_name); + let partial_path_byte_length = partial_path.as_bytes().len(); + let mut targets = Vec::new(); + + for target in package.targets().iter() { + let target_path_str = try!(target.src_path().to_str() + .ok_or(CargoError::from(format!("path for {}'s target {} wasn't unicode", &full_name, target.name())))) + .to_owned(); + let crate_name_str_idx = try!(target_path_str.find(&partial_path) + .ok_or(CargoError::from(format!("path for {}'s target {} should have been in vendor directory", &full_name, target.name())))); + let local_path_bytes = target_path_str.bytes() + .skip(crate_name_str_idx + partial_path_byte_length) + .collect::>(); + let local_path_str = String::from_utf8(local_path_bytes).unwrap(); + for kind in util::kind_to_kinds(target.kind()) { + targets.push(BuildTarget { + name: target.name().to_owned(), + path: local_path_str.clone(), + kind: kind, + }); + } + } + + Ok(targets) +} diff --git a/src/rendering.rs b/src/rendering.rs new file mode 100644 index 000000000..5211542fa --- /dev/null +++ b/src/rendering.rs @@ -0,0 +1,18 @@ +use cargo::util::CargoResult; +use planning::PlannedBuild; + +#[derive(Debug, Clone)] +pub struct FileOutputs { + pub path: String, + pub contents: String +} + +#[derive(Debug, Clone)] +pub struct RenderDetails { + pub path_prefix: String +} + +pub trait BuildRenderer { + fn render_planned_build(&mut self, render_details: &RenderDetails, planned_build: &PlannedBuild) -> CargoResult>; + fn render_remote_planned_build(&mut self, render_details: &RenderDetails, planned_build: &PlannedBuild) -> CargoResult>; +} diff --git a/src/settings.rs b/src/settings.rs new file mode 100644 index 000000000..712f81ab6 --- /dev/null +++ b/src/settings.rs @@ -0,0 +1,123 @@ +use std::collections::HashMap; + +#[derive(Debug, Clone, Deserialize, PartialEq, Eq)] +pub enum GenMode { + /** Generate Vendored-style dependencies. + * + * This mode assumes that files are vendored (into vendor/), and generates BUILD files + * accordingly + */ + Vendored, + + /** + * Generate Remote-style dependencies. + * + * This mode assumes that files are not locally vendored, and generates a workspace-level + * function that can bring them in. + */ + Remote, +} + +#[derive(Debug, Clone, Deserialize)] +pub struct CargoToml { + /** The raze settings (the only part of the Cargo.toml we care about. */ + pub raze: RazeSettings, +} + +#[derive(Debug, Clone, Deserialize)] +pub struct RazeSettings { + /** The path to the Cargo.toml working directory. */ + pub workspace_path: String, + + /** The platform target to generate BUILD rules for. + * + * This comes in the form of a "triple", such as "x86_64-unknown-linux-gnu" + */ + #[serde(default = "default_target")] + pub target: String, + + /** Any crate-specific configuration. See CrateSetings for details. */ + #[serde(default)] + pub crates: HashMap>, + + /** + * Prefix for generated Bazel workspaces (from workspace_rules) + * + * This is only useful with remote genmode. It prefixes the names of the workspaces for + * dependencies (@PREFIX_crateName_crateVersion) as well as the name of the repository function + * generated in crates.bzl (PREFIX_fetch_remote_crates()). + * + * TODO(acmcarther): Does this have a non-bazel analogue? + */ + #[serde(default = "default_gen_workspace_prefix")] + pub gen_workspace_prefix: String, + + /** How to generate the dependencies. See GenMode for details. */ + #[serde(default = "default_genmode")] + pub genmode: GenMode, +} + +fn default_target() -> String { + "x86_64-unknown-linux-gnu".to_owned() +} + +fn default_gen_workspace_prefix() -> String { + "raze".to_owned() +} + +fn default_genmode() -> GenMode { + GenMode::Vendored +} + +#[derive(Debug, Clone, Deserialize)] +pub struct CrateSettings { + /** + * Dependencies to be added to a crate. + * + * Importantly, the format of dependency references depends on the genmode. + * Remote: @{gen_workspace_prefix}__{dep_name}__{dep_version_sanitized}/:{dep_name} + * Vendored: //{workspace_path}/vendor/{dep_name}-{dep_version}:{dep_name} + * + * In addition, the added deps must be accessible from a remote workspace under Remote GenMode. + * Usually, this means they _also_ need to be remote, but a "local" build path prefixed with + * "@", in the form "@//something_local" may work. + */ + #[serde(default)] + pub additional_deps: Vec, + + /** + * Dependencies to be removed from a crate, in the form "//etc". + * + * Importantly, the format of dependency references depends on the gen mode. + * Remote: @{gen_workspace_prefix}__{dep_name}__{dep_version_sanitized}/:{dep_name} + * Vendored: //{workspace_path}/vendor/{dep_name}-{dep_version}:{dep_name} + */ + #[serde(default)] + pub skipped_deps: Vec, + + /** + * Library targets that should be aliased in the root BUILD file. + * + * This is useful to facilitate using binary utility crates, such as bindgen, as part of genrules. + */ + #[serde(default)] + pub extra_aliased_targets: Vec, + + /** Flags to be added to the crate compilation process, in the form "--flag". */ + #[serde(default)] + pub additional_flags: Vec, + + /** + * Whether or not to generate the build script that goes with this crate. + * + * Many build scripts will not function, as they will still be built hermetically. However, build + * scripts that merely generate files into OUT_DIR may be fully functional. + */ + #[serde(default = "default_gen_buildrs")] + pub gen_buildrs: bool, + +} + +fn default_gen_buildrs() -> bool { + false +} diff --git a/src/templates/crate.BUILD.template b/src/templates/crate.BUILD.template new file mode 100644 index 000000000..c5670e84e --- /dev/null +++ b/src/templates/crate.BUILD.template @@ -0,0 +1,34 @@ +""" +cargo-raze crate build file. + +DO NOT EDIT! Replaced on runs of cargo-raze +""" +package(default_visibility = ["{{workspace.workspace_path}}:__subpackages__"]) + +load( + "@io_bazel_rules_rust//rust:rust.bzl", + "rust_library", + "rust_binary", + "rust_test", + "rust_bench_test", +) + +{%- set crate_name_sanitized = crate.pkg_name | replace(from="-", to="_") %} +{%- if crate.build_script_target %} +{%- include "templates/partials/build_script.template" %} +{%- endif %} +{%- for target in crate.targets %} +{%- if target.kind == "lib" %} +{%- include "templates/partials/rust_library.template" %} +{%- elif target.kind == "bin" %} +{%- include "templates/partials/rust_binary.template" %} +{%- elif target.kind == "proc-macro" %} +{%- include "templates/partials/rust_library.template" %} +{%- elif target.kind == "dylib" %} +{%- include "templates/partials/rust_library.template" %} +{%- elif target.kind == "rlib" %} +{%- include "templates/partials/rust_library.template" %} +{%- else %} +# Unsupported target "{{ target.name }}" with type "{{ target.kind }}" omitted +{%- endif %} +{%- endfor %} diff --git a/src/templates/partials/build_script.template b/src/templates/partials/build_script.template new file mode 100644 index 000000000..34950fd47 --- /dev/null +++ b/src/templates/partials/build_script.template @@ -0,0 +1,46 @@ +rust_binary( + name = "{{ crate_name_sanitized }}_build_script", + srcs = glob(["**/*.rs"]), + {%- if crate.build_script_target.path %} + crate_root = "{{ crate.build_script_target.path }}", + {%- else %} + crate_root = "build.rs", + {%- endif %} + data = glob([ + "*" + ]), + deps = [ + {%- for dependency in crate.build_dependencies %} + "{{workspace.workspace_path}}/vendor/{{dependency.name}}-{{dependency.version}}:{{dependency.name | replace(from="-", to="_") }}", + {%- endfor %} + ], + rustc_flags = [ + "--cap-lints allow", + "--target={{crate.platform_triple}}", + ], + crate_features = [ + {%- for feature in crate.features %} + "{{feature}}", + {%- endfor %} + ], + visibility = ["//visibility:private"], +) + +genrule( + name = "{{ crate_name_sanitized }}_build_script_executor", + srcs = glob(["*", "**/*.rs"]), + outs = ["{{ crate_name_sanitized }}_out_dir_outputs.tar.gz"], + tools = [":{{ crate_name_sanitized }}_build_script"], + local = 1, + cmd = "mkdir {{ crate_name_sanitized}}_out_dir_outputs/;" + + " (export CARGO_MANIFEST_DIR=\"$$PWD/{{ workspace.workspace_path | replace(from="//", to="") }}/vendor/{{ crate.pkg_name }}-{{ crate.pkg_version }}\";" + + " export TARGET='{{ crate.platform_triple }}';" + + " export RUST_BACKTRACE=1;" + {%- for feature in crate.features %} + + " export CARGO_FEATURE_{{ feature | upper | replace(from="-", to="_") }}=1;" + {%- endfor %} + + " export OUT_DIR=$$PWD/{{ crate_name_sanitized }}_out_dir_outputs;" + + " export BINARY_PATH=\"$$PWD/$(location :{{ crate_name_sanitized }}_build_script)\";" + + " export OUT_TAR=$$PWD/$@;" + + " cd $$(dirname $(location :Cargo.toml)) && $$BINARY_PATH && tar -czf $$OUT_TAR -C $$OUT_DIR .)" +) diff --git a/src/templates/partials/remote_build_script.template b/src/templates/partials/remote_build_script.template new file mode 100644 index 000000000..a38fa9d98 --- /dev/null +++ b/src/templates/partials/remote_build_script.template @@ -0,0 +1,46 @@ +rust_binary( + name = "{{ crate_name_sanitized }}_build_script", + srcs = glob(["**/*.rs"]), + {%- if crate.build_script_target.path %} + crate_root = "{{ crate.build_script_target.path }}", + {%- else %} + crate_root = "build.rs", + {%- endif %} + data = glob([ + "*" + ]), + deps = [ + {%- for dependency in crate.build_dependencies %} + "@{{workspace.gen_workspace_prefix}}__{{dependency.name | slugify | replace(from="-", to="_")}}__{{dependency.version | slugify | replace(from="-", to="_")}}//:{{dependency.name | replace(from="-", to="_") }}", + {%- endfor %} + ], + rustc_flags = [ + "--cap-lints allow", + "--target={{crate.platform_triple}}", + ], + crate_features = [ + {%- for feature in crate.features %} + "{{feature}}", + {%- endfor %} + ], + visibility = ["//visibility:private"], +) + +genrule( + name = "{{ crate_name_sanitized }}_build_script_executor", + srcs = glob(["*", "**/*.rs"]), + outs = ["{{ crate_name_sanitized }}_out_dir_outputs.tar.gz"], + tools = [":{{ crate_name_sanitized }}_build_script"], + local = 1, + cmd = "mkdir {{ crate_name_sanitized}}_out_dir_outputs/;" + + " (export CARGO_MANIFEST_DIR=\"$$PWD/$$(dirname $(location :Cargo.toml))\";" + + " export TARGET='{{ crate.platform_triple }}';" + + " export RUST_BACKTRACE=1;" + {%- for feature in crate.features %} + + " export CARGO_FEATURE_{{ feature | upper | replace(from="-", to="_") }}=1;" + {%- endfor %} + + " export OUT_DIR=$$PWD/{{ crate_name_sanitized }}_out_dir_outputs;" + + " export BINARY_PATH=\"$$PWD/$(location :{{ crate_name_sanitized }}_build_script)\";" + + " export OUT_TAR=$$PWD/$@;" + + " cd $$(dirname $(location :Cargo.toml)) && $$BINARY_PATH && tar -czf $$OUT_TAR -C $$OUT_DIR .)" +) diff --git a/src/templates/partials/remote_rust_binary.template b/src/templates/partials/remote_rust_binary.template new file mode 100644 index 000000000..b0b744789 --- /dev/null +++ b/src/templates/partials/remote_rust_binary.template @@ -0,0 +1,33 @@ +{%- set target_name_sanitized = target.name | replace(from="-", to="_") %} +rust_binary( + # Prefix bin name to disambiguate from (probable) collision with lib name + # N.B.: The exact form of this is subject to change. + name = "cargo_bin_{{ target_name_sanitized }}", + crate_root = "{{ target.path }}", + srcs = glob(["**/*.rs"]), + deps = [ + # Binaries get an implicit dependency on their lib + ":{{crate.pkg_name | replace(from="-", to="_") }}", + {%- for dependency in crate.dependencies %} + "@{{workspace.gen_workspace_prefix}}__{{dependency.name | slugify | replace(from="-", to="_")}}__{{dependency.version | slugify | replace(from="-", to="_")}}//:{{dependency.name | replace(from="-", to="_") }}", + {%- endfor %} + {%- for dependency in crate.additional_deps %} + "{{dependency}}", + {%- endfor %} + ], + rustc_flags = [ + "--cap-lints allow", + "--target={{crate.platform_triple}}", + {%- for flag in crate.additional_flags %} + "{{flag}}", + {%- endfor %} + ], + {%- if crate.build_script_target %} + out_dir_tar = ":{{ crate.pkg_name | replace(from="-", to="_")}}_build_script_executor", + {%- endif %} + crate_features = [ + {%- for feature in crate.features %} + "{{feature}}", + {%- endfor %} + ], +) diff --git a/src/templates/partials/remote_rust_library.template b/src/templates/partials/remote_rust_library.template new file mode 100644 index 000000000..62867579b --- /dev/null +++ b/src/templates/partials/remote_rust_library.template @@ -0,0 +1,37 @@ +{%- set target_name_sanitized = target.name | replace(from="-", to="_") %} +{%- if target_name_sanitized != crate_name_sanitized %} +alias( + name = "{{ crate_name_sanitized }}", + actual = ":{{ target_name_sanitized }}", +) +{%- endif %} + +rust_library( + name = "{{ target_name_sanitized }}", + crate_root = "{{ target.path }}", + crate_type = "{{ target.kind }}", + srcs = glob(["**/*.rs"]), + deps = [ + {%- for dependency in crate.dependencies %} + "@{{workspace.gen_workspace_prefix}}__{{dependency.name | slugify | replace(from="-", to="_")}}__{{dependency.version | slugify | replace(from="-", to="_")}}//:{{dependency.name | replace(from="-", to="_") }}", + {%- endfor %} + {%- for dependency in crate.additional_deps %} + "{{dependency}}", + {%- endfor %} + ], + rustc_flags = [ + "--cap-lints allow", + "--target={{crate.platform_triple}}", + {%- for flag in crate.additional_flags %} + "{{flag}}", + {%- endfor %} + ], + {%- if crate.build_script_target %} + out_dir_tar = ":{{ crate.pkg_name | replace(from="-", to="_")}}_build_script_executor", + {%- endif %} + crate_features = [ + {%- for feature in crate.features %} + "{{feature}}", + {%- endfor %} + ], +) diff --git a/src/templates/partials/rust_binary.template b/src/templates/partials/rust_binary.template new file mode 100644 index 000000000..e5d153c42 --- /dev/null +++ b/src/templates/partials/rust_binary.template @@ -0,0 +1,33 @@ +{%- set target_name_sanitized = target.name | replace(from="-", to="_") %} +rust_binary( + # Prefix bin name to disambiguate from (probable) collision with lib name + # N.B.: The exact form of this is subject to change. + name = "cargo_bin_{{ target_name_sanitized }}", + crate_root = "{{ target.path }}", + srcs = glob(["**/*.rs"]), + deps = [ + # Binaries get an implicit dependency on their lib + ":{{crate.pkg_name | replace(from="-", to="_") }}", + {%- for dependency in crate.dependencies %} + "{{workspace.workspace_path}}/vendor/{{dependency.name}}-{{dependency.version}}:{{dependency.name | replace(from="-", to="_") }}", + {%- endfor %} + {%- for dependency in crate.additional_deps %} + "{{dependency}}", + {%- endfor %} + ], + rustc_flags = [ + "--cap-lints allow", + "--target={{crate.platform_triple}}", + {%- for flag in crate.additional_flags %} + "{{flag}}", + {%- endfor %} + ], + {%- if crate.build_script_target %} + out_dir_tar = ":{{ crate.pkg_name | replace(from="-", to="_")}}_build_script_executor", + {%- endif %} + crate_features = [ + {%- for feature in crate.features %} + "{{feature}}", + {%- endfor %} + ], +) diff --git a/src/templates/partials/rust_library.template b/src/templates/partials/rust_library.template new file mode 100644 index 000000000..5898267f7 --- /dev/null +++ b/src/templates/partials/rust_library.template @@ -0,0 +1,37 @@ +{%- set target_name_sanitized = target.name | replace(from="-", to="_") %} +{%- if target_name_sanitized != crate_name_sanitized %} +alias( + name = "{{ crate_name_sanitized }}", + actual = ":{{ target_name_sanitized }}", +) +{%- endif %} + +rust_library( + name = "{{ target_name_sanitized }}", + crate_root = "{{ target.path }}", + crate_type = "{{ target.kind }}", + srcs = glob(["**/*.rs"]), + deps = [ + {%- for dependency in crate.dependencies %} + "{{workspace.workspace_path}}/vendor/{{dependency.name}}-{{dependency.version}}:{{dependency.name | replace(from="-", to="_") }}", + {%- endfor %} + {%- for dependency in crate.additional_deps %} + "{{dependency}}", + {%- endfor %} + ], + rustc_flags = [ + "--cap-lints allow", + "--target={{crate.platform_triple}}", + {%- for flag in crate.additional_flags %} + "{{flag}}", + {%- endfor %} + ], + {%- if crate.build_script_target %} + out_dir_tar = ":{{ crate.pkg_name | replace(from="-", to="_")}}_build_script_executor", + {%- endif %} + crate_features = [ + {%- for feature in crate.features %} + "{{feature}}", + {%- endfor %} + ], +) diff --git a/src/templates/remote_crate.BUILD.template b/src/templates/remote_crate.BUILD.template new file mode 100644 index 000000000..fe54cd177 --- /dev/null +++ b/src/templates/remote_crate.BUILD.template @@ -0,0 +1,33 @@ +""" +cargo-raze crate build file. + +DO NOT EDIT! Replaced on runs of cargo-raze +""" +package(default_visibility = ["//visibility:public"]) + +load( + "@io_bazel_rules_rust//rust:rust.bzl", + "rust_library", + "rust_binary", + "rust_test", + "rust_bench_test", +) +{% set crate_name_sanitized = crate.pkg_name | replace(from="-", to="_") %} +{%- if crate.build_script_target %} +{%- include "templates/partials/remote_build_script.template" %} +{%- endif %} +{%- for target in crate.targets %} +{%- if target.kind == "lib" %} +{%- include "templates/partials/remote_rust_library.template" %} +{%- elif target.kind == "bin" %} +{%- include "templates/partials/remote_rust_binary.template" %} +{%- elif target.kind == "proc-macro" %} +{%- include "templates/partials/remote_rust_library.template" %} +{%- elif target.kind == "dylib" %} +{%- include "templates/partials/remote_rust_library.template" %} +{%- elif target.kind == "rlib" %} +{%- include "templates/partials/remote_rust_library.template" %} +{%- else %} +# Unsupported target "{{ target.name }}" with type "{{ target.kind }}" omitted +{%- endif %} +{%- endfor %} diff --git a/src/templates/remote_crates.bzl.template b/src/templates/remote_crates.bzl.template new file mode 100644 index 000000000..96b6e0dbb --- /dev/null +++ b/src/templates/remote_crates.bzl.template @@ -0,0 +1,16 @@ +""" +cargo-raze crate workspace functions + +DO NOT EDIT! Replaced on runs of cargo-raze +""" + +def {{workspace.gen_workspace_prefix}}_fetch_remote_crates(): +{% for crate in crates %} + native.new_http_archive( + name = "{{workspace.gen_workspace_prefix}}__{{crate.pkg_name | slugify | replace(from="-", to="_")}}__{{crate.pkg_version | slugify | replace(from="-", to="_")}}", + url = "https://crates-io.s3-us-west-1.amazonaws.com/crates/{{crate.pkg_name}}/{{crate.pkg_name}}-{{crate.pkg_version}}.crate", + type = "tar.gz", + strip_prefix = "{{crate.pkg_name}}-{{crate.pkg_version}}", + build_file = "{{workspace.workspace_path}}:{{crate.pkg_name}}-{{crate.pkg_version}}.BUILD" + ) +{% endfor %} diff --git a/src/templates/remote_workspace.BUILD.template b/src/templates/remote_workspace.BUILD.template new file mode 100644 index 000000000..144fa9a7a --- /dev/null +++ b/src/templates/remote_workspace.BUILD.template @@ -0,0 +1,23 @@ +""" +cargo-raze workspace build file. + +DO NOT EDIT! Replaced on runs of cargo-raze +""" +package(default_visibility = ["//visibility:public"]) +{% for crate in crates %} +{%- if crate.is_root_dependency %} +{%- set crate_name_sanitized = crate.pkg_name | replace(from="-", to="_") %} +alias( + name = "{{crate_name_sanitized}}", + actual = "@{{workspace.gen_workspace_prefix}}__{{crate.pkg_name | slugify | replace(from="-", to="_")}}__{{crate.pkg_version | slugify | replace(from="-", to="_")}}//:{{crate_name_sanitized}}", +) +{%- endif %} +{%- for aliased_target in crate.extra_aliased_targets %} +alias( + # Extra aliased target, from raze configuration + # N.B.: The exact form of this is subject to change. + name = "{{aliased_target}}", + actual = "@{{workspace.gen_workspace_prefix}}__{{crate.pkg_name | slugify | replace(from="-", to="_")}}__{{crate.pkg_version | slugify | replace(from="-", to="_")}}//:{{aliased_target}}", +) +{%- endfor %} +{%- endfor %} diff --git a/src/templates/workspace.BUILD.template b/src/templates/workspace.BUILD.template new file mode 100644 index 000000000..1b5229e75 --- /dev/null +++ b/src/templates/workspace.BUILD.template @@ -0,0 +1,24 @@ +""" +cargo-raze workspace build file. + +DO NOT EDIT! Replaced on runs of cargo-raze +""" +package(default_visibility = ["//visibility:public"]) + +{%- for crate in crates %} +{%- if crate.is_root_dependency %} +{%- set crate_name_sanitized = crate.pkg_name | replace(from="-", to="_") %} +alias( + name = "{{crate_name_sanitized}}", + actual = "{{workspace.workspace_path}}/vendor/{{crate.pkg_name}}-{{crate.pkg_version}}:{{crate_name_sanitized}}", +) +{%- endif %} +{%- for aliased_target in crate.extra_aliased_targets %} +alias( + # Extra aliased target, from raze configuration + # N.B.: The exact form of this is subject to change. + name = "{{aliased_target}}", + actual = "{{workspace.workspace_path}}/vendor/{{crate.pkg_name}}-{{crate.pkg_version}}:{{aliased_target}}", +) +{%- endfor %} +{%- endfor %} diff --git a/src/util.rs b/src/util.rs new file mode 100644 index 000000000..9884f637c --- /dev/null +++ b/src/util.rs @@ -0,0 +1,70 @@ +use cargo::CargoError; +use cargo::core::Dependency; +use cargo::core::TargetKind; +use cargo::core::dependency::Kind; +use cargo::util::CargoResult; +use cargo::util::Cfg; +use std::collections::HashSet; +use std::process::Command; +use std::str::FromStr; +use std::str; + +/** Extracts the dependencies that are of the provided kind. */ +pub fn take_kinded_dep_names(platform_deps: &Vec, kind: Kind) -> HashSet { + platform_deps + .iter() + .filter(|d| d.kind() == kind) + .map(|dep| dep.name().to_owned()) + .collect() +} + +/** + * Extracts consistently named Strings for the provided TargetKind. + * + * TODO(acmcarther): Remove this shim borrowed from Cargo when Cargo is upgraded + */ +pub fn kind_to_kinds(kind: &TargetKind) -> Vec { + match kind { + &TargetKind::Lib(ref kinds) => kinds.iter().map(|k| k.crate_type().to_owned()).collect(), + &TargetKind::Bin => vec!["bin".to_owned()], + &TargetKind::ExampleBin | &TargetKind::ExampleLib(_) => vec!["example".to_owned()], + &TargetKind::Test => vec!["test".to_owned()], + &TargetKind::CustomBuild => vec!["custom-build".to_owned()], + &TargetKind::Bench => vec!["bench".to_owned()], + } +} + +/** + * Gets the proper system attributes for the provided platform triple using rustc. + */ +pub fn fetch_attrs(target: &str) -> CargoResult> { + let args = vec![ + format!("--target={}", target), + "--print=cfg".to_owned(), + ]; + + + let output = try!(Command::new("rustc") + .args(&args) + .output() + .map_err(|_| CargoError::from(format!("could not run rustc to fetch attrs for target {}", target)))); + + if !output.status.success() { + panic!(format!("getting target attrs for {} failed with status: '{}' \n\ + stdout: {}\n\ + stderr: {}", + target, + output.status, + String::from_utf8(output.stdout).unwrap_or("[unparseable bytes]".to_owned()), + String::from_utf8(output.stderr).unwrap_or("[unparseable bytes]".to_owned()))) + } + + let attr_str = String::from_utf8(output.stdout) + .expect("successful run of rustc's output to be utf8"); + + Ok(attr_str.lines() + .map(Cfg::from_str) + .map(|cfg| cfg.expect("attrs from rustc should be parsable into Cargo Cfg")) + .collect()) +} +