├── migrations ├── .gitkeep └── 20161115044326_create_timers │ ├── down.sql │ └── up.sql ├── .gitattributes ├── angry-clock-eats-person.png ├── .gitignore ├── lib └── tock │ ├── src │ ├── schema.rs │ ├── models.rs │ └── lib.rs │ ├── Cargo.toml │ └── Cargo.lock ├── .travis.yml ├── CONTRIBUTING.md ├── Cargo.toml ├── ISSUE_TEMPLATE.md ├── src ├── config.yml └── main.rs ├── LICENSE.md ├── Makefile ├── PULL_REQUEST_TEMPLATE.md ├── CODE_OF_CONDUCT.md ├── README.md └── Cargo.lock /migrations/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | Cargo.lock binary 2 | -------------------------------------------------------------------------------- /migrations/20161115044326_create_timers/down.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE timers 2 | -------------------------------------------------------------------------------- /angry-clock-eats-person.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rogeruiz/srht-tick/HEAD/angry-clock-eats-person.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Tick specific files 2 | target 3 | .env 4 | 5 | # OS and Editor files 6 | .DS_Store 7 | *.DS_Store 8 | Thumbs.db 9 | *.sublime-project 10 | *.sublime-workspace 11 | .svn 12 | .idea 13 | 14 | # Ignore fun directories 15 | tmp/ 16 | -------------------------------------------------------------------------------- /lib/tock/src/schema.rs: -------------------------------------------------------------------------------- 1 | diesel::table! { 2 | timers (id) { 3 | id -> Integer, 4 | name -> VarChar, 5 | start_time -> Integer, 6 | end_time -> Integer, 7 | start_entry -> Text, 8 | end_entry -> Text, 9 | running -> Integer, 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | 3 | rust: 4 | - stable 5 | 6 | cache: cargo 7 | 8 | before_script: 9 | - export PATH=$HOME/.cargo/bin:$PATH 10 | - mkdir -p $HOME/.config/tick 11 | - "echo 'database_path: ~/.config/tick/test.db' > $HOME/.config/tick/config.yaml" 12 | - cargo build 13 | - ./target/debug/tick help 14 | -------------------------------------------------------------------------------- /migrations/20161115044326_create_timers/up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE timers ( 2 | id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, 3 | name VARCHAR NOT NULL, 4 | start_time INTEGER NOT NULL, 5 | end_time INTEGER NOT NULL DEFAULT 0, 6 | start_entry TEXT NOT NULL DEFAULT '', 7 | end_entry TEXT NOT NULL DEFAULT '', 8 | running INTEGER NOT NULL DEFAULT 0 9 | ) 10 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Welcome! 2 | 3 | I'm so glad you're thinking about contributing to Tick CLI! If you're unsure 4 | about anything, just ask -- or submit the issue or pull request anyway. The 5 | worst that can happen is you'll be politely asked to change something. 6 | 7 | I want to ensure a welcoming environment for all of my projects. Please be 8 | kind. 9 | 10 | I encourage you to read this project's CONTRIBUTING policy (you are here), 11 | its [LICENSE](LICENSE.md), and its [README](README.md). 12 | -------------------------------------------------------------------------------- /lib/tock/src/models.rs: -------------------------------------------------------------------------------- 1 | use super::schema::timers; 2 | 3 | #[derive(Queryable)] 4 | pub struct Timer { 5 | pub id: i32, 6 | pub name: String, 7 | pub start_time: i32, 8 | pub end_time: i32, 9 | pub start_entry: String, 10 | pub end_entry: String, 11 | pub running: i32, 12 | } 13 | 14 | #[derive(Insertable)] 15 | #[table_name = "timers"] 16 | pub struct NewTimer<'a> { 17 | pub name: &'a str, 18 | pub start_time: i32, 19 | pub start_entry: &'a str, 20 | pub running: i32, 21 | } 22 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tick" 3 | version = "1.0.0" 4 | authors = ["Roger Steve Ruiz 2 | 3 | ## Detailed Description 4 | 5 | 6 | ## Context 7 | 8 | 9 | 10 | ## Possible Implementation 11 | 12 | 13 | ## Your Environment 14 | 15 | * Rust version: 16 | * Operating System and version (e.g. Mac OS X, Linux, Windows): 17 | * Link to your project: 18 | 19 | -------------------------------------------------------------------------------- /src/config.yml: -------------------------------------------------------------------------------- 1 | name: tick 2 | args: 3 | - name: &name 4 | short: n 5 | long: name 6 | help: Set a name for this timer. 7 | takes_value: true 8 | - entry: &entry 9 | short: m 10 | long: message 11 | help: Set a message for this timer. 12 | takes_value: true 13 | - verbose: 14 | short: v 15 | long: verbose 16 | multiple: false 17 | help: Sets the level of verbosity. 18 | subcommands: 19 | - start: 20 | about: Start a ticking timer. 21 | args: 22 | - name: *name 23 | - entry: *entry 24 | - stop: 25 | about: Stop a ticking timer. 26 | args: 27 | - name: *name 28 | - entry: *entry 29 | - status: 30 | about: Get the status of a running timer. 31 | - list: 32 | about: Get list of all the timers. 33 | - remove: 34 | about: Remove a specific timer by id. 35 | args: 36 | - id: 37 | long: id 38 | help: The timer id to remove 39 | takes_value: true 40 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Roger Steve Ruiz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # This is a template Makefile that I use for automating projects that might 2 | # require one. 3 | # 4 | # For more guidance around Makefiles, the checkout out the helpful 5 | # [makefiletutorial](https://makefiletutorial.com/). 6 | 7 | check_defined = \ 8 | $(strip $(foreach 1,$1, \ 9 | $(call __check_defined,$1,$(strip $(value 2))))) 10 | __check_defined = \ 11 | $(if $(value $1),, \ 12 | $(error Undefined $1$(if $2, ($2)))) 13 | 14 | .PHONY: clean 15 | clean: ## Clean target directory. 16 | @cargo clean 17 | 18 | .PHONY: build 19 | build: clean ## Build a debug binary for Tick. 20 | @cargo build 21 | @echo "Binary avaiable at ./target/debug/tick" 22 | 23 | .PHONY: release 24 | release: clean ## Build a release binary for Tick. 25 | @cargo build --release 26 | @echo "Binary avaiable at ./target/release/tick" 27 | 28 | .PHONY: test 29 | test: clean ## Run the tests for Tick. 30 | @cargo test 31 | 32 | .PHONY: update 33 | update: clean ## Update Cargo.lock file with Cargo.toml configuration. 34 | @cargo update 35 | 36 | .PHONY: help 37 | help: ## Outputs this help message. 38 | @grep -E '^[0-9a-zA-Z_-]+:.*?## .*$$' $(firstword $(MAKEFILE_LIST)) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' 39 | -------------------------------------------------------------------------------- /PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Description 4 | 5 | 6 | ## Related Issue 7 | 8 | 9 | 10 | 11 | 12 | ## Motivation and Context 13 | 14 | 15 | ## How Has This Been Tested? 16 | 17 | 18 | 19 | 20 | ## Screenshots (if appropriate): 21 | 22 | ## Types of changes 23 | 24 | - [ ] Bug fix (non-breaking change which fixes an issue) 25 | - [ ] New feature (non-breaking change which adds functionality) 26 | - [ ] Breaking change (fix or feature that would cause existing functionality to change) 27 | 28 | ## Checklist: 29 | 30 | 31 | - [ ] My code follows the code style of this project. 32 | - [ ] My change requires a change to the documentation. 33 | - [ ] I have updated the documentation accordingly. 34 | - [ ] I have read the **CONTRIBUTING** document. 35 | - [ ] I have added tests to cover my changes. 36 | - [ ] All new and existing tests passed. 37 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at hi@rog.gr. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Tick CLI for tracking your time 2 | 3 | ![Angry clock eats person](angry-clock-eats-person.png) 4 | 5 | I use `tick` to track all my time using `tmux` sessions. But `tick` can be used 6 | without `tmux`, `node` or any other dependency. The `tick` CLI is written in Rust. 7 | 8 | Info | Description 9 | --- | --- 10 | [![Project Build Status](https://travis-ci.org/rogeruiz/tick.svg?branch=master)](https://travis-ci.org/rogeruiz/tick) | Project build status for Tick CLI 11 | [Installation](#installation) | Installing Tick CLI. 12 | [Motivation](#motivation) | Why use Tick CLI? 13 | [Commands](#commands) | Using Tick CLI. 14 | [Inspiration](#inspiration) | Everything is a remix, including Tick CLI. 15 | [Contributing](CONTRIBUTING.md) | Contribute to Tick CLI. 16 | [License](LICENSE.md) | License for Tick CLI. 17 | 18 | ## Installation 19 | 20 | To install Tick, you can either compile it from source or download the binary 21 | from [the releases page][tick-releases] for the release you want and the 22 | platform you need. 23 | 24 | [tick-releases]: https://github.com/rogeruiz/tick/releases "The releases for this repo" 25 | 26 | ### Supported platforms 27 | 28 | Tick has been used daily by me on different platforms such as macOS, Ubuntu, and 29 | Arch. While it hasn't been tested on other platforms such as Windows, patches 30 | are welcome to add tests for this. 31 | 32 | ### Dependencies 33 | 34 | Tick leverages SQlite 3+ as a database. Make sure you have `sqlite3` installed 35 | on your machine. This ships with macOS and can usually be installed with a 36 | package manager on your platform of choice. 37 | 38 | ### Compiling Tick from source 39 | 40 | The steps are pretty straight-forward as long as you are within the realm of 41 | [Tier 1 support][rustlang-tier1] for the Rust compiler. 42 | 43 | [rustlang-tier1]: https://forge.rust-lang.org/platform-support.html#tier-1 "Rust Platform Support" 44 | 45 | ```shell 46 | # Clone the repository. 47 | >_ git clone https://github.com/rogeruiz/tick.git 48 | 49 | >_ cd tick 50 | 51 | # Setup your Tock configuration file 52 | >_ mkdir -p ~/.config/tick 53 | >_ echo "database_path: ~/.config/tick/main.db" > "${_}/config.yaml" 54 | 55 | # Build the release. 56 | >_ cargo build --release 57 | 58 | # Install in your path. 59 | >_ cp ./target/release/tick /usr/local/bin/tick 60 | ``` 61 | 62 | ## Motivation 63 | 64 | I track my time a lot while using the terminal using a wrapper around `tmux`. 65 | The wrapper I have is [a shell script called `tux`][tux-src]. While the wrapper 66 | works great, it depends on `clocker` and `node` to handle time tracking. 67 | 68 | The main motivation around writing this was to remove the `node` and `clocker` 69 | dependencies from `tux` along with adding customizable exporting mechanisms. 70 | Tracking your time can be hard enough, so Tick tries making it a lot easier. 71 | 72 | [tux-src]: https://github.com/rogeruiz/.files/blob/master/bin/tux "`.files/bin/tux` Source" 73 | 74 | ## Commands 75 | 76 | Run `tick --help` to see all the available commands you can use. Below is an 77 | example workflow of how you would use Tick. 78 | 79 | ```sh 80 | >_ tick [ -v ] start --name my-timer [ --message "I can do the thing!" ] 81 | >_ tick [ -v ] status 82 | >_ tick [ -v ] stop --name my-timer [ --message "I did the thing!" ] 83 | >_ tick [ -v ] stop [ --message "I did the thing!" ] # without a name argument stops the latest running timer 84 | >_ tick [ -v ] list 85 | >_ tick [ -v ] remove --id $( tick list | tail -1 | awk '{ print $1 }' ) # delete the latest timer by Timer ID 86 | ``` 87 | 88 | ## Inspiration 89 | 90 | This project would not be possible without being inspired by other's work. 91 | 92 | - `clocker` - [repository][clocker-repo] 93 | - `watson` - [repository][watson-repo] 94 | 95 | [clocker-repo]: https://github.com/substack/clocker "Clocker Repository" 96 | [watson-repo]: https://github.com/TailorDev/Watson "Watson Repository" 97 | 98 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate clap; 3 | extern crate tock; 4 | 5 | use std::env; 6 | use std::process; 7 | use clap::App; 8 | 9 | /* 10 | * The main function which sets up the CLI and calls the match handlers 11 | */ 12 | fn main() { 13 | let config = load_yaml!("config.yml"); 14 | let matches = App::from_yaml(config) 15 | .about(env!("CARGO_PKG_DESCRIPTION")) 16 | .version(crate_version!()) 17 | .get_matches(); 18 | let verbosity = matches.is_present("verbose"); 19 | let connection = tock::establish_connection(); 20 | 21 | match matches.subcommand() { 22 | ("start", Some(o)) => { 23 | let n = o.value_of("name").unwrap_or(""); 24 | let e = o.value_of("entry").unwrap_or(""); 25 | 26 | if n == "" { 27 | println!("Cannot start a timer without a name"); 28 | process::exit(99); 29 | } 30 | 31 | if verbosity { 32 | println!("Starting a timer for `{}` with message \"{}\".", &n, &e); 33 | } 34 | tock::create_timer(&connection, &n, &e); 35 | if verbosity { 36 | println!("Started timer for {}", n); 37 | } 38 | } 39 | ("stop", Some(o)) => { 40 | let n = o.value_of("name").unwrap_or(""); 41 | let e = o.value_of("entry").unwrap_or(""); 42 | if verbosity { 43 | if n == "" { 44 | println!("Ending latest running timer with message \"{}\"", &e); 45 | } else { 46 | println!("Ending a timer for `{}` with message \"{}\".", &n, &e); 47 | } 48 | } 49 | 50 | tock::stop_timer(&connection, &n, &e); 51 | } 52 | ("list", _) => { 53 | let results = tock::list_timers(&connection); 54 | 55 | if verbosity { 56 | println!("Displaying {} timers", results.len()); 57 | } 58 | for timer in results { 59 | println!( 60 | "{timer_id} {start_date} [ {start_time} - {end_time} ] ( {duration} ) [ {timer_name} ]", 61 | timer_id=timer.id, 62 | start_date=tock::parse_date( timer.start_time ), 63 | start_time=tock::parse_time( timer.start_time ), 64 | end_time=tock::parse_time( timer.end_time ), 65 | duration=tock::get_duration( timer.start_time, timer.end_time ), 66 | timer_name=timer.name 67 | ); 68 | if verbosity { 69 | println!("message(s):\n{}\n{}", timer.start_entry, timer.end_entry); 70 | } 71 | } 72 | } 73 | ("status", _) => { 74 | let results = tock::check_timer(&connection); 75 | 76 | if results.len() > 0 { 77 | let timer = results.first().unwrap(); 78 | if verbosity { 79 | println!( 80 | "{timer_id} {start_date} [ {start_time} - {end_time} ] ( {duration} ) [ {timer_name} ]", 81 | timer_id=timer.id, 82 | start_date=tock::parse_date( timer.start_time ), 83 | start_time=tock::parse_time( timer.start_time ), 84 | end_time=tock::parse_time( timer.end_time ), 85 | duration=tock::get_duration( timer.start_time, timer.end_time ), 86 | timer_name=timer.name 87 | ); 88 | println!("message(s):\n{} {}", timer.start_entry, timer.end_entry); 89 | } else { 90 | println!( 91 | "elapsed time: {}", 92 | tock::get_duration(timer.start_time, timer.end_time) 93 | ); 94 | } 95 | } else { 96 | println!("No timers currently running"); 97 | process::exit(99); 98 | } 99 | } 100 | ("remove", Some(o)) => { 101 | let i: i32 = value_t!(o, "id", i32).unwrap_or(0); 102 | 103 | if i < 1 { 104 | println!("Cannot remove timers without a proper id."); 105 | process::exit(99); 106 | } 107 | 108 | if verbosity { 109 | println!("Removing timer with matching id {}", &i); 110 | } 111 | 112 | tock::remove_timer(&connection, &i); 113 | } 114 | _ => (), 115 | }; 116 | } 117 | -------------------------------------------------------------------------------- /lib/tock/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate diesel; 3 | #[macro_use] 4 | extern crate diesel_migrations; 5 | 6 | pub mod schema; 7 | pub mod models; 8 | 9 | extern crate config; 10 | extern crate shellexpand; 11 | extern crate chrono; 12 | 13 | use config::*; 14 | use chrono::prelude::*; 15 | use diesel::prelude::*; 16 | use diesel::sqlite::SqliteConnection; 17 | 18 | use models::*; 19 | use schema::timers; 20 | 21 | embed_migrations!("../../migrations"); 22 | 23 | // establish_connection returns a SqliteConnection to the 24 | // TICK_DATABASE_FILE environment variable 25 | pub fn establish_connection() -> SqliteConnection { 26 | 27 | let config_path = shellexpand::tilde("~/.config/tick/config.yaml").to_string(); 28 | 29 | let mut settings = Config::default(); 30 | 31 | settings.merge(File::with_name(&config_path)) 32 | .unwrap_or_else(|_| panic!("Error finding config file {:?}", &config_path)); 33 | 34 | let mut db_path = settings.get_str("database_path") 35 | .expect("The key `database_path` was not found in the config file."); 36 | 37 | db_path = shellexpand::tilde(&db_path).to_string(); 38 | 39 | let connection = SqliteConnection::establish(&db_path) 40 | .unwrap_or_else(|_| panic!("Error connecting to {:?}", &db_path)); 41 | 42 | // Run the migrations for the database 43 | let _ = embedded_migrations::run(&connection); 44 | 45 | // Return the SqliteConnection 46 | connection 47 | } 48 | 49 | // create_timer takes a conenction and a name and start_entry string and creates 50 | // a new timer. 51 | pub fn create_timer<'a>(conn: &SqliteConnection, name: &'a str, start_entry: &'a str) -> usize { 52 | let new_timer = NewTimer { 53 | name, 54 | start_time: Local::now().timestamp() as i32, 55 | start_entry, 56 | running: 1, 57 | }; 58 | 59 | diesel::insert_into(timers::table) 60 | .values(&new_timer) 61 | .execute(conn) 62 | .expect("Error saving new timer") 63 | } 64 | 65 | // latest_timer is a private function which gets the latest running timer by 66 | // timer_name or the latest timer by "running" being true. 67 | fn latest_timer<'a>(conn: &'a SqliteConnection, timer_name: &'a str) -> Result { 68 | use schema::timers::dsl::*; 69 | 70 | if timer_name != "" { 71 | timers.filter(name.like(&timer_name)) 72 | .filter(running.eq(1)) 73 | .first(conn) 74 | } else { 75 | timers.filter(running.eq(1)) 76 | .first(conn) 77 | } 78 | } 79 | 80 | // stop_timer takes a connection and a name and end_entry string and stops a 81 | // running timer. 82 | pub fn stop_timer<'a>(conn: &'a SqliteConnection, timer_name: &'a str, timer_end_entry: &'a str) -> () { 83 | use schema::timers::dsl::*; 84 | 85 | let timer = latest_timer(&conn, &timer_name); 86 | 87 | match timer { 88 | Ok(t) => { 89 | diesel::update(timers.find(&t.id)) 90 | .set(( 91 | running.eq(0), 92 | end_time.eq(Local::now().timestamp() as i32), 93 | end_entry.eq(&timer_end_entry) 94 | )) 95 | .execute(conn) 96 | .expect(&format!("Unable to stop timer {}", &t.id)); 97 | }, 98 | Err(_) => println!("Are you sure a timer is running? Better go catch it.") 99 | } 100 | 101 | } 102 | 103 | // list_timers takes a connection and returns ascending order timers. 104 | pub fn list_timers<'a>(conn: &'a SqliteConnection) -> Vec { 105 | use schema::timers::dsl::*; 106 | 107 | timers.order(id.asc()) 108 | .load::(conn) 109 | .expect("Error loading timers table") 110 | } 111 | 112 | // check_timer takes a connection and returns descending order running timers. 113 | pub fn check_timer<'a>(conn: &'a SqliteConnection) -> Vec { 114 | use schema::timers::dsl::*; 115 | 116 | timers.filter(running.eq(1)) 117 | .order(id.desc()) 118 | .load::(conn) 119 | .expect("Error getting running timer") 120 | } 121 | 122 | // remove_timer takes a connection and an ID and deletes the timer matching the ID. 123 | pub fn remove_timer<'a>(conn: &'a SqliteConnection, lookup_id: &'a i32) -> usize { 124 | use schema::timers::dsl::*; 125 | 126 | diesel::delete(timers.find(&lookup_id)) 127 | .execute(conn) 128 | .expect(&format!("Unable to remove timer matching id {}", &lookup_id)) 129 | } 130 | 131 | // parse_date takes a timestamp number and returns a date-formatted string. 132 | pub fn parse_date<'a>(ts: i32) -> String { 133 | let timestring = format!("{:?}", ts); 134 | let dt: DateTime = Local.datetime_from_str(×tring, "%s").unwrap(); 135 | dt.format("%Y-%m-%d").to_string() 136 | } 137 | 138 | // parse_time takes a timestamp number and returns a time-formatted string. 139 | pub fn parse_time<'a>(ts: i32) -> String { 140 | let timestring = format!("{:?}", ts); 141 | let dt: DateTime = Local.datetime_from_str(×tring, "%s").unwrap(); 142 | if ts == 0 { 143 | format!("NOW") 144 | } else { 145 | dt.format("%H:%M:%S").to_string() 146 | } 147 | } 148 | 149 | // get_duration takes a start and end timestamp number and returns the delta 150 | // between the start and end timestamp as a time-formatted string. 151 | pub fn get_duration<'a>(s: i32, e: i32) -> String { 152 | let mut now: i32 = Local::now().timestamp() as i32; 153 | if e > s { 154 | now = e; 155 | } 156 | let delta = now - s; 157 | format!( 158 | "{hours:02}:{minutes:02}:{seconds:02}", 159 | hours = delta / 60 / 60, 160 | minutes = delta / 60 % 60, 161 | seconds = delta % 60 162 | ) 163 | } 164 | 165 | -------------------------------------------------------------------------------- /lib/tock/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "aho-corasick" 5 | version = "0.7.18" 6 | source = "registry+https://github.com/rust-lang/crates.io-index" 7 | checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" 8 | dependencies = [ 9 | "memchr", 10 | ] 11 | 12 | [[package]] 13 | name = "arrayvec" 14 | version = "0.5.2" 15 | source = "registry+https://github.com/rust-lang/crates.io-index" 16 | checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" 17 | 18 | [[package]] 19 | name = "autocfg" 20 | version = "1.0.1" 21 | source = "registry+https://github.com/rust-lang/crates.io-index" 22 | checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" 23 | 24 | [[package]] 25 | name = "bitflags" 26 | version = "1.2.1" 27 | source = "registry+https://github.com/rust-lang/crates.io-index" 28 | checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" 29 | 30 | [[package]] 31 | name = "byteorder" 32 | version = "1.4.3" 33 | source = "registry+https://github.com/rust-lang/crates.io-index" 34 | checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" 35 | 36 | [[package]] 37 | name = "cfg-if" 38 | version = "1.0.0" 39 | source = "registry+https://github.com/rust-lang/crates.io-index" 40 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 41 | 42 | [[package]] 43 | name = "chrono" 44 | version = "0.3.0" 45 | source = "registry+https://github.com/rust-lang/crates.io-index" 46 | checksum = "158b0bd7d75cbb6bf9c25967a48a2e9f77da95876b858eadfabaa99cd069de6e" 47 | dependencies = [ 48 | "num", 49 | "time", 50 | ] 51 | 52 | [[package]] 53 | name = "config" 54 | version = "0.11.0" 55 | source = "registry+https://github.com/rust-lang/crates.io-index" 56 | checksum = "1b1b9d958c2b1368a663f05538fc1b5975adce1e19f435acceae987aceeeb369" 57 | dependencies = [ 58 | "lazy_static", 59 | "nom", 60 | "rust-ini", 61 | "serde 1.0.126", 62 | "serde-hjson", 63 | "serde_json", 64 | "toml", 65 | "yaml-rust", 66 | ] 67 | 68 | [[package]] 69 | name = "diesel" 70 | version = "1.4.6" 71 | source = "registry+https://github.com/rust-lang/crates.io-index" 72 | checksum = "047bfc4d5c3bd2ef6ca6f981941046113524b9a9f9a7cbdfdd7ff40f58e6f542" 73 | dependencies = [ 74 | "byteorder", 75 | "diesel_derives", 76 | "libsqlite3-sys", 77 | ] 78 | 79 | [[package]] 80 | name = "diesel_derives" 81 | version = "1.4.1" 82 | source = "registry+https://github.com/rust-lang/crates.io-index" 83 | checksum = "45f5098f628d02a7a0f68ddba586fb61e80edec3bdc1be3b921f4ceec60858d3" 84 | dependencies = [ 85 | "proc-macro2", 86 | "quote", 87 | "syn", 88 | ] 89 | 90 | [[package]] 91 | name = "diesel_migrations" 92 | version = "1.4.0" 93 | source = "registry+https://github.com/rust-lang/crates.io-index" 94 | checksum = "bf3cde8413353dc7f5d72fa8ce0b99a560a359d2c5ef1e5817ca731cd9008f4c" 95 | dependencies = [ 96 | "migrations_internals", 97 | "migrations_macros", 98 | ] 99 | 100 | [[package]] 101 | name = "dirs-next" 102 | version = "2.0.0" 103 | source = "registry+https://github.com/rust-lang/crates.io-index" 104 | checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" 105 | dependencies = [ 106 | "cfg-if", 107 | "dirs-sys-next", 108 | ] 109 | 110 | [[package]] 111 | name = "dirs-sys-next" 112 | version = "0.1.2" 113 | source = "registry+https://github.com/rust-lang/crates.io-index" 114 | checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" 115 | dependencies = [ 116 | "libc", 117 | "redox_users", 118 | "winapi", 119 | ] 120 | 121 | [[package]] 122 | name = "getrandom" 123 | version = "0.2.3" 124 | source = "registry+https://github.com/rust-lang/crates.io-index" 125 | checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" 126 | dependencies = [ 127 | "cfg-if", 128 | "libc", 129 | "wasi", 130 | ] 131 | 132 | [[package]] 133 | name = "itoa" 134 | version = "0.4.7" 135 | source = "registry+https://github.com/rust-lang/crates.io-index" 136 | checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" 137 | 138 | [[package]] 139 | name = "lazy_static" 140 | version = "1.4.0" 141 | source = "registry+https://github.com/rust-lang/crates.io-index" 142 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 143 | 144 | [[package]] 145 | name = "lexical-core" 146 | version = "0.7.6" 147 | source = "registry+https://github.com/rust-lang/crates.io-index" 148 | checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe" 149 | dependencies = [ 150 | "arrayvec", 151 | "bitflags", 152 | "cfg-if", 153 | "ryu", 154 | "static_assertions", 155 | ] 156 | 157 | [[package]] 158 | name = "libc" 159 | version = "0.2.95" 160 | source = "registry+https://github.com/rust-lang/crates.io-index" 161 | checksum = "789da6d93f1b866ffe175afc5322a4d76c038605a1c3319bb57b06967ca98a36" 162 | 163 | [[package]] 164 | name = "libsqlite3-sys" 165 | version = "0.20.1" 166 | source = "registry+https://github.com/rust-lang/crates.io-index" 167 | checksum = "64d31059f22935e6c31830db5249ba2b7ecd54fd73a9909286f0a67aa55c2fbd" 168 | dependencies = [ 169 | "pkg-config", 170 | "vcpkg", 171 | ] 172 | 173 | [[package]] 174 | name = "linked-hash-map" 175 | version = "0.5.4" 176 | source = "registry+https://github.com/rust-lang/crates.io-index" 177 | checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" 178 | 179 | [[package]] 180 | name = "memchr" 181 | version = "2.4.0" 182 | source = "registry+https://github.com/rust-lang/crates.io-index" 183 | checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" 184 | 185 | [[package]] 186 | name = "migrations_internals" 187 | version = "1.4.1" 188 | source = "registry+https://github.com/rust-lang/crates.io-index" 189 | checksum = "2b4fc84e4af020b837029e017966f86a1c2d5e83e64b589963d5047525995860" 190 | dependencies = [ 191 | "diesel", 192 | ] 193 | 194 | [[package]] 195 | name = "migrations_macros" 196 | version = "1.4.2" 197 | source = "registry+https://github.com/rust-lang/crates.io-index" 198 | checksum = "9753f12909fd8d923f75ae5c3258cae1ed3c8ec052e1b38c93c21a6d157f789c" 199 | dependencies = [ 200 | "migrations_internals", 201 | "proc-macro2", 202 | "quote", 203 | "syn", 204 | ] 205 | 206 | [[package]] 207 | name = "nom" 208 | version = "5.1.2" 209 | source = "registry+https://github.com/rust-lang/crates.io-index" 210 | checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" 211 | dependencies = [ 212 | "lexical-core", 213 | "memchr", 214 | "version_check", 215 | ] 216 | 217 | [[package]] 218 | name = "num" 219 | version = "0.1.42" 220 | source = "registry+https://github.com/rust-lang/crates.io-index" 221 | checksum = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" 222 | dependencies = [ 223 | "num-integer", 224 | "num-iter", 225 | "num-traits 0.2.14", 226 | ] 227 | 228 | [[package]] 229 | name = "num-integer" 230 | version = "0.1.44" 231 | source = "registry+https://github.com/rust-lang/crates.io-index" 232 | checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" 233 | dependencies = [ 234 | "autocfg", 235 | "num-traits 0.2.14", 236 | ] 237 | 238 | [[package]] 239 | name = "num-iter" 240 | version = "0.1.42" 241 | source = "registry+https://github.com/rust-lang/crates.io-index" 242 | checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59" 243 | dependencies = [ 244 | "autocfg", 245 | "num-integer", 246 | "num-traits 0.2.14", 247 | ] 248 | 249 | [[package]] 250 | name = "num-traits" 251 | version = "0.1.43" 252 | source = "registry+https://github.com/rust-lang/crates.io-index" 253 | checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" 254 | dependencies = [ 255 | "num-traits 0.2.14", 256 | ] 257 | 258 | [[package]] 259 | name = "num-traits" 260 | version = "0.2.14" 261 | source = "registry+https://github.com/rust-lang/crates.io-index" 262 | checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" 263 | dependencies = [ 264 | "autocfg", 265 | ] 266 | 267 | [[package]] 268 | name = "pkg-config" 269 | version = "0.3.19" 270 | source = "registry+https://github.com/rust-lang/crates.io-index" 271 | checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" 272 | 273 | [[package]] 274 | name = "proc-macro2" 275 | version = "1.0.27" 276 | source = "registry+https://github.com/rust-lang/crates.io-index" 277 | checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038" 278 | dependencies = [ 279 | "unicode-xid", 280 | ] 281 | 282 | [[package]] 283 | name = "quote" 284 | version = "1.0.9" 285 | source = "registry+https://github.com/rust-lang/crates.io-index" 286 | checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" 287 | dependencies = [ 288 | "proc-macro2", 289 | ] 290 | 291 | [[package]] 292 | name = "redox_syscall" 293 | version = "0.2.8" 294 | source = "registry+https://github.com/rust-lang/crates.io-index" 295 | checksum = "742739e41cd49414de871ea5e549afb7e2a3ac77b589bcbebe8c82fab37147fc" 296 | dependencies = [ 297 | "bitflags", 298 | ] 299 | 300 | [[package]] 301 | name = "redox_users" 302 | version = "0.4.0" 303 | source = "registry+https://github.com/rust-lang/crates.io-index" 304 | checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" 305 | dependencies = [ 306 | "getrandom", 307 | "redox_syscall", 308 | ] 309 | 310 | [[package]] 311 | name = "regex" 312 | version = "1.5.4" 313 | source = "registry+https://github.com/rust-lang/crates.io-index" 314 | checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" 315 | dependencies = [ 316 | "aho-corasick", 317 | "memchr", 318 | "regex-syntax", 319 | ] 320 | 321 | [[package]] 322 | name = "regex-syntax" 323 | version = "0.6.25" 324 | source = "registry+https://github.com/rust-lang/crates.io-index" 325 | checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" 326 | 327 | [[package]] 328 | name = "rust-ini" 329 | version = "0.13.0" 330 | source = "registry+https://github.com/rust-lang/crates.io-index" 331 | checksum = "3e52c148ef37f8c375d49d5a73aa70713125b7f19095948a923f80afdeb22ec2" 332 | 333 | [[package]] 334 | name = "ryu" 335 | version = "1.0.5" 336 | source = "registry+https://github.com/rust-lang/crates.io-index" 337 | checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" 338 | 339 | [[package]] 340 | name = "serde" 341 | version = "0.8.23" 342 | source = "registry+https://github.com/rust-lang/crates.io-index" 343 | checksum = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8" 344 | 345 | [[package]] 346 | name = "serde" 347 | version = "1.0.126" 348 | source = "registry+https://github.com/rust-lang/crates.io-index" 349 | checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03" 350 | 351 | [[package]] 352 | name = "serde-hjson" 353 | version = "0.9.1" 354 | source = "registry+https://github.com/rust-lang/crates.io-index" 355 | checksum = "6a3a4e0ea8a88553209f6cc6cfe8724ecad22e1acf372793c27d995290fe74f8" 356 | dependencies = [ 357 | "lazy_static", 358 | "num-traits 0.1.43", 359 | "regex", 360 | "serde 0.8.23", 361 | ] 362 | 363 | [[package]] 364 | name = "serde_json" 365 | version = "1.0.64" 366 | source = "registry+https://github.com/rust-lang/crates.io-index" 367 | checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79" 368 | dependencies = [ 369 | "itoa", 370 | "ryu", 371 | "serde 1.0.126", 372 | ] 373 | 374 | [[package]] 375 | name = "shellexpand" 376 | version = "2.1.0" 377 | source = "registry+https://github.com/rust-lang/crates.io-index" 378 | checksum = "83bdb7831b2d85ddf4a7b148aa19d0587eddbe8671a436b7bd1182eaad0f2829" 379 | dependencies = [ 380 | "dirs-next", 381 | ] 382 | 383 | [[package]] 384 | name = "static_assertions" 385 | version = "1.1.0" 386 | source = "registry+https://github.com/rust-lang/crates.io-index" 387 | checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" 388 | 389 | [[package]] 390 | name = "syn" 391 | version = "1.0.72" 392 | source = "registry+https://github.com/rust-lang/crates.io-index" 393 | checksum = "a1e8cdbefb79a9a5a65e0db8b47b723ee907b7c7f8496c76a1770b5c310bab82" 394 | dependencies = [ 395 | "proc-macro2", 396 | "quote", 397 | "unicode-xid", 398 | ] 399 | 400 | [[package]] 401 | name = "time" 402 | version = "0.1.43" 403 | source = "registry+https://github.com/rust-lang/crates.io-index" 404 | checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" 405 | dependencies = [ 406 | "libc", 407 | "winapi", 408 | ] 409 | 410 | [[package]] 411 | name = "tock" 412 | version = "1.0.0" 413 | dependencies = [ 414 | "chrono", 415 | "config", 416 | "diesel", 417 | "diesel_migrations", 418 | "shellexpand", 419 | ] 420 | 421 | [[package]] 422 | name = "toml" 423 | version = "0.5.8" 424 | source = "registry+https://github.com/rust-lang/crates.io-index" 425 | checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" 426 | dependencies = [ 427 | "serde 1.0.126", 428 | ] 429 | 430 | [[package]] 431 | name = "unicode-xid" 432 | version = "0.2.2" 433 | source = "registry+https://github.com/rust-lang/crates.io-index" 434 | checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" 435 | 436 | [[package]] 437 | name = "vcpkg" 438 | version = "0.2.13" 439 | source = "registry+https://github.com/rust-lang/crates.io-index" 440 | checksum = "025ce40a007e1907e58d5bc1a594def78e5573bb0b1160bc389634e8f12e4faa" 441 | 442 | [[package]] 443 | name = "version_check" 444 | version = "0.9.3" 445 | source = "registry+https://github.com/rust-lang/crates.io-index" 446 | checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" 447 | 448 | [[package]] 449 | name = "wasi" 450 | version = "0.10.2+wasi-snapshot-preview1" 451 | source = "registry+https://github.com/rust-lang/crates.io-index" 452 | checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" 453 | 454 | [[package]] 455 | name = "winapi" 456 | version = "0.3.9" 457 | source = "registry+https://github.com/rust-lang/crates.io-index" 458 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 459 | dependencies = [ 460 | "winapi-i686-pc-windows-gnu", 461 | "winapi-x86_64-pc-windows-gnu", 462 | ] 463 | 464 | [[package]] 465 | name = "winapi-i686-pc-windows-gnu" 466 | version = "0.4.0" 467 | source = "registry+https://github.com/rust-lang/crates.io-index" 468 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 469 | 470 | [[package]] 471 | name = "winapi-x86_64-pc-windows-gnu" 472 | version = "0.4.0" 473 | source = "registry+https://github.com/rust-lang/crates.io-index" 474 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 475 | 476 | [[package]] 477 | name = "yaml-rust" 478 | version = "0.4.5" 479 | source = "registry+https://github.com/rust-lang/crates.io-index" 480 | checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" 481 | dependencies = [ 482 | "linked-hash-map", 483 | ] 484 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "aho-corasick" 5 | version = "0.7.18" 6 | source = "registry+https://github.com/rust-lang/crates.io-index" 7 | checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" 8 | dependencies = [ 9 | "memchr", 10 | ] 11 | 12 | [[package]] 13 | name = "ansi_term" 14 | version = "0.11.0" 15 | source = "registry+https://github.com/rust-lang/crates.io-index" 16 | checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" 17 | dependencies = [ 18 | "winapi", 19 | ] 20 | 21 | [[package]] 22 | name = "arrayvec" 23 | version = "0.5.2" 24 | source = "registry+https://github.com/rust-lang/crates.io-index" 25 | checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" 26 | 27 | [[package]] 28 | name = "atty" 29 | version = "0.2.14" 30 | source = "registry+https://github.com/rust-lang/crates.io-index" 31 | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" 32 | dependencies = [ 33 | "hermit-abi", 34 | "libc", 35 | "winapi", 36 | ] 37 | 38 | [[package]] 39 | name = "autocfg" 40 | version = "1.0.1" 41 | source = "registry+https://github.com/rust-lang/crates.io-index" 42 | checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" 43 | 44 | [[package]] 45 | name = "bitflags" 46 | version = "1.2.1" 47 | source = "registry+https://github.com/rust-lang/crates.io-index" 48 | checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" 49 | 50 | [[package]] 51 | name = "byteorder" 52 | version = "1.4.3" 53 | source = "registry+https://github.com/rust-lang/crates.io-index" 54 | checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" 55 | 56 | [[package]] 57 | name = "cfg-if" 58 | version = "1.0.0" 59 | source = "registry+https://github.com/rust-lang/crates.io-index" 60 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 61 | 62 | [[package]] 63 | name = "chrono" 64 | version = "0.3.0" 65 | source = "registry+https://github.com/rust-lang/crates.io-index" 66 | checksum = "158b0bd7d75cbb6bf9c25967a48a2e9f77da95876b858eadfabaa99cd069de6e" 67 | dependencies = [ 68 | "num", 69 | "time", 70 | ] 71 | 72 | [[package]] 73 | name = "clap" 74 | version = "2.33.3" 75 | source = "registry+https://github.com/rust-lang/crates.io-index" 76 | checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" 77 | dependencies = [ 78 | "ansi_term", 79 | "atty", 80 | "bitflags", 81 | "strsim", 82 | "term_size", 83 | "textwrap", 84 | "unicode-width", 85 | "vec_map", 86 | "yaml-rust 0.3.5", 87 | ] 88 | 89 | [[package]] 90 | name = "config" 91 | version = "0.11.0" 92 | source = "registry+https://github.com/rust-lang/crates.io-index" 93 | checksum = "1b1b9d958c2b1368a663f05538fc1b5975adce1e19f435acceae987aceeeb369" 94 | dependencies = [ 95 | "lazy_static", 96 | "nom", 97 | "rust-ini", 98 | "serde 1.0.126", 99 | "serde-hjson", 100 | "serde_json", 101 | "toml", 102 | "yaml-rust 0.4.5", 103 | ] 104 | 105 | [[package]] 106 | name = "diesel" 107 | version = "1.4.6" 108 | source = "registry+https://github.com/rust-lang/crates.io-index" 109 | checksum = "047bfc4d5c3bd2ef6ca6f981941046113524b9a9f9a7cbdfdd7ff40f58e6f542" 110 | dependencies = [ 111 | "byteorder", 112 | "diesel_derives", 113 | "libsqlite3-sys", 114 | ] 115 | 116 | [[package]] 117 | name = "diesel_derives" 118 | version = "1.4.1" 119 | source = "registry+https://github.com/rust-lang/crates.io-index" 120 | checksum = "45f5098f628d02a7a0f68ddba586fb61e80edec3bdc1be3b921f4ceec60858d3" 121 | dependencies = [ 122 | "proc-macro2", 123 | "quote", 124 | "syn", 125 | ] 126 | 127 | [[package]] 128 | name = "diesel_migrations" 129 | version = "1.4.0" 130 | source = "registry+https://github.com/rust-lang/crates.io-index" 131 | checksum = "bf3cde8413353dc7f5d72fa8ce0b99a560a359d2c5ef1e5817ca731cd9008f4c" 132 | dependencies = [ 133 | "migrations_internals", 134 | "migrations_macros", 135 | ] 136 | 137 | [[package]] 138 | name = "dirs-next" 139 | version = "2.0.0" 140 | source = "registry+https://github.com/rust-lang/crates.io-index" 141 | checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" 142 | dependencies = [ 143 | "cfg-if", 144 | "dirs-sys-next", 145 | ] 146 | 147 | [[package]] 148 | name = "dirs-sys-next" 149 | version = "0.1.2" 150 | source = "registry+https://github.com/rust-lang/crates.io-index" 151 | checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" 152 | dependencies = [ 153 | "libc", 154 | "redox_users", 155 | "winapi", 156 | ] 157 | 158 | [[package]] 159 | name = "getrandom" 160 | version = "0.2.3" 161 | source = "registry+https://github.com/rust-lang/crates.io-index" 162 | checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" 163 | dependencies = [ 164 | "cfg-if", 165 | "libc", 166 | "wasi", 167 | ] 168 | 169 | [[package]] 170 | name = "hermit-abi" 171 | version = "0.1.18" 172 | source = "registry+https://github.com/rust-lang/crates.io-index" 173 | checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" 174 | dependencies = [ 175 | "libc", 176 | ] 177 | 178 | [[package]] 179 | name = "itoa" 180 | version = "0.4.7" 181 | source = "registry+https://github.com/rust-lang/crates.io-index" 182 | checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" 183 | 184 | [[package]] 185 | name = "lazy_static" 186 | version = "1.4.0" 187 | source = "registry+https://github.com/rust-lang/crates.io-index" 188 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 189 | 190 | [[package]] 191 | name = "lexical-core" 192 | version = "0.7.6" 193 | source = "registry+https://github.com/rust-lang/crates.io-index" 194 | checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe" 195 | dependencies = [ 196 | "arrayvec", 197 | "bitflags", 198 | "cfg-if", 199 | "ryu", 200 | "static_assertions", 201 | ] 202 | 203 | [[package]] 204 | name = "libc" 205 | version = "0.2.95" 206 | source = "registry+https://github.com/rust-lang/crates.io-index" 207 | checksum = "789da6d93f1b866ffe175afc5322a4d76c038605a1c3319bb57b06967ca98a36" 208 | 209 | [[package]] 210 | name = "libsqlite3-sys" 211 | version = "0.20.1" 212 | source = "registry+https://github.com/rust-lang/crates.io-index" 213 | checksum = "64d31059f22935e6c31830db5249ba2b7ecd54fd73a9909286f0a67aa55c2fbd" 214 | dependencies = [ 215 | "pkg-config", 216 | "vcpkg", 217 | ] 218 | 219 | [[package]] 220 | name = "linked-hash-map" 221 | version = "0.5.4" 222 | source = "registry+https://github.com/rust-lang/crates.io-index" 223 | checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" 224 | 225 | [[package]] 226 | name = "memchr" 227 | version = "2.4.0" 228 | source = "registry+https://github.com/rust-lang/crates.io-index" 229 | checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" 230 | 231 | [[package]] 232 | name = "migrations_internals" 233 | version = "1.4.1" 234 | source = "registry+https://github.com/rust-lang/crates.io-index" 235 | checksum = "2b4fc84e4af020b837029e017966f86a1c2d5e83e64b589963d5047525995860" 236 | dependencies = [ 237 | "diesel", 238 | ] 239 | 240 | [[package]] 241 | name = "migrations_macros" 242 | version = "1.4.2" 243 | source = "registry+https://github.com/rust-lang/crates.io-index" 244 | checksum = "9753f12909fd8d923f75ae5c3258cae1ed3c8ec052e1b38c93c21a6d157f789c" 245 | dependencies = [ 246 | "migrations_internals", 247 | "proc-macro2", 248 | "quote", 249 | "syn", 250 | ] 251 | 252 | [[package]] 253 | name = "nom" 254 | version = "5.1.2" 255 | source = "registry+https://github.com/rust-lang/crates.io-index" 256 | checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" 257 | dependencies = [ 258 | "lexical-core", 259 | "memchr", 260 | "version_check", 261 | ] 262 | 263 | [[package]] 264 | name = "num" 265 | version = "0.1.42" 266 | source = "registry+https://github.com/rust-lang/crates.io-index" 267 | checksum = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" 268 | dependencies = [ 269 | "num-integer", 270 | "num-iter", 271 | "num-traits 0.2.14", 272 | ] 273 | 274 | [[package]] 275 | name = "num-integer" 276 | version = "0.1.44" 277 | source = "registry+https://github.com/rust-lang/crates.io-index" 278 | checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" 279 | dependencies = [ 280 | "autocfg", 281 | "num-traits 0.2.14", 282 | ] 283 | 284 | [[package]] 285 | name = "num-iter" 286 | version = "0.1.42" 287 | source = "registry+https://github.com/rust-lang/crates.io-index" 288 | checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59" 289 | dependencies = [ 290 | "autocfg", 291 | "num-integer", 292 | "num-traits 0.2.14", 293 | ] 294 | 295 | [[package]] 296 | name = "num-traits" 297 | version = "0.1.43" 298 | source = "registry+https://github.com/rust-lang/crates.io-index" 299 | checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" 300 | dependencies = [ 301 | "num-traits 0.2.14", 302 | ] 303 | 304 | [[package]] 305 | name = "num-traits" 306 | version = "0.2.14" 307 | source = "registry+https://github.com/rust-lang/crates.io-index" 308 | checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" 309 | dependencies = [ 310 | "autocfg", 311 | ] 312 | 313 | [[package]] 314 | name = "pkg-config" 315 | version = "0.3.19" 316 | source = "registry+https://github.com/rust-lang/crates.io-index" 317 | checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" 318 | 319 | [[package]] 320 | name = "proc-macro2" 321 | version = "1.0.27" 322 | source = "registry+https://github.com/rust-lang/crates.io-index" 323 | checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038" 324 | dependencies = [ 325 | "unicode-xid", 326 | ] 327 | 328 | [[package]] 329 | name = "quote" 330 | version = "1.0.9" 331 | source = "registry+https://github.com/rust-lang/crates.io-index" 332 | checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" 333 | dependencies = [ 334 | "proc-macro2", 335 | ] 336 | 337 | [[package]] 338 | name = "redox_syscall" 339 | version = "0.2.8" 340 | source = "registry+https://github.com/rust-lang/crates.io-index" 341 | checksum = "742739e41cd49414de871ea5e549afb7e2a3ac77b589bcbebe8c82fab37147fc" 342 | dependencies = [ 343 | "bitflags", 344 | ] 345 | 346 | [[package]] 347 | name = "redox_users" 348 | version = "0.4.0" 349 | source = "registry+https://github.com/rust-lang/crates.io-index" 350 | checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" 351 | dependencies = [ 352 | "getrandom", 353 | "redox_syscall", 354 | ] 355 | 356 | [[package]] 357 | name = "regex" 358 | version = "1.5.4" 359 | source = "registry+https://github.com/rust-lang/crates.io-index" 360 | checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" 361 | dependencies = [ 362 | "aho-corasick", 363 | "memchr", 364 | "regex-syntax", 365 | ] 366 | 367 | [[package]] 368 | name = "regex-syntax" 369 | version = "0.6.25" 370 | source = "registry+https://github.com/rust-lang/crates.io-index" 371 | checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" 372 | 373 | [[package]] 374 | name = "rust-ini" 375 | version = "0.13.0" 376 | source = "registry+https://github.com/rust-lang/crates.io-index" 377 | checksum = "3e52c148ef37f8c375d49d5a73aa70713125b7f19095948a923f80afdeb22ec2" 378 | 379 | [[package]] 380 | name = "ryu" 381 | version = "1.0.5" 382 | source = "registry+https://github.com/rust-lang/crates.io-index" 383 | checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" 384 | 385 | [[package]] 386 | name = "serde" 387 | version = "0.8.23" 388 | source = "registry+https://github.com/rust-lang/crates.io-index" 389 | checksum = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8" 390 | 391 | [[package]] 392 | name = "serde" 393 | version = "1.0.126" 394 | source = "registry+https://github.com/rust-lang/crates.io-index" 395 | checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03" 396 | 397 | [[package]] 398 | name = "serde-hjson" 399 | version = "0.9.1" 400 | source = "registry+https://github.com/rust-lang/crates.io-index" 401 | checksum = "6a3a4e0ea8a88553209f6cc6cfe8724ecad22e1acf372793c27d995290fe74f8" 402 | dependencies = [ 403 | "lazy_static", 404 | "num-traits 0.1.43", 405 | "regex", 406 | "serde 0.8.23", 407 | ] 408 | 409 | [[package]] 410 | name = "serde_json" 411 | version = "1.0.64" 412 | source = "registry+https://github.com/rust-lang/crates.io-index" 413 | checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79" 414 | dependencies = [ 415 | "itoa", 416 | "ryu", 417 | "serde 1.0.126", 418 | ] 419 | 420 | [[package]] 421 | name = "shellexpand" 422 | version = "2.1.0" 423 | source = "registry+https://github.com/rust-lang/crates.io-index" 424 | checksum = "83bdb7831b2d85ddf4a7b148aa19d0587eddbe8671a436b7bd1182eaad0f2829" 425 | dependencies = [ 426 | "dirs-next", 427 | ] 428 | 429 | [[package]] 430 | name = "static_assertions" 431 | version = "1.1.0" 432 | source = "registry+https://github.com/rust-lang/crates.io-index" 433 | checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" 434 | 435 | [[package]] 436 | name = "strsim" 437 | version = "0.8.0" 438 | source = "registry+https://github.com/rust-lang/crates.io-index" 439 | checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" 440 | 441 | [[package]] 442 | name = "syn" 443 | version = "1.0.72" 444 | source = "registry+https://github.com/rust-lang/crates.io-index" 445 | checksum = "a1e8cdbefb79a9a5a65e0db8b47b723ee907b7c7f8496c76a1770b5c310bab82" 446 | dependencies = [ 447 | "proc-macro2", 448 | "quote", 449 | "unicode-xid", 450 | ] 451 | 452 | [[package]] 453 | name = "term_size" 454 | version = "0.3.2" 455 | source = "registry+https://github.com/rust-lang/crates.io-index" 456 | checksum = "1e4129646ca0ed8f45d09b929036bafad5377103edd06e50bf574b353d2b08d9" 457 | dependencies = [ 458 | "libc", 459 | "winapi", 460 | ] 461 | 462 | [[package]] 463 | name = "textwrap" 464 | version = "0.11.0" 465 | source = "registry+https://github.com/rust-lang/crates.io-index" 466 | checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" 467 | dependencies = [ 468 | "term_size", 469 | "unicode-width", 470 | ] 471 | 472 | [[package]] 473 | name = "tick" 474 | version = "1.0.0" 475 | dependencies = [ 476 | "clap", 477 | "tock", 478 | ] 479 | 480 | [[package]] 481 | name = "time" 482 | version = "0.1.44" 483 | source = "registry+https://github.com/rust-lang/crates.io-index" 484 | checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" 485 | dependencies = [ 486 | "libc", 487 | "wasi", 488 | "winapi", 489 | ] 490 | 491 | [[package]] 492 | name = "tock" 493 | version = "1.0.0" 494 | dependencies = [ 495 | "chrono", 496 | "config", 497 | "diesel", 498 | "diesel_migrations", 499 | "shellexpand", 500 | ] 501 | 502 | [[package]] 503 | name = "toml" 504 | version = "0.5.8" 505 | source = "registry+https://github.com/rust-lang/crates.io-index" 506 | checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" 507 | dependencies = [ 508 | "serde 1.0.126", 509 | ] 510 | 511 | [[package]] 512 | name = "unicode-width" 513 | version = "0.1.8" 514 | source = "registry+https://github.com/rust-lang/crates.io-index" 515 | checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" 516 | 517 | [[package]] 518 | name = "unicode-xid" 519 | version = "0.2.2" 520 | source = "registry+https://github.com/rust-lang/crates.io-index" 521 | checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" 522 | 523 | [[package]] 524 | name = "vcpkg" 525 | version = "0.2.13" 526 | source = "registry+https://github.com/rust-lang/crates.io-index" 527 | checksum = "025ce40a007e1907e58d5bc1a594def78e5573bb0b1160bc389634e8f12e4faa" 528 | 529 | [[package]] 530 | name = "vec_map" 531 | version = "0.8.2" 532 | source = "registry+https://github.com/rust-lang/crates.io-index" 533 | checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" 534 | 535 | [[package]] 536 | name = "version_check" 537 | version = "0.9.3" 538 | source = "registry+https://github.com/rust-lang/crates.io-index" 539 | checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" 540 | 541 | [[package]] 542 | name = "wasi" 543 | version = "0.10.0+wasi-snapshot-preview1" 544 | source = "registry+https://github.com/rust-lang/crates.io-index" 545 | checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" 546 | 547 | [[package]] 548 | name = "winapi" 549 | version = "0.3.9" 550 | source = "registry+https://github.com/rust-lang/crates.io-index" 551 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 552 | dependencies = [ 553 | "winapi-i686-pc-windows-gnu", 554 | "winapi-x86_64-pc-windows-gnu", 555 | ] 556 | 557 | [[package]] 558 | name = "winapi-i686-pc-windows-gnu" 559 | version = "0.4.0" 560 | source = "registry+https://github.com/rust-lang/crates.io-index" 561 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 562 | 563 | [[package]] 564 | name = "winapi-x86_64-pc-windows-gnu" 565 | version = "0.4.0" 566 | source = "registry+https://github.com/rust-lang/crates.io-index" 567 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 568 | 569 | [[package]] 570 | name = "yaml-rust" 571 | version = "0.3.5" 572 | source = "registry+https://github.com/rust-lang/crates.io-index" 573 | checksum = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992" 574 | 575 | [[package]] 576 | name = "yaml-rust" 577 | version = "0.4.5" 578 | source = "registry+https://github.com/rust-lang/crates.io-index" 579 | checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" 580 | dependencies = [ 581 | "linked-hash-map", 582 | ] 583 | --------------------------------------------------------------------------------