vc, svn and hg refactors; hg blame works
--HG-- branch : pmacs2
This commit is contained in:
parent
0fad7e130c
commit
b92be6cc27
26
method/hg.py
26
method/hg.py
|
@ -1,7 +1,9 @@
|
||||||
|
import os
|
||||||
|
import re
|
||||||
from subprocess import Popen, PIPE, STDOUT
|
from subprocess import Popen, PIPE, STDOUT
|
||||||
|
|
||||||
from method import Method, Argument
|
from method import Method, Argument
|
||||||
from method.vc import VcBlame
|
from method.vc import VcBlame
|
||||||
import re
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from mercurial import hg, ui
|
from mercurial import hg, ui
|
||||||
|
@ -20,31 +22,23 @@ class HgBase(object):
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
def _hg_init(self):
|
def _hg_init(self, **kwargs):
|
||||||
ui_imp = ui.ui(verbose=True)
|
ui_imp = ui.ui(**kwargs)
|
||||||
ui_imp.pushbuffer()
|
ui_imp.pushbuffer()
|
||||||
repo = hg.repository(ui=ui_imp, path='.')
|
repo = hg.repository(ui=ui_imp, path='.')
|
||||||
return ui_imp, repo
|
return ui_imp, repo
|
||||||
|
|
||||||
class HgBlame(VcBlame, HgBase):
|
class HgBlame(VcBlame, HgBase):
|
||||||
"""Show buffer annotated with hg metadata"""
|
"""Show buffer annotated with hg metadata"""
|
||||||
line_re = re.compile(r'^ *(?P<user>[^ ]+) (?P<rev>\d+) (?P<date>\d{4}-\d{2}-\d{2}): (?P<content>.*)\n$')
|
num_fields = 3
|
||||||
prefix_fmt = '[b:d:*]%(rev)-5s [c:d:*]%(user)-10s [b:d:*]%(date)10s[d:d:*]'
|
# user, rev, [changeset], date, content
|
||||||
|
line_re = re.compile(r'^ *([^ ]+) +(\d+) +[^ ]+ +(\d{4}-\d{2}-\d{2}): (.*)\n$')
|
||||||
|
prefix_fmt = '[g:d:*]%*s [c:d:*]%*s [b:d:*]%*s[d:d:*]'
|
||||||
_is_method = True
|
_is_method = True
|
||||||
def _open_pipe(self, w, **vargs):
|
def _open_pipe(self, w, **vargs):
|
||||||
cmd = ("hg", 'blame', '-nudq', w.buffer.path)
|
cmd = ("hg", 'blame', '-cnudq', w.buffer.path)
|
||||||
return Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
|
return Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
|
||||||
|
|
||||||
class HgBlame2(Method, HgBase):
|
|
||||||
def _execute(self, w, **vargs):
|
|
||||||
if not self._hg_check(w):
|
|
||||||
return
|
|
||||||
ui_imp, repo = self._hg_init()
|
|
||||||
hgc.identify(ui_imp, repo, w.buffer.path)
|
|
||||||
hgc.annotate(ui_imp, repo, w.buffer.path, user=None, date=None, rev=None)
|
|
||||||
s = ''.join(ui_imp.popbuffer())
|
|
||||||
w.application.data_buffer('*Blame*', s, switch_to=True)
|
|
||||||
|
|
||||||
class HgLog(Method, HgBase):
|
class HgLog(Method, HgBase):
|
||||||
"""Show hg log for this buffer"""
|
"""Show hg log for this buffer"""
|
||||||
def _execute(self, w, **vargs):
|
def _execute(self, w, **vargs):
|
||||||
|
|
|
@ -264,10 +264,12 @@ class SvnDiff3(Method):
|
||||||
|
|
||||||
class SvnBlame(VcBlame):
|
class SvnBlame(VcBlame):
|
||||||
'''show blame output for the current version in SVN'''
|
'''show blame output for the current version in SVN'''
|
||||||
line_re = re.compile('^ *(?P<rev>\d+) *(?P<user>[a-zA-Z0-9_]+) *(?P<date>[-0-9]+) *(?P<time>[:0-9]+) *(?P<tz>-\d{4}) *\((?P<vdate>[^\)]+)\) (?P<content>.*)\n$')
|
# rev, user, date, [time], [timezone], [date-str], content
|
||||||
prefix_fmt = '[b:d:*]%(rev)-4s [c:d:*]%(user)-10s [b:d:*]%(date)10s[d:d:*]'
|
num_fields = 3
|
||||||
_is_method = True
|
line_re = re.compile(r'^ *(\d+) *([a-zA-Z0-9_]+) *([-0-9]+) *[:0-9]+ *-\d{4} *\(.+?\) (.*)\n$')
|
||||||
|
prefix_fmt = '[g:d:*]%*s [c:d:*]%-*s [b:d:*]%*s[d:d:*]'
|
||||||
pretest_err_msg = 'Subversion is not installed'
|
pretest_err_msg = 'Subversion is not installed'
|
||||||
|
_is_method = True
|
||||||
def _pretest(self):
|
def _pretest(self):
|
||||||
return has_svn
|
return has_svn
|
||||||
def _open_pipe(self, w, **vargs):
|
def _open_pipe(self, w, **vargs):
|
||||||
|
|
54
method/vc.py
54
method/vc.py
|
@ -10,34 +10,37 @@ class VcBlame(Method):
|
||||||
line_re = None
|
line_re = None
|
||||||
prefix_fmt = None
|
prefix_fmt = None
|
||||||
pretest_err_msg = None
|
pretest_err_msg = None
|
||||||
|
num_fields = 1
|
||||||
def _pretest(self):
|
def _pretest(self):
|
||||||
return True
|
return True
|
||||||
def _filter(self, line):
|
def _filter(self, line):
|
||||||
m = self.line_re.match(line)
|
m = self.line_re.match(line)
|
||||||
if not m:
|
if not m:
|
||||||
raise VcException("couldn't parse %r" % line)
|
raise VcException("couldn't parse %r" % line)
|
||||||
return m.groupdict()
|
groups = m.groups()
|
||||||
|
return {'fields': groups[:-1], 'content': groups[-1], 'tokens': []}
|
||||||
def _open_pipe(self, w, **vargs):
|
def _open_pipe(self, w, **vargs):
|
||||||
raise Exception('unimplemented')
|
raise Exception('unimplemented')
|
||||||
def _execute(self, w, **vargs):
|
def _build_groups(self, w, **vargs):
|
||||||
if not self._pretest():
|
|
||||||
w.set_error(self.pretest_err_msg)
|
|
||||||
return
|
|
||||||
elif not hasattr(w.buffer, 'path'):
|
|
||||||
w.set_error("Buffer has no corresponding file")
|
|
||||||
return
|
|
||||||
|
|
||||||
pipe = self._open_pipe(w, **vargs)
|
pipe = self._open_pipe(w, **vargs)
|
||||||
groups = [self._filter(line) for line in pipe.stdout]
|
groups = []
|
||||||
|
gsizes = [0] * self.num_fields
|
||||||
|
for line in pipe.stdout:
|
||||||
|
d = self._filter(line)
|
||||||
|
for i in range(0, self.num_fields):
|
||||||
|
gsizes[i] = max(gsizes[i], len(d['fields'][i]))
|
||||||
|
groups.append(d)
|
||||||
status = pipe.wait() >> 8
|
status = pipe.wait() >> 8
|
||||||
|
if status != 0:
|
||||||
|
raise Exception("There was an error (%d)" % status)
|
||||||
|
return groups, gsizes
|
||||||
|
def _lex_groups(self, groups, w, **vargs):
|
||||||
if w.mode.grammar:
|
if w.mode.grammar:
|
||||||
lexer = lex.Lexer(w.mode, w.mode.grammar)
|
lexer = lex.Lexer(w.mode, w.mode.grammar)
|
||||||
tokens = list(lexer.lex([d['content'] for d in groups]))
|
for t in lexer.lex([d['content'] for d in groups]):
|
||||||
for t in tokens:
|
|
||||||
groups[t.y].setdefault('tokens', [])
|
|
||||||
groups[t.y]['tokens'].append(t)
|
groups[t.y]['tokens'].append(t)
|
||||||
|
def _build_lines(self, groups, gsizes, w, **vargs):
|
||||||
|
self._lex_groups(groups, w, **vargs)
|
||||||
lines = []
|
lines = []
|
||||||
for d in groups:
|
for d in groups:
|
||||||
if d['tokens']:
|
if d['tokens']:
|
||||||
|
@ -47,10 +50,21 @@ class VcBlame(Method):
|
||||||
suffix += code + util.cbuf_escape(t.string)
|
suffix += code + util.cbuf_escape(t.string)
|
||||||
else:
|
else:
|
||||||
suffix = d['content'] + '\n'
|
suffix = d['content'] + '\n'
|
||||||
lines.append(self.prefix_fmt % d + ' ' + suffix)
|
tpl = tuple(util.flatzip(gsizes, d['fields']))
|
||||||
data = ''.join(lines)
|
lines.append(self.prefix_fmt % tpl + ' ' + suffix)
|
||||||
|
return lines
|
||||||
|
def _execute(self, w, **vargs):
|
||||||
|
if not self._pretest():
|
||||||
|
w.set_error(self.pretest_err_msg)
|
||||||
|
return
|
||||||
|
elif not hasattr(w.buffer, 'path'):
|
||||||
|
w.set_error("Buffer has no corresponding file")
|
||||||
|
return
|
||||||
|
|
||||||
if status == 0:
|
try:
|
||||||
|
groups, gsizes = self._build_groups(w, **vargs)
|
||||||
|
except Exception, e:
|
||||||
|
w.set_error(str(e))
|
||||||
|
|
||||||
|
data = ''.join(self._build_lines(groups, gsizes, w, **vargs))
|
||||||
w.application.color_data_buffer("*Blame*", data, switch_to=True)
|
w.application.color_data_buffer("*Blame*", data, switch_to=True)
|
||||||
else:
|
|
||||||
w.set_error("There was an error (%s)" % (status))
|
|
||||||
|
|
7
util.py
7
util.py
|
@ -7,6 +7,13 @@ cbuf_re = re.compile(r'[\[\]\\]')
|
||||||
def cbuf_escape(s):
|
def cbuf_escape(s):
|
||||||
return cbuf_re.sub(lambda m: '\\' + m.group(0), s)
|
return cbuf_re.sub(lambda m: '\\' + m.group(0), s)
|
||||||
|
|
||||||
|
def flatzip(a, b):
|
||||||
|
l = []
|
||||||
|
for x, y in zip(a, b):
|
||||||
|
l.append(x)
|
||||||
|
l.append(y)
|
||||||
|
return l
|
||||||
|
|
||||||
def normal_path(path):
|
def normal_path(path):
|
||||||
#path = os.path.realpath(path)
|
#path = os.path.realpath(path)
|
||||||
path = os.path.normpath(path)
|
path = os.path.normpath(path)
|
||||||
|
|
Loading…
Reference in New Issue