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

GothenburgBitFactory / taskwarrior / 10152339701

29 Jul 2024 09:45PM UTC coverage: 84.437% (+0.07%) from 84.372%
10152339701

push

github

web-flow
Merge pull request #3566 from felixschurk/add-clang-format

Add clang-format to enforce style guide

12359 of 13760 new or added lines in 147 files covered. (89.82%)

123 existing lines in 42 files now uncovered.

19070 of 22585 relevant lines covered (84.44%)

19724.02 hits per line

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

78.13
/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
// cmake.h include header must come first
29

30
#include <format.h>
31

32
#include <iostream>
33

34
#include "tc/Replica.h"
35
#include "tc/Server.h"
36
#include "tc/Task.h"
37
#include "tc/WorkingSet.h"
38
#include "tc/util.h"
39

40
using namespace tc::ffi;
41

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

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

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

63
////////////////////////////////////////////////////////////////////////////////
NEW
64
tc::Replica::Replica(Replica &&other) noexcept {
×
65
  // move inner from other
NEW
66
  inner = unique_tcreplica_ptr(other.inner.release(), [](TCReplica *rep) { tc_replica_free(rep); });
×
67
}
68

69
////////////////////////////////////////////////////////////////////////////////
70
tc::Replica &tc::Replica::operator=(Replica &&other) noexcept {
4,390✔
71
  if (this != &other) {
4,390✔
72
    // move inner from other
73
    inner =
74
        unique_tcreplica_ptr(other.inner.release(), [](TCReplica *rep) { tc_replica_free(rep); });
8,780✔
75
  }
76
  return *this;
4,390✔
77
}
78

79
////////////////////////////////////////////////////////////////////////////////
80
tc::Replica::Replica(const std::string &dir, bool create_if_missing) {
4,391✔
81
  TCString path = tc_string_borrow(dir.c_str());
4,391✔
82
  TCString error;
83
  auto tcreplica = tc_replica_new_on_disk(path, create_if_missing, &error);
4,391✔
84
  if (!tcreplica) {
4,391✔
85
    auto errmsg = format("Could not create replica at {1}: {2}", dir, tc_string_content(&error));
2✔
86
    tc_string_free(&error);
1✔
87
    throw errmsg;
1✔
88
  }
1✔
89
  inner = unique_tcreplica_ptr(tcreplica, [](TCReplica *rep) { tc_replica_free(rep); });
4,390✔
90
}
4,391✔
91

92
////////////////////////////////////////////////////////////////////////////////
93
tc::WorkingSet tc::Replica::working_set() {
4,711✔
94
  TCWorkingSet *tcws = tc_replica_working_set(&*inner);
4,711✔
95
  if (!tcws) {
4,711✔
NEW
96
    throw replica_error();
×
97
  }
98
  return WorkingSet{tcws};
4,711✔
99
}
100

101
////////////////////////////////////////////////////////////////////////////////
102
std::optional<tc::Task> tc::Replica::get_task(const std::string &uuid) {
27,254✔
103
  TCTask *tctask = tc_replica_get_task(&*inner, uuid2tc(uuid));
27,254✔
104
  if (!tctask) {
27,254✔
105
    auto error = tc_replica_error(&*inner);
1,588✔
106
    if (error.ptr) {
1,588✔
NEW
107
      throw replica_error(error);
×
108
    } else {
109
      return std::nullopt;
1,588✔
110
    }
111
  }
112
  return std::make_optional(Task(tctask));
25,666✔
113
}
114

115
////////////////////////////////////////////////////////////////////////////////
116
tc::Task tc::Replica::new_task(tc::Status status, const std::string &description) {
1✔
117
  TCTask *tctask = tc_replica_new_task(&*inner, (tc::ffi::TCStatus)status, string2tc(description));
1✔
118
  if (!tctask) {
1✔
NEW
119
    throw replica_error();
×
120
  }
121
  return Task(tctask);
1✔
122
}
123

124
////////////////////////////////////////////////////////////////////////////////
125
tc::Task tc::Replica::import_task_with_uuid(const std::string &uuid) {
2,935✔
126
  TCTask *tctask = tc_replica_import_task_with_uuid(&*inner, uuid2tc(uuid));
2,935✔
127
  if (!tctask) {
2,935✔
NEW
128
    throw replica_error();
×
129
  }
130
  return Task(tctask);
2,935✔
131
}
132

133
////////////////////////////////////////////////////////////////////////////////
134
void tc::Replica::delete_task(const std::string &uuid) {
6✔
135
  auto res = tc_replica_delete_task(&*inner, uuid2tc(uuid));
6✔
136
  if (res != TC_RESULT_OK) {
6✔
NEW
137
    throw replica_error();
×
138
  }
139
}
6✔
140

141
////////////////////////////////////////////////////////////////////////////////
142
void tc::Replica::expire_tasks() {
1✔
143
  auto res = tc_replica_expire_tasks(&*inner);
1✔
144
  if (res != TC_RESULT_OK) {
1✔
NEW
145
    throw replica_error();
×
146
  }
147
}
1✔
148

149
////////////////////////////////////////////////////////////////////////////////
150
void tc::Replica::sync(Server server, bool avoid_snapshots) {
2✔
151
  // The server remains owned by this function, per tc_replica_sync docs.
152
  auto res = tc_replica_sync(&*inner, server.inner.get(), avoid_snapshots);
2✔
153
  if (res != TC_RESULT_OK) {
2✔
NEW
154
    throw replica_error();
×
155
  }
156
}
2✔
157

158
////////////////////////////////////////////////////////////////////////////////
159
TCReplicaOpList tc::Replica::get_undo_ops() { return tc_replica_get_undo_ops(&*inner); }
7✔
160

161
////////////////////////////////////////////////////////////////////////////////
162
void tc::Replica::commit_undo_ops(TCReplicaOpList tc_undo_ops, int32_t *undone_out) {
4✔
163
  auto res = tc_replica_commit_undo_ops(&*inner, tc_undo_ops, undone_out);
4✔
164
  if (res != TC_RESULT_OK) {
4✔
NEW
165
    throw replica_error();
×
166
  }
167
}
4✔
168

169
////////////////////////////////////////////////////////////////////////////////
170
void tc::Replica::free_replica_ops(TCReplicaOpList tc_undo_ops) {
3✔
171
  tc_replica_op_list_free(&tc_undo_ops);
3✔
172
}
3✔
173

174
////////////////////////////////////////////////////////////////////////////////
175
std::string tc::Replica::get_op_uuid(TCReplicaOp &tc_replica_op) const {
26✔
176
  TCString uuid = tc_replica_op_get_uuid(&tc_replica_op);
26✔
177
  return tc2string(uuid);
52✔
178
}
179

180
////////////////////////////////////////////////////////////////////////////////
181
std::string tc::Replica::get_op_property(TCReplicaOp &tc_replica_op) const {
24✔
182
  TCString property = tc_replica_op_get_property(&tc_replica_op);
24✔
183
  return tc2string(property);
48✔
184
}
185

186
////////////////////////////////////////////////////////////////////////////////
187
std::string tc::Replica::get_op_value(TCReplicaOp &tc_replica_op) const {
24✔
188
  TCString value = tc_replica_op_get_value(&tc_replica_op);
24✔
189
  return tc2string(value);
48✔
190
}
191

192
////////////////////////////////////////////////////////////////////////////////
193
std::string tc::Replica::get_op_old_value(TCReplicaOp &tc_replica_op) const {
24✔
194
  TCString old_value = tc_replica_op_get_old_value(&tc_replica_op);
24✔
195
  return tc2string(old_value);
48✔
196
}
197

198
////////////////////////////////////////////////////////////////////////////////
NEW
199
std::string tc::Replica::get_op_timestamp(TCReplicaOp &tc_replica_op) const {
×
UNCOV
200
  TCString timestamp = tc_replica_op_get_timestamp(&tc_replica_op);
×
201
  return tc2string(timestamp);
×
202
}
203

204
////////////////////////////////////////////////////////////////////////////////
NEW
205
std::string tc::Replica::get_op_old_task_description(TCReplicaOp &tc_replica_op) const {
×
UNCOV
206
  TCString description = tc_replica_op_get_old_task_description(&tc_replica_op);
×
207
  return tc2string(description);
×
208
}
209

210
////////////////////////////////////////////////////////////////////////////////
211
int64_t tc::Replica::num_local_operations() {
5✔
212
  auto num = tc_replica_num_local_operations(&*inner);
5✔
213
  if (num < 0) {
5✔
NEW
214
    throw replica_error();
×
215
  }
216
  return num;
5✔
217
}
218

219
////////////////////////////////////////////////////////////////////////////////
220
int64_t tc::Replica::num_undo_points() {
3✔
221
  auto num = tc_replica_num_undo_points(&*inner);
3✔
222
  if (num < 0) {
3✔
NEW
223
    throw replica_error();
×
224
  }
225
  return num;
3✔
226
}
227

228
////////////////////////////////////////////////////////////////////////////////
229
std::vector<tc::Task> tc::Replica::all_tasks() {
2,304✔
230
  TCTaskList tasks = tc_replica_all_tasks(&*inner);
2,304✔
231
  if (!tasks.items) {
2,304✔
NEW
232
    throw replica_error();
×
233
  }
234

235
  std::vector<Task> all;
2,304✔
236
  all.reserve(tasks.len);
2,304✔
237
  for (size_t i = 0; i < tasks.len; i++) {
737,161✔
238
    auto tctask = tc_task_list_take(&tasks, i);
734,857✔
239
    if (tctask) {
734,857✔
240
      all.push_back(Task(tctask));
734,857✔
241
    }
242
  }
243

244
  return all;
4,608✔
245
}
246

247
////////////////////////////////////////////////////////////////////////////////
248
void tc::Replica::rebuild_working_set(bool force) {
879✔
249
  auto res = tc_replica_rebuild_working_set(&*inner, force);
879✔
250
  if (res != TC_RESULT_OK) {
879✔
NEW
251
    throw replica_error();
×
252
  }
253
}
879✔
254

255
////////////////////////////////////////////////////////////////////////////////
256
tc::ReplicaGuard tc::Replica::mutate_task(tc::Task &task) { return ReplicaGuard(*this, task); }
3,488✔
257

258
////////////////////////////////////////////////////////////////////////////////
NEW
259
std::string tc::Replica::replica_error() { return replica_error(tc_replica_error(&*inner)); }
×
260

261
////////////////////////////////////////////////////////////////////////////////
NEW
262
std::string tc::Replica::replica_error(TCString error) {
×
263
  std::string errmsg;
×
264
  if (!error.ptr) {
×
NEW
265
    errmsg = std::string("Unknown TaskChampion error");
×
266
  } else {
NEW
267
    errmsg = std::string(tc_string_content(&error));
×
268
  }
NEW
269
  tc_string_free(&error);
×
270
  return errmsg;
×
271
}
272

273
////////////////////////////////////////////////////////////////////////////////
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