mercurial/commands.py
changeset 45696 de6f2afc0247
parent 45695 760bb4d74aad
child 45697 494642ed3c50
equal deleted inserted replaced
45695:760bb4d74aad 45696:de6f2afc0247
     5 # This software may be used and distributed according to the terms of the
     5 # This software may be used and distributed according to the terms of the
     6 # GNU General Public License version 2 or any later version.
     6 # GNU General Public License version 2 or any later version.
     7 
     7 
     8 from __future__ import absolute_import
     8 from __future__ import absolute_import
     9 
     9 
    10 import difflib
       
    11 import errno
    10 import errno
    12 import os
    11 import os
    13 import re
    12 import re
    14 import sys
    13 import sys
    15 
    14 
    39     exchange,
    38     exchange,
    40     extensions,
    39     extensions,
    41     filemerge,
    40     filemerge,
    42     formatter,
    41     formatter,
    43     graphmod,
    42     graphmod,
       
    43     grep as grepmod,
    44     hbisect,
    44     hbisect,
    45     help,
    45     help,
    46     hg,
    46     hg,
    47     logcmdutil,
    47     logcmdutil,
    48     match as matchmod,
    48     match as matchmod,
  3397     sep, eol = b':', b'\n'
  3397     sep, eol = b':', b'\n'
  3398     if opts.get(b'print0'):
  3398     if opts.get(b'print0'):
  3399         sep = eol = b'\0'
  3399         sep = eol = b'\0'
  3400 
  3400 
  3401     getfile = util.lrucachefunc(repo.file)
  3401     getfile = util.lrucachefunc(repo.file)
  3402 
       
  3403     def matchlines(body, regexp):
       
  3404         begin = 0
       
  3405         linenum = 0
       
  3406         while begin < len(body):
       
  3407             match = regexp.search(body, begin)
       
  3408             if not match:
       
  3409                 break
       
  3410             mstart, mend = match.span()
       
  3411             linenum += body.count(b'\n', begin, mstart) + 1
       
  3412             lstart = body.rfind(b'\n', begin, mstart) + 1 or begin
       
  3413             begin = body.find(b'\n', mend) + 1 or len(body) + 1
       
  3414             lend = begin - 1
       
  3415             yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
       
  3416 
       
  3417     class linestate(object):
       
  3418         def __init__(self, line, linenum, colstart, colend):
       
  3419             self.line = line
       
  3420             self.linenum = linenum
       
  3421             self.colstart = colstart
       
  3422             self.colend = colend
       
  3423 
       
  3424         def __hash__(self):
       
  3425             return hash(self.line)
       
  3426 
       
  3427         def __eq__(self, other):
       
  3428             return self.line == other.line
       
  3429 
       
  3430         def findpos(self, regexp):
       
  3431             """Iterate all (start, end) indices of matches"""
       
  3432             yield self.colstart, self.colend
       
  3433             p = self.colend
       
  3434             while p < len(self.line):
       
  3435                 m = regexp.search(self.line, p)
       
  3436                 if not m:
       
  3437                     break
       
  3438                 if m.end() == p:
       
  3439                     p += 1
       
  3440                 else:
       
  3441                     yield m.span()
       
  3442                     p = m.end()
       
  3443 
       
  3444     matches = {}
  3402     matches = {}
  3445     copies = {}
  3403     copies = {}
  3446 
  3404 
  3447     def grepbody(fn, rev, body):
  3405     def grepbody(fn, rev, body):
  3448         matches[rev].setdefault(fn, [])
  3406         matches[rev].setdefault(fn, [])
  3449         m = matches[rev][fn]
  3407         m = matches[rev][fn]
  3450         if body is None:
  3408         if body is None:
  3451             return
  3409             return
  3452 
  3410 
  3453         for lnum, cstart, cend, line in matchlines(body, regexp):
  3411         for lnum, cstart, cend, line in grepmod.matchlines(body, regexp):
  3454             s = linestate(line, lnum, cstart, cend)
  3412             s = grepmod.linestate(line, lnum, cstart, cend)
  3455             m.append(s)
  3413             m.append(s)
  3456 
       
  3457     def difflinestates(a, b):
       
  3458         sm = difflib.SequenceMatcher(None, a, b)
       
  3459         for tag, alo, ahi, blo, bhi in sm.get_opcodes():
       
  3460             if tag == 'insert':
       
  3461                 for i in pycompat.xrange(blo, bhi):
       
  3462                     yield (b'+', b[i])
       
  3463             elif tag == 'delete':
       
  3464                 for i in pycompat.xrange(alo, ahi):
       
  3465                     yield (b'-', a[i])
       
  3466             elif tag == 'replace':
       
  3467                 for i in pycompat.xrange(alo, ahi):
       
  3468                     yield (b'-', a[i])
       
  3469                 for i in pycompat.xrange(blo, bhi):
       
  3470                     yield (b'+', b[i])
       
  3471 
  3414 
  3472     uipathfn = scmutil.getuipathfn(repo)
  3415     uipathfn = scmutil.getuipathfn(repo)
  3473 
  3416 
  3474     def display(fm, fn, ctx, pstates, states):
  3417     def display(fm, fn, ctx, pstates, states):
  3475         rev = scmutil.intrev(ctx)
  3418         rev = scmutil.intrev(ctx)
  3491             except error.WdirUnsupported:
  3434             except error.WdirUnsupported:
  3492                 return ctx[fn].isbinary()
  3435                 return ctx[fn].isbinary()
  3493 
  3436 
  3494         fieldnamemap = {b'linenumber': b'lineno'}
  3437         fieldnamemap = {b'linenumber': b'lineno'}
  3495         if diff:
  3438         if diff:
  3496             iter = difflinestates(pstates, states)
  3439             iter = grepmod.difflinestates(pstates, states)
  3497         else:
  3440         else:
  3498             iter = [(b'', l) for l in states]
  3441             iter = [(b'', l) for l in states]
  3499         for change, l in iter:
  3442         for change, l in iter:
  3500             fm.startitem()
  3443             fm.startitem()
  3501             fm.context(ctx=ctx)
  3444             fm.context(ctx=ctx)