Show More
@@ -23,6 +23,7 b' from mercurial.i18n import _' | |||
|
23 | 23 | from mercurial.node import bin, hex, nullid |
|
24 | 24 | from mercurial import hg, util, context, bookmarks, error, scmutil, exchange |
|
25 | 25 | from mercurial import phases |
|
26 | from mercurial import merge as mergemod | |
|
26 | 27 | |
|
27 | 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 | 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 | 219 | def putcommit(self, files, copies, parents, commit, source, revmap, full, |
|
180 | 220 | cleanp2): |
|
181 | 221 | files = dict(files) |
|
182 | 222 | |
|
183 | 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 | 225 | self.ui.debug('reusing %s from p2\n' % f) |
|
186 | 226 | return p2ctx[f] |
|
187 | 227 | try: |
@@ -255,6 +295,7 b' class mercurial_sink(converter_sink):' | |||
|
255 | 295 | while parents: |
|
256 | 296 | p1 = p2 |
|
257 | 297 | p2 = parents.pop(0) |
|
298 | p1ctx = self.repo[p1] | |
|
258 | 299 | p2ctx = None |
|
259 | 300 | if p2 != nullid: |
|
260 | 301 | p2ctx = self.repo[p2] |
@@ -262,6 +303,13 b' class mercurial_sink(converter_sink):' | |||
|
262 | 303 | if full: |
|
263 | 304 | fileset.update(self.repo[p1]) |
|
264 | 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 | 313 | ctx = context.memctx(self.repo, (p1, p2), text, fileset, |
|
266 | 314 | getfilectx, commit.author, commit.date, extra) |
|
267 | 315 |
@@ -671,3 +671,61 b' test named branch pruning' | |||
|
671 | 671 | |/ |
|
672 | 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