diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index f9fdf03..8726f9e 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -14,53 +14,34 @@ before_script:
# kcov
# - apt-get install -y libcurl4-openssl-dev libelf-dev libdw-dev cmake gcc binutils-dev libiberty-dev
+.cargo_test_template: &cargo_test
+ stage: test
+ script:
+ - rustc --version && cargo --version
+ - cargo build
+ - cargo test --verbose -- --test-threads=1
+
variables:
# RUSTFLAGS: "-C link-dead-code"
RUST_BACKTRACE: "FULL"
-# Currently doesnt work.
-# # Build with meson
-# build:stable:
-# # Stable img
-# # https://hub.docker.com/_/rust/
-# image: "rust"
-# script:
-# - rustc --version && cargo --version
-# - ./configure --prefix=/usr/local
-# - make && sudo make install
-
-# build:nightly:
-# # Nightly
-# # https://hub.docker.com/r/rustlang/rust/
-# image: "rustlang/rust:nightly"
-# script:
-# - rustc --version && cargo --version
-# - ./configure --prefix=/usr/local
-# - make && sudo make install
-
-test:stable:
- # Stable img
+stable:test:
# https://hub.docker.com/_/rust/
image: "rust"
- script:
- - rustc --version && cargo --version
- - cargo build
- - cargo test --verbose -- --test-threads=1
+ <<: *cargo_test
-test:nightly:
- # Nightly
+nightly:test:
# https://hub.docker.com/r/rustlang/rust/
image: "rustlang/rust:nightly"
- script:
- - rustc --version && cargo --version
- - cargo build
- - cargo test --verbose -- --test-threads=1
- # - cargo bench
+ <<: *cargo_test
# Configure and run rustfmt on nightly
# Exits and builds fails if on bad format
-lint:rustfmt:
+rustfmt:
image: "rustlang/rust:nightly"
+ stage: lint
+ variables:
+ CFG_RELEASE_CHANNEL: "nightly"
script:
- rustc --version && cargo --version
- cargo install rustfmt-nightly
@@ -68,8 +49,9 @@ lint:rustfmt:
# Configure and run clippy on nightly
# Only fails on errors atm.
-lint:clippy:
+clippy:
image: "rustlang/rust:nightly"
+ stage: lint
script:
- rustc --version && cargo --version
- cargo install clippy
diff --git a/Cargo.lock b/Cargo.lock
index 1a740c6..f6037b3 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -14,10 +14,23 @@ dependencies = [
[[package]]
name = "aho-corasick"
-version = "0.6.3"
+version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "ammonia"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "html5ever 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "maplit 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -38,7 +51,7 @@ dependencies = [
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"glib-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gobject-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -48,7 +61,7 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
"termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -62,7 +75,7 @@ dependencies = [
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -73,7 +86,7 @@ version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -81,7 +94,7 @@ name = "base64"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -107,7 +120,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "byteorder"
-version = "1.1.0"
+version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -115,7 +128,7 @@ name = "bytes"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"iovec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -133,7 +146,7 @@ dependencies = [
"cairo-sys-rs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"glib 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"glib-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -142,7 +155,7 @@ name = "cairo-sys-rs"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -162,7 +175,7 @@ name = "chrono"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -181,7 +194,7 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -189,7 +202,7 @@ name = "core-foundation-sys"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -256,31 +269,30 @@ dependencies = [
[[package]]
name = "diesel"
-version = "0.16.0"
-source = "git+https://github.com/diesel-rs/diesel.git#07f80c3a0d07daa26efff3166fbf0297dc0f0a7b"
+version = "0.99.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "diesel_derives 0.99.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libsqlite3-sys 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
-name = "diesel_codegen"
-version = "0.16.0"
-source = "git+https://github.com/diesel-rs/diesel.git#07f80c3a0d07daa26efff3166fbf0297dc0f0a7b"
+name = "diesel_derives"
+version = "0.99.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "diesel 0.16.0 (git+https://github.com/diesel-rs/diesel.git)",
- "diesel_infer_schema 0.16.0 (git+https://github.com/diesel-rs/diesel.git)",
- "dotenv 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
-name = "diesel_infer_schema"
-version = "0.16.0"
-source = "git+https://github.com/diesel-rs/diesel.git#07f80c3a0d07daa26efff3166fbf0297dc0f0a7b"
+name = "diesel_migrations"
+version = "0.99.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "diesel 0.16.0 (git+https://github.com/diesel-rs/diesel.git)",
+ "migrations_internals 0.99.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "migrations_macros 0.99.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -299,7 +311,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"derive-error-chain 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -338,7 +350,15 @@ dependencies = [
[[package]]
name = "foreign-types"
-version = "0.2.0"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "foreign-types-shared"
+version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -394,7 +414,7 @@ dependencies = [
"glib 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"glib-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gobject-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
"pango 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -407,7 +427,7 @@ dependencies = [
"glib 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"glib-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gobject-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -419,7 +439,7 @@ dependencies = [
"gio-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"glib-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gobject-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -434,7 +454,7 @@ dependencies = [
"gio-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"glib-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gobject-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
"pango-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -449,7 +469,7 @@ dependencies = [
"glib 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"glib-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gobject-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -460,7 +480,7 @@ dependencies = [
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"glib-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gobject-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -473,7 +493,7 @@ dependencies = [
"glib-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gobject-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -482,7 +502,7 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -493,7 +513,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"glib-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -515,7 +535,7 @@ dependencies = [
"glib-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gobject-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gtk-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
"pango 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -532,7 +552,7 @@ dependencies = [
"gio-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"glib-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gobject-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
"pango-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -541,20 +561,22 @@ dependencies = [
name = "hammond-data"
version = "0.1.0"
dependencies = [
+ "ammonia 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"chrono 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "diesel 0.16.0 (git+https://github.com/diesel-rs/diesel.git)",
- "diesel_codegen 0.16.0 (git+https://github.com/diesel-rs/diesel.git)",
+ "derive_builder 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "diesel 0.99.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "diesel_migrations 0.99.0 (registry+https://github.com/rust-lang/crates.io-index)",
"dotenv 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "r2d2 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "r2d2-diesel 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "r2d2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "r2d2-diesel 0.99.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
"rayon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"reqwest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rfc822_sanitizer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "rss 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rss 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"xdg 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -564,12 +586,12 @@ dependencies = [
name = "hammond-downloader"
version = "0.1.0"
dependencies = [
- "diesel 0.16.0 (git+https://github.com/diesel-rs/diesel.git)",
+ "diesel 0.99.0 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"hammond-data 0.1.0",
"hyper 0.11.7 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "mime_guess 1.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mime_guess 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)",
"reqwest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -578,8 +600,7 @@ dependencies = [
name = "hammond-gtk"
version = "0.1.0"
dependencies = [
- "diesel 0.16.0 (git+https://github.com/diesel-rs/diesel.git)",
- "diesel_codegen 0.16.0 (git+https://github.com/diesel-rs/diesel.git)",
+ "diesel 0.99.0 (registry+https://github.com/rust-lang/crates.io-index)",
"dissolve 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"gdk 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gdk-pixbuf 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -589,9 +610,10 @@ dependencies = [
"hammond-data 0.1.0",
"hammond-downloader 0.1.0",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "loggerv 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "loggerv 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rayon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -663,7 +685,7 @@ name = "iovec"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -691,6 +713,11 @@ name = "lazy_static"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
+[[package]]
+name = "lazy_static"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
[[package]]
name = "lazycell"
version = "0.5.1"
@@ -698,7 +725,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
-version = "0.2.33"
+version = "0.2.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -707,7 +734,7 @@ version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"adler32 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"crc 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -727,7 +754,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "loggerv"
-version = "0.5.1"
+version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -740,6 +767,11 @@ name = "mac"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
+[[package]]
+name = "maplit"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
[[package]]
name = "markup5ever"
version = "0.6.2"
@@ -760,10 +792,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "memchr"
-version = "1.0.2"
+version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "migrations_internals"
+version = "0.99.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "diesel 0.99.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "migrations_macros"
+version = "0.99.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "migrations_internals 0.99.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -784,7 +834,7 @@ dependencies = [
[[package]]
name = "mime_guess"
-version = "1.8.2"
+version = "1.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -795,7 +845,7 @@ dependencies = [
[[package]]
name = "mime_guess"
-version = "2.0.0-alpha.2"
+version = "2.0.0-alpha.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"mime 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -814,7 +864,7 @@ dependencies = [
"iovec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazycell 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -838,7 +888,7 @@ name = "native-tls"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "openssl 0.9.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl 0.9.22 (registry+https://github.com/rust-lang/crates.io-index)",
"schannel 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"security-framework 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
"security-framework-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -852,19 +902,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num"
-version = "0.1.40"
+version = "0.1.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
"num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
- "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -872,7 +922,7 @@ name = "num-integer"
version = "0.1.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -881,12 +931,12 @@ version = "0.1.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
- "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num-traits"
-version = "0.1.40"
+version = "0.1.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -894,7 +944,7 @@ name = "num_cpus"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -904,23 +954,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "openssl"
-version = "0.9.21"
+version = "0.9.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.22 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "openssl-sys"
-version = "0.9.21"
+version = "0.9.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -934,7 +984,7 @@ dependencies = [
"glib 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"glib-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gobject-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
"pango-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -946,7 +996,7 @@ dependencies = [
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"glib-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gobject-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1002,12 +1052,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "quick-xml"
-version = "0.9.4"
+version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"encoding_rs 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1017,21 +1067,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "r2d2"
-version = "0.7.4"
+version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "scheduled-thread-pool 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "scheduled-thread-pool 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "r2d2-diesel"
-version = "0.16.0"
+version = "0.99.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "diesel 0.16.0 (git+https://github.com/diesel-rs/diesel.git)",
- "r2d2 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "diesel 0.99.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "r2d2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1040,7 +1090,7 @@ version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1059,14 +1109,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "redox_syscall"
-version = "0.1.31"
+version = "0.1.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -1074,16 +1124,16 @@ name = "redox_termios"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex"
-version = "0.2.2"
+version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1113,10 +1163,10 @@ dependencies = [
"hyper-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libflate 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "mime_guess 2.0.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mime_guess 2.0.0-alpha.3 (registry+https://github.com/rust-lang/crates.io-index)",
"native-tls 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_urlencoded 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-core 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1132,16 +1182,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"chrono 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rss"
-version = "1.1.0"
+version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"derive_builder 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "quick-xml 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quick-xml 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1175,7 +1225,7 @@ dependencies = [
[[package]]
name = "scheduled-thread-pool"
-version = "0.1.0"
+version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1207,7 +1257,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"core-foundation 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
"security-framework-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1217,23 +1267,23 @@ version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde"
-version = "1.0.21"
+version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde_json"
-version = "1.0.6"
+version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -1243,7 +1293,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1276,7 +1326,7 @@ dependencies = [
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
"precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)",
"string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1343,8 +1393,8 @@ name = "termion"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
- "redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1363,8 +1413,8 @@ version = "0.1.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
- "redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -1552,7 +1602,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum adler32 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6cbd0b9af8587c72beadc9f72d35b9fbb070982c9e6203e46e93f10df25f8f45"
"checksum advapi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e06588080cb19d0acb6739808aafa5f26bfb2ca015b2b6370028b44cf7cb8a9a"
-"checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699"
+"checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4"
+"checksum ammonia 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2cc0ea12b4977283c563e78eaf227b024d89d72a6394040fad4063899bfcfb48"
"checksum ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b3568b48b7cefa6b8ce125f9bb4989e52fbcc29ebea88df04cc7c5f12f70455"
"checksum antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34fde25430d87a9388dadbe6e34d7f72a462c8b43ac8d309b42b0a8505d7e2a5"
"checksum atk-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "33a67fd81e1922dddc335887516f2f5254534e89c9d39fa89bca5d79bd150d34"
@@ -1564,7 +1615,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
"checksum build_const 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e90dc84f5e62d2ebe7676b83c22d33b6db8bd27340fb6ffbff0a364efa0cb9c9"
-"checksum byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff81738b726f5d099632ceaffe7fb65b90212e8dce59d518729e7e8634032d3d"
+"checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23"
"checksum bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d828f97b58cc5de3e40c421d0cf2132d6b2da4ee0e11b8632fa838f0f9333ad6"
"checksum c_vec 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6237ac5a4b1e81c213c24c6437964c61e646df910a914b4ab1487b46df20bd13"
"checksum cairo-rs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6b5695f59fd036fe5741bc5a4eb20c78fbe42256e3b08a2af26bbcbe8070bf3"
@@ -1582,9 +1633,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum derive-error-chain 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3c9ca9ade651388daad7c993f005d0d20c4f6fe78c1cdc93e95f161c6f5ede4a"
"checksum derive_builder 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "03600ae366b6eb2314e54d62adc833d9866da03798acc61c61789654ceaa227a"
"checksum derive_builder_core 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eed37eae64daa5511467b1a55cebdf472deeaef108d22f62f25e8bbcaffd56ac"
-"checksum diesel 0.16.0 (git+https://github.com/diesel-rs/diesel.git)" = ""
-"checksum diesel_codegen 0.16.0 (git+https://github.com/diesel-rs/diesel.git)" = ""
-"checksum diesel_infer_schema 0.16.0 (git+https://github.com/diesel-rs/diesel.git)" = ""
+"checksum diesel 0.99.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0b97bd43f72d4819fac99f24d0030184c64c5ebdee96f94c7a7d4215c50506a7"
+"checksum diesel_derives 0.99.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad228b6fd05c86050b95f56e497a8135073ffce28602e2200e63a21047eb474d"
+"checksum diesel_migrations 0.99.0 (registry+https://github.com/rust-lang/crates.io-index)" = "745dcfe39e3043c267e46dbe4f2ebbc9917039bdf4d81b108950be61244dfc89"
"checksum dissolve 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "898542be4716d992082c8e4fc331b792d626cfa71cb2b4790f828b9a8f921a90"
"checksum dotenv 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d6f0e2bb24d163428d8031d3ebd2d2bd903ad933205a97d0f18c7c1aade380f3"
"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
@@ -1592,7 +1643,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum encoding_rs 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f5215aabf22b83153be3ee44dfe3f940214541b2ce13d419c55e7a115c8c51a9"
"checksum error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9435d864e017c3c6afeac1654189b06cdb491cf2ff73dbf0d73b0f292f42ff8"
"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
-"checksum foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e4056b9bd47f8ac5ba12be771f77a0dae796d1bbaaf5fd0b9c2d38b69b8a29d"
+"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
+"checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
"checksum fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f6c0581a4e363262e52b87f59ee2afe3415361c6ec35e665924eb08afe8ff159"
"checksum fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "43f3795b4bae048dc6123a6b972cadde2e676f9ded08aef6bb77f5f157684a82"
"checksum futf 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "51f93f3de6ba1794dcd5810b3546d004600a59a98266487c8407bc4b24e398f3"
@@ -1619,32 +1671,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
+"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d"
"checksum lazycell 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b585b7a6811fb03aa10e74b278a0f00f8dd9b45dc681f148bb29fa5cb61859b"
-"checksum libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "5ba3df4dcb460b9dfbd070d41c94c19209620c191b0340b929ce748a2bcd42d2"
+"checksum libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)" = "36fbc8a8929c632868295d0178dd8f63fc423fd7537ad0738372bd010b3ac9b0"
"checksum libflate 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "ae46bcdafa496981e996e57c5be82c0a7f130a071323764c6faa4803619f1e67"
"checksum libsqlite3-sys 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "370090ad578ba845a3ad4f383ceb3deba7abd51ab1915ad1f2c982cc6035e31c"
"checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b"
-"checksum loggerv 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5bb7c9e1ed99294067005cc7d4413441197ba354e8286c36b72a66a557c13661"
+"checksum loggerv 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b178879253fab6ddb4ea931e1e6f514d45ce6a53f7fe618a0a8751f43e42e4f1"
"checksum mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
+"checksum maplit 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ed95049d40b8a1a7691adbabca028ad481f7e6a2921ce4846e1ee168b4e4ca5"
"checksum markup5ever 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2cf89d3e0486c32c9d99521455ddf9a438910a1ce2bd376936086edc15dff5fc"
"checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376"
-"checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a"
+"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
+"checksum migrations_internals 0.99.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ac1d17f6f161f4d91cb7e5a72cce5b24a60b80f96580a8ac94351c56b8606a"
+"checksum migrations_macros 0.99.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dc767420eac6b718cd593aaa09c06a31d4ed228291c8538b274737e28a29939b"
"checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0"
"checksum mime 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e2e00e17be181010a91dbfefb01660b17311059dc8c7f48b9017677721e732bd"
-"checksum mime_guess 1.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bbee1a836f344ac39d4a59bfe7be2bd3150353ff71678afb740216f8270b333e"
-"checksum mime_guess 2.0.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)" = "27a5e6679a0614e25adc14c6434ba84e41632b765a6d9cb2031a0cca682699ae"
+"checksum mime_guess 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dc7e82a15629bb4ecd9e72365bf33d1382be91e030f820edb8e2a21c02430da8"
+"checksum mime_guess 2.0.0-alpha.3 (registry+https://github.com/rust-lang/crates.io-index)" = "013572795763289e14710c7b279461295f2673b2b338200c235082cd7ca9e495"
"checksum mio 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0e8411968194c7b139e9105bc4ae7db0bae232af087147e72f0616ebf5fdb9cb"
"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
"checksum native-tls 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04b781c9134a954c84f0594b9ab3f5606abc516030388e8511887ef4c204a1e5"
"checksum net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "3a80f842784ef6c9a958b68b7516bc7e35883c614004dd94959a4dca1b716c09"
-"checksum num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "a311b77ebdc5dd4cf6449d81e4135d9f0e3b153839ac90e648a8ef538f923525"
+"checksum num 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cc4083e14b542ea3eb9b5f33ff48bd373a92d78687e74f4cc0a30caeb754f0ca"
"checksum num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "d1452e8b06e448a07f0e6ebb0bb1d92b8890eea63288c0b627331d53514d0fba"
"checksum num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "7485fcc84f85b4ecd0ea527b14189281cf27d60e583ae65ebc9c088b13dffe01"
-"checksum num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "99843c856d68d8b4313b03a17e33c4bb42ae8f6610ea81b28abe076ac721b9b0"
+"checksum num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cacfcab5eb48250ee7d0c7896b51a2c5eec99c1feea5f32025635f5ae4b00070"
"checksum num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "514f0d73e64be53ff320680ca671b64fe3fb91da01e1ae2ddc99eb51d453b20d"
"checksum open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c281318d992e4432cfa799969467003d05921582a7489a8325e37f8a450d5113"
-"checksum openssl 0.9.21 (registry+https://github.com/rust-lang/crates.io-index)" = "2225c305d8f57001a0d34263e046794aa251695f20773102fbbfeb1e7b189955"
-"checksum openssl-sys 0.9.21 (registry+https://github.com/rust-lang/crates.io-index)" = "92867746af30eea7a89feade385f7f5366776f1c52ec6f0de81360373fa88363"
+"checksum openssl 0.9.22 (registry+https://github.com/rust-lang/crates.io-index)" = "419ef26bb651d72b6c5a603bcc4e4856a362460e62352dfffa53de91d2e81181"
+"checksum openssl-sys 0.9.22 (registry+https://github.com/rust-lang/crates.io-index)" = "5483bdc56756041ba6aa37c9cb59cc2219f012a2a1377d97ad35556ac6676ee7"
"checksum pango 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e81c404ab81ea7ea2fc2431a0a7672507b80e4b8bf4b41eac3fc83cc665104e"
"checksum pango-sys 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34f34a1be107fe16abb2744e0e206bee4b3b07460b5fddd3009a6aaf60bd69ab"
"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
@@ -1654,33 +1710,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "07e24b0ca9643bdecd0632f2b3da6b1b89bbb0030e0b992afc1113b23a7bc2f2"
"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
"checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
-"checksum quick-xml 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)" = "19a3a610544419c527d5f51ae1a6ae3db533e25c117d3eed8fce6434f70c5e95"
+"checksum quick-xml 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d0fb3e41d968cd20da34a9e81abae097398b38fe0987149e321572eb75d3317"
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
-"checksum r2d2 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "2c8284508b38df440f8f3527395e23c4780b22f74226b270daf58fee38e4bcce"
-"checksum r2d2-diesel 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f6b921696a6c45991296d21b52ed973b9fb56f6c47524fda1f99458c2d6c0478"
+"checksum r2d2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "59611202bee496c586ecd84e3ed149b4ec75981b0fc10d7f60e878fa23ae16e9"
+"checksum r2d2-diesel 0.99.0 (registry+https://github.com/rust-lang/crates.io-index)" = "77aaed149a82720f4b664427f359e1b2a34d8787c1bc3fb1d167b104a1ddd866"
"checksum rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)" = "6475140dfd8655aeb72e1fd4b7a1cc1c202be65d71669476e392fe62532b9edd"
"checksum rayon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed02d09394c94ffbdfdc755ad62a132e94c3224a8354e78a1200ced34df12edf"
"checksum rayon-core 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e64b609139d83da75902f88fd6c01820046840a18471e4dfcd5ac7c0f46bea53"
-"checksum redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "8dde11f18c108289bef24469638a04dce49da56084f2d50618b226e47eb04509"
+"checksum redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "ab105df655884ede59d45b7070c8a65002d921461ee813a024558ca16030eea0"
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
-"checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b"
+"checksum regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ac6ab4e9218ade5b423358bbd2567d1617418403c7a512603630181813316322"
"checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db"
"checksum relay 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f301bafeb60867c85170031bdb2fcf24c8041f33aee09e7b116a58d4e9f781c5"
"checksum reqwest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f73a8482e3b2b20ef5c07168b27048fc3778a012ce9b11a021556a450a01e9b5"
"checksum rfc822_sanitizer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "680e8305c1e0cdf836dc4bec5424e045f278c975a3cac36d1ca01c4695f9d815"
-"checksum rss 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "70294b2be2d620fed3939032067684c53b8ccae18e8ca0b8410447f0f07228c5"
+"checksum rss 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3fbc1a0587ebbc7404b3295c8e1f717d00dad48e3c205adadf916f15ff67d05b"
"checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e"
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
"checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f"
"checksum schannel 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7554288337c1110e34d7a2433518d889374c1de1a45f856b7bcddb03702131fc"
-"checksum scheduled-thread-pool 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d9fbe48ead32343b76f544c85953bf260ed39219a8bbbb62cd85f6a00f9644f"
+"checksum scheduled-thread-pool 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a2ff3fc5223829be817806c6441279c676e454cc7da608faf03b0ccc09d3889"
"checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d"
"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
"checksum secur32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f412dfa83308d893101dd59c10d6fda8283465976c28c287c5c855bf8d216bc"
"checksum security-framework 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "dfa44ee9c54ce5eecc9de7d5acbad112ee58755239381f687e564004ba4a2332"
"checksum security-framework-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "5421621e836278a0b139268f36eee0dc7e389b784dc3f79d8f11aabadf41bead"
-"checksum serde 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6eda663e865517ee783b0891a3f6eb3a253e0b0dabb46418969ee9635beadd9e"
-"checksum serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e4586746d1974a030c48919731ecffd0ed28d0c40749d0d18d43b3a7d6c9b20e"
+"checksum serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)" = "6a7c37d7f192f00041e8a613e936717923a71bc0c9051fc4425a49b104140f05"
+"checksum serde_json 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ea28ea0cca944668919bec6af209864a8dfe769fd2b0b723f36b22e20c1bf69f"
"checksum serde_urlencoded 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce0fd303af908732989354c6f02e05e2e6d597152870f2c6990efb0577137480"
"checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537"
"checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23"
diff --git a/Cargo.toml b/Cargo.toml
index 545646a..d1deebf 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -8,7 +8,3 @@ members = [
[profile.release]
debug = false
-[patch.crates-io]
-diesel = { git = "https://github.com/diesel-rs/diesel.git" }
-diesel_infer_schema = { git = "https://github.com/diesel-rs/diesel.git" }
-diesel_codegen = { git = "https://github.com/diesel-rs/diesel.git" }
diff --git a/TODO.md b/TODO.md
index 0316ac8..1ed5678 100644
--- a/TODO.md
+++ b/TODO.md
@@ -1,14 +1,9 @@
## TODOs:
-**General:**
-
-- [ ] Write docs
-
## Planned Features
## Priorities:
-- [ ] Discuss and decide when to schedule the download cleaner. [#3](https://gitlab.gnome.org/alatiera/Hammond/issues/3)
- [ ] Unplayed Only and Downloaded only view.
- [ ] Auto-updater
- [ ] OPML import/export // Probably need to create a crate.
diff --git a/hammond-data/Cargo.toml b/hammond-data/Cargo.toml
index 2083fe0..34e41c4 100644
--- a/hammond-data/Cargo.toml
+++ b/hammond-data/Cargo.toml
@@ -5,27 +5,29 @@ version = "0.1.0"
workspace = "../"
[dependencies]
+ammonia = "1.0.0"
chrono = "0.4.0"
+derive_builder = "0.5.0"
dotenv = "0.10.1"
error-chain = "0.11.0"
-lazy_static = "0.2.11"
+lazy_static = "1.0.0"
log = "0.3.8"
-r2d2 = "0.7.4"
-r2d2-diesel = "0.16.0"
+r2d2 = "0.8.1"
+r2d2-diesel = "0.99.0"
rayon = "0.9.0"
reqwest = "0.8.1"
rfc822_sanitizer = "0.3.3"
-rss = "1.1.0"
+rss = "1.2.1"
url = "1.6.0"
xdg = "2.1.0"
[dependencies.diesel]
features = ["sqlite"]
-git = "https://github.com/diesel-rs/diesel.git"
+version = "0.99.0"
-[dependencies.diesel_codegen]
+[dependencies.diesel_migrations]
features = ["sqlite"]
-git = "https://github.com/diesel-rs/diesel.git"
+version = "0.99.0"
[dev-dependencies]
rand = "0.3.18"
diff --git a/hammond-data/src/database.rs b/hammond-data/src/database.rs
index c3f024e..bb18bda 100644
--- a/hammond-data/src/database.rs
+++ b/hammond-data/src/database.rs
@@ -3,16 +3,14 @@ use diesel::prelude::*;
use r2d2;
use std::path::PathBuf;
-use std::sync::Arc;
use std::io;
-use std::time::Duration;
use errors::*;
#[cfg(not(test))]
use xdg_dirs;
-type Pool = Arc>>;
+type Pool = r2d2::Pool>;
embed_migrations!("migrations/");
@@ -38,19 +36,18 @@ lazy_static! {
}
pub(crate) fn connection() -> Pool {
- Arc::clone(&POOL)
+ POOL.clone()
}
fn init_pool(db_path: &str) -> Pool {
- let config = r2d2::Config::builder()
- .pool_size(1)
- .connection_timeout(Duration::from_secs(60))
- .build();
let manager = ConnectionManager::::new(db_path);
- let pool = Arc::new(r2d2::Pool::new(config, manager).expect("Failed to create pool."));
+ let pool = r2d2::Pool::builder()
+ .max_size(1)
+ .build(manager)
+ .expect("Failed to create pool.");
{
- let db = Arc::clone(&pool).get().expect("Failed to initialize pool.");
+ let db = pool.get().expect("Failed to initialize pool.");
run_migration_on(&*db).expect("Failed to run migrations during init.");
}
info!("Database pool initialized.");
diff --git a/hammond-data/src/dbqueries.rs b/hammond-data/src/dbqueries.rs
index f4c0791..1604547 100644
--- a/hammond-data/src/dbqueries.rs
+++ b/hammond-data/src/dbqueries.rs
@@ -198,9 +198,10 @@ pub fn update_none_to_played_now(parent: &Podcast) -> Result {
let epoch_now = Utc::now().timestamp() as i32;
con.transaction(|| -> Result {
- Ok(diesel::update(
- Episode::belonging_to(parent).filter(played.is_null()),
- ).set(played.eq(Some(epoch_now)))
- .execute(&*con)?)
+ Ok(
+ diesel::update(Episode::belonging_to(parent).filter(played.is_null()))
+ .set(played.eq(Some(epoch_now)))
+ .execute(&*con)?,
+ )
})
}
diff --git a/hammond-data/src/errors.rs b/hammond-data/src/errors.rs
index 372cc55..274a1a1 100644
--- a/hammond-data/src/errors.rs
+++ b/hammond-data/src/errors.rs
@@ -1,5 +1,5 @@
use diesel::result;
-use diesel::migrations::RunMigrationsError;
+use diesel_migrations::RunMigrationsError;
use rss;
use reqwest;
use r2d2;
@@ -8,7 +8,7 @@ use std::io;
error_chain! {
foreign_links {
- R2D2TimeoutError(r2d2::GetTimeout);
+ R2D2Error(r2d2::Error);
DieselResultError(result::Error);
DieselMigrationError(RunMigrationsError);
RSSError(rss::Error);
diff --git a/hammond-data/src/feed.rs b/hammond-data/src/feed.rs
index 5fd9d33..af38f1a 100644
--- a/hammond-data/src/feed.rs
+++ b/hammond-data/src/feed.rs
@@ -4,7 +4,7 @@ use rayon::prelude::*;
use diesel::prelude::*;
use rayon::iter::IntoParallelIterator;
-use diesel::Identifiable;
+use diesel::associations::Identifiable;
use rss;
use dbqueries;
@@ -276,13 +276,12 @@ mod tests {
f2.get_episodes().unwrap()
};
- eps1.into_par_iter()
- .zip(eps2)
- .into_par_iter()
- .for_each(|(ep1, ep2): (Episode, Episode)| {
+ eps1.into_par_iter().zip(eps2).into_par_iter().for_each(
+ |(ep1, ep2): (Episode, Episode)| {
assert_eq!(ep1, ep2);
assert_eq!(ep1.id(), ep2.id());
assert_eq!(ep1.podcast_id(), ep2.podcast_id());
- });
+ },
+ );
}
}
diff --git a/hammond-data/src/lib.rs b/hammond-data/src/lib.rs
index e8ca7f4..9828740 100644
--- a/hammond-data/src/lib.rs
+++ b/hammond-data/src/lib.rs
@@ -1,5 +1,4 @@
#![recursion_limit = "1024"]
-#![deny(missing_docs)]
#![cfg_attr(feature = "cargo-clippy", allow(blacklisted_name))]
#![cfg_attr(feature = "clippy",
warn(option_unwrap_used, result_unwrap_used, print_stdout,
@@ -11,6 +10,15 @@
//! A libraty for parsing, indexing and retrieving podcast Feeds,
//! into and from a Database.
+#![deny(bad_style, const_err, dead_code, improper_ctypes, legacy_directory_ownership,
+ non_shorthand_field_patterns, no_mangle_generic_items, overflowing_literals,
+ path_statements, patterns_in_fns_without_body, plugin_as_library, private_in_public,
+ private_no_mangle_fns, private_no_mangle_statics, safe_extern_statics,
+ unconditional_recursion, unions_with_drop_fields, unused, unused_allocation,
+ unused_comparisons, unused_parens, while_true)]
+#![deny(missing_debug_implementations, missing_docs, trivial_casts, trivial_numeric_casts,
+ unused_extern_crates)]
+
#[macro_use]
extern crate error_chain;
@@ -22,9 +30,14 @@ extern crate log;
#[macro_use]
extern crate diesel;
-#[macro_use]
-extern crate diesel_codegen;
+#[macro_use]
+extern crate diesel_migrations;
+
+#[macro_use]
+extern crate derive_builder;
+
+extern crate ammonia;
extern crate chrono;
extern crate r2d2;
extern crate r2d2_diesel;
@@ -49,6 +62,7 @@ mod schema;
pub use models::queryables::{Episode, Podcast, Source};
/// [XDG Base Direcotory](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html) Paths.
+#[allow(missing_debug_implementations)]
pub mod xdg_dirs {
use std::path::PathBuf;
use xdg;
diff --git a/hammond-data/src/models/insertables.rs b/hammond-data/src/models/insertables.rs
index 7a0ddef..c303dfa 100644
--- a/hammond-data/src/models/insertables.rs
+++ b/hammond-data/src/models/insertables.rs
@@ -1,3 +1,5 @@
+#![allow(unused_mut)]
+
use diesel::prelude::*;
use schema::{episode, podcast, source};
@@ -20,7 +22,10 @@ trait Update {
#[derive(Insertable)]
#[table_name = "source"]
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, Default, Builder)]
+#[builder(default)]
+#[builder(derive(Debug))]
+#[builder(setter(into))]
pub(crate) struct NewSource {
uri: String,
last_modified: Option,
@@ -63,15 +68,15 @@ impl NewSource {
#[derive(Insertable, AsChangeset)]
#[table_name = "podcast"]
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, Default, Builder)]
+#[builder(default)]
+#[builder(derive(Debug))]
+#[builder(setter(into))]
pub(crate) struct NewPodcast {
title: String,
link: String,
description: String,
image_uri: Option,
- favorite: bool,
- archive: bool,
- always_dl: bool,
source_id: i32,
}
@@ -124,78 +129,6 @@ impl NewPodcast {
}
}
-#[derive(Debug, Default)]
-pub(crate) struct NewPodcastBuilder {
- title: String,
- link: String,
- description: String,
- image_uri: Option,
- favorite: bool,
- archive: bool,
- always_dl: bool,
- source_id: i32,
-}
-
-#[allow(dead_code)]
-impl NewPodcastBuilder {
- pub(crate) fn new() -> NewPodcastBuilder {
- NewPodcastBuilder::default()
- }
-
- pub(crate) fn title(mut self, s: String) -> NewPodcastBuilder {
- self.title = s;
- self
- }
-
- pub(crate) fn link(mut self, s: String) -> NewPodcastBuilder {
- self.link = s;
- self
- }
-
- pub(crate) fn description(mut self, s: String) -> NewPodcastBuilder {
- self.description = s;
- self
- }
-
- pub(crate) fn image_uri(mut self, s: Option) -> NewPodcastBuilder {
- self.image_uri = s;
- self
- }
-
- pub(crate) fn source_id(mut self, s: i32) -> NewPodcastBuilder {
- self.source_id = s;
- self
- }
-
- pub(crate) fn favorite(mut self, s: bool) -> NewPodcastBuilder {
- self.favorite = s;
- self
- }
-
- pub(crate) fn archive(mut self, s: bool) -> NewPodcastBuilder {
- self.archive = s;
- self
- }
-
- pub(crate) fn always_dl(mut self, s: bool) -> NewPodcastBuilder {
- self.always_dl = s;
- self
- }
-
- pub(crate) fn build(self) -> NewPodcast {
- NewPodcast {
- title: self.title,
- link: self.link,
- description: self.description,
- image_uri: self.image_uri,
- favorite: self.favorite,
- archive: self.archive,
- always_dl: self.always_dl,
- source_id: self.source_id,
- }
- }
-}
-
#[allow(dead_code)]
// Ignore the following geters. They are used in unit tests mainly.
impl NewPodcast {
@@ -222,19 +155,18 @@ impl NewPodcast {
#[derive(Insertable, AsChangeset)]
#[table_name = "episode"]
-#[derive(Debug, Clone, Default)]
+#[derive(Debug, Clone, Default, Builder)]
+#[builder(default)]
+#[builder(derive(Debug))]
+#[builder(setter(into))]
pub(crate) struct NewEpisode {
title: Option,
uri: String,
- local_uri: Option,
description: Option,
published_date: Option,
length: Option,
guid: Option,
epoch: i32,
- played: Option,
- favorite: bool,
- archive: bool,
podcast_id: i32,
}
@@ -256,8 +188,6 @@ impl Update for NewEpisode {
}
impl NewEpisode {
- // TODO: Currently using diesel from master git.
- // Watch out for v0.99.0 beta and change the toml.
// TODO: Refactor into batch indexes instead.
pub(crate) fn into_episode(self, con: &SqliteConnection) -> Result {
self.index(con)?;
@@ -287,108 +217,8 @@ impl NewEpisode {
}
}
-#[derive(Debug, Default)]
-pub(crate) struct NewEpisodeBuilder {
- title: Option,
- uri: String,
- local_uri: Option,
- description: Option,
- published_date: Option,
- length: Option,
- guid: Option,
- epoch: i32,
- played: Option,
- favorite: bool,
- archive: bool,
- podcast_id: i32,
-}
-
#[allow(dead_code)]
-impl NewEpisodeBuilder {
- pub(crate) fn new() -> NewEpisodeBuilder {
- NewEpisodeBuilder::default()
- }
-
- pub(crate) fn title(mut self, s: Option) -> NewEpisodeBuilder {
- self.title = s;
- self
- }
-
- pub(crate) fn uri(mut self, s: String) -> NewEpisodeBuilder {
- self.uri = s;
- self
- }
-
- pub(crate) fn local_uri(mut self, s: Option) -> NewEpisodeBuilder {
- self.local_uri = s;
- self
- }
-
- pub(crate) fn description(mut self, s: Option) -> NewEpisodeBuilder {
- self.description = s;
- self
- }
-
- pub(crate) fn published_date(mut self, s: Option) -> NewEpisodeBuilder {
- self.published_date = s;
- self
- }
-
- pub(crate) fn length(mut self, s: Option) -> NewEpisodeBuilder {
- self.length = s;
- self
- }
-
- pub(crate) fn played(mut self, s: Option) -> NewEpisodeBuilder {
- self.played = s;
- self
- }
-
- pub(crate) fn guid(mut self, s: Option) -> NewEpisodeBuilder {
- self.guid = s;
- self
- }
-
- pub(crate) fn epoch(mut self, s: i32) -> NewEpisodeBuilder {
- self.epoch = s;
- self
- }
-
- pub(crate) fn podcast_id(mut self, s: i32) -> NewEpisodeBuilder {
- self.podcast_id = s;
- self
- }
-
- pub(crate) fn favorite(mut self, s: bool) -> NewEpisodeBuilder {
- self.favorite = s;
- self
- }
-
- pub(crate) fn archive(mut self, s: bool) -> NewEpisodeBuilder {
- self.archive = s;
- self
- }
-
- pub(crate) fn build(self) -> NewEpisode {
- NewEpisode {
- title: self.title,
- uri: self.uri,
- local_uri: self.local_uri,
- description: self.description,
- published_date: self.published_date,
- length: self.length,
- guid: self.guid,
- epoch: self.epoch,
- played: self.played,
- favorite: self.favorite,
- archive: self.archive,
- podcast_id: self.podcast_id,
- }
- }
-}
-
-#[allow(dead_code)]
-// Ignore the following geters. They are used in unit tests mainly.
+// Ignore the following getters. They are used in unit tests mainly.
impl NewEpisode {
pub(crate) fn title(&self) -> Option<&str> {
self.title.as_ref().map(|s| s.as_str())
diff --git a/hammond-data/src/models/queryables.rs b/hammond-data/src/models/queryables.rs
index 2e991df..2e41ea6 100644
--- a/hammond-data/src/models/queryables.rs
+++ b/hammond-data/src/models/queryables.rs
@@ -342,9 +342,9 @@ impl<'a> Source {
let lmod = headers.get::();
// FIXME: This dsnt work most of the time apparently
- if self.http_etag() != etag.map(|x| x.tag())
- || self.last_modified != lmod.map(|x| format!("{}", x))
- {
+ if self.http_etag() != etag.map(|x| x.tag()) || self.last_modified != lmod.map(|x| {
+ format!("{}", x)
+ }) {
self.http_etag = etag.map(|x| x.tag().to_string().to_owned());
self.last_modified = lmod.map(|x| format!("{}", x));
self.save()?;
diff --git a/hammond-data/src/parser.rs b/hammond-data/src/parser.rs
index 5ea6ce2..97043a5 100644
--- a/hammond-data/src/parser.rs
+++ b/hammond-data/src/parser.rs
@@ -1,3 +1,4 @@
+use ammonia;
use rss::{Channel, Item};
use rfc822_sanitizer::parse_from_rfc2822_with_fallback;
@@ -9,10 +10,10 @@ use errors::*;
// TODO: Extend the support for parsing itunes extensions
/// Parses a `rss::Channel` into a `NewPodcast` Struct.
pub(crate) fn new_podcast(chan: &Channel, source_id: i32) -> NewPodcast {
- let title = chan.title().trim().to_owned();
- let description = chan.description().trim().to_owned();
+ let title = chan.title().trim();
+ let description = ammonia::clean(chan.description().trim());
- let link = url_cleaner(chan.link()).to_owned();
+ let link = url_cleaner(chan.link());
let x = chan.itunes_ext().map(|s| s.image());
let image_uri = if let Some(img) = x {
img.map(|s| url_cleaner(s))
@@ -20,19 +21,20 @@ pub(crate) fn new_podcast(chan: &Channel, source_id: i32) -> NewPodcast {
chan.image().map(|foo| url_cleaner(foo.url()))
};
- NewPodcastBuilder::new()
+ NewPodcastBuilder::default()
.title(title)
.description(description)
.link(link)
.image_uri(image_uri)
.source_id(source_id)
.build()
+ .unwrap()
}
/// Parses an `rss::Item` into a `NewEpisode` Struct.
pub(crate) fn new_episode(item: &Item, parent_id: i32) -> Result {
let title = item.title().map(|s| s.trim().to_owned());
- let description = item.description().map(|s| s.trim().to_owned());
+ let description = item.description().map(|s| ammonia::clean(s.trim()));
let guid = item.guid().map(|s| s.value().trim().to_owned());
// Its kinda weird this being an Option type.
@@ -60,18 +62,17 @@ pub(crate) fn new_episode(item: &Item, parent_id: i32) -> Result {
let length = item.enclosure().map(|x| x.length().parse().unwrap_or(0));
- Ok(
- NewEpisodeBuilder::new()
- .title(title)
- .uri(uri)
- .description(description)
- .length(length)
- .published_date(pub_date)
- .epoch(epoch)
- .guid(guid)
- .podcast_id(parent_id)
- .build(),
- )
+ Ok(NewEpisodeBuilder::default()
+ .title(title)
+ .uri(uri)
+ .description(description)
+ .length(length)
+ .published_date(pub_date)
+ .epoch(epoch)
+ .guid(guid)
+ .podcast_id(parent_id)
+ .build()
+ .unwrap())
}
@@ -274,10 +275,10 @@ mod tests {
let channel = Channel::read_from(BufReader::new(file)).unwrap();
let firstitem = channel.items().first().unwrap();
- let descr =
- "Audit your network with a couple of easy commands on Kali Linux. Chris decides to \
- blow off a little steam by attacking his IoT devices, Wes has the scope on Equifax \
- blaming open source & the Beard just saved the show. It’s a really packed episode!";
+ let descr = "Audit your network with a couple of easy commands on Kali Linux. Chris \
+ decides to blow off a little steam by attacking his IoT devices, Wes has the \
+ scope on Equifax blaming open source & the Beard just saved the show. \
+ It’s a really packed episode!";
let i = new_episode(&firstitem, 0).unwrap();
assert_eq!(i.title(), Some("Hacking Devices with Kali Linux | LUP 214"));
@@ -299,7 +300,7 @@ mod tests {
decisions for the next version of Gnome have us worried about the \
future.
\n\nPlus we chat with Wimpy about the Ubuntu Rally in NYC, \
Microsoft’s sneaky move to turn Windows 10 into the “ULTIMATE LINUX \
- RUNTIME”, community news & more!
";
+ RUNTIME”, community news & more!";
assert_eq!(i2.title(), Some("Gnome Does it Again | LUP 213"));
assert_eq!(
i2.uri(),
@@ -318,9 +319,8 @@ mod tests {
let channel = Channel::read_from(BufReader::new(file)).unwrap();
let firstitem = channel.items().iter().nth(9).unwrap();
- let descr = "This week we look at RFC 2094 \
- \"Non-lexical lifetimes\"";
+ let descr = "This week we look at RFC 2094 \"Non-lexical lifetimes\"";
let i = new_episode(&firstitem, 0).unwrap();
assert_eq!(i.title(), Some("Episode #9 - A Once in a Lifetime RFC"));
@@ -342,8 +342,9 @@ mod tests {
let i2 = new_episode(&second, 0).unwrap();
let descr2 = "This week we look at RFC 2071 \"Add \
- impl Trait type alias and variable declarations\"";
+ href=\"https://github.com/rust-lang/rfcs/pull/2071\" rel=\"noopener \
+ noreferrer\">RFC 2071 \"Add impl Trait type alias and variable \
+ declarations\"";
assert_eq!(i2.title(), Some("Episode #8 - An Existential Crisis"));
assert_eq!(
i2.uri(),
diff --git a/hammond-data/src/utils.rs b/hammond-data/src/utils.rs
index a29ad6b..d297102 100644
--- a/hammond-data/src/utils.rs
+++ b/hammond-data/src/utils.rs
@@ -105,6 +105,16 @@ pub fn url_cleaner(s: &str) -> String {
}
}
+/// Placeholder
+// TODO: Docs
+pub fn replace_extra_spaces(s: &str) -> String {
+ s.lines()
+ .map(|x| x.split_whitespace().collect::>().join(" "))
+ .filter(|x| !x.is_empty())
+ .collect::>()
+ .join("\n")
+}
+
#[cfg(test)]
mod tests {
extern crate tempdir;
@@ -129,20 +139,29 @@ mod tests {
// Setup episodes
let db = connection();
let con = db.get().unwrap();
- NewEpisodeBuilder::new()
+ NewEpisodeBuilder::default()
.uri("foo_bar".to_string())
- .local_uri(Some(valid_path.to_str().unwrap().to_owned()))
.build()
+ .unwrap()
.into_episode(&con)
.unwrap();
- NewEpisodeBuilder::new()
+ NewEpisodeBuilder::default()
.uri("bar_baz".to_string())
- .local_uri(Some(bad_path.to_str().unwrap().to_owned()))
.build()
+ .unwrap()
.into_episode(&con)
.unwrap();
+ let mut ep1 = dbqueries::get_episode_from_uri(&con, "foo_bar").unwrap();
+ let mut ep2 = dbqueries::get_episode_from_uri(&con, "bar_baz").unwrap();
+ ep1.set_local_uri(Some(valid_path.to_str().unwrap()));
+ ep2.set_local_uri(Some(bad_path.to_str().unwrap()));
+
+ drop(con);
+ ep1.save().unwrap();
+ ep2.save().unwrap();
+
tmp_dir
}
@@ -232,4 +251,22 @@ mod tests {
assert_eq!(url_cleaner(good_url), good_url);
assert_eq!(url_cleaner(&format!(" {}\t\n", bad_url)), good_url);
}
+
+ #[test]
+ fn test_whitespace() {
+ let bad_txt = "1 2 3 4 5";
+ let valid_txt = "1 2 3 4 5";
+
+ assert_eq!(replace_extra_spaces(&bad_txt), valid_txt);
+
+ let bad_txt = "1 2 3 \n 4 5\n";
+ let valid_txt = "1 2 3\n4 5";
+
+ assert_eq!(replace_extra_spaces(&bad_txt), valid_txt);
+
+ let bad_txt = "1 2 3 \n\n\n \n 4 5\n";
+ let valid_txt = "1 2 3\n4 5";
+
+ assert_eq!(replace_extra_spaces(&bad_txt), valid_txt);
+ }
}
diff --git a/hammond-downloader/Cargo.toml b/hammond-downloader/Cargo.toml
index 7d19efc..f063adc 100644
--- a/hammond-downloader/Cargo.toml
+++ b/hammond-downloader/Cargo.toml
@@ -8,13 +8,13 @@ workspace = "../"
error-chain = "0.11.0"
hyper = "0.11.7"
log = "0.3.8"
-mime_guess = "1.8.2"
+mime_guess = "1.8.3"
reqwest = "0.8.1"
tempdir = "0.3.5"
[dependencies.diesel]
features = ["sqlite"]
-git = "https://github.com/diesel-rs/diesel.git"
+version = "0.99"
[dependencies.hammond-data]
path = "../hammond-data"
diff --git a/hammond-downloader/src/downloader.rs b/hammond-downloader/src/downloader.rs
index 64df7de..f3b695a 100644
--- a/hammond-downloader/src/downloader.rs
+++ b/hammond-downloader/src/downloader.rs
@@ -38,24 +38,7 @@ fn download_into(dir: &str, file_title: &str, url: &str) -> Result {
ct_len.map(|x| info!("File Lenght: {}", x));
ct_type.map(|x| info!("Content Type: {}", x));
- // This could be prettier.
- // Determine the file extension from the http content-type header.
- let ext = if let Some(t) = ct_type {
- let mime = mime_guess::get_extensions(t.type_().as_ref(), t.subtype().as_ref());
- if let Some(m) = mime {
- if m.contains(&t.subtype().as_ref()) {
- t.subtype().as_ref().to_string()
- } else {
- m.first().unwrap().to_string()
- }
- } else {
- error!("Unkown mime type. {}", t);
- "unkown".to_string()
- }
- } else {
- error!("Unkown mime type.");
- "unkown".to_string()
- };
+ let ext = get_ext(ct_type.cloned()).unwrap_or(String::from("unkown"));
info!("Extension: {}", ext);
// Construct a temp file to save desired content.
@@ -74,6 +57,20 @@ fn download_into(dir: &str, file_title: &str, url: &str) -> Result {
Ok(target)
}
+// Determine the file extension from the http content-type header.
+fn get_ext(content: Option) -> Option {
+ let cont = content.clone()?;
+ content
+ .and_then(|c| mime_guess::get_extensions(c.type_().as_ref(), c.subtype().as_ref()))
+ .and_then(|c| {
+ if c.contains(&cont.subtype().as_ref()) {
+ Some(cont.subtype().as_ref().to_string())
+ } else {
+ Some(c.first().unwrap().to_string())
+ }
+ })
+}
+
// TODO: Write unit-tests.
/// Handles the I/O of fetching a remote file and saving into a Buffer and A File.
fn save_io(file: &str, resp: &mut reqwest::Response, content_lenght: Option) -> Result<()> {
@@ -185,7 +182,7 @@ mod tests {
use hammond_data::Source;
use hammond_data::feed::index;
use hammond_data::dbqueries;
- use diesel::Identifiable;
+ use diesel::associations::Identifiable;
use std::fs;
diff --git a/hammond-gtk/Cargo.toml b/hammond-gtk/Cargo.toml
index 39b12fe..810cbbb 100644
--- a/hammond-gtk/Cargo.toml
+++ b/hammond-gtk/Cargo.toml
@@ -12,17 +12,14 @@ gdk-pixbuf = "0.3.0"
gio = "0.3.0"
glib = "0.4.0"
log = "0.3.8"
-loggerv = "0.5.1"
+loggerv = "0.6.0"
open = "1.2.1"
rayon = "0.9.0"
+regex = "0.2.3"
[dependencies.diesel]
features = ["sqlite"]
-git = "https://github.com/diesel-rs/diesel.git"
-
-[dependencies.diesel_codegen]
-features = ["sqlite"]
-git = "https://github.com/diesel-rs/diesel.git"
+version = "0.99.0"
[dependencies.gtk]
features = ["v3_22"]
diff --git a/hammond-gtk/resources/gtk/headerbar.ui b/hammond-gtk/resources/gtk/headerbar.ui
index e84409d..d28c2ae 100644
--- a/hammond-gtk/resources/gtk/headerbar.ui
+++ b/hammond-gtk/resources/gtk/headerbar.ui
@@ -3,7 +3,6 @@
- True
False
Add a new feed
center
diff --git a/hammond-gtk/resources/gtk/podcast_widget.ui b/hammond-gtk/resources/gtk/podcast_widget.ui
index f8e9b44..0241f05 100644
--- a/hammond-gtk/resources/gtk/podcast_widget.ui
+++ b/hammond-gtk/resources/gtk/podcast_widget.ui
@@ -109,7 +109,6 @@ Warn: This will delete downloaded content associated with this Podcast.
- True
True
True
Mark all episodes as Played.
diff --git a/hammond-gtk/resources/gtk/podcasts_view.ui b/hammond-gtk/resources/gtk/podcasts_view.ui
index 4cdc447..5a3dff6 100644
--- a/hammond-gtk/resources/gtk/podcasts_view.ui
+++ b/hammond-gtk/resources/gtk/podcasts_view.ui
@@ -12,7 +12,7 @@
True
in
-
+
True
False
diff --git a/hammond-gtk/src/content.rs b/hammond-gtk/src/content.rs
new file mode 100644
index 0000000..249f589
--- /dev/null
+++ b/hammond-gtk/src/content.rs
@@ -0,0 +1,269 @@
+use gtk;
+use gtk::prelude::*;
+
+use hammond_data::Podcast;
+use hammond_data::dbqueries;
+
+use widgets::podcast::PodcastWidget;
+use views::podcasts::PopulatedView;
+use views::empty::EmptyView;
+
+#[derive(Debug)]
+pub struct Content {
+ pub stack: gtk::Stack,
+ pub widget: PodcastWidget,
+ pub podcasts: PopulatedView,
+ pub empty: EmptyView,
+}
+
+impl Content {
+ pub fn new() -> Content {
+ let stack = gtk::Stack::new();
+
+ let widget = PodcastWidget::new();
+ let podcasts = PopulatedView::new();
+ let empty = EmptyView::new();
+
+ stack.add_named(&widget.container, "widget");
+ stack.add_named(&podcasts.container, "podcasts");
+ stack.add_named(&empty.container, "empty");
+
+ Content {
+ stack,
+ widget,
+ empty,
+ podcasts,
+ }
+ }
+
+ pub fn new_initialized() -> Content {
+ let ct = Content::new();
+ ct.init();
+ ct
+ }
+
+ pub fn init(&self) {
+ self.podcasts.init(&self.stack);
+ if self.podcasts.flowbox.get_children().is_empty() {
+ self.stack.set_visible_child_name("empty");
+ return;
+ }
+
+ self.stack.set_visible_child_name("podcasts");
+ }
+
+ fn replace_widget(&mut self, pdw: PodcastWidget) {
+ let vis = self.stack.get_visible_child_name().unwrap();
+ let old = self.stack.get_child_by_name("widget").unwrap();
+ self.stack.remove(&old);
+
+ self.widget = pdw;
+ self.stack.add_named(&self.widget.container, "widget");
+ self.stack.set_visible_child_name(&vis);
+ old.destroy();
+ }
+
+ fn replace_podcasts(&mut self, pop: PopulatedView) {
+ let vis = self.stack.get_visible_child_name().unwrap();
+ let old = self.stack.get_child_by_name("podcasts").unwrap();
+ self.stack.remove(&old);
+
+ self.podcasts = pop;
+ self.stack.add_named(&self.podcasts.container, "podcasts");
+ self.stack.set_visible_child_name(&vis);
+ old.destroy();
+ }
+}
+
+#[derive(Debug)]
+// Experiementing with Wrapping gtk::Stack into a State machine.
+// Gonna revist it when TryInto trais is stabilized.
+pub struct ContentState {
+ content: Content,
+ state: S,
+}
+
+pub trait UpdateView {
+ fn update(&mut self);
+}
+
+#[derive(Debug)]
+pub struct Empty {}
+
+#[derive(Debug)]
+pub struct PodcastsView {}
+
+#[derive(Debug)]
+pub struct WidgetsView {}
+
+impl Into> for ContentState {
+ fn into(self) -> ContentState {
+ self.content.stack.set_visible_child_name("podcasts");
+
+ ContentState {
+ content: self.content,
+ state: PodcastsView {},
+ }
+ }
+}
+
+impl UpdateView for ContentState {
+ fn update(&mut self) {}
+}
+
+impl Into> for ContentState {
+ fn into(self) -> ContentState {
+ self.content.stack.set_visible_child_name("empty");
+ ContentState {
+ content: self.content,
+ state: Empty {},
+ }
+ }
+}
+
+impl Into> for ContentState {
+ fn into(self) -> ContentState {
+ self.content.stack.set_visible_child_name("widget");
+
+ ContentState {
+ content: self.content,
+ state: WidgetsView {},
+ }
+ }
+}
+
+impl UpdateView for ContentState {
+ fn update(&mut self) {
+ let pop = PopulatedView::new_initialized(&self.content.stack);
+ self.content.replace_podcasts(pop)
+ }
+}
+
+impl Into> for ContentState {
+ fn into(self) -> ContentState {
+ self.content.stack.set_visible_child_name("podcasts");
+ ContentState {
+ content: self.content,
+ state: PodcastsView {},
+ }
+ }
+}
+
+impl Into> for ContentState {
+ fn into(self) -> ContentState {
+ self.content.stack.set_visible_child_name("empty");
+ ContentState {
+ content: self.content,
+ state: Empty {},
+ }
+ }
+}
+
+impl UpdateView for ContentState {
+ fn update(&mut self) {
+ let old = self.content.stack.get_child_by_name("widget").unwrap();
+ let id = WidgetExt::get_name(&old).unwrap();
+ let pd = dbqueries::get_podcast_from_id(id.parse::().unwrap()).unwrap();
+
+ let pdw = PodcastWidget::new_initialized(&self.content.stack, &pd);
+ self.content.replace_widget(pdw);
+ }
+}
+
+impl ContentState {
+ #[allow(dead_code)]
+ pub fn new() -> Result, ContentState> {
+ let content = Content::new();
+
+ content.podcasts.init(&content.stack);
+ if content.podcasts.flowbox.get_children().is_empty() {
+ content.stack.set_visible_child_name("empty");
+ return Err(ContentState {
+ content,
+ state: Empty {},
+ });
+ }
+
+ content.stack.set_visible_child_name("podcasts");
+ Ok(ContentState {
+ content,
+ state: PodcastsView {},
+ })
+ }
+
+ #[allow(dead_code)]
+ pub fn get_stack(&self) -> gtk::Stack {
+ self.content.stack.clone()
+ }
+}
+
+fn replace_widget(stack: >k::Stack, pdw: &PodcastWidget) {
+ let old = stack.get_child_by_name("widget").unwrap();
+ stack.remove(&old);
+ stack.add_named(&pdw.container, "widget");
+ old.destroy();
+}
+
+fn replace_podcasts(stack: >k::Stack, pop: &PopulatedView) {
+ let old = stack.get_child_by_name("podcasts").unwrap();
+ stack.remove(&old);
+ stack.add_named(&pop.container, "podcasts");
+ old.destroy();
+}
+
+#[allow(dead_code)]
+pub fn show_widget(stack: >k::Stack) {
+ stack.set_visible_child_name("widget")
+}
+
+pub fn show_podcasts(stack: >k::Stack) {
+ stack.set_visible_child_name("podcasts")
+}
+
+pub fn show_empty(stack: >k::Stack) {
+ stack.set_visible_child_name("empty")
+}
+
+pub fn update_podcasts(stack: >k::Stack) {
+ let pods = PopulatedView::new_initialized(stack);
+
+ if pods.flowbox.get_children().is_empty() {
+ show_empty(stack)
+ }
+
+ replace_podcasts(stack, &pods);
+}
+
+pub fn update_widget(stack: >k::Stack, pd: &Podcast) {
+ let pdw = PodcastWidget::new_initialized(stack, pd);
+ replace_widget(stack, &pdw);
+}
+
+pub fn update_podcasts_preserve_vis(stack: >k::Stack) {
+ let vis = stack.get_visible_child_name().unwrap();
+ update_podcasts(stack);
+ if vis != "empty" {
+ stack.set_visible_child_name(&vis)
+ }
+}
+
+pub fn update_widget_preserve_vis(stack: >k::Stack, pd: &Podcast) {
+ let vis = stack.get_visible_child_name().unwrap();
+ update_widget(stack, pd);
+ stack.set_visible_child_name(&vis)
+}
+
+pub fn on_podcasts_child_activate(stack: >k::Stack, pd: &Podcast) {
+ update_widget(stack, pd);
+ stack.set_visible_child_full("widget", gtk::StackTransitionType::SlideLeft);
+}
+
+pub fn on_home_button_activate(stack: >k::Stack) {
+ let vis = stack.get_visible_child_name().unwrap();
+
+ if vis != "widget" {
+ update_podcasts(stack);
+ }
+
+ show_podcasts(stack);
+}
diff --git a/hammond-gtk/src/headerbar.rs b/hammond-gtk/src/headerbar.rs
index ac6c736..20f491e 100644
--- a/hammond-gtk/src/headerbar.rs
+++ b/hammond-gtk/src/headerbar.rs
@@ -4,57 +4,77 @@ use gtk::prelude::*;
use hammond_data::Source;
use hammond_data::utils::url_cleaner;
-use podcasts_view::update_podcasts_view;
use utils;
+use content;
-pub fn get_headerbar(stack: >k::Stack) -> gtk::HeaderBar {
- let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/headerbar.ui");
-
- let header: gtk::HeaderBar = builder.get_object("headerbar1").unwrap();
- let home_button: gtk::Button = builder.get_object("homebutton").unwrap();
- let refresh_button: gtk::Button = builder.get_object("refbutton").unwrap();
-
- let add_toggle_button: gtk::MenuButton = builder.get_object("add-toggle-button").unwrap();
- let add_popover: gtk::Popover = builder.get_object("add-popover").unwrap();
- let new_url: gtk::Entry = builder.get_object("new-url").unwrap();
- let add_button: gtk::Button = builder.get_object("add-button").unwrap();
- // TODO: check if url exists in the db and lock the button
- new_url.connect_changed(move |url| {
- println!("{:?}", url.get_text());
- });
-
- add_button.connect_clicked(clone!(stack, add_popover => move |_| {
- let url = new_url.get_text().unwrap_or_default();
- let url = url_cleaner(&url);
- on_add_bttn_clicked(&stack, &url);
-
- // TODO: lock the button instead of hiding and add notification of feed added.
- // TODO: map the spinner
- add_popover.hide();
- }));
- add_popover.hide();
- add_toggle_button.set_popover(&add_popover);
-
- // TODO: make it a back arrow button, that will hide when appropriate,
- // and add a StackSwitcher when more views are added.
- home_button.connect_clicked(clone!(stack => move |_| {
- let vis = stack.get_visible_child_name().unwrap();
- stack.set_visible_child_name("fb_parent");
- if vis != "pdw" {
- update_podcasts_view(&stack);
- }
- }));
-
- // FIXME: There appears to be a memmory leak here.
- refresh_button.connect_clicked(clone!(stack => move |_| {
- utils::refresh_feed(&stack, None, None);
- }));
-
- header
+#[derive(Debug)]
+pub struct Header {
+ pub container: gtk::HeaderBar,
+ home: gtk::Button,
+ refresh: gtk::Button,
+ add_toggle: gtk::MenuButton,
}
-fn on_add_bttn_clicked(stack: >k::Stack, url: &str) {
- let source = Source::from_url(url);
+impl Header {
+ pub fn new() -> Header {
+ let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/headerbar.ui");
+
+ let header: gtk::HeaderBar = builder.get_object("headerbar1").unwrap();
+ let home: gtk::Button = builder.get_object("homebutton").unwrap();
+ let refresh: gtk::Button = builder.get_object("refbutton").unwrap();
+ let add_toggle: gtk::MenuButton = builder.get_object("add-toggle-button").unwrap();
+
+ Header {
+ container: header,
+ home,
+ refresh,
+ add_toggle,
+ }
+ }
+
+ pub fn new_initialized(stack: >k::Stack) -> Header {
+ let header = Header::new();
+ header.init(stack);
+ header
+ }
+
+ fn init(&self, stack: >k::Stack) {
+ let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/headerbar.ui");
+
+ let add_popover: gtk::Popover = builder.get_object("add-popover").unwrap();
+ let new_url: gtk::Entry = builder.get_object("new-url").unwrap();
+ let add_button: gtk::Button = builder.get_object("add-button").unwrap();
+
+ new_url.connect_changed(move |url| {
+ println!("{:?}", url.get_text());
+ });
+
+ add_button.connect_clicked(clone!(stack, add_popover, new_url => move |_| {
+ on_add_bttn_clicked(&stack, &new_url);
+
+ // TODO: lock the button instead of hiding and add notification of feed added.
+ // TODO: map the spinner
+ add_popover.hide();
+ }));
+ self.add_toggle.set_popover(&add_popover);
+
+ // TODO: make it a back arrow button, that will hide when appropriate,
+ // and add a StackSwitcher when more views are added.
+ self.home.connect_clicked(clone!(stack => move |_| {
+ content::on_home_button_activate(&stack);
+ }));
+
+ // FIXME: There appears to be a memmory leak here.
+ self.refresh.connect_clicked(clone!(stack => move |_| {
+ utils::refresh_feed(&stack, None, None);
+ }));
+ }
+}
+
+fn on_add_bttn_clicked(stack: >k::Stack, entry: >k::Entry) {
+ let url = entry.get_text().unwrap_or_default();
+ let url = url_cleaner(&url);
+ let source = Source::from_url(&url);
if let Ok(s) = source {
info!("{:?} feed added", url);
diff --git a/hammond-gtk/src/main.rs b/hammond-gtk/src/main.rs
index 5f65291..f4fd89b 100644
--- a/hammond-gtk/src/main.rs
+++ b/hammond-gtk/src/main.rs
@@ -12,6 +12,7 @@ extern crate hammond_downloader;
extern crate log;
extern crate loggerv;
extern crate open;
+extern crate regex;
// extern crate rayon;
// use rayon::prelude::*;
@@ -43,12 +44,11 @@ macro_rules! clone {
mod views;
mod widgets;
mod headerbar;
+mod content;
mod utils;
mod static_resource;
-use views::podcasts_view;
-
/*
THIS IS STILL A PROTOTYPE.
*/
@@ -62,8 +62,13 @@ fn build_ui(app: >k::Application) {
// Get the main window
let window = gtk::ApplicationWindow::new(app);
window.set_default_size(1150, 650);
- // Setup the Stack that will manage the switch between podcasts_view and podcast_widget.
- let stack = podcasts_view::setup_stack();
+
+ // TODO: this will blow horribly
+ // let ct = content::ContentState::new().unwrap();
+ // let stack = ct.get_stack();
+
+ let ct = content::Content::new_initialized();
+ let stack = ct.stack;
window.add(&stack);
window.connect_delete_event(|w, _| {
@@ -98,8 +103,8 @@ fn build_ui(app: >k::Application) {
});
// Get the headerbar
- let header = headerbar::get_headerbar(&stack);
- window.set_titlebar(&header);
+ let header = headerbar::Header::new_initialized(&stack);
+ window.set_titlebar(&header.container);
window.show_all();
window.activate();
diff --git a/hammond-gtk/src/utils.rs b/hammond-gtk/src/utils.rs
index 69bd584..5402b90 100644
--- a/hammond-gtk/src/utils.rs
+++ b/hammond-gtk/src/utils.rs
@@ -1,14 +1,18 @@
use glib;
use gtk;
+use gdk_pixbuf::Pixbuf;
use hammond_data::feed;
-use hammond_data::Source;
+use hammond_data::{Podcast, Source};
+use hammond_downloader::downloader;
use std::{thread, time};
use std::cell::RefCell;
use std::sync::mpsc::{channel, Receiver};
+use std::borrow::Cow;
-use views::podcasts_view;
+use content;
+use regex::Regex;
type Foo = RefCell)>>;
@@ -55,9 +59,54 @@ fn refresh_podcasts_view() -> glib::Continue {
GLOBAL.with(|global| {
if let Some((ref stack, ref reciever)) = *global.borrow() {
if reciever.try_recv().is_ok() {
- podcasts_view::update_podcasts_view(stack);
+ content::update_podcasts_preserve_vis(stack);
}
}
});
glib::Continue(false)
}
+
+pub fn get_pixbuf_from_path(pd: &Podcast) -> Option {
+ let img_path = downloader::cache_image(pd)?;
+ Pixbuf::new_from_file_at_scale(&img_path, 256, 256, true).ok()
+}
+
+#[allow(dead_code)]
+// WIP: parse html to markup
+pub fn html_to_markup(s: &mut str) -> Cow {
+ s.trim();
+ s.replace('&', "&");
+ s.replace('<', "<");
+ s.replace('>', ">");
+
+ let re = Regex::new("(?Phttps?://[^\\s&,)(\"]+(&\\w=[\\w._-]?)*(#[\\w._-]+)?)").unwrap();
+ re.replace_all(s, "$url ")
+}
+
+#[cfg(test)]
+mod tests {
+ use hammond_data::Source;
+ use hammond_data::feed::index;
+ use hammond_data::dbqueries;
+ use diesel::associations::Identifiable;
+ use super::*;
+
+ #[test]
+ fn test_get_pixbuf_from_path() {
+ let url = "http://www.newrustacean.com/feed.xml";
+
+ // Create and index a source
+ let source = Source::from_url(url).unwrap();
+ // Copy it's id
+ let sid = source.id().clone();
+
+ // Convert Source it into a Feed and index it
+ let feed = source.into_feed().unwrap();
+ index(vec![feed]);
+
+ // Get the Podcast
+ let pd = dbqueries::get_podcast_from_source_id(sid).unwrap();
+ let pxbuf = get_pixbuf_from_path(&pd);
+ assert!(pxbuf.is_some());
+ }
+}
diff --git a/hammond-gtk/src/views/empty.rs b/hammond-gtk/src/views/empty.rs
new file mode 100644
index 0000000..1c93da7
--- /dev/null
+++ b/hammond-gtk/src/views/empty.rs
@@ -0,0 +1,15 @@
+use gtk;
+
+#[derive(Debug, Clone)]
+pub struct EmptyView {
+ pub container: gtk::Box,
+}
+
+impl EmptyView {
+ pub fn new() -> EmptyView {
+ let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/empty_view.ui");
+ let view: gtk::Box = builder.get_object("empty_view").unwrap();
+
+ EmptyView { container: view }
+ }
+}
diff --git a/hammond-gtk/src/views/mod.rs b/hammond-gtk/src/views/mod.rs
index 69e01ee..9c47e7d 100644
--- a/hammond-gtk/src/views/mod.rs
+++ b/hammond-gtk/src/views/mod.rs
@@ -1 +1,2 @@
-pub mod podcasts_view;
+pub mod podcasts;
+pub mod empty;
diff --git a/hammond-gtk/src/views/podcasts.rs b/hammond-gtk/src/views/podcasts.rs
new file mode 100644
index 0000000..711be87
--- /dev/null
+++ b/hammond-gtk/src/views/podcasts.rs
@@ -0,0 +1,144 @@
+use gtk;
+use gtk::prelude::*;
+use gdk_pixbuf::Pixbuf;
+use diesel::associations::Identifiable;
+
+use hammond_data::dbqueries;
+use hammond_data::Podcast;
+
+use utils::get_pixbuf_from_path;
+
+use content;
+
+#[derive(Debug, Clone)]
+pub struct PopulatedView {
+ pub container: gtk::Box,
+ pub flowbox: gtk::FlowBox,
+ viewport: gtk::Viewport,
+}
+
+#[derive(Debug)]
+struct PodcastChild {
+ container: gtk::Box,
+ title: gtk::Label,
+ cover: gtk::Image,
+ banner: gtk::Image,
+ number: gtk::Label,
+ child: gtk::FlowBoxChild,
+}
+
+impl PopulatedView {
+ pub fn new() -> PopulatedView {
+ let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/podcasts_view.ui");
+ let container: gtk::Box = builder.get_object("fb_parent").unwrap();
+ let flowbox: gtk::FlowBox = builder.get_object("flowbox").unwrap();
+ let viewport: gtk::Viewport = builder.get_object("viewport").unwrap();
+
+ PopulatedView {
+ container,
+ flowbox,
+ viewport,
+ }
+ }
+
+ #[allow(dead_code)]
+ pub fn new_initialized(stack: >k::Stack) -> PopulatedView {
+ let pop = PopulatedView::new();
+ pop.init(stack);
+ pop
+ }
+
+ pub fn init(&self, stack: >k::Stack) {
+ use gtk::WidgetExt;
+
+ // TODO: handle unwraps.
+ self.flowbox
+ .connect_child_activated(clone!(stack => move |_, child| {
+ // This is such an ugly hack...
+ // let id = child.get_name().unwrap().parse::().unwrap();
+ let id = WidgetExt::get_name(child).unwrap().parse::().unwrap();
+ let parent = dbqueries::get_podcast_from_id(id).unwrap();
+ on_flowbox_child_activate(&stack, &parent);
+ }));
+ // Populate the flowbox with the Podcasts.
+ self.populate_flowbox();
+ }
+
+ fn populate_flowbox(&self) {
+ let podcasts = dbqueries::get_podcasts();
+
+ if let Ok(pds) = podcasts {
+ pds.iter().for_each(|parent| {
+ let flowbox_child = PodcastChild::new_initialized(parent);
+ self.flowbox.add(&flowbox_child.child);
+ });
+ self.flowbox.show_all();
+ }
+ }
+}
+
+impl PodcastChild {
+ fn new() -> PodcastChild {
+ let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/podcasts_child.ui");
+
+ // Copy of gnome-music AlbumWidget
+ let container: gtk::Box = builder.get_object("fb_child").unwrap();
+ let title: gtk::Label = builder.get_object("pd_title").unwrap();
+ let cover: gtk::Image = builder.get_object("pd_cover").unwrap();
+ let banner: gtk::Image = builder.get_object("banner").unwrap();
+ let number: gtk::Label = builder.get_object("banner_label").unwrap();
+
+ let child = gtk::FlowBoxChild::new();
+ child.add(&container);
+
+ PodcastChild {
+ container,
+ title,
+ cover,
+ banner,
+ number,
+ child,
+ }
+ }
+
+ fn init(&self, pd: &Podcast) {
+ self.title.set_text(pd.title());
+
+ let cover = get_pixbuf_from_path(pd);
+ if let Some(img) = cover {
+ self.cover.set_from_pixbuf(&img);
+ };
+
+ WidgetExt::set_name(&self.child, &pd.id().to_string());
+ self.configure_banner(pd);
+ }
+
+ pub fn new_initialized(pd: &Podcast) -> PodcastChild {
+ let child = PodcastChild::new();
+ child.init(pd);
+
+ child
+ }
+
+ fn configure_banner(&self, pd: &Podcast) {
+ let bann =
+ Pixbuf::new_from_resource_at_scale("/org/gnome/hammond/banner.png", 256, 256, true);
+ if let Ok(b) = bann {
+ self.banner.set_from_pixbuf(&b);
+
+ let new_episodes = dbqueries::get_pd_unplayed_episodes(pd);
+
+ if let Ok(n) = new_episodes {
+ if !n.is_empty() {
+ self.number.set_text(&n.len().to_string());
+ self.banner.show();
+ self.number.show();
+ }
+ }
+ }
+ }
+}
+
+fn on_flowbox_child_activate(stack: >k::Stack, parent: &Podcast) {
+ content::on_podcasts_child_activate(stack, parent)
+}
diff --git a/hammond-gtk/src/views/podcasts_view.rs b/hammond-gtk/src/views/podcasts_view.rs
deleted file mode 100644
index 44de32e..0000000
--- a/hammond-gtk/src/views/podcasts_view.rs
+++ /dev/null
@@ -1,152 +0,0 @@
-use gtk;
-use gtk::prelude::*;
-use gdk_pixbuf::Pixbuf;
-use diesel::associations::Identifiable;
-
-use hammond_data::dbqueries;
-use hammond_data::Podcast;
-
-use widgets::podcast::*;
-
-fn setup_empty_view(stack: >k::Stack) {
- let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/empty_view.ui");
- let view: gtk::Box = builder.get_object("empty_view").unwrap();
- stack.add_named(&view, "empty");
-}
-
-fn show_empty_view(stack: >k::Stack) {
- stack.set_visible_child_name("empty");
-
- info!("Empty view.");
-}
-
-fn populate_flowbox(flowbox: >k::FlowBox) {
- let podcasts = dbqueries::get_podcasts();
-
- if let Ok(pds) = podcasts {
- pds.iter().for_each(|parent| {
- let f = create_flowbox_child(parent);
- flowbox.add(&f);
- });
- flowbox.show_all();
- }
-}
-
-fn create_flowbox_child(pd: &Podcast) -> gtk::FlowBoxChild {
- let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/podcasts_child.ui");
-
- // Copy of gnome-music AlbumWidget
- let box_: gtk::Box = builder.get_object("fb_child").unwrap();
- let pd_title: gtk::Label = builder.get_object("pd_title").unwrap();
- let pd_cover: gtk::Image = builder.get_object("pd_cover").unwrap();
- let banner: gtk::Image = builder.get_object("banner").unwrap();
- let banner_title: gtk::Label = builder.get_object("banner_label").unwrap();
-
- pd_title.set_text(pd.title());
-
- let cover = get_pixbuf_from_path(pd);
- if let Some(img) = cover {
- pd_cover.set_from_pixbuf(&img);
- };
-
- configure_banner(pd, &banner, &banner_title);
-
- let fbc = gtk::FlowBoxChild::new();
- // There's probably a better way to store the id somewhere.
- // fbc.set_name(&pd.id().to_string());
- WidgetExt::set_name(&fbc, &pd.id().to_string());
- fbc.add(&box_);
- fbc
-}
-
-fn configure_banner(pd: &Podcast, banner: >k::Image, banner_title: >k::Label) {
- let bann = Pixbuf::new_from_resource_at_scale("/org/gnome/hammond/banner.png", 256, 256, true);
- if let Ok(b) = bann {
- banner.set_from_pixbuf(&b);
-
- let new_episodes = dbqueries::get_pd_unplayed_episodes(pd);
-
- if let Ok(n) = new_episodes {
- if !n.is_empty() {
- banner_title.set_text(&n.len().to_string());
- banner.show();
- banner_title.show();
- }
- }
- }
-}
-
-fn on_flowbox_child_activate(stack: >k::Stack, parent: &Podcast) {
- let old = stack.get_child_by_name("pdw").unwrap();
- let pdw = podcast_widget(stack, parent);
-
- stack.remove(&old);
- stack.add_named(&pdw, "pdw");
- stack.set_visible_child(&pdw);
-
- // aggresive memory cleanup
- // probably not needed
- old.destroy();
-}
-
-fn setup_podcasts_flowbox(stack: >k::Stack) -> gtk::FlowBox {
- let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/podcasts_view.ui");
- let fb_parent: gtk::Box = builder.get_object("fb_parent").unwrap();
- let flowbox: gtk::FlowBox = builder.get_object("flowbox").unwrap();
- init_flowbox(stack, &flowbox);
-
- stack.add_named(&fb_parent, "fb_parent");
-
- if flowbox.get_children().is_empty() {
- show_empty_view(stack);
- } else {
- stack.set_visible_child(&fb_parent);
- };
-
- flowbox
-}
-
-pub fn setup_stack() -> gtk::Stack {
- let stack = gtk::Stack::new();
- stack.set_transition_type(gtk::StackTransitionType::SlideLeftRight);
- setup_empty_view(&stack);
- setup_podcast_widget(&stack);
- setup_podcasts_flowbox(&stack);
- stack
-}
-
-pub fn update_podcasts_view(stack: >k::Stack) {
- let vis = stack.get_visible_child_name().unwrap();
- let old = stack.get_child_by_name("fb_parent").unwrap();
- stack.remove(&old);
-
- let flowbox = setup_podcasts_flowbox(stack);
-
- if vis == "empty" && !flowbox.get_children().is_empty() {
- stack.set_visible_child_name("fb_parent");
- } else if vis == "fb_parent" && flowbox.get_children().is_empty() {
- stack.set_visible_child_name("empty");
- } else {
- // preserve the visible widget
- stack.set_visible_child_name(&vis);
- };
-
- // aggresive memory cleanup
- // probably not needed
- old.destroy();
-}
-
-fn init_flowbox(stack: >k::Stack, flowbox: >k::FlowBox) {
- use gtk::WidgetExt;
-
- // TODO: handle unwraps.
- flowbox.connect_child_activated(clone!(stack => move |_, child| {
- // This is such an ugly hack...
- // let id = child.get_name().unwrap().parse::().unwrap();
- let id = WidgetExt::get_name(child).unwrap().parse::().unwrap();
- let parent = dbqueries::get_podcast_from_id(id).unwrap();
- on_flowbox_child_activate(&stack, &parent);
- }));
- // Populate the flowbox with the Podcasts.
- populate_flowbox(flowbox);
-}
diff --git a/hammond-gtk/src/widgets/episode.rs b/hammond-gtk/src/widgets/episode.rs
index 4851a03..c113b51 100644
--- a/hammond-gtk/src/widgets/episode.rs
+++ b/hammond-gtk/src/widgets/episode.rs
@@ -1,115 +1,170 @@
+use glib;
+use gtk;
+use gtk::prelude::*;
+use gtk::{ContainerExt, TextBufferExt};
+
use open;
+use dissolve::strip_html_tags;
+use diesel::associations::Identifiable;
+
use hammond_data::dbqueries;
use hammond_data::{Episode, Podcast};
use hammond_downloader::downloader;
use hammond_data::utils::*;
use hammond_data::errors::*;
+use hammond_data::utils::replace_extra_spaces;
-use dissolve::strip_html_tags;
-use diesel::associations::Identifiable;
+// use utils::html_to_markup;
use std::thread;
use std::cell::RefCell;
use std::sync::mpsc::{channel, Receiver};
use std::path::Path;
-use glib;
-use gtk;
-use gtk::prelude::*;
-use gtk::{ContainerExt, TextBufferExt};
-
type Foo = RefCell)>>;
thread_local!(static GLOBAL: Foo = RefCell::new(None));
-fn epidose_widget(episode: &mut Episode, pd_title: &str) -> gtk::Box {
- // This is just a prototype and will be reworked probably.
- let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/episode_widget.ui");
+#[derive(Debug)]
+struct EpisodeWidget {
+ container: gtk::Box,
+ download: gtk::Button,
+ play: gtk::Button,
+ delete: gtk::Button,
+ played: gtk::Button,
+ unplayed: gtk::Button,
+ title: gtk::Label,
+ description: gtk::TextView,
+ // description: gtk::Label,
+ expander: gtk::Expander,
+}
- let ep: gtk::Box = builder.get_object("episode_box").unwrap();
- let download_button: gtk::Button = builder.get_object("download_button").unwrap();
- let play_button: gtk::Button = builder.get_object("play_button").unwrap();
- let delete_button: gtk::Button = builder.get_object("delete_button").unwrap();
- let played_button: gtk::Button = builder.get_object("mark_played_button").unwrap();
- let unplayed_button: gtk::Button = builder.get_object("mark_unplayed_button").unwrap();
+impl EpisodeWidget {
+ fn new() -> EpisodeWidget {
+ // This is just a prototype and will be reworked probably.
+ let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/episode_widget.ui");
- let title_label: gtk::Label = builder.get_object("title_label").unwrap();
- // let desc_label: gtk::Label = builder.get_object("desc_label").unwrap();
- let expander: gtk::Expander = builder.get_object("expand_desc").unwrap();
- let desc_text_view: gtk::TextView = builder.get_object("desc_text_view").unwrap();
+ let container: gtk::Box = builder.get_object("episode_box").unwrap();
+ let download: gtk::Button = builder.get_object("download_button").unwrap();
+ let play: gtk::Button = builder.get_object("play_button").unwrap();
+ let delete: gtk::Button = builder.get_object("delete_button").unwrap();
+ let played: gtk::Button = builder.get_object("mark_played_button").unwrap();
+ let unplayed: gtk::Button = builder.get_object("mark_unplayed_button").unwrap();
- title_label.set_xalign(0.0);
+ let title: gtk::Label = builder.get_object("title_label").unwrap();
+ let expander: gtk::Expander = builder.get_object("expand_desc").unwrap();
+ let description: gtk::TextView = builder.get_object("desc_text_view").unwrap();
+ // let description: gtk::Label = builder.get_object("desc_text").unwrap();
- if let Some(t) = episode.title() {
- title_label.set_text(t);
+ EpisodeWidget {
+ container,
+ download,
+ play,
+ delete,
+ played,
+ unplayed,
+ title,
+ expander,
+ description,
+ }
}
- if episode.description().is_some() {
- let d = episode.description().unwrap().to_owned();
-
- expander.connect_activate(move |_| {
- let plain_text = strip_html_tags(&d).join(" ");
- // TODO: handle unwrap
- let buff = desc_text_view.get_buffer().unwrap();
- buff.set_text(plain_text.trim());
- });
+ pub fn new_initialized(episode: &mut Episode, pd: &Podcast) -> EpisodeWidget {
+ let widget = EpisodeWidget::new();
+ widget.init(episode, pd);
+ widget
}
- if episode.played().is_some() {
- unplayed_button.show();
- played_button.hide();
+ fn init(&self, episode: &mut Episode, pd: &Podcast) {
+ self.title.set_xalign(0.0);
+
+ if let Some(t) = episode.title() {
+ self.title.set_text(t);
+ }
+
+ if episode.description().is_some() {
+ let text = episode.description().unwrap().to_owned();
+ let description = &self.description;
+ self.expander
+ .connect_activate(clone!(description, text => move |_| {
+ // let mut text = text.clone();
+ // html_to_markup(&mut text);
+ // description.set_markup(&text)
+
+ let plain_text = strip_html_tags(&text).join(" ");
+ // TODO: handle unwrap
+ let buff = description.get_buffer().unwrap();
+ buff.set_text(&replace_extra_spaces(&plain_text));
+ }));
+ }
+
+ if episode.played().is_some() {
+ self.unplayed.show();
+ self.played.hide();
+ }
+
+ // Show or hide the play/delete/download buttons upon widget initialization.
+ let local_uri = episode.local_uri();
+ if local_uri.is_some() && Path::new(local_uri.unwrap()).exists() {
+ self.download.hide();
+ self.play.show();
+ self.delete.show();
+ }
+
+ let played = &self.played;
+ let unplayed = &self.unplayed;
+ self.play
+ .connect_clicked(clone!(episode, played, unplayed => move |_| {
+ let mut episode = episode.clone();
+ on_play_bttn_clicked(*episode.id());
+ let _ = episode.set_played_now();
+ played.hide();
+ unplayed.show();
+ }));
+
+ let play = &self.play;
+ let download = &self.download;
+ self.delete
+ .connect_clicked(clone!(episode, play, download => move |del| {
+ on_delete_bttn_clicked(*episode.id());
+ del.hide();
+ play.hide();
+ download.show();
+ }));
+
+ let unplayed = &self.unplayed;
+ self.played
+ .connect_clicked(clone!(episode, unplayed => move |played| {
+ let mut episode = episode.clone();
+ let _ = episode.set_played_now();
+ played.hide();
+ unplayed.show();
+ }));
+
+ let played = &self.played;
+ self.unplayed
+ .connect_clicked(clone!(episode, played => move |un| {
+ let mut episode = episode.clone();
+ episode.set_played(None);
+ let _ = episode.save();
+ un.hide();
+ played.show();
+ }));
+
+ let pd_title = pd.title().to_owned();
+ let play = &self.play;
+ let delete = &self.delete;
+ self.download
+ .connect_clicked(clone!(play, delete, episode => move |dl| {
+ on_download_clicked(
+ &pd_title,
+ &mut episode.clone(),
+ dl,
+ &play,
+ &delete,
+ );
+ }));
}
-
- // Show or hide the play/delete/download buttons upon widget initialization.
- let local_uri = episode.local_uri();
- if local_uri.is_some() && Path::new(local_uri.unwrap()).exists() {
- download_button.hide();
- play_button.show();
- delete_button.show();
- }
-
- play_button.connect_clicked(clone!(episode, played_button, unplayed_button => move |_| {
- let mut episode = episode.clone();
- on_play_bttn_clicked(*episode.id());
- let _ = episode.set_played_now();
- played_button.hide();
- unplayed_button.show();
- }));
-
- delete_button.connect_clicked(clone!(episode, play_button, download_button => move |del| {
- on_delete_bttn_clicked(*episode.id());
- del.hide();
- play_button.hide();
- download_button.show();
- }));
-
- played_button.connect_clicked(clone!(episode, unplayed_button => move |played| {
- let mut episode = episode.clone();
- let _ = episode.set_played_now();
- played.hide();
- unplayed_button.show();
- }));
-
- unplayed_button.connect_clicked(clone!(episode, played_button => move |un| {
- let mut episode = episode.clone();
- episode.set_played(None);
- let _ = episode.save();
- un.hide();
- played_button.show();
- }));
-
- let pd_title = pd_title.to_owned();
- download_button.connect_clicked(clone!(play_button, delete_button, episode => move |dl| {
- on_download_clicked(
- &pd_title,
- &mut episode.clone(),
- dl,
- &play_button,
- &delete_button,
- );
- }));
-
- ep
}
// TODO: show notification when dl is finished.
@@ -192,8 +247,9 @@ pub fn episodes_listbox(pd: &Podcast) -> Result {
let list = gtk::ListBox::new();
episodes.into_iter().for_each(|mut ep| {
- let w = epidose_widget(&mut ep, pd.title());
- list.add(&w)
+ // let w = epidose_widget(&mut ep, pd.title());
+ let widget = EpisodeWidget::new_initialized(&mut ep, pd);
+ list.add(&widget.container)
});
list.set_vexpand(false);
diff --git a/hammond-gtk/src/widgets/podcast.rs b/hammond-gtk/src/widgets/podcast.rs
index 6d765a3..206ffd9 100644
--- a/hammond-gtk/src/widgets/podcast.rs
+++ b/hammond-gtk/src/widgets/podcast.rs
@@ -1,6 +1,6 @@
use gtk::prelude::*;
use gtk;
-use gdk_pixbuf::Pixbuf;
+use diesel::Identifiable;
use std::fs;
@@ -9,48 +9,90 @@ use hammond_data::Podcast;
use hammond_downloader::downloader;
use widgets::episode::episodes_listbox;
-use podcasts_view::update_podcasts_view;
+use utils::get_pixbuf_from_path;
+use content;
-pub fn podcast_widget(stack: >k::Stack, pd: &Podcast) -> gtk::Box {
- // Adapted from gnome-music AlbumWidget
- let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/podcast_widget.ui");
- let pd_widget: gtk::Box = builder.get_object("podcast_widget").unwrap();
+#[derive(Debug)]
+pub struct PodcastWidget {
+ pub container: gtk::Box,
+ cover: gtk::Image,
+ title: gtk::Label,
+ description: gtk::TextView,
+ view: gtk::Viewport,
+ unsub: gtk::Button,
+ played: gtk::Button,
+}
- let cover: gtk::Image = builder.get_object("cover").unwrap();
- let title_label: gtk::Label = builder.get_object("title_label").unwrap();
- let desc_text_view: gtk::TextView = builder.get_object("desc_text_view").unwrap();
- let view: gtk::Viewport = builder.get_object("view").unwrap();
- let unsub_button: gtk::Button = builder.get_object("unsub_button").unwrap();
- let played_button: gtk::Button = builder.get_object("mark_all_played_button").unwrap();
+impl PodcastWidget {
+ pub fn new() -> PodcastWidget {
+ // Adapted from gnome-music AlbumWidget
+ let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/podcast_widget.ui");
+ let container: gtk::Box = builder.get_object("podcast_widget").unwrap();
- // TODO: should spawn a thread to avoid locking the UI probably.
- unsub_button.connect_clicked(clone!(stack, pd => move |bttn| {
- on_unsub_button_clicked(&stack, &pd, bttn);
- }));
+ let cover: gtk::Image = builder.get_object("cover").unwrap();
+ let title: gtk::Label = builder.get_object("title_label").unwrap();
+ let description: gtk::TextView = builder.get_object("desc_text_view").unwrap();
+ let view: gtk::Viewport = builder.get_object("view").unwrap();
+ let unsub: gtk::Button = builder.get_object("unsub_button").unwrap();
+ let played: gtk::Button = builder.get_object("mark_all_played_button").unwrap();
- title_label.set_text(pd.title());
- let listbox = episodes_listbox(pd);
- if let Ok(l) = listbox {
- view.add(&l);
+ PodcastWidget {
+ container,
+ cover,
+ title,
+ description,
+ view,
+ unsub,
+ played,
+ }
}
- {
- let buff = desc_text_view.get_buffer().unwrap();
- buff.set_text(pd.description());
+ pub fn new_initialized(stack: >k::Stack, pd: &Podcast) -> PodcastWidget {
+ let pdw = PodcastWidget::new();
+ pdw.init(stack, pd);
+ pdw
}
- let img = get_pixbuf_from_path(pd);
- if let Some(i) = img {
- cover.set_from_pixbuf(&i);
+ pub fn init(&self, stack: >k::Stack, pd: &Podcast) {
+ WidgetExt::set_name(&self.container, &pd.id().to_string());
+
+ // TODO: should spawn a thread to avoid locking the UI probably.
+ self.unsub.connect_clicked(clone!(stack, pd => move |bttn| {
+ on_unsub_button_clicked(&stack, &pd, bttn);
+ }));
+
+ self.title.set_text(pd.title());
+ let listbox = episodes_listbox(pd);
+ if let Ok(l) = listbox {
+ self.view.add(&l);
+ }
+
+ {
+ let buff = self.description.get_buffer().unwrap();
+ buff.set_text(pd.description());
+ }
+
+ let img = get_pixbuf_from_path(pd);
+ if let Some(i) = img {
+ self.cover.set_from_pixbuf(&i);
+ }
+
+ self.played.connect_clicked(clone!(stack, pd => move |_| {
+ on_played_button_clicked(&stack, &pd);
+ }));
+
+ self.show_played_button(pd);
}
- played_button.connect_clicked(clone!(stack, pd => move |_| {
- on_played_button_clicked(&stack, &pd);
- }));
+ fn show_played_button(&self, pd: &Podcast) {
+ let new_episodes = dbqueries::get_pd_unplayed_episodes(pd);
- show_played_button(pd, &played_button);
-
- pd_widget
+ if let Ok(n) = new_episodes {
+ if !n.is_empty() {
+ self.played.show()
+ }
+ }
+ }
}
fn on_unsub_button_clicked(stack: >k::Stack, pd: &Podcast, unsub_button: >k::Button) {
@@ -69,76 +111,12 @@ fn on_unsub_button_clicked(stack: >k::Stack, pd: &Podcast, unsub_button: >k:
}
};
}
- stack.set_visible_child_name("fb_parent");
- update_podcasts_view(stack);
+ content::update_podcasts(stack);
+ content::show_podcasts(stack);
}
fn on_played_button_clicked(stack: >k::Stack, pd: &Podcast) {
let _ = dbqueries::update_none_to_played_now(pd);
- update_podcast_widget(stack, pd);
-}
-
-fn show_played_button(pd: &Podcast, played_button: >k::Button) {
- let new_episodes = dbqueries::get_pd_unplayed_episodes(pd);
-
- if let Ok(n) = new_episodes {
- if !n.is_empty() {
- played_button.show()
- }
- }
-}
-
-pub fn get_pixbuf_from_path(pd: &Podcast) -> Option {
- let img_path = downloader::cache_image(pd);
- if let Some(i) = img_path {
- Pixbuf::new_from_file_at_scale(&i, 256, 256, true).ok()
- } else {
- None
- }
-}
-
-pub fn setup_podcast_widget(stack: >k::Stack) {
- let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/podcast_widget.ui");
- let pd_widget: gtk::Box = builder.get_object("podcast_widget").unwrap();
-
- stack.add_named(&pd_widget, "pdw");
-}
-
-pub fn update_podcast_widget(stack: >k::Stack, pd: &Podcast) {
- let old = stack.get_child_by_name("pdw").unwrap();
- let pdw = podcast_widget(stack, pd);
- let vis = stack.get_visible_child_name().unwrap();
-
- stack.remove(&old);
- stack.add_named(&pdw, "pdw");
- stack.set_visible_child_name(&vis);
- old.destroy();
-}
-
-#[cfg(test)]
-mod tests {
- use hammond_data::Source;
- use hammond_data::feed::index;
- use diesel::Identifiable;
- use super::*;
-
- #[test]
- fn test_get_pixbuf_from_path() {
- let url = "http://www.newrustacean.com/feed.xml";
-
- // Create and index a source
- let source = Source::from_url(url).unwrap();
- // Copy it's id
- let sid = source.id().clone();
-
- // Convert Source it into a Feed and index it
- let feed = source.into_feed().unwrap();
- index(vec![feed]);
-
- // Get the Podcast
- let pd = dbqueries::get_podcast_from_source_id(sid).unwrap();
- let pxbuf = get_pixbuf_from_path(&pd);
- assert!(pxbuf.is_some());
- }
+ content::update_widget_preserve_vis(stack, pd);
}
diff --git a/org.gnome.Hammond.json b/org.gnome.Hammond.json
index 459b13c..ea403fc 100644
--- a/org.gnome.Hammond.json
+++ b/org.gnome.Hammond.json
@@ -14,18 +14,18 @@
"--talk-name=org.freedesktop.Notifications"
],
"build-options": {
+ "append-path": "/usr/lib/sdk/rust-stable/bin",
+ "build-args": [
+ "--share=network"
+ ],
"env": {
"CARGO_HOME": "/run/build/Hammond/cargo"
- },
- "build-args": [ "--share=network" ]
+ }
},
"modules": [
{
"name": "Hammond",
- "buildsystem": "simple",
- "build-commands": [
- "source /usr/lib/sdk/rust-stable/enable.sh && ./configure --prefix=/app && make && make install"
- ],
+ "buildsystem": "meson",
"sources": [
{
"type": "git",
diff --git a/rustfmt.toml b/rustfmt.toml
index 3a40cc5..477cd1c 100644
--- a/rustfmt.toml
+++ b/rustfmt.toml
@@ -1,3 +1,4 @@
+unstable_features = true
verbose = false
disable_all_formatting = false
skip_children = false
diff --git a/scripts/release.sh b/scripts/release.sh
index 9715f8b..cced5a7 100755
--- a/scripts/release.sh
+++ b/scripts/release.sh
@@ -12,14 +12,12 @@ mkdir -p $DIST
cp -rf hammond-data $DIST
cp -rf hammond-gtk $DIST
cp -rf hammond-downloader $DIST
-cp build.rs $DIST
cp Cargo.toml $DIST
cp configure $DIST
cp meson.build $DIST
cp Hammond.doap $DIST
cp LICENSE $DIST
cp README.md $DIST
-# cp -rf assets/org.gnome.Hammond.desktop $DIST
cp -rf assets $DIST
cp -rf scripts $DIST