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