149 abortconflicts.update(conflicts) |
149 abortconflicts.update(conflicts) |
150 elif config == b'warn': |
150 elif config == b'warn': |
151 warnconflicts.update(conflicts) |
151 warnconflicts.update(conflicts) |
152 |
152 |
153 checkunknowndirs = _unknowndirschecker() |
153 checkunknowndirs = _unknowndirschecker() |
154 for f, (m, args, msg) in pycompat.iteritems(mresult.actions): |
154 for f, args, msg in mresult.getactions( |
155 if m in ( |
155 [ |
156 mergestatemod.ACTION_CREATED, |
156 mergestatemod.ACTION_CREATED, |
157 mergestatemod.ACTION_DELETED_CHANGED, |
157 mergestatemod.ACTION_DELETED_CHANGED, |
158 ): |
158 ] |
159 if _checkunknownfile(repo, wctx, mctx, f): |
159 ): |
160 fileconflicts.add(f) |
160 if _checkunknownfile(repo, wctx, mctx, f): |
161 elif pathconfig and f not in wctx: |
161 fileconflicts.add(f) |
162 path = checkunknowndirs(repo, wctx, f) |
162 elif pathconfig and f not in wctx: |
163 if path is not None: |
163 path = checkunknowndirs(repo, wctx, f) |
164 pathconflicts.add(path) |
164 if path is not None: |
165 elif m == mergestatemod.ACTION_LOCAL_DIR_RENAME_GET: |
165 pathconflicts.add(path) |
166 if _checkunknownfile(repo, wctx, mctx, f, args[0]): |
166 for f, args, msg in mresult.getactions( |
167 fileconflicts.add(f) |
167 [mergestatemod.ACTION_LOCAL_DIR_RENAME_GET] |
|
168 ): |
|
169 if _checkunknownfile(repo, wctx, mctx, f, args[0]): |
|
170 fileconflicts.add(f) |
168 |
171 |
169 allconflicts = fileconflicts | pathconflicts |
172 allconflicts = fileconflicts | pathconflicts |
170 ignoredconflicts = {c for c in allconflicts if repo.dirstate._ignore(c)} |
173 ignoredconflicts = {c for c in allconflicts if repo.dirstate._ignore(c)} |
171 unknownconflicts = allconflicts - ignoredconflicts |
174 unknownconflicts = allconflicts - ignoredconflicts |
172 collectconflicts(ignoredconflicts, ignoredconfig) |
175 collectconflicts(ignoredconflicts, ignoredconfig) |
173 collectconflicts(unknownconflicts, unknownconfig) |
176 collectconflicts(unknownconflicts, unknownconfig) |
174 else: |
177 else: |
175 for f, (m, args, msg) in pycompat.iteritems(mresult.actions): |
178 for f, args, msg in mresult.getactions( |
176 if m == mergestatemod.ACTION_CREATED_MERGE: |
179 [mergestatemod.ACTION_CREATED_MERGE] |
177 fl2, anc = args |
180 ): |
178 different = _checkunknownfile(repo, wctx, mctx, f) |
181 fl2, anc = args |
179 if repo.dirstate._ignore(f): |
182 different = _checkunknownfile(repo, wctx, mctx, f) |
180 config = ignoredconfig |
183 if repo.dirstate._ignore(f): |
181 else: |
184 config = ignoredconfig |
182 config = unknownconfig |
185 else: |
183 |
186 config = unknownconfig |
184 # The behavior when force is True is described by this table: |
187 |
185 # config different mergeforce | action backup |
188 # The behavior when force is True is described by this table: |
186 # * n * | get n |
189 # config different mergeforce | action backup |
187 # * y y | merge - |
190 # * n * | get n |
188 # abort y n | merge - (1) |
191 # * y y | merge - |
189 # warn y n | warn + get y |
192 # abort y n | merge - (1) |
190 # ignore y n | get y |
193 # warn y n | warn + get y |
191 # |
194 # ignore y n | get y |
192 # (1) this is probably the wrong behavior here -- we should |
195 # |
193 # probably abort, but some actions like rebases currently |
196 # (1) this is probably the wrong behavior here -- we should |
194 # don't like an abort happening in the middle of |
197 # probably abort, but some actions like rebases currently |
195 # merge.update. |
198 # don't like an abort happening in the middle of |
196 if not different: |
199 # merge.update. |
197 mresult.addfile( |
200 if not different: |
198 f, |
201 mresult.addfile( |
199 mergestatemod.ACTION_GET, |
202 f, |
200 (fl2, False), |
203 mergestatemod.ACTION_GET, |
201 b'remote created', |
204 (fl2, False), |
202 ) |
205 b'remote created', |
203 elif mergeforce or config == b'abort': |
206 ) |
204 mresult.addfile( |
207 elif mergeforce or config == b'abort': |
205 f, |
208 mresult.addfile( |
206 mergestatemod.ACTION_MERGE, |
209 f, |
207 (f, f, None, False, anc), |
210 mergestatemod.ACTION_MERGE, |
208 b'remote differs from untracked local', |
211 (f, f, None, False, anc), |
209 ) |
212 b'remote differs from untracked local', |
210 elif config == b'abort': |
213 ) |
211 abortconflicts.add(f) |
214 elif config == b'abort': |
212 else: |
215 abortconflicts.add(f) |
213 if config == b'warn': |
216 else: |
214 warnconflicts.add(f) |
217 if config == b'warn': |
215 mresult.addfile( |
218 warnconflicts.add(f) |
216 f, |
219 mresult.addfile( |
217 mergestatemod.ACTION_GET, |
220 f, mergestatemod.ACTION_GET, (fl2, True), b'remote created', |
218 (fl2, True), |
221 ) |
219 b'remote created', |
|
220 ) |
|
221 |
222 |
222 for f in sorted(abortconflicts): |
223 for f in sorted(abortconflicts): |
223 warn = repo.ui.warn |
224 warn = repo.ui.warn |
224 if f in pathconflicts: |
225 if f in pathconflicts: |
225 if repo.wvfs.isfileorlink(f): |
226 if repo.wvfs.isfileorlink(f): |
240 if repo.wvfs.isfileorlink(f): |
241 if repo.wvfs.isfileorlink(f): |
241 repo.ui.warn(_(b"%s: replacing untracked file\n") % f) |
242 repo.ui.warn(_(b"%s: replacing untracked file\n") % f) |
242 else: |
243 else: |
243 repo.ui.warn(_(b"%s: replacing untracked files in directory\n") % f) |
244 repo.ui.warn(_(b"%s: replacing untracked files in directory\n") % f) |
244 |
245 |
245 for f, (m, args, msg) in pycompat.iteritems(mresult.actions): |
246 for f, args, msg in mresult.getactions([mergestatemod.ACTION_CREATED]): |
246 if m == mergestatemod.ACTION_CREATED: |
247 backup = ( |
247 backup = ( |
248 f in fileconflicts |
248 f in fileconflicts |
249 or f in pathconflicts |
249 or f in pathconflicts |
250 or any(p in pathconflicts for p in pathutil.finddirs(f)) |
250 or any(p in pathconflicts for p in pathutil.finddirs(f)) |
251 ) |
251 ) |
252 (flags,) = args |
252 (flags,) = args |
253 mresult.addfile(f, mergestatemod.ACTION_GET, (flags, backup), msg) |
253 mresult.addfile(f, mergestatemod.ACTION_GET, (flags, backup), msg) |
|
254 |
254 |
255 |
255 |
256 def _forgetremoved(wctx, mctx, branchmerge): |
256 def _forgetremoved(wctx, mctx, branchmerge): |
257 """ |
257 """ |
258 Forget removed files |
258 Forget removed files |
648 self.addfile(f, a, data, msg) |
648 self.addfile(f, a, data, msg) |
649 |
649 |
650 def hasconflicts(self): |
650 def hasconflicts(self): |
651 """ tells whether this merge resulted in some actions which can |
651 """ tells whether this merge resulted in some actions which can |
652 result in conflicts or not """ |
652 result in conflicts or not """ |
653 for _f, (m, _unused, _unused) in pycompat.iteritems(self._filemapping): |
653 for a in self._actionmapping.keys(): |
654 if m not in ( |
654 if ( |
655 mergestatemod.ACTION_GET, |
655 a |
656 mergestatemod.ACTION_KEEP, |
656 not in ( |
657 mergestatemod.ACTION_EXEC, |
657 mergestatemod.ACTION_GET, |
658 mergestatemod.ACTION_REMOVE, |
658 mergestatemod.ACTION_KEEP, |
659 mergestatemod.ACTION_PATH_CONFLICT_RESOLVE, |
659 mergestatemod.ACTION_EXEC, |
|
660 mergestatemod.ACTION_REMOVE, |
|
661 mergestatemod.ACTION_PATH_CONFLICT_RESOLVE, |
|
662 ) |
|
663 and self._actionmapping[a] |
660 ): |
664 ): |
661 return True |
665 return True |
662 |
666 |
663 return False |
667 return False |
664 |
668 |
990 def _resolvetrivial(repo, wctx, mctx, ancestor, mresult): |
994 def _resolvetrivial(repo, wctx, mctx, ancestor, mresult): |
991 """Resolves false conflicts where the nodeid changed but the content |
995 """Resolves false conflicts where the nodeid changed but the content |
992 remained the same.""" |
996 remained the same.""" |
993 # We force a copy of actions.items() because we're going to mutate |
997 # We force a copy of actions.items() because we're going to mutate |
994 # actions as we resolve trivial conflicts. |
998 # actions as we resolve trivial conflicts. |
995 for f, (m, args, msg) in list(mresult.actions.items()): |
999 for f, args, msg in mresult.getactions( |
996 if ( |
1000 [mergestatemod.ACTION_CHANGED_DELETED] |
997 m == mergestatemod.ACTION_CHANGED_DELETED |
1001 ): |
998 and f in ancestor |
1002 if f in ancestor and not wctx[f].cmp(ancestor[f]): |
999 and not wctx[f].cmp(ancestor[f]) |
|
1000 ): |
|
1001 # local did change but ended up with same content |
1003 # local did change but ended up with same content |
1002 mresult.addfile( |
1004 mresult.addfile( |
1003 f, mergestatemod.ACTION_REMOVE, None, b'prompt same' |
1005 f, mergestatemod.ACTION_REMOVE, None, b'prompt same' |
1004 ) |
1006 ) |
1005 elif ( |
1007 |
1006 m == mergestatemod.ACTION_DELETED_CHANGED |
1008 for f, args, msg in list( |
1007 and f in ancestor |
1009 mresult.getactions([mergestatemod.ACTION_DELETED_CHANGED]) |
1008 and not mctx[f].cmp(ancestor[f]) |
1010 ): |
1009 ): |
1011 if f in ancestor and not mctx[f].cmp(ancestor[f]): |
1010 # remote did change but ended up with same content |
1012 # remote did change but ended up with same content |
1011 mresult.removefile(f) # don't get = keep local deleted |
1013 mresult.removefile(f) # don't get = keep local deleted |
1012 |
1014 |
1013 |
1015 |
1014 def calculateupdates( |
1016 def calculateupdates( |