• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

GothenburgBitFactory / taskwarrior / 9929113862

14 Jul 2024 03:59PM UTC coverage: 84.28% (-0.07%) from 84.35%
9929113862

push

github

web-flow
Restore 'task purge' functionality (#3540)

Co-authored-by: ryneeverett <ryneeverett@gmail.com>

69 of 74 new or added lines in 3 files covered. (93.24%)

28 existing lines in 2 files now uncovered.

19327 of 22932 relevant lines covered (84.28%)

20319.09 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

77.94
/src/tc/Replica.cpp
1
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Copyright 2022, Dustin J. Mitchell
4
//
5
// Permission is hereby granted, free of charge, to any person obtaining a copy
6
// of this software and associated documentation files (the "Software"), to deal
7
// in the Software without restriction, including without limitation the rights
8
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
// copies of the Software, and to permit persons to whom the Software is
10
// furnished to do so, subject to the following conditions:
11
//
12
// The above copyright notice and this permission notice shall be included
13
// in all copies or substantial portions of the Software.
14
//
15
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
// SOFTWARE.
22
//
23
// https://www.opensource.org/licenses/mit-license.php
24
//
25
////////////////////////////////////////////////////////////////////////////////
26

27
#include <cmake.h>
28
#include <format.h>
29
#include "tc/Replica.h"
30
#include "tc/Task.h"
31
#include "tc/Server.h"
32
#include "tc/WorkingSet.h"
33
#include "tc/util.h"
34
#include <iostream>
35

36
using namespace tc::ffi;
37

38
////////////////////////////////////////////////////////////////////////////////
39
tc::ReplicaGuard::ReplicaGuard (Replica &replica, Task &task) :
3,483✔
40
  replica(replica),
3,483✔
41
  task(task)
3,483✔
42
{
43
  // "steal" the reference from the Replica and store it locally, so that any
44
  // attempt to use the Replica will fail
45
  tcreplica = replica.inner.release();
3,483✔
46
  task.to_mut(tcreplica);
3,483✔
47
}
3,483✔
48

49
////////////////////////////////////////////////////////////////////////////////
50
tc::ReplicaGuard::~ReplicaGuard ()
3,483✔
51
{
52
  task.to_immut();
3,483✔
53
  // return the reference to the Replica.
54
  replica.inner.reset(tcreplica);
3,483✔
55
}
3,483✔
56

57
////////////////////////////////////////////////////////////////////////////////
58
tc::Replica::Replica ()
4,391✔
59
{
60
  inner = unique_tcreplica_ptr (
8,782✔
61
      tc_replica_new_in_memory (),
62
      [](TCReplica* rep) { tc_replica_free (rep); });
8,782✔
63
}
4,391✔
64

65
////////////////////////////////////////////////////////////////////////////////
66
tc::Replica::Replica (Replica &&other) noexcept
×
67
{
68
  // move inner from other
69
  inner = unique_tcreplica_ptr (
×
70
      other.inner.release (),
71
      [](TCReplica* rep) { tc_replica_free (rep); });
×
72
}
73

74
////////////////////////////////////////////////////////////////////////////////
75
tc::Replica& tc::Replica::operator= (Replica &&other) noexcept
4,382✔
76
{
77
  if (this != &other) {
4,382✔
78
    // move inner from other
79
    inner = unique_tcreplica_ptr (
8,764✔
80
        other.inner.release (),
81
        [](TCReplica* rep) { tc_replica_free (rep); });
8,764✔
82
  }
83
  return *this;
4,382✔
84
}
85

86
////////////////////////////////////////////////////////////////////////////////
87
tc::Replica::Replica (const std::string& dir, bool create_if_missing)
4,383✔
88
{
89
  TCString path = tc_string_borrow (dir.c_str ());
4,383✔
90
  TCString error;
91
  auto tcreplica = tc_replica_new_on_disk (path, create_if_missing, &error);
4,383✔
92
  if (!tcreplica) {
4,383✔
93
    auto errmsg = format ("Could not create replica at {1}: {2}", dir, tc_string_content (&error));
2✔
94
    tc_string_free (&error);
1✔
95
    throw errmsg;
1✔
96
  }
1✔
97
  inner = unique_tcreplica_ptr (
8,764✔
98
      tcreplica,
99
      [](TCReplica* rep) { tc_replica_free (rep); });
4,382✔
100
}
4,383✔
101

102
////////////////////////////////////////////////////////////////////////////////
103
tc::WorkingSet tc::Replica::working_set ()
4,704✔
104
{
105
  TCWorkingSet *tcws = tc_replica_working_set (&*inner);
4,704✔
106
  if (!tcws) {
4,704✔
107
    throw replica_error ();
×
108
  }
109
  return WorkingSet {tcws};
4,704✔
110
}
111

112
////////////////////////////////////////////////////////////////////////////////
113
std::optional<tc::Task> tc::Replica::get_task (const std::string &uuid)
27,240✔
114
{
115
  TCTask *tctask = tc_replica_get_task (&*inner, uuid2tc (uuid));
27,240✔
116
  if (!tctask) {
27,240✔
117
    auto error = tc_replica_error (&*inner);
1,587✔
118
    if (error.ptr) {
1,587✔
119
      throw replica_error (error);
×
120
    } else {
121
      return std::nullopt;
1,587✔
122
    }
123
  }
124
  return std::make_optional (Task (tctask));
25,653✔
125
}
126

127
////////////////////////////////////////////////////////////////////////////////
128
tc::Task tc::Replica::new_task (tc::Status status, const std::string &description)
1✔
129
{
130
  TCTask *tctask = tc_replica_new_task (&*inner, (tc::ffi::TCStatus)status, string2tc (description));
1✔
131
  if (!tctask) {
1✔
132
    throw replica_error ();
×
133
  }
134
  return Task (tctask);
1✔
135
}
136

137
////////////////////////////////////////////////////////////////////////////////
138
tc::Task tc::Replica::import_task_with_uuid (const std::string &uuid)
2,931✔
139
{
140
  TCTask *tctask = tc_replica_import_task_with_uuid (&*inner, uuid2tc (uuid));
2,931✔
141
  if (!tctask) {
2,931✔
142
    throw replica_error ();
×
143
  }
144
  return Task (tctask);
2,931✔
145
}
146

147
////////////////////////////////////////////////////////////////////////////////
148
void tc::Replica::delete_task (const std::string &uuid)
6✔
149
{
150
  auto res = tc_replica_delete_task (&*inner, uuid2tc (uuid));
6✔
151
  if (res != TC_RESULT_OK) {
6✔
NEW
152
    throw replica_error ();
×
153
  }
154
}
6✔
155

156
////////////////////////////////////////////////////////////////////////////////
157
void tc::Replica::expire_tasks ()
1✔
158
{
159
  auto res = tc_replica_expire_tasks (&*inner);
1✔
160
  if (res != TC_RESULT_OK) {
1✔
161
    throw replica_error ();
×
162
  }
163
}
1✔
164

165
////////////////////////////////////////////////////////////////////////////////
166
void tc::Replica::sync (Server server, bool avoid_snapshots)
2✔
167
{
168
  // The server remains owned by this function, per tc_replica_sync docs.
169
  auto res = tc_replica_sync (&*inner, server.inner.get(), avoid_snapshots);
2✔
170
  if (res != TC_RESULT_OK) {
2✔
171
    throw replica_error ();
×
172
  }
173
}
2✔
174

175
////////////////////////////////////////////////////////////////////////////////
176
TCReplicaOpList tc::Replica::get_undo_ops ()
7✔
177
{
178
  return tc_replica_get_undo_ops(&*inner);
7✔
179
}
180

181
////////////////////////////////////////////////////////////////////////////////
182
void tc::Replica::commit_undo_ops (TCReplicaOpList tc_undo_ops, int32_t *undone_out)
4✔
183
{
184
  auto res = tc_replica_commit_undo_ops (&*inner, tc_undo_ops, undone_out);
4✔
185
  if (res != TC_RESULT_OK) {
4✔
186
    throw replica_error ();
×
187
  }
188
}
4✔
189

190
////////////////////////////////////////////////////////////////////////////////
191
void tc::Replica::free_replica_ops (TCReplicaOpList tc_undo_ops)
3✔
192
{
193
  tc_replica_op_list_free(&tc_undo_ops);
3✔
194
}
3✔
195

196
////////////////////////////////////////////////////////////////////////////////
197
std::string tc::Replica::get_op_uuid(TCReplicaOp &tc_replica_op) const
27✔
198
{
199
  TCString uuid = tc_replica_op_get_uuid(&tc_replica_op);
27✔
200
  return tc2string(uuid);
54✔
201
}
202

203
////////////////////////////////////////////////////////////////////////////////
204
std::string tc::Replica::get_op_property(TCReplicaOp &tc_replica_op) const
25✔
205
{
206
  TCString property = tc_replica_op_get_property(&tc_replica_op);
25✔
207
  return tc2string(property);
50✔
208
}
209

210
////////////////////////////////////////////////////////////////////////////////
211
std::string tc::Replica::get_op_value(TCReplicaOp &tc_replica_op) const
25✔
212
{
213
  TCString value = tc_replica_op_get_value(&tc_replica_op);
25✔
214
  return tc2string(value);
50✔
215
}
216

217
////////////////////////////////////////////////////////////////////////////////
218
std::string tc::Replica::get_op_old_value(TCReplicaOp &tc_replica_op) const
25✔
219
{
220
  TCString old_value = tc_replica_op_get_old_value(&tc_replica_op);
25✔
221
  return tc2string(old_value);
50✔
222
}
223

224
////////////////////////////////////////////////////////////////////////////////
225
std::string tc::Replica::get_op_timestamp(TCReplicaOp &tc_replica_op) const
×
226
{
227
  TCString timestamp = tc_replica_op_get_timestamp(&tc_replica_op);
×
228
  return tc2string(timestamp);
×
229
}
230

231
////////////////////////////////////////////////////////////////////////////////
232
std::string tc::Replica::get_op_old_task_description(TCReplicaOp &tc_replica_op) const
×
233
{
234
  TCString description = tc_replica_op_get_old_task_description(&tc_replica_op);
×
235
  return tc2string(description);
×
236
}
237

238
////////////////////////////////////////////////////////////////////////////////
239
int64_t tc::Replica::num_local_operations ()
5✔
240
{
241
  auto num = tc_replica_num_local_operations (&*inner);
5✔
242
  if (num < 0) {
5✔
243
    throw replica_error ();
×
244
  }
245
  return num;
5✔
246
}
247

248
////////////////////////////////////////////////////////////////////////////////
249
int64_t tc::Replica::num_undo_points ()
3✔
250
{
251
  auto num = tc_replica_num_undo_points (&*inner);
3✔
252
  if (num < 0) {
3✔
253
    throw replica_error ();
×
254
  }
255
  return num;
3✔
256
}
257

258
////////////////////////////////////////////////////////////////////////////////
259
std::vector<tc::Task> tc::Replica::all_tasks ()
2,303✔
260
{
261
  TCTaskList tasks = tc_replica_all_tasks (&*inner);
2,303✔
262
  if (!tasks.items) {
2,303✔
263
    throw replica_error ();
×
264
  }
265

266
  std::vector <Task> all;
2,303✔
267
  all.reserve (tasks.len);
2,303✔
268
  for (size_t i = 0; i < tasks.len; i++) {
737,160✔
269
    auto tctask = tc_task_list_take (&tasks, i);
734,857✔
270
    if (tctask) {
734,857✔
271
      all.push_back (Task (tctask));
734,857✔
272
    }
273
  }
274

275
  return all;
4,606✔
276
}
277

278
////////////////////////////////////////////////////////////////////////////////
279
void tc::Replica::rebuild_working_set (bool force)
876✔
280
{
281
  auto res = tc_replica_rebuild_working_set (&*inner, force);
876✔
282
  if (res != TC_RESULT_OK) {
876✔
283
    throw replica_error ();
×
284
  }
285
}
876✔
286

287
////////////////////////////////////////////////////////////////////////////////
288
tc::ReplicaGuard tc::Replica::mutate_task (tc::Task &task) {
3,483✔
289
  return ReplicaGuard(*this, task);
3,483✔
290
}
291

292
////////////////////////////////////////////////////////////////////////////////
293
std::string tc::Replica::replica_error () {
×
294
  return replica_error (tc_replica_error (&*inner));
×
295
}
296

297
////////////////////////////////////////////////////////////////////////////////
298
std::string tc::Replica::replica_error (TCString error) {
×
299
  std::string errmsg;
×
300
  if (!error.ptr) {
×
301
    errmsg = std::string ("Unknown TaskChampion error");
×
302
  } else {
303
    errmsg = std::string (tc_string_content (&error));
×
304
  }
305
  tc_string_free (&error);
×
306
  return errmsg;
×
307
}
308

309
////////////////////////////////////////////////////////////////////////////////
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc