-
Notifications
You must be signed in to change notification settings - Fork 6
/
cmd.hh
304 lines (268 loc) · 12.4 KB
/
cmd.hh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
#ifndef __CMD_HH__
#define __CMD_HH__
// Copyright (C) 2002 Graydon Hoare <graydon@pobox.com>
//
// This program is made available under the GNU GPL version 2.0 or
// greater. See the accompanying file COPYING for details.
//
// This program is distributed WITHOUT ANY WARRANTY; without even the
// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE.
#include <map>
#include <set>
#include "commands.hh"
#include "selectors.hh"
#include "options.hh"
#include "sanity.hh"
class app_state;
class database;
class project_t;
struct workspace;
namespace commands
{
class command
{
public:
typedef std::set< utf8 > names_set;
typedef std::set< command * > children_set;
private:
// NB: these strings are stored _un_translated, because we cannot
// translate them until after main starts, by which time the
// command objects have all been constructed.
utf8 m_primary_name;
names_set m_names;
command * m_parent;
bool m_is_group;
bool m_hidden;
utf8 m_params;
utf8 m_abstract;
utf8 m_desc;
bool m_use_workspace_options;
options::options_type m_opts;
children_set m_children;
bool m_allow_completion;
std::map< command_id, command * >
find_completions(utf8 const & prefix, command_id const & completed,
bool completion_ok = true) const;
command * find_child_by_name(utf8 const & name) const;
bool allow_completion() const;
public:
command(std::string const & primary_name,
std::string const & other_names,
command * parent,
bool is_group,
bool hidden,
std::string const & params,
std::string const & abstract,
std::string const & desc,
bool use_workspace_options,
options::options_type const & opts,
bool allow_completion);
virtual ~command(void);
command_id ident(void) const;
utf8 const & primary_name(void) const;
names_set const & names(void) const;
void add_alias(const utf8 &new_name);
command * parent(void) const;
bool is_group(void) const;
bool hidden(void) const;
virtual std::string params(void) const;
virtual std::string abstract(void) const;
virtual std::string desc(void) const;
virtual names_set subcommands(void) const;
options::options_type const & opts(void) const;
bool use_workspace_options(void) const;
children_set & children(void);
children_set const & children(void) const;
bool is_leaf(void) const;
bool operator<(command const & cmd) const;
virtual void exec(app_state & app,
command_id const & execid,
args_vector const & args) const = 0;
bool has_name(utf8 const & name) const;
command const * find_command(command_id const & id) const;
command * find_command(command_id const & id);
std::set< command_id >
complete_command(command_id const & id,
command_id completed = command_id(),
bool completion_ok = true) const;
};
class automate : public command
{
// This function is supposed to be called only after the requirements
// for "automate" commands have been fulfilled. This is done by the
// "exec" function defined below, which implements code shared among
// all automation commands. Also, this is also needed by the "stdio"
// automation, as it executes multiple of these commands sharing the
// same initialization, hence the friend declaration.
virtual void exec_from_automate(app_state & app,
command_id const & execid,
args_vector const & args,
std::ostream & output) const = 0;
friend class automate_stdio;
public:
automate(std::string const & name,
std::string const & params,
std::string const & abstract,
std::string const & desc,
options::options_type const & opts);
void exec(app_state & app,
command_id const & execid,
args_vector const & args,
std::ostream & output) const;
void exec(app_state & app,
command_id const & execid,
args_vector const & args) const;
};
};
inline std::vector<file_path>
args_to_paths(args_vector const & args)
{
std::vector<file_path> paths;
for (args_vector::const_iterator i = args.begin(); i != args.end(); ++i)
{
if (bookkeeping_path::external_string_is_bookkeeping_path(*i))
W(F("ignored bookkeeping path '%s'") % *i);
else
paths.push_back(file_path_external(*i));
}
// "it should not be the case that args were passed, but our paths set
// ended up empty". This test is because some commands have default
// behavior for empty path sets -- in particular, it is the same as having
// no restriction at all. "mtn revert _MTN" turning into "mtn revert"
// would be bad. (Or substitute diff, etc.)
N(!(!args.empty() && paths.empty()),
F("all arguments given were bookkeeping paths; aborting"));
return paths;
}
std::string
describe_revision(project_t & project, revision_id const & id);
void
notify_if_multiple_heads(project_t & project, branch_name const & branchname,
bool ignore_suspend_certs);
void
process_commit_message_args(options const & opts,
bool & given,
utf8 & log_message,
utf8 const & message_prefix = utf8());
#define CMD_FWD_DECL(C) \
namespace commands { \
class cmd_ ## C; \
extern cmd_ ## C C ## _cmd; \
}
#define CMD_REF(C) ((commands::command *)&(commands::C ## _cmd))
#define _CMD2(C, name, aliases, parent, hidden, params, abstract, desc, opts) \
namespace commands { \
class cmd_ ## C : public command \
{ \
public: \
cmd_ ## C() : command(name, aliases, parent, false, hidden, \
params, abstract, desc, true, \
options::options_type() | opts, true) \
{} \
virtual void exec(app_state & app, \
command_id const & execid, \
args_vector const & args) const; \
}; \
cmd_ ## C C ## _cmd; \
} \
void commands::cmd_ ## C::exec(app_state & app, \
command_id const & execid, \
args_vector const & args) const
#define CMD(C, name, aliases, parent, params, abstract, desc, opts) \
_CMD2(C, name, aliases, parent, false, params, abstract, desc, opts)
#define CMD_HIDDEN(C, name, aliases, parent, params, abstract, desc, opts) \
_CMD2(C, name, aliases, parent, true, params, abstract, desc, opts)
#define _CMD_GROUP2(C, name, aliases, parent, abstract, desc, cmpl) \
namespace commands { \
class cmd_ ## C : public command \
{ \
public: \
cmd_ ## C() : command(name, aliases, parent, true, false, "", \
abstract, desc, true, \
options::options_type(), cmpl) \
{} \
virtual void exec(app_state & app, \
command_id const & execid, \
args_vector const & args) const; \
}; \
cmd_ ## C C ## _cmd; \
} \
void commands::cmd_ ## C::exec(app_state & app, \
command_id const & execid, \
args_vector const & args) const \
{ \
I(false); \
}
#define CMD_GROUP(C, name, aliases, parent, abstract, desc) \
_CMD_GROUP2(C, name, aliases, parent, abstract, desc, true)
#define CMD_GROUP_NO_COMPLETE(C, name, aliases, parent, abstract, desc) \
_CMD_GROUP2(C, name, aliases, parent, abstract, desc, false)
// Use this for commands that should specifically _not_ look for an
// _MTN dir and load options from it.
#define CMD_NO_WORKSPACE(C, name, aliases, parent, params, abstract, \
desc, opts) \
namespace commands { \
class cmd_ ## C : public command \
{ \
public: \
cmd_ ## C() : command(name, aliases, parent, false, false, \
params, abstract, desc, false, \
options::options_type() | opts, true) \
{} \
virtual void exec(app_state & app, \
command_id const & execid, \
args_vector const & args) const; \
}; \
cmd_ ## C C ## _cmd; \
} \
void commands::cmd_ ## C::exec(app_state & app, \
command_id const & execid, \
args_vector const & args) const
// TODO: 'abstract' and 'desc' should be refactored so that the
// command definition allows the description of input/output format,
// error conditions, version when added, etc. 'desc' can later be
// automatically built from these.
#define CMD_AUTOMATE(C, params, abstract, desc, opts) \
namespace commands { \
class automate_ ## C : public automate \
{ \
void exec_from_automate(app_state & app, \
command_id const & execid, \
args_vector const & args, \
std::ostream & output) const; \
public: \
automate_ ## C() : automate(#C, params, abstract, desc, \
options::options_type() | opts) \
{} \
}; \
automate_ ## C C ## _automate; \
} \
void commands::automate_ ## C :: exec_from_automate \
(app_state & app, \
command_id const & execid, \
args_vector const & args, \
std::ostream & output) const
CMD_FWD_DECL(__root__);
CMD_FWD_DECL(automation);
CMD_FWD_DECL(conflicts);
CMD_FWD_DECL(database);
CMD_FWD_DECL(debug);
CMD_FWD_DECL(informative);
CMD_FWD_DECL(key_and_cert);
CMD_FWD_DECL(network);
CMD_FWD_DECL(packet_io);
CMD_FWD_DECL(rcs);
CMD_FWD_DECL(review);
CMD_FWD_DECL(tree);
CMD_FWD_DECL(variables);
CMD_FWD_DECL(workspace);
CMD_FWD_DECL(user);
// Local Variables:
// mode: C++
// fill-column: 76
// c-file-style: "gnu"
// indent-tabs-mode: nil
// End:
// vim: et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s:
#endif