46 os.unlink(b) |
46 os.unlink(b) |
47 os.unlink(c) |
47 os.unlink(c) |
48 return r |
48 return r |
49 |
49 |
50 def update(repo, node, branchmerge=False, force=False, partial=None, |
50 def update(repo, node, branchmerge=False, force=False, partial=None, |
51 forcemerge=False, wlock=None, show_stats=True, remind=True): |
51 wlock=None, show_stats=True, remind=True): |
|
52 |
|
53 overwrite = force and not branchmerge |
|
54 forcemerge = force and branchmerge |
52 |
55 |
53 if not wlock: |
56 if not wlock: |
54 wlock = repo.wlock() |
57 wlock = repo.wlock() |
55 |
58 |
56 ### check phase |
59 ### check phase |
57 |
60 |
58 pl = repo.dirstate.parents() |
61 pl = repo.dirstate.parents() |
59 if not force and pl[1] != nullid: |
62 if not overwrite and pl[1] != nullid: |
60 raise util.Abort(_("outstanding uncommitted merges")) |
63 raise util.Abort(_("outstanding uncommitted merges")) |
61 |
64 |
62 p1, p2 = pl[0], node |
65 p1, p2 = pl[0], node |
63 pa = repo.changelog.ancestor(p1, p2) |
66 pa = repo.changelog.ancestor(p1, p2) |
64 |
67 |
66 linear_path = (pa == p1 or pa == p2) |
69 linear_path = (pa == p1 or pa == p2) |
67 if branchmerge and linear_path: |
70 if branchmerge and linear_path: |
68 raise util.Abort(_("there is nothing to merge, just use " |
71 raise util.Abort(_("there is nothing to merge, just use " |
69 "'hg update' or look at 'hg heads'")) |
72 "'hg update' or look at 'hg heads'")) |
70 |
73 |
71 if not force and not linear_path and not branchmerge: |
74 if not overwrite and not linear_path and not branchmerge: |
72 raise util.Abort(_("this update spans a branch, use 'hg merge' " |
75 raise util.Abort(_("update spans branches, use 'hg merge' " |
73 "or 'hg update -C' to lose changes")) |
76 "or 'hg update -C' to lose changes")) |
74 |
77 |
75 modified, added, removed, deleted, unknown = repo.changes() |
78 modified, added, removed, deleted, unknown = repo.changes() |
76 if branchmerge and not forcemerge: |
79 if branchmerge and not forcemerge: |
77 if modified or added or removed: |
80 if modified or added or removed: |
85 m2 = repo.manifest.read(m2n).copy() |
88 m2 = repo.manifest.read(m2n).copy() |
86 mf2 = repo.manifest.readflags(m2n) |
89 mf2 = repo.manifest.readflags(m2n) |
87 ma = repo.manifest.read(man) |
90 ma = repo.manifest.read(man) |
88 mfa = repo.manifest.readflags(man) |
91 mfa = repo.manifest.readflags(man) |
89 |
92 |
90 if not forcemerge and not force: |
93 if not forcemerge and not overwrite: |
91 for f in unknown: |
94 for f in unknown: |
92 if f in m2: |
95 if f in m2: |
93 t1 = repo.wread(f) |
96 t1 = repo.wread(f) |
94 t2 = repo.file(f).read(m2[f]) |
97 t2 = repo.file(f).read(m2[f]) |
95 if cmp(t1, t2) != 0: |
98 if cmp(t1, t2) != 0: |
97 " dir and differs from remote") % f) |
100 " dir and differs from remote") % f) |
98 |
101 |
99 # resolve the manifest to determine which files |
102 # resolve the manifest to determine which files |
100 # we care about merging |
103 # we care about merging |
101 repo.ui.note(_("resolving manifests\n")) |
104 repo.ui.note(_("resolving manifests\n")) |
102 repo.ui.debug(_(" force %s branchmerge %s partial %s linear %s\n") % |
105 repo.ui.debug(_(" overwrite %s branchmerge %s partial %s linear %s\n") % |
103 (force, branchmerge, partial and True or False, linear_path)) |
106 (overwrite, branchmerge, partial and True or False, linear_path)) |
104 repo.ui.debug(_(" ancestor %s local %s remote %s\n") % |
107 repo.ui.debug(_(" ancestor %s local %s remote %s\n") % |
105 (short(man), short(m1n), short(m2n))) |
108 (short(man), short(m1n), short(m2n))) |
106 |
109 |
107 merge = {} |
110 merge = {} |
108 get = {} |
111 get = {} |
157 merge[f] = (m1.get(f, nullid), m2[f], mode) |
160 merge[f] = (m1.get(f, nullid), m2[f], mode) |
158 s = 1 |
161 s = 1 |
159 # are we clobbering? |
162 # are we clobbering? |
160 # is remote's version newer? |
163 # is remote's version newer? |
161 # or are we going back in time? |
164 # or are we going back in time? |
162 elif force or m2[f] != a or (p2 == pa and mw[f] == m1[f]): |
165 elif overwrite or m2[f] != a or (p2 == pa and mw[f] == m1[f]): |
163 repo.ui.debug(_(" remote %s is newer, get\n") % f) |
166 repo.ui.debug(_(" remote %s is newer, get\n") % f) |
164 get[f] = m2[f] |
167 get[f] = m2[f] |
165 s = 1 |
168 s = 1 |
166 elif f in umap or f in added: |
169 elif f in umap or f in added: |
167 # this unknown file is the same as the checkout |
170 # this unknown file is the same as the checkout |
168 # we need to reset the dirstate if the file was added |
171 # we need to reset the dirstate if the file was added |
169 get[f] = m2[f] |
172 get[f] = m2[f] |
170 |
173 |
171 if not s and mfw[f] != mf2[f]: |
174 if not s and mfw[f] != mf2[f]: |
172 if force: |
175 if overwrite: |
173 repo.ui.debug(_(" updating permissions for %s\n") % f) |
176 repo.ui.debug(_(" updating permissions for %s\n") % f) |
174 util.set_exec(repo.wjoin(f), mf2[f]) |
177 util.set_exec(repo.wjoin(f), mf2[f]) |
175 else: |
178 else: |
176 a, b, c = mfa.get(f, 0), mfw[f], mf2[f] |
179 a, b, c = mfa.get(f, 0), mfw[f], mf2[f] |
177 mode = ((a^b) | (a^c)) ^ a |
180 mode = ((a^b) | (a^c)) ^ a |
181 util.set_exec(repo.wjoin(f), mode) |
184 util.set_exec(repo.wjoin(f), mode) |
182 del m2[f] |
185 del m2[f] |
183 elif f in ma: |
186 elif f in ma: |
184 if n != ma[f]: |
187 if n != ma[f]: |
185 r = _("d") |
188 r = _("d") |
186 if not force and (linear_path or branchmerge): |
189 if not overwrite and (linear_path or branchmerge): |
187 r = repo.ui.prompt( |
190 r = repo.ui.prompt( |
188 (_(" local changed %s which remote deleted\n") % f) + |
191 (_(" local changed %s which remote deleted\n") % f) + |
189 _("(k)eep or (d)elete?"), _("[kd]"), _("k")) |
192 _("(k)eep or (d)elete?"), _("[kd]"), _("k")) |
190 if r == _("d"): |
193 if r == _("d"): |
191 remove.append(f) |
194 remove.append(f) |
192 else: |
195 else: |
193 repo.ui.debug(_("other deleted %s\n") % f) |
196 repo.ui.debug(_("other deleted %s\n") % f) |
194 remove.append(f) # other deleted it |
197 remove.append(f) # other deleted it |
195 else: |
198 else: |
196 # file is created on branch or in working directory |
199 # file is created on branch or in working directory |
197 if force and f not in umap: |
200 if overwrite and f not in umap: |
198 repo.ui.debug(_("remote deleted %s, clobbering\n") % f) |
201 repo.ui.debug(_("remote deleted %s, clobbering\n") % f) |
199 remove.append(f) |
202 remove.append(f) |
200 elif n == m1.get(f, nullid): # same as parent |
203 elif n == m1.get(f, nullid): # same as parent |
201 if p2 == pa: # going backwards? |
204 if p2 == pa: # going backwards? |
202 repo.ui.debug(_("remote deleted %s\n") % f) |
205 repo.ui.debug(_("remote deleted %s\n") % f) |
211 continue |
214 continue |
212 if f[0] == "/": |
215 if f[0] == "/": |
213 continue |
216 continue |
214 if f in ma and n != ma[f]: |
217 if f in ma and n != ma[f]: |
215 r = _("k") |
218 r = _("k") |
216 if not force and (linear_path or branchmerge): |
219 if not overwrite and (linear_path or branchmerge): |
217 r = repo.ui.prompt( |
220 r = repo.ui.prompt( |
218 (_("remote changed %s which local deleted\n") % f) + |
221 (_("remote changed %s which local deleted\n") % f) + |
219 _("(k)eep or (d)elete?"), _("[kd]"), _("k")) |
222 _("(k)eep or (d)elete?"), _("[kd]"), _("k")) |
220 if r == _("k"): |
223 if r == _("k"): |
221 get[f] = n |
224 get[f] = n |
222 elif f not in ma: |
225 elif f not in ma: |
223 repo.ui.debug(_("remote created %s\n") % f) |
226 repo.ui.debug(_("remote created %s\n") % f) |
224 get[f] = n |
227 get[f] = n |
225 else: |
228 else: |
226 if force or p2 == pa: # going backwards? |
229 if overwrite or p2 == pa: # going backwards? |
227 repo.ui.debug(_("local deleted %s, recreating\n") % f) |
230 repo.ui.debug(_("local deleted %s, recreating\n") % f) |
228 get[f] = n |
231 get[f] = n |
229 else: |
232 else: |
230 repo.ui.debug(_("local deleted %s\n") % f) |
233 repo.ui.debug(_("local deleted %s\n") % f) |
231 |
234 |
232 del mw, m1, m2, ma |
235 del mw, m1, m2, ma |
233 |
236 |
234 if force: |
237 if overwrite: |
235 for f in merge: |
238 for f in merge: |
236 get[f] = merge[f][1] |
239 get[f] = merge[f][1] |
237 merge = {} |
240 merge = {} |
238 |
241 |
239 if linear_path or force: |
242 if linear_path or overwrite: |
240 # we don't need to do any magic, just jump to the new rev |
243 # we don't need to do any magic, just jump to the new rev |
241 p1, p2 = p2, nullid |
244 p1, p2 = p2, nullid |
242 |
245 |
243 xp1 = hex(p1) |
246 xp1 = hex(p1) |
244 xp2 = hex(p2) |
247 xp2 = hex(p2) |