comparison mercurial/merge.py @ 3105:7c7469d41ade

merge: pull manifest comparison out into separate function
author Matt Mackall <mpm@selenic.com>
date Sun, 17 Sep 2006 16:13:03 -0500
parents ef4e5d05bac4
children 4ec28446fca8
comparison
equal deleted inserted replaced
3104:ef4e5d05bac4 3105:7c7469d41ade
50 50
51 os.unlink(b) 51 os.unlink(b)
52 os.unlink(c) 52 os.unlink(c)
53 return r 53 return r
54 54
55 def manifestmerge(ui, m1, m2, ma, overwrite, backwards):
56 """
57 Merge manifest m1 with m2 using ancestor ma and generate merge action list
58 """
59
60 action = []
61
62 # Compare manifests
63 for f, n in m1.iteritems():
64 if f in m2:
65 queued = 0
66
67 # are files different?
68 if n != m2[f]:
69 a = ma.get(f, nullid)
70 # are both different from the ancestor?
71 if not overwrite and n != a and m2[f] != a:
72 ui.debug(_(" %s versions differ, resolve\n") % f)
73 action.append((f, "m", fmerge(f, m1, m2, ma), n[:20], m2[f]))
74 queued = 1
75 # are we clobbering?
76 # is remote's version newer?
77 # or are we going back in time and clean?
78 elif overwrite or m2[f] != a or (backwards and not n[20:]):
79 ui.debug(_(" remote %s is newer, get\n") % f)
80 action.append((f, "g", m2.execf(f), m2[f]))
81 queued = 1
82 elif n[20:] in ("u","a"):
83 # this unknown file is the same as the checkout
84 # we need to reset the dirstate if the file was added
85 action.append((f, "g", m2.execf(f), m2[f]))
86
87 # do we still need to look at mode bits?
88 if not queued and m1.execf(f) != m2.execf(f):
89 if overwrite:
90 ui.debug(_(" updating permissions for %s\n") % f)
91 action.append((f, "e", m2.execf(f)))
92 else:
93 mode = fmerge(f, m1, m2, ma)
94 if mode != m1.execf(f):
95 ui.debug(_(" updating permissions for %s\n")
96 % f)
97 action.append((f, "e", m2.execf(f)))
98 del m2[f]
99 elif f in ma:
100 if n != ma[f]:
101 r = _("d")
102 if not overwrite:
103 r = ui.prompt(
104 (_(" local changed %s which remote deleted\n") % f) +
105 _("(k)eep or (d)elete?"), _("[kd]"), _("k"))
106 if r == _("d"):
107 action.append((f, "r"))
108 else:
109 ui.debug(_("other deleted %s\n") % f)
110 action.append((f, "r"))
111 else:
112 # file is created on branch or in working directory
113 if overwrite and n[20:] != "u":
114 ui.debug(_("remote deleted %s, clobbering\n") % f)
115 action.append((f, "r"))
116 elif not n[20:]: # same as parent
117 if backwards:
118 ui.debug(_("remote deleted %s\n") % f)
119 action.append((f, "r"))
120 else:
121 ui.debug(_("local modified %s, keeping\n") % f)
122 else:
123 ui.debug(_("working dir created %s, keeping\n") % f)
124
125 for f, n in m2.iteritems():
126 if f[0] == "/":
127 continue
128 if f in ma and n != ma[f]:
129 r = _("k")
130 if not overwrite:
131 r = ui.prompt(
132 (_("remote changed %s which local deleted\n") % f) +
133 _("(k)eep or (d)elete?"), _("[kd]"), _("k"))
134 if r == _("k"):
135 action.append((f, "g", m2.execf(f), n))
136 elif f not in ma:
137 ui.debug(_("remote created %s\n") % f)
138 action.append((f, "g", m2.execf(f), n))
139 else:
140 if overwrite or backwards:
141 ui.debug(_("local deleted %s, recreating\n") % f)
142 action.append((f, "g", m2.execf(f), n))
143 else:
144 ui.debug(_("local deleted %s\n") % f)
145
146 return action
147
55 def update(repo, node, branchmerge=False, force=False, partial=None, 148 def update(repo, node, branchmerge=False, force=False, partial=None,
56 wlock=None, show_stats=True, remind=True): 149 wlock=None, show_stats=True, remind=True):
57 150
58 overwrite = force and not branchmerge 151 overwrite = force and not branchmerge
59 forcemerge = force and branchmerge 152 forcemerge = force and branchmerge
132 for f in m1.keys(): 225 for f in m1.keys():
133 if not partial(f): del m1[f] 226 if not partial(f): del m1[f]
134 for f in m2.keys(): 227 for f in m2.keys():
135 if not partial(f): del m2[f] 228 if not partial(f): del m2[f]
136 229
137 # Compare manifests 230 action += manifestmerge(repo.ui, m1, m2, ma, overwrite, backwards)
138 for f, n in m1.iteritems():
139 if f in m2:
140 queued = 0
141
142 # are files different?
143 if n != m2[f]:
144 a = ma.get(f, nullid)
145 # are both different from the ancestor?
146 if not overwrite and n != a and m2[f] != a:
147 repo.ui.debug(_(" %s versions differ, resolve\n") % f)
148 action.append((f, "m", fmerge(f, m1, m2, ma), n[:20], m2[f]))
149 queued = 1
150 # are we clobbering?
151 # is remote's version newer?
152 # or are we going back in time and clean?
153 elif overwrite or m2[f] != a or (backwards and not n[20:]):
154 repo.ui.debug(_(" remote %s is newer, get\n") % f)
155 action.append((f, "g", m2.execf(f), m2[f]))
156 queued = 1
157 elif n[20:] in ("u","a"):
158 # this unknown file is the same as the checkout
159 # we need to reset the dirstate if the file was added
160 action.append((f, "g", m2.execf(f), m2[f]))
161
162 # do we still need to look at mode bits?
163 if not queued and m1.execf(f) != m2.execf(f):
164 if overwrite:
165 repo.ui.debug(_(" updating permissions for %s\n") % f)
166 action.append((f, "e", m2.execf(f)))
167 else:
168 mode = fmerge(f, m1, m2, ma)
169 if mode != m1.execf(f):
170 repo.ui.debug(_(" updating permissions for %s\n")
171 % f)
172 action.append((f, "e", m2.execf(f)))
173 del m2[f]
174 elif f in ma:
175 if n != ma[f]:
176 r = _("d")
177 if not overwrite:
178 r = repo.ui.prompt(
179 (_(" local changed %s which remote deleted\n") % f) +
180 _("(k)eep or (d)elete?"), _("[kd]"), _("k"))
181 if r == _("d"):
182 action.append((f, "r"))
183 else:
184 repo.ui.debug(_("other deleted %s\n") % f)
185 action.append((f, "r"))
186 else:
187 # file is created on branch or in working directory
188 if overwrite and n[20:] != "u":
189 repo.ui.debug(_("remote deleted %s, clobbering\n") % f)
190 action.append((f, "r"))
191 elif not n[20:]: # same as parent
192 if backwards:
193 repo.ui.debug(_("remote deleted %s\n") % f)
194 action.append((f, "r"))
195 else:
196 repo.ui.debug(_("local modified %s, keeping\n") % f)
197 else:
198 repo.ui.debug(_("working dir created %s, keeping\n") % f)
199
200 for f, n in m2.iteritems():
201 if f[0] == "/":
202 continue
203 if f in ma and n != ma[f]:
204 r = _("k")
205 if not overwrite:
206 r = repo.ui.prompt(
207 (_("remote changed %s which local deleted\n") % f) +
208 _("(k)eep or (d)elete?"), _("[kd]"), _("k"))
209 if r == _("k"):
210 action.append((f, "g", m2.execf(f), n))
211 elif f not in ma:
212 repo.ui.debug(_("remote created %s\n") % f)
213 action.append((f, "g", m2.execf(f), n))
214 else:
215 if overwrite or backwards:
216 repo.ui.debug(_("local deleted %s, recreating\n") % f)
217 action.append((f, "g", m2.execf(f), n))
218 else:
219 repo.ui.debug(_("local deleted %s\n") % f)
220
221 del m1, m2, ma 231 del m1, m2, ma
222 232
223 ### apply phase 233 ### apply phase
224 234
225 if linear_path or overwrite: 235 if linear_path or overwrite: