monotone

monotone Mtn Source Tree

Root/cmd_db.cc

1// Copyright (C) 2002 Graydon Hoare <graydon@pobox.com>
2//
3// This program is made available under the GNU GPL version 2.0 or
4// greater. See the accompanying file COPYING for details.
5//
6// This program is distributed WITHOUT ANY WARRANTY; without even the
7// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
8// PURPOSE.
9
10#include "base.hh"
11#include <iostream>
12#include <utility>
13
14#include "charset.hh"
15#include "cmd.hh"
16#include "database_check.hh"
17#include "revision.hh"
18#include "constants.hh"
19#include "app_state.hh"
20
21using std::cin;
22using std::cout;
23using std::make_pair;
24using std::pair;
25using std::set;
26using std::string;
27
28CMD_GROUP(db, "db", "", CMD_REF(database),
29 N_("Deals with the database"),
30 "");
31
32CMD(db_init, "init", "", CMD_REF(db), "",
33 N_("Initializes a database"),
34 N_("Creates a new database file and initializes it."),
35 options::opts::none)
36{
37 N(args.size() == 0,
38 F("no arguments needed"));
39
40 app.db.initialize();
41}
42
43CMD(db_info, "info", "", CMD_REF(db), "",
44 N_("Shows information about the database"),
45 "",
46 options::opts::none)
47{
48 N(args.size() == 0,
49 F("no arguments needed"));
50
51 app.db.info(cout);
52}
53
54CMD(db_version, "version", "", CMD_REF(db), "",
55 N_("Shows the database's version"),
56 "",
57 options::opts::none)
58{
59 N(args.size() == 0,
60 F("no arguments needed"));
61
62 app.db.version(cout);
63}
64
65CMD(db_dump, "dump", "", CMD_REF(db), "",
66 N_("Dumps the contents of the database"),
67 N_("Generates a list of SQL instructions that represent the whole "
68 "contents of the database. The resulting output is useful to later "
69 "restore the database from a text file that serves as a backup."),
70 options::opts::none)
71{
72 N(args.size() == 0,
73 F("no arguments needed"));
74
75 app.db.dump(cout);
76}
77
78CMD(db_load, "load", "", CMD_REF(db), "",
79 N_("Loads the contents of the database"),
80 N_("Reads a list of SQL instructions that regenerate the contents of "
81 "the database. This is supposed to be used in conjunction with the "
82 "output generated by the 'dump' command."),
83 options::opts::none)
84{
85 N(args.size() == 0,
86 F("no arguments needed"));
87
88 app.db.load(cin);
89}
90
91CMD(db_migrate, "migrate", "", CMD_REF(db), "",
92 N_("Migrates the database to a newer schema"),
93 N_("Updates the database's internal schema to the most recent one. "
94 "Needed to automatically resolve incompatibilities that may be "
95 "introduced in newer versions of monotone."),
96 options::opts::none)
97{
98 N(args.size() == 0,
99 F("no arguments needed"));
100
101 app.db.migrate();
102}
103
104CMD(db_execute, "execute", "", CMD_REF(db), "",
105 N_("Executes an SQL command on the database"),
106 N_("Directly executes the given SQL command on the database"),
107 options::opts::none)
108{
109 if (args.size() != 1)
110 throw usage(execid);
111
112 app.db.debug(idx(args, 0)(), cout);
113}
114
115CMD(db_kill_rev_locally, "kill_rev_locally", "", CMD_REF(db), "ID",
116 N_("Kills a revision from the local database"),
117 "",
118 options::opts::none)
119{
120 if (args.size() != 1)
121 throw usage(execid);
122
123 revision_id revid;
124
125 complete(app, idx(args, 0)(), revid);
126 N(app.db.revision_exists(revid),
127 F("no such revision '%s'") % revid);
128
129 // Check that the revision does not have any children
130 std::set<revision_id> children;
131 app.db.get_revision_children(revid, children);
132 N(!children.size(),
133 F("revision %s already has children. We cannot kill it.") % revid);
134
135 // If we're executing this in a workspace, check if the workspace parent
136 // revision is the one to kill. If so, write out the changes made in this
137 // particular revision to _MTN/revision to allow the user redo his (fixed)
138 // commit afterwards. Of course we can't do this at all if
139 //
140 // a) the user is currently not inside a workspace
141 // b) the user has updated the current workspace to another revision already
142 // thus the working revision is no longer based on the revision we're
143 // trying to kill
144 // c) there are uncomitted changes in the working revision of this workspace.
145 // this *eventually* could be handled with a workspace merge scenario, but
146 // is left out for now
147 app.allow_workspace();
148 if (app.found_workspace)
149 {
150 revision_t old_work_rev;
151 app.work.get_work_rev(old_work_rev);
152
153 for (edge_map::const_iterator i = old_work_rev.edges.begin();
154 i != old_work_rev.edges.end(); i++)
155 {
156 if (edge_old_revision(i) != revid)
157 continue;
158
159 N(!app.work.has_changes(),
160 F("Cannot kill revision %s,\n"
161 "because it would leave the current workspace in an invalid\n"
162 "state, from which monotone cannot recover automatically since\n"
163 "the workspace contains uncommitted changes.\n"
164 "Consider updating your workspace to another revision first,\n"
165 "before you try to kill this revision again.") % revid);
166
167 P(F("applying changes from %s on the current workspace")
168 % revid);
169
170 revision_t new_work_rev;
171 app.db.get_revision(revid, new_work_rev);
172 new_work_rev.made_for = made_for_workspace;
173 app.work.put_work_rev(new_work_rev);
174
175 // extra paranoia... we _should_ never run this section twice
176 // since a merged workspace would fail early with work.has_changes()
177 break;
178 }
179 }
180
181 app.db.delete_existing_rev_and_certs(revid);
182}
183
184CMD(db_kill_branch_certs_locally, "kill_branch_certs_locally", "", CMD_REF(db),
185 "BRANCH",
186 N_("Kills branch certificates from the local database"),
187 "",
188 options::opts::none)
189{
190 if (args.size() != 1)
191 throw usage(execid);
192
193 app.db.delete_branch_named(cert_value(idx(args, 0)()));
194}
195
196CMD(db_kill_tag_locally, "kill_tag_locally", "", CMD_REF(db), "TAG",
197 N_("Kills a tag from the local database"),
198 "",
199 options::opts::none)
200{
201 if (args.size() != 1)
202 throw usage(execid);
203
204 app.db.delete_tag_named(cert_value(idx(args, 0)()));
205}
206
207CMD(db_check, "check", "", CMD_REF(db), "",
208 N_("Does some sanity checks on the database"),
209 N_("Ensures that the database is consistent by issuing multiple "
210 "checks."),
211 options::opts::none)
212{
213 N(args.size() == 0,
214 F("no arguments needed"));
215
216 check_db(app);
217}
218
219CMD(db_changesetify, "changesetify", "", CMD_REF(db), "",
220 N_("Converts the database to the changeset format"),
221 "",
222 options::opts::none)
223{
224 N(args.size() == 0,
225 F("no arguments needed"));
226
227 build_changesets_from_manifest_ancestry(app);
228}
229
230CMD(db_rosterify, "rosterify", "", CMD_REF(db), "",
231 N_("Converts the database to the rosters format"),
232 "",
233 options::opts::drop_attr)
234{
235 N(args.size() == 0,
236 F("no arguments needed"));
237
238 build_roster_style_revs_from_manifest_style_revs(app);
239}
240
241CMD(db_regenerate_caches, "regenerate_caches", "", CMD_REF(db), "",
242 N_("Regenerates the caches stored in the database"),
243 "",
244 options::opts::none)
245{
246 N(args.size() == 0,
247 F("no arguments needed"));
248
249 regenerate_caches(app);
250}
251
252CMD_HIDDEN(clear_epoch, "clear_epoch", "", CMD_REF(db), "BRANCH",
253 N_("Clears the branch's epoch"),
254 "",
255 options::opts::none)
256{
257 if (args.size() != 1)
258 throw usage(execid);
259
260 app.db.clear_epoch(branch_name(idx(args, 0)()));
261}
262
263CMD(db_set_epoch, "set_epoch", "", CMD_REF(db), "BRANCH EPOCH",
264 N_("Sets the branch's epoch"),
265 "",
266 options::opts::none)
267{
268 if (args.size() != 2)
269 throw usage(execid);
270
271 epoch_data ed(idx(args, 1)());
272 N(ed.inner()().size() == constants::epochlen,
273 F("The epoch must be %s characters") % constants::epochlen);
274 app.db.set_epoch(branch_name(idx(args, 0)()), ed);
275}
276
277CMD(set, "set", "", CMD_REF(variables), N_("DOMAIN NAME VALUE"),
278 N_("Sets a database variable"),
279 N_("This command modifies (or adds if it did not exist before) the "
280 "variable named NAME, stored in the database, and sets it to the "
281 "given value in VALUE. The variable is placed in the domain DOMAIN."),
282 options::opts::none)
283{
284 if (args.size() != 3)
285 throw usage(execid);
286
287 var_domain d;
288 var_name n;
289 var_value v;
290 internalize_var_domain(idx(args, 0), d);
291 n = var_name(idx(args, 1)());
292 v = var_value(idx(args, 2)());
293 app.db.set_var(make_pair(d, n), v);
294}
295
296CMD(unset, "unset", "", CMD_REF(variables), N_("DOMAIN NAME"),
297 N_("Unsets a database variable"),
298 N_("This command removes the variable NAME from domain DOMAIN, which "
299 "was previously stored in the database."),
300 options::opts::none)
301{
302 if (args.size() != 2)
303 throw usage(execid);
304
305 var_domain d;
306 var_name n;
307 internalize_var_domain(idx(args, 0), d);
308 n = var_name(idx(args, 1)());
309 var_key k(d, n);
310 N(app.db.var_exists(k),
311 F("no var with name %s in domain %s") % n % d);
312 app.db.clear_var(k);
313}
314
315CMD(complete, "complete", "", CMD_REF(informative),
316 N_("(revision|file|key) PARTIAL-ID"),
317 N_("Completes a partial identifier"),
318 "",
319 options::opts::verbose)
320{
321 if (args.size() != 2)
322 throw usage(execid);
323
324 bool verbose = app.opts.verbose;
325
326 N(idx(args, 1)().find_first_not_of("abcdef0123456789") == string::npos,
327 F("non-hex digits in partial id"));
328
329 if (idx(args, 0)() == "revision")
330 {
331 set<revision_id> completions;
332 app.db.complete(idx(args, 1)(), completions);
333 for (set<revision_id>::const_iterator i = completions.begin();
334 i != completions.end(); ++i)
335 {
336 if (!verbose) cout << i->inner()() << '\n';
337 else cout << describe_revision(app, *i) << '\n';
338 }
339 }
340 else if (idx(args, 0)() == "file")
341 {
342 set<file_id> completions;
343 app.db.complete(idx(args, 1)(), completions);
344 for (set<file_id>::const_iterator i = completions.begin();
345 i != completions.end(); ++i)
346 cout << i->inner()() << '\n';
347 }
348 else if (idx(args, 0)() == "key")
349 {
350 typedef set< pair<key_id, utf8 > > completions_t;
351 completions_t completions;
352 app.db.complete(idx(args, 1)(), completions);
353 for (completions_t::const_iterator i = completions.begin();
354 i != completions.end(); ++i)
355 {
356 cout << i->first.inner()();
357 if (verbose) cout << ' ' << i->second();
358 cout << '\n';
359 }
360 }
361 else
362 throw usage(execid);
363}
364
365CMD_HIDDEN(test_migration_step, "test_migration_step", "", CMD_REF(db),
366 "SCHEMA",
367 N_("Runs one step of migration on the specified database"),
368 N_("This command migrates the given database from the specified "
369 "schema in SCHEMA to its successor."),
370 options::opts::none)
371{
372 if (args.size() != 1)
373 throw usage(execid);
374 app.db.test_migration_step(idx(args,0)());
375}
376
377// Local Variables:
378// mode: C++
379// fill-column: 76
380// c-file-style: "gnu"
381// indent-tabs-mode: nil
382// End:
383// vim: et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s:

Archive Download this file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status