Skip to content

Commit d1b0f8d

Browse files
committed
backend: Make refreshing newly added tasks more robust
The mechanism for obtaining information about newly added task (also called refreshing) was a bit fragile in situations when the only reference to the new task object is an ID number. In particular, if taskwarrior has some GC cleanup pending, and a new task is added through tasklib, the GC will be performed while exporting the information about the newly added task, thus changing the IDs and rendering the ID reference invalid. This effect is now mitigated in two ways: 1.) We use the new-uuid (available since 2.4.0) verbosity token, which makes "task add" command output a UUID for the newly added task. 2.) The GC mechanism is disabled during refreshing. This will only be useful if a manual ID reference was used to get a task by the user.
1 parent de17dfc commit d1b0f8d

1 file changed

Lines changed: 13 additions & 9 deletions

File tree

tasklib/backends.py

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -330,16 +330,19 @@ def save_task(self, task):
330330

331331
args = [task['uuid'], 'modify'] if task.saved else ['add']
332332
args.extend(self._get_modified_task_fields_as_args(task))
333-
output = self.execute_command(args)
333+
output = self.execute_command(
334+
args,
335+
config_override={'verbose': 'new-uuid'}
336+
)
334337

335338
# Parse out the new ID, if the task is being added for the first time
336339
if not task.saved:
337340
id_lines = [l for l in output if l.startswith('Created task ')]
338341

339342
# Complain loudly if it seems that more tasks were created
340343
# Should not happen.
341-
# Expected output: Created task 1.
342-
# Created task 1 (recurrence template).
344+
# Expected output: Created task bd23f69a-a078-48a4-ac11-afba0643eca9.
345+
# Created task bd23f69a-a078-48a4-ac11-afba0643eca9 (recurrence template).
343346
if len(id_lines) != 1 or len(id_lines[0].split(' ')) not in (3, 5):
344347
raise TaskWarriorException(
345348
'Unexpected output when creating '
@@ -349,11 +352,8 @@ def save_task(self, task):
349352
# Circumvent the ID storage, since ID is considered read-only
350353
identifier = id_lines[0].split(' ')[2].rstrip('.')
351354

352-
# Identifier can be either ID or UUID for completed tasks
353-
try:
354-
task._data['id'] = int(identifier)
355-
except ValueError:
356-
task._data['uuid'] = identifier
355+
# Identifier is UUID, because we used new-uuid verbosity override
356+
task._data['uuid'] = identifier
357357

358358
# Refreshing is very important here, as not only modification time
359359
# is updated, but arbitrary attribute may have changed due hooks
@@ -385,7 +385,11 @@ def refresh_task(self, task, after_save=False):
385385
# of newly saved tasks. Any other place in the code is fine
386386
# with using UUID only.
387387
args = [task['uuid'] or task['id'], 'export']
388-
output = self.execute_command(args)
388+
output = self.execute_command(
389+
args,
390+
# Supress GC, which can change ID numbers (undesirable for refresh)
391+
config_override={'gc': '0'}
392+
)
389393

390394
def valid(output):
391395
return len(output) == 1 and output[0].startswith('{')

0 commit comments

Comments
 (0)