From a5dc0cd3858a1392984ee70f7d87872522629c55 Mon Sep 17 00:00:00 2001 From: Thomas Lauf Date: Thu, 6 Apr 2017 22:46:52 +0200 Subject: [PATCH] TI-27: Continue tracking by ID - Make command 'continue' process ids - Fix test: immediate start stop creates empty intervals? --- ChangeLog | 2 + src/commands/CmdContinue.cpp | 72 +++++++++++++++++++++++++++++++----- test/continue.t | 17 +++++---- 3 files changed, 73 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3ac55515..c3eb1a6d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,6 +4,8 @@ (Thanks to Jörg Krause, Ben Boeckel). - TW-1845 Cygwin build fails, missing get_current_dir_name (thanks to hosaka). +- TI-27 Continue tracking by ID + (thanks to Dennis Schubert) - TI-29 timew config can't add new value (thanks to Yury Vidineev) - TI-32 taskwarrior hook script doesn't stop recording waiting task diff --git a/src/commands/CmdContinue.cpp b/src/commands/CmdContinue.cpp index 754d40b2..cf494752 100644 --- a/src/commands/CmdContinue.cpp +++ b/src/commands/CmdContinue.cpp @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -35,20 +36,71 @@ int CmdContinue ( Rules& rules, Database& database) { - auto latest = getLatestInterval (database); - if (latest.empty ()) - throw std::string ("There is no previous tracking to continue."); + // Gather IDs and TAGs. + std::vector ids; - if (latest.range.is_open ()) - throw std::string ("There is already active tracking."); + for (auto& arg : cli._args) + { + if (arg.hasTag ("ID")) + ids.push_back (strtol (arg.attribute ("value").c_str (), NULL, 10)); + } - // Open an identical interval and update hte DB. - latest.range.open (); - validate (cli, rules, database, latest); - database.addInterval (latest); + if (ids.size() > 1) + throw std::string ("You can only specify one ID to continue."); + + Interval to_copy; + Interval latest = getLatestInterval (database); + + if (ids.size() == 1) + { + // Load the data. + // Note: There is no filter. + Interval filter; + auto tracked = getTracked (database, rules, filter); + + if (ids[0] > static_cast (tracked.size ())) + throw format ("ID '@{1}' does not correspond to any tracking.", ids[0]); + + to_copy = tracked[tracked.size () - ids[0]]; + } + else + { + if (latest.empty ()) + throw std::string ("There is no previous tracking to continue."); + + if (latest.range.is_open ()) + throw std::string ("There is already active tracking."); + + to_copy = latest; + } + + Datetime current_time = Datetime (); + + if (latest.range.is_open()) { + auto filter = getFilter (cli); + auto exclusions = getAllExclusions (rules, filter.range); + + // Stop it, at the given start time, if applicable. + Interval modified {latest}; + modified.range.end = current_time; + + // Update database. + database.deleteInterval (latest); + for (auto& interval : flatten (modified, exclusions)) { + database.addInterval (interval); + + if (rules.getBoolean ("verbose")) + std::cout << '\n' << intervalSummarize (database, rules, interval); + } + } + + // Open an identical interval and update the DB. + to_copy.range.open (current_time); + validate (cli, rules, database, to_copy); + database.addInterval (to_copy); if (rules.getBoolean ("verbose")) - std::cout << intervalSummarize (database, rules, latest); + std::cout << intervalSummarize (database, rules, to_copy); return 0; } diff --git a/test/continue.t b/test/continue.t index e59d632b..0401f78a 100755 --- a/test/continue.t +++ b/test/continue.t @@ -92,16 +92,16 @@ class TestContinue(TestCase): def test_continue_with_id_without_active_tracking(self): """Verify that continuing a specified interval works""" - code, out, err = self.t("start FOO") + code, out, err = self.t("start FOO 1h ago") self.assertIn("Tracking FOO\n", out) - code, out, err = self.t("stop") + code, out, err = self.t("stop 30min ago") self.assertIn("Recorded FOO\n", out) - code, out, err = self.t("start BAR") + code, out, err = self.t("start BAR 30min ago") self.assertIn("Tracking BAR\n", out) - code, out, err = self.t("stop") + code, out, err = self.t("stop 15min ago") self.assertIn("Recorded BAR\n", out) code, out, err = self.t("continue @2") @@ -109,17 +109,18 @@ class TestContinue(TestCase): def test_continue_with_id_with_active_tracking(self): """Verify that continuing a specified interval stops active tracking""" - code, out, err = self.t("start FOO") + code, out, err = self.t("start FOO 1h ago") self.assertIn("Tracking FOO\n", out) - code, out, err = self.t("stop") + code, out, err = self.t("stop 30min ago") self.assertIn("Recorded FOO\n", out) - code, out, err = self.t("start BAR") + code, out, err = self.t("start BAR 30min ago") self.assertIn("Tracking BAR\n", out) code, out, err = self.t("continue @2") - self.assertIn("Recorded BAR\nTracking FOO\n", out) + self.assertIn("Recorded BAR\n", out) + self.assertIn("Tracking FOO\n", out) if __name__ == "__main__": from simpletap import TAPTestRunner