GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/publish/command.cc
Date: 2025-06-29 02:35:41
Exec Total Coverage
Lines: 0 72 0.0%
Branches: 0 132 0.0%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 */
4
5
6 #include "publish/command.h"
7
8 #include <getopt.h>
9
10 #include <cassert>
11 #include <cstdlib>
12 #include <cstring>
13
14 #include "publish/except.h"
15 #include "util/logging.h"
16 #include "util/smalloc.h"
17 #include "util/string.h"
18
19 using namespace std; // NOLINT
20
21 namespace publish {
22
23 std::string Command::GetExamples() const {
24 std::vector<std::string> examples = DoGetExamples();
25 std::string result;
26 for (unsigned i = 0; i < examples.size(); ++i) {
27 result += progname() + " " + GetName() + " " + examples[i] + "\n";
28 }
29 return result;
30 }
31
32
33 Command::Options Command::ParseOptions(int argc, char **argv) {
34 Options result;
35 progname_ = argv[0];
36 ParameterList params = GetParams();
37
38 string shortopts;
39 struct option *longopts = reinterpret_cast<option *>(
40 smalloc((params.size() + 1) * sizeof(struct option)));
41 struct option lastopt;
42 memset(&lastopt, 0, sizeof(lastopt));
43 longopts[params.size()] = lastopt;
44
45 for (unsigned i = 0; i < params.size(); ++i) {
46 shortopts.push_back(params[i].short_key);
47 if (!params[i].is_switch)
48 shortopts.push_back(':');
49
50 longopts[i].name = strdup(params[i].key.c_str());
51 longopts[i].has_arg = params[i].is_switch ? no_argument : required_argument;
52 longopts[i].flag = NULL;
53 longopts[i].val = params[i].short_key;
54 }
55
56 int idx;
57 int c;
58 opterr = 0; // Don't print error messages in getopt
59 optind = 2; // Skip the command itself
60 while ((c = getopt_long(argc, argv, shortopts.c_str(), longopts, &idx))
61 != -1) {
62 bool found = false;
63 for (unsigned i = 0; i < params.size(); ++i) {
64 if (c == params[i].short_key) {
65 Argument argument;
66 if (!params[i].is_switch) {
67 argument.value_str = optarg;
68 argument.value_int = String2Int64(argument.value_str);
69 }
70 result.Set(params[i], argument);
71 found = true;
72 break;
73 }
74 }
75
76 if (!found) {
77 assert(c == '?');
78 // Easier to duplicate the next few lines than to add an RAII wrapper
79 for (unsigned i = 0; i < params.size(); ++i) {
80 free(const_cast<char *>(longopts[i].name));
81 }
82 free(longopts);
83
84 throw EPublish(
85 GetName() + ": unrecognized parameter '" + argv[optind - 1] + "'",
86 EPublish::kFailInvocation);
87 }
88 }
89
90 for (unsigned i = 0; i < params.size(); ++i) {
91 free(const_cast<char *>(longopts[i].name));
92 }
93 free(longopts);
94
95 for (unsigned i = 0; i < params.size(); ++i) {
96 if (!params[i].is_optional && !result.Has(params[i].key)) {
97 throw EPublish(
98 GetName() + ": missing mandatory parameter '" + params[i].key + "'",
99 EPublish::kFailInvocation);
100 }
101 }
102
103 for (int i = optind; i < argc; ++i) {
104 result.AppendPlain(Argument(argv[i]));
105 }
106
107 if (result.plain_args().size() < GetMinPlainArgs()) {
108 LogCvmfs(kLogCvmfs, kLogStderr, "Usage: %s %s %s", progname().c_str(),
109 GetName().c_str(), GetUsage().c_str());
110 throw EPublish(GetName() + ": missing argument", EPublish::kFailInvocation);
111 }
112
113 return result;
114 }
115
116
117 //------------------------------------------------------------------------------
118
119
120 CommandList::~CommandList() {
121 for (unsigned i = 0; i < commands_.size(); ++i)
122 delete commands_[i];
123 }
124
125 Command *CommandList::Find(const std::string &name) {
126 Command *result = NULL;
127 for (unsigned i = 0; i < commands_.size(); ++i) {
128 if (commands_[i]->GetName() == name) {
129 result = commands_[i];
130 break;
131 }
132 }
133 return result;
134 }
135
136 void CommandList::TakeCommand(Command *command) {
137 assert(Find(command->GetName()) == NULL);
138 commands_.push_back(command);
139 }
140
141 } // namespace publish
142