Add cli & lib crates

This commit is contained in:
hulthe committed 2021-04-22 15:13:28 +02:00
1 parent e39cffa3f6
commit 3a9ecc398a
53 files changed
+5065 -99

No files matched your search

+2
View File
@@ -1,3 +1,5 @@
Dockerfile
target
*/target
database
.git
Generated
+514 -4
View File
@@ -1,7 +1,5 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "addr2line"
version = "0.14.1"
@@ -80,6 +78,15 @@ dependencies = [
"memchr",
]
[[package]]
name = "ansi_term"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "async-trait"
version = "0.1.50"
@@ -259,6 +266,21 @@ dependencies = [
"generic-array 0.14.4",
]
[[package]]
name = "clap"
version = "2.33.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
dependencies = [
"ansi_term",
"atty",
"bitflags",
"strsim",
"textwrap",
"unicode-width",
"vec_map",
]
[[package]]
name = "const_fn"
version = "0.4.7"
@@ -288,6 +310,22 @@ dependencies = [
"version_check",
]
[[package]]
name = "core-foundation"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a89e2ae426ea83155dccf10c0fa6b1463ef6d5fcb44cee0b224a408fa640a62"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "core-foundation-sys"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b"
[[package]]
name = "cpuid-bool"
version = "0.1.2"
@@ -454,6 +492,19 @@ dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "env_logger"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
dependencies = [
"atty",
"humantime",
"log",
"regex",
"termcolor",
]
[[package]]
name = "failure"
version = "0.1.8"
@@ -514,6 +565,31 @@ version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "foreign-types"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
dependencies = [
"foreign-types-shared",
]
[[package]]
name = "foreign-types-shared"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]]
name = "form_urlencoded"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191"
dependencies = [
"matches",
"percent-encoding",
]
[[package]]
name = "fs2"
version = "0.4.3"
@@ -753,7 +829,7 @@ dependencies = [
"log",
"pest",
"pest_derive",
"quick-error",
"quick-error 2.0.0",
"serde",
"serde_json",
]
@@ -764,6 +840,15 @@ version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
[[package]]
name = "heck"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87cbf45460356b7deeb5e3415b5563308c0a9b057c85e12b06ad551f98d0a6ac"
dependencies = [
"unicode-segmentation",
]
[[package]]
name = "hermit-abi"
version = "0.1.18"
@@ -827,6 +912,15 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05842d0d43232b23ccb7060ecb0f0626922c21f30012e97b767b30afd4a5d4b9"
[[package]]
name = "humantime"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
dependencies = [
"quick-error 1.2.3",
]
[[package]]
name = "hyper"
version = "0.14.6"
@@ -851,6 +945,30 @@ dependencies = [
"want",
]
[[package]]
name = "hyper-tls"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
dependencies = [
"bytes",
"hyper",
"native-tls",
"tokio",
"tokio-native-tls",
]
[[package]]
name = "idna"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8"
dependencies = [
"matches",
"unicode-bidi",
"unicode-normalization",
]
[[package]]
name = "indexmap"
version = "1.6.2"
@@ -906,12 +1024,27 @@ dependencies = [
"libc",
]
[[package]]
name = "ipnet"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47be2f14c678be2fdcab04ab1171db51b2762ce6f0a8ee87c8dd4a04ed216135"
[[package]]
name = "itoa"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
[[package]]
name = "js-sys"
version = "0.3.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d99f9e3e84b8f67f846ef5b4cbbc3b1c29f6c759fcbce6f01aa0e73d932a24c"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "kernel32-sys"
version = "0.2.2"
@@ -977,6 +1110,12 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
[[package]]
name = "matches"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
[[package]]
name = "memchr"
version = "2.3.4"
@@ -1092,6 +1231,24 @@ dependencies = [
"version_check",
]
[[package]]
name = "native-tls"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8d96b2e1c8da3957d58100b09f102c6d9cfdfced01b7ec5a8974044bb09dbd4"
dependencies = [
"lazy_static",
"libc",
"log",
"openssl",
"openssl-probe",
"openssl-sys",
"schannel",
"security-framework",
"security-framework-sys",
"tempfile",
]
[[package]]
name = "net2"
version = "0.2.37"
@@ -1192,6 +1349,39 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]]
name = "openssl"
version = "0.10.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a61075b62a23fef5a29815de7536d940aa35ce96d18ce0cc5076272db678a577"
dependencies = [
"bitflags",
"cfg-if 1.0.0",
"foreign-types",
"libc",
"once_cell",
"openssl-sys",
]
[[package]]
name = "openssl-probe"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
[[package]]
name = "openssl-sys"
version = "0.9.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "313752393519e876837e09e1fa183ddef0be7735868dced3196f4472d536277f"
dependencies = [
"autocfg",
"cc",
"libc",
"pkg-config",
"vcpkg",
]
[[package]]
name = "parking_lot"
version = "0.11.1"
@@ -1321,6 +1511,12 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkg-config"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
[[package]]
name = "polyval"
version = "0.4.5"
@@ -1338,6 +1534,16 @@ version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
[[package]]
name = "pretty_env_logger"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "926d36b9553851b8b0005f1275891b392ee4d2d833852c417ed025477350fb9d"
dependencies = [
"env_logger",
"log",
]
[[package]]
name = "proc-macro-error"
version = "1.0.4"
@@ -1396,6 +1602,12 @@ dependencies = [
"yansi",
]
[[package]]
name = "quick-error"
version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
[[package]]
name = "quick-error"
version = "2.0.0"
@@ -1506,6 +1718,41 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "reqwest"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2296f2fac53979e8ccbc4a1136b25dcefd37be9ed7e4a1f6b05a6029c84ff124"
dependencies = [
"base64",
"bytes",
"encoding_rs",
"futures-core",
"futures-util",
"http",
"http-body",
"hyper",
"hyper-tls",
"ipnet",
"js-sys",
"lazy_static",
"log",
"mime",
"native-tls",
"percent-encoding",
"pin-project-lite",
"serde",
"serde_json",
"serde_urlencoded",
"tokio",
"tokio-native-tls",
"url",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
"winreg",
]
[[package]]
name = "rocket"
version = "0.5.0-dev"
@@ -1634,6 +1881,16 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "schannel"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75"
dependencies = [
"lazy_static",
"winapi 0.3.9",
]
[[package]]
name = "scoped-tls"
version = "1.0.0"
@@ -1646,6 +1903,29 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "security-framework"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3670b1d2fdf6084d192bc71ead7aabe6c06aa2ea3fbd9cc3ac111fa5c2b1bd84"
dependencies = [
"bitflags",
"core-foundation",
"core-foundation-sys",
"libc",
"security-framework-sys",
]
[[package]]
name = "security-framework-sys"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3676258fd3cfe2c9a0ec99ce3038798d847ce3e4bb17746373eb9f0f1ac16339"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "semver"
version = "0.9.0"
@@ -1710,6 +1990,18 @@ dependencies = [
"serde",
]
[[package]]
name = "serde_urlencoded"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9"
dependencies = [
"form_urlencoded",
"itoa",
"ryu",
"serde",
]
[[package]]
name = "sha-1"
version = "0.8.2"
@@ -1865,7 +2157,7 @@ checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0"
[[package]]
name = "stl"
version = "2.4.0"
version = "2.5.0"
dependencies = [
"bincode",
"chrono",
@@ -1881,10 +2173,69 @@ dependencies = [
"serde_derive",
"serde_json",
"sled",
"stl_lib",
"tokio",
"uuid",
]
[[package]]
name = "stl_cli"
version = "2.5.0"
dependencies = [
"chrono",
"futures",
"log",
"notify",
"pretty_env_logger",
"reqwest",
"serde",
"stl_lib",
"structopt",
"syscalls",
"thiserror",
"tokio",
"uuid",
]
[[package]]
name = "stl_lib"
version = "2.5.0"
dependencies = [
"chrono",
"serde",
"uuid",
]
[[package]]
name = "strsim"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]]
name = "structopt"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5277acd7ee46e63e5168a80734c9f6ee81b1367a7d8772a2d765df2a3705d28c"
dependencies = [
"clap",
"lazy_static",
"structopt-derive",
]
[[package]]
name = "structopt-derive"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ba9cdfda491b814720b6b06e0cac513d922fc407582032e8706e9f137976f90"
dependencies = [
"heck",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "subtle"
version = "2.4.0"
@@ -1914,6 +2265,15 @@ dependencies = [
"unicode-xid",
]
[[package]]
name = "syscalls"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ad4126c98e506c5c2ada914b40c17b57a99f7d7044e35ff631a3504effb28e4"
dependencies = [
"cc",
]
[[package]]
name = "tempfile"
version = "3.2.0"
@@ -1928,6 +2288,44 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "termcolor"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
dependencies = [
"winapi-util",
]
[[package]]
name = "textwrap"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
dependencies = [
"unicode-width",
]
[[package]]
name = "thiserror"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "time"
version = "0.1.43"
@@ -1976,6 +2374,21 @@ dependencies = [
"syn",
]
[[package]]
name = "tinyvec"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b5220f05bb7de7f3f53c7c065e1199b3172696fe2db9f9c4d8ad9b4ee74c342"
dependencies = [
"tinyvec_macros",
]
[[package]]
name = "tinyvec_macros"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]]
name = "tokio"
version = "1.5.0"
@@ -2006,6 +2419,16 @@ dependencies = [
"syn",
]
[[package]]
name = "tokio-native-tls"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b"
dependencies = [
"native-tls",
"tokio",
]
[[package]]
name = "tokio-util"
version = "0.6.6"
@@ -2108,6 +2531,36 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eeba86d422ce181a719445e51872fa30f1f7413b62becb52e95ec91aa262d85c"
[[package]]
name = "unicode-bidi"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eeb8be209bb1c96b7c177c7420d26e04eccacb0eeae6b980e35fcb74678107e0"
dependencies = [
"matches",
]
[[package]]
name = "unicode-normalization"
version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07fbfce1c8a97d547e8b5334978438d9d6ec8c20e38f56d4a4374d181493eaef"
dependencies = [
"tinyvec",
]
[[package]]
name = "unicode-segmentation"
version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796"
[[package]]
name = "unicode-width"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
[[package]]
name = "unicode-xid"
version = "0.2.1"
@@ -2124,6 +2577,18 @@ dependencies = [
"subtle",
]
[[package]]
name = "url"
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ccd964113622c8e9322cfac19eb1004a07e636c545f325da085d5cdde6f1f8b"
dependencies = [
"form_urlencoded",
"idna",
"matches",
"percent-encoding",
]
[[package]]
name = "uuid"
version = "0.8.2"
@@ -2134,6 +2599,18 @@ dependencies = [
"serde",
]
[[package]]
name = "vcpkg"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbdbff6266a24120518560b5dc983096efb98462e51d0d68169895b237be3e5d"
[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]]
name = "version_check"
version = "0.9.3"
@@ -2174,6 +2651,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83240549659d187488f91f33c0f8547cbfef0b2088bc470c116d1d260ef623d9"
dependencies = [
"cfg-if 1.0.0",
"serde",
"serde_json",
"wasm-bindgen-macro",
]
@@ -2192,6 +2671,18 @@ dependencies = [
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81b8b767af23de6ac18bf2168b690bed2902743ddf0fb39252e36f9e2bfc63ea"
dependencies = [
"cfg-if 1.0.0",
"js-sys",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.73"
@@ -2221,6 +2712,16 @@ version = "0.2.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9a543ae66aa233d14bb765ed9af4a33e81b8b58d1584cf1b47ff8cd0b9e4489"
[[package]]
name = "web-sys"
version = "0.3.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a905d57e488fec8861446d3393670fb50d27a262344013181c2cdf9fff5481be"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "winapi"
version = "0.2.8"
@@ -2264,6 +2765,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "winreg"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69"
dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "ws2_32-sys"
version = "0.2.1"
+6 -38
View File
@@ -1,38 +1,6 @@
[package]
name = "stl"
description = "studielogg aka scuffed toggl"
version = "2.4.0"
authors = ["Joakim Hulthe <joakim@hulthe.net>"]
license = "MPL-2.0"
edition = "2018"
[dependencies]
dotenv = "0.13.0"
serde = "1"
serde_json = "1"
serde_derive = "1"
log = "0.4.8"
futures = "0.3"
chrono = { version = "0.4", features = ["serde"] }
sled = "0.34"
semver = "0.11"
uuid = { version = "0.8", features = ["serde", "v4"] }
duplicate = "0.2"
bincode = "1"
handlebars = "3"
[dependencies.tokio]
version = "1"
features = ["sync", "time"]
[dependencies.rocket]
#version = "0.4"
git = "https://github.com/SergioBenitez/Rocket"
branch = "master"
features = ["secrets"]
[dependencies.rocket_contrib]
#version = "0.4"
git = "https://github.com/SergioBenitez/Rocket"
branch = "master"
features = ["handlebars_templates", "uuid"]
[workspace]
members = [
"server",
"cli",
"lib",
]
+5 -3
View File
@@ -1,7 +1,7 @@
###################
### BUILD STAGE ###
###################
FROM rust:1.47 as build_stage
FROM rust:1.51 as build_stage
# Install build dependencies
RUN rustup target add x86_64-unknown-linux-musl
@@ -9,7 +9,9 @@ RUN rustup target add x86_64-unknown-linux-musl
# Build project
WORKDIR /app
COPY . .
WORKDIR /app/server
RUN cargo build --release --target x86_64-unknown-linux-musl
WORKDIR /app
RUN strip target/x86_64-unknown-linux-musl/release/stl
########################
@@ -29,8 +31,8 @@ VOLUME "/database"
WORKDIR /
# Copy static files
COPY templates templates
COPY static static
COPY server/templates templates
COPY server/static static
# Copy application binary
COPY --from=build_stage /app/target/x86_64-unknown-linux-musl/release/stl stl
+1
View File
@@ -0,0 +1 @@
/target
+1711
View File
File diff suppressed because it is too large. Load diff
+36
View File
@@ -0,0 +1,36 @@
[package]
name = "stl_cli"
version = "2.5.0"
authors = ["Joakim Hulthe <joakim@hulthe.net>"]
license = "MPL-2.0"
edition = "2018"
[[bin]]
name = "stl"
path = "src/main.rs"
[dependencies]
thiserror = "1.0.24"
notify = "4.0.16"
log = "0.4.14"
pretty_env_logger = "0.4.0"
uuid = { version = "0.8", features = ["serde", "v4"] }
chrono = { version = "0.4", features = ["serde"] }
structopt = "0.3.21"
syscalls = { version = "0.3", default-features = false }
futures = "0.3"
[dependencies.stl_lib]
path = "../lib"
[dependencies.serde]
version = "1"
features = ["derive"]
[dependencies.reqwest]
version = "0.11.3"
features = ["json"]
[dependencies.tokio]
version = "1.5.0"
features = ["fs", "rt", "rt-multi-thread", "macros"]
View File
Whitespace-only changes.
+161
View File
@@ -0,0 +1,161 @@
use crate::util::proxy_channel;
use crate::DaemonOpt;
use crate::Error;
use futures::poll;
use futures::task::Poll;
use notify::{INotifyWatcher, Op, RecursiveMode, Watcher};
use serde::Deserialize;
use std::collections::HashMap;
use std::sync::mpsc;
use std::time::{Duration, Instant};
use stl_lib::api::url;
use stl_lib::v2::trees::category;
use tokio::fs;
use tokio::runtime::Runtime;
use tokio::task::{spawn, JoinHandle};
pub fn run(opt: DaemonOpt) -> Result<(), Error> {
let opt: &'static DaemonOpt = Box::leak(Box::new(opt));
let rt = Runtime::new()?;
rt.block_on(async {
let (tx, rx) = mpsc::channel();
info!("creating output file");
fs::write(&opt.file, b"").await?;
let mut watcher = INotifyWatcher::new_raw(tx).unwrap();
watcher
.watch(&opt.file, RecursiveMode::NonRecursive)
.expect("failed to watch file");
update_category_list(opt).await?;
let mut last_update = Instant::now();
let mut wfe: JoinHandle<_> = spawn(wait_for_event(opt));
let mut rx = proxy_channel(rx);
loop {
let event = match rx.recv().await {
Some(event) => event,
None => return Err(Error::ChannelClosed),
};
debug!("event op {:?}", event.op);
match event.op {
Ok(Op::CHMOD) => { /* YEESSS */ }
_ => continue,
}
debug!("CHMOD event detected");
let update_categories;
let restart_wfe;
match poll!(&mut wfe) {
Poll::Ready(Ok(Ok(_wfe))) => {
restart_wfe = true;
update_categories = Some(true);
}
Poll::Ready(Ok(Err(e))) => {
error!("error waiting for event (falling back to timing): {}", e);
restart_wfe = false;
update_categories = None;
}
Poll::Ready(Err(_)) => {
restart_wfe = false;
update_categories = None;
}
Poll::Pending => {
restart_wfe = false;
update_categories = Some(false);
}
}
let elapsed = last_update.elapsed();
let update_categories =
update_categories.unwrap_or_else(|| elapsed > Duration::from_secs(opt.poll_delay));
if update_categories {
update_category_list(opt).await?;
last_update = Instant::now();
}
if update_categories || restart_wfe {
wfe = spawn(wait_for_event(opt));
}
}
})
}
#[derive(Deserialize)]
struct WaitForEvent {
#[allow(dead_code)]
timeout: bool,
}
async fn wait_for_event(opt: &DaemonOpt) -> Result<WaitForEvent, Error> {
info!("calling wait_for_event");
let client = reqwest::Client::new();
let wfe: WaitForEvent = client
.get(format!(
"{}{}?timeout={}",
&opt.api_uri,
url::WAIT_FOR_EVENT,
opt.poll_delay
))
.header("Cookie", &opt.cookie)
.send()
.await?
.json()
.await?;
Ok(wfe)
}
async fn update_category_list(opt: &DaemonOpt) -> Result<(), Error> {
let categories = get_active_categories(opt).await?;
info!("writing output file");
let data = categories.join("|");
let data = if data.is_empty() {
b"--"
} else {
data.as_bytes()
};
fs::write(&opt.file, data).await?;
Ok(())
}
async fn get_active_categories(opt: &DaemonOpt) -> Result<Vec<String>, Error> {
info!("downloading category list");
let client = reqwest::Client::new();
let response = client
.get(format!("{}{}", &opt.api_uri, url::SESSIONS))
.header("Cookie", &opt.cookie)
.send()
.await?;
let categories: HashMap<category::K, category::V> = response.json().await?;
// sort by the longest running log
let mut categories: Vec<category::V> = categories.into_iter().map(|(_, v)| v).collect();
categories.sort_by_key(|c| (c.started));
Ok(categories
.into_iter()
.inspect(|category| {
info!(
" name={} active={}",
category.name,
category.started.is_some()
)
})
.filter(|category| category.started.is_some())
.map(|category| category.name)
.collect())
}
+80
View File
@@ -0,0 +1,80 @@
#[macro_use]
extern crate log;
pub mod daemon;
pub mod stat;
pub mod util;
use std::path::PathBuf;
use structopt::StructOpt;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum Error {
#[error("request error {0:?}")]
Request(#[from] reqwest::Error),
#[error("input/output error")]
IO(#[from] tokio::io::Error),
#[error("notify channel closed")]
ChannelClosed,
#[error("syscall error, code = {error_code}")]
SysCall { error_code: i64 },
}
#[derive(StructOpt)]
pub enum Opt {
/// Launch the daemon
Daemon(DaemonOpt),
/// touch the stat file if it exists
/// otherwise exit with status code 1
Stat(StatOpt),
}
#[derive(StructOpt)]
pub struct DaemonOpt {
/// The path to the output file
#[structopt(short, long)]
file: PathBuf,
/// The server uri
#[structopt(short, long, default_value = "https://stl.nubo.sh")]
api_uri: String,
/// The amount of time to wait between polls
#[structopt(short = "d", long, default_value = "30")]
poll_delay: u64,
/// The authorization cookie for the server
#[structopt(short, long)]
cookie: String,
}
#[derive(StructOpt)]
pub struct StatOpt {
#[structopt(short, long)]
file: PathBuf,
}
fn main() {
pretty_env_logger::init();
let opt = Opt::from_args();
let result = match opt {
Opt::Daemon(opt) => daemon::run(opt),
Opt::Stat(opt) => stat::run(&opt),
};
match result {
Ok(_) => {}
Err(e) => {
error!("{}", e);
}
}
info!("stld starting");
}
+34
View File
@@ -0,0 +1,34 @@
use crate::{Error, StatOpt};
use std::fs;
use std::os::unix::io::AsRawFd;
use std::process::exit;
use syscalls::syscall;
pub fn run(opt: &StatOpt) -> Result<(), Error> {
let file = match fs::OpenOptions::new()
.write(true)
.read(false)
.create(false)
.open(&opt.file)
{
Ok(file) => file,
Err(_) => exit(1),
};
let fd: i32 = file.as_raw_fd();
let result: i64 = unsafe {
// update file mtime (to trigger inotify) in the daemon
//
// SAFETY:
// - fd is a valid file descriptor, since it was created using a File
// - passing NULL to all other parameters is valid according to `man 2 utimensat`
syscall!(SYS_utimensat, fd, 0, 0, 0)
}
.map_err(|error_code| Error::SysCall { error_code })?;
// 0 should be the only possible return value, since error cases are handled by the result
assert_eq!(result, 0);
Ok(())
}
+24
View File
@@ -0,0 +1,24 @@
use std::sync::mpsc as std_mpsc;
use tokio::sync::mpsc as tokio_mpsc;
use tokio::task;
pub fn proxy_channel<T>(std_rx: std_mpsc::Receiver<T>) -> tokio_mpsc::Receiver<T>
where
T: 'static + Send + Sync,
{
let (tx, tokio_rx) = tokio_mpsc::channel(255);
task::spawn_blocking(move || loop {
let msg = match std_rx.recv() {
Ok(msg) => msg,
Err(_) => return,
};
match tx.blocking_send(msg) {
Ok(_) => {}
Err(_) => return,
}
});
tokio_rx
}
+13
View File
@@ -0,0 +1,13 @@
[package]
name = "stl_lib"
version = "2.5.0"
authors = ["Joakim Hulthe <joakim@hulthe.net>"]
license = "MPL-2.0"
edition = "2018"
[dependencies]
chrono = { version = "0.4", features = ["serde"] }
serde = { version = "1", features = ["derive"] }
uuid = { version = "0.8", features = ["serde", "v4"] }
+4
View File
@@ -0,0 +1,4 @@
pub mod url {
pub const SESSIONS: &str = "/api/sessions";
pub const WAIT_FOR_EVENT: &str = "/api/wait_for_event";
}
+27
View File
@@ -0,0 +1,27 @@
use chrono::{DateTime, Local};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
pub type CategoryKey = Uuid;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Category {
/// The name of the category
pub name: String,
/// The description of the category
pub description: Option<String>,
/// The HTML color of the category in the rendered view
pub color: String,
/// If the session is not active, this will be None
pub started: Option<DateTime<Local>>,
/// The parent category of this category
/// If none, the category has no parent
pub parent: Option<CategoryKey>,
/// Whether the item has been "deleted", e.g. it shoudn't be shown in the view
pub deleted: bool,
}
+3
View File
@@ -0,0 +1,3 @@
pub mod api;
pub mod v2;
pub mod wfe;
+63
View File
@@ -0,0 +1,63 @@
pub(self) use chrono::{DateTime, Local};
pub(self) use serde::{Deserialize, Serialize};
pub(self) use uuid::Uuid;
/// Stuff in the default namespace
pub mod global {}
pub mod trees {
pub mod category {
use super::super::*;
pub const NAME: &str = "CATEGORIES";
pub type K = Uuid;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct V {
/// The name of the category
pub name: String,
/// The description of the category
pub description: Option<String>,
/// The HTML color of the category in the rendered view
pub color: String,
/// If the session is not active, this will be None
pub started: Option<DateTime<Local>>,
/// The parent category of this category
/// If none, the category has no parent
pub parent: Option<K>,
// FIXME: this field is currently not used
/// Whether the item has been "deleted", e.g. it shoudn't be shown in the view
pub deleted: bool,
}
}
pub mod session {
use super::super::*;
pub const NAME: &str = "SESSIONS";
pub type K = Uuid;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct V {
/// The UUID of the category to which this session belongs
pub category: trees::category::K,
/// The time when this session was started
pub started: DateTime<Local>,
/// The time when this session was ended
pub ended: DateTime<Local>,
// FIXME: this field is currently not used
/// Whether the item has been "deleted", e.g. it shoudn't be shown in the view
pub deleted: bool,
}
}
}
+6
View File
@@ -0,0 +1,6 @@
use serde::Serialize;
#[derive(Serialize)]
pub struct WaitForEvent {
pub timeout: bool,
}
+2281
View File
File diff suppressed because it is too large. Load diff
+41
View File
@@ -0,0 +1,41 @@
[package]
name = "stl"
description = "studielogg aka scuffed toggl"
version = "2.5.0"
authors = ["Joakim Hulthe <joakim@hulthe.net>"]
license = "MPL-2.0"
edition = "2018"
[dependencies]
dotenv = "0.13.0"
serde = "1"
serde_json = "1"
serde_derive = "1"
log = "0.4.8"
futures = "0.3"
chrono = { version = "0.4", features = ["serde"] }
sled = "0.34"
semver = "0.11"
uuid = { version = "0.8", features = ["serde", "v4"] }
duplicate = "0.2"
bincode = "1"
handlebars = "3"
[dependencies.stl_lib]
path = "../lib"
[dependencies.tokio]
version = "1"
features = ["sync", "time"]
[dependencies.rocket]
#version = "0.4"
git = "https://github.com/SergioBenitez/Rocket"
branch = "master"
features = ["secrets"]
[dependencies.rocket_contrib]
#version = "0.4"
git = "https://github.com/SergioBenitez/Rocket"
branch = "master"
features = ["handlebars_templates", "uuid"]
+4
View File
@@ -0,0 +1,4 @@
segment_size: 524288
use_compression: false
version: 0.34
vQ�
Binary file not shown.
Binary file not shown.
View File
File renamed without changes.
View File
File renamed without changes.
File renamed without changes.
@@ -12,7 +12,7 @@ pub fn migrate(db: &mut Db) -> Result<(), MigrationError> {
// Open old & new trees
let v1_past_sessions = db.open_tree(v1::trees::past_sessions::NAME)?;
let v2_sessions = db.open_tree(v2::trees::sessions::NAME)?;
let v2_sessions = db.open_tree(v2::trees::session::NAME)?;
// Iterate over old tree
for r in v1_past_sessions.iter() {
@@ -26,7 +26,7 @@ pub fn migrate(db: &mut Db) -> Result<(), MigrationError> {
} = deserialize(&v)?;
// Convert to new value
let v2_value = v2::trees::sessions::V {
let v2_value = v2::trees::session::V {
category,
started: DateTime::<Utc>::from_utc(started, Utc).into(),
ended: DateTime::<Utc>::from_utc(ended, Utc).into(),
@@ -59,7 +59,7 @@ pub fn migrate(db: &mut Db) -> Result<(), MigrationError> {
} = deserialize(&v)?;
// Convert to new value
let v2_value = v2::trees::categories::V {
let v2_value = v2::trees::category::V {
name,
description: None,
color,
@@ -1,7 +1,7 @@
pub mod unversioned;
pub mod util;
pub mod v1;
pub mod v2;
pub use stl_lib::v2;
pub mod migrations;
File renamed without changes.
@@ -1,12 +1,12 @@
use crate::database::latest::trees::categories;
use crate::database::latest::trees::category;
use crate::status_json::StatusJson;
use bincode::{deserialize, serialize};
use std::collections::HashMap;
pub fn get_category(
tree: &sled::Tree,
key: &categories::K,
) -> Result<Option<categories::V>, StatusJson> {
key: &category::K,
) -> Result<Option<category::V>, StatusJson> {
Ok(match tree.get(serialize(key)?)? {
Some(raw) => Some(deserialize(&raw)?),
None => None,
@@ -15,7 +15,7 @@ pub fn get_category(
pub fn get_all_categories(
tree: &sled::Tree,
) -> Result<HashMap<categories::K, categories::V>, StatusJson> {
) -> Result<HashMap<category::K, category::V>, StatusJson> {
Ok(tree
.iter()
.map(|result| {
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
View File
File renamed without changes.
+16 -21
View File
@@ -1,5 +1,5 @@
use crate::auth::Authorized;
use crate::database::latest::trees::{categories, sessions};
use crate::database::latest::trees::{category, session};
use crate::database::util::category::get_all_categories;
use crate::routes::pages;
use crate::status_json::StatusJson;
@@ -12,16 +12,16 @@ use rocket::response::Redirect;
use rocket::{get, post, uri, State};
use rocket_contrib::json::Json;
use rocket_contrib::uuid::Uuid;
use serde::Serialize;
use sled::Transactional;
use std::collections::HashMap;
use stl_lib::wfe::WaitForEvent;
#[get("/sessions")]
pub fn get_sessions(
_auth: Authorized,
db: State<'_, sled::Db>,
) -> Result<Json<HashMap<categories::K, categories::V>>, StatusJson> {
let categories_tree = db.open_tree(categories::NAME)?;
) -> Result<Json<HashMap<category::K, category::V>>, StatusJson> {
let categories_tree = db.open_tree(category::NAME)?;
Ok(Json(get_all_categories(&categories_tree)?))
}
@@ -39,10 +39,10 @@ pub fn create_category(
) -> Result<StatusJson, StatusJson> {
let category = category.into_inner();
let categories_tree = db.open_tree(categories::NAME)?;
let categories_tree = db.open_tree(category::NAME)?;
categories_tree.insert(
serialize(&uuid::Uuid::new_v4())?,
serialize(&categories::V {
serialize(&category::V {
name: category.name,
description: None,
color: category.color,
@@ -65,13 +65,13 @@ pub fn bump_session(
let duration = Duration::minutes(minutes);
let category_uuid_s = sled::IVec::from(serialize(&category_uuid.into_inner())?);
let categories_tree = db.open_tree(categories::NAME)?;
let categories_tree = db.open_tree(category::NAME)?;
Ok((&categories_tree).transaction(|tx_categories| {
match tx_categories.get(&category_uuid_s)? {
None => return Ok(Err(Status::NotFound.into())),
Some(data) => {
let mut category: categories::V = deserialize(&data).unwrap();
let mut category: category::V = deserialize(&data).unwrap();
match category.started.as_mut() {
Some(started) => {
if let Some(new_started) = started.checked_sub_signed(duration) {
@@ -127,15 +127,15 @@ pub fn toggle_category_session(
) -> Result<StatusJson, StatusJson> {
let category_uuid_s = sled::IVec::from(serialize(&category_uuid.into_inner())?);
let categories_tree = db.open_tree(categories::NAME)?;
let sessions_tree = db.open_tree(sessions::NAME)?;
let categories_tree = db.open_tree(category::NAME)?;
let sessions_tree = db.open_tree(session::NAME)?;
Ok(
(&categories_tree, &sessions_tree).transaction(|(tx_categories, tx_sessions)| {
match tx_categories.get(&category_uuid_s)? {
None => return Ok(Err(Status::NotFound)),
Some(data) => {
let mut category: categories::V = deserialize(&data).unwrap();
let mut category: category::V = deserialize(&data).unwrap();
let now = Local::now();
match (set_active, category.started.take()) {
@@ -144,7 +144,7 @@ pub fn toggle_category_session(
let duration = now - started;
if duration > Duration::minutes(5) {
let session_uuid = serialize(&uuid::Uuid::new_v4()).unwrap();
let session = sessions::V {
let session = session::V {
category: category_uuid.into_inner(),
started,
ended: now,
@@ -189,7 +189,7 @@ pub fn edit_session(
) -> Result<Redirect, StatusJson> {
let session_uuid_s = sled::IVec::from(serialize(&session_uuid.into_inner())?);
let session = sessions::V {
let session = session::V {
category: session.category.into_inner(),
started: Local
.from_local_datetime(&NaiveDateTime::parse_from_str(
@@ -213,7 +213,7 @@ pub fn edit_session(
));
}
db.open_tree(sessions::NAME)?
db.open_tree(session::NAME)?
.insert(session_uuid_s, serialize(&session)?)?;
// FIXME: Uuid does not implement FromUriParam for some reason... File an issue?
@@ -229,7 +229,7 @@ pub fn delete_session(
) -> Result<Redirect, StatusJson> {
let session_uuid_s = sled::IVec::from(serialize(&session_uuid.into_inner())?);
let sessions_tree = db.open_tree(sessions::NAME)?;
let sessions_tree = db.open_tree(session::NAME)?;
match sessions_tree.remove(session_uuid_s)? {
Some(_) => Ok(Redirect::to(uri!(pages::history))),
@@ -241,18 +241,13 @@ pub fn delete_session(
// match tx_sessions.get(&session_uuid_s)? {
// None => return Ok(Err(Status::NotFound)),
// Some(data) => {
// let mut session: sessions::V = deserialize(&data).unwrap();
// let mut session: session::V = deserialize(&data).unwrap();
// }
// }
// Ok(Ok(Redirect::to(uri!(pages::history))))
// })??)
}
#[derive(Serialize)]
pub struct WaitForEvent {
timeout: bool,
}
#[get("/wait_for_event?<timeout>")]
pub async fn wait_for_event(
_auth: Authorized,
File renamed without changes.
@@ -1,7 +1,7 @@
pub mod stats;
use crate::auth::Authorized;
use crate::database::latest::trees::{categories, sessions};
use crate::database::latest::trees::{category, session};
use crate::status_json::StatusJson;
use bincode::{deserialize, serialize};
use rocket::http::Status;
@@ -16,10 +16,10 @@ use std::time::Duration;
pub fn index(_auth: Authorized, db: State<'_, sled::Db>) -> Result<Template, StatusJson> {
#[derive(Debug, Serialize, Deserialize)]
struct TemplateContext {
categories: Vec<(uuid::Uuid, categories::V)>,
categories: Vec<(category::K, category::V)>,
}
let categories_tree = db.open_tree(categories::NAME)?;
let categories_tree = db.open_tree(category::NAME)?;
let context = TemplateContext {
categories: categories_tree
@@ -41,13 +41,13 @@ pub fn session_edit(
) -> Result<Template, StatusJson> {
#[derive(Debug, Serialize, Deserialize)]
struct SessionPageContext {
session: sessions::V,
session: session::V,
session_id: uuid::Uuid,
}
let session_uuid_s = sled::IVec::from(serialize(&session_uuid.into_inner())?);
let sessions_tree = db.open_tree(sessions::NAME)?;
let sessions_tree = db.open_tree(session::NAME)?;
match sessions_tree.get(session_uuid_s)? {
None => Err(Status::NotFound)?,
Some(data) => {
@@ -65,8 +65,8 @@ pub fn session_edit(
pub fn history(_auth: Authorized, db: State<'_, sled::Db>) -> Result<Template, StatusJson> {
#[derive(Debug, Serialize, Deserialize)]
struct HistoryEntryContext {
category: categories::V,
session: sessions::V,
category: category::V,
session: session::V,
session_id: uuid::Uuid,
duration: Duration,
}
@@ -76,17 +76,17 @@ pub fn history(_auth: Authorized, db: State<'_, sled::Db>) -> Result<Template, S
entries: Vec<HistoryEntryContext>,
}
let categories_tree = db.open_tree(categories::NAME)?;
let sessions_tree = db.open_tree(sessions::NAME)?;
let categories_tree = db.open_tree(category::NAME)?;
let sessions_tree = db.open_tree(session::NAME)?;
let categories: HashMap<categories::K, categories::V> = categories_tree
let categories: HashMap<category::K, category::V> = categories_tree
.iter()
.map(|result| {
result.map(|(k, v)| deserialize(&k).and_then(|k| deserialize(&v).map(|v| (k, v))))
})
.collect::<Result<Result<_, _>, _>>()??;
let sessions: HashMap<sessions::K, sessions::V> = sessions_tree
let sessions: HashMap<session::K, session::V> = sessions_tree
.iter()
.map(|result| {
result.map(|(k, v)| deserialize(&k).and_then(|k| deserialize(&v).map(|v| (k, v))))
@@ -1,5 +1,5 @@
use crate::auth::Authorized;
use crate::database::latest::trees::{categories, sessions};
use crate::database::latest::trees::{category, session};
use crate::database::util::category::get_category;
use crate::status_json::StatusJson;
use bincode::deserialize;
@@ -14,8 +14,8 @@ use std::collections::{BTreeMap, HashMap};
#[derive(Debug, Serialize, Deserialize)]
struct CategoryStatsContext {
category_id: categories::K,
category: categories::V,
category_id: category::K,
category: category::V,
last_session_start: Option<DateTime<Local>>,
secs_last_session: u64,
@@ -26,7 +26,7 @@ struct CategoryStatsContext {
bars: Vec<(u32, f64, f64)>,
}
fn sum_sessions<'a>(iter: impl IntoIterator<Item = &'a sessions::V>) -> u64 {
fn sum_sessions<'a>(iter: impl IntoIterator<Item = &'a session::V>) -> u64 {
iter.into_iter()
.map(|session| session.ended - session.started)
.map(|duration| duration.num_seconds() as u64)
@@ -39,13 +39,13 @@ pub fn single_stats(
category_uuid: Uuid,
db: State<'_, sled::Db>,
) -> Result<Template, StatusJson> {
let categories_tree = db.open_tree(categories::NAME)?;
let sessions_tree = db.open_tree(sessions::NAME)?;
let categories_tree = db.open_tree(category::NAME)?;
let sessions_tree = db.open_tree(session::NAME)?;
let category: categories::V =
let category: category::V =
get_category(&categories_tree, &category_uuid)?.ok_or(Status::NotFound)?;
let sessions: HashMap<sessions::K, sessions::V> = sessions_tree
let sessions: HashMap<session::K, session::V> = sessions_tree
.iter()
.map(|result| {
result.map(|(k, v)| deserialize(&k).and_then(|k| deserialize(&v).map(|v| (k, v))))
@@ -114,17 +114,17 @@ pub fn all_stats(_auth: Authorized, db: State<'_, sled::Db>) -> Result<Template,
let now = Local::now();
let categories_tree = db.open_tree(categories::NAME)?;
let sessions_tree = db.open_tree(sessions::NAME)?;
let categories_tree = db.open_tree(category::NAME)?;
let sessions_tree = db.open_tree(session::NAME)?;
let categories: HashMap<categories::K, categories::V> = categories_tree
let categories: HashMap<category::K, category::V> = categories_tree
.iter()
.map(|result| {
result.map(|(k, v)| deserialize(&k).and_then(|k| deserialize(&v).map(|v| (k, v))))
})
.collect::<Result<Result<_, _>, _>>()??;
let sessions: HashMap<sessions::K, sessions::V> = sessions_tree
let sessions: HashMap<session::K, session::V> = sessions_tree
.iter()
.map(|result| {
result.map(|(k, v)| deserialize(&k).and_then(|k| deserialize(&v).map(|v| (k, v))))
@@ -193,7 +193,7 @@ pub fn all_stats(_auth: Authorized, db: State<'_, sled::Db>) -> Result<Template,
fn compute_percentage_per_hour<'a, I>(sessions: I) -> BTreeMap<u32, f64>
where
I: Iterator<Item = &'a sessions::V>,
I: Iterator<Item = &'a session::V>,
{
let mut stats_per_hour = BTreeMap::new();
for session in sessions {
@@ -282,7 +282,7 @@ mod test {
.unwrap()
};
sessions::V {
session::V {
category: Default::default(),
deleted: false,
started: set_hm(today, h1, m1),
File renamed without changes.
View File
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.