Merged in code-reorg (pull request #38)

Code re-organization
This commit is contained in:
Dorian 2020-02-07 04:18:49 +00:00
commit 9df505ab9a
24 changed files with 1182 additions and 876 deletions

View File

@ -1,75 +1,100 @@
version: 2.1 version: 2.1
orbs:
docker: circleci/docker@0.5.20
jobs: jobs:
setup-build-env: build-rookeries:
working_directory: ~/rookeries_ci
docker: docker:
- image: dorianpula/circleci-test:2.0.0 - image: dorianpula/rookeries-build:latest
steps: steps:
- checkout - checkout
- setup_remote_docker
- run: - run:
name: Create build image name: Build Rookeries
command: | command: cargo make build-all
docker pull dorianpula/rookeries-build:latest || true
docker build . --tag dorianpula/rookeries-build:latest
- deploy:
name: Upload Build Images to Docker Hub
command: |
docker login -u ${DOCKER_USER} -p ${DOCKER_PASS}
docker push dorianpula/rookeries-build:latest
test-site-generator: test-site-generator:
working_directory: ~/rookeries_ci
docker: docker:
- image: dorianpula/circleci-test:2.0.0 - image: dorianpula/rookeries-build:latest
steps: steps:
- checkout - checkout
- setup_remote_docker - run:
name: Audit dependencies.
command: cargo audit
- run:
name: Build Rookeries
command: |
cargo make build-all
# Initial run to resolve test issue.
INITIAL_RUN=$(mktemp -d)
cargo run -- init ${INITIAL_RUN}
- run: - run:
name: Test static site generator name: Test static site generator
command: | command: cargo make test
docker pull dorianpula/rookeries-build:latest - run:
docker run dorianpula/rookeries-build:latest cargo audit name: Check code with clippy
docker run dorianpula/rookeries-build:latest cargo make test command: cargo clippy
test-site-app: test-site-app:
working_directory: ~/rookeries_ci
docker: docker:
- image: dorianpula/circleci-test:2.0.0 - image: dorianpula/rookeries-build:latest
steps: steps:
- checkout - checkout
- setup_remote_docker - run:
name: Build Rookeries
command: cargo make build-all
- run: - run:
name: Test site webapp name: Test site webapp
command: | command: cargo make test-js
docker pull dorianpula/rookeries-build:latest
docker run dorianpula/rookeries-build:latest cargo make test-js
test-plugins: test-plugins:
working_directory: ~/rookeries_ci
docker: docker:
- image: dorianpula/circleci-test:2.0.0 - image: dorianpula/rookeries-build:latest
steps: steps:
- checkout - checkout
- setup_remote_docker
- run: - run:
name: Test plugins name: Test plugins
command: | command: cargo make test-plugins
docker pull dorianpula/rookeries-build:latest
docker run dorianpula/rookeries-build:latest cargo make test-plugins
workflows: workflows:
version: 2 version: 2
build-test-push: # TODO: Add a workflow that will create OS X and FreeBSD versions when a tag is present. And will upload to Object Storage.
scheduled-docker-build:
jobs: jobs:
- setup-build-env - docker/publish:
image: dorianpula/rookeries-build
docker-username: DOCKER_USER
docker-password: DOCKER_PASS
tag: latest
triggers:
- schedule:
cron: "0 15 * * 6"
filters:
branches:
only:
- master
# # -- Uncomment when we need to do manual docker rebuilds. --
# manual-docker-build:
# jobs:
# - push_start:
# type: approval
# - docker/publish:
# image: dorianpula/rookeries-build
# docker-username: DOCKER_USER
# docker-password: DOCKER_PASS
# tag: latest
# requires:
# - push_start
test:
jobs:
- build-rookeries
- test-site-generator: - test-site-generator:
requires: requires:
- setup-build-env - build-rookeries
- test-site-app: - test-site-app:
requires: requires:
- setup-build-env - build-rookeries
- test-plugins: - test-plugins:
requires: requires:
- setup-build-env - build-rookeries

View File

@ -1,19 +0,0 @@
FROM rust:1.34
RUN apt-get update -qq && \
apt-get install -qq \
apt-transport-https \
ca-certificates \
curl \
gnupg2 \
software-properties-common \
python-pip \
git
# Docker and docker-compose
RUN curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add - &&\
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable" && \
apt-get -qq update && apt-get install -y docker-ce && \
pip install docker-compose
RUN cargo install cargo-make

278
Cargo.lock generated
View File

@ -7,7 +7,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -24,7 +24,7 @@ dependencies = [
"either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
"http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"trust-dns-resolver 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", "trust-dns-resolver 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -42,7 +42,7 @@ dependencies = [
"bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
"derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
"mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)",
"percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -80,11 +80,11 @@ dependencies = [
"indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
"percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
@ -104,8 +104,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
"http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)",
"string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -132,7 +132,7 @@ dependencies = [
"actix-server-config 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "actix-server-config 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"actix-service 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "actix-service 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)",
"net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -170,7 +170,7 @@ dependencies = [
"derive_more 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", "derive_more 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -186,7 +186,7 @@ dependencies = [
"bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
"either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -212,11 +212,11 @@ dependencies = [
"encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)", "encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
"hashbrown 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "hashbrown 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
"net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
@ -240,10 +240,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "aho-corasick" name = "aho-corasick"
version = "0.6.6" version = "0.7.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -289,7 +289,7 @@ dependencies = [
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "0.1.4" version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
@ -304,7 +304,7 @@ dependencies = [
"bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
"derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
"percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -395,6 +395,14 @@ dependencies = [
"libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "bstr"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "byte-tools" name = "byte-tools"
version = "0.3.1" version = "0.3.1"
@ -455,6 +463,15 @@ dependencies = [
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "chrono-tz"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
"parse-zoneinfo 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "cloudabi" name = "cloudabi"
version = "0.0.3" version = "0.0.3"
@ -490,6 +507,14 @@ dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "crossbeam-channel"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "crossbeam-utils" name = "crossbeam-utils"
version = "0.6.5" version = "0.6.5"
@ -499,6 +524,16 @@ dependencies = [
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "crossbeam-utils"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "ctor" name = "ctor"
version = "0.1.12" version = "0.1.12"
@ -527,7 +562,7 @@ dependencies = [
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -576,7 +611,7 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.72 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.72 (registry+https://github.com/rust-lang/crates.io-index)",
"strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -674,19 +709,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"termcolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "error-chain"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "failure" name = "failure"
version = "0.1.5" version = "0.1.5"
@ -806,9 +833,25 @@ dependencies = [
] ]
[[package]] [[package]]
name = "glob" name = "globset"
version = "0.2.11" version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"aho-corasick 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)",
"bstr 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "globwalk"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ignore 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "h2" name = "h2"
@ -821,7 +864,7 @@ dependencies = [
"futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
"http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
"indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
@ -879,6 +922,23 @@ dependencies = [
"unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "ignore"
version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "1.0.2" version = "1.0.2"
@ -983,7 +1043,7 @@ dependencies = [
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.4" version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1009,11 +1069,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.0.1" version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "mime" name = "mime"
@ -1072,7 +1129,7 @@ dependencies = [
"iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1085,7 +1142,7 @@ version = "2.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -1131,7 +1188,7 @@ name = "nom"
version = "4.2.3" version = "4.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -1257,11 +1314,24 @@ dependencies = [
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "parse-zoneinfo"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "percent-encoding" name = "percent-encoding"
version = "1.0.1" version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "percent-encoding"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "pest" name = "pest"
version = "2.1.1" version = "2.1.1"
@ -1431,7 +1501,7 @@ name = "rand"
version = "0.6.5" version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1461,7 +1531,7 @@ name = "rand_chacha"
version = "0.1.1" version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -1470,7 +1540,7 @@ name = "rand_chacha"
version = "0.2.0" version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -1553,7 +1623,7 @@ name = "rand_pcg"
version = "0.1.2" version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -1599,23 +1669,19 @@ dependencies = [
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.0.2" version = "1.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"aho-corasick 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "aho-corasick 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "regex-syntax" name = "regex-syntax"
version = "0.6.2" version = "0.6.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "resolv-conf" name = "resolv-conf"
@ -1644,16 +1710,16 @@ dependencies = [
"env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)",
"fake 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "fake 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"filetime 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"notify 4.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
"opener 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "opener 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.72 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.72 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
"tera 0.11.20 (registry+https://github.com/rust-lang/crates.io-index)", "tera 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"uuid 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"zip 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "zip 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1891,22 +1957,23 @@ dependencies = [
[[package]] [[package]]
name = "tera" name = "tera"
version = "0.11.20" version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "chrono-tz 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "globwalk 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"humansize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "humansize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pest 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "pest 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
"slug 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "slug 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"unic-segment 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "unic-segment 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -1929,7 +1996,7 @@ dependencies = [
[[package]] [[package]]
name = "thread_local" name = "thread_local"
version = "0.3.6" version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1988,7 +2055,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -1999,7 +2066,7 @@ dependencies = [
"crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2065,7 +2132,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2091,7 +2158,7 @@ dependencies = [
"futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
"idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"socket2 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "socket2 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2114,7 +2181,7 @@ dependencies = [
"futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
"ipconfig 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "ipconfig 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2132,53 +2199,48 @@ name = "ucd-trie"
version = "0.1.1" version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "ucd-util"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "unic-char-property" name = "unic-char-property"
version = "0.7.0" version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"unic-char-range 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "unic-char-range 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "unic-char-range" name = "unic-char-range"
version = "0.7.0" version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "unic-common" name = "unic-common"
version = "0.7.0" version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "unic-segment" name = "unic-segment"
version = "0.7.0" version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"unic-ucd-segment 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "unic-ucd-segment 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "unic-ucd-segment" name = "unic-ucd-segment"
version = "0.7.0" version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"unic-char-property 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "unic-char-property 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unic-char-range 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "unic-char-range 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unic-ucd-version 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "unic-ucd-version 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "unic-ucd-version" name = "unic-ucd-version"
version = "0.7.0" version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"unic-common 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "unic-common 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -2231,11 +2293,6 @@ dependencies = [
"percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "utf8-ranges"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "uuid" name = "uuid"
version = "0.6.5" version = "0.6.5"
@ -2401,14 +2458,14 @@ dependencies = [
"checksum actix-web 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0dc7ab62d04b9eeb0f368ad9c6ee20c2e3541fb9a25a5eb727c9118b59e8ff2" "checksum actix-web 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0dc7ab62d04b9eeb0f368ad9c6ee20c2e3541fb9a25a5eb727c9118b59e8ff2"
"checksum actix-web-codegen 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe9e3cdec1e645b675f354766e0688c5705021c85ab3cf739be1c8999b91c76" "checksum actix-web-codegen 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe9e3cdec1e645b675f354766e0688c5705021c85ab3cf739be1c8999b91c76"
"checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" "checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c"
"checksum aho-corasick 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c1c6d463cbe7ed28720b5b489e7c083eeb8f90d08be2a0d6bb9e1ffea9ce1afa" "checksum aho-corasick 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5f56c476256dc249def911d6f7580b5fc7e875895b5d7ee88f5d602208035744"
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
"checksum approx 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08abcc3b4e9339e33a3d0a5ed15d84a687350c05689d825e0f6655eef9e76a94" "checksum approx 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08abcc3b4e9339e33a3d0a5ed15d84a687350c05689d825e0f6655eef9e76a94"
"checksum arc-swap 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "bc4662175ead9cd84451d5c35070517777949a2ed84551764129cedb88384841" "checksum arc-swap 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "bc4662175ead9cd84451d5c35070517777949a2ed84551764129cedb88384841"
"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee"
"checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba" "checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba"
"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
"checksum autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0e49efa51329a5fd37e7c79db4621af617cd4e3e5bc224939808d076077077bf" "checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
"checksum awc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4c4763e6aa29a801d761dc3464f081d439ea5249ba90c3c3bdfc8dd3f739d233" "checksum awc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4c4763e6aa29a801d761dc3464f081d439ea5249ba90c3c3bdfc8dd3f739d233"
"checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a" "checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a"
"checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0" "checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0"
@ -2419,6 +2476,7 @@ dependencies = [
"checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09" "checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09"
"checksum brotli-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4445dea95f4c2b41cde57cc9fee236ae4dbae88d8fcbdb4750fc1bb5d86aaecd" "checksum brotli-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4445dea95f4c2b41cde57cc9fee236ae4dbae88d8fcbdb4750fc1bb5d86aaecd"
"checksum brotli2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0cb036c3eade309815c15ddbacec5b22c4d1f3983a774ab2eac2e3e9ea85568e" "checksum brotli2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0cb036c3eade309815c15ddbacec5b22c4d1f3983a774ab2eac2e3e9ea85568e"
"checksum bstr 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "fe8a65814ca90dfc9705af76bb6ba3c6e2534489a72270e797e603783bb4990b"
"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
"checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" "checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c"
@ -2427,12 +2485,15 @@ dependencies = [
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
"checksum cgmath 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)" = "64a4b57c8f4e3a2e9ac07e0f6abc9c24b6fc9e1b54c3478cfb598f3d0023e51c" "checksum cgmath 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)" = "64a4b57c8f4e3a2e9ac07e0f6abc9c24b6fc9e1b54c3478cfb598f3d0023e51c"
"checksum chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "77d81f58b7301084de3b958691458a53c3f7e0b1d702f77e550b6a88e3a88abe" "checksum chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "77d81f58b7301084de3b958691458a53c3f7e0b1d702f77e550b6a88e3a88abe"
"checksum chrono-tz 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e0e430fad0384e4defc3dc6b1223d1b886087a8bf9b7080e5ae027f73851ea15"
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
"checksum colored 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6cdb90b60f2927f8d76139c72dbde7e10c3a2bc47c8594c9c7a66529f2687c03" "checksum colored 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6cdb90b60f2927f8d76139c72dbde7e10c3a2bc47c8594c9c7a66529f2687c03"
"checksum constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "995a44c877f9212528ccc74b21a232f66ad69001e40ede5bcee2ac9ef2657120" "checksum constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "995a44c877f9212528ccc74b21a232f66ad69001e40ede5bcee2ac9ef2657120"
"checksum copyless 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ff9c56c9fb2a49c05ef0e431485a22400af20d33226dc0764d891d09e724127" "checksum copyless 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ff9c56c9fb2a49c05ef0e431485a22400af20d33226dc0764d891d09e724127"
"checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" "checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
"checksum crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "acec9a3b0b3559f15aee4f90746c4e5e293b701c0f7d3925d24e01645267b68c"
"checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" "checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c"
"checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4"
"checksum ctor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd8ce37ad4184ab2ce004c33bf6379185d3b1c95801cab51026bd271bf68eedc" "checksum ctor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd8ce37ad4184ab2ce004c33bf6379185d3b1c95801cab51026bd271bf68eedc"
"checksum derive_more 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6d944ac6003ed268757ef1ee686753b57efc5fcf0ebe7b64c9fc81e7e32ff839" "checksum derive_more 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6d944ac6003ed268757ef1ee686753b57efc5fcf0ebe7b64c9fc81e7e32ff839"
"checksum derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a141330240c921ec6d074a3e188a7c7ef95668bb95e7d44fa0e5778ec2a7afe" "checksum derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a141330240c921ec6d074a3e188a7c7ef95668bb95e7d44fa0e5778ec2a7afe"
@ -2454,7 +2515,6 @@ dependencies = [
"checksum encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4155785c79f2f6701f185eb2e6b4caf0555ec03477cb4c70db67b465311620ed" "checksum encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4155785c79f2f6701f185eb2e6b4caf0555ec03477cb4c70db67b465311620ed"
"checksum enum-as-inner 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3d58266c97445680766be408285e798d3401c6d4c378ec5552e78737e681e37d" "checksum enum-as-inner 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3d58266c97445680766be408285e798d3401c6d4c378ec5552e78737e681e37d"
"checksum env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)" = "f4d7e69c283751083d53d01eac767407343b8b69c4bd70058e08adc2637cb257" "checksum env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)" = "f4d7e69c283751083d53d01eac767407343b8b69c4bd70058e08adc2637cb257"
"checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02"
"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2"
"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1"
"checksum fake 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ee967b904f8a2ffc72c1cce48981f08b1e5802a8c520aa02dd9cd78b95063a3e" "checksum fake 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ee967b904f8a2ffc72c1cce48981f08b1e5802a8c520aa02dd9cd78b95063a3e"
@ -2470,7 +2530,8 @@ dependencies = [
"checksum futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "45dc39533a6cae6da2b56da48edae506bb767ec07370f86f70fc062e9d435869" "checksum futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "45dc39533a6cae6da2b56da48edae506bb767ec07370f86f70fc062e9d435869"
"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" "checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
"checksum getrandom 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e65cce4e5084b14874c4e7097f38cab54f47ee554f9194673456ea379dcc4c55" "checksum getrandom 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e65cce4e5084b14874c4e7097f38cab54f47ee554f9194673456ea379dcc4c55"
"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "925aa2cac82d8834e2b2a4415b6f6879757fb5c0928fc445ae76461a12eed8f2"
"checksum globwalk 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "53cbcf0368596897b0a3b8ff2110acf2400e80ffad4ca9238b52ff282a9b267b"
"checksum h2 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "a539b63339fbbb00e081e84b6e11bd1d9634a82d91da2984a18ac74a8823f392" "checksum h2 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "a539b63339fbbb00e081e84b6e11bd1d9634a82d91da2984a18ac74a8823f392"
"checksum hashbrown 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e1de41fb8dba9714efd92241565cdff73f78508c95697dd56787d3cba27e2353" "checksum hashbrown 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e1de41fb8dba9714efd92241565cdff73f78508c95697dd56787d3cba27e2353"
"checksum hostname 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "21ceb46a83a85e824ef93669c8b390009623863b5c195d1ba747292c0c72f94e" "checksum hostname 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "21ceb46a83a85e824ef93669c8b390009623863b5c195d1ba747292c0c72f94e"
@ -2479,6 +2540,7 @@ dependencies = [
"checksum humansize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6cab2627acfc432780848602f3f558f7e9dd427352224b0d9324025796d2a5e" "checksum humansize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6cab2627acfc432780848602f3f558f7e9dd427352224b0d9324025796d2a5e"
"checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e" "checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e"
"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e"
"checksum ignore 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "522daefc3b69036f80c7d2990b28ff9e0471c683bad05ca258e0a01dd22c5a1e"
"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" "checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d"
"checksum inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b54539f3910d6f84fbf9a643efd6e3aa6e4f001426c0329576128255994718" "checksum inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b54539f3910d6f84fbf9a643efd6e3aa6e4f001426c0329576128255994718"
"checksum inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0" "checksum inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0"
@ -2493,11 +2555,11 @@ dependencies = [
"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" "checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83"
"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c"
"checksum lock_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed946d4529956a20f2d63ebe1b69996d5a2137c91913fe3ebbeff957f5bca7ff" "checksum lock_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed946d4529956a20f2d63ebe1b69996d5a2137c91913fe3ebbeff957f5bca7ff"
"checksum log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cba860f648db8e6f269df990180c2217f333472b4a6e901e97446858487971e2" "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
"checksum lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" "checksum lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c"
"checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43" "checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43"
"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" "checksum memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3197e20c7edb283f87c071ddfc7a2cca8f8e0b888c242959846a6fce03c72223"
"checksum mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "3e27ca21f40a310bd06d9031785f4801710d566c184a6e15bad4f1d9b65f9425" "checksum mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "3e27ca21f40a310bd06d9031785f4801710d566c184a6e15bad4f1d9b65f9425"
"checksum mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30de2e4613efcba1ec63d8133f344076952090c122992a903359be5a4f99c3ed" "checksum mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30de2e4613efcba1ec63d8133f344076952090c122992a903359be5a4f99c3ed"
"checksum miniz-sys 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9e3ae51cea1576ceba0dde3d484d30e6e5b86dee0b2d412fe3a16a15c98202" "checksum miniz-sys 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9e3ae51cea1576ceba0dde3d484d30e6e5b86dee0b2d412fe3a16a15c98202"
@ -2523,7 +2585,9 @@ dependencies = [
"checksum parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa7767817701cce701d5585b9c4db3cdd02086398322c1d7e8bf5094a96a2ce7" "checksum parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa7767817701cce701d5585b9c4db3cdd02086398322c1d7e8bf5094a96a2ce7"
"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9"
"checksum parking_lot_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb88cb1cb3790baa6776844f968fea3be44956cf184fa1be5a03341f5491278c" "checksum parking_lot_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb88cb1cb3790baa6776844f968fea3be44956cf184fa1be5a03341f5491278c"
"checksum parse-zoneinfo 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "feece9d0113b400182a7d00adcff81ccf29158c49c5abd11e2eed8589bf6ff07"
"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
"checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
"checksum pest 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "933085deae3f32071f135d799d75667b63c8dc1f4537159756e3d4ceab41868c" "checksum pest 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "933085deae3f32071f135d799d75667b63c8dc1f4537159756e3d4ceab41868c"
"checksum pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" "checksum pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0"
"checksum pest_generator 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63120576c4efd69615b5537d3d052257328a4ca82876771d6944424ccfd9f646" "checksum pest_generator 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63120576c4efd69615b5537d3d052257328a4ca82876771d6944424ccfd9f646"
@ -2562,8 +2626,8 @@ dependencies = [
"checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" "checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1"
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
"checksum redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecedbca3bf205f8d8f5c2b44d83cd0690e39ee84b951ed649e9f1841132b66d" "checksum redox_users 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecedbca3bf205f8d8f5c2b44d83cd0690e39ee84b951ed649e9f1841132b66d"
"checksum regex 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5bbbea44c5490a1e84357ff28b7d518b4619a159fed5d25f6c1de2d19cc42814" "checksum regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "322cf97724bea3ee221b78fe25ac9c46114ebb51747ad5babd51a2fc6a8235a8"
"checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d" "checksum regex-syntax 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)" = "b28dfe3fe9badec5dbf0a79a9cccad2cfc2ab5484bdb3e44cbd1ae8b3ba2be06"
"checksum resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b263b4aa1b5de9ffc0054a2386f96992058bb6870aab516f8cdeb8a667d56dcb" "checksum resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b263b4aa1b5de9ffc0054a2386f96992058bb6870aab516f8cdeb8a667d56dcb"
"checksum rgb 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)" = "4f089652ca87f5a82a62935ec6172a534066c7b97be003cc8f702ee9a7a59c92" "checksum rgb 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)" = "4f089652ca87f5a82a62935ec6172a534066c7b97be003cc8f702ee9a7a59c92"
"checksum rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf" "checksum rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf"
@ -2596,10 +2660,10 @@ dependencies = [
"checksum syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d960b829a55e56db167e861ddb43602c003c7be0bee1d345021703fac2fb7c" "checksum syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d960b829a55e56db167e861ddb43602c003c7be0bee1d345021703fac2fb7c"
"checksum syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1e4ff033220a41d1a57d8125eab57bf5263783dfdcc18688b1dacc6ce9651ef8" "checksum syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1e4ff033220a41d1a57d8125eab57bf5263783dfdcc18688b1dacc6ce9651ef8"
"checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" "checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f"
"checksum tera 0.11.20 (registry+https://github.com/rust-lang/crates.io-index)" = "4b505279e19d8f7d24b1a9dc58327c9c36174b1a2c7ebdeac70792d017cb64f3" "checksum tera 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8501ae034d1c2d2e8c29f3c259d919c11489220d8ee8a268e7e1fe3eff94c86a"
"checksum termcolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "722426c4a0539da2c4ffd9b419d90ad540b4cff4a053be9069c908d4d07e2836" "checksum termcolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "722426c4a0539da2c4ffd9b419d90ad540b4cff4a053be9069c908d4d07e2836"
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
"checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865" "checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865"
"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
"checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" "checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f"
@ -2617,13 +2681,12 @@ dependencies = [
"checksum trust-dns-resolver 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6c9992e58dba365798803c0b91018ff6c8d3fc77e06977c4539af2a6bfe0a039" "checksum trust-dns-resolver 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6c9992e58dba365798803c0b91018ff6c8d3fc77e06977c4539af2a6bfe0a039"
"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
"checksum ucd-trie 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "71a9c5b1fe77426cf144cc30e49e955270f5086e31a6441dfa8b32efc09b9d77" "checksum ucd-trie 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "71a9c5b1fe77426cf144cc30e49e955270f5086e31a6441dfa8b32efc09b9d77"
"checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d" "checksum unic-char-property 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221"
"checksum unic-char-property 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce36d3f7ce754afdbccccf8ff0dd0134e50fb44aaae579f96218856e9e5dbd1e" "checksum unic-char-range 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc"
"checksum unic-char-range 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9ab85fab42ad1b26cafc03bf891f69cb4d6e15f491030e89a0122197baa8ae8" "checksum unic-common 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc"
"checksum unic-common 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff8d4a7ade929ef7d971e16ced21a8cd56a63869aa6032dfb8cb083cf7d077bf" "checksum unic-segment 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e4ed5d26be57f84f176157270c112ef57b86debac9cd21daaabbe56db0f88f23"
"checksum unic-segment 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c9ca47cbb09fb5fcd066b5867d11dc528302fa465277882797d6a836e1ee6f9e" "checksum unic-ucd-segment 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2079c122a62205b421f499da10f3ee0f7697f012f55b675e002483c73ea34700"
"checksum unic-ucd-segment 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "48f1a08ce0409a9e391b88d1930118eec48af12742fc538bcec55f775865776e" "checksum unic-ucd-version 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4"
"checksum unic-ucd-version 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1f5e6c6c53c2d0ece4a5964bc55fcff8602153063cb4fab20958ff32998ff6"
"checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33"
"checksum unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a84e5511b2a947f3ae965dcb29b13b7b1691b6e7332cf5dbc1744138d5acb7f6" "checksum unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a84e5511b2a947f3ae965dcb29b13b7b1691b6e7332cf5dbc1744138d5acb7f6"
"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
@ -2631,7 +2694,6 @@ dependencies = [
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
"checksum url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2a321979c09843d272956e73700d12c4e7d3d92b2ee112b31548aef0d4efc5a6" "checksum url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2a321979c09843d272956e73700d12c4e7d3d92b2ee112b31548aef0d4efc5a6"
"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
"checksum uuid 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e1436e58182935dcd9ce0add9ea0b558e8a87befe01c1a301e6020aeb0876363" "checksum uuid 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e1436e58182935dcd9ce0add9ea0b558e8a87befe01c1a301e6020aeb0876363"
"checksum v_escape 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8865501b78eef9193c1b45486acf18ba889e5662eba98854d6fc59d8ecf3542d" "checksum v_escape 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8865501b78eef9193c1b45486acf18ba889e5662eba98854d6fc59d8ecf3542d"
"checksum v_escape_derive 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "306896ff4b75998501263a1dc000456de442e21d68fe8c8bdf75c66a33a58e23" "checksum v_escape_derive 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "306896ff4b75998501263a1dc000456de442e21d68fe8c8bdf75c66a33a58e23"

View File

@ -31,7 +31,7 @@ regex = "1.0"
serde = "1.0" serde = "1.0"
serde_derive = "1.0" serde_derive = "1.0"
serde_json = "1.0" serde_json = "1.0"
tera = "0.11" tera = "1.0"
toml = "0.5" toml = "0.5"
uuid = { version = "0.6", features = ["serde", "v4"] } uuid = { version = "0.6", features = ["serde", "v4"] }
# Can not include the default bzip2 support due to OS X linking issues. # Can not include the default bzip2 support due to OS X linking issues.

View File

@ -2,7 +2,7 @@ FROM rust:1.39-stretch
MAINTAINER Dorian Pula <dorian.pula@amber-penguin-software.ca> MAINTAINER Dorian Pula <dorian.pula@amber-penguin-software.ca>
# Cache the Rust dependencies -> http://whitfin.io/speeding-up-rust-docker-builds/ # Cache the Rust dependencies -> http://whitfin.io/speeding-up-rust-docker-builds/
RUN rustup component add rustfmt && \ RUN rustup component add rustfmt clippy && \
cargo install cargo-make && \ cargo install cargo-make && \
cargo install cargo-audit cargo install cargo-audit

View File

@ -4,7 +4,14 @@ releases_release_uri = "https://github.com/dorianpula/rookeries/releases/%s"
releases_issue_uri = "https://bitbucket.org/dorianpula/rookeries/issues/%s" releases_issue_uri = "https://bitbucket.org/dorianpula/rookeries/issues/%s"
* :release:`0.18.0 <2019-02-??>` * :release:`0.18.0 <2019-02-??>`
* :feature:`38` Add support for TOML-based frontmatter for Markdown source files.
* :feature:`38` Use new and improved site format.
* :support:`37` General code clean-up as part of using Rust 2018. * :support:`37` General code clean-up as part of using Rust 2018.
* :support:`37` Add support for migrating old versions of Rookeries site to a newer version.
* :support:`39` Significant improvements to the CI build process.
* :support:`38` Improve code layout and updates to site format and templates.
* :support:`38` Add support for new object store for built artifacts.
* :support:`38` Add backwards compatibility with v0.17.0 sites.
* :release:`0.17.0 <2019-01-20>` * :release:`0.17.0 <2019-01-20>`
* :feature:`35` Add support for automatically rebuilding the site when using * :feature:`35` Add support for automatically rebuilding the site when using

View File

@ -14,7 +14,7 @@ case $1 in
;; ;;
esac esac
capital=$(echo "{action}" | awk '{ print toupper(substr($1, 1,1)) substr($1, 2) }') capital=$(echo "${action}" | awk '{ print toupper(substr($1, 1,1)) substr($1, 2) }')
description="${capital}ing" description="${capital}ing"
for plugin in ${PLUGINS}; for plugin in ${PLUGINS};

View File

@ -46,12 +46,12 @@ check_shasum_installed () {
} }
build_rookeries_path () { build_rookeries_path () {
echo "https://rookeries.org/${1}" echo "https://rookeries.us-east-1.linodeobjects.com/${1}"
} }
latest_stable_version () { latest_stable_version () {
local version_release_path local version_release_path
version_release_path="$(build_rookeries_path downloads/latest_stable_version)" version_release_path="$(build_rookeries_path latest_stable_version)"
local latest_stable_version local latest_stable_version
latest_stable_version="$(curl -X GET "${version_release_path}" -sSf)" latest_stable_version="$(curl -X GET "${version_release_path}" -sSf)"
@ -130,7 +130,7 @@ install () {
bin_download_path="${DOWNLOAD_PATH}/${binary_to_fetch}" bin_download_path="${DOWNLOAD_PATH}/${binary_to_fetch}"
checksum_download_path="${DOWNLOAD_PATH}/${checksum_for_binary}" checksum_download_path="${DOWNLOAD_PATH}/${checksum_for_binary}"
rookeries_fetch_path="$(build_rookeries_path downloads/${rookeries_version})" rookeries_fetch_path="$(build_rookeries_path ${rookeries_version})"
if [[ ! -f "${bin_download_path}" ]] || [[ ! -f "${checksum_download_path}" ]] if [[ ! -f "${bin_download_path}" ]] || [[ ! -f "${checksum_download_path}" ]]
then then

View File

@ -1,7 +1,9 @@
use crate::{current_version, files::get_rookeries_home_cache_dir};
use colored::Colorize; use colored::Colorize;
use env_logger::{Builder, Env, Target}; use env_logger::{Builder, Env, Target};
use log::{debug, error, info}; use log::{debug, error, info};
use serde::Deserialize; use serde::Deserialize;
use std::process::Command;
pub const USAGE: &str = " pub const USAGE: &str = "
@ -73,7 +75,6 @@ pub fn header_message(message: &str) {
pub fn success_message(message: &str) { pub fn success_message(message: &str) {
info!(" {} {}", "".green(), message); info!(" {} {}", "".green(), message);
} }
pub fn caution_message(message: &str) { pub fn caution_message(message: &str) {
info!(" {} {}", "".yellow(), message); info!(" {} {}", "".yellow(), message);
} }
@ -88,3 +89,30 @@ pub fn error_message(error: Box<dyn std::error::Error>) {
} }
info!(""); info!("");
} }
pub fn display_debug_info() {
debug!("Rookeries version: \t{}", current_version());
debug!("Git commit: \t\t{}", env!("GIT_REVISION"));
let os_info = Command::new("uname")
.args(&["-sr"])
.output()
.and_then(|output| {
if output.status.success() {
Ok(String::from_utf8_lossy(&output.stdout).to_string())
} else {
Ok(std::env::consts::OS.to_string())
}
})
.unwrap_or_else(|_| std::env::consts::OS.to_string());
debug!("Operating System: \t{}", os_info.trim());
debug!("Architecture: \t\t{}", std::env::consts::ARCH);
let cache_directory = match get_rookeries_home_cache_dir() {
Ok(path) => path.display().to_string(),
Err(err) => format!("{}", err),
};
debug!("Rookeries Home: \t{}", cache_directory);
}

314
src/commands/build.rs Normal file
View File

@ -0,0 +1,314 @@
use crate::migration::PreStable18Site;
use crate::{
cli::{caution_message, header_message, success_message},
errors::RookeriesError,
files::{build_path, copy_directory, copy_file, create_directory, FileType},
Page, PageHeader, Project, Site,
};
use colored::Colorize;
use serde_json::json;
use std::{
ffi::OsString,
fs::{read_dir, read_to_string, remove_dir_all, write},
path::Path,
};
use uuid::Uuid;
const ROOKERIES_UNKNOWN_PLACEHOLDER: &str = "???";
pub fn build_site(project: &Project, activate_dev_mode: bool) -> Result<(), RookeriesError> {
header_message("Building the site...");
// Check if project manifest is available.
if !project.site_manifest().exists() {
return Err(RookeriesError::MissingSiteToml);
}
let project_manifest_details = read_to_string(project.site_manifest()).map_err(|err| {
RookeriesError::ReadFileFailure(err, "site.toml".to_string(), FileType::SiteToml)
})?;
// TODO: Improve the migration workflow once requirements around templates is better understood.
let older_site: Option<PreStable18Site> = match toml::from_str(&project_manifest_details) {
Err(_) => None,
Ok(site) => Some(site),
};
let project_site: Site = match older_site.clone() {
None => toml::from_str(&project_manifest_details)
.map_err(RookeriesError::SiteTomlDeserializationError)?,
Some(site) => site.migrate(),
};
success_message(&format!(
"Found a project manifest for the \"{}\" site!",
&project_site.title.green(),
));
// Build a list of the pages to build out.
header_message("Searching for pages...");
let mut site_source_pages: Vec<OsString> = Vec::new();
for entry in read_dir(project.root_dir())? {
// TODO: Make the search recursive through directories.
let path = entry?.path();
if path.is_file()
&& path.extension() != None
&& path.extension().unwrap_or(&path.as_os_str()) == "md"
{
site_source_pages.push(path.into_os_string());
}
}
site_source_pages.sort();
for source in &site_source_pages {
let path = Path::new(source);
success_message(&format!("Found {}", path.display()));
}
// TODO: Add in support for figuring out the index page or allowing one to be set.
header_message("Compiling page information...");
// TODO: Add warning about a missing index page.
// TODO: Add support for aliases (e.g. such as about being an index page)
let site_source_pages: Vec<Page> = site_source_pages
.iter()
.map(|source_page| {
// TODO: Extract separate per page build.
let source_path = Path::new(source_page);
let slug = source_path
.file_stem()
.unwrap_or_else(|| source_path.as_os_str())
.to_str()
.unwrap_or(ROOKERIES_UNKNOWN_PLACEHOLDER)
.to_string();
let raw_content = read_to_string(source_path)
.map_err(|err| {
let source_page_err = source_page
.clone()
.into_string()
.unwrap_or_else(|_| ROOKERIES_UNKNOWN_PLACEHOLDER.to_string());
RookeriesError::ReadFileFailure(err, source_page_err, FileType::SourceMarkdown)
})
.unwrap_or_else(|_| ROOKERIES_UNKNOWN_PLACEHOLDER.to_string());
// Extract the page header from the content.
let parsed_content: Vec<&str> = raw_content.split("+++").collect();
let (header, content) = if parsed_content.len() > 1 {
(parsed_content[1], parsed_content[2])
} else {
("", parsed_content[parsed_content.len() - 1])
};
// TODO: Remember to check valid titles post-migration.
let header: PageHeader =
toml::from_str(&header).unwrap_or(PageHeader::new(slug.clone()));
success_message(&format!("Compiling \"{}\" page", &slug.green()));
Page {
title: header.title,
slug,
content: content.to_string(),
created_at: None,
}
})
.collect();
// Create a build directory for the resulting files.
header_message("Preparing build directory...");
let build_directory = project.build_dir();
if build_directory.exists() {
caution_message("Recreating build directory...");
remove_dir_all(&build_directory)?;
create_directory(&build_directory, FileType::BuildRoot)?;
} else {
create_directory(&build_directory, FileType::BuildRoot)?;
}
header_message("Initialize page rendering system...");
let mut render_engine = tera::Tera::default();
// TODO: Add templates programmatically.
let template_path = project.template_dir().join("base_index.html");
let another_template_path = project.template_dir().join("sample.html");
render_engine
.add_template_files(vec![
(&template_path, Some("index")),
(&another_template_path, Some("sample")),
])
.map_err(RookeriesError::TemplateSetupFailure)?;
let status = json!({
"version": env!("CARGO_PKG_VERSION").to_string(),
"app": env!("CARGO_PKG_NAME").to_string(),
"gitRevision": env!("GIT_REVISION").to_string(),
"contentBuildId": Uuid::new_v4(),
});
header_message("Creating the index page...");
let mut ctx = tera::Context::new();
// TODO: Figure out better support for Pre 0.18.0 version sites.
if older_site.is_some() {
let deprecation_message = format!(
"{} Using deprecated values: {} and {} in the templates.",
"WARNING!".yellow(),
"site.name".yellow(),
"plugins".yellow(),
);
caution_message(&deprecation_message);
let deprecation_message = format!(
"{} Update these values to: {} and {} respectively in the templates.",
"RECOMMENDATION:".yellow(),
"site.title".yellow(),
"site.plugins".yellow(),
);
caution_message(&deprecation_message);
ctx.insert("site", &older_site.unwrap());
ctx.insert("plugins", &project_site.plugins)
} else {
ctx.insert("site", &project_site);
}
// TODO: Ensure getting the right page as documented in the landingPage
ctx.insert("current_page", "index");
ctx.insert("rookeries", &status);
if activate_dev_mode {
ctx.insert("dev_mode", "active");
}
// TODO: Add index pages into the site source pages.
let render_page_str = render_engine
.render("sample", &ctx)
.map_err(|err| RookeriesError::RenderTemplateFailure(err, "index".to_string()))?;
write(build_directory.join("index.html"), render_page_str).map_err(|err| {
RookeriesError::WriteFileFailure(err, "index.html".to_string(), FileType::RenderedHtml)
})?;
success_message(&format!("Created the {} HTML page.", "index".green()));
header_message("Creating the pages...");
for page in &site_source_pages {
create_directory(&build_directory.join(&page.slug), FileType::Page)?;
ctx.insert("current_page", &page.slug);
let render_page_str = render_engine.render("index", &ctx).map_err(|err| {
RookeriesError::RenderTemplateFailure(err, format!("{}/index", &page.slug))
})?;
write(
build_directory.join(&page.slug).join("index.html"),
render_page_str,
)
.map_err(|err| {
RookeriesError::WriteFileFailure(
err,
format!("{}/index.html", &page.slug),
FileType::RenderedHtml,
)
})?;
success_message(&format!("Created the {} HTML page.", &page.slug.green()));
}
// Create the API representations.
header_message("Creating the API JSON files...");
let api_path = &build_directory.join("api");
create_directory(&api_path, FileType::APIRoot)?;
// Create a build artifact.
let status = serde_json::to_string_pretty(&status).map_err(|err| {
RookeriesError::JsonSerializationError(
err,
"_build.json".to_string(),
FileType::BuildArtifactJson,
)
})?;
write(api_path.join("_build.json"), status).map_err(|err| {
RookeriesError::WriteFileFailure(
err,
"api/_build.json".to_string(),
FileType::BuildArtifactJson,
)
})?;
success_message(&format!(
"Created the {}.",
FileType::BuildArtifactJson.to_string().green()
));
let site_json = serde_json::to_string_pretty(&project_site).map_err(|err| {
RookeriesError::JsonSerializationError(
err,
"site.json".to_string(),
FileType::RenderedSiteJson,
)
})?;
write(&api_path.join("site.json"), site_json).map_err(|err| {
RookeriesError::WriteFileFailure(
err,
"api/site.json".to_string(),
FileType::RenderedSiteJson,
)
})?;
success_message(&format!(
"Created the {}.",
FileType::RenderedSiteJson.to_string().green()
));
// Create all the page API reps.
let api_pages_path = &api_path.join("pages");
create_directory(&api_pages_path, FileType::PageAPI)?;
for page in site_source_pages {
let page_json_filename = format!("{}.json", &page.slug);
let page_json = serde_json::to_string_pretty(&page).map_err(|err| {
RookeriesError::JsonSerializationError(
err,
page_json_filename.clone(),
FileType::RenderedPageJson,
)
})?;
write(api_pages_path.join(&page_json_filename), page_json).map_err(|err| {
RookeriesError::WriteFileFailure(err, page_json_filename, FileType::RenderedPageJson)
})?;
success_message(&format!(
"Created the {} for the {} page.",
FileType::RenderedPageJson.to_string().green(),
&page.slug.green(),
));
}
// Bring in the static file directory.
// TODO: Ensure a separate copy over of JS assets from Rookeries. (from plugins and standalone compiled JS)
let assets_source_dir =
build_path(project.static_assets_dir().as_path(), FileType::StaticAsset)?;
let assets_target_dir = Path::new(&build_directory).join("static");
header_message("Copying static assets to built site...");
copy_directory(
&assets_source_dir,
&assets_target_dir,
FileType::StaticAsset,
None,
)?;
success_message(&format!(
"Copied over {} directory!",
FileType::StaticAsset.to_string().green()
));
// Copy over plugins too!
// TODO: Copy over plugins by version.
header_message("Activate plugins...");
if project_site.plugins.is_empty() {
success_message("No plugins to activate.");
} else {
let plugins_install_path = build_path(project.plugins_dir().as_path(), FileType::Plugin)?;
let static_js_path = Path::new(&assets_target_dir).join("js");
for plugin in project_site.plugins {
let plugin_file_name = format!("{}-plugin.js", plugin.name);
copy_file(
&plugins_install_path,
&static_js_path,
&plugin_file_name,
FileType::Plugin,
)?;
}
}
Ok(())
}

173
src/commands/init.rs Normal file
View File

@ -0,0 +1,173 @@
use crate::{
cli::{caution_message, header_message, success_message},
current_version,
errors::RookeriesError,
files::{copy_directory, copy_file, create_directory, get_rookeries_home_cache_dir, FileType},
template, Project, Site,
};
use chrono::prelude::*;
use colored::Colorize;
use serde_json::{json, Value};
use std::{collections::HashMap, fs::write};
/// Initializes the site.
///
/// # Arguments
///
/// * `project` - The project to base around the site.
///
pub fn initialize_site(project: Project) -> Result<(), RookeriesError> {
header_message("Initializing a new site...");
// TODO: Add support for interactive wizard to populate values.
// TODO: Add support for .gitignore + git initialization. (Maybe post initialization plugins).
let project_initial_details: Site = Default::default();
prepare_project_directory(&project)?;
// Create a site toml if one is missing.
match &project.site_manifest().exists() {
true => caution_message("Found an existing site.toml. Skipping."),
false => create_site_manifest(&project_initial_details, &project)?,
}
// Template copy over and setup
let rookeries_home_path = get_rookeries_home_cache_dir()?;
let template_path = &rookeries_home_path.join("template");
if !template_path.exists() {
template::install_templates()?;
}
header_message("Adding templates to site...");
let site_template_path = project.template_dir();
if site_template_path.exists() {
// TODO: Figure out override.
caution_message("Found existing templates. Skipping.");
} else {
copy_directory(
&template_path,
&site_template_path,
FileType::HtmlTemplate,
Some(vec!["ico", "md", "css", "js"]),
)?;
success_message(&format!(
"Copied over the {} directory!",
FileType::Template.to_string().green()
));
}
header_message("Adding template static assets to site...");
let site_static_path = project.static_assets_dir();
if site_static_path.exists() {
caution_message("Found existing static assets. Skipping.");
} else {
copy_directory(
&template_path,
&site_static_path,
FileType::StaticAsset,
Some(vec!["md", "html"]),
)?;
success_message(&format!(
"Copied over the {} directory!",
FileType::StaticAsset.to_string().green()
));
}
header_message("Adding sample markdown files to site...");
let sample_pages = sample_pages();
let mut ordered_pages: Vec<&String> = sample_pages.keys().collect();
ordered_pages.sort();
for page in ordered_pages {
let page_file_name = format!("{}.md", &page);
let sample_page_path = project.root_dir().join(&page_file_name);
match &sample_page_path.exists() {
true => {
caution_message(&format!(
"Found existing {}. Skipping.",
&page_file_name.yellow()
));
}
false => {
copy_file(
&template_path,
&project.root_dir(),
&page_file_name,
FileType::SampleMarkdown,
)?;
}
}
}
let plugins_path = &rookeries_home_path.join("plugins");
if !plugins_path.exists() {
template::install_plugins()?;
}
// Plugin copy over
// TODO: Improve plugin setup...
header_message("Adding plugins to site...");
let site_plugins_path = project.plugins_dir();
if site_plugins_path.exists() {
// TODO: Figure out override.
caution_message("Found existing plugins. Skipping.");
} else {
create_directory(&site_plugins_path, FileType::Plugin)?;
for plugin in project_initial_details.plugins {
let plugin_file_name = format!("{}-plugin.js", &plugin.name);
copy_file(
&plugins_path,
&site_plugins_path,
&plugin_file_name,
FileType::Plugin,
)?;
success_message(&format!("Copied over the {} plugin!", &plugin.name.green()));
}
}
Ok(())
}
fn prepare_project_directory(project: &Project) -> Result<(), RookeriesError> {
// Build out the project directory.
let project_directory = project.root_dir();
if !project_directory.exists() {
create_directory(&project_directory, FileType::ProjectRoot)?;
}
let project_dir = &project_directory.canonicalize()?;
let message = &format!(
"Created a new project in {}",
&project_dir.display().to_string().green()
);
Ok(success_message(message))
}
fn create_site_manifest(site: &Site, project: &Project) -> Result<(), RookeriesError> {
let site_toml_content =
toml::to_string_pretty(&site).map_err(RookeriesError::SiteTomlSerializationError)?;
// TODO: Consider a more complex template for the site.
let generation_timestamp: DateTime<Local> = Local::now();
let generation_timestamp = generation_timestamp.format("%B %e, %Y @ %R").to_string();
let site_toml_header = format!(
"# Site generated by Rookeries v{} on {}",
current_version(),
generation_timestamp
);
let site_toml = format!("{}\n\n{}", site_toml_header, site_toml_content);
write(&project.site_manifest(), site_toml).map_err(|err| {
RookeriesError::WriteFileFailure(err, "site.toml".to_string(), FileType::SiteToml)
})?;
Ok(success_message("Created a site.toml!"))
}
fn sample_pages() -> HashMap<String, Value> {
let mut sample_pages: HashMap<String, Value> = HashMap::new();
sample_pages.insert("index".to_string(), json!({"title": "Welcome"}));
sample_pages.insert("demo".to_string(), json!({"title": "Demo"}));
sample_pages.insert(
"license".to_string(),
json!({"title": "License (Apache v2.0)"}),
);
sample_pages
}

3
src/commands/mod.rs Normal file
View File

@ -0,0 +1,3 @@
pub mod build;
pub mod init;
pub mod server;

136
src/commands/server.rs Normal file
View File

@ -0,0 +1,136 @@
//! # Server
//!
//! Manages running a local development server, to allow for seeing the results of building
//! a site in real-time.
use crate::{
cli::{caution_message, details_message, error_message, header_message, success_message},
commands::build::build_site,
errors::RookeriesError,
Project,
};
use actix_web::{middleware::Logger, App, HttpServer};
use colored::Colorize;
use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher};
use std::{net::SocketAddr, sync::mpsc::channel, thread::spawn, time::Duration};
/// The default port for running a local development server.
const DEFAULT_SERVER_PORT: u16 = 8080;
pub fn serve_site(
project: Project,
server_port: u16,
open_browser: bool,
) -> Result<(), RookeriesError> {
header_message("Preparing to serve site...");
// Check if build directory is available.
let build_directory = project.build_dir();
if !build_directory.exists() || !build_directory.is_dir() {
caution_message("This project needs a build first!");
header_message("Attempting to build the site...");
build_site(&project, true)?;
}
spawn(move || watch(project.clone()));
success_message("Found a built site to serve!");
let server_addr = local_dev_server_addr(server_port);
HttpServer::new(move || {
App::new()
.service(actix_files::Files::new("/", build_directory.clone()).index_file("index.html"))
.wrap(Logger::default())
})
.bind(server_addr)
.map_err(|err| RookeriesError::ServerPortBind(err, server_addr.port()))
.and_then(|res| {
success_message(&format!(
"Serving project at local port {}",
server_addr.port().to_string().green()
));
if open_browser {
spawn(move || open_browser_tab(server_addr.port()));
}
Ok(res)
})?
.run()?;
Ok(())
}
/// Creates a socket address representation for the local development server.
fn local_dev_server_addr(port: u16) -> SocketAddr {
let port = match port {
x if x <= u16::min_value() || x >= u16::max_value() => DEFAULT_SERVER_PORT,
x => x,
};
([127, 0, 0, 1], port).into()
}
fn open_browser_tab(port: u16) {
let url_to_open = format!("http://{}/", local_dev_server_addr(port));
match opener::open(&url_to_open)
.map_err(|err| RookeriesError::OpenBrowserFailure(err, url_to_open.clone()))
{
Ok(_) => success_message(&format!(
"Opened {} in the default web browser.",
&url_to_open.green()
)),
Err(err) => error_message(err.into()),
};
}
fn watch(project: Project) -> notify::Result<()> {
let (tx, rx) = channel();
let mut watcher: RecommendedWatcher = Watcher::new(tx, Duration::from_secs(2))?;
// Add watch to all source paths.
setup_watchers(&mut watcher, &project)?;
let build_dir = project.build_dir();
loop {
match rx.recv() {
// TODO: Add more fine-grained control to avoid a full rebuild for minor changes.
Ok(event) => {
details_message(&format!("{:?}", event));
let trigger_rebuild = match event {
DebouncedEvent::Rescan => false,
DebouncedEvent::Error(_, _) => false,
DebouncedEvent::Remove(path) => !path.starts_with(&build_dir),
DebouncedEvent::Create(path) => !path.starts_with(&build_dir),
DebouncedEvent::NoticeRemove(path) => !path.starts_with(&build_dir),
DebouncedEvent::NoticeWrite(path) => !path.starts_with(&build_dir),
_ => true,
};
if trigger_rebuild {
teardown_watchers(&mut watcher, &project)?;
details_message("Rebuild triggered!");
if let Err(err) = build_site(&project, true) {
error_message(err.into());
}
setup_watchers(&mut watcher, &project)?;
}
}
Err(e) => details_message(&format!("watch error: {:?}", e)),
}
}
}
fn setup_watchers(watcher: &mut RecommendedWatcher, project: &Project) -> notify::Result<()> {
watcher.watch(project.root_dir(), RecursiveMode::NonRecursive)?;
watcher.watch(project.static_assets_dir(), RecursiveMode::Recursive)?;
watcher.watch(project.template_dir(), RecursiveMode::Recursive)?;
watcher.watch(project.plugins_dir(), RecursiveMode::NonRecursive)?;
Ok(())
}
fn teardown_watchers(watcher: &mut RecommendedWatcher, project: &Project) -> notify::Result<()> {
watcher.unwatch(project.root_dir())?;
watcher.unwatch(project.static_assets_dir())?;
watcher.unwatch(project.template_dir())?;
watcher.unwatch(project.plugins_dir())?;
Ok(())
}

View File

@ -2,6 +2,7 @@ use crate::{cli::error_message, files::FileType};
use std::{error, fmt, io}; use std::{error, fmt, io};
use colored::Colorize; use colored::Colorize;
use std::error::Error;
#[derive(Debug)] #[derive(Debug)]
pub enum RookeriesError { pub enum RookeriesError {
@ -30,7 +31,7 @@ impl fmt::Display for RookeriesError {
match *self { match *self {
RookeriesError::GeneralIO(ref err) => { RookeriesError::GeneralIO(ref err) => {
writeln!(f, "Encountered an unexpected I/O error.")?; writeln!(f, "Encountered an unexpected I/O error.")?;
write!(f, "Exact cause: {}", err) write!(f, "Cause: {}", err)
} }
RookeriesError::ServerPortBind(ref err, port) => { RookeriesError::ServerPortBind(ref err, port) => {
writeln!( writeln!(
@ -38,7 +39,7 @@ impl fmt::Display for RookeriesError {
"The server could not to bind to port \"{}\". Try using a different port.", "The server could not to bind to port \"{}\". Try using a different port.",
port.to_string().red() port.to_string().red()
)?; )?;
write!(f, "Exact cause: {}", err) write!(f, "Cause: {}", err)
} }
RookeriesError::MissingSiteToml => writeln!( RookeriesError::MissingSiteToml => writeln!(
f, f,
@ -47,15 +48,15 @@ impl fmt::Display for RookeriesError {
), ),
RookeriesError::CopyFileFailure(ref err, ref filename, ref file_type) => { RookeriesError::CopyFileFailure(ref err, ref filename, ref file_type) => {
writeln!(f, "Could not copy over {} {}.", file_type, filename.red())?; writeln!(f, "Could not copy over {} {}.", file_type, filename.red())?;
write!(f, "Exact cause: {}", err) write!(f, "Cause: {}", err)
} }
RookeriesError::WriteFileFailure(ref err, ref filename, ref file_type) => { RookeriesError::WriteFileFailure(ref err, ref filename, ref file_type) => {
writeln!(f, "Could not write {} {}.", file_type, filename.red())?; writeln!(f, "Could not write {} {}.", file_type, filename.red())?;
write!(f, "Exact cause: {}", err) write!(f, "Cause: {}", err)
} }
RookeriesError::ReadFileFailure(ref err, ref filename, ref file_type) => { RookeriesError::ReadFileFailure(ref err, ref filename, ref file_type) => {
writeln!(f, "Could not read {} {}.", file_type, filename.red())?; writeln!(f, "Could not read {} {}.", file_type, filename.red())?;
write!(f, "Exact cause: {}", err) write!(f, "Cause: {}", err)
} }
RookeriesError::CreateDirectoryFailure(ref err, ref directory_type) => { RookeriesError::CreateDirectoryFailure(ref err, ref directory_type) => {
writeln!( writeln!(
@ -63,7 +64,7 @@ impl fmt::Display for RookeriesError {
"Could not create {} directory.", "Could not create {} directory.",
directory_type.to_string().red() directory_type.to_string().red()
)?; )?;
write!(f, "Exact cause: {}", err) write!(f, "Cause: {}", err)
} }
RookeriesError::CopyDirectoryFailure( RookeriesError::CopyDirectoryFailure(
ref err, ref err,
@ -78,7 +79,7 @@ impl fmt::Display for RookeriesError {
source_directory.red(), source_directory.red(),
target_directory.red() target_directory.red()
)?; )?;
write!(f, "Exact cause: {}", err) write!(f, "Cause: {}", err)
} }
RookeriesError::CopyDirectoryFailureMissingSource( RookeriesError::CopyDirectoryFailureMissingSource(
ref source_directory, ref source_directory,
@ -94,7 +95,7 @@ impl fmt::Display for RookeriesError {
)?; )?;
write!( write!(
f, f,
"Exact cause: source directory {} is missing.", "Cause: source directory {} is missing.",
source_directory.red() source_directory.red()
) )
} }
@ -112,15 +113,16 @@ impl fmt::Display for RookeriesError {
path.red() path.red()
)?; )?;
} }
write!(f, "Exact cause: {}", err) write!(f, "Cause: {}", err)
} }
RookeriesError::TemplateSetupFailure(ref err) => { RookeriesError::TemplateSetupFailure(ref err) => {
writeln!(f, "Unable to setup site generation templates.")?; writeln!(f, "Unable to set up site generation templates.")?;
write!(f, "Exact cause: {}", err) write!(f, "Cause: {}", err)
} }
RookeriesError::RenderTemplateFailure(ref err, ref page) => { RookeriesError::RenderTemplateFailure(ref err, ref page) => {
writeln!(f, "Unable to render the {} page.", page.red())?; writeln!(f, "Unable to render the {} page.", page.red())?;
write!(f, "\tExact cause: {}", err) writeln!(f, "\tCause: {}", err)?;
write!(f, "\tSource: {}", err.source().unwrap())
} }
RookeriesError::JsonSerializationError(ref err, ref file_name, ref file_type) => { RookeriesError::JsonSerializationError(ref err, ref file_name, ref file_type) => {
writeln!( writeln!(
@ -129,15 +131,15 @@ impl fmt::Display for RookeriesError {
file_type.to_string().red(), file_type.to_string().red(),
file_name.red(), file_name.red(),
)?; )?;
write!(f, "Exact cause: {}", err) write!(f, "Cause: {}", err)
} }
RookeriesError::SiteTomlSerializationError(ref err) => { RookeriesError::SiteTomlSerializationError(ref err) => {
writeln!(f, "Could not serialize the site into TOML.")?; writeln!(f, "Could not serialize the site into TOML.")?;
write!(f, "Exact cause: {}", err) write!(f, "Cause: {}", err)
} }
RookeriesError::SiteTomlDeserializationError(ref err) => { RookeriesError::SiteTomlDeserializationError(ref err) => {
writeln!(f, "Could not deserialize the site from TOML.")?; writeln!(f, "Could not deserialize the site from TOML.")?;
write!(f, "Exact cause: {}", err) write!(f, "Cause: {}", err)
} }
RookeriesError::ExtractArchiveError(ref err, ref file_type) => { RookeriesError::ExtractArchiveError(ref err, ref file_type) => {
writeln!( writeln!(
@ -145,7 +147,7 @@ impl fmt::Display for RookeriesError {
"Unable to extract the {} installer archive.", "Unable to extract the {} installer archive.",
file_type.to_string().red() file_type.to_string().red()
)?; )?;
write!(f, "Exact cause: {}", err) write!(f, "Cause: {}", err)
} }
RookeriesError::UnableToAccessRookeriesHome => { RookeriesError::UnableToAccessRookeriesHome => {
write!(f, "Unable to access ROOKERIES_HOME.") write!(f, "Unable to access ROOKERIES_HOME.")
@ -156,7 +158,7 @@ impl fmt::Display for RookeriesError {
"Failed to open the locally served site on {} in a browser.", "Failed to open the locally served site on {} in a browser.",
desired_url.red(), desired_url.red(),
)?; )?;
write!(f, "Exact cause: {}", err) write!(f, "Cause: {}", err)
} }
} }
} }

View File

@ -1,5 +1,8 @@
use crate::cli::{caution_message, details_message}; use crate::{
use crate::{cli::success_message, errors::RookeriesError}; cli::{caution_message, details_message, success_message},
current_version,
errors::RookeriesError,
};
use colored::Colorize; use colored::Colorize;
use directories::ProjectDirs; use directories::ProjectDirs;
use std::{ use std::{
@ -25,7 +28,6 @@ pub enum FileType {
RenderedPageJson, RenderedPageJson,
BuildArtifactJson, BuildArtifactJson,
StaticAsset, StaticAsset,
// TODO: This will probably go once the ROOKERIES_HOME code is removed.
RookeriesHomeRoot, RookeriesHomeRoot,
} }
@ -201,5 +203,5 @@ pub fn build_path(built_path: &Path, file_type: FileType) -> Result<PathBuf, Roo
pub fn get_rookeries_home_cache_dir() -> Result<PathBuf, RookeriesError> { pub fn get_rookeries_home_cache_dir() -> Result<PathBuf, RookeriesError> {
let rookeries_dirs = ProjectDirs::from("org", "Amber Penguin Software", "rookeries") let rookeries_dirs = ProjectDirs::from("org", "Amber Penguin Software", "rookeries")
.ok_or_else(|| RookeriesError::UnableToAccessRookeriesHome)?; .ok_or_else(|| RookeriesError::UnableToAccessRookeriesHome)?;
Ok(rookeries_dirs.data_dir().join(env!("CARGO_PKG_VERSION"))) Ok(rookeries_dirs.data_dir().join(current_version()))
} }

View File

@ -1,21 +1,89 @@
use std::{collections::HashMap, default::Default};
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_json::Value; use std::{
default::Default,
path::{Path, PathBuf},
};
pub mod cli; pub mod cli;
pub mod commands;
pub mod errors; pub mod errors;
pub mod files; pub mod files;
pub mod migration;
pub mod template; pub mod template;
/// Defines a project and its related assets.
#[derive(Debug, Clone)]
pub struct Project {
root: String,
}
impl Project {
/// Creates a new project based on a root directory.
///
/// # Arguments
///
/// * `root` - A string slice of the relative path to the root location of the project.
///
pub fn new(root: &str) -> Project {
Project { root: root.into() }
}
/// Gets a path to the root directory of the project.
pub fn root_dir(&self) -> PathBuf {
Path::new(&self.root).to_path_buf()
}
/// Gets a path to the project's build directory. This contains the built site.
pub fn build_dir(&self) -> PathBuf {
self.root_dir().join("build")
}
/// Gets a path to the project's directory of static assets.
pub fn static_assets_dir(&self) -> PathBuf {
self.root_dir().join("static")
}
/// Gets a path to the project's directory of templates.
pub fn template_dir(&self) -> PathBuf {
self.root_dir().join("template")
}
/// Gets a path to the directory of plugins connected to the project.
pub fn plugins_dir(&self) -> PathBuf {
self.root_dir().join("plugins")
}
/// Gets a path to the site manifest (site.toml) for the project.
pub fn site_manifest(&self) -> PathBuf {
self.root_dir().join("site.toml")
}
}
/// Creates a project that uses the current working directory as the default root of the project.
impl Default for Project {
fn default() -> Project {
Project::new(".")
}
}
#[derive(Serialize, Deserialize, Clone, Debug)] #[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Page { pub struct Page {
// TODO: Make this present in the page as TOML header.
pub slug: String, pub slug: String,
pub title: String, pub title: String,
pub content: String, pub content: String,
#[serde(rename = "created", skip_deserializing)] #[serde(rename = "created", skip_deserializing)]
pub created_at: Option<DateTime<Utc>>, pub created_at: Option<DateTime<Utc>>,
// TODO: Add something like a skip option to not add a source markdown into the site.
}
#[derive(Serialize, Deserialize, Clone, Debug)]
/// Represents the optional TOML header in a Markdown page.
pub struct PageHeader {
pub title: String,
}
impl PageHeader {
pub fn new(slug: String) -> Self {
PageHeader {
title: format!("Rookeries :: {}", &slug),
}
}
} }
impl Default for Page { impl Default for Page {
@ -30,18 +98,42 @@ impl Default for Page {
} }
#[derive(Serialize, Deserialize, Clone, Debug)] #[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Site { /// Represents a plugin attached to a site.
pub struct Plugin {
pub name: String, pub name: String,
pub version: String,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
/// Represents the details of the managed site.
pub struct Site {
pub title: String,
pub index: Option<String>, pub index: Option<String>,
pub pages: Option<HashMap<String, Value>>, pub version: String,
pub plugins: Vec<Plugin>,
}
impl Site {
pub fn new(title: String, index: Option<String>, version: String) -> Self {
Site {
title: title.clone(),
index: index.clone(),
plugins: Vec::new(),
version,
}
}
} }
impl Default for Site { impl Default for Site {
fn default() -> Site { fn default() -> Site {
Site { Site::new(
name: Default::default(), "New Rookeries Site".to_string(),
index: Default::default(), Default::default(),
pages: Some(HashMap::new()), current_version(),
} )
} }
} }
pub fn current_version() -> String {
env!("CARGO_PKG_VERSION").to_string()
}

View File

@ -1,71 +1,19 @@
use actix_web::{middleware::Logger, App, HttpServer};
use chrono::prelude::*;
use colored::Colorize; use colored::Colorize;
use docopt::Docopt; use docopt::Docopt;
use log::{debug, info}; use log::info;
use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher};
use rookeries::{ use rookeries::{
cli::{ cli::{display_debug_info, header_message, initialize_logging, Args, USAGE},
caution_message, details_message, error_message, header_message, initialize_logging, commands::{build::build_site, init::initialize_site, server::serve_site},
success_message, Args, USAGE, current_version,
}, errors::exit_on_fatal_error,
errors::{exit_on_fatal_error, RookeriesError}, Project,
files::{
build_path, copy_directory, copy_file, create_directory, get_rookeries_home_cache_dir,
FileType,
},
template, Page, Site,
}; };
use serde_json::{json, Value};
use std::{
collections::HashMap,
ffi::OsString,
fs::{read_dir, read_to_string, remove_dir_all, write},
path::{Path, PathBuf},
process::Command,
sync::mpsc::channel,
thread::spawn,
time::Duration,
};
use uuid::Uuid;
const ROOKERIES_UNKNOWN_PLACEHOLDER: &str = "???"; fn get_project(args: &Args) -> Project {
match &args.arg_project {
fn get_project_directory(args: &Args) -> std::result::Result<PathBuf, RookeriesError> { None => Default::default(),
let project_directory = match &args.arg_project { Some(directory) => Project::new(directory),
None => String::from("."), }
Some(directory) => directory.clone(),
};
let project_directory = Path::new(&project_directory);
build_path(&project_directory, FileType::ProjectRoot)
}
fn display_debug_info() {
debug!("Rookeries version: \t{}", env!("CARGO_PKG_VERSION"));
debug!("Git commit: \t\t{}", env!("GIT_REVISION"));
let os_info = Command::new("uname")
.args(&["-sr"])
.output()
.and_then(|output| {
if output.status.success() {
Ok(String::from_utf8_lossy(&output.stdout).to_string())
} else {
Ok(std::env::consts::OS.to_string())
}
})
.unwrap_or_else(|_| std::env::consts::OS.to_string());
debug!("Operating System: \t{}", os_info.trim());
debug!("Architecture: \t\t{}", std::env::consts::ARCH);
let cache_directory = match get_rookeries_home_cache_dir() {
Ok(path) => path.display().to_string(),
Err(err) => format!("{}", err),
};
debug!("Rookeries Home: \t{}", cache_directory);
} }
fn main() { fn main() {
@ -82,26 +30,29 @@ fn main() {
if args.flag_version { if args.flag_version {
info!("{}", get_app_version()); info!("{}", get_app_version());
std::process::exit(0); return;
} }
if args.cmd_serve { if args.cmd_serve {
serve_site(&args).unwrap_or_else(|err| exit_on_fatal_error(err.into())); let project = get_project(&args);
serve_site(project, args.flag_port, args.flag_open)
.unwrap_or_else(|err| exit_on_fatal_error(err.into()));
} }
if args.cmd_build { if args.cmd_build {
let project_directory = get_project_directory(&args).unwrap_or_default(); let project = get_project(&args);
match build_site(project_directory, false) { match build_site(&project, false) {
Err(err) => exit_on_fatal_error(err.into()), Err(err) => exit_on_fatal_error(err.into()),
Ok(_) => header_message(&format!("Site built. Happy hacking! {}", "".green())), Ok(_) => header_message(&format!("Site built. Happy hacking! {}", "".green())),
} }
} }
if args.cmd_init { if args.cmd_init {
match initialize_site(&args) { let project = get_project(&args);
match initialize_site(project) {
Err(err) => exit_on_fatal_error(err.into()), Err(err) => exit_on_fatal_error(err.into()),
Ok(_) => header_message(&format!( Ok(_) => header_message(&format!(
"Site initialized. You can know build and serve the site. Happy hacking! {}", "Site initialized. You can now start building your new site. Happy hacking! {}",
"".green() "".green()
)), )),
} }
@ -110,580 +61,10 @@ fn main() {
info!(""); info!("");
} }
type Result = std::result::Result<(), RookeriesError>;
fn serve_site(args: &Args) -> Result {
header_message("Preparing to serve site...");
let project_directory = get_project_directory(&args)?;
// Check if build directory is available.
let build_directory = project_directory.clone().join("build");
if !build_directory.exists() || !build_directory.is_dir() {
caution_message("This project needs a build first!");
header_message("Attempting to build the site...");
build_site(project_directory.clone(), true)?;
}
let watched_folder = project_directory
.canonicalize()
.unwrap_or_default()
.to_str()
.unwrap_or_default()
.to_string();
spawn(move || watch(watched_folder));
success_message("Found a built site to serve!");
let port = match args.flag_port {
x if x <= u16::min_value() || x >= u16::max_value() => 8000,
x => x,
};
HttpServer::new(move || {
App::new()
.service(actix_files::Files::new("/", build_directory.clone()).index_file("index.html"))
.wrap(Logger::default())
})
.bind(format!("127.0.0.1:{}", port))
.map_err(|err| RookeriesError::ServerPortBind(err, port))
.and_then(|res| {
success_message(&format!(
"Serving project at local port {}",
port.to_string().green()
));
if args.flag_open {
spawn(move || open_browser_tab(port));
}
Ok(res)
})?
.run()?;
Ok(())
}
fn open_browser_tab(port: u16) {
let url_to_open = format!("http://localhost:{}/", port);
match opener::open(&url_to_open)
.map_err(|err| RookeriesError::OpenBrowserFailure(err, url_to_open.clone()))
{
Ok(_) => success_message(&format!(
"Opened {} in the default web browser.",
&url_to_open.green()
)),
Err(err) => error_message(err.into()),
};
}
fn watch(watch_path: String) -> notify::Result<()> {
let (tx, rx) = channel();
let mut watcher: RecommendedWatcher = Watcher::new(tx, Duration::from_secs(2))?;
// Add watch to all source paths.
let project_root_dir = Path::new(&watch_path);
setup_watchers(&mut watcher, project_root_dir)?;
let build_dir = project_root_dir.join("build");
loop {
match rx.recv() {
// TODO: Add more fine-grained control to avoid a full rebuild for minor changes.
Ok(event) => {
details_message(&format!("{:?}", event));
let trigger_rebuild = match event {
DebouncedEvent::Rescan => false,
DebouncedEvent::Error(_, _) => false,
DebouncedEvent::Remove(path) => !path.starts_with(&build_dir),
DebouncedEvent::Create(path) => !path.starts_with(&build_dir),
DebouncedEvent::NoticeRemove(path) => !path.starts_with(&build_dir),
DebouncedEvent::NoticeWrite(path) => !path.starts_with(&build_dir),
_ => true,
};
if trigger_rebuild {
teardown_watchers(&mut watcher, &project_root_dir)?;
details_message("Rebuild triggered!");
if let Err(err) = build_site(project_root_dir.to_path_buf(), true) {
error_message(err.into());
}
setup_watchers(&mut watcher, &project_root_dir)?;
}
}
Err(e) => details_message(&format!("watch error: {:?}", e)),
}
}
}
fn setup_watchers(watcher: &mut RecommendedWatcher, project_root_dir: &Path) -> notify::Result<()> {
watcher.watch(project_root_dir, RecursiveMode::NonRecursive)?;
let static_assets_dir = project_root_dir.join("static");
watcher.watch(static_assets_dir, RecursiveMode::Recursive)?;
let template_dir = project_root_dir.join("template");
watcher.watch(template_dir, RecursiveMode::Recursive)?;
let plugins_dir = project_root_dir.join("plugins");
watcher.watch(plugins_dir, RecursiveMode::NonRecursive)?;
Ok(())
}
fn teardown_watchers(
watcher: &mut RecommendedWatcher,
project_root_dir: &Path,
) -> notify::Result<()> {
watcher.unwatch(project_root_dir)?;
let static_assets_dir = project_root_dir.join("static");
watcher.unwatch(static_assets_dir)?;
let template_dir = project_root_dir.join("template");
watcher.unwatch(template_dir)?;
let plugins_dir = project_root_dir.join("plugins");
watcher.unwatch(plugins_dir)?;
Ok(())
}
fn build_site(project_directory: PathBuf, activate_dev_mode: bool) -> Result {
header_message("Building the site...");
// Check if project manifest is available.
let project_manifest = project_directory.clone().join("site.toml");
if !project_manifest.exists() {
return Err(RookeriesError::MissingSiteToml);
}
let project_manifest_details = read_to_string(project_manifest).map_err(|err| {
RookeriesError::ReadFileFailure(err, "site.toml".to_string(), FileType::SiteToml)
})?;
let project_site: Site = toml::from_str(&project_manifest_details)
.map_err(RookeriesError::SiteTomlDeserializationError)?;
success_message(&format!(
"Found a project manifest for the \"{}\" site!",
&project_site.name.green(),
));
// Build a list of the pages to build out.
header_message("Searching for pages...");
let mut site_source_pages: Vec<OsString> = Vec::new();
for entry in read_dir(&project_directory.as_path())? {
// TODO: Make the search recursive through directories.
let path = entry?.path();
if path.is_file()
&& path.extension() != None
&& path.extension().unwrap_or(&path.as_os_str()) == "md"
{
success_message(&format!("Found {}", path.display()));
site_source_pages.push(path.into_os_string());
}
}
// TODO: Add in support for figuring out the index page or allowing one to be set.
header_message("Compiling page information...");
let page_overrides = project_site.clone().pages.unwrap_or_default();
// TODO: Add warning about a missing index page.
// TODO: Add support for aliases (e.g. such as about being an index page)
let site_source_pages: Vec<Page> = site_source_pages
.iter()
.map(|source_page| {
// TODO: Extract separate per page build.
let source_path = Path::new(source_page);
let slug = source_path
.file_stem()
.unwrap_or_else(|| source_path.as_os_str())
.to_str()
.unwrap_or(ROOKERIES_UNKNOWN_PLACEHOLDER)
.to_string();
let content = read_to_string(source_path)
.map_err(|err| {
let source_page_err = source_page
.clone()
.into_string()
.unwrap_or_else(|_| ROOKERIES_UNKNOWN_PLACEHOLDER.to_string());
RookeriesError::ReadFileFailure(err, source_page_err, FileType::SourceMarkdown)
})
.unwrap_or_else(|_| ROOKERIES_UNKNOWN_PLACEHOLDER.to_string());
// TODO: Be able to extract the title from the header of the markdown content.
let title = match &page_overrides.get(&slug) {
Some(page_entry) => match page_entry.get("title") {
Some(title_) => {
let title_str = serde_json::to_string(title_)
.unwrap_or_else(|_| ROOKERIES_UNKNOWN_PLACEHOLDER.to_string());
title_str.replacen("\"", "", 2)
}
None => format!("Rookeries :: {}", &slug),
},
None => format!("Rookeries :: {}", &slug),
};
success_message(&format!("Compiling \"{}\" page", &slug.green()));
Page {
title,
slug,
content,
created_at: None,
}
})
.collect();
// Create a build directory for the resulting files.
header_message("Preparing build directory...");
let build_directory = project_directory.clone().join("build");
if build_directory.exists() {
caution_message("Recreating build directory...");
remove_dir_all(&build_directory)?;
create_directory(&build_directory, FileType::BuildRoot)?;
} else {
create_directory(&build_directory, FileType::BuildRoot)?;
}
header_message("Initialize page rendering system...");
let mut render_engine = tera::Tera::default();
let template_path = &project_directory.join("template/base_index.html");
let another_template_path = &project_directory.join("template/sample.html");
render_engine
.add_template_files(vec![
(&template_path, Some("index")),
(&another_template_path, Some("sample")),
])
.map_err(RookeriesError::TemplateSetupFailure)?;
let status = json!({
"version": env!("CARGO_PKG_VERSION").to_string(),
"app": env!("CARGO_PKG_NAME").to_string(),
"gitRevision": env!("GIT_REVISION").to_string(),
"contentBuildId": Uuid::new_v4(),
});
header_message("Creating the index page...");
let plugin_list = vec!["hello-world", "dark-mode-switch"];
let mut ctx = tera::Context::new();
ctx.insert("site", &project_site);
// TODO: Ensure getting the right page as documented in the landingPage
ctx.insert("current_page", "index");
ctx.insert("plugins", &plugin_list);
ctx.insert("rookeries", &status);
if activate_dev_mode {
ctx.insert("dev_mode", "active");
}
// TODO: Add index pages into the site source pages.
let render_page_str = render_engine
.render("sample", &ctx)
.map_err(|err| RookeriesError::RenderTemplateFailure(err, "index".to_string()))?;
write(build_directory.join("index.html"), render_page_str).map_err(|err| {
RookeriesError::WriteFileFailure(err, "index.html".to_string(), FileType::RenderedHtml)
})?;
success_message(&format!("Created the {} HTML page.", "index".green()));
header_message("Creating the pages...");
for page in &site_source_pages {
create_directory(&build_directory.join(&page.slug), FileType::Page)?;
ctx.insert("current_page", &page.slug);
let render_page_str = render_engine.render("index", &ctx).map_err(|err| {
RookeriesError::RenderTemplateFailure(err, format!("{}/index", &page.slug))
})?;
write(
build_directory.join(&page.slug).join("index.html"),
render_page_str,
)
.map_err(|err| {
RookeriesError::WriteFileFailure(
err,
format!("{}/index.html", &page.slug),
FileType::RenderedHtml,
)
})?;
success_message(&format!("Created the {} HTML page.", &page.slug.green()));
}
// Create the API representations.
header_message("Creating the API JSON files...");
let api_path = &build_directory.join("api");
create_directory(&api_path, FileType::APIRoot)?;
// Create a build artifact.
let status = serde_json::to_string_pretty(&status).map_err(|err| {
RookeriesError::JsonSerializationError(
err,
"_build.json".to_string(),
FileType::BuildArtifactJson,
)
})?;
write(api_path.join("_build.json"), status).map_err(|err| {
RookeriesError::WriteFileFailure(
err,
"api/_build.json".to_string(),
FileType::BuildArtifactJson,
)
})?;
success_message(&format!(
"Created the {}.",
FileType::BuildArtifactJson.to_string().green()
));
let site_json = serde_json::to_string_pretty(&project_site).map_err(|err| {
RookeriesError::JsonSerializationError(
err,
"site.json".to_string(),
FileType::RenderedSiteJson,
)
})?;
write(&api_path.join("site.json"), site_json).map_err(|err| {
RookeriesError::WriteFileFailure(
err,
"api/site.json".to_string(),
FileType::RenderedSiteJson,
)
})?;
success_message(&format!(
"Created the {}.",
FileType::RenderedSiteJson.to_string().green()
));
// Create all the page API reps.
let api_pages_path = &api_path.join("pages");
create_directory(&api_pages_path, FileType::PageAPI)?;
for page in site_source_pages {
let page_json_filename = format!("{}.json", &page.slug);
let page_json = serde_json::to_string_pretty(&page).map_err(|err| {
RookeriesError::JsonSerializationError(
err,
page_json_filename.clone(),
FileType::RenderedPageJson,
)
})?;
write(api_pages_path.join(&page_json_filename), page_json).map_err(|err| {
RookeriesError::WriteFileFailure(err, page_json_filename, FileType::RenderedPageJson)
})?;
success_message(&format!(
"Created the {} for the {} page.",
FileType::RenderedPageJson.to_string().green(),
&page.slug.green(),
));
}
// Bring in the static file directory.
// TODO: Ensure a separate copy over of JS assets from Rookeries. (from plugins and standalone compiled JS)
let assets_source_dir = build_path(
&Path::new(&project_directory).join("static"),
FileType::StaticAsset,
)?;
let assets_target_dir = Path::new(&build_directory).join("static");
header_message("Copying static assets to built site...");
copy_directory(
&assets_source_dir,
&assets_target_dir,
FileType::StaticAsset,
None,
)?;
success_message(&format!(
"Copied over {} directory!",
FileType::StaticAsset.to_string().green()
));
// Copy over plugins too!
header_message("Activate plugins...");
// TODO: Copy over only active and available markdown plugins.
let plugin_list = vec!["hello-world", "dark-mode-switch"];
let plugins_install_path = build_path(
&Path::new(&project_directory).join("plugins"),
FileType::Plugin,
)?;
let static_js_path = Path::new(&assets_target_dir).join("js");
for plugin in plugin_list {
let plugin_file_name = format!("{}-plugin.js", plugin);
copy_file(
&plugins_install_path,
&static_js_path,
&plugin_file_name,
FileType::Plugin,
)?;
}
Ok(())
}
fn initialize_site(args: &Args) -> Result {
header_message("Initializing a new site...");
// TODO: Add support for an override flag.
// Build out the project directory.
let project_directory = match &args.arg_project {
None => String::from("."),
Some(directory) => directory.clone(),
};
let project_directory = Path::new(&project_directory);
if !project_directory.exists() {
create_directory(&project_directory.to_path_buf(), FileType::ProjectRoot)?;
let project_dir = &project_directory.canonicalize()?;
success_message(&format!(
"Created a new project in {}",
&project_dir.display().to_string().green()
));
}
let project_directory = build_path(&project_directory, FileType::ProjectRoot)?;
// TODO: Make the sample pages happen.
let mut sample_pages: HashMap<String, Value> = HashMap::new();
sample_pages.insert("index".to_string(), json!({"title": "Welcome"}));
sample_pages.insert("demo".to_string(), json!({"title": "Demo"}));
sample_pages.insert(
"license".to_string(),
json!({"title": "License (Apache v2.0)"}),
);
// Create a site toml if one is missing.
let project_manifest = project_directory.join("site.toml");
match &project_manifest.exists() {
true => {
caution_message("Found existing site.toml. Skipping.");
}
false => {
// TODO: Support an interactive setup of the Rookeries site.
let mut site = Site::default();
site.name = "New Rookeries Site".to_string();
site.pages = Some(sample_pages.clone());
let site_toml_content =
toml::to_string(&site).map_err(RookeriesError::SiteTomlSerializationError)?;
// TODO: Consider a more complex template for the site.
let rookeries_version = env!("CARGO_PKG_VERSION");
let generation_timestamp: DateTime<Local> = Local::now();
let generation_timestamp = generation_timestamp.format("%B %e, %Y @ %R").to_string();
let site_toml_header = format!(
"# Site generated by Rookeries v{} on {}",
rookeries_version, generation_timestamp
);
let site_toml = format!("{}\n\n{}", site_toml_header, site_toml_content);
write(&project_manifest, site_toml).map_err(|err| {
RookeriesError::WriteFileFailure(err, "site.toml".to_string(), FileType::SiteToml)
})?;
success_message("Created a site.toml!");
}
}
// Create a Rookeries home directory if it doesn't exist.
let rookeries_home_path = get_rookeries_home_cache_dir()?;
if !rookeries_home_path.exists() {
header_message("Create local Rookeries home cache...");
create_directory(&rookeries_home_path, FileType::RookeriesHomeRoot)?;
}
// Template copy over and setup
let template_path = &rookeries_home_path.join("template");
if !template_path.exists() {
template::install_templates()?;
}
header_message("Adding templates to site...");
let site_template_path = &project_directory.join("template");
if site_template_path.exists() {
// TODO: Figure out override.
caution_message("Found existing templates. Skipping.");
} else {
copy_directory(
&template_path,
&site_template_path,
FileType::HtmlTemplate,
Some(vec!["md", "css", "js"]),
)?;
success_message(&format!(
"Copied over the {} directory!",
FileType::Template.to_string().green()
));
}
header_message("Adding template static assets to site...");
let site_static_path = &project_directory.join("static");
if site_static_path.exists() {
caution_message("Found existing static assets. Skipping.");
} else {
copy_directory(
&template_path,
&site_static_path,
FileType::StaticAsset,
Some(vec!["md", "html"]),
)?;
success_message(&format!(
"Copied over the {} directory!",
FileType::StaticAsset.to_string().green()
));
}
header_message("Adding sample markdown files to site...");
let mut ordered_pages: Vec<&String> = sample_pages.keys().collect();
ordered_pages.sort();
for page in ordered_pages {
let page_file_name = format!("{}.md", &page);
let sample_page_path = project_directory.join(&page_file_name);
match &sample_page_path.exists() {
true => {
caution_message(&format!(
"Found existing {}. Skipping.",
&page_file_name.yellow()
));
}
false => {
copy_file(
&template_path,
&project_directory,
&page_file_name,
FileType::SampleMarkdown,
)?;
}
}
}
let plugins_path = &rookeries_home_path.join("plugins");
if !plugins_path.exists() {
template::install_plugins()?;
}
// Plugin copy over
header_message("Adding plugins to site...");
let site_plugins_path = &project_directory.join("plugins");
if site_plugins_path.exists() {
// TODO: Figure out override.
caution_message("Found existing plugins. Skipping.");
} else {
create_directory(&site_plugins_path, FileType::Plugin)?;
let plugin_list = vec!["hello-world", "dark-mode-switch"];
for plugin in plugin_list {
let plugin_file_name = format!("{}-plugin.js", &plugin);
copy_file(
&plugins_path,
&site_plugins_path,
&plugin_file_name,
FileType::Plugin,
)?;
success_message(&format!("Copied over the {} plugin!", &plugin.green()));
}
}
Ok(())
}
fn get_app_version() -> String { fn get_app_version() -> String {
format!( format!(
"rookeries v{version} © 2013-2020 {authors}", "rookeries v{version} © 2013-2020 {authors}",
version = env!("CARGO_PKG_VERSION"), version = current_version(),
authors = env!("CARGO_PKG_AUTHORS"), authors = env!("CARGO_PKG_AUTHORS"),
) )
} }

96
src/migration.rs Normal file
View File

@ -0,0 +1,96 @@
//! # Migration
//!
//! Migrates older versions of Rookeries site to newer site formats.
use crate::{cli::caution_message, current_version, Plugin, Site};
use colored::Colorize;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::collections::HashMap;
#[derive(Serialize, Deserialize, Clone, Debug)]
/// The format of a site for version 0.17.0 and earlier of Rookeries.
pub struct PreStable18Site {
name: String,
index: Option<String>,
pages: Option<HashMap<String, Value>>,
}
impl PreStable18Site {
/// List of the default plugins for a pre-0.18.0 site.
fn default_plugins() -> Vec<Plugin> {
vec![
Plugin {
name: "hello-world".to_string(),
version: "0.3.0".to_string(),
},
Plugin {
name: "dark-mode-switch".to_string(),
version: "0.1.0".to_string(),
},
]
}
/// Migrates from a pre 0.18.0 version of the site to the new format.
pub fn migrate(&self) -> Site {
// TODO: See how to update the templates: template/base_index.html & template/sample.html to site.title instead of site.name.
// TODO: Also migrate {% for plugin in site.plugins %}
// <script type="application/javascript" src="/static/js/{{ plugin.name }}-plugin.js"></script>
let migration_message = format!(
"{} You are using a site using a deprecated site format and template created before {}!",
"WARNING!".yellow(),
"0.18.0".yellow(),
);
caution_message(&migration_message);
let pages_for_migration = match &self.pages {
Some(pages) => pages.clone(),
None => HashMap::new(),
};
for (page, page_details) in pages_for_migration.iter() {
match page_details.get("title") {
Some(title) => {
let formatted_title = format!("\n\n+++\ntitle = {}\n+++\n", title);
let page_message = format!(
"{} Add the following to the {} page as Markdown frontend matter. {}",
"RECOMMENDATION:".yellow(),
format!("{}.md", page).yellow(),
formatted_title.cyan(),
);
caution_message(&page_message);
}
None => continue,
}
}
let plugins = PreStable18Site::default_plugins();
let plugin_message: &str = &plugins
.iter()
.map(|plugin| format!("{}: v{}", plugin.name, plugin.version))
.collect::<Vec<String>>()
.join(", ");
let migration_message = format!(
"{} Sites created before {} use default plugins: [{}]!",
"WARNING!".yellow(),
current_version().yellow(),
plugin_message.yellow(),
);
caution_message(&migration_message);
let site = Site {
title: self.name.clone(),
index: self.index.clone(),
version: "0.17.0".to_string(),
plugins,
};
let updated_site_message = format!(
"{} Update {} to the the new format: \n\n{}\n",
"RECOMMENDATION:".yellow(),
"site.toml".yellow(),
toml::to_string_pretty(&site).unwrap_or_default().cyan(),
);
caution_message(&updated_site_message);
site
}
}

View File

@ -2,7 +2,7 @@ use crate::files::FileType;
use crate::{ use crate::{
cli::{caution_message, details_message, header_message, success_message}, cli::{caution_message, details_message, header_message, success_message},
errors::RookeriesError, errors::RookeriesError,
files::get_rookeries_home_cache_dir, files::{create_directory, get_rookeries_home_cache_dir},
}; };
use colored::Colorize; use colored::Colorize;
use std::fs; use std::fs;
@ -28,6 +28,13 @@ fn extract_and_install_archive(
file_type: FileType, file_type: FileType,
) -> Result<(), RookeriesError> { ) -> Result<(), RookeriesError> {
let rookeries_home_cache = get_rookeries_home_cache_dir()?; let rookeries_home_cache = get_rookeries_home_cache_dir()?;
// Create a Rookeries home directory if it doesn't exist.
if !rookeries_home_cache.exists() {
header_message("Create local Rookeries home cache...");
create_directory(&rookeries_home_cache, FileType::RookeriesHomeRoot)?;
}
let reader = std::io::Cursor::new(installer_archive); let reader = std::io::Cursor::new(installer_archive);
let mut zip = zip::ZipArchive::new(reader) let mut zip = zip::ZipArchive::new(reader)
.map_err(|err| RookeriesError::ExtractArchiveError(err, file_type))?; .map_err(|err| RookeriesError::ExtractArchiveError(err, file_type))?;

View File

@ -1,7 +1,7 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/html"> <html lang="en" xmlns="http://www.w3.org/1999/html">
<head> <head>
<title>{{ site.name }} :: {{ current_page }}</title> <title>{{ site.title }} :: {{ current_page }}</title>
<link rel="icon" type="image/icon" href="/static/favicon.ico" /> <link rel="icon" type="image/icon" href="/static/favicon.ico" />
<link rel="stylesheet" <link rel="stylesheet"
type="text/css" type="text/css"
@ -22,7 +22,7 @@
<a href="/demo">Demo</a> <a href="/demo">Demo</a>
<a href="/license">License</a> <a href="/license">License</a>
</nav> </nav>
<rookeries-app title="{{ site.name }}" {% if dev_mode %}dev-mode{% endif %}></rookeries-app> <rookeries-app title="{{ site.title }}" {% if dev_mode %}dev-mode{% endif %}></rookeries-app>
<footer> <footer>
@ -34,8 +34,8 @@
</div> </div>
<script type="application/javascript" src="/static/js/rookeries.js"></script> <script type="application/javascript" src="/static/js/rookeries.js"></script>
{% for plugin in plugins %} {% for plugin in site.plugins %}
<script type="application/javascript" src="/static/js/{{ plugin }}-plugin.js"></script> <script type="application/javascript" src="/static/js/{{ plugin.name }}-plugin.js"></script>
{% endfor %} {% endfor %}
</body> </body>
</html> </html>

View File

@ -1,3 +1,7 @@
+++
title = "Demo"
+++
# Demo # Demo
## Markdown + HTML5 Templates ## Markdown + HTML5 Templates

View File

@ -1,3 +1,7 @@
+++
title = "Welcome"
+++
# Hello there! # Hello there!
Welcome to your new **Rookeries** powered site! Welcome to your new **Rookeries** powered site!

View File

@ -1,3 +1,7 @@
+++
title = "License (Apache v2.0)"
+++
# License for Rookeries # License for Rookeries
Copyright 2019 Dorian Puła Copyright 2019 Dorian Puła

View File

@ -78,12 +78,8 @@ fn test_init_creates_site() {
Adding plugins to site... Adding plugins to site...
Created the plugin directory. Created the plugin directory.
Copied over plugin: hello-world-plugin.js
Copied over the hello-world plugin!
Copied over plugin: dark-mode-switch-plugin.js
Copied over the dark-mode-switch plugin!
Site initialized. You can know build and serve the site. Happy hacking! Site initialized. You can now start building your new site. Happy hacking!
", ",
test_directory = &test_directory test_directory = &test_directory
@ -100,13 +96,10 @@ fn test_init_creates_site() {
let site_config_raw = assert_file_readable_into_string(site_config_file); let site_config_raw = assert_file_readable_into_string(site_config_file);
let site_config: Site = toml::from_str(&site_config_raw).unwrap(); let site_config: Site = toml::from_str(&site_config_raw).unwrap();
assert_eq!(site_config.name, "New Rookeries Site"); assert_eq!(site_config.title, "New Rookeries Site");
assert_expected_sample_pages_present(&site_config);
// Assert the pages are setup. // Assert the pages are setup.
let sample_pages = &site_config.pages.unwrap(); for page in expected_pages() {
for page in sample_pages.keys() {
let sample_page_path = &project_root_dir.join(format!("{}.md", page)); let sample_page_path = &project_root_dir.join(format!("{}.md", page));
assert!(sample_page_path.exists()); assert!(sample_page_path.exists());
@ -130,18 +123,11 @@ fn test_init_creates_site() {
assert_valid_file_types_in_path(&plugins_dir, vec!["js"], true); assert_valid_file_types_in_path(&plugins_dir, vec!["js"], true);
} }
fn assert_expected_sample_pages_present(site: &Site) { fn expected_pages() -> Vec<String> {
let sample_pages = site.pages.as_ref().unwrap(); EXPECTED_DEMO_PAGES
let expected_sample_pages: Vec<String> = EXPECTED_DEMO_PAGES
.split(" ") .split(" ")
.map(|x| x.to_string()) .map(|x| x.to_string())
.collect(); .collect()
assert_eq!(sample_pages.len(), expected_sample_pages.len());
for actual_page in sample_pages.keys() {
assert!(expected_sample_pages.contains(&actual_page));
}
} }
fn assert_file_readable_into_string(test_file: &Path) -> String { fn assert_file_readable_into_string(test_file: &Path) -> String {
@ -184,6 +170,7 @@ fn assert_valid_directory(path: &Path) {
assert!(path.is_dir()); assert!(path.is_dir());
} }
// TODO: Add a test with plugins and extras.
#[test] #[test]
fn test_build_builds_site() { fn test_build_builds_site() {
let mut rng = thread_rng(); let mut rng = thread_rng();
@ -238,8 +225,7 @@ fn test_build_builds_site() {
Copied over static asset directory! Copied over static asset directory!
Activate plugins... Activate plugins...
Copied over plugin: hello-world-plugin.js No plugins to activate.
Copied over plugin: dark-mode-switch-plugin.js
Site built. Happy hacking! Site built. Happy hacking!
@ -270,18 +256,17 @@ fn test_build_builds_site() {
let site_json = api_dir.join("site.json"); let site_json = api_dir.join("site.json");
let site_json_data = assert_file_readable_into_string(&site_json); let site_json_data = assert_file_readable_into_string(&site_json);
let test_site: Site = serde_json::from_str(&site_json_data).unwrap(); let test_site: Site = serde_json::from_str(&site_json_data).unwrap();
assert_eq!(test_site.name, "New Rookeries Site"); assert_eq!(test_site.title, "New Rookeries Site");
assert!(test_site.pages.is_some());
// Ensure sample pages rendered as JSON APIs. // Ensure sample pages rendered as JSON APIs.
assert_expected_sample_pages_present(&test_site); for test_page_name in expected_pages() {
let test_pages = &test_site.pages.unwrap();
for test_page_name in test_pages.keys() {
let actual_page_path = api_dir.join(format!("pages/{}.json", &test_page_name)); let actual_page_path = api_dir.join(format!("pages/{}.json", &test_page_name));
let actual_page_data = assert_file_readable_into_string(&actual_page_path); let actual_page_data = assert_file_readable_into_string(&actual_page_path);
let page: Page = serde_json::from_str(&actual_page_data).unwrap_or_default(); let page: Page = serde_json::from_str(&actual_page_data).unwrap_or_default();
assert_eq!(&page.slug, test_page_name); assert_eq!(page.slug, test_page_name);
assert_ne!(&page.title, ""); assert_ne!(&page.title, "");
let default_generated_title = format!("Rookeries :: {}", &page.slug);
assert_ne!(&page.title, &default_generated_title);
assert_ne!(&page.content, ""); assert_ne!(&page.content, "");
} }
@ -294,7 +279,7 @@ fn test_build_builds_site() {
); );
// Check if pages are present and rendered as expected. // Check if pages are present and rendered as expected.
for test_page_name in test_pages.keys() { for test_page_name in expected_pages() {
let actual_page_path = build_dir.join(format!("{}/index.html", &test_page_name)); let actual_page_path = build_dir.join(format!("{}/index.html", &test_page_name));
assert_file_readable_into_string(&actual_page_path); assert_file_readable_into_string(&actual_page_path);
} }