Show More
@@ -23,6 +23,7 b' from mercurial.i18n import _' | |||||
23 | from mercurial.node import bin, hex, nullid |
|
23 | from mercurial.node import bin, hex, nullid | |
24 | from mercurial import hg, util, context, bookmarks, error, scmutil, exchange |
|
24 | from mercurial import hg, util, context, bookmarks, error, scmutil, exchange | |
25 | from mercurial import phases |
|
25 | from mercurial import phases | |
|
26 | from mercurial import merge as mergemod | |||
26 |
|
27 | |||
27 | from common import NoRepo, commit, converter_source, converter_sink, mapfile |
|
28 | from common import NoRepo, commit, converter_source, converter_sink, mapfile | |
28 |
|
29 | |||
@@ -176,12 +177,51 b' class mercurial_sink(converter_sink):' | |||||
176 |
|
177 | |||
177 | return fp.getvalue() |
|
178 | return fp.getvalue() | |
178 |
|
179 | |||
|
180 | def _calculatemergedfiles(self, source, p1ctx, p2ctx): | |||
|
181 | """Calculates the files from p2 that we need to pull in when merging p1 | |||
|
182 | and p2, given that the merge is coming from the given source. | |||
|
183 | ||||
|
184 | This prevents us from losing files that only exist in the target p2 and | |||
|
185 | that don't come from the source repo (like if you're merging multiple | |||
|
186 | repositories together). | |||
|
187 | """ | |||
|
188 | anc = [p1ctx.ancestor(p2ctx)] | |||
|
189 | # Calculate what files are coming from p2 | |||
|
190 | actions, diverge, rename = mergemod.calculateupdates( | |||
|
191 | self.repo, p1ctx, p2ctx, anc, | |||
|
192 | True, # branchmerge | |||
|
193 | True, # force | |||
|
194 | False, # partial | |||
|
195 | False, # acceptremote | |||
|
196 | False, # followcopies | |||
|
197 | ) | |||
|
198 | ||||
|
199 | for file, (action, info, msg) in actions.iteritems(): | |||
|
200 | if source.targetfilebelongstosource(file): | |||
|
201 | # If the file belongs to the source repo, ignore the p2 | |||
|
202 | # since it will be covered by the existing fileset. | |||
|
203 | continue | |||
|
204 | ||||
|
205 | # If the file requires actual merging, abort. We don't have enough | |||
|
206 | # context to resolve merges correctly. | |||
|
207 | if action in ['m', 'dm', 'cd', 'dc']: | |||
|
208 | raise util.Abort(_("unable to convert merge commit " | |||
|
209 | "since target parents do not merge cleanly (file " | |||
|
210 | "%s, parents %s and %s)") % (file, p1ctx, | |||
|
211 | p2ctx)) | |||
|
212 | elif action == 'k': | |||
|
213 | # 'keep' means nothing changed from p1 | |||
|
214 | continue | |||
|
215 | else: | |||
|
216 | # Any other change means we want to take the p2 version | |||
|
217 | yield file | |||
|
218 | ||||
179 | def putcommit(self, files, copies, parents, commit, source, revmap, full, |
|
219 | def putcommit(self, files, copies, parents, commit, source, revmap, full, | |
180 | cleanp2): |
|
220 | cleanp2): | |
181 | files = dict(files) |
|
221 | files = dict(files) | |
182 |
|
222 | |||
183 | def getfilectx(repo, memctx, f): |
|
223 | def getfilectx(repo, memctx, f): | |
184 |
if p2ctx and f in |
|
224 | if p2ctx and f in p2files and f not in copies: | |
185 | self.ui.debug('reusing %s from p2\n' % f) |
|
225 | self.ui.debug('reusing %s from p2\n' % f) | |
186 | return p2ctx[f] |
|
226 | return p2ctx[f] | |
187 | try: |
|
227 | try: | |
@@ -255,6 +295,7 b' class mercurial_sink(converter_sink):' | |||||
255 | while parents: |
|
295 | while parents: | |
256 | p1 = p2 |
|
296 | p1 = p2 | |
257 | p2 = parents.pop(0) |
|
297 | p2 = parents.pop(0) | |
|
298 | p1ctx = self.repo[p1] | |||
258 | p2ctx = None |
|
299 | p2ctx = None | |
259 | if p2 != nullid: |
|
300 | if p2 != nullid: | |
260 | p2ctx = self.repo[p2] |
|
301 | p2ctx = self.repo[p2] | |
@@ -262,6 +303,13 b' class mercurial_sink(converter_sink):' | |||||
262 | if full: |
|
303 | if full: | |
263 | fileset.update(self.repo[p1]) |
|
304 | fileset.update(self.repo[p1]) | |
264 | fileset.update(self.repo[p2]) |
|
305 | fileset.update(self.repo[p2]) | |
|
306 | ||||
|
307 | if p2ctx: | |||
|
308 | p2files = set(cleanp2) | |||
|
309 | for file in self._calculatemergedfiles(source, p1ctx, p2ctx): | |||
|
310 | p2files.add(file) | |||
|
311 | fileset.add(file) | |||
|
312 | ||||
265 | ctx = context.memctx(self.repo, (p1, p2), text, fileset, |
|
313 | ctx = context.memctx(self.repo, (p1, p2), text, fileset, | |
266 | getfilectx, commit.author, commit.date, extra) |
|
314 | getfilectx, commit.author, commit.date, extra) | |
267 |
|
315 |
@@ -671,3 +671,61 b' test named branch pruning' | |||||
671 | |/ |
|
671 | |/ | |
672 | o 0:c334dc3be0da@default "add" files: a |
|
672 | o 0:c334dc3be0da@default "add" files: a | |
673 |
|
673 | |||
|
674 | $ cd .. | |||
|
675 | ||||
|
676 | test converting merges into a repo that contains other files | |||
|
677 | ||||
|
678 | $ hg init merge-test1 | |||
|
679 | $ cd merge-test1 | |||
|
680 | $ touch a && hg commit -Aqm a | |||
|
681 | $ hg up -q null | |||
|
682 | $ touch b && hg commit -Aqm b | |||
|
683 | $ hg merge -q 0 && hg commit -qm merge | |||
|
684 | $ cd .. | |||
|
685 | $ hg init merge-test2 | |||
|
686 | $ cd merge-test2 | |||
|
687 | $ mkdir converted | |||
|
688 | $ touch converted/a && hg commit -Aqm 'a' | |||
|
689 | $ touch x && hg commit -Aqm 'x' | |||
|
690 | $ cd .. | |||
|
691 | $ hg log -G -T '{node}' -R merge-test1 | |||
|
692 | @ ea7c1a7ae9588677a715ce4f204cd89c28d5471f | |||
|
693 | |\ | |||
|
694 | | o d7486e00c6f1b633dcadc0582f78006d805c7a0f | |||
|
695 | | | |||
|
696 | o 3903775176ed42b1458a6281db4a0ccf4d9f287a | |||
|
697 | ||||
|
698 | $ hg log -G -T '{node}' -R merge-test2 | |||
|
699 | @ 34f1aa7da42559bae87920880b522d47b3ddbc0d | |||
|
700 | | | |||
|
701 | o e01a12b07b4fdfd61ff90a2a1b4560a7a776f323 | |||
|
702 | ||||
|
703 | - Build a shamap where the target converted/a is in on top of an unrelated | |||
|
704 | - change to 'x'. This simulates using convert to merge several repositories | |||
|
705 | - together. | |||
|
706 | $ cat >> merge-test2/.hg/shamap <<EOF | |||
|
707 | > 3903775176ed42b1458a6281db4a0ccf4d9f287a 34f1aa7da42559bae87920880b522d47b3ddbc0d | |||
|
708 | > EOF | |||
|
709 | $ cat >> merge-test-filemap <<EOF | |||
|
710 | > rename . converted/ | |||
|
711 | > EOF | |||
|
712 | $ hg convert --filemap merge-test-filemap merge-test1 merge-test2 --traceback | |||
|
713 | scanning source... | |||
|
714 | sorting... | |||
|
715 | converting... | |||
|
716 | 1 b | |||
|
717 | 0 merge | |||
|
718 | $ hg -R merge-test2 manifest -r tip | |||
|
719 | converted/a | |||
|
720 | converted/b | |||
|
721 | x | |||
|
722 | $ hg -R merge-test2 log -G -T '{node}\n{files % "{file}\n"}' | |||
|
723 | o 4b5e2f0218d3442a0c14892b18685bf9c8059c4a | |||
|
724 | |\ | |||
|
725 | | o 214325dd2e4cff981dcf00cb120cd39e1ea36dcc | |||
|
726 | | converted/b | |||
|
727 | @ 34f1aa7da42559bae87920880b522d47b3ddbc0d | |||
|
728 | | x | |||
|
729 | o e01a12b07b4fdfd61ff90a2a1b4560a7a776f323 | |||
|
730 | converted/a | |||
|
731 |
General Comments 0
You need to be logged in to leave comments.
Login now