diff --git a/ChangeLog b/ChangeLog index 32bf8118b..d1913c941 100644 --- a/ChangeLog +++ b/ChangeLog @@ -24,6 +24,7 @@ Features + The 'due' urgency component now uses seconds, not days, in the calculation. + The 'debug.tls' configuration variable takes an integer which corresponds to the GnuTLS log level. For debugging. + + File format 2 (used in version 0.9.3 - 1.5.0) is no longer supported. Bugs + #1196 Now builds on Hurd (thanks to Jakub Wilk). diff --git a/NEWS b/NEWS index a89b744f5..c1d9ab0c7 100644 --- a/NEWS +++ b/NEWS @@ -22,7 +22,7 @@ New configuration options in taskwarrior 2.3.0 Newly deprecated features in taskwarrior 2.3.0 - - + - File format 2 (used in version 0.9.3 - 1.5.0) is no longer supported. --- diff --git a/cmake.h.in b/cmake.h.in index 73d03b535..e6188b84a 100644 --- a/cmake.h.in +++ b/cmake.h.in @@ -1,5 +1,8 @@ /* cmake.h.in. Creates cmake.h during a cmake run */ +/* Product identification */ +#define PRODUCT_TASKWARRIOR 1 + /* Package information */ #define PACKAGE "${PACKAGE}" #define VERSION "${VERSION}" diff --git a/src/Task.cpp b/src/Task.cpp index 4563947a1..e763da500 100644 --- a/src/Task.cpp +++ b/src/Task.cpp @@ -25,21 +25,30 @@ // //////////////////////////////////////////////////////////////////////////////// +#include +#ifdef PRODUCT_TASKWARRIOR #include +#endif #include +#ifdef PRODUCT_TASKWARRIOR #include #include #include #include #include +#endif #include #include #include #include +#ifdef PRODUCT_TASKWARRIOR #include +#endif #include #include + #include +#ifdef PRODUCT_TASKWARRIOR #include #define APPROACHING_INFINITY 1000 // Close enough. This isn't rocket surgery. @@ -96,14 +105,17 @@ void initializeUrgencyCoefficients () coefficients[*var] = context.config.getReal (*var); } } +#endif //////////////////////////////////////////////////////////////////////////////// Task::Task () : id (0) +#ifdef PRODUCT_TASKWARRIOR , urgency_value (0.0) , recalc_urgency (true) , is_blocked (false) , is_blocking (false) +#endif , annotation_count (0) { } @@ -120,13 +132,14 @@ Task& Task::operator= (const Task& other) if (this != &other) { std::map ::operator= (other); - id = other.id; +#ifdef PRODUCT_TASKWARIROR urgency_value = other.urgency_value; recalc_urgency = other.recalc_urgency; is_blocked = other.is_blocked; is_blocking = other.is_blocking; annotation_count = other.annotation_count; +#endif } return *this; @@ -152,11 +165,13 @@ bool Task::operator== (const Task& other) Task::Task (const std::string& input) { id = 0; +#ifdef PRODUCT_TASKWARRIOR urgency_value = 0.0; recalc_urgency = true; is_blocked = false; is_blocking = false; annotation_count = 0; +#endif parse (input); } @@ -189,6 +204,7 @@ std::string Task::statusToText (Task::status s) return "pending"; } +#ifdef PRODUCT_TASKWARRIOR //////////////////////////////////////////////////////////////////////////////// void Task::setEntry () { @@ -218,6 +234,7 @@ void Task::setStart () recalc_urgency = true; } +#endif //////////////////////////////////////////////////////////////////////////////// void Task::setModified () @@ -258,6 +275,7 @@ const std::string Task::get (const std::string& name) const return ""; } +#ifdef PRODUCT_TASKWARRIOR //////////////////////////////////////////////////////////////////////////////// const std::string& Task::get_ref (const std::string& name) const { @@ -287,6 +305,7 @@ unsigned long Task::get_ulong (const std::string& name) const return 0; } +#endif //////////////////////////////////////////////////////////////////////////////// time_t Task::get_date (const std::string& name) const @@ -303,7 +322,9 @@ void Task::set (const std::string& name, const std::string& value) { (*this)[name] = value; +#ifdef PRODUCT_TASKWARRIOR recalc_urgency = true; +#endif } //////////////////////////////////////////////////////////////////////////////// @@ -311,7 +332,9 @@ void Task::set (const std::string& name, int value) { (*this)[name] = format (value); +#ifdef PRODUCT_TASKWARRIOR recalc_urgency = true; +#endif } //////////////////////////////////////////////////////////////////////////////// @@ -321,7 +344,9 @@ void Task::remove (const std::string& name) if ((it = this->find (name)) != this->end ()) this->erase (it); +#ifdef PRODUCT_TASKWARRIOR recalc_urgency = true; +#endif } //////////////////////////////////////////////////////////////////////////////// @@ -335,9 +360,12 @@ void Task::setStatus (Task::status status) { set ("status", statusToText (status)); +#ifdef PRODUCT_TASKWARRIOR recalc_urgency = true; +#endif } +#ifdef PRODUCT_TASKWARRIOR //////////////////////////////////////////////////////////////////////////////// bool Task::is_due () const { @@ -391,10 +419,13 @@ bool Task::is_overdue () const return false; } +#endif //////////////////////////////////////////////////////////////////////////////// // Attempt an FF4 parse first, using Task::parse, and in the event of an error -// try a legacy parse (F3, FF2). Note that FF1 is no longer supported. +// try a JSON parse, otherwise a legacy parse (FF3). +// +// Note that FF1 and FF2 are no longer supported. // // start --> [ --> Att --> ] --> end // ^ | @@ -410,6 +441,7 @@ void Task::parse (const std::string& input) try { + // File format version 4, from 2009-5-16 - now, v1.7.1+ clear (); Nibbler n (copy); @@ -451,88 +483,141 @@ void Task::parse (const std::string& input) if (remainder.length ()) throw std::string (STRING_RECORD_JUNK_AT_EOL); } + else if (input[0] == '{') + parseJSON (input); else throw std::string (STRING_RECORD_NOT_FF4); } catch (const std::string&) { - legacyParse (copy); + parseLegacy (copy); } +#ifdef PRODUCT_TASKWARRIOR recalc_urgency = true; +#endif +} + +//////////////////////////////////////////////////////////////////////////////// +void Task::parseJSON (const std::string& line) +{ + // Parse the whole thing. + json::value* root = json::parse (line); + if (root->type () == json::j_object) + { + json::object* root_obj = (json::object*)root; + + // For each object element... + json_object_iter i; + for (i = root_obj->_data.begin (); + i != root_obj->_data.end (); + ++i) + { + // If the attribute is a recognized column. + Column* col = context.columns[i->first]; + if (col) + { + // Any specified id is ignored. + if (i->first == "id") + ; + + // Urgency, if present, is ignored. + else if (i->first == "urgency") + ; + + // Dates are converted from ISO to epoch. + else if (col->type () == "date") + { + Date d (unquoteText (i->second->dump ())); + set (i->first, d.toEpochString ()); + } + + // Tags are an array of JSON strings. + else if (i->first == "tags") + { + json::array* tags = (json::array*)i->second; + json_array_iter t; + for (t = tags->_data.begin (); + t != tags->_data.end (); + ++t) + { + json::string* tag = (json::string*)*t; + addTag (tag->_data); + } + } + + // Other types are simply added. + else + set (i->first, unquoteText (i->second->dump ())); + } + + // UDA orphans and annotations do not have columns. + else + { + // Annotations are an array of JSON objects with 'entry' and + // 'description' values and must be converted. + if (i->first == "annotations") + { + std::map annos; + + json::array* atts = (json::array*)i->second; + json_array_iter annotations; + for (annotations = atts->_data.begin (); + annotations != atts->_data.end (); + ++annotations) + { + json::object* annotation = (json::object*)*annotations; + json::string* when = (json::string*)annotation->_data["entry"]; + json::string* what = (json::string*)annotation->_data["description"]; + + if (! when) + throw format (STRING_TASK_NO_ENTRY, line); + + if (! what) + throw format (STRING_TASK_NO_DESC, line); + + std::string name = "annotation_" + Date (when->_data).toEpochString (); + + annos.insert (std::make_pair (name, what->_data)); + } + + setAnnotations (annos); + } + + // UDA Orphan - must be preserved. + else + { +#ifdef PRODUCT_TASKWARRIOR + std::stringstream message; + message << "Task::parseJSON found orphan '" + << i->first + << "' with value '" + << i->second + << "' --> preserved\n"; + context.debug (message.str ()); +#endif + set (i->first, unquoteText (i->second->dump ())); + } + } + } + } } //////////////////////////////////////////////////////////////////////////////// // Support FF2, FF3. // Thankfully FF1 is no longer supported. -void Task::legacyParse (const std::string& line) +void Task::parseLegacy (const std::string& line) { switch (determineVersion (line)) { - // File format version 1, from 2006.11.27 - 2007.12.31 - case 1: - throw std::string (STRING_TASK_NO_FF1); - break; + // File format version 1, from 2006-11-27 - 2007-12-31, v0.x+ - v0.9.3 + case 1: throw std::string (STRING_TASK_NO_FF1); - // File format version 2, from 2008.1.1 - 2009.3.23 - case 2: - { - if (line.length () > 46) // ^.{36} . \[\] \[\] \n - { - set ("uuid", line.substr (0, 36)); + // File format version 2, from 2008-1-1 - 2009-3-23, v0.9.3 - v1.5.0 + case 2: throw std::string (STRING_TASK_NO_FF2); - Task::status status = line[37] == '+' ? completed - : line[37] == 'X' ? deleted - : line[37] == 'r' ? recurring - : pending; - - set ("status", statusToText (status)); - - size_t openTagBracket = line.find ("["); - size_t closeTagBracket = line.find ("]", openTagBracket); - if (openTagBracket != std::string::npos && - closeTagBracket != std::string::npos) - { - size_t openAttrBracket = line.find ("[", closeTagBracket); - size_t closeAttrBracket = line.find ("]", openAttrBracket); - if (openAttrBracket != std::string::npos && - closeAttrBracket != std::string::npos) - { - std::string tags = line.substr ( - openTagBracket + 1, closeTagBracket - openTagBracket - 1); - std::vector tagSet; - split (tagSet, tags, ' '); - addTags (tagSet); - - std::string attributes = line.substr ( - openAttrBracket + 1, closeAttrBracket - openAttrBracket - 1); - std::vector pairs; - split (pairs, attributes, ' '); - for (size_t i = 0; i < pairs.size (); ++i) - { - std::vector pair; - split (pair, pairs[i], ':'); - if (pair.size () == 2) - set (pair[0], pair[1]); - } - - set ("description", line.substr (closeAttrBracket + 2)); - } - else - throw std::string (STRING_TASK_PARSE_ATT_BRACK); - } - else - throw std::string (STRING_TASK_PARSE_TAG_BRACK); - } - else - throw std::string (STRING_TASK_PARSE_TOO_SHORT); - - removeAnnotations (); - } - break; - - // File format version 3, from 2009.3.23 + // File format version 3, from 2009-3-23 - 2009-05-16, v1.6.0 - v1.7.1 case 3: { if (line.length () > 49) // ^.{36} . \[\] \[\] \[\] \n @@ -640,7 +725,9 @@ void Task::legacyParse (const std::string& line) break; } +#ifdef PRODUCT_TASKWARRIOR recalc_urgency = true; +#endif } //////////////////////////////////////////////////////////////////////////////// @@ -669,14 +756,15 @@ std::string Task::composeF4 () const return ff4; } +#ifdef PRODUCT_TASKWARRIOR //////////////////////////////////////////////////////////////////////////////// -std::string Task::composeJSON (bool include_id /*= false*/) const +std::string Task::composeJSON (bool decorate /*= false*/) const { std::stringstream out; out << "{"; // ID inclusion is optional, not recommended. - if (include_id) + if (decorate) out << "\"id\":" << id << ","; // First the non-annotations. @@ -765,10 +853,11 @@ std::string Task::composeJSON (bool include_id /*= false*/) const } // Include urgency. - out << "," - << "\"urgency\":\"" - << urgency_c () - <<"\""; + if (decorate) + out << "," + << "\"urgency\":\"" + << urgency_c () + <<"\""; out << "}"; return out.str (); @@ -780,31 +869,6 @@ bool Task::hasAnnotations () const return annotation_count ? true : false; } -//////////////////////////////////////////////////////////////////////////////// -void Task::getAnnotations (std::map & annotations) const -{ - annotations.clear (); - - Task::const_iterator ci; - for (ci = this->begin (); ci != this->end (); ++ci) - if (ci->first.substr (0, 11) == "annotation_") - annotations.insert (*ci); -} - -//////////////////////////////////////////////////////////////////////////////// -void Task::setAnnotations (const std::map & annotations) -{ - // Erase old annotations. - removeAnnotations (); - - std::map ::const_iterator ci; - for (ci = annotations.begin (); ci != annotations.end (); ++ci) - this->insert (*ci); - - annotation_count = annotations.size (); - recalc_urgency = true; -} - //////////////////////////////////////////////////////////////////////////////// // The timestamp is part of the name: // annotation_1234567890:"..." @@ -847,6 +911,31 @@ void Task::removeAnnotations () recalc_urgency = true; } +//////////////////////////////////////////////////////////////////////////////// +void Task::getAnnotations (std::map & annotations) const +{ + annotations.clear (); + + Task::const_iterator ci; + for (ci = this->begin (); ci != this->end (); ++ci) + if (ci->first.substr (0, 11) == "annotation_") + annotations.insert (*ci); +} + +//////////////////////////////////////////////////////////////////////////////// +void Task::setAnnotations (const std::map & annotations) +{ + // Erase old annotations. + removeAnnotations (); + + std::map ::const_iterator ci; + for (ci = annotations.begin (); ci != annotations.end (); ++ci) + this->insert (*ci); + + annotation_count = annotations.size (); + recalc_urgency = true; +} + //////////////////////////////////////////////////////////////////////////////// void Task::addDependency (int id) { @@ -1189,6 +1278,7 @@ void Task::substitute ( recalc_urgency = true; } } +#endif //////////////////////////////////////////////////////////////////////////////// // The purpose of Task::validate is three-fold: @@ -1224,6 +1314,7 @@ void Task::validate (bool applyDefault /* = true */) // Store the derived status. setStatus (status); +#ifdef PRODUCT_TASKWARRIOR // Provide an entry date unless user already specified one. if (!has ("entry")) setEntry (); @@ -1309,6 +1400,7 @@ void Task::validate (bool applyDefault /* = true */) validate_before ("scheduled", "start"); validate_before ("scheduled", "due"); validate_before ("scheduled", "end"); +#endif // 3) To generate errors when the inconsistencies are not fixable @@ -1341,6 +1433,8 @@ void Task::validate (bool applyDefault /* = true */) } } +#ifdef PRODUCT_TASKWARRIOR +//////////////////////////////////////////////////////////////////////////////// void Task::validate_before (const std::string& left, const std::string& right) { if (has (left) && @@ -1674,5 +1768,6 @@ float Task::urgency_blocking () const return 0.0; } +#endif //////////////////////////////////////////////////////////////////////////////// diff --git a/src/Task.h b/src/Task.h index b7c52ea1d..65880957c 100644 --- a/src/Task.h +++ b/src/Task.h @@ -28,13 +28,15 @@ #ifndef INCLUDED_TASK #define INCLUDED_TASK +#include #include #include #include #include - +#ifdef PRODUCT_TASKWARRIOR void initializeUrgencyCoefficients (); +#endif class Task : public std::map { @@ -48,18 +50,22 @@ public: void parse (const std::string&); std::string composeF4 () const; - std::string composeJSON (bool include_id = false) const; +#ifdef PRODUCT_TASKWARRIOR + std::string composeJSON (bool decorate = false) const; +#endif // Status values. enum status {pending, completed, deleted, recurring, waiting}; // Public data. int id; +#ifdef PRODUCT_TASKWARRIOR float urgency_value; bool recalc_urgency; bool is_blocked; bool is_blocking; +#endif int annotation_count; @@ -67,39 +73,50 @@ public: static status textToStatus (const std::string&); static std::string statusToText (status); +#ifdef PRODUCT_TASKWARRIOR void setEntry (); void setEnd (); void setStart (); +#endif void setModified (); bool has (const std::string&) const; std::vector all (); const std::string get (const std::string&) const; +#ifdef PRODUCT_TASKWARRIOR const std::string& get_ref (const std::string&) const; int get_int (const std::string&) const; unsigned long get_ulong (const std::string&) const; +#endif time_t get_date (const std::string&) const; void set (const std::string&, const std::string&); void set (const std::string&, int); void remove (const std::string&); +#ifdef PRODUCT_TASKWARRIOR bool is_due () const; bool is_duetoday () const; bool is_overdue () const; +#endif status getStatus () const; void setStatus (status); +#ifdef PRODUCT_TASKWARRIOR int getTagCount () const; bool hasTag (const std::string&) const; +#endif void addTag (const std::string&); void addTags (const std::vector &); +#ifdef PRODUCT_TASKWARRIOR void getTags (std::vector&) const; void removeTag (const std::string&); bool hasAnnotations () const; void getAnnotations (std::map &) const; +#endif void setAnnotations (const std::map &); +#ifdef PRODUCT_TASKWARRIOR void addAnnotation (const std::string&); void removeAnnotations (); @@ -114,15 +131,20 @@ public: void getUDAOrphans (std::vector &) const; void substitute (const std::string&, const std::string&, bool); +#endif void validate (bool applyDefault = true); +#ifdef PRODUCT_TASKWARRIOR float urgency_c () const; float urgency (); +#endif private: int determineVersion (const std::string&); - void legacyParse (const std::string&); + void parseJSON (const std::string&); + void parseLegacy (const std::string&); +#ifdef PRODUCT_TASKWARRIOR void validate_before (const std::string&, const std::string&); inline float urgency_priority () const; @@ -137,6 +159,7 @@ private: inline float urgency_due () const; inline float urgency_blocking () const; inline float urgency_age () const; +#endif }; #endif diff --git a/src/commands/CmdImport.cpp b/src/commands/CmdImport.cpp index 046301513..f53947f0f 100644 --- a/src/commands/CmdImport.cpp +++ b/src/commands/CmdImport.cpp @@ -172,10 +172,10 @@ int CmdImport::execute (std::string& output) json::string* what = (json::string*)annotation->_data["description"]; if (! when) - throw format (STRING_CMD_IMPORT_NO_ENTRY, *line); + throw format (STRING_TASK_NO_ENTRY, *line); if (! what) - throw format (STRING_CMD_IMPORT_NO_DESC, *line); + throw format (STRING_TASK_NO_DESC, *line); std::string name = "annotation_" + Date (when->_data).toEpochString (); diff --git a/src/en-US.h b/src/en-US.h index 3b66a9d5a..cf82bf804 100644 --- a/src/en-US.h +++ b/src/en-US.h @@ -396,8 +396,8 @@ #define STRING_CMD_IMPORT_NOFILE "You must specify a file to import." #define STRING_CMD_IMPORT_FILE "Importing '{1}'" #define STRING_CMD_IMPORT_NOT_JSON "Not a JSON object: {1}" -#define STRING_CMD_IMPORT_NO_DESC "Annotation is missing a description: {1}" -#define STRING_CMD_IMPORT_NO_ENTRY "Annotation is missing an entry date: {1}" +#define STRING_TASK_NO_DESC "Annotation is missing a description: {1}" +#define STRING_TASK_NO_ENTRY "Annotation is missing an entry date: {1}" #define STRING_CMD_SHELL_HELP1 "Enter any task command (such as 'list'), or hit 'Enter'." #define STRING_CMD_SHELL_HELP2 "There is no need to include the 'task' command itself." #define STRING_CMD_SHELL_HELP3 "Enter 'quit' (or 'bye', 'exit') to end the session." @@ -779,6 +779,7 @@ // Task #define STRING_TASK_NO_FF1 "Taskwarrior no longer supports file format 1, originally used between 27 November 2006 and 31 December 2007." +#define STRING_TASK_NO_FF2 "Taskwarrior no longer supports file format 2, originally used between 1 January 2008 and 12 April 2009." #define STRING_TASK_PARSE_ANNO_BRACK "Missing annotation brackets." #define STRING_TASK_PARSE_ATT_BRACK "Missing attribute brackets." #define STRING_TASK_PARSE_TAG_BRACK "Missing tag brackets." diff --git a/src/es-ES.h b/src/es-ES.h index ad34d29fc..fd6da7f30 100644 --- a/src/es-ES.h +++ b/src/es-ES.h @@ -406,8 +406,8 @@ #define STRING_CMD_IMPORT_NOFILE "Debe especificar un archivo a importar." #define STRING_CMD_IMPORT_FILE "Importando '{1}'" #define STRING_CMD_IMPORT_NOT_JSON "No es un objeto JSON: {1}" -#define STRING_CMD_IMPORT_NO_DESC "La anotación carece de descripción: {1}" -#define STRING_CMD_IMPORT_NO_ENTRY "La anotación carece de fecha de entrada: {1}" +#define STRING_TASK_NO_DESC "La anotación carece de descripción: {1}" +#define STRING_TASK_NO_ENTRY "La anotación carece de fecha de entrada: {1}" #define STRING_CMD_SHELL_HELP1 "Escriba un comando de task (como 'list'), o pulse 'Enter'." #define STRING_CMD_SHELL_HELP2 "No hace falta incluir el propio comando 'task'." #define STRING_CMD_SHELL_HELP3 "Escriba 'quit' (o 'bye', 'exit') para terminar la sesión." @@ -794,6 +794,7 @@ // Task #define STRING_TASK_NO_FF1 "Taskwarrior ya no admite el formato de archivo 1, usado originalmente entre el 27 de noviembre del 2006 y el 31 de diciembre del 2007." +#define STRING_TASK_NO_FF2 "Taskwarrior no longer supports file format 2, originally used between 1 January 2008 and 12 April 2009." #define STRING_TASK_PARSE_ANNO_BRACK "Faltan corchetes de anotación." #define STRING_TASK_PARSE_ATT_BRACK "Faltan corchetes de atributo." #define STRING_TASK_PARSE_TAG_BRACK "Faltan corchetes de marca." diff --git a/src/fr-FR.h b/src/fr-FR.h index 70e736217..0f7eb063f 100644 --- a/src/fr-FR.h +++ b/src/fr-FR.h @@ -396,8 +396,8 @@ #define STRING_CMD_IMPORT_NOFILE "You must specify a file to import." #define STRING_CMD_IMPORT_FILE "Importing '{1}'" #define STRING_CMD_IMPORT_NOT_JSON "Not a JSON object: {1}" -#define STRING_CMD_IMPORT_NO_DESC "Annotation is missing a description: {1}" -#define STRING_CMD_IMPORT_NO_ENTRY "Annotation is missing an entry date: {1}" +#define STRING_TASK_NO_DESC "Annotation is missing a description: {1}" +#define STRING_TASK_NO_ENTRY "Annotation is missing an entry date: {1}" #define STRING_CMD_SHELL_HELP1 "Enter any task command (such as 'list'), or hit 'Enter'." #define STRING_CMD_SHELL_HELP2 "There is no need to include the 'task' command itself." #define STRING_CMD_SHELL_HELP3 "Enter 'quit' (or 'bye', 'exit') to end the session." @@ -779,6 +779,7 @@ // Task #define STRING_TASK_NO_FF1 "Taskwarrior no longer supports file format 1, originally used between 27 November 2006 and 31 December 2007." +#define STRING_TASK_NO_FF2 "Taskwarrior no longer supports file format 2, originally used between 1 January 2008 and 12 April 2009." #define STRING_TASK_PARSE_ANNO_BRACK "Missing annotation brackets." #define STRING_TASK_PARSE_ATT_BRACK "Missing attribute brackets." #define STRING_TASK_PARSE_TAG_BRACK "Missing tag brackets." diff --git a/src/it-IT.h b/src/it-IT.h index ba4641a40..f65baec66 100644 --- a/src/it-IT.h +++ b/src/it-IT.h @@ -397,8 +397,8 @@ #define STRING_CMD_IMPORT_NOFILE "Specificare il file da importare." #define STRING_CMD_IMPORT_FILE "Importazione di '{1}'" #define STRING_CMD_IMPORT_NOT_JSON "Non è un oggetto JSON: {1}" -#define STRING_CMD_IMPORT_NO_DESC "Annotazione senza descrizione: {1}" -#define STRING_CMD_IMPORT_NO_ENTRY "Annotazione senza data di immissione: {1}" +#define STRING_TASK_NO_DESC "Annotazione senza descrizione: {1}" +#define STRING_TASK_NO_ENTRY "Annotazione senza data di immissione: {1}" #define STRING_CMD_SHELL_HELP1 "Inserisci un comando (es. 'list'), o premi 'Enter'." #define STRING_CMD_SHELL_HELP2 "Non è necessario includere il comando 'task'." #define STRING_CMD_SHELL_HELP3 "Inserisci 'quit' (o 'bye', 'exit') per terminare la sessione." @@ -780,6 +780,7 @@ // Task #define STRING_TASK_NO_FF1 "Taskwarrior non supporta più il formato di file 1, usato tra il 27 Novembre 2006 e il 31 Dicembre 2007." +#define STRING_TASK_NO_FF2 "Taskwarrior no longer supports file format 2, originally used between 1 January 2008 and 12 April 2009." #define STRING_TASK_PARSE_ANNO_BRACK "Parentesi di annotazione mancanti." #define STRING_TASK_PARSE_ATT_BRACK "Parentesi di attributo mancanti." #define STRING_TASK_PARSE_TAG_BRACK "Parentesi di tag mancanti." diff --git a/test/t.t.cpp b/test/t.t.cpp index 7c7163fb6..a939d484e 100644 --- a/test/t.t.cpp +++ b/test/t.t.cpp @@ -33,7 +33,7 @@ Context context; //////////////////////////////////////////////////////////////////////////////// int main (int argc, char** argv) { - UnitTest test (37); + UnitTest test (30); test.is ((int)Task::textToStatus ("pending"), (int)Task::pending, "textToStatus pending"); test.is ((int)Task::textToStatus ("completed"), (int)Task::completed, "textToStatus completed"); @@ -57,7 +57,7 @@ int main (int argc, char** argv) after = t3.composeF4 (); test.is (before, after, "Task::composeF4 -> parse round trip 4 iterations"); - // Legacy Format 1 + // Legacy Format 1 (no longer supported) // [tags] [attributes] description\n // X [tags] [attributes] description\n std::string sample = "[tag1 tag2] [att1:value1 att2:value2] Description"; @@ -69,27 +69,16 @@ int main (int argc, char** argv) try { Task ff1 (sample); } catch (...) { good = false; } test.notok (good, "Support for ff1 removed"); - // Legacy Format 2 + // Legacy Format 2 (no longer supported) // uuid status [tags] [attributes] description\n sample = "00000000-0000-0000-0000-000000000000 " "- " "[tag1 tag2] " "[att1:value1 att2:value2] " "Description"; - Task ff2 (sample); - std::string value = ff2.get ("uuid"); - test.is (value, "00000000-0000-0000-0000-000000000000", "ff2 uuid"); - value = ff2.get ("status"); - test.is (value, "pending", "ff2 status"); - test.ok (ff2.hasTag ("tag1"), "ff2 tag1"); - test.ok (ff2.hasTag ("tag2"), "ff2 tag2"); - test.is (ff2.getTagCount (), 2, "ff2 # tags"); - value = ff2.get ("att1"); - test.is (value, "value1", "ff2 att1"); - value = ff2.get ("att2"); - test.is (value, "value2", "ff2 att2"); - value = ff2.get ("description"); - test.is (value, "Description", "ff2 description"); + good = true; + try { Task ff2 (sample); } catch (...) { good = false; } + test.notok (good, "Support for ff2 removed"); // Legacy Format 3 // uuid status [tags] [attributes] [annotations] description\n @@ -99,13 +88,13 @@ int main (int argc, char** argv) "[att1:value1 att2:value2] " "[123:ann1 456:ann2] Description"; Task ff3 (sample); - value = ff2.get ("uuid"); + std::string value = ff3.get ("uuid"); test.is (value, "00000000-0000-0000-0000-000000000000", "ff3 uuid"); - value = ff2.get ("status"); + value = ff3.get ("status"); test.is (value, "pending", "ff3 status"); - test.ok (ff2.hasTag ("tag1"), "ff3 tag1"); - test.ok (ff2.hasTag ("tag2"), "ff3 tag2"); - test.is (ff2.getTagCount (), 2, "ff3 # tags"); + test.ok (ff3.hasTag ("tag1"), "ff3 tag1"); + test.ok (ff3.hasTag ("tag2"), "ff3 tag2"); + test.is (ff3.getTagCount (), 2, "ff3 # tags"); value = ff3.get ("att1"); test.is (value, "value1", "ff3 att1"); value = ff3.get ("att2"); @@ -117,20 +106,20 @@ int main (int argc, char** argv) // [name:"value" ...]\n sample = "[" "uuid:\"00000000-0000-0000-0000-000000000000\" " - "status:\"P\" " - "tags:\"tag1&commaltag2\" " + "status:\"pending\" " + "tags:\"tag1,tag2\" " "att1:\"value1\" " "att2:\"value2\" " "description:\"Description\"" "]"; Task ff4 (sample); - value = ff2.get ("uuid"); + value = ff4.get ("uuid"); test.is (value, "00000000-0000-0000-0000-000000000000", "ff4 uuid"); - value = ff2.get ("status"); + value = ff4.get ("status"); test.is (value, "pending", "ff4 status"); - test.ok (ff2.hasTag ("tag1"), "ff4 tag1"); - test.ok (ff2.hasTag ("tag2"), "ff4 tag2"); - test.is (ff2.getTagCount (), 2, "ff4 # tags"); + test.ok (ff4.hasTag ("tag1"), "ff4 tag1"); + test.ok (ff4.hasTag ("tag2"), "ff4 tag2"); + test.is (ff4.getTagCount (), 2, "ff4 # tags"); value = ff4.get ("att1"); test.is (value, "value1", "ff4 att1"); value = ff4.get ("att2");