##// END OF EJS Templates
convert: fix convert dropping p2 contents during filemap merge...
Durham Goode -
r26037:a75d2453 default
parent child Browse files
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 cleanp2 and f not in copies:
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