• 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

99.53
/src/commands/Command.cpp
1
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Copyright 2006 - 2021, Tomas Babej, Paul Beckingham, Federico Hernandez.
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 <CmdAdd.h>
31
#include <CmdAliases.h>
32
#include <CmdAnnotate.h>
33
#include <CmdAppend.h>
34
#include <CmdAttributes.h>
35
#include <CmdBurndown.h>
36
#include <CmdCalc.h>
37
#include <CmdCalendar.h>
38
#include <CmdColor.h>
39
#include <CmdColumns.h>
40
#include <CmdCommands.h>
41
#include <CmdConfig.h>
42
#include <CmdContext.h>
43
#include <CmdCount.h>
44
#include <CmdCustom.h>
45
#include <CmdDelete.h>
46
#include <CmdDenotate.h>
47
#include <CmdDiagnostics.h>
48
#include <CmdDone.h>
49
#include <CmdDuplicate.h>
50
#include <CmdEdit.h>
51
#include <Command.h>
52
#include <format.h>
53
#include <main.h>
54
#include <shared.h>
55
#include <stdlib.h>
56
#include <util.h>
57

58
#include <iostream>
59
#include <vector>
60
#ifdef HAVE_EXECUTE
61
#include <CmdExec.h>
62
#endif
63
#include <CmdExport.h>
64
#include <CmdGet.h>
65
#include <CmdHelp.h>
66
#include <CmdHistory.h>
67
#include <CmdIDs.h>
68
#include <CmdImport.h>
69
#include <CmdInfo.h>
70
#include <CmdLog.h>
71
#include <CmdLogo.h>
72
#include <CmdModify.h>
73
#include <CmdNews.h>
74
#include <CmdPrepend.h>
75
#include <CmdProjects.h>
76
#include <CmdPurge.h>
77
#include <CmdReports.h>
78
#include <CmdShow.h>
79
#include <CmdStart.h>
80
#include <CmdStats.h>
81
#include <CmdStop.h>
82
#include <CmdSummary.h>
83
#include <CmdSync.h>
84
#include <CmdTags.h>
85
#include <CmdTimesheet.h>
86
#include <CmdUDAs.h>
87
#include <CmdUndo.h>
88
#include <CmdUnique.h>
89
#include <CmdUrgency.h>
90
#include <CmdVersion.h>
91
#include <ColDue.h>
92
#include <ColProject.h>
93
#include <Context.h>
94

95
////////////////////////////////////////////////////////////////////////////////
96
void Command::factory(std::map<std::string, Command*>& all) {
4,389✔
97
  Command* c;
98

99
  c = new CmdAdd();
4,389✔
100
  all[c->keyword()] = c;
4,389✔
101
  c = new CmdAnnotate();
4,389✔
102
  all[c->keyword()] = c;
4,389✔
103
  c = new CmdAppend();
4,389✔
104
  all[c->keyword()] = c;
4,389✔
105
  c = new CmdBurndownDaily();
4,389✔
106
  all[c->keyword()] = c;
4,389✔
107
  c = new CmdBurndownMonthly();
4,389✔
108
  all[c->keyword()] = c;
4,389✔
109
  c = new CmdBurndownWeekly();
4,389✔
110
  all[c->keyword()] = c;
4,389✔
111
  c = new CmdCalc();
4,389✔
112
  all[c->keyword()] = c;
4,389✔
113
  c = new CmdCalendar();
4,389✔
114
  all[c->keyword()] = c;
4,389✔
115
  c = new CmdColor();
4,389✔
116
  all[c->keyword()] = c;
4,389✔
117
  c = new CmdColumns();
4,389✔
118
  all[c->keyword()] = c;
4,389✔
119
  c = new CmdCommands();
4,389✔
120
  all[c->keyword()] = c;
4,389✔
121
  c = new CmdCompletionAliases();
4,389✔
122
  all[c->keyword()] = c;
4,389✔
123
  c = new CmdCompletionColumns();
4,389✔
124
  all[c->keyword()] = c;
4,389✔
125
  c = new CmdCompletionCommands();
4,389✔
126
  all[c->keyword()] = c;
4,389✔
127
  c = new CmdCompletionConfig();
4,389✔
128
  all[c->keyword()] = c;
4,389✔
129
  c = new CmdCompletionContext();
4,389✔
130
  all[c->keyword()] = c;
4,389✔
131
  c = new CmdCompletionIds();
4,389✔
132
  all[c->keyword()] = c;
4,389✔
133
  c = new CmdCompletionUDAs();
4,389✔
134
  all[c->keyword()] = c;
4,389✔
135
  c = new CmdCompletionUuids();
4,389✔
136
  all[c->keyword()] = c;
4,389✔
137
  c = new CmdCompletionProjects();
4,389✔
138
  all[c->keyword()] = c;
4,389✔
139
  c = new CmdCompletionTags();
4,389✔
140
  all[c->keyword()] = c;
4,389✔
141
  c = new CmdCompletionVersion();
4,389✔
142
  all[c->keyword()] = c;
4,389✔
143
  c = new CmdConfig();
4,389✔
144
  all[c->keyword()] = c;
4,389✔
145
  c = new CmdContext();
4,389✔
146
  all[c->keyword()] = c;
4,389✔
147
  c = new CmdCount();
4,389✔
148
  all[c->keyword()] = c;
4,389✔
149
  c = new CmdDelete();
4,389✔
150
  all[c->keyword()] = c;
4,389✔
151
  c = new CmdDenotate();
4,389✔
152
  all[c->keyword()] = c;
4,389✔
153
  c = new CmdDiagnostics();
4,389✔
154
  all[c->keyword()] = c;
4,389✔
155
  c = new CmdDone();
4,389✔
156
  all[c->keyword()] = c;
4,389✔
157
  c = new CmdDuplicate();
4,389✔
158
  all[c->keyword()] = c;
4,389✔
159
  c = new CmdEdit();
4,389✔
160
  all[c->keyword()] = c;
4,389✔
161
#ifdef HAVE_EXECUTE
162
  c = new CmdExec();
4,389✔
163
  all[c->keyword()] = c;
4,389✔
164
#endif
165
  c = new CmdExport();
4,389✔
166
  all[c->keyword()] = c;
4,389✔
167
  c = new CmdGet();
4,389✔
168
  all[c->keyword()] = c;
4,389✔
169
  c = new CmdGHistoryDaily();
4,389✔
170
  all[c->keyword()] = c;
4,389✔
171
  c = new CmdGHistoryWeekly();
4,389✔
172
  all[c->keyword()] = c;
4,389✔
173
  c = new CmdGHistoryMonthly();
4,389✔
174
  all[c->keyword()] = c;
4,389✔
175
  c = new CmdGHistoryAnnual();
4,389✔
176
  all[c->keyword()] = c;
4,389✔
177
  c = new CmdHelp();
4,389✔
178
  all[c->keyword()] = c;
4,389✔
179
  c = new CmdHistoryDaily();
4,389✔
180
  all[c->keyword()] = c;
4,389✔
181
  c = new CmdHistoryWeekly();
4,389✔
182
  all[c->keyword()] = c;
4,389✔
183
  c = new CmdHistoryMonthly();
4,389✔
184
  all[c->keyword()] = c;
4,389✔
185
  c = new CmdHistoryAnnual();
4,389✔
186
  all[c->keyword()] = c;
4,389✔
187
  c = new CmdIDs();
4,389✔
188
  all[c->keyword()] = c;
4,389✔
189
  c = new CmdImport();
4,389✔
190
  all[c->keyword()] = c;
4,389✔
191
  c = new CmdInfo();
4,389✔
192
  all[c->keyword()] = c;
4,389✔
193
  c = new CmdLog();
4,389✔
194
  all[c->keyword()] = c;
4,389✔
195
  c = new CmdLogo();
4,389✔
196
  all[c->keyword()] = c;
4,389✔
197
  c = new CmdModify();
4,389✔
198
  all[c->keyword()] = c;
4,389✔
199
  c = new CmdNews();
4,389✔
200
  all[c->keyword()] = c;
4,389✔
201
  c = new CmdPrepend();
4,389✔
202
  all[c->keyword()] = c;
4,389✔
203
  c = new CmdProjects();
4,389✔
204
  all[c->keyword()] = c;
4,389✔
205
  c = new CmdPurge();
4,389✔
206
  all[c->keyword()] = c;
4,389✔
207
  c = new CmdReports();
4,389✔
208
  all[c->keyword()] = c;
4,389✔
209
  c = new CmdShow();
4,389✔
210
  all[c->keyword()] = c;
4,389✔
211
  c = new CmdShowRaw();
4,389✔
212
  all[c->keyword()] = c;
4,389✔
213
  c = new CmdStart();
4,389✔
214
  all[c->keyword()] = c;
4,389✔
215
  c = new CmdStats();
4,389✔
216
  all[c->keyword()] = c;
4,389✔
217
  c = new CmdStop();
4,389✔
218
  all[c->keyword()] = c;
4,389✔
219
  c = new CmdSummary();
4,389✔
220
  all[c->keyword()] = c;
4,389✔
221
  c = new CmdSync();
4,389✔
222
  all[c->keyword()] = c;
4,389✔
223
  c = new CmdTags();
4,389✔
224
  all[c->keyword()] = c;
4,389✔
225
  c = new CmdTimesheet();
4,389✔
226
  all[c->keyword()] = c;
4,389✔
227
  c = new CmdUDAs();
4,389✔
228
  all[c->keyword()] = c;
4,389✔
229
  c = new CmdUndo();
4,389✔
230
  all[c->keyword()] = c;
4,389✔
231
  c = new CmdUnique();
4,389✔
232
  all[c->keyword()] = c;
4,389✔
233
  c = new CmdUrgency();
4,389✔
234
  all[c->keyword()] = c;
4,389✔
235
  c = new CmdUUIDs();
4,389✔
236
  all[c->keyword()] = c;
4,389✔
237
  c = new CmdVersion();
4,389✔
238
  all[c->keyword()] = c;
4,389✔
239
  c = new CmdZshAttributes();
4,389✔
240
  all[c->keyword()] = c;
4,389✔
241
  c = new CmdZshCommands();
4,389✔
242
  all[c->keyword()] = c;
4,389✔
243
  c = new CmdZshCompletionIds();
4,389✔
244
  all[c->keyword()] = c;
4,389✔
245
  c = new CmdZshCompletionUuids();
4,389✔
246
  all[c->keyword()] = c;
4,389✔
247

248
  // Instantiate a command object for each custom report.
249
  std::vector<std::string> reports;
4,389✔
250
  for (auto& i : Context::getContext().config) {
1,083,369✔
251
    if (i.first.substr(0, 7) == "report.") {
1,078,980✔
252
      std::string report = i.first.substr(7);
453,336✔
253
      auto columns = report.find(".columns");
453,336✔
254
      if (columns != std::string::npos) reports.push_back(report.substr(0, columns));
453,336✔
255
    }
453,336✔
256
  }
257

258
  for (auto& report : reports) {
79,427✔
259
    // Make sure a custom report does not clash with a built-in command.
260
    if (all.find(report) != all.end())
75,038✔
NEW
261
      throw format("Custom report '{1}' conflicts with built-in task command.", report);
×
262

263
    c = new CmdCustom(report, "task <filter> " + report,
75,038✔
264
                      Context::getContext().config.get("report." + report + ".description"));
75,038✔
265

266
    all[c->keyword()] = c;
75,038✔
267
  }
268
}
4,389✔
269

270
////////////////////////////////////////////////////////////////////////////////
271
const std::map<Command::Category, std::string> Command::categoryNames = {
272
    // These strings are intentionally not l10n'd: they are used as identifiers.
273
    {Command::Category::unassigned, "unassigned"}  // should never happen
274
    ,
275
    {Command::Category::metadata, "metadata"},
276
    {Command::Category::report, "report"},
277
    {Command::Category::operation, "operation"},
278
    {Command::Category::context, "context"},
279
    {Command::Category::graphs, "graphs"},
280
    {Command::Category::config, "config"},
281
    {Command::Category::migration, "migration"},
282
    {Command::Category::misc, "misc"},
283
    {Command::Category::internal, "internal"},
284
    {Command::Category::UNDOCUMENTED, "undocumented"}};
285

286
////////////////////////////////////////////////////////////////////////////////
287
Command::Command()
395,442✔
288
    : _keyword(""),
395,442✔
289
      _usage(""),
395,442✔
290
      _description(""),
395,442✔
291
      _read_only(true),
395,442✔
292
      _displays_id(true),
395,442✔
293
      _needs_confirm(false),
395,442✔
294
      _needs_gc(true),
395,442✔
295
      _uses_context(false),
395,442✔
296
      _accepts_filter(false),
395,442✔
297
      _accepts_modifications(false),
395,442✔
298
      _accepts_miscellaneous(false),
395,442✔
299
      _category(Category::unassigned),
395,442✔
300
      _permission_quit(false),
395,442✔
301
      _permission_all(false),
395,442✔
302
      _first_iteration(true) {}
790,884✔
303

304
////////////////////////////////////////////////////////////////////////////////
305
std::string Command::keyword() const { return _keyword; }
395,442✔
306

307
////////////////////////////////////////////////////////////////////////////////
308
std::string Command::usage() const { return _usage; }
91✔
309

310
////////////////////////////////////////////////////////////////////////////////
311
std::string Command::description() const { return _description; }
508✔
312

313
////////////////////////////////////////////////////////////////////////////////
314
bool Command::read_only() const { return _read_only; }
5,123✔
315

316
////////////////////////////////////////////////////////////////////////////////
317
bool Command::displays_id() const { return _displays_id; }
5,123✔
318

319
////////////////////////////////////////////////////////////////////////////////
320
bool Command::needs_gc() const { return _needs_gc; }
9,507✔
321

322
////////////////////////////////////////////////////////////////////////////////
323
bool Command::uses_context() const { return _uses_context; }
7,742✔
324

325
////////////////////////////////////////////////////////////////////////////////
326
bool Command::accepts_filter() const { return _accepts_filter; }
46,368✔
327

328
////////////////////////////////////////////////////////////////////////////////
329
bool Command::accepts_modifications() const { return _accepts_modifications; }
32,661✔
330

331
////////////////////////////////////////////////////////////////////////////////
332
bool Command::accepts_miscellaneous() const { return _accepts_miscellaneous; }
17,385✔
333

334
////////////////////////////////////////////////////////////////////////////////
335
Command::Category Command::category() const { return _category; }
408✔
336

337
////////////////////////////////////////////////////////////////////////////////
338
// Returns true or false indicating whether to proceed with a write command, on
339
// a per-task basis, after (potentially) asking for permission.
340
//
341
// Factors:
342
//   filtered.size ()
343
//   rc.bulk
344
//   rc.confirmation
345
//   this->_read_only
346
bool Command::permission(const std::string& question, unsigned int quantity) {
439✔
347
  // Read-only commands do not need to seek permission.  Write commands are
348
  // granted permission automatically if the 'all' selection was made in an
349
  // earlier call.  Or if the 'all' option has already been made.
350
  if (_read_only || _permission_all) return true;
439✔
351

352
  // If the 'quit' selection has already been made.
353
  if (_permission_quit) return false;
427✔
354

355
  // What remains are write commands that have not yet selected 'all' or 'quit'.
356
  // Describe the task.
357
  bool confirmation = Context::getContext().config.getBoolean("confirmation");
427✔
358
  unsigned int bulk = Context::getContext().config.getInteger("bulk");
427✔
359

360
  // Quantity 1 modifications have optional confirmation, and only (y/n).
361
  if (quantity == 1) {
427✔
362
    if (!_needs_confirm || !confirmation) return true;
382✔
363

364
    bool answer = confirm(question);
53✔
365
    return answer;
53✔
366
  }
367

368
  // 1 < Quantity < bulk modifications have optional confirmation, in the (y/n/a/q)
369
  // style. Bulk = 0 denotes infinite bulk.
370
  if ((bulk == 0 || quantity < bulk) && (!_needs_confirm || !confirmation)) return true;
45✔
371

372
  if (Context::getContext().verbose("blank") && !_first_iteration) std::cout << '\n';
27✔
373
  int answer = confirm4(question);
27✔
374
  _first_iteration = false;
27✔
375
  switch (answer) {
27✔
376
    case 1:
13✔
377
      return true;  // yes
13✔
378
    case 2:
5✔
379
      _permission_all = true;
5✔
380
      return true;  // all
5✔
381
    case 3:
4✔
382
      _permission_quit = true;
4✔
383
      return false;  // quit
4✔
384
  }
385

386
  return false;  // This line keeps the compiler happy.
5✔
387
}
388

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