133 lines
4.1 KiB
Rust
133 lines
4.1 KiB
Rust
use std::io::Write;
|
|
use std::convert::TryFrom;
|
|
|
|
use chrono::{DateTime, Utc};
|
|
use clap::ArgMatches;
|
|
|
|
use crate::database::Database;
|
|
use crate::config::Config;
|
|
use crate::error::{Error, Result};
|
|
use crate::timeparse::parse_time;
|
|
use crate::old::{time_or_warning, warn_if_needed};
|
|
|
|
use super::Command;
|
|
|
|
#[derive(Default)]
|
|
pub struct Args {
|
|
at: Option<DateTime<Utc>>,
|
|
}
|
|
|
|
impl<'a> TryFrom<&'a ArgMatches<'a>> for Args {
|
|
type Error = Error;
|
|
|
|
fn try_from(matches: &'a ArgMatches) -> Result<Args> {
|
|
Ok(Args {
|
|
at: matches.value_of("at").map(|s| parse_time(s)).transpose()?,
|
|
})
|
|
}
|
|
}
|
|
|
|
pub struct OutCommand{}
|
|
|
|
impl<'a> Command<'a> for OutCommand {
|
|
type Args = Args;
|
|
|
|
fn handle<D: Database, O: Write, E: Write>(args: Self::Args, db: &mut D, out: &mut O, err: &mut E, _config: &Config, now: DateTime<Utc>) -> Result<()> {
|
|
let end = args.at.unwrap_or(now);
|
|
let sheet = db.current_sheet()?.unwrap_or("default".into());
|
|
|
|
let (end, needs_warning) = time_or_warning(end, db)?;
|
|
|
|
if let Some(entry) = db.running_entry(&sheet)? {
|
|
writeln!(out, "Checked out of sheet \"{}\".", sheet)?;
|
|
|
|
db.entry_update(entry.id, entry.start, Some(end), entry.note, &entry.sheet)?;
|
|
db.set_last_checkout_id(entry.id)?;
|
|
} else {
|
|
writeln!(out, "No running entry on sheet \"{}\".", sheet)?;
|
|
}
|
|
|
|
warn_if_needed(err, needs_warning)?;
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use ansi_term::Color::Yellow;
|
|
use pretty_assertions::assert_eq;
|
|
use chrono::{TimeZone, Local};
|
|
|
|
use crate::test_utils::PrettyString;
|
|
use crate::database::SqliteDatabase;
|
|
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn finishes_entry() {
|
|
let mut db = SqliteDatabase::from_memory().unwrap();
|
|
let args = Default::default();
|
|
let mut out = Vec::new();
|
|
let mut err = Vec::new();
|
|
let now = Utc::now();
|
|
|
|
db.init().unwrap();
|
|
|
|
db.entry_insert(now, None, None, "default").unwrap();
|
|
|
|
OutCommand::handle(args, &mut db, &mut out, &mut err, &Default::default(), now).unwrap();
|
|
|
|
let e = db.entries_full(None, None).unwrap().into_iter().next().unwrap();
|
|
|
|
assert_eq!(e.end, Some(now));
|
|
|
|
assert_eq!(PrettyString(&String::from_utf8_lossy(&out)), PrettyString("Checked out of sheet \"default\".\n"));
|
|
assert_eq!(PrettyString(&String::from_utf8_lossy(&err)), PrettyString(""));
|
|
assert_eq!(db.last_checkout_id().unwrap().unwrap(), 1);
|
|
}
|
|
|
|
#[test]
|
|
fn tells_if_no_running_entry() {
|
|
let mut db = SqliteDatabase::from_memory().unwrap();
|
|
let args = Default::default();
|
|
let mut out = Vec::new();
|
|
let mut err = Vec::new();
|
|
let now = Utc::now();
|
|
|
|
db.init().unwrap();
|
|
|
|
db.entry_insert(now, None, None, "non-default").unwrap();
|
|
|
|
OutCommand::handle(args, &mut db, &mut out, &mut err, &Default::default(), now).unwrap();
|
|
|
|
assert_eq!(PrettyString(&String::from_utf8_lossy(&out)), PrettyString("No running entry on sheet \"default\".\n"));
|
|
assert_eq!(PrettyString(&String::from_utf8_lossy(&err)), PrettyString(""));
|
|
}
|
|
|
|
#[test]
|
|
fn warns_if_old_database() {
|
|
let mut db = SqliteDatabase::from_memory().unwrap();
|
|
let args = Default::default();
|
|
let mut out = Vec::new();
|
|
let mut err = Vec::new();
|
|
let now = Utc::now();
|
|
|
|
db.init_old().unwrap();
|
|
|
|
db.entry_insert(now, None, None, "default").unwrap();
|
|
|
|
OutCommand::handle(args, &mut db, &mut out, &mut err, &Default::default(), now).unwrap();
|
|
|
|
let e = db.entries_full(None, None).unwrap().into_iter().next().unwrap();
|
|
|
|
assert_eq!(e.end, Some(Utc.from_utc_datetime(&now.with_timezone(&Local).naive_local())));
|
|
|
|
assert_eq!(PrettyString(&String::from_utf8_lossy(&out)), PrettyString("Checked out of sheet \"default\".\n"));
|
|
assert_eq!(PrettyString(&String::from_utf8_lossy(&err)), PrettyString(&format!(
|
|
"{} You are using the old timetrap format, it is advised that \
|
|
you update your database using t migrate\n",
|
|
Yellow.bold().paint("[WARNING]"))));
|
|
}
|
|
}
|