monotone

monotone Mtn Source Tree

Root/src/cmd_merging.cc

1// Copyright (C) 2002 Graydon Hoare <graydon@pobox.com>
2// 2008, 2010, 2012 Stephen Leake <stephen_leake@stephe-leake.org>
3//
4// This program is made available under the GNU GPL version 2.0 or
5// greater. See the accompanying file COPYING for details.
6//
7// This program is distributed WITHOUT ANY WARRANTY; without even the
8// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
9// PURPOSE.
10
11#include "base.hh"
12#include <cstring>
13#include <iostream>
14#include <iomanip>
15
16#include "basic_io.hh"
17#include "cmd.hh"
18#include "diff_output.hh"
19#include "merge_content.hh"
20#include "restrictions.hh"
21#include "revision.hh"
22#include "merge_roster.hh"
23#include "transforms.hh"
24#include "update.hh"
25#include "work.hh"
26#include "safe_map.hh"
27#include "app_state.hh"
28#include "maybe_workspace_updater.hh"
29#include "project.hh"
30#include "simplestring_xform.hh"
31#include "keys.hh"
32#include "key_store.hh"
33#include "database.hh"
34#include "vocab_cast.hh"
35
36using std::cout;
37using std::make_pair;
38using std::map;
39using std::set;
40using std::string;
41using std::vector;
42using std::strlen;
43
44using boost::shared_ptr;
45
46static void
47add_dormant_attrs(const_node_t parent, node_t child)
48{
49 for (attr_map_t::const_iterator i = parent->attrs.begin();
50 i != parent->attrs.end(); ++i)
51 {
52 // if the child does not have the associated attr add a dormant one
53 if (child->attrs.find(i->first) == child->attrs.end())
54 safe_insert(child->attrs,
55 make_pair(i->first, make_pair(false, attr_value())));
56 }
57}
58
59static void
60three_way_merge(revision_id const & ancestor_rid, roster_t const & ancestor_roster,
61 revision_id const & left_rid, roster_t const & left_roster,
62 revision_id const & right_rid, roster_t const & right_roster,
63 roster_merge_result & result,
64 marking_map & left_markings,
65 marking_map & right_markings)
66{
67 MM(ancestor_roster);
68 MM(left_roster);
69 MM(right_roster);
70
71 MM(ancestor_rid);
72 MM(left_rid);
73 MM(right_rid);
74
75 // for this to work correctly attrs that exist in the ancestor *must*
76 // exist in both children, since attrs are never deleted they are only
77 // marked as dormant. however, since this may be any arbitrary arrangement
78 // of three revisions it is possible that attrs do exist in the parent and
79 // not in the children. in this case the attrs must be added to the
80 // children as dormant so that roster_merge works correctly.
81
82 roster_t left_with_attrs(left_roster);
83 roster_t right_with_attrs(right_roster);
84
85 MM(left_with_attrs);
86 MM(right_with_attrs);
87
88 node_map const & nodes = ancestor_roster.all_nodes();
89
90 for (node_map::const_iterator i = nodes.begin(); i != nodes.end(); ++i)
91 {
92 if (left_with_attrs.has_node(i->first))
93 add_dormant_attrs(i->second, left_with_attrs.get_node_for_update(i->first));
94 if (right_with_attrs.has_node(i->first))
95 add_dormant_attrs(i->second, right_with_attrs.get_node_for_update(i->first));
96 }
97
98 // Mark up the ANCESTOR
99 marking_map ancestor_markings; MM(ancestor_markings);
100 mark_roster_with_no_parents(ancestor_rid, ancestor_roster, ancestor_markings);
101
102 // Mark up the LEFT roster
103 left_markings.clear();
104 MM(left_markings);
105 mark_roster_with_one_parent(ancestor_roster, ancestor_markings,
106 left_rid, left_with_attrs, left_markings);
107
108 // Mark up the RIGHT roster
109 right_markings.clear();
110 MM(right_markings);
111 mark_roster_with_one_parent(ancestor_roster, ancestor_markings,
112 right_rid, right_with_attrs, right_markings);
113
114 // Make the synthetic graph, by creating uncommon ancestor sets
115 std::set<revision_id> left_uncommon_ancestors, right_uncommon_ancestors;
116 safe_insert(left_uncommon_ancestors, left_rid);
117 safe_insert(right_uncommon_ancestors, right_rid);
118
119 P(F("[left] %s") % left_rid);
120 P(F("[right] %s") % right_rid);
121
122 // And do the merge
123 roster_merge(left_with_attrs, left_markings, left_uncommon_ancestors,
124 right_with_attrs, right_markings, right_uncommon_ancestors,
125 result);
126}
127
128static bool
129pick_branch_for_update(options & opts, database & db,
130 project_t & project, revision_id chosen_rid)
131{
132 bool switched_branch = false;
133
134 // figure out which branches the target is in
135 vector<cert> certs;
136 db.get_revision_certs(chosen_rid, branch_cert_name, certs);
137 db.erase_bogus_certs(project, certs);
138
139 set<branch_name> branches;
140 for (vector<cert>::const_iterator i = certs.begin();
141 i != certs.end(); i++)
142 branches.insert(typecast_vocab<branch_name>(i->value));
143
144 if (!opts.ignore_suspend_certs)
145 {
146 vector<cert> suspend_certs;
147 db.get_revision_certs(chosen_rid, suspend_cert_name, suspend_certs);
148
149 for (vector<cert>::const_iterator i = suspend_certs.begin();
150 i != suspend_certs.end(); i++)
151 {
152 branch_name susp_branch = typecast_vocab<branch_name>(i->value);
153 set<branch_name>::iterator pos = branches.find(susp_branch);
154 if (pos != branches.end())
155 {
156 branches.erase(pos);
157 }
158 }
159 }
160
161 if (branches.find(opts.branch) != branches.end())
162 {
163 L(FL("using existing branch %s") % opts.branch());
164 }
165 else
166 {
167 P(F("target revision is not in current branch"));
168 if (branches.size() > 1)
169 {
170 // multiple non-matching branchnames
171 string branch_list;
172 for (set<branch_name>::const_iterator i = branches.begin();
173 i != branches.end(); i++)
174 branch_list += "\n " + (*i)();
175 E(false, origin::user,
176 F("target revision is in multiple branches:%s\n\n"
177 "Try again with explicit '--branch'") % branch_list);
178 }
179 else if (branches.size() == 1)
180 {
181 // one non-matching, inform and update
182 opts.branch = *(branches.begin());
183 switched_branch = true;
184 }
185 else
186 {
187 W(F("target revision not in any branch.\n"
188 "Next commit will use branch '%s'")
189 % opts.branch);
190 }
191 }
192 return switched_branch;
193}
194
195// also used from maybe_workspace_updater.cc
196void
197update(app_state & app,
198 args_vector const & args)
199{
200 database db(app);
201 workspace work(app);
202 project_t project(db);
203
204 // Figure out where we are
205 parent_map parents;
206 work.get_parent_rosters(db, parents);
207
208 E(parents.size() == 1, origin::user,
209 F("this command can only be used in a single-parent workspace"));
210
211 revision_id old_rid = parent_id(parents.begin());
212 E(!null_id(old_rid), origin::user,
213 F("this workspace is a new project; cannot update"));
214
215 // Figure out where we're going
216 E(!app.opts.branch().empty(), origin::user,
217 F("cannot determine branch for update"));
218
219 revision_id chosen_rid;
220 if (app.opts.revision.empty())
221 {
222 P(F("updating along branch '%s'") % app.opts.branch);
223 set<revision_id> candidates;
224 pick_update_candidates(app.lua, project, candidates, old_rid,
225 app.opts.branch,
226 app.opts.ignore_suspend_certs);
227 E(!candidates.empty(), origin::user,
228 F("your request matches no descendents of the current revision.\n"
229 "In fact, it doesn't even match the current revision.\n"
230 "Maybe you want something like '--revision=h:%s'")
231 % app.opts.branch);
232 if (candidates.size() != 1)
233 {
234 P(F("multiple update candidates:"));
235 for (set<revision_id>::const_iterator i = candidates.begin();
236 i != candidates.end(); ++i)
237 P(i18n_format(" %s")
238 % describe_revision(app.opts, app.lua, project, *i));
239 P(F("choose one with '%s update -r<id>'") % prog_name);
240 E(false, origin::user,
241 F("multiple update candidates remain after selection"));
242 }
243 chosen_rid = *(candidates.begin());
244 }
245 else
246 {
247 complete(app.opts, app.lua, project, app.opts.revision[0](), chosen_rid);
248 }
249 I(!null_id(chosen_rid));
250
251 // do this notification before checking to see if we can bail out early,
252 // because when you are at one of several heads, and you hit update, you
253 // want to know that merging would let you update further.
254 notify_if_multiple_heads(project,
255 app.opts.branch, app.opts.ignore_suspend_certs);
256
257 if (old_rid == chosen_rid)
258 {
259 P(F("already up to date at %s") % old_rid);
260 // do still switch the workspace branch, in case they have used
261 // update to switch branches.
262 work.set_options(app.opts, app.lua, true);
263 return;
264 }
265
266 P(F("selected update target %s") % chosen_rid);
267
268 // Fiddle around with branches, in an attempt to guess what the user
269 // wants.
270 bool switched_branch = pick_branch_for_update(app.opts, db, project, chosen_rid);
271 if (switched_branch)
272 P(F("switching to branch '%s'") % app.opts.branch());
273
274 // Okay, we have a target, we have a branch, let's do this merge!
275
276 // We have:
277 //
278 // old --> working
279 // | |
280 // V V
281 // chosen --> merged
282 //
283 // - old is the revision specified in _MTN/revision
284 // - working is based on old and includes the workspace's changes
285 // - chosen is the revision we're updating to and will end up in _MTN/revision
286 // - merged is the merge of working and chosen, that will become the new
287 // workspace
288 //
289 // we apply the working to merged cset to the workspace
290 // and write the cset from chosen to merged changeset in _MTN/work
291
292 temp_node_id_source nis;
293
294 // Get the OLD and WORKING rosters
295 roster_t_cp old_roster
296 = parent_cached_roster(parents.begin()).first;
297 MM(*old_roster);
298
299 shared_ptr<roster_t> working_roster = shared_ptr<roster_t>(new roster_t());
300
301 MM(*working_roster);
302 work.get_current_roster_shape(db, nis, *working_roster);
303 work.update_current_roster_from_filesystem(*working_roster);
304
305 revision_t working_rev;
306 revision_id working_rid;
307 make_revision_for_workspace(parents, *working_roster, working_rev);
308 calculate_ident(working_rev, working_rid);
309
310 // Get the CHOSEN roster
311 roster_t chosen_roster; MM(chosen_roster);
312 db.get_roster(chosen_rid, chosen_roster);
313
314
315 // And finally do the merge
316 roster_merge_result result;
317 marking_map left_markings, right_markings;
318 three_way_merge(old_rid, *old_roster,
319 working_rid, *working_roster,
320 chosen_rid, chosen_roster,
321 result, left_markings, right_markings);
322
323 roster_t & merged_roster = result.roster;
324
325 map<file_id, file_path> paths;
326 get_content_paths(*working_roster, paths);
327
328 content_merge_workspace_adaptor wca(db, old_rid, old_roster,
329 left_markings, right_markings, paths);
330 wca.cache_roster(working_rid, working_roster);
331 resolve_merge_conflicts(app.lua, app.opts, *working_roster, chosen_roster,
332 result, wca, nis, false);
333
334 // Make sure it worked...
335 I(result.is_clean());
336 merged_roster.check_sane(true);
337
338 // Now finally modify the workspace
339 cset update;
340 make_cset(*working_roster, merged_roster, update);
341 work.perform_content_update(*working_roster, merged_roster, update, wca, true,
342 app.opts.move_conflicting_paths);
343
344 revision_t remaining;
345 make_revision_for_workspace(chosen_rid, chosen_roster,
346 merged_roster, remaining);
347
348 // small race condition here... FIXME: what is it?
349 work.put_update_id(old_rid);
350 work.put_work_rev(remaining);
351 work.maybe_update_inodeprints(db);
352 work.set_options(app.opts, app.lua, true);
353
354 if (switched_branch)
355 P(F("switched branch; next commit will use branch '%s'") % app.opts.branch());
356 P(F("updated to base revision %s") % chosen_rid);
357}
358
359CMD(update, "update", "", CMD_REF(workspace), "",
360 N_("Updates the workspace"),
361 N_("This command modifies your workspace to be based off of a "
362 "different revision, preserving uncommitted changes as it does so. "
363 "If a revision is given, update the workspace to that revision. "
364 "If not, update the workspace to the head of the branch."),
365 options::opts::branch | options::opts::revision |
366 options::opts::move_conflicting_paths)
367{
368 if (!args.empty())
369 throw usage(execid);
370
371 if (app.opts.revision.size() > 1)
372 throw usage(execid);
373
374 update(app, args);
375}
376
377CMD_AUTOMATE(update, "",
378 N_("Updates the workspace"),
379 "",
380 options::opts::branch | options::opts::revision |
381 options::opts::move_conflicting_paths)
382{
383 E(args.empty(), origin::user,
384 F("wrong argument count"));
385
386 E(app.opts.revision.size() <= 1, origin::user,
387 F("at most one revision selector may be specified"));
388
389 update(app, args);
390}
391
392// Subroutine of CMD(merge) and CMD(explicit_merge). Merge LEFT with RIGHT,
393// placing results onto BRANCH. Note that interactive_merge_and_store may
394// bomb out, and therefore so may this.
395static void
396merge_two(options & opts, lua_hooks & lua, project_t & project,
397 key_store & keys,
398 revision_id const & left, revision_id const & right,
399 branch_name const & branch, string const & caller,
400 std::ostream & output, bool automate)
401{
402 // The following mess constructs a neatly formatted log message that looks
403 // like this:
404 // CALLER of 'LEFT'
405 // and 'RIGHT'
406 // to branch 'BRANCH'
407 // where the last line is left out if we're merging onto the current branch.
408 // We use a stringstream because boost::format does not support %-*s.
409 using std::ostringstream;
410 using std::setw;
411 using std::max;
412
413 ostringstream log;
414 utf8 log_message("");
415 bool log_message_given;
416 size_t fieldwidth = max(caller.size() + strlen(" of '"), strlen("and '"));
417
418 if (branch != opts.branch)
419 fieldwidth = max(fieldwidth, strlen("to branch '"));
420
421 log << setw(fieldwidth - strlen(" of '")) << caller << " of '" << left
422 << "'\n" << setw(fieldwidth) << "and '" << right
423 << "'\n";
424
425 if (branch != opts.branch)
426 log << setw(fieldwidth) << "to branch '" << branch << "'\n";
427
428 process_commit_message_args(opts, log_message_given, log_message,
429 utf8(log.str(), origin::internal));
430
431 // Now it's time for the real work.
432 if (automate)
433 {
434 output << left << " " << right << " ";
435 }
436 else
437 {
438 P(F("[left] %s") % left);
439 P(F("[right] %s") % right);
440 }
441
442 revision_id merged;
443 transaction_guard guard(project.db);
444 interactive_merge_and_store(lua, project.db, opts, left, right, merged);
445
446 project.put_standard_certs_from_options(opts, lua, keys, merged, branch, log_message);
447
448 guard.commit();
449 if (automate)
450 output << merged << "\n";
451 else
452 P(F("[merged] %s") % merged);
453}
454
455typedef std::pair<revision_id, revision_id> revpair;
456typedef set<revision_id>::const_iterator rid_set_iter;
457
458// Subroutine of 'merge' and 'automate show_conflicts'; find first pair of
459// heads to merge.
460static revpair
461find_heads_to_merge(database & db, set<revision_id> const heads)
462{
463 I(heads.size() >= 2);
464
465 if (heads.size() == 2)
466 {
467 rid_set_iter i = heads.begin();
468 revision_id left = *i++;
469 revision_id right = *i++;
470 return revpair(left, right);
471 };
472
473 map<revision_id, revpair> heads_for_ancestor;
474 set<revision_id> ancestors;
475
476 // For every pair of heads, determine their merge ancestor, and
477 // remember the ancestor->head mapping.
478 for (rid_set_iter i = heads.begin(); i != heads.end(); ++i)
479 for (rid_set_iter j = i; j != heads.end(); ++j)
480 {
481 // It is not possible to initialize j to i+1 (set iterators
482 // expose neither operator+ nor a nondestructive next() method)
483 if (j == i)
484 continue;
485
486 revision_id ancestor;
487 find_common_ancestor_for_merge(db, *i, *j, ancestor);
488
489 // More than one pair might have the same ancestor (e.g. if we
490 // have three heads all with the same parent); as this table
491 // will be recalculated on every pass, we just take the first
492 // one we find.
493 if (ancestors.insert(ancestor).second)
494 safe_insert(heads_for_ancestor, std::make_pair(ancestor, revpair(*i, *j)));
495 }
496
497 // Erasing ancestors from ANCESTORS will now produce a set of merge
498 // ancestors each of which is not itself an ancestor of any other
499 // merge ancestor.
500 erase_ancestors(db, ancestors);
501 I(!ancestors.empty());
502
503 // Take the first ancestor from the above set.
504 return heads_for_ancestor[*ancestors.begin()];
505}
506
507// should merge support --message, --message-file? It seems somewhat weird,
508// since a single 'merge' command may perform arbitrarily many actual merges.
509// (Possibility: append the --message/--message-file text to the synthetic
510// log message constructed in merge_two().)
511CMD(merge, "merge", "", CMD_REF(tree), "",
512 N_("Merges unmerged heads of a branch"),
513 "",
514 options::opts::branch | options::opts::date | options::opts::author |
515 options::opts::messages | options::opts::resolve_conflicts_opts |
516 options::opts::auto_update)
517{
518 database db(app);
519 key_store keys(app);
520 project_t project(db);
521
522 maybe_workspace_updater updater(app, project);
523
524 if (!args.empty())
525 throw usage(execid);
526
527 E(!app.opts.branch().empty(), origin::user,
528 F("please specify a branch, with '--branch=BRANCH'"));
529
530 set<revision_id> heads;
531 project.get_branch_heads(app.opts.branch, heads,
532 app.opts.ignore_suspend_certs);
533
534 E(!heads.empty(), origin::user,
535 F("branch '%s' is empty") % app.opts.branch);
536 if (heads.size() == 1)
537 {
538 P(F("branch '%s' is already merged") % app.opts.branch);
539 return;
540 }
541
542 P(FP("%d head on branch '%s'", "%d heads on branch '%s'", heads.size())
543 % heads.size() % app.opts.branch);
544
545 // avoid failure after lots of work
546 cache_user_key(app.opts, project, keys, app.lua);
547
548 size_t pass = 1, todo = heads.size() - 1;
549
550 if (app.opts.resolve_conflicts)
551 {
552 // conflicts and resolutions only apply to first merge, so only do that one.
553 todo = 1;
554 }
555
556 // If there are more than two heads to be merged, on each iteration we
557 // merge a pair whose least common ancestor is not an ancestor of any
558 // other pair's least common ancestor. For example, if the history graph
559 // looks like this:
560 //
561 // X
562 // / \. (periods to prevent multi-line
563 // Y C comment warnings)
564 // / \.
565 // A B
566 //
567 // A and B will be merged first, and then the result will be merged with C.
568 while (pass <= todo)
569 {
570 P(F("merge %d / %d:") % pass % todo);
571 P(F("calculating best pair of heads to merge next"));
572
573 revpair p = find_heads_to_merge(db, heads);
574
575 merge_two(app.opts, app.lua, project, keys,
576 p.first, p.second, app.opts.branch, string("merge"),
577 std::cout, false);
578
579 project.get_branch_heads(app.opts.branch, heads,
580 app.opts.ignore_suspend_certs);
581 pass++;
582 }
583
584 if (heads.size() > 1)
585 P(F("note: branch '%s' still has %d heads; run merge again") % app.opts.branch % heads.size());
586
587 updater.maybe_do_update();
588}
589
590// This is a special merge operator, but very useful for people
591// maintaining "slightly disparate but related" trees. It does a one-way
592// merge; less powerful than putting things in the same branch and also
593// more flexible.
594//
595// 1. Check to see if src and dst branches are merged, if not abort, if so
596// call heads N1 and N2 respectively.
597//
598// 2. (FIXME: not yet present) Run the hook propagate ("src-branch",
599// "dst-branch", N1, N2) which gives the user a chance to massage N1 into
600// a state which is likely to "merge nicely" with N2, eg. edit pathnames,
601// omit optional files of no interest.
602//
603// 3. Do a normal 2 or 3-way merge on N1 and N2, depending on the
604// existence of common ancestors.
605//
606// 4. Save the results as the delta (N2,M), the ancestry edges (N1,M)
607// and (N2,M), and the cert (N2,dst).
608//
609// There are also special cases we have to check for where no merge is
610// actually necessary, because there hasn't been any divergence since the
611// last time propagate was run.
612//
613// If dir is not the empty string, rename the root of N1 to have the name
614// 'dir' in the merged tree. (ie, it has name "basename(dir)", and its
615// parent node is "N2.get_node(dirname(dir))")
616void perform_merge_into_dir(app_state & app,
617 commands::command_id const & execid,
618 args_vector const & args)
619{
620 database db(app);
621 key_store keys(app);
622 project_t project(db);
623 set<revision_id> src_heads, dst_heads;
624
625 if (args.size() != 3)
626 throw usage(execid);
627
628 maybe_workspace_updater updater(app, project);
629
630 project.get_branch_heads(typecast_vocab<branch_name>(idx(args, 0)), src_heads,
631 app.opts.ignore_suspend_certs);
632 project.get_branch_heads(typecast_vocab<branch_name>(idx(args, 1)), dst_heads,
633 app.opts.ignore_suspend_certs);
634
635 E(src_heads.size() != 0, origin::user,
636 F("branch '%s' is empty") % idx(args, 0)());
637 E(src_heads.size() == 1, origin::user,
638 F("branch '%s' is not merged") % idx(args, 0)());
639
640 E(dst_heads.size() != 0, origin::user,
641 F("branch '%s' is empty") % idx(args, 1)());
642 E(dst_heads.size() == 1, origin::user,
643 F("branch '%s' is not merged") % idx(args, 1)());
644
645 set<revision_id>::const_iterator src_i = src_heads.begin();
646 set<revision_id>::const_iterator dst_i = dst_heads.begin();
647
648 if (*src_i == *dst_i || is_ancestor(db, *src_i, *dst_i))
649 {
650 P(F("branch '%s' is up-to-date with respect to branch '%s'")
651 % idx(args, 1)() % idx(args, 0)());
652 P(F("no action taken"));
653 return;
654 }
655
656 cache_user_key(app.opts, project, keys, app.lua);
657
658 P(F("propagating %s -> %s") % idx(args,0) % idx(args,1));
659 P(F("[left] %s") % *src_i);
660 P(F("[right] %s") % *dst_i);
661
662 // check for special cases
663 if (is_ancestor(db, *dst_i, *src_i))
664 {
665 P(F("no merge necessary; putting %s in branch '%s'")
666 % *src_i % idx(args, 1)());
667 transaction_guard guard(db);
668 project.put_revision_in_branch(keys, *src_i,
669 typecast_vocab<branch_name>(idx(args, 1)));
670 guard.commit();
671 }
672 else
673 {
674 revision_id merged;
675 transaction_guard guard(db);
676
677 {
678 revision_id const & left_rid(*src_i), & right_rid(*dst_i);
679 roster_t left_roster, right_roster;
680 MM(left_roster);
681 MM(right_roster);
682 marking_map left_marking_map, right_marking_map;
683 set<revision_id>
684 left_uncommon_ancestors,
685 right_uncommon_ancestors;
686
687 db.get_roster(left_rid, left_roster, left_marking_map);
688 db.get_roster(right_rid, right_roster, right_marking_map);
689 db.get_uncommon_ancestors(left_rid, right_rid,
690 left_uncommon_ancestors,
691 right_uncommon_ancestors);
692
693 if (!idx(args,2)().empty())
694 {
695 dir_t moved_root = left_roster.root();
696 file_path pth = file_path_external(idx(args, 2));
697 file_path dir;
698 path_component base;
699 MM(dir);
700 pth.dirname_basename(dir, base);
701
702 E(right_roster.has_node(dir), origin::user,
703 F("Path '%s' not found in destination tree.") % pth);
704 const_node_t parent = right_roster.get_node(dir);
705 moved_root->parent = parent->self;
706 moved_root->name = base;
707
708 marking_t i = left_marking_map.get_marking_for_update(moved_root->self);
709 i->parent_name.clear();
710 i->parent_name.insert(left_rid);
711 }
712
713 roster_merge_result result;
714 roster_merge(left_roster,
715 left_marking_map,
716 left_uncommon_ancestors,
717 right_roster,
718 right_marking_map,
719 right_uncommon_ancestors,
720 result);
721
722 temp_node_id_source nis;
723 content_merge_database_adaptor
724 dba(db, left_rid, right_rid, left_marking_map, right_marking_map);
725
726 bool resolutions_given;
727
728 parse_resolve_conflicts_opts
729 (app.opts, left_rid, left_roster, right_rid, right_roster, result, resolutions_given);
730
731 resolve_merge_conflicts(app.lua, app.opts, left_roster, right_roster,
732 result, dba, nis, resolutions_given);
733
734 {
735 dir_t moved_root = left_roster.root();
736 moved_root->parent = the_null_node;
737 moved_root->name = path_component();
738 }
739
740 // Write new files into the db.
741 store_roster_merge_result(db, left_roster, right_roster, result,
742 left_rid, right_rid, merged);
743 }
744
745 bool log_message_given;
746 utf8 log_message;
747 utf8 log_prefix = utf8((FL("propagate from branch '%s' (head %s)\n"
748 " to branch '%s' (head %s)\n")
749 % idx(args, 0)
750 % *src_i
751 % idx(args, 1)
752 % *dst_i).str(),
753 origin::internal);
754
755 process_commit_message_args(app.opts, log_message_given, log_message, log_prefix);
756
757 project.put_standard_certs_from_options(app.opts, app.lua,
758 keys,
759 merged,
760 typecast_vocab<branch_name>(idx(args, 1)),
761 log_message);
762
763 guard.commit();
764 P(F("[merged] %s") % merged);
765 }
766
767 updater.maybe_do_update();
768}
769
770CMD(propagate, "propagate", "", CMD_REF(tree),
771 N_("SOURCE-BRANCH DEST-BRANCH"),
772 N_("Merges from one branch to another asymmetrically"),
773 "",
774 options::opts::date | options::opts::author | options::opts::messages |
775 options::opts::resolve_conflicts_opts)
776{
777 if (args.size() != 2)
778 throw usage(execid);
779 args_vector a = args;
780 a.push_back(arg_type());
781 perform_merge_into_dir(app, make_command_id("tree merge_into_dir"), a);
782}
783
784CMD(merge_into_dir, "merge_into_dir", "", CMD_REF(tree),
785 N_("SOURCE-BRANCH DEST-BRANCH DIR"),
786 N_("Merges one branch into a subdirectory in another branch"),
787 "",
788 options::opts::date | options::opts::author | options::opts::messages |
789 options::opts::resolve_conflicts_opts | options::opts::auto_update)
790{
791 perform_merge_into_dir(app, execid, args);
792}
793
794CMD(merge_into_workspace, "merge_into_workspace", "", CMD_REF(tree),
795 N_("OTHER-REVISION"),
796 N_("Merges a revision into the current workspace's base revision"),
797 N_("Merges OTHER-REVISION into the current workspace's base revision, "
798 "and update the current workspace with the result. There can be no "
799 "pending changes in the current workspace. Both OTHER-REVISION and "
800 "the workspace's base revision will be recorded as parents on commit. "
801 "The workspace's selected branch is not changed."),
802 options::opts::move_conflicting_paths)
803{
804 revision_id left_id, right_id;
805 cached_roster left, right;
806 shared_ptr<roster_t> working_roster = shared_ptr<roster_t>(new roster_t());
807
808 if (args.size() != 1)
809 throw usage(execid);
810
811 database db(app);
812 workspace work(app);
813 project_t project(db);
814
815 // Get the current state of the workspace.
816
817 // This command cannot be applied to a workspace with more than one parent
818 // (revs can have no more than two parents).
819 revision_id working_rid;
820
821 {
822 parent_map parents;
823 work.get_parent_rosters(db, parents);
824 E(parents.size() == 1, origin::user,
825 F("this command can only be used in a single-parent workspace"));
826
827 temp_node_id_source nis;
828 work.get_current_roster_shape(db, nis, *working_roster);
829 work.update_current_roster_from_filesystem(*working_roster);
830
831 E(parent_roster(parents.begin()) == *working_roster, origin::user,
832 F("'%s' can only be used in a workspace with no pending changes") %
833 join_words(execid)());
834
835 left_id = parent_id(parents.begin());
836 left = parent_cached_roster(parents.begin());
837
838 revision_t working_rev;
839 make_revision_for_workspace(parents, *working_roster, working_rev);
840 calculate_ident(working_rev, working_rid);
841 }
842
843 complete(app.opts, app.lua, project, idx(args, 0)(), right_id);
844 db.get_roster(right_id, right);
845 E(!(left_id == right_id), origin::user,
846 F("workspace is already at revision %s") % left_id);
847
848 E(!is_ancestor(db, right_id, left_id), origin::user,
849 F("revision %s is already an ancestor of your workspace") % right_id);
850 E(!is_ancestor(db, left_id, right_id), origin::user,
851 F("revision %s is a descendant of the workspace parent,\n"
852 "did you mean 'mtn update -r %s'?") % right_id % right_id);
853
854 P(F("[left] %s") % left_id);
855 P(F("[right] %s") % right_id);
856
857 set<revision_id> left_uncommon_ancestors, right_uncommon_ancestors;
858 db.get_uncommon_ancestors(left_id, right_id,
859 left_uncommon_ancestors,
860 right_uncommon_ancestors);
861
862 roster_merge_result merge_result;
863 MM(merge_result);
864 roster_merge(*left.first, *left.second, left_uncommon_ancestors,
865 *right.first, *right.second, right_uncommon_ancestors,
866 merge_result);
867
868 revision_id lca_id;
869 cached_roster lca;
870 find_common_ancestor_for_merge(db, left_id, right_id, lca_id);
871 db.get_roster(lca_id, lca);
872
873 map<file_id, file_path> paths;
874 get_content_paths(*working_roster, paths);
875
876 temp_node_id_source nis;
877 content_merge_workspace_adaptor wca(db, lca_id, lca.first,
878 *left.second, *right.second, paths);
879 wca.cache_roster(working_rid, working_roster);
880 resolve_merge_conflicts(app.lua, app.opts, *left.first, *right.first, merge_result, wca, nis, false);
881
882 // Make sure it worked...
883 I(merge_result.is_clean());
884 merge_result.roster.check_sane(true);
885
886 // Construct the workspace revision.
887 parent_map parents;
888 safe_insert(parents, std::make_pair(left_id, left));
889 safe_insert(parents, std::make_pair(right_id, right));
890
891 revision_t merged_rev;
892 make_revision_for_workspace(parents, merge_result.roster, merged_rev);
893
894 // Note: the csets in merged_rev are _not_ suitable for submission to
895 // perform_content_update, because content changes have been dropped.
896 cset update;
897 make_cset(*left.first, merge_result.roster, update);
898
899 // small race condition here...
900 work.perform_content_update(*left.first, merge_result.roster, update, wca, true,
901 app.opts.move_conflicting_paths);
902 work.put_work_rev(merged_rev);
903 work.maybe_update_inodeprints(db);
904
905 P(F("updated to result of merge\n"
906 " [left] %s\n"
907 "[right] %s\n")
908 % left_id
909 % right_id);
910}
911
912CMD(explicit_merge, "explicit_merge", "", CMD_REF(tree),
913 N_("LEFT-REVISION RIGHT-REVISION DEST-BRANCH"),
914 N_("Merges two explicitly given revisions"),
915 N_("The results of the merge are placed on the branch specified by "
916 "DEST-BRANCH."),
917 options::opts::date | options::opts::author |
918 options::opts::messages | options::opts::resolve_conflicts_opts |
919 options::opts::auto_update)
920{
921 database db(app);
922 key_store keys(app);
923 project_t project(db);
924 revision_id left, right;
925 branch_name branch;
926
927 if (args.size() != 3)
928 throw usage(execid);
929
930 maybe_workspace_updater updater(app, project);
931
932 complete(app.opts, app.lua, project, idx(args, 0)(), left);
933 complete(app.opts, app.lua, project, idx(args, 1)(), right);
934 branch = typecast_vocab<branch_name>(idx(args, 2));
935
936 E(!(left == right), origin::user,
937 F("%s and %s are the same revision, aborting")
938 % left % right);
939 E(!is_ancestor(db, left, right), origin::user,
940 F("%s is already an ancestor of %s")
941 % left % right);
942 E(!is_ancestor(db, right, left), origin::user,
943 F("%s is already an ancestor of %s")
944 % right % left);
945
946 // avoid failure after lots of work
947 cache_user_key(app.opts, project, keys, app.lua);
948 merge_two(app.opts, app.lua, project, keys,
949 left, right, branch, string("explicit merge"),
950 std::cout, false);
951
952 updater.maybe_do_update();
953}
954
955namespace
956{
957 namespace syms
958 {
959 symbol const ancestor("ancestor");
960 symbol const left("left");
961 symbol const right("right");
962 }
963}
964
965static void
966show_conflicts_core (database & db,
967 lua_hooks & lua,
968 revision_id const & l_id,
969 revision_id const & r_id,
970 bool const basic_io,
971 bool automate,
972 std::ostream & output)
973{
974 // Note that left and right are in the order specified on the command line.
975 // They are not in lexical order as they are with other merge commands so
976 // they may appear swapped here. The user may have done that deliberately,
977 // especially via automate, so we don't sort them here.
978
979 basic_io::stanza st;
980
981 if (basic_io)
982 {
983 st.push_binary_pair(syms::left, l_id.inner());
984 st.push_binary_pair(syms::right, r_id.inner());
985 }
986 else
987 {
988 P(F("[left] %s") % l_id);
989 P(F("[right] %s") % r_id);
990 }
991
992 if (is_ancestor(db, l_id, r_id))
993 {
994 if (basic_io)
995 {
996 basic_io::printer pr;
997 pr.print_stanza(st);
998 output.write(pr.buf.data(), pr.buf.size());
999 }
1000 else
1001 P(F("%s is an ancestor of %s; no merge is needed.")
1002 % l_id % r_id);
1003
1004 return;
1005 }
1006
1007 if (is_ancestor(db, r_id, l_id))
1008 {
1009 if (basic_io)
1010 {
1011 basic_io::printer pr;
1012 pr.print_stanza(st);
1013 output.write(pr.buf.data(), pr.buf.size());
1014 }
1015 else
1016 P(F("%s is an ancestor of %s; no merge is needed.")
1017 % r_id % l_id);
1018
1019 return;
1020 }
1021
1022 shared_ptr<roster_t> l_roster = shared_ptr<roster_t>(new roster_t());
1023 shared_ptr<roster_t> r_roster = shared_ptr<roster_t>(new roster_t());
1024 marking_map l_marking, r_marking;
1025 db.get_roster(l_id, *l_roster, l_marking);
1026 db.get_roster(r_id, *r_roster, r_marking);
1027 set<revision_id> l_uncommon_ancestors, r_uncommon_ancestors;
1028 db.get_uncommon_ancestors(l_id, r_id, l_uncommon_ancestors, r_uncommon_ancestors);
1029 roster_merge_result result;
1030 roster_merge(*l_roster, l_marking, l_uncommon_ancestors,
1031 *r_roster, r_marking, r_uncommon_ancestors,
1032 result);
1033
1034 if (result.is_clean())
1035 {
1036 if (basic_io)
1037 {
1038 basic_io::printer pr;
1039 pr.print_stanza(st);
1040 output.write(pr.buf.data(), pr.buf.size());
1041 }
1042
1043 if (!automate)
1044 P(F("0 conflicts"));
1045 }
1046 else
1047 {
1048 content_merge_database_adaptor adaptor(db, l_id, r_id,
1049 l_marking, r_marking);
1050
1051 if (basic_io)
1052 {
1053 basic_io::printer pr;
1054 st.push_binary_pair(syms::ancestor, adaptor.lca.inner());
1055 pr.print_stanza(st);
1056 output.write(pr.buf.data(), pr.buf.size());
1057 }
1058 else
1059 {
1060 P(F("[ancestor] %s") % adaptor.lca);
1061 }
1062
1063 // The basic_io routines in roster_merge.cc access these rosters via
1064 // the adaptor.
1065 adaptor.cache_roster (l_id, l_roster);
1066 adaptor.cache_roster (r_id, r_roster);
1067
1068 result.report_missing_root_conflicts(*l_roster, *r_roster, adaptor, basic_io, output);
1069 result.report_invalid_name_conflicts(*l_roster, *r_roster, adaptor, basic_io, output);
1070 result.report_directory_loop_conflicts(*l_roster, *r_roster, adaptor, basic_io, output);
1071
1072 result.report_orphaned_node_conflicts(*l_roster, *r_roster, adaptor, basic_io, output);
1073 result.report_multiple_name_conflicts(*l_roster, *r_roster, adaptor, basic_io, output);
1074 result.report_dropped_modified_conflicts(*l_roster, *r_roster, adaptor, basic_io, output);
1075 result.report_duplicate_name_conflicts(*l_roster, *r_roster, adaptor, basic_io, output);
1076
1077 result.report_attribute_conflicts(*l_roster, *r_roster, adaptor, basic_io, output);
1078 result.report_file_content_conflicts(lua, *l_roster, *r_roster, adaptor, basic_io, output);
1079
1080 if (!automate)
1081 {
1082 int const supported = result.count_supported_resolution();
1083 int const unsupported = result.count_unsupported_resolution();
1084
1085 P(FP("%d conflict with supported resolutions.",
1086 "%d conflicts with supported resolutions.",
1087 supported) % supported);
1088
1089 if (unsupported > 0)
1090 P(FP("warning: %d conflict with no supported resolutions.",
1091 "warning: %d conflicts with no supported resolutions.",
1092 unsupported) % unsupported);
1093 }
1094 }
1095}
1096
1097CMD(show_conflicts, "show_conflicts", "", CMD_REF(informative), N_("REV REV"),
1098 N_("Shows what conflicts need resolution between two revisions"),
1099 N_("The conflicts are calculated based on the two revisions given in "
1100 "the REV parameters."),
1101 options::opts::none)
1102{
1103 database db(app);
1104 project_t project(db);
1105
1106 if (args.size() != 2)
1107 throw usage(execid);
1108 revision_id l_id, r_id;
1109 complete(app.opts, app.lua, project, idx(args,0)(), l_id);
1110 complete(app.opts, app.lua, project, idx(args,1)(), r_id);
1111
1112 show_conflicts_core(db, app.lua, l_id, r_id,
1113 false, // basic_io
1114 false, // automate
1115 std::cout);
1116}
1117
1118static void get_conflicts_rids(args_vector const & args,
1119 database & db,
1120 project_t & project,
1121 app_state & app,
1122 revision_id & left_rid,
1123 revision_id & right_rid)
1124{
1125 if (args.empty())
1126 {
1127 // get ids from heads
1128 E(!app.opts.branch().empty(), origin::user,
1129 F("please specify a branch, with '--branch=BRANCH'"));
1130
1131 set<revision_id> heads;
1132 project.get_branch_heads(app.opts.branch, heads,
1133 app.opts.ignore_suspend_certs);
1134
1135 E(heads.size() >= 2, origin::user,
1136 F("branch '%s' has only 1 head; must be at least 2 for conflicts") % app.opts.branch);
1137
1138 revpair p = find_heads_to_merge (db, heads);
1139 left_rid = p.first;
1140 right_rid = p.second;
1141 }
1142 else if (args.size() == 2)
1143 {
1144 // get ids from args
1145 complete(app.opts, app.lua, project, idx(args,0)(), left_rid);
1146 complete(app.opts, app.lua, project, idx(args,1)(), right_rid);
1147 }
1148 else
1149 E(false, origin::user, F("wrong argument count"));
1150}
1151
1152// Name: show_conflicts
1153// Arguments:
1154// Two revision ids (optional, determined from the workspace if not given; there must be exactly two heads)
1155// Added in: 8.0
1156// Changed in: 9.0 (see monotone.texi for details)
1157// Purpose: Prints the conflicts between two revisions, to aid in merging them.
1158//
1159// Output format: see monotone.texi
1160//
1161// Error conditions:
1162//
1163// If the revision IDs are unknown or invalid prints an error message to
1164// stderr and exits with status 1.
1165//
1166// If revision ids are not given, and the current workspace does not have
1167// two heads, prints an error message to stderr and exits with status 1.
1168//
1169CMD_AUTOMATE(show_conflicts, N_("[LEFT_REVID RIGHT_REVID]"),
1170 N_("Shows the conflicts between two revisions"),
1171 N_("If no arguments are given, LEFT_REVID and RIGHT_REVID default to the "
1172 "first two heads that would be chosen by the 'merge' command."),
1173 options::opts::branch | options::opts::ignore_suspend_certs)
1174{
1175 database db(app);
1176 project_t project(db);
1177 revision_id l_id, r_id;
1178
1179 get_conflicts_rids(args, db, project, app, l_id, r_id);
1180 show_conflicts_core(db, app.lua, l_id, r_id,
1181 true, // basic_io
1182 true, // automate
1183 output);
1184}
1185
1186CMD(store, "store", "", CMD_REF(conflicts),
1187 "[LEFT_REVID RIGHT_REVID]",
1188 N_("Store the conflicts from merging two revisions"),
1189 (F("If no arguments are given, LEFT_REVID and RIGHT_REVID default to the "
1190 "first two heads that would be chosen by the 'merge' command. If "
1191 "'--conflicts-file' is not given, '%s' is used.") % bookkeeping_conflicts_file).str(),
1192 options::opts::branch | options::opts::conflicts_opts)
1193{
1194 database db(app);
1195 project_t project(db);
1196 revision_id left_id, right_id;
1197
1198 workspace::require_workspace(F("conflicts file must be under '_MTN'"));
1199
1200 get_conflicts_rids(args, db, project, app, left_id, right_id);
1201
1202 std::ostringstream output;
1203 show_conflicts_core(db, app.lua, left_id, right_id,
1204 true, // basic_io
1205 false, // automate
1206 output);
1207
1208 data dat(output.str(), origin::internal);
1209 write_data(app.opts.conflicts_file, dat);
1210 P(F("stored in '%s'") % app.opts.conflicts_file);
1211}
1212
1213CMD_AUTOMATE(file_merge, N_("LEFT_REVID LEFT_FILENAME RIGHT_REVID RIGHT_FILENAME"),
1214 N_("Prints the results of the internal line merger, given two child revisions and file names"),
1215 "",
1216 options::opts::none)
1217{
1218 // We would have liked to take arguments of ancestor, left, right revision
1219 // and file ids; those are provided by show_conflicts and would save
1220 // computing the common ancestor and searching for file names. But we need
1221 // the file names to get the manual merge and file encoding attributes,
1222 // and there is no way to go from file id to file name. And there is no
1223 // way to specify the ancestor id for a merge adaptor; why should we trust
1224 // the user?
1225
1226 E(args.size() == 4, origin::user,
1227 F("wrong argument count"));
1228
1229 database db(app);
1230 project_t project(db);
1231
1232 revision_id left_rid;
1233 complete(app.opts, app.lua, project, idx(args,0)(), left_rid);
1234 file_path const left_path = file_path_external(idx(args,1));
1235
1236 revision_id right_rid;
1237 complete(app.opts, app.lua, project, idx(args,2)(), right_rid);
1238 file_path const right_path = file_path_external(idx(args,3));
1239
1240 roster_t left_roster;
1241 roster_t right_roster;
1242 marking_map left_marking, right_marking;
1243 db.get_roster(left_rid, left_roster, left_marking);
1244 db.get_roster(right_rid, right_roster, right_marking);
1245
1246 content_merge_database_adaptor adaptor(db, left_rid, right_rid,
1247 left_marking, right_marking);
1248
1249 const_file_t left_n = downcast_to_file_t(left_roster.get_node(left_path));
1250 const_file_t right_n = downcast_to_file_t(right_roster.get_node(right_path));
1251
1252 revision_id ancestor_rid;
1253 file_path ancestor_path;
1254 file_id ancestor_fid;
1255 shared_ptr<roster_t const> ancestor_roster;
1256 adaptor.get_ancestral_roster(left_n->self, ancestor_rid, ancestor_roster);
1257 ancestor_roster->get_file_details(left_n->self, ancestor_fid, ancestor_path);
1258
1259 content_merger cm(app.lua, *ancestor_roster, left_roster, right_roster, adaptor);
1260 file_data ancestor_data, left_data, right_data, merge_data;
1261
1262 E(cm.attempt_auto_merge(ancestor_path, left_path, right_path,
1263 ancestor_fid, left_n->content, right_n->content,
1264 left_data, right_data, merge_data),
1265 origin::user,
1266 F("internal line merger failed"));
1267
1268 output << merge_data;
1269}
1270
1271CMD(pluck, "pluck", "", CMD_REF(workspace), N_("[PATH...]"),
1272 N_("Applies changes made at arbitrary places in history"),
1273 N_("This command takes changes made at any point in history, and "
1274 "edits your current workspace to include those changes. The end result "
1275 "is identical to 'mtn diff -r FROM -r TO | patch -p0', except that "
1276 "this command uses monotone's merger, and thus intelligently handles "
1277 "renames, conflicts, and so on.\n"
1278 "If one revision is given, applies the changes made in that revision "
1279 "compared to its parent.\n"
1280 "If two revisions are given, applies the changes made to get from the "
1281 "first revision to the second."),
1282 options::opts::revision | options::opts::depth | options::opts::exclude |
1283 options::opts::move_conflicting_paths)
1284{
1285 database db(app);
1286 workspace work(app);
1287 project_t project(db);
1288
1289 // Work out our arguments
1290 revision_id from_rid, to_rid;
1291 if (app.opts.revision.size() == 1)
1292 {
1293 complete(app.opts, app.lua, project, idx(app.opts.revision, 0)(), to_rid);
1294 std::set<revision_id> parents;
1295 db.get_revision_parents(to_rid, parents);
1296 E(parents.size() == 1, origin::user,
1297 F("revision %s is a merge.\n"
1298 "To apply the changes relative to one of its parents, use:\n"
1299 " %s pluck -r PARENT -r %s")
1300 % to_rid
1301 % prog_name
1302 % to_rid);
1303 from_rid = *parents.begin();
1304 }
1305 else if (app.opts.revision.size() == 2)
1306 {
1307 complete(app.opts, app.lua, project, idx(app.opts.revision, 0)(), from_rid);
1308 complete(app.opts, app.lua, project, idx(app.opts.revision, 1)(), to_rid);
1309 }
1310 else
1311 throw usage(execid);
1312
1313 E(!(from_rid == to_rid), origin::user, F("no changes to apply"));
1314
1315 // notionally, we have the situation
1316 //
1317 // from --> working
1318 // | |
1319 // V V
1320 // to --> merged
1321 //
1322 // - from is the revision we start plucking from
1323 // - to is the revision we stop plucking at
1324 // - working is the current contents of the workspace
1325 // - merged is the result of the plucking, and achieved by running a
1326 // merge in the fictional graph seen above
1327 //
1328 // To perform the merge, we use the real from roster, and the real working
1329 // roster, but synthesize a temporary 'to' roster. This ensures that the
1330 // 'from', 'working' and 'base' rosters all use the same nid namespace,
1331 // while any additions that happened between 'from' and 'to' should be
1332 // considered as new nodes, even if the file that was added is in fact in
1333 // 'working' already -- so 'to' needs its own namespace. (Among other
1334 // things, it is impossible with our merge formalism to have the above
1335 // graph with a node that exists in 'to' and 'working', but not 'from'.)
1336 //
1337 // finally, we take the cset from working -> merged, and apply that to the
1338 // workspace
1339 // and take the cset from the workspace's base, and write that to _MTN/work
1340
1341 // The node id source we'll use for the 'working' and 'to' rosters.
1342 temp_node_id_source nis;
1343
1344 // Get the FROM roster
1345 shared_ptr<roster_t> from_roster = shared_ptr<roster_t>(new roster_t());
1346 MM(*from_roster);
1347 db.get_roster(from_rid, *from_roster);
1348
1349 // Get the WORKING roster
1350 shared_ptr<roster_t> working_roster = shared_ptr<roster_t>(new roster_t());
1351 MM(*working_roster);
1352 work.get_current_roster_shape(db, nis, *working_roster);
1353
1354 work.update_current_roster_from_filesystem(*working_roster);
1355
1356 // Get the FROM->TO cset...
1357 cset from_to_to; MM(from_to_to);
1358 cset from_to_to_excluded; MM(from_to_to_excluded);
1359 {
1360 roster_t to_true_roster;
1361 db.get_roster(to_rid, to_true_roster);
1362 node_restriction mask(args_to_paths(args),
1363 args_to_paths(app.opts.exclude),
1364 app.opts.depth,
1365 *from_roster, to_true_roster,
1366 ignored_file(work));
1367
1368 roster_t restricted_roster;
1369 make_restricted_roster(*from_roster, to_true_roster,
1370 restricted_roster, mask);
1371
1372 make_cset(*from_roster, restricted_roster, from_to_to);
1373 make_cset(restricted_roster, to_true_roster, from_to_to_excluded);
1374 }
1375 E(!from_to_to.empty(), origin::user, F("no changes to be applied"));
1376 // ...and use it to create the TO roster
1377 shared_ptr<roster_t> to_roster = shared_ptr<roster_t>(new roster_t());
1378 MM(*to_roster);
1379 {
1380 *to_roster = *from_roster;
1381 editable_roster_base editable_to_roster(*to_roster, nis);
1382 from_to_to.apply_to(editable_to_roster);
1383 }
1384
1385 parent_map parents;
1386 work.get_parent_rosters(db, parents);
1387
1388 revision_t working_rev;
1389 revision_id working_rid;
1390 make_revision_for_workspace(parents, *working_roster, working_rev);
1391 calculate_ident(working_rev, working_rid);
1392
1393 // Now do the merge
1394 roster_merge_result result;
1395 marking_map left_markings, right_markings;
1396 three_way_merge(from_rid, *from_roster,
1397 working_rid, *working_roster,
1398 to_rid, *to_roster,
1399 result, left_markings, right_markings);
1400
1401 roster_t & merged_roster = result.roster;
1402
1403 map<file_id, file_path> paths;
1404 get_content_paths(*working_roster, paths);
1405
1406 content_merge_workspace_adaptor wca(db, from_rid, from_roster,
1407 left_markings, right_markings, paths);
1408
1409 wca.cache_roster(working_rid, working_roster);
1410 // cache the synthetic to_roster under the to_rid so that the real
1411 // to_roster is not fetched from the db which does not have temporary nids
1412 wca.cache_roster(to_rid, to_roster);
1413
1414 resolve_merge_conflicts(app.lua, app.opts, *working_roster, *to_roster,
1415 result, wca, nis, false);
1416
1417 I(result.is_clean());
1418 // temporary node ids may appear
1419 merged_roster.check_sane(true);
1420
1421 // we apply the working to merged cset to the workspace
1422 cset update;
1423 MM(update);
1424 make_cset(*working_roster, merged_roster, update);
1425 E(!update.empty(), origin::no_fault, F("no changes were applied"));
1426 work.perform_content_update(*working_roster, merged_roster, update, wca, true,
1427 app.opts.move_conflicting_paths);
1428
1429 P(F("applied changes to workspace"));
1430
1431 // and record any remaining changes in _MTN/revision
1432 revision_t remaining;
1433 MM(remaining);
1434 make_revision_for_workspace(parents, merged_roster, remaining);
1435
1436 // small race condition here...
1437 work.put_work_rev(remaining);
1438
1439 // add a note to the user log file about what we did
1440 {
1441 utf8 log;
1442 work.read_user_log(log);
1443 std::string log_str = log();
1444 if (!log_str.empty())
1445 log_str += "\n";
1446 if (from_to_to_excluded.empty())
1447 log_str += (FL("applied changes from %s\n"
1448 " through %s\n")
1449 % from_rid
1450 % to_rid).str();
1451 else
1452 log_str += (FL("applied partial changes from %s\n"
1453 " through %s\n")
1454 % from_rid
1455 % to_rid).str();
1456 work.write_user_log(utf8(log_str, origin::internal));
1457 }
1458}
1459
1460CMD(heads, "heads", "", CMD_REF(tree), "",
1461 N_("Shows unmerged head revisions of a branch"),
1462 "",
1463 options::opts::branch)
1464{
1465 set<revision_id> heads;
1466 if (!args.empty())
1467 throw usage(execid);
1468
1469 E(!app.opts.branch().empty(), origin::user,
1470 F("please specify a branch, with '--branch=BRANCH'"));
1471
1472 database db(app);
1473 project_t project(db);
1474
1475 project.get_branch_heads(app.opts.branch, heads,
1476 app.opts.ignore_suspend_certs);
1477
1478 if (heads.empty())
1479 P(F("branch '%s' is empty") % app.opts.branch);
1480 else if (heads.size() == 1)
1481 P(F("branch '%s' is currently merged:") % app.opts.branch);
1482 else
1483 P(F("branch '%s' is currently unmerged:") % app.opts.branch);
1484
1485 for (set<revision_id>::const_iterator i = heads.begin();
1486 i != heads.end(); ++i)
1487 cout << describe_revision(app.opts, app.lua, project, *i) << '\n';
1488}
1489
1490CMD(get_roster, "get_roster", "", CMD_REF(debug), N_("[REVID]"),
1491 N_("Dumps the roster associated with a given identifier"),
1492 N_("If no REVID is given, the workspace is used."),
1493 options::opts::none)
1494{
1495 database db(app);
1496 roster_t roster;
1497 marking_map mm;
1498
1499 if (args.empty())
1500 {
1501 parent_map parents;
1502 temp_node_id_source nis;
1503 revision_id rid(fake_id());
1504
1505 workspace work(app);
1506 work.get_parent_rosters(db, parents);
1507 work.get_current_roster_shape(db, nis, roster);
1508 work.update_current_roster_from_filesystem(roster);
1509
1510 if (parents.empty())
1511 {
1512 mark_roster_with_no_parents(rid, roster, mm);
1513 }
1514 else if (parents.size() == 1)
1515 {
1516 roster_t parent = parent_roster(parents.begin());
1517 marking_map parent_mm = parent_marking(parents.begin());
1518 mark_roster_with_one_parent(parent, parent_mm, rid, roster, mm);
1519 }
1520 else
1521 {
1522 parent_map::const_iterator i = parents.begin();
1523 revision_id left_id = parent_id(i);
1524 roster_t const & left_roster = parent_roster(i);
1525 marking_map const & left_markings = parent_marking(i);
1526
1527 i++;
1528 revision_id right_id = parent_id(i);
1529 roster_t const & right_roster = parent_roster(i);
1530 marking_map const & right_markings = parent_marking(i);
1531
1532 i++; I(i == parents.end());
1533
1534 set<revision_id> left_uncommon_ancestors, right_uncommon_ancestors;
1535 db.get_uncommon_ancestors(left_id, right_id,
1536 left_uncommon_ancestors,
1537 right_uncommon_ancestors);
1538
1539 mark_merge_roster(left_roster, left_markings,
1540 left_uncommon_ancestors,
1541 right_roster, right_markings,
1542 right_uncommon_ancestors,
1543 rid, roster, mm);
1544 }
1545 }
1546 else if (args.size() == 1)
1547 {
1548 database db(app);
1549 project_t project(db);
1550 revision_id rid;
1551 complete(app.opts, app.lua, project, idx(args, 0)(), rid);
1552 I(!null_id(rid));
1553 db.get_roster(rid, roster, mm);
1554 }
1555 else
1556 throw usage(execid);
1557
1558 roster_data dat;
1559 write_roster_and_marking(roster, mm, dat);
1560 cout << dat;
1561}
1562
1563
1564// Local Variables:
1565// mode: C++
1566// fill-column: 76
1567// c-file-style: "gnu"
1568// indent-tabs-mode: nil
1569// End:
1570// 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