comparison mercurial/commands.py @ 2868:81f351c5264d

grep: display correct user/revision for --all in reverse. Also handle multiple occurrences of the same line by storing linestates in an array instead of a dict, and using difflib to compute the difference between linestates.
author Brendan Cully <brendan@kublai.com>
date Sat, 12 Aug 2006 13:51:14 -0700
parents 7706fa503677
children 8eaaf1321bfe
comparison
equal deleted inserted replaced
2842:7706fa503677 2868:81f351c5264d
8 from demandload import demandload 8 from demandload import demandload
9 from node import * 9 from node import *
10 from i18n import gettext as _ 10 from i18n import gettext as _
11 demandload(globals(), "os re sys signal shutil imp urllib pdb") 11 demandload(globals(), "os re sys signal shutil imp urllib pdb")
12 demandload(globals(), "fancyopts ui hg util lock revlog templater bundlerepo") 12 demandload(globals(), "fancyopts ui hg util lock revlog templater bundlerepo")
13 demandload(globals(), "fnmatch mdiff random signal tempfile time") 13 demandload(globals(), "fnmatch mdiff difflib random signal tempfile time")
14 demandload(globals(), "traceback errno socket version struct atexit sets bz2") 14 demandload(globals(), "traceback errno socket version struct atexit sets bz2")
15 demandload(globals(), "archival cStringIO changegroup email.Parser") 15 demandload(globals(), "archival cStringIO changegroup email.Parser")
16 demandload(globals(), "hgweb.server sshserver") 16 demandload(globals(), "hgweb.server sshserver")
17 17
18 class UnknownCommand(Exception): 18 class UnknownCommand(Exception):
1642 def __init__(self, line, linenum, colstart, colend): 1642 def __init__(self, line, linenum, colstart, colend):
1643 self.line = line 1643 self.line = line
1644 self.linenum = linenum 1644 self.linenum = linenum
1645 self.colstart = colstart 1645 self.colstart = colstart
1646 self.colend = colend 1646 self.colend = colend
1647
1647 def __eq__(self, other): 1648 def __eq__(self, other):
1648 return self.line == other.line 1649 return self.line == other.line
1649 def __hash__(self):
1650 return hash(self.line)
1651 1650
1652 matches = {} 1651 matches = {}
1653 def grepbody(fn, rev, body): 1652 def grepbody(fn, rev, body):
1654 matches[rev].setdefault(fn, {}) 1653 matches[rev].setdefault(fn, [])
1655 m = matches[rev][fn] 1654 m = matches[rev][fn]
1656 for lnum, cstart, cend, line in matchlines(body): 1655 for lnum, cstart, cend, line in matchlines(body):
1657 s = linestate(line, lnum, cstart, cend) 1656 s = linestate(line, lnum, cstart, cend)
1658 m[s] = s 1657 m.append(s)
1659 1658
1660 # FIXME: prev isn't used, why ? 1659 def difflinestates(a, b):
1660 sm = difflib.SequenceMatcher(None, a, b)
1661 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1662 if tag == 'insert':
1663 for i in range(blo, bhi):
1664 yield ('+', b[i])
1665 elif tag == 'delete':
1666 for i in range(alo, ahi):
1667 yield ('-', a[i])
1668 elif tag == 'replace':
1669 for i in range(alo, ahi):
1670 yield ('-', a[i])
1671 for i in range(blo, bhi):
1672 yield ('+', b[i])
1673
1661 prev = {} 1674 prev = {}
1662 ucache = {} 1675 ucache = {}
1663 def display(fn, rev, states, prevstates): 1676 def display(fn, rev, states, prevstates):
1664 diff = list(sets.Set(states).symmetric_difference(sets.Set(prevstates)))
1665 diff.sort(lambda x, y: cmp(x.linenum, y.linenum))
1666 counts = {'-': 0, '+': 0} 1677 counts = {'-': 0, '+': 0}
1667 filerevmatches = {} 1678 filerevmatches = {}
1668 for l in diff: 1679 if incrementing or not opts['all']:
1680 a, b = prevstates, states
1681 else:
1682 a, b = states, prevstates
1683 for change, l in difflinestates(a, b):
1669 if incrementing or not opts['all']: 1684 if incrementing or not opts['all']:
1670 change = ((l in prevstates) and '-') or '+'
1671 r = rev 1685 r = rev
1672 else: 1686 else:
1673 change = ((l in states) and '-') or '+'
1674 r = prev[fn] 1687 r = prev[fn]
1675 cols = [fn, str(rev)] 1688 cols = [fn, str(r)]
1676 if opts['line_number']: 1689 if opts['line_number']:
1677 cols.append(str(l.linenum)) 1690 cols.append(str(l.linenum))
1678 if opts['all']: 1691 if opts['all']:
1679 cols.append(change) 1692 cols.append(change)
1680 if opts['user']: 1693 if opts['user']:
1681 cols.append(trimuser(ui, getchange(rev)[1], rev, 1694 cols.append(trimuser(ui, getchange(r)[1], rev,
1682 ucache)) 1695 ucache))
1683 if opts['files_with_matches']: 1696 if opts['files_with_matches']:
1684 c = (fn, rev) 1697 c = (fn, rev)
1685 if c in filerevmatches: 1698 if c in filerevmatches:
1686 continue 1699 continue
1687 filerevmatches[c] = 1 1700 filerevmatches[c] = 1