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

Archive Download this file

Branches

Tags

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