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 work.maybe_update_inodeprints(db);
192
193 // extra paranoia... we _should_ never run this section twice
194 // since a merged workspace would fail early with work.has_changes()
195 break;
196 }
197 }
198
199 db.delete_existing_rev_and_certs(revid);
200}
201
202CMD(db_kill_branch_certs_locally, "kill_branch_certs_locally", "", CMD_REF(db),
203 "BRANCH",
204 N_("Kills branch certificates from the local database"),
205 "",
206 options::opts::none)
207{
208 if (args.size() != 1)
209 throw usage(execid);
210
211 database db(app);
212 db.delete_branch_named(cert_value(idx(args, 0)()));
213}
214
215CMD(db_kill_tag_locally, "kill_tag_locally", "", CMD_REF(db), "TAG",
216 N_("Kills a tag from the local database"),
217 "",
218 options::opts::none)
219{
220 if (args.size() != 1)
221 throw usage(execid);
222
223 database db(app);
224 db.delete_tag_named(cert_value(idx(args, 0)()));
225}
226
227CMD(db_check, "check", "", CMD_REF(db), "",
228 N_("Does some sanity checks on the database"),
229 N_("Ensures that the database is consistent by issuing multiple "
230 "checks."),
231 options::opts::none)
232{
233 N(args.size() == 0,
234 F("no arguments needed"));
235
236 database db(app);
237 check_db(db);
238}
239
240CMD(db_changesetify, "changesetify", "", CMD_REF(db), "",
241 N_("Converts the database to the changeset format"),
242 "",
243 options::opts::none)
244{
245 database db(app);
246 key_store keys(app);
247
248 N(args.size() == 0,
249 F("no arguments needed"));
250
251 db.ensure_open_for_format_changes();
252 db.check_is_not_rosterified();
253
254 // early short-circuit to avoid failure after lots of work
255 cache_user_key(app.opts, app.lua, db, keys);
256
257 build_changesets_from_manifest_ancestry(db, keys, set<string>());
258}
259
260CMD(db_rosterify, "rosterify", "", CMD_REF(db), "",
261 N_("Converts the database to the rosters format"),
262 "",
263 options::opts::drop_attr)
264{
265 database db(app);
266 key_store keys(app);
267
268 N(args.size() == 0,
269 F("no arguments needed"));
270
271 db.ensure_open_for_format_changes();
272 db.check_is_not_rosterified();
273
274 // early short-circuit to avoid failure after lots of work
275 cache_user_key(app.opts, app.lua, db, keys);
276
277 build_roster_style_revs_from_manifest_style_revs(db, keys,
278 app.opts.attrs_to_drop);
279}
280
281CMD(db_regenerate_caches, "regenerate_caches", "", CMD_REF(db), "",
282 N_("Regenerates the caches stored in the database"),
283 "",
284 options::opts::none)
285{
286 N(args.size() == 0,
287 F("no arguments needed"));
288
289 database db(app);
290 regenerate_caches(db);
291}
292
293CMD_HIDDEN(clear_epoch, "clear_epoch", "", CMD_REF(db), "BRANCH",
294 N_("Clears the branch's epoch"),
295 "",
296 options::opts::none)
297{
298 if (args.size() != 1)
299 throw usage(execid);
300
301 database db(app);
302 db.clear_epoch(branch_name(idx(args, 0)()));
303}
304
305CMD(db_set_epoch, "set_epoch", "", CMD_REF(db), "BRANCH EPOCH",
306 N_("Sets the branch's epoch"),
307 "",
308 options::opts::none)
309{
310 if (args.size() != 2)
311 throw usage(execid);
312
313 N(idx(args, 1)().size() == constants::epochlen,
314 F("The epoch must be %s characters") % constants::epochlen);
315
316 epoch_data ed(decode_hexenc(idx(args, 1)()));
317 database db(app);
318 db.set_epoch(branch_name(idx(args, 0)()), ed);
319}
320
321CMD(set, "set", "", CMD_REF(variables), N_("DOMAIN NAME VALUE"),
322 N_("Sets a database variable"),
323 N_("This command modifies (or adds if it did not exist before) the "
324 "variable named NAME, stored in the database, and sets it to the "
325 "given value in VALUE. The variable is placed in the domain DOMAIN."),
326 options::opts::none)
327{
328 if (args.size() != 3)
329 throw usage(execid);
330
331 var_domain d;
332 var_name n;
333 var_value v;
334 internalize_var_domain(idx(args, 0), d);
335 n = var_name(idx(args, 1)());
336 v = var_value(idx(args, 2)());
337
338 database db(app);
339 db.set_var(make_pair(d, n), v);
340}
341
342CMD(unset, "unset", "", CMD_REF(variables), N_("DOMAIN NAME"),
343 N_("Unsets a database variable"),
344 N_("This command removes the variable NAME from domain DOMAIN, which "
345 "was previously stored in the database."),
346 options::opts::none)
347{
348 if (args.size() != 2)
349 throw usage(execid);
350
351 var_domain d;
352 var_name n;
353 internalize_var_domain(idx(args, 0), d);
354 n = var_name(idx(args, 1)());
355 var_key k(d, n);
356
357 database db(app);
358 N(db.var_exists(k),
359 F("no var with name %s in domain %s") % n % d);
360 db.clear_var(k);
361}
362
363CMD(complete, "complete", "", CMD_REF(informative),
364 N_("(revision|file|key) PARTIAL-ID"),
365 N_("Completes a partial identifier"),
366 "",
367 options::opts::verbose)
368{
369 if (args.size() != 2)
370 throw usage(execid);
371
372 database db(app);
373 project_t project(db);
374
375 bool verbose = app.opts.verbose;
376
377 N(idx(args, 1)().find_first_not_of("abcdef0123456789") == string::npos,
378 F("non-hex digits in partial id"));
379
380 if (idx(args, 0)() == "revision")
381 {
382 set<revision_id> completions;
383 db.complete(idx(args, 1)(), completions);
384 for (set<revision_id>::const_iterator i = completions.begin();
385 i != completions.end(); ++i)
386 {
387 if (!verbose) cout << *i << '\n';
388 else cout << describe_revision(project, *i) << '\n';
389 }
390 }
391 else if (idx(args, 0)() == "file")
392 {
393 set<file_id> completions;
394 db.complete(idx(args, 1)(), completions);
395 for (set<file_id>::const_iterator i = completions.begin();
396 i != completions.end(); ++i)
397 cout << *i << '\n';
398 }
399 else if (idx(args, 0)() == "key")
400 {
401 typedef set< pair<key_id, utf8 > > completions_t;
402 completions_t completions;
403 db.complete(idx(args, 1)(), completions);
404 for (completions_t::const_iterator i = completions.begin();
405 i != completions.end(); ++i)
406 {
407 cout << i->first;
408 if (verbose) cout << ' ' << i->second();
409 cout << '\n';
410 }
411 }
412 else
413 throw usage(execid);
414}
415
416CMD_HIDDEN(test_migration_step, "test_migration_step", "", CMD_REF(db),
417 "SCHEMA",
418 N_("Runs one step of migration on the specified database"),
419 N_("This command migrates the given database from the specified "
420 "schema in SCHEMA to its successor."),
421 options::opts::none)
422{
423 database db(app);
424 key_store keys(app);
425
426 if (args.size() != 1)
427 throw usage(execid);
428 db.test_migration_step(keys, idx(args,0)());
429}
430
431CMD_HIDDEN(rev_height, "rev_height", "", CMD_REF(informative), N_("REV"),
432 N_("Shows a revision's height"),
433 "",
434 options::opts::none)
435{
436 if (args.size() != 1)
437 throw usage(execid);
438 revision_id rid(idx(args, 0)());
439 database db(app);
440 N(db.revision_exists(rid), F("no such revision '%s'") % rid);
441 rev_height height;
442 db.get_rev_height(rid, height);
443 P(F("cached height: %s") % height);
444}
445
446// Local Variables:
447// mode: C++
448// fill-column: 76
449// c-file-style: "gnu"
450// indent-tabs-mode: nil
451// End:
452// 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