comparison hgext/histedit.py @ 28216:eed7d8c07c20

histedit: make histedit aware of obsolescense not stored in state (issue4800) Before this change, when histedit exited to interactive session (during edit command for example), user could introduce obsolescence markers that would not be known to histedit. For example, user could've amended one of the commits. The fact of this amendment would not be stored in histedit's state file and later, when histedit would try to process all the replacements, one of the final successors (in histedit's opinion) would turn out to be hidden. This behavior is described in issue4800. This commit fixes it.
author Kostia Balytskyi <ikostia@fb.com>
date Tue, 23 Feb 2016 21:38:36 +0000
parents 2e11f6756d9c
children 8ec5478aa0d6
comparison
equal deleted inserted replaced
28215:f7c5c7847b53 28216:eed7d8c07c20
1384 raise error.ParseError(_('missing rules for changeset %s') % 1384 raise error.ParseError(_('missing rules for changeset %s') %
1385 missing[0][:12], 1385 missing[0][:12],
1386 hint=_('use "drop %s" to discard, see also: ' 1386 hint=_('use "drop %s" to discard, see also: '
1387 '"hg help -e histedit.config"') % missing[0][:12]) 1387 '"hg help -e histedit.config"') % missing[0][:12])
1388 1388
1389 def adjustreplacementsfrommarkers(repo, oldreplacements):
1390 """Adjust replacements from obsolescense markers
1391
1392 Replacements structure is originally generated based on
1393 histedit's state and does not account for changes that are
1394 not recorded there. This function fixes that by adding
1395 data read from obsolescense markers"""
1396 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1397 return oldreplacements
1398
1399 unfi = repo.unfiltered()
1400 newreplacements = list(oldreplacements)
1401 oldsuccs = [r[1] for r in oldreplacements]
1402 # successors that have already been added to succstocheck once
1403 seensuccs = set().union(*oldsuccs) # create a set from an iterable of tuples
1404 succstocheck = list(seensuccs)
1405 while succstocheck:
1406 n = succstocheck.pop()
1407 try:
1408 ctx = unfi[n]
1409 except error.RepoError:
1410 # XXX node unknown locally, we should properly follow marker
1411 newreplacements.append((n, ()))
1412 continue
1413
1414 for marker in obsolete.successormarkers(ctx):
1415 nsuccs = marker.succnodes()
1416 newreplacements.append((n, nsuccs))
1417 for nsucc in nsuccs:
1418 if nsucc not in seensuccs:
1419 seensuccs.add(nsucc)
1420 succstocheck.append(nsucc)
1421
1422 return newreplacements
1423
1389 def processreplacement(state): 1424 def processreplacement(state):
1390 """process the list of replacements to return 1425 """process the list of replacements to return
1391 1426
1392 1) the final mapping between original and created nodes 1427 1) the final mapping between original and created nodes
1393 2) the list of temporary node created by histedit 1428 2) the list of temporary node created by histedit
1394 3) the list of new commit created by histedit""" 1429 3) the list of new commit created by histedit"""
1395 replacements = state.replacements 1430 replacements = adjustreplacementsfrommarkers(state.repo, state.replacements)
1396 allsuccs = set() 1431 allsuccs = set()
1397 replaced = set() 1432 replaced = set()
1398 fullmapping = {} 1433 fullmapping = {}
1399 # initialize basic set 1434 # initialize basic set
1400 # fullmapping records all operations recorded in replacement 1435 # fullmapping records all operations recorded in replacement