monotone

monotone Mtn Source Tree

Root/roster_merge.hh

1#ifndef __ROSTER_MERGE_HH__
2#define __ROSTER_MERGE_HH__
3
4// Copyright (C) 2005 Nathaniel Smith <njs@pobox.com>
5//
6// This program is made available under the GNU GPL version 2.0 or
7// greater. See the accompanying file COPYING for details.
8//
9// This program is distributed WITHOUT ANY WARRANTY; without even the
10// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11// PURPOSE.
12
13
14#include "vocab.hh"
15#include "roster.hh"
16
17// our general strategy is to return a (possibly insane) roster, and a list of
18// conflicts encountered in that roster. Each conflict encountered in merging
19// the roster creates an entry in this list.
20
21// nodes with name conflicts are left detached in the resulting roster, with
22// null parent and name fields.
23// note that it is possible that the parent node on the left, the right, or
24// both, no longer exist in the merged roster. also note that it is possible
25// that on one or both sides, they do exist, but already have an entry with
26// the given name.
27struct node_name_conflict
28{
29 node_id nid;
30 node_name_conflict(node_id nid) : nid(nid) {}
31 std::pair<node_id, path_component> left, right;
32};
33
34// files with content conflicts are left attached in resulting tree (unless
35// detached for some other reason), but with a null content hash.
36struct file_content_conflict
37{
38 node_id nid;
39 file_content_conflict(node_id nid) : nid(nid) {}
40 file_id left, right;
41};
42
43// nodes with attrs conflicts are left attached in the resulting tree (unless
44// detached for some other reason), but with the given attribute left out of
45// their full_attr_map_t. Note that this doesn't actually leave the resulting
46// roster insane (FIXME: we could put an invalid attr value in instead, like a
47// pair (false, "foo") (since the second value can only be non-null if the
48// first is 'true'). Should we do this?)
49struct node_attr_conflict
50{
51 node_id nid;
52 node_attr_conflict(node_id nid) : nid(nid) {}
53 attr_key key;
54 std::pair<bool, attr_value> left, right;
55};
56
57// interactions between conflict types:
58// node rename conflicts never participate in structural conflicts
59// (e.g., merge <rename a foo; rename b bar>, <rename a bar> could be
60// considered to have two conflicts -- 'a' being renamed to both 'foo' and
61// 'bar', and 'a' and 'b' both being renamed to 'bar'. Only the former
62// occurs; 'b' merges cleanly and will be named 'bar' in the resulting
63// manifest.)
64//
65
66// orphaned nodes always merged their name cleanly, so we simply put that name
67// here. the node in the resulting roster is detached.
68struct orphaned_node_conflict
69{
70 node_id nid;
71 std::pair<node_id, path_component> parent_name;
72};
73
74// this is when two distinct nodes want to have the same name. these nodes
75// always each merged their names cleanly. the nodes in the resulting roster
76// are both detached.
77// only two nodes are possible, because we
78// -- only merge two rosters at a time
79// -- merge (parent, basename) as a single scalar. If we merged them
80// separately, then it would be possible to have one side of a merge
81// rename a bunch of files in different directories to all have the same
82// basename, and the other side of the merge to move them all into the
83// same directory.
84// a clean *-merge of a scalar always takes on the value of one parent or
85// another, and the requirement here is that each node have a unique (parent,
86// basename) tuple, and since our requirement matches our *-merge scalar,
87// we're okay.
88struct rename_target_conflict
89{
90 node_id nid1, nid2;
91 std::pair<node_id, path_component> parent_name;
92};
93
94struct directory_loop_conflict
95{
96 node_id nid;
97 std::pair<node_id, path_component> parent_name;
98};
99
100// renaming the root dir allows these:
101// -- _MTN in root
102// -- missing root directory
103
104// this is a node that cleanly merged to some name, but that name was somehow
105// forbidden. (Currently, the only forbidden name is "_MTN" in the root
106// directory.)
107struct illegal_name_conflict
108{
109 node_id nid;
110 std::pair<node_id, path_component> parent_name;
111};
112
113struct roster_merge_result
114{
115 std::vector<node_name_conflict> node_name_conflicts;
116 std::vector<file_content_conflict> file_content_conflicts;
117 std::vector<node_attr_conflict> node_attr_conflicts;
118 std::vector<orphaned_node_conflict> orphaned_node_conflicts;
119 std::vector<rename_target_conflict> rename_target_conflicts;
120 std::vector<directory_loop_conflict> directory_loop_conflicts;
121 std::vector<illegal_name_conflict> illegal_name_conflicts;
122 bool missing_root_dir;
123 // this roster is sane if is_clean() returns true
124 roster_t roster;
125 bool is_clean() const;
126 bool is_clean_except_for_content() const;
127 void log_conflicts() const;
128 void warn_non_content_conflicts() const;
129 void clear();
130};
131
132template <> void dump(roster_merge_result const & result, std::string & out);
133
134void
135roster_merge(roster_t const & left_parent,
136 marking_map const & left_markings,
137 std::set<revision_id> const & left_uncommon_ancestors,
138 roster_t const & right_parent,
139 marking_map const & right_markings,
140 std::set<revision_id> const & right_uncommon_ancestors,
141 roster_merge_result & result);
142
143
144// Local Variables:
145// mode: C++
146// fill-column: 76
147// c-file-style: "gnu"
148// indent-tabs-mode: nil
149// End:
150// vim: et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s:
151
152#endif

Archive Download this file

Branches

Tags

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