89 raise util.Abort(_("outstanding uncommitted changes")) |
89 raise util.Abort(_("outstanding uncommitted changes")) |
90 |
90 |
91 m1n = repo.changelog.read(p1)[0] |
91 m1n = repo.changelog.read(p1)[0] |
92 m2n = repo.changelog.read(p2)[0] |
92 m2n = repo.changelog.read(p2)[0] |
93 man = repo.manifest.ancestor(m1n, m2n) |
93 man = repo.manifest.ancestor(m1n, m2n) |
94 m1 = repo.manifest.read(m1n) |
94 m1 = repo.manifest.read(m1n).copy() |
95 m2 = repo.manifest.read(m2n).copy() |
95 m2 = repo.manifest.read(m2n).copy() |
96 ma = repo.manifest.read(man) |
96 ma = repo.manifest.read(man) |
97 |
97 |
98 if not force: |
98 if not force: |
99 for f in unknown: |
99 for f in unknown: |
113 merge = {} |
113 merge = {} |
114 get = {} |
114 get = {} |
115 remove = [] |
115 remove = [] |
116 forget = [] |
116 forget = [] |
117 |
117 |
118 # construct a working dir manifest |
118 # update m1 from working dir |
119 mw = m1.copy() |
|
120 umap = dict.fromkeys(unknown) |
119 umap = dict.fromkeys(unknown) |
121 |
120 |
122 for f in added + modified + unknown: |
121 for f in added + modified + unknown: |
123 mw[f] = nullid + "+" |
122 m1[f] = m1.get(f, nullid) + "+" |
124 mw.set(f, util.is_exec(repo.wjoin(f), mw.execf(f))) |
123 m1.set(f, util.is_exec(repo.wjoin(f), m1.execf(f))) |
|
124 |
|
125 for f in deleted + removed: |
125 if f in m1: |
126 if f in m1: |
126 mw[f] = m1[f] + "+" |
127 del m1[f] |
127 |
|
128 for f in deleted + removed: |
|
129 if f in mw: |
|
130 del mw[f] |
|
131 |
128 |
132 # If we're jumping between revisions (as opposed to merging), |
129 # If we're jumping between revisions (as opposed to merging), |
133 # and if neither the working directory nor the target rev has |
130 # and if neither the working directory nor the target rev has |
134 # the file, then we need to remove it from the dirstate, to |
131 # the file, then we need to remove it from the dirstate, to |
135 # prevent the dirstate from listing the file when it is no |
132 # prevent the dirstate from listing the file when it is no |
136 # longer in the manifest. |
133 # longer in the manifest. |
137 if linear_path and f not in m2: |
134 if linear_path and f not in m2: |
138 forget.append(f) |
135 forget.append(f) |
139 |
136 |
140 if partial: |
137 if partial: |
141 for f in mw.keys(): |
138 for f in m1.keys(): |
142 if not partial(f): del mw[f] |
139 if not partial(f): del m1[f] |
143 for f in m2.keys(): |
140 for f in m2.keys(): |
144 if not partial(f): del m2[f] |
141 if not partial(f): del m2[f] |
145 |
142 |
146 # Compare manifests |
143 # Compare manifests |
147 for f, n in mw.iteritems(): |
144 for f, n in m1.iteritems(): |
148 if f in m2: |
145 if f in m2: |
149 queued = 0 |
146 queued = 0 |
150 |
147 |
151 # are files different? |
148 # are files different? |
152 if n != m2[f]: |
149 if n != m2[f]: |
153 a = ma.get(f, nullid) |
150 a = ma.get(f, nullid) |
154 # are both different from the ancestor? |
151 # are both different from the ancestor? |
155 if not overwrite and n != a and m2[f] != a: |
152 if not overwrite and n != a and m2[f] != a: |
156 repo.ui.debug(_(" %s versions differ, resolve\n") % f) |
153 repo.ui.debug(_(" %s versions differ, resolve\n") % f) |
157 merge[f] = (fmerge(f, mw, m2, ma), n[:20], m2[f]) |
154 merge[f] = (fmerge(f, m1, m2, ma), n[:20], m2[f]) |
158 queued = 1 |
155 queued = 1 |
159 # are we clobbering? |
156 # are we clobbering? |
160 # is remote's version newer? |
157 # is remote's version newer? |
161 # or are we going back in time and clean? |
158 # or are we going back in time and clean? |
162 elif overwrite or m2[f] != a or (backwards and not n[20:]): |
159 elif overwrite or m2[f] != a or (backwards and not n[20:]): |
167 # this unknown file is the same as the checkout |
164 # this unknown file is the same as the checkout |
168 # we need to reset the dirstate if the file was added |
165 # we need to reset the dirstate if the file was added |
169 get[f] = (m2.execf(f), m2[f]) |
166 get[f] = (m2.execf(f), m2[f]) |
170 |
167 |
171 # do we still need to look at mode bits? |
168 # do we still need to look at mode bits? |
172 if not queued and mw.execf(f) != m2.execf(f): |
169 if not queued and m1.execf(f) != m2.execf(f): |
173 if overwrite: |
170 if overwrite: |
174 repo.ui.debug(_(" updating permissions for %s\n") % f) |
171 repo.ui.debug(_(" updating permissions for %s\n") % f) |
175 util.set_exec(repo.wjoin(f), m2.execf(f)) |
172 util.set_exec(repo.wjoin(f), m2.execf(f)) |
176 else: |
173 else: |
177 if fmerge(f, mw, m2, ma) != mw.execf(f): |
174 if fmerge(f, m1, m2, ma) != m1.execf(f): |
178 repo.ui.debug(_(" updating permissions for %s\n") |
175 repo.ui.debug(_(" updating permissions for %s\n") |
179 % f) |
176 % f) |
180 util.set_exec(repo.wjoin(f), mode) |
177 util.set_exec(repo.wjoin(f), mode) |
181 del m2[f] |
178 del m2[f] |
182 elif f in ma: |
179 elif f in ma: |
224 repo.ui.debug(_("local deleted %s, recreating\n") % f) |
221 repo.ui.debug(_("local deleted %s, recreating\n") % f) |
225 get[f] = (m2.execf(f), n) |
222 get[f] = (m2.execf(f), n) |
226 else: |
223 else: |
227 repo.ui.debug(_("local deleted %s\n") % f) |
224 repo.ui.debug(_("local deleted %s\n") % f) |
228 |
225 |
229 del mw, m1, m2, ma |
226 del m1, m2, ma |
230 |
227 |
231 ### apply phase |
228 ### apply phase |
232 |
229 |
233 if linear_path or overwrite: |
230 if linear_path or overwrite: |
234 # we don't need to do any magic, just jump to the new rev |
231 # we don't need to do any magic, just jump to the new rev |