diff --git a/src/commands/CmdImport.cpp b/src/commands/CmdImport.cpp index 4bfe3072b..77d6f0ce1 100644 --- a/src/commands/CmdImport.cpp +++ b/src/commands/CmdImport.cpp @@ -32,6 +32,7 @@ #include #include #include +#include //////////////////////////////////////////////////////////////////////////////// CmdImport::CmdImport () @@ -90,6 +91,20 @@ int CmdImport::execute (std::string&) } Context::getContext ().footnote (format ("Imported {1} tasks.", count)); + + // Warn the user about multiple occurrences of the same UUID. + auto duplicates = false; + for (const auto& [uuid, occurrences] : uuid_occurrences) + { + if (occurrences > 1) + { + duplicates = true; + Context::getContext ().footnote (format ("Input contains UUID '{1}' {2} times.", uuid, occurrences)); + } + } + if (duplicates) + Context::getContext ().footnote ("Tasks with the same UUID have been merged. Please check the results."); + return rc; } @@ -186,7 +201,9 @@ void CmdImport::importSingleTask (json::object* obj) // Check whether the imported task is new or a modified existing task. Task before; - if (Context::getContext ().tdb2.get (task.get ("uuid"), before)) + auto uuid = task.get("uuid"); + uuid_occurrences[uuid]++; + if (Context::getContext ().tdb2.get (uuid, before)) { // We need to neglect updates from attributes with dynamic defaults // unless they have been explicitly specified on import. diff --git a/src/commands/CmdImport.h b/src/commands/CmdImport.h index f492481ea..b27d94362 100644 --- a/src/commands/CmdImport.h +++ b/src/commands/CmdImport.h @@ -38,6 +38,7 @@ public: int execute (std::string&); private: + std::unordered_map uuid_occurrences; int import (const std::string&); void importSingleTask (json::object*); }; diff --git a/test/import.test.py b/test/import.test.py index 83b17b2ec..3bf6118b5 100755 --- a/test/import.test.py +++ b/test/import.test.py @@ -224,6 +224,15 @@ class TestImport(TestCase): code, out2, err = self.t("export") self.assertEqual(out1, out2) + def test_import_duplicate_uuid_in_input(self): + """Test import warns if input contains the same UUID twice.""" + _data = """[ +{"uuid":"a0000000-a000-a000-a000-a00000000000","description":"first description"}, +{"uuid":"a0000000-a000-a000-a000-a00000000000","description":"second description"} +]""" + _, _, err = self.t("import", input=_data) + self.assertIn("Input contains UUID 'a0000000-a000-a000-a000-a00000000000' 2 times", err) + class TestImportExportRoundtrip(TestCase): def setUp(self):