comparison mercurial/context.py @ 32651:c850f0ed54c1 stable 4.2.1

status: don't crash if a lookup file disappears This can happen if another process (even another hg process!) comes along and removes the file at that time. This partly resolves issue5584, but not completely -- a bogus dirstate update can still happen. However, the full fix is too involved for stable.
author Siddharth Agarwal <sid0@fb.com>
date Fri, 02 Jun 2017 22:27:52 -0700
parents a457da5296a5
children 9929af2b09b4
comparison
equal deleted inserted replaced
32608:85b978031a75 32651:c850f0ed54c1
1611 return sane 1611 return sane
1612 1612
1613 def _checklookup(self, files): 1613 def _checklookup(self, files):
1614 # check for any possibly clean files 1614 # check for any possibly clean files
1615 if not files: 1615 if not files:
1616 return [], [] 1616 return [], [], []
1617 1617
1618 modified = [] 1618 modified = []
1619 deleted = []
1619 fixup = [] 1620 fixup = []
1620 pctx = self._parents[0] 1621 pctx = self._parents[0]
1621 # do a full compare of any files that might have changed 1622 # do a full compare of any files that might have changed
1622 for f in sorted(files): 1623 for f in sorted(files):
1623 if (f not in pctx or self.flags(f) != pctx.flags(f) 1624 try:
1624 or pctx[f].cmp(self[f])): 1625 # This will return True for a file that got replaced by a
1625 modified.append(f) 1626 # directory in the interim, but fixing that is pretty hard.
1626 else: 1627 if (f not in pctx or self.flags(f) != pctx.flags(f)
1627 fixup.append(f) 1628 or pctx[f].cmp(self[f])):
1629 modified.append(f)
1630 else:
1631 fixup.append(f)
1632 except (IOError, OSError):
1633 # A file become inaccessible in between? Mark it as deleted,
1634 # matching dirstate behavior (issue5584).
1635 # The dirstate has more complex behavior around whether a
1636 # missing file matches a directory, etc, but we don't need to
1637 # bother with that: if f has made it to this point, we're sure
1638 # it's in the dirstate.
1639 deleted.append(f)
1628 1640
1629 # update dirstate for files that are actually clean 1641 # update dirstate for files that are actually clean
1630 if fixup: 1642 if fixup:
1631 try: 1643 try:
1632 # updating the dirstate is optional 1644 # updating the dirstate is optional
1642 # after this block from doing so for subsequent 1654 # after this block from doing so for subsequent
1643 # changing files 1655 # changing files
1644 self._repo.dirstate.write(self._repo.currenttransaction()) 1656 self._repo.dirstate.write(self._repo.currenttransaction())
1645 except error.LockError: 1657 except error.LockError:
1646 pass 1658 pass
1647 return modified, fixup 1659 return modified, deleted, fixup
1648 1660
1649 def _dirstatestatus(self, match=None, ignored=False, clean=False, 1661 def _dirstatestatus(self, match=None, ignored=False, clean=False,
1650 unknown=False): 1662 unknown=False):
1651 '''Gets the status from the dirstate -- internal use only.''' 1663 '''Gets the status from the dirstate -- internal use only.'''
1652 listignored, listclean, listunknown = ignored, clean, unknown 1664 listignored, listclean, listunknown = ignored, clean, unknown
1657 cmp, s = self._repo.dirstate.status(match, subrepos, listignored, 1669 cmp, s = self._repo.dirstate.status(match, subrepos, listignored,
1658 listclean, listunknown) 1670 listclean, listunknown)
1659 1671
1660 # check for any possibly clean files 1672 # check for any possibly clean files
1661 if cmp: 1673 if cmp:
1662 modified2, fixup = self._checklookup(cmp) 1674 modified2, deleted2, fixup = self._checklookup(cmp)
1663 s.modified.extend(modified2) 1675 s.modified.extend(modified2)
1676 s.deleted.extend(deleted2)
1664 1677
1665 # update dirstate for files that are actually clean 1678 # update dirstate for files that are actually clean
1666 if fixup and listclean: 1679 if fixup and listclean:
1667 s.clean.extend(fixup) 1680 s.clean.extend(fixup)
1668 1681