##// END OF EJS Templates
py3: work around comparison between int and None in tagmerge
Yuya Nishihara -
r36752:b77ff4fb default
parent child Browse files
Show More
@@ -1,390 +1,391
1 1 test-abort-checkin.t
2 2 test-add.t
3 3 test-addremove-similar.t
4 4 test-addremove.t
5 5 test-amend-subrepo.t
6 6 test-ancestor.py
7 7 test-annotate.py
8 8 test-annotate.t
9 9 test-archive-symlinks.t
10 10 test-atomictempfile.py
11 11 test-audit-path.t
12 12 test-audit-subrepo.t
13 13 test-automv.t
14 14 test-backout.t
15 15 test-backwards-remove.t
16 16 test-basic.t
17 17 test-bheads.t
18 18 test-bisect2.t
19 19 test-bookmarks-current.t
20 20 test-bookmarks-merge.t
21 21 test-bookmarks-rebase.t
22 22 test-bookmarks-strip.t
23 23 test-bookmarks.t
24 24 test-branch-option.t
25 25 test-branch-tag-confict.t
26 26 test-branches.t
27 27 test-bundle-phases.t
28 28 test-bundle-type.t
29 29 test-bundle-vs-outgoing.t
30 30 test-bundle2-multiple-changegroups.t
31 31 test-cappedreader.py
32 32 test-casecollision.t
33 33 test-cat.t
34 34 test-censor.t
35 35 test-changelog-exec.t
36 36 test-check-commit.t
37 37 test-check-execute.t
38 38 test-check-module-imports.t
39 39 test-check-pyflakes.t
40 40 test-check-pylint.t
41 41 test-check-shbang.t
42 42 test-children.t
43 43 test-clone-pull-corruption.t
44 44 test-clone-r.t
45 45 test-clone-update-order.t
46 46 test-command-template.t
47 47 test-commit-amend.t
48 48 test-commit-unresolved.t
49 49 test-commit.t
50 50 test-completion.t
51 51 test-config-env.py
52 52 test-config.t
53 53 test-conflict.t
54 54 test-confused-revert.t
55 55 test-contrib-check-code.t
56 56 test-contrib-check-commit.t
57 57 test-convert-authormap.t
58 58 test-convert-clonebranches.t
59 59 test-convert-datesort.t
60 60 test-convert-filemap.t
61 61 test-convert-hg-sink.t
62 62 test-convert-hg-source.t
63 63 test-convert-hg-startrev.t
64 64 test-copy-move-merge.t
65 65 test-copy.t
66 66 test-copytrace-heuristics.t
67 67 test-debugbuilddag.t
68 68 test-debugbundle.t
69 69 test-debugextensions.t
70 70 test-debugindexdot.t
71 71 test-debugrename.t
72 72 test-default-push.t
73 73 test-diff-binary-file.t
74 74 test-diff-change.t
75 75 test-diff-copy-depth.t
76 76 test-diff-hashes.t
77 77 test-diff-issue2761.t
78 78 test-diff-newlines.t
79 79 test-diff-reverse.t
80 80 test-diff-subdir.t
81 81 test-diffdir.t
82 82 test-directaccess.t
83 83 test-dirstate-backup.t
84 84 test-dirstate-nonnormalset.t
85 85 test-doctest.py
86 86 test-double-merge.t
87 87 test-drawdag.t
88 88 test-duplicateoptions.py
89 89 test-empty-dir.t
90 90 test-empty-file.t
91 91 test-empty-group.t
92 92 test-empty.t
93 93 test-encode.t
94 94 test-encoding-func.py
95 95 test-encoding.t
96 96 test-eol-add.t
97 97 test-eol-clone.t
98 98 test-eol-hook.t
99 99 test-eol-tag.t
100 100 test-eol-update.t
101 101 test-excessive-merge.t
102 102 test-exchange-obsmarkers-case-A1.t
103 103 test-exchange-obsmarkers-case-A2.t
104 104 test-exchange-obsmarkers-case-A3.t
105 105 test-exchange-obsmarkers-case-A4.t
106 106 test-exchange-obsmarkers-case-A5.t
107 107 test-exchange-obsmarkers-case-A6.t
108 108 test-exchange-obsmarkers-case-A7.t
109 109 test-exchange-obsmarkers-case-B1.t
110 110 test-exchange-obsmarkers-case-B2.t
111 111 test-exchange-obsmarkers-case-B3.t
112 112 test-exchange-obsmarkers-case-B4.t
113 113 test-exchange-obsmarkers-case-B5.t
114 114 test-exchange-obsmarkers-case-B6.t
115 115 test-exchange-obsmarkers-case-B7.t
116 116 test-exchange-obsmarkers-case-C1.t
117 117 test-exchange-obsmarkers-case-C2.t
118 118 test-exchange-obsmarkers-case-C3.t
119 119 test-exchange-obsmarkers-case-C4.t
120 120 test-exchange-obsmarkers-case-D1.t
121 121 test-exchange-obsmarkers-case-D2.t
122 122 test-exchange-obsmarkers-case-D3.t
123 123 test-exchange-obsmarkers-case-D4.t
124 124 test-execute-bit.t
125 125 test-extdiff.t
126 126 test-extra-filelog-entry.t
127 127 test-filebranch.t
128 128 test-fileset-generated.t
129 129 test-flags.t
130 130 test-generaldelta.t
131 131 test-getbundle.t
132 132 test-git-export.t
133 133 test-glog-topological.t
134 134 test-gpg.t
135 135 test-graft.t
136 136 test-hghave.t
137 137 test-hgignore.t
138 138 test-hgk.t
139 139 test-hgweb-bundle.t
140 140 test-hgweb-descend-empties.t
141 141 test-hgweb-removed.t
142 142 test-histedit-arguments.t
143 143 test-histedit-base.t
144 144 test-histedit-bookmark-motion.t
145 145 test-histedit-commute.t
146 146 test-histedit-drop.t
147 147 test-histedit-edit.t
148 148 test-histedit-fold-non-commute.t
149 149 test-histedit-fold.t
150 150 test-histedit-no-change.t
151 151 test-histedit-non-commute-abort.t
152 152 test-histedit-non-commute.t
153 153 test-histedit-obsolete.t
154 154 test-histedit-outgoing.t
155 155 test-histedit-templates.t
156 156 test-http-branchmap.t
157 157 test-http-bundle1.t
158 158 test-http-clone-r.t
159 159 test-identify.t
160 160 test-import-unknown.t
161 161 test-imports-checker.t
162 162 test-inherit-mode.t
163 163 test-issue1089.t
164 164 test-issue1102.t
165 165 test-issue1175.t
166 166 test-issue1306.t
167 167 test-issue1438.t
168 168 test-issue1502.t
169 169 test-issue1802.t
170 170 test-issue1877.t
171 171 test-issue1993.t
172 172 test-issue2137.t
173 173 test-issue3084.t
174 174 test-issue4074.t
175 175 test-issue522.t
176 176 test-issue586.t
177 177 test-issue612.t
178 178 test-issue619.t
179 179 test-issue672.t
180 180 test-issue842.t
181 181 test-journal-exists.t
182 182 test-largefiles-cache.t
183 183 test-largefiles-misc.t
184 184 test-largefiles-small-disk.t
185 185 test-locate.t
186 186 test-lock-badness.t
187 187 test-log.t
188 188 test-logexchange.t
189 189 test-lrucachedict.py
190 190 test-mactext.t
191 191 test-manifest-merging.t
192 192 test-manifest.py
193 193 test-manifest.t
194 194 test-match.py
195 195 test-mdiff.py
196 196 test-merge-closedheads.t
197 197 test-merge-commit.t
198 198 test-merge-criss-cross.t
199 199 test-merge-default.t
200 200 test-merge-internal-tools-pattern.t
201 201 test-merge-local.t
202 202 test-merge-remove.t
203 203 test-merge-revert.t
204 204 test-merge-revert2.t
205 205 test-merge-subrepos.t
206 206 test-merge-symlinks.t
207 207 test-merge-types.t
208 208 test-merge1.t
209 209 test-merge10.t
210 210 test-merge2.t
211 211 test-merge4.t
212 212 test-merge5.t
213 213 test-merge6.t
214 214 test-merge7.t
215 215 test-merge8.t
216 216 test-merge9.t
217 217 test-mq-git.t
218 218 test-mq-header-date.t
219 219 test-mq-header-from.t
220 220 test-mq-pull-from-bundle.t
221 221 test-mq-qdiff.t
222 222 test-mq-qfold.t
223 223 test-mq-qgoto.t
224 224 test-mq-qimport-fail-cleanup.t
225 225 test-mq-qpush-exact.t
226 226 test-mq-qqueue.t
227 227 test-mq-qrefresh-replace-log-message.t
228 228 test-mq-qrefresh.t
229 229 test-mq-qrename.t
230 230 test-mq-qsave.t
231 231 test-mq-safety.t
232 232 test-mq-symlinks.t
233 233 test-mv-cp-st-diff.t
234 234 test-narrow-archive.t
235 235 test-narrow-clone-no-ellipsis.t
236 236 test-narrow-clone-nonlinear.t
237 237 test-narrow-clone.t
238 238 test-narrow-commit.t
239 239 test-narrow-copies.t
240 240 test-narrow-debugcommands.t
241 241 test-narrow-debugrebuilddirstate.t
242 242 test-narrow-exchange-merges.t
243 243 test-narrow-exchange.t
244 244 test-narrow-expanddirstate.t
245 245 test-narrow-merge.t
246 246 test-narrow-patch.t
247 247 test-narrow-patterns.t
248 248 test-narrow-pull.t
249 249 test-narrow-rebase.t
250 250 test-narrow-shallow-merges.t
251 251 test-narrow-shallow.t
252 252 test-narrow-strip.t
253 253 test-narrow-update.t
254 254 test-nested-repo.t
255 255 test-newbranch.t
256 256 test-obshistory.t
257 257 test-obsmarker-template.t
258 258 test-obsmarkers-effectflag.t
259 259 test-obsolete-bundle-strip.t
260 260 test-obsolete-changeset-exchange.t
261 261 test-obsolete-checkheads.t
262 262 test-obsolete-distributed.t
263 263 test-obsolete-tag-cache.t
264 264 test-parents.t
265 265 test-pathconflicts-merge.t
266 266 test-pathconflicts-update.t
267 267 test-pending.t
268 268 test-permissions.t
269 269 test-phases.t
270 270 test-pull-branch.t
271 271 test-pull-http.t
272 272 test-pull-permission.t
273 273 test-pull-pull-corruption.t
274 274 test-pull-r.t
275 275 test-pull-update.t
276 276 test-purge.t
277 277 test-push-checkheads-partial-C1.t
278 278 test-push-checkheads-partial-C2.t
279 279 test-push-checkheads-partial-C3.t
280 280 test-push-checkheads-partial-C4.t
281 281 test-push-checkheads-pruned-B1.t
282 282 test-push-checkheads-pruned-B2.t
283 283 test-push-checkheads-pruned-B3.t
284 284 test-push-checkheads-pruned-B4.t
285 285 test-push-checkheads-pruned-B5.t
286 286 test-push-checkheads-pruned-B6.t
287 287 test-push-checkheads-pruned-B7.t
288 288 test-push-checkheads-pruned-B8.t
289 289 test-push-checkheads-superceed-A1.t
290 290 test-push-checkheads-superceed-A2.t
291 291 test-push-checkheads-superceed-A3.t
292 292 test-push-checkheads-superceed-A4.t
293 293 test-push-checkheads-superceed-A5.t
294 294 test-push-checkheads-superceed-A6.t
295 295 test-push-checkheads-superceed-A7.t
296 296 test-push-checkheads-superceed-A8.t
297 297 test-push-checkheads-unpushed-D1.t
298 298 test-push-checkheads-unpushed-D2.t
299 299 test-push-checkheads-unpushed-D3.t
300 300 test-push-checkheads-unpushed-D4.t
301 301 test-push-checkheads-unpushed-D5.t
302 302 test-push-checkheads-unpushed-D6.t
303 303 test-push-checkheads-unpushed-D7.t
304 304 test-push-http.t
305 305 test-push-warn.t
306 306 test-pushvars.t
307 307 test-rebase-abort.t
308 308 test-rebase-base-flag.t
309 309 test-rebase-bookmarks.t
310 310 test-rebase-brute-force.t
311 311 test-rebase-cache.t
312 312 test-rebase-check-restore.t
313 313 test-rebase-collapse.t
314 314 test-rebase-dest.t
315 315 test-rebase-detach.t
316 316 test-rebase-emptycommit.t
317 317 test-rebase-inmemory.t
318 318 test-rebase-interruptions.t
319 319 test-rebase-issue-noparam-single-rev.t
320 320 test-rebase-legacy.t
321 321 test-rebase-mq-skip.t
322 322 test-rebase-named-branches.t
323 323 test-rebase-newancestor.t
324 324 test-rebase-obsolete.t
325 325 test-rebase-parameters.t
326 326 test-rebase-partial.t
327 327 test-rebase-pull.t
328 328 test-rebase-rename.t
329 329 test-rebase-scenario-global.t
330 330 test-rebase-templates.t
331 331 test-rebase-transaction.t
332 332 test-record.t
333 333 test-relink.t
334 334 test-remove.t
335 335 test-rename-after-merge.t
336 336 test-rename-dir-merge.t
337 337 test-rename-merge1.t
338 338 test-rename.t
339 339 test-repair-strip.t
340 340 test-repo-compengines.t
341 341 test-resolve.t
342 342 test-revert-flags.t
343 343 test-revert-unknown.t
344 344 test-revlog-ancestry.py
345 345 test-revlog-group-emptyiter.t
346 346 test-revlog-mmapindex.t
347 347 test-revlog-packentry.t
348 348 test-revset-dirstate-parents.t
349 349 test-revset-outgoing.t
350 350 test-run-tests.py
351 351 test-schemes.t
352 352 test-serve.t
353 353 test-share.t
354 354 test-show-stack.t
355 355 test-show-work.t
356 356 test-show.t
357 357 test-simple-update.t
358 358 test-single-head.t
359 359 test-sparse-clear.t
360 360 test-sparse-merges.t
361 361 test-sparse-requirement.t
362 362 test-sparse-verbose-json.t
363 363 test-ssh-clone-r.t
364 364 test-ssh-proto.t
365 365 test-sshserver.py
366 366 test-status-rev.t
367 367 test-status-terse.t
368 368 test-strip-cross.t
369 369 test-strip.t
370 370 test-subrepo-deep-nested-change.t
371 371 test-subrepo.t
372 372 test-symlinks.t
373 test-tag.t
373 374 test-treemanifest.t
374 375 test-unamend.t
375 376 test-uncommit.t
376 377 test-unified-test.t
377 378 test-unrelated-pull.t
378 379 test-up-local-change.t
379 380 test-update-branches.t
380 381 test-update-dest.t
381 382 test-update-issue1456.t
382 383 test-update-names.t
383 384 test-update-reverse.t
384 385 test-upgrade-repo.t
385 386 test-url-rev.t
386 387 test-username-newline.t
387 388 test-verify.t
388 389 test-websub.t
389 390 test-win32text.t
390 391 test-xdg.t
@@ -1,271 +1,269
1 1 # tagmerge.py - merge .hgtags files
2 2 #
3 3 # Copyright 2014 Angel Ezquerra <angel.ezquerra@gmail.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 # This module implements an automatic merge algorithm for mercurial's tag files
9 9 #
10 10 # The tagmerge algorithm implemented in this module is able to resolve most
11 11 # merge conflicts that currently would trigger a .hgtags merge conflict. The
12 12 # only case that it does not (and cannot) handle is that in which two tags point
13 13 # to different revisions on each merge parent _and_ their corresponding tag
14 14 # histories have the same rank (i.e. the same length). In all other cases the
15 15 # merge algorithm will choose the revision belonging to the parent with the
16 16 # highest ranked tag history. The merged tag history is the combination of both
17 17 # tag histories (special care is taken to try to combine common tag histories
18 18 # where possible).
19 19 #
20 20 # In addition to actually merging the tags from two parents, taking into
21 21 # account the base, the algorithm also tries to minimize the difference
22 22 # between the merged tag file and the first parent's tag file (i.e. it tries to
23 23 # make the merged tag order as as similar as possible to the first parent's tag
24 24 # file order).
25 25 #
26 26 # The algorithm works as follows:
27 27 # 1. read the tags from p1, p2 and the base
28 28 # - when reading the p1 tags, also get the line numbers associated to each
29 29 # tag node (these will be used to sort the merged tags in a way that
30 30 # minimizes the diff to p1). Ignore the file numbers when reading p2 and
31 31 # the base
32 32 # 2. recover the "lost tags" (i.e. those that are found in the base but not on
33 33 # p1 or p2) and add them back to p1 and/or p2
34 34 # - at this point the only tags that are on p1 but not on p2 are those new
35 35 # tags that were introduced in p1. Same thing for the tags that are on p2
36 36 # but not on p2
37 37 # 3. take all tags that are only on p1 or only on p2 (but not on the base)
38 38 # - Note that these are the tags that were introduced between base and p1
39 39 # and between base and p2, possibly on separate clones
40 40 # 4. for each tag found both on p1 and p2 perform the following merge algorithm:
41 41 # - the tags conflict if their tag "histories" have the same "rank" (i.e.
42 42 # length) AND the last (current) tag is NOT the same
43 43 # - for non conflicting tags:
44 44 # - choose which are the high and the low ranking nodes
45 45 # - the high ranking list of nodes is the one that is longer.
46 46 # In case of draw favor p1
47 47 # - the merged node list is made of 3 parts:
48 48 # - first the nodes that are common to the beginning of both
49 49 # the low and the high ranking nodes
50 50 # - second the non common low ranking nodes
51 51 # - finally the non common high ranking nodes (with the last
52 52 # one being the merged tag node)
53 53 # - note that this is equivalent to putting the whole low ranking
54 54 # node list first, followed by the non common high ranking nodes
55 55 # - note that during the merge we keep the "node line numbers", which will
56 56 # be used when writing the merged tags to the tag file
57 57 # 5. write the merged tags taking into account to their positions in the first
58 58 # parent (i.e. try to keep the relative ordering of the nodes that come
59 59 # from p1). This minimizes the diff between the merged and the p1 tag files
60 60 # This is done by using the following algorithm
61 61 # - group the nodes for a given tag that must be written next to each other
62 62 # - A: nodes that come from consecutive lines on p1
63 63 # - B: nodes that come from p2 (i.e. whose associated line number is
64 64 # None) and are next to one of the a nodes in A
65 65 # - each group is associated with a line number coming from p1
66 66 # - generate a "tag block" for each of the groups
67 67 # - a tag block is a set of consecutive "node tag" lines belonging to
68 68 # the same tag and which will be written next to each other on the
69 69 # merged tags file
70 70 # - sort the "tag blocks" according to their associated number line
71 71 # - put blocks whose nodes come all from p2 first
72 72 # - write the tag blocks in the sorted order
73 73
74 74 from __future__ import absolute_import
75 75
76 import operator
77
78 76 from .i18n import _
79 77 from .node import (
80 78 hex,
81 79 nullid,
82 80 )
83 81 from .import (
84 82 tags as tagsmod,
85 83 util,
86 84 )
87 85
88 86 hexnullid = hex(nullid)
89 87
90 88 def readtagsformerge(ui, repo, lines, fn='', keeplinenums=False):
91 89 '''read the .hgtags file into a structure that is suitable for merging
92 90
93 91 Depending on the keeplinenums flag, clear the line numbers associated
94 92 with each tag. This is done because only the line numbers of the first
95 93 parent are useful for merging.
96 94 '''
97 95 filetags = tagsmod._readtaghist(ui, repo, lines, fn=fn, recode=None,
98 96 calcnodelines=True)[1]
99 97 for tagname, taginfo in filetags.items():
100 98 if not keeplinenums:
101 99 for el in taginfo:
102 100 el[1] = None
103 101 return filetags
104 102
105 103 def grouptagnodesbyline(tagnodes):
106 104 '''
107 105 Group nearby nodes (i.e. those that must be written next to each other)
108 106
109 107 The input is a list of [node, position] pairs, corresponding to a given tag
110 108 The position is the line number where the node was found on the first parent
111 109 .hgtags file, or None for those nodes that came from the base or the second
112 110 parent .hgtags files.
113 111
114 112 This function groups those [node, position] pairs, returning a list of
115 113 groups of nodes that must be written next to each other because their
116 114 positions are consecutive or have no position preference (because their
117 115 position is None).
118 116
119 117 The result is a list of [position, [consecutive node list]]
120 118 '''
121 119 firstlinenum = None
122 120 for hexnode, linenum in tagnodes:
123 121 firstlinenum = linenum
124 122 if firstlinenum is not None:
125 123 break
126 124 if firstlinenum is None:
127 125 return [[None, [el[0] for el in tagnodes]]]
128 126 tagnodes[0][1] = firstlinenum
129 127 groupednodes = [[firstlinenum, []]]
130 128 prevlinenum = firstlinenum
131 129 for hexnode, linenum in tagnodes:
132 130 if linenum is not None and linenum - prevlinenum > 1:
133 131 groupednodes.append([linenum, []])
134 132 groupednodes[-1][1].append(hexnode)
135 133 if linenum is not None:
136 134 prevlinenum = linenum
137 135 return groupednodes
138 136
139 137 def writemergedtags(fcd, mergedtags):
140 138 '''
141 139 write the merged tags while trying to minimize the diff to the first parent
142 140
143 141 This function uses the ordering info stored on the merged tags dict to
144 142 generate an .hgtags file which is correct (in the sense that its contents
145 143 correspond to the result of the tag merge) while also being as close as
146 144 possible to the first parent's .hgtags file.
147 145 '''
148 146 # group the node-tag pairs that must be written next to each other
149 147 for tname, taglist in list(mergedtags.items()):
150 148 mergedtags[tname] = grouptagnodesbyline(taglist)
151 149
152 150 # convert the grouped merged tags dict into a format that resembles the
153 151 # final .hgtags file (i.e. a list of blocks of 'node tag' pairs)
154 152 def taglist2string(tlist, tname):
155 153 return '\n'.join(['%s %s' % (hexnode, tname) for hexnode in tlist])
156 154
157 155 finaltags = []
158 156 for tname, tags in mergedtags.items():
159 157 for block in tags:
160 158 block[1] = taglist2string(block[1], tname)
161 159 finaltags += tags
162 160
163 161 # the tag groups are linked to a "position" that can be used to sort them
164 162 # before writing them
165 163 # the position is calculated to ensure that the diff of the merged .hgtags
166 164 # file to the first parent's .hgtags file is as small as possible
167 finaltags.sort(key=operator.itemgetter(0))
165 finaltags.sort(key=lambda x: -1 if x[0] is None else x[0])
168 166
169 167 # finally we can join the sorted groups to get the final contents of the
170 168 # merged .hgtags file, and then write it to disk
171 169 mergedtagstring = '\n'.join([tags for rank, tags in finaltags if tags])
172 170 fcd.write(mergedtagstring + '\n', fcd.flags())
173 171
174 172 def singletagmerge(p1nodes, p2nodes):
175 173 '''
176 174 merge the nodes corresponding to a single tag
177 175
178 176 Note that the inputs are lists of node-linenum pairs (i.e. not just lists
179 177 of nodes)
180 178 '''
181 179 if not p2nodes:
182 180 return p1nodes
183 181 if not p1nodes:
184 182 return p2nodes
185 183
186 184 # there is no conflict unless both tags point to different revisions
187 185 # and have a non identical tag history
188 186 p1currentnode = p1nodes[-1][0]
189 187 p2currentnode = p2nodes[-1][0]
190 188 if p1currentnode != p2currentnode and len(p1nodes) == len(p2nodes):
191 189 # cannot merge two tags with same rank pointing to different nodes
192 190 return None
193 191
194 192 # which are the highest ranking (hr) / lowest ranking (lr) nodes?
195 193 if len(p1nodes) >= len(p2nodes):
196 194 hrnodes, lrnodes = p1nodes, p2nodes
197 195 else:
198 196 hrnodes, lrnodes = p2nodes, p1nodes
199 197
200 198 # the lowest ranking nodes will be written first, followed by the highest
201 199 # ranking nodes
202 200 # to avoid unwanted tag rank explosion we try to see if there are some
203 201 # common nodes that can be written only once
204 202 commonidx = len(lrnodes)
205 203 for n in range(len(lrnodes)):
206 204 if hrnodes[n][0] != lrnodes[n][0]:
207 205 commonidx = n
208 206 break
209 207 lrnodes[n][1] = p1nodes[n][1]
210 208
211 209 # the merged node list has 3 parts:
212 210 # - common nodes
213 211 # - non common lowest ranking nodes
214 212 # - non common highest ranking nodes
215 213 # note that the common nodes plus the non common lowest ranking nodes is the
216 214 # whole list of lr nodes
217 215 return lrnodes + hrnodes[commonidx:]
218 216
219 217 def merge(repo, fcd, fco, fca):
220 218 '''
221 219 Merge the tags of two revisions, taking into account the base tags
222 220 Try to minimize the diff between the merged tags and the first parent tags
223 221 '''
224 222 ui = repo.ui
225 223 # read the p1, p2 and base tags
226 224 # only keep the line numbers for the p1 tags
227 225 p1tags = readtagsformerge(
228 226 ui, repo, fcd.data().splitlines(), fn="p1 tags",
229 227 keeplinenums=True)
230 228 p2tags = readtagsformerge(
231 229 ui, repo, fco.data().splitlines(), fn="p2 tags",
232 230 keeplinenums=False)
233 231 basetags = readtagsformerge(
234 232 ui, repo, fca.data().splitlines(), fn="base tags",
235 233 keeplinenums=False)
236 234
237 235 # recover the list of "lost tags" (i.e. those that were found on the base
238 236 # revision but not on one of the revisions being merged)
239 237 basetagset = set(basetags)
240 238 for n, pntags in enumerate((p1tags, p2tags)):
241 239 pntagset = set(pntags)
242 240 pnlosttagset = basetagset - pntagset
243 241 for t in pnlosttagset:
244 242 pntags[t] = basetags[t]
245 243 if pntags[t][-1][0] != hexnullid:
246 244 pntags[t].append([hexnullid, None])
247 245
248 246 conflictedtags = [] # for reporting purposes
249 247 mergedtags = util.sortdict(p1tags)
250 248 # sortdict does not implement iteritems()
251 249 for tname, p2nodes in p2tags.items():
252 250 if tname not in mergedtags:
253 251 mergedtags[tname] = p2nodes
254 252 continue
255 253 p1nodes = mergedtags[tname]
256 254 mergednodes = singletagmerge(p1nodes, p2nodes)
257 255 if mergednodes is None:
258 256 conflictedtags.append(tname)
259 257 continue
260 258 mergedtags[tname] = mergednodes
261 259
262 260 if conflictedtags:
263 261 numconflicts = len(conflictedtags)
264 262 ui.warn(_('automatic .hgtags merge failed\n'
265 263 'the following %d tags are in conflict: %s\n')
266 264 % (numconflicts, ', '.join(sorted(conflictedtags))))
267 265 return True, 1
268 266
269 267 writemergedtags(fcd, mergedtags)
270 268 ui.note(_('.hgtags merged successfully\n'))
271 269 return False, 0
General Comments 0
You need to be logged in to leave comments. Login now