From 9d6067e2fe35cdab4289b56eb14e593c8539099e Mon Sep 17 00:00:00 2001 From: Wilhelm Schuermann Date: Fri, 29 May 2015 19:49:54 +0200 Subject: [PATCH] TW-303: Make "task import" update existing tasks --- AUTHORS | 2 +- ChangeLog | 3 +++ doc/man/task.1.in | 11 +++++++---- src/commands/CmdImport.cpp | 17 ++++++++++++++--- test/import.t | 6 +----- test/import.yaml.t | 6 +----- test/{import_stdin.t => import_NEW.t} | 24 +++++++++++++++++++++++- 7 files changed, 50 insertions(+), 19 deletions(-) rename test/{import_stdin.t => import_NEW.t} (65%) diff --git a/AUTHORS b/AUTHORS index 2b1fb2e9d..422cd1341 100644 --- a/AUTHORS +++ b/AUTHORS @@ -213,7 +213,7 @@ suggestions: Dmitriy Matrosov Michele Santullo Scott Kroll - Kosta H + Kosta Harlan Hector Arciga Jan Kunder jck diff --git a/ChangeLog b/ChangeLog index 6e0a6e574..45085fb36 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,8 +1,11 @@ 2.4.5 () - +- TW-303 Ability for "import" to update existing tasks (thanks to Kosta +Harlan). - TW-1440 "task import" from STDIN (thanks to Renato Alves). - TW-1432 start/stop can be issued on completed tasks (thanks to Renato Alves). - TW-1572 Better urgency inheritance (thanks to Jens Erat). +- Prevent potential task duplication during import for non-pending tasks. ------ current release --------------------------- diff --git a/doc/man/task.1.in b/doc/man/task.1.in index 5ef0bd27a..1194e5914 100644 --- a/doc/man/task.1.in +++ b/doc/man/task.1.in @@ -346,14 +346,17 @@ provided for exceptional circumstances. Use carefully. .TP .B task import [ ...] -Imports tasks in the JSON format. The standard task release comes with a few -example scripts, such as: +Imports tasks in the JSON format. Can be used to add new tasks, or update +existing ones. Tasks are identified by their UUID. + +If no file or "-" is specified, import tasks from STDIN. + +For importing other file formats, the standard task release comes with a +few example scripts, such as: import-todo.sh.pl import-yaml.pl -If no file or "-" is specified, import tasks from STDIN. - .TP .B task log Adds a new task that is already completed, to the task list. diff --git a/src/commands/CmdImport.cpp b/src/commands/CmdImport.cpp index de6e71a58..d466ee65a 100644 --- a/src/commands/CmdImport.cpp +++ b/src/commands/CmdImport.cpp @@ -110,11 +110,22 @@ int CmdImport::import (std::vector & lines) // Parse the whole thing. Task task (object); - context.tdb2.add (task); + + // Check whether the imported task is new or a modified existing task. + Task dummy; + if (context.tdb2.get (task.get ("uuid"), dummy)) + { + context.tdb2.modify (task); + std::cout << " mod "; + } + else + { + context.tdb2.add (task); + std::cout << " add "; + } ++count; - std::cout << " " - << task.get ("uuid") + std::cout << task.get ("uuid") << " " << task.get ("description") << "\n"; diff --git a/test/import.t b/test/import.t index 536aa4e26..bf6087161 100755 --- a/test/import.t +++ b/test/import.t @@ -27,7 +27,7 @@ use strict; use warnings; -use Test::More tests => 9; +use Test::More tests => 8; # Ensure environment has no influence. delete $ENV{'TASKDATA'}; @@ -79,10 +79,6 @@ unlike ($output, qr/1.+A.+zero/, 't1 missing'); unlike ($output, qr/2.+B.+one/, 't2 missing'); like ($output, qr/2\/13\/2009.+two/, 't3 present'); -# Make sure that a duplicate task cannot be imported. -$output = qx{../src/task rc:import.rc import import.txt 2>&1 >/dev/null}; -like ($output, qr/Cannot add task because the uuid .+ is not unique\./, 'error on duplicate uuid'); - # Create import file. if (open my $fh, '>', 'import2.txt') { diff --git a/test/import.yaml.t b/test/import.yaml.t index 87730314a..d835061e1 100755 --- a/test/import.yaml.t +++ b/test/import.yaml.t @@ -27,7 +27,7 @@ use strict; use warnings; -use Test::More tests => 16; +use Test::More tests => 15; # Ensure environment has no influence. delete $ENV{'TASKDATA'}; @@ -136,10 +136,6 @@ like ($output, qr/1.+A.+zero.*\n.+ONE/, "$ut: t1 selected by tag, has like ($output, qr/2.+B.+one.*\n.+TWO.*\n.+THREE/, "$ut: t2 selected by tag, has two annotations"); like ($output, qr/\n2 tasks\n/, "$ut: tag selected two tasks"); -# Make sure that a duplicate task cannot be imported. -$output = qx{../src/task rc:$rc import import.json 2>&1 >/dev/null}; -like ($output, qr/Cannot add task because the uuid '.{36}' is not unique\./, "$ut: error on duplicate uuid"); - # Create import file. if (open my $fh, '>', 'import.txt') { diff --git a/test/import_stdin.t b/test/import_NEW.t similarity index 65% rename from test/import_stdin.t rename to test/import_NEW.t index d33f2933c..9e510a069 100755 --- a/test/import_stdin.t +++ b/test/import_NEW.t @@ -35,7 +35,7 @@ sys.path.append(os.path.dirname(os.path.abspath(__file__))) from basetest import Task, TestCase -class TestImportSTDIN(TestCase): +class TestImport(TestCase): def setUp(self): self.t = Task() self.t.config("report.foo.description", "foo") @@ -55,6 +55,28 @@ class TestImportSTDIN(TestCase): self.assertRegexpMatches(out, "2\s+one", "second task present") self.assertRegexpMatches(out, "-\s+two", "third task present") + def test_import_update(self): + """Update existing tasks""" + json_data = """ + {"uuid":"00000000-0000-0000-0000-000000000000","description":"zero","project":"A","status":"pending","entry":"1234567889"} + {"uuid":"11111111-1111-1111-1111-111111111111","description":"one","project":"B","status":"deleted","entry":"1234567889"} + {"uuid":"22222222-2222-2222-2222-222222222222","description":"two","status":"completed","entry":"1234524689","end":"1234524690"}""" + self.t("import", input=json_data) + + self.t("next") # Run GC + + json_data = """ + {"uuid":"00000000-0000-0000-0000-000000000000","description":"zero","project":"C","status":"pending","entry":"1234567889"} + {"uuid":"11111111-1111-1111-1111-111111111111","description":"one","project":"B","status":"pending","entry":"1234567889"} + {"uuid":"22222222-2222-2222-2222-222222222222","description":"two","status":"pending","entry":"1234524689","end":"1234524690"}""" + self.t("import", input=json_data) + + zero, one, two = sorted(self.t.export(), key=lambda t: t["uuid"]) + self.assertEqual(zero["status"], "pending", "status for 'zero' unchanged") + self.assertEqual(zero["project"], "C", "project for 'zero' changed to 'C'") + self.assertEqual(one["status"], "pending", "status for 'one' changed to pending") + self.assertEqual(two["status"], "pending", "status for 'two' changed to pending") + if __name__ == "__main__": from simpletap import TAPTestRunner