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#include "rev_types.hh"
14#include "database.hh"
15#include "diff_patch.hh"
16#include "roster.hh" // needs full definition of roster_t available
17
18// interactions between conflict types:
19// node rename conflicts never participate in structural conflicts
20// (e.g., merge <rename a foo; rename b bar>, <rename a bar> could be
21// considered to have two conflicts -- 'a' being renamed to both 'foo' and
22// 'bar', and 'a' and 'b' both being renamed to 'bar'. Only the former
23// occurs; 'b' merges cleanly and will be named 'bar' in the resulting
24// manifest.)
25//
26
27// renaming the root dir allows these:
28// -- _MTN in root
29// -- missing root directory
30
31// this is a node that cleanly merged to some name, but that name was somehow
32// forbidden. (Currently, the only forbidden name is "_MTN" in the root
33// directory.)
34struct invalid_name_conflict
35{
36 node_id nid;
37 std::pair<node_id, path_component> parent_name;
38};
39
40struct directory_loop_conflict
41{
42 node_id nid;
43 std::pair<node_id, path_component> parent_name;
44};
45
46// orphaned nodes always merged their name cleanly, so we simply put that name
47// here. the node in the resulting roster is detached.
48struct orphaned_node_conflict
49{
50 node_id nid;
51 std::pair<node_id, path_component> parent_name;
52};
53
54// our general strategy is to return a (possibly insane) roster, and a list of
55// conflicts encountered in that roster. Each conflict encountered in merging
56// the roster creates an entry in this list.
57
58// nodes with multiple name conflicts are left detached in the resulting
59// roster, with null parent and name fields.
60// note that it is possible that the parent node on the left, the right, or
61// both, no longer exist in the merged roster. also note that it is possible
62// that on one or both sides, they do exist, but already have an entry with
63// the given name.
64struct multiple_name_conflict
65{
66 node_id nid;
67 multiple_name_conflict(node_id nid) : nid(nid) {}
68 std::pair<node_id, path_component> left, right;
69};
70
71// this is when two distinct nodes want to have the same name. these nodes
72// always each merged their names cleanly. the nodes in the resulting roster
73// are both detached.
74// only two nodes are possible, because we
75// -- only merge two rosters at a time
76// -- merge (parent, basename) as a single scalar. If we merged them
77// separately, then it would be possible to have one side of a merge
78// rename a bunch of files in different directories to all have the same
79// basename, and the other side of the merge to move them all into the
80// same directory.
81// a clean *-merge of a scalar always takes on the value of one parent or
82// another, and the requirement here is that each node have a unique (parent,
83// basename) tuple, and since our requirement matches our *-merge scalar,
84// we're okay.
85struct duplicate_name_conflict
86{
87 node_id left_nid, right_nid;
88 std::pair<node_id, path_component> parent_name;
89};
90
91// nodes with attribute conflicts are left attached in the resulting tree (unless
92// detached for some other reason), but with the given attribute left out of
93// their full_attr_map_t. Note that this doesn't actually leave the resulting
94// roster insane (FIXME: we could put an invalid attr value in instead, like a
95// pair (false, "foo") (since the second value can only be non-null if the
96// first is 'true'). Should we do this?)
97struct attribute_conflict
98{
99 node_id nid;
100 attribute_conflict(node_id nid) : nid(nid) {}
101 attr_key key; // attr_name?
102 std::pair<bool, attr_value> left, right;
103};
104
105// files with content conflicts are left attached in resulting tree (unless
106// detached for some other reason), but with a null content hash.
107struct file_content_conflict
108{
109 node_id nid;
110 file_content_conflict(node_id nid) : nid(nid) {}
111 file_id left, right;
112};
113
114
115template <> void dump(invalid_name_conflict const & conflict, std::string & out);
116template <> void dump(directory_loop_conflict const & conflict, std::string & out);
117
118template <> void dump(orphaned_node_conflict const & conflict, std::string & out);
119template <> void dump(multiple_name_conflict const & conflict, std::string & out);
120template <> void dump(duplicate_name_conflict const & conflict, std::string & out);
121
122template <> void dump(attribute_conflict const & conflict, std::string & out);
123template <> void dump(file_content_conflict const & conflict, std::string & out);
124
125struct roster_merge_result
126{
127 // three main types of conflicts
128 // - structural conflicts (which have the following subtypes)
129 // - missing root directory
130 // - invalid name conflicts
131 // - duplicate name conflicts
132 // - orphaned node conflicts
133 // - multiple name conflicts
134 // - directory loop conflicts
135 // - attribute conflicts
136 // - file content conflicts
137
138 bool missing_root_dir;
139 std::vector<invalid_name_conflict> invalid_name_conflicts;
140 std::vector<directory_loop_conflict> directory_loop_conflicts;
141
142 std::vector<orphaned_node_conflict> orphaned_node_conflicts;
143 std::vector<multiple_name_conflict> multiple_name_conflicts;
144 std::vector<duplicate_name_conflict> duplicate_name_conflicts;
145
146 std::vector<attribute_conflict> attribute_conflicts;
147 std::vector<file_content_conflict> file_content_conflicts;
148
149
150 // this roster is sane if is_clean() returns true
151 roster_t roster;
152 bool is_clean() const;
153 bool has_content_conflicts() const;
154 bool has_non_content_conflicts() const;
155 void log_conflicts() const;
156
157 void report_missing_root_conflicts(roster_t const & left,
158 roster_t const & right,
159 content_merge_adaptor & adaptor,
160 bool const basic_io,
161 std::ostream & output) const;
162 void report_invalid_name_conflicts(roster_t const & left,
163 roster_t const & right,
164 content_merge_adaptor & adaptor,
165 bool const basic_io,
166 std::ostream & output) const;
167 void report_directory_loop_conflicts(roster_t const & left,
168 roster_t const & right,
169 content_merge_adaptor & adaptor,
170 bool const basic_io,
171 std::ostream & output) const;
172
173 void report_orphaned_node_conflicts(roster_t const & left,
174 roster_t const & right,
175 content_merge_adaptor & adaptor,
176 bool const basic_io,
177 std::ostream & output) const;
178 void report_multiple_name_conflicts(roster_t const & left,
179 roster_t const & right,
180 content_merge_adaptor & adaptor,
181 bool const basic_io,
182 std::ostream & output) const;
183 void report_duplicate_name_conflicts(roster_t const & left,
184 roster_t const & right,
185 content_merge_adaptor & adaptor,
186 bool const basic_io,
187 std::ostream & output) const;
188
189 void report_attribute_conflicts(roster_t const & left,
190 roster_t const & right,
191 content_merge_adaptor & adaptor,
192 bool const basic_io,
193 std::ostream & output) const;
194 void report_file_content_conflicts(roster_t const & left,
195 roster_t const & right,
196 content_merge_adaptor & adaptor,
197 bool const basic_io,
198 std::ostream & output) const;
199
200 void clear();
201};
202
203template <> void dump(roster_merge_result const & result, std::string & out);
204
205void
206roster_merge(roster_t const & left_parent,
207 marking_map const & left_markings,
208 std::set<revision_id> const & left_uncommon_ancestors,
209 roster_t const & right_parent,
210 marking_map const & right_markings,
211 std::set<revision_id> const & right_uncommon_ancestors,
212 roster_merge_result & result);
213
214
215// Local Variables:
216// mode: C++
217// fill-column: 76
218// c-file-style: "gnu"
219// indent-tabs-mode: nil
220// End:
221// vim: et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s:
222
223#endif

Archive Download this file

Branches

Tags

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