From 1cc67e98957bccf1f7b2277076def8c80c0d9341 Mon Sep 17 00:00:00 2001 From: Paul Beckingham Date: Thu, 2 Sep 2010 21:32:33 -0400 Subject: [PATCH] Enhancement - Importing the same YAML twice now generates an error. --- ChangeLog | 1 + NEWS | 3 ++- src/TDB.cpp | 33 +++++++++++++++++++++++++++------ src/TDB.h | 2 ++ src/import.cpp | 5 +++++ src/tests/import.yaml.t | 6 +++++- 6 files changed, 42 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1b404ea4d..2f2ea31a1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -41,6 +41,7 @@ + New fish shell tab completion script (thanks to Mick Koch). + Color rules now obey the rc.search.case.sensitive configuration option. + The color.keyword.XXX color rule now applies to annotations too. + + Importing the same YAML twice now generates an error. + Fixed bug #427, preventing the task edit command to parse annotation dates with spaces. + Fixed bug #433, making task command output more consistent. diff --git a/NEWS b/NEWS index 9595f7ac0..8d631fde6 100644 --- a/NEWS +++ b/NEWS @@ -13,7 +13,8 @@ New Features in taskwarrior 1.9.3 - Now supports 'now' as a date/time. - Now defines an overdue task as being one second after the due date, instead of the day after the due date. - - Import and export of YAML 1.1, including round-trip capability. + - Import and export of YAML 1.1, including round-trip capability, and + detection of duplicate imports. - New merge capability for syncing task data files. - New push capability for distributing merged changes. - When completing or modifying a task, the project status is displayed. diff --git a/src/TDB.cpp b/src/TDB.cpp index 6df89e0a5..21580e3d9 100644 --- a/src/TDB.cpp +++ b/src/TDB.cpp @@ -463,17 +463,25 @@ const std::vector & TDB::getAllModified () // Note: mLocations[0] is where all tasks are written. void TDB::add (const Task& task) { + std::string unique; Task t (task); if (task.get ("uuid") == "") - { - std::string unique = ::uuid (); - t.set ("uuid", unique); - } + unique = ::uuid (); else - t.set ("uuid", task.get ("uuid")); + unique = task.get ("uuid"); + + t.set ("uuid", unique); + + // If the tasks are loaded, then verify that this uuid is not already in + // the file. + if (uuidAlreadyUsed (unique, mNew) || + uuidAlreadyUsed (unique, mModified) || + uuidAlreadyUsed (unique, mPending) || + uuidAlreadyUsed (unique, mCompleted)) + throw std::string ("Cannot add task because the uuid '") + unique + "' is not unique."; mNew.push_back (t); - mI2U[task.id] = t.get ("uuid"); + mI2U[task.id] = unique; mU2I[task.get ("uuid")] = t.id; } @@ -1610,3 +1618,16 @@ void TDB::writeUndo (const Task& before, const Task& after, FILE* file) } //////////////////////////////////////////////////////////////////////////////// +bool TDB::uuidAlreadyUsed ( + const std::string& uuid, + const std::vector & all) +{ + std::vector ::const_iterator it; + for (it = all.begin (); it != all.end (); ++it) + if (it->get ("uuid") == uuid) + return true; + + return false; +} + +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/TDB.h b/src/TDB.h index c92134005..922969608 100644 --- a/src/TDB.h +++ b/src/TDB.h @@ -76,6 +76,8 @@ private: FILE* openAndLock (const std::string&); void writeUndo (const Task&, FILE*); void writeUndo (const Task&, const Task&, FILE*); + bool uuidAlreadyUsed (const std::string&); + bool uuidAlreadyUsed (const std::string&, const std::vector &); private: std::vector mLocations; diff --git a/src/import.cpp b/src/import.cpp index db376aa5f..b89ce176a 100644 --- a/src/import.cpp +++ b/src/import.cpp @@ -1169,6 +1169,11 @@ static std::string importYAML (const std::vector & lines) context.tdb.lock (context.config.getBoolean ("locking")); + // Load all the tasks so that the uuid uniqueness can be checked. + std::vector tasks; + Filter filter; + context.tdb.load (tasks, filter); + Task t; std::string name; diff --git a/src/tests/import.yaml.t b/src/tests/import.yaml.t index ff178f505..eaa84e07a 100755 --- a/src/tests/import.yaml.t +++ b/src/tests/import.yaml.t @@ -28,7 +28,7 @@ use strict; use warnings; -use Test::More tests => 14; +use Test::More tests => 15; # Create the rc file. if (open my $fh, '>', 'import.rc') @@ -96,6 +96,10 @@ 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{../task rc:import.rc import import.txt}; +like ($output, qr/Cannot add task because the uuid .+ is not unique\./, 'error on duplicate uuid'); + # Cleanup. unlink 'import.txt'; ok (!-r 'import.txt', 'Removed import.txt');