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

GothenburgBitFactory / taskwarrior / 9829041530

07 Jul 2024 05:19PM CUT coverage: 84.053% (-0.03%) from 84.083%
9829041530

push

github

web-flow
Remove duplicate check from task diag (#3545)

1 of 1 new or added line in 1 file covered. (100.0%)

7 existing lines in 3 files now uncovered.

19202 of 22845 relevant lines covered (84.05%)

20027.35 hits per line

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

90.2
/src/commands/CmdDiagnostics.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
#include <CmdDiagnostics.h>
29
#include <iomanip>
30
#include <sstream>
31
#include <algorithm>
32
#include <stdlib.h>
33
#include <time.h>
34
#include <RX.h>
35
#include <Context.h>
36
#include <shared.h>
37
#include <format.h>
38
#ifdef HAVE_COMMIT
39
#include <commit.h>
40
#endif
41

42
////////////////////////////////////////////////////////////////////////////////
43
CmdDiagnostics::CmdDiagnostics ()
4,285✔
44
{
45
  _keyword               = "diagnostics";
4,285✔
46
  _usage                 = "task          diagnostics";
4,285✔
47
  _description           = "Platform, build and environment details";
4,285✔
48
  _read_only             = true;
4,285✔
49
  _displays_id           = false;
4,285✔
50
  _needs_gc              = false;
4,285✔
51
  _uses_context          = false;
4,285✔
52
  _accepts_filter        = false;
4,285✔
53
  _accepts_modifications = false;
4,285✔
54
  _accepts_miscellaneous = false;
4,285✔
55
  _category              = Command::Category::misc;
4,285✔
56
}
4,285✔
57

58
////////////////////////////////////////////////////////////////////////////////
59
// This command will generate output that is intended to help diagnose problems.
60
//
61
// Although this will change over time, initially this command will answer the
62
// kind of questions we always have to ask whenever something is wrong.
63
int CmdDiagnostics::execute (std::string& output)
7✔
64
{
65
  Color bold;
7✔
66
  if (Context::getContext ().color ())
7✔
67
    bold = Color ("bold");
1✔
68

69
  std::stringstream out;
7✔
70
  out << '\n'
71
      << bold.colorize (PACKAGE_STRING)
14✔
72
      << '\n';
14✔
73

74
  out << "   Platform: " << osName ()
7✔
75
      << "\n\n";
7✔
76

77
  // Compiler.
78
  out << bold.colorize ("Compiler")
14✔
79
      << '\n'
80
#ifdef __VERSION__
81
      << "    Version: "
82
      << __VERSION__ << '\n'
83
#endif
84
      << "       Caps:"
85
#ifdef __STDC__
86
      << " +stdc"
87
#endif
88
#ifdef __STDC_HOSTED__
89
      << " +stdc_hosted"
90
#endif
91
#ifdef __STDC_VERSION__
92
      << " +" << __STDC_VERSION__
93
#endif
94
#ifdef _POSIX_VERSION
95
      << " +" << _POSIX_VERSION
96
#endif
97
#ifdef _POSIX2_C_VERSION
98
      << " +" << _POSIX2_C_VERSION
99
#endif
100
#ifdef _ILP32
101
      << " +ILP32"
102
#endif
103
#ifdef _LP64
104
      << " +LP64"
105
#endif
106
      << " +c"      << 8 * sizeof (char)
7✔
107
      << " +i"      << 8 * sizeof (int)
7✔
108
      << " +l"      << 8 * sizeof (long)
7✔
109
      << " +vp"     << 8 * sizeof (void*)
7✔
110
      << " +time_t" << 8 * sizeof (time_t)
7✔
111
      << '\n';
7✔
112

113
  // Compiler compliance level.
114
  out << " Compliance: "
115
      << cppCompliance ()
7✔
116
      << "\n\n";
7✔
117

118
  out << bold.colorize ("Build Features")
14✔
119
      << '\n'
120

121
#ifdef HAVE_COMMIT
122
      << "     Commit: " << COMMIT << '\n'
123
#endif
124
      << "      CMake: " << CMAKE_VERSION << '\n';
7✔
125

126
  out << "    libuuid: "
127
#ifdef HAVE_UUID_UNPARSE_LOWER
128
      << "libuuid + uuid_unparse_lower"
129
#else
130
      << "libuuid, no uuid_unparse_lower"
131
#endif
132
      << '\n';
7✔
133

134
  out << " Build type: "
135
#ifdef CMAKE_BUILD_TYPE
136
      << CMAKE_BUILD_TYPE
137
#else
138
      << '-'
139
#endif
140
      << "\n\n";
7✔
141

142
  // Config: .taskrc found, readable, writable
143
  File rcFile (Context::getContext ().config.file ());
7✔
144
  out << bold.colorize ("Configuration")
14✔
145
      << '\n'
146
      << "       File: " << rcFile._data << ' '
147
      << (rcFile.exists ()
14✔
148
           ? "(found)"
149
           : "(missing)")
150
      << ", " << rcFile.size () << ' ' << "bytes"
7✔
151
      << ", mode "
152
      << std::setbase (8)
7✔
153
      << rcFile.mode ()
7✔
154
      << '\n';
7✔
155

156
  // Config: data.location found, readable, writable
157
  File location (Context::getContext ().config.get ("data.location"));
14✔
158
  out << "       Data: " << location._data << ' '
159
      << (location.exists ()
14✔
160
           ? "(found)"
161
           : "(missing)")
162
      << ", " << (location.is_directory () ? "dir" : "?")
14✔
163
      << ", mode "
164
      << std::setbase (8)
7✔
165
      << location.mode ()
7✔
166
      << '\n';
7✔
167

168
  char* env = getenv ("TASKRC");
7✔
169
  if (env)
7✔
170
    out << "     TASKRC: "
171
        << env
172
        << '\n';
7✔
173

174
  env = getenv ("TASKDATA");
7✔
175
  if (env)
7✔
176
    out << "   TASKDATA: "
177
        << env
178
        << '\n';
7✔
179

180
  out << "         GC: "
181
      << (Context::getContext ().config.getBoolean ("gc")
14✔
182
           ? "Enabled"
183
           : "Disabled")
184
      << '\n';
14✔
185

186
  // Determine rc.editor/$EDITOR/$VISUAL.
187
  char* peditor;
188
  if (Context::getContext ().config.get ("editor") != "")
7✔
189
    out << "  rc.editor: " << Context::getContext ().config.get ("editor") << '\n';
1✔
190
  else if ((peditor = getenv ("VISUAL")) != nullptr)
6✔
191
    out << "    $VISUAL: " << peditor << '\n';
×
192
  else if ((peditor = getenv ("EDITOR")) != nullptr)
6✔
193
    out << "    $EDITOR: " << peditor << '\n';
×
194

195
  // Display hook status.
196
  Path hookLocation;
7✔
197
  if (Context::getContext ().config.has ("hooks.location"))
7✔
198
  {
199
    hookLocation = Path (Context::getContext ().config.get ("hooks.location"));
×
200
  }
201
  else
202
  {
203
    hookLocation = Path (Context::getContext ().config.get ("data.location"));
7✔
204
    hookLocation += "hooks";
7✔
205
  }
206

207
  out << bold.colorize ("Hooks")
14✔
208
      << '\n'
209
      << "     System: "
210
      << (Context::getContext ().config.getBoolean ("hooks") ? "Enabled" : "Disabled")
14✔
211
      << '\n'
212
      << "   Location: "
213
      << static_cast <std::string> (hookLocation)
7✔
214
      << '\n';
14✔
215

216
  auto hooks = Context::getContext ().hooks.list ();
7✔
217
  if (hooks.size ())
7✔
218
  {
219
    unsigned int longest = 0;
1✔
220
    for (auto& hook : hooks)
5✔
221
      if (hook.length () > longest)
4✔
222
        longest = hook.length ();
4✔
223
    longest -= hookLocation._data.length () + 1;
1✔
224

225
    out << "     Active: ";
1✔
226
    int count = 0;
1✔
227
    for (auto& hook : hooks)
5✔
228
    {
229
      Path p (hook);
4✔
230
      if (! p.is_directory ())
4✔
231
      {
232
        auto name = p.name ();
4✔
233

234
        if (p.executable () &&
8✔
235
            (name.substr (0, 6) == "on-add"    ||
8✔
236
             name.substr (0, 9) == "on-modify" ||
8✔
237
             name.substr (0, 9) == "on-launch" ||
7✔
238
             name.substr (0, 7) == "on-exit"))
5✔
239
        {
240
          out << (count++ ? "             " : "");
1✔
241

242
          out.width (longest);
1✔
243
          out << std::left << name
1✔
244
              << " (executable)"
245
              << (p.is_link () ? " (symlink)" : "")
2✔
246
              << '\n';
1✔
247
        }
248
      }
4✔
249
    }
4✔
250

251
    if (! count)
1✔
252
      out << '\n';
×
253

254
    out << "   Inactive: ";
1✔
255
    count = 0;
1✔
256
    for (auto& hook : hooks)
5✔
257
    {
258
      Path p (hook);
4✔
259
      if (! p.is_directory ())
4✔
260
      {
261
        auto name = p.name ();
4✔
262

263
        if (! p.executable () ||
6✔
264
            (name.substr (0, 6) != "on-add"    &&
6✔
265
             name.substr (0, 9) != "on-modify" &&
6✔
266
             name.substr (0, 9) != "on-launch" &&
6✔
267
             name.substr (0, 7) != "on-exit"))
5✔
268
        {
269
          out << (count++ ? "             " : "");
3✔
270

271
          out.width (longest);
3✔
272
          out << std::left << name
3✔
273
              << (p.executable () ? " (executable)" : " (not executable)")
6✔
274
              << (p.is_link () ? " (symlink)" : "")
6✔
275
              << ((name.substr (0, 6) == "on-add" ||
6✔
276
                   name.substr (0, 9) == "on-modify" ||
9✔
277
                   name.substr (0, 9) == "on-launch" ||
9✔
278
                   name.substr (0, 7) == "on-exit") ? "" : "unrecognized hook name")
6✔
279
              << '\n';
6✔
280
        }
281
      }
4✔
282
    }
4✔
283

284
    if (! count)
1✔
285
      out << '\n';
×
286
  }
287
  else
288
    out << "             (-none-)\n";
6✔
289

290
  out << '\n';
7✔
291

292
  // Verify UUIDs are all unique.
293
  out << bold.colorize ("Tests")
14✔
294
      << '\n';
7✔
295

296
  // Report terminal dimensions.
297
  out << "   Terminal: "
7✔
298
      << Context::getContext ().getWidth ()
7✔
299
      << 'x'
7✔
300
      << Context::getContext ().getHeight ()
7✔
301
      << '\n';
7✔
302

303
  // Check all the UUID references
304
  auto all = Context::getContext ().tdb2.all_tasks ();
7✔
305

306
  bool noBrokenRefs = true;
7✔
307
  out << " Broken ref: "
308
      << format ("Scanned {1} tasks for broken references:", all.size ())
14✔
309
      << '\n';
14✔
310

311
  for (auto& task : all)
7✔
312
  {
313
    // Check dependencies
UNCOV
314
    for (auto& uuid : task.getDependencyUUIDs ())
×
315
    {
316
      if (! Context::getContext ().tdb2.has (uuid))
×
317
      {
318
        out << "             "
319
            << format ("Task {1} depends on nonexistent task: {2}", task.get ("uuid"), uuid)
×
320
            << '\n';
×
321
        noBrokenRefs = false;
×
322
      }
323
    }
324

325
    // Check recurrence parent
UNCOV
326
    auto parentUUID = task.get ("parent");
×
327

UNCOV
328
    if (parentUUID != "" && ! Context::getContext ().tdb2.has (parentUUID))
×
329
    {
330
      out << "             "
331
          << format ("Task {1} has nonexistent recurrence template {2}", task.get ("uuid"), parentUUID)
×
332
          << '\n';
×
333
      noBrokenRefs = false;
×
334
    }
335
  }
336

337
  if (noBrokenRefs)
7✔
338
    out << "             No broken references found\n";
7✔
339

340
  out << '\n';
7✔
341
  output = out.str ();
7✔
342
  return 0;
7✔
343
}
7✔
344

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

© 2025 Coveralls, Inc