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

Archive Download this file

Branches

Tags

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