pmacs3/method/cvs.py

301 lines
11 KiB
Python
Raw Permalink Normal View History

import os, subprocess, re, tempfile
from subprocess import Popen, PIPE, STDOUT
import buffer, default, dirutil, lex, regex, util, window
from point import Point
from method import Method, Argument, arg
from method.vc import VcBlame, VcRevView, VcDateView
class CvsCommit(Method):
'''diff the current file with the version in CVS'''
args = [arg("msg", t=type(""), p="Commit Message: ",
h="commit message to send to CVS")]
regex = re.compile('^new revision: ([0-9.]+); previous revision: ([0-9.]+)$')
def _execute(self, w, **vargs):
if not hasattr(w.buffer, 'path'):
w.set_error("Buffer has no corresponding file")
return
cwd = os.getcwd() + os.path.sep
path = w.buffer.path
if path.startswith(cwd):
path = path[len(cwd):]
cmd = ["cvs", "ci", "-m", vargs['msg'], path]
status, out, err = util.communicate(cmd)
if status != 0:
w.set_error("Problems with CVS commit: %d" % status)
w.application.data_buffer("*Commit*", err, switch_to=True)
return
for line in out.split('\n'):
m = self.regex.match(line)
if not m:
continue
w.set_error("Committed [%s -> %s]" % (m.group(2), m.group(1)))
return
w.set_error("Up-to-date")
class CvsStatus(Method):
regex1 = re.compile('^File: (.+?) *\tStatus: (.*?)$')
regex2 = re.compile('^ Working revision:\t([0-9\.]+)$')
regex3 = re.compile('^ Repository revision:\t([0-9\.]+)\t(.*)$')
regex4 = re.compile('^ Sticky Tag:\t\t\((.*)\)$')
regex5 = re.compile('^ Sticky Date:\t\t\((.*)\)$')
regex6 = re.compile('^ Sticky Options:\t\((.*)\)$')
def _execute(self, w, **vargs):
if not hasattr(w.buffer, 'path'):
w.set_error("Buffer has no corresponding file")
return
cwd = os.getcwd() + os.path.sep
path = w.buffer.path
if path.startswith(cwd):
path = path[len(cwd):]
#cmd = "cvs status %r" % path
cmd = ['cvs', 'status', path]
status, out, err = util.communicate(cmd)
if status != 0:
w.set_error("Problems with CVS status: %d" % status)
return
lines = out.split('\n')
if lines[0].startswith('cvs status: nothing known about '):
w.set_error('File is not under CVS control')
return
m = self.regex1.match(lines[1])
assert m, "regex1 %r" % lines[1]
ffile = m.group(1)
fstatus = m.group(2)
m = self.regex2.match(lines[3])
assert m, "regex2 %r" % lines[3]
wrev = m.group(1)
m = self.regex3.match(lines[4])
assert m, "regex3 %r" % lines[4]
rrev = m.group(1)
rpath = m.group(2)
m = self.regex4.match(lines[5])
assert m, "regex4 %r" % lines[5]
stag = m.group(1)
m = self.regex5.match(lines[6])
assert m, "regex5 %r" % lines[6]
sdate = m.group(1)
m = self.regex6.match(lines[7])
assert m, "regex6 %r" % lines[7]
soptions = m.group(1)
2009-03-04 14:44:41 -05:00
w.buffer.metadata['cvs-filename'] = ffile
w.buffer.metadata['cvs-status'] = fstatus
w.buffer.metadata['cvs-wrev'] = wrev
w.buffer.metadata['cvs-rrev'] = rrev
w.buffer.metadata['cvs-tag'] = stag
w.buffer.metadata['cvs-date'] = sdate
w.buffer.metadata['vc-info'] = '[cvs:%s/%s]' % (wrev, rrev)
tpl = (ffile, fstatus, wrev, rrev, stag, sdate, soptions)
w.set_error('%s %s %s/%s [%s|%s|%s]' % tpl)
2008-09-18 14:12:29 -04:00
class CvsLog(Method):
'''diff the current file with the version in CVS'''
def _execute(self, w, **vargs):
if not hasattr(w.buffer, 'path'):
w.set_error("Buffer has no corresponding file")
return
cwd = os.getcwd() + os.path.sep
path = w.buffer.path
if path.startswith(cwd):
path = path[len(cwd):]
#cmd = "cvs log %r" % path
cmd = ['cvs', 'log', path]
status, out, err = util.communicate(cmd)
w.application.data_buffer("*Log*", out, switch_to=True)
2008-09-18 14:12:29 -04:00
w.set_error("cvs log exited with %d" % status)
class CvsDiff(Method):
'''diff the current file with the version in CVS'''
def _execute(self, w, **vargs):
if not hasattr(w.buffer, 'path'):
w.set_error("Buffer has no corresponding file")
return
cwd = os.getcwd() + os.path.sep
path = w.buffer.path
if path.startswith(cwd):
path = path[len(cwd):]
#cmd = "cvs diff -u %r" % path
cmd = ['cvs', 'diff', '-u', path]
status, out, err = util.communicate(cmd)
if status == 0:
w.set_error("No difference found")
else:
w.application.data_buffer("*Diff*", out, switch_to=True, modename='diff')
w.set_error("Differences were found")
class CvsDiff2(Method):
'''diff the current file's contents with a version in CVS'''
rev_regex = re.compile('^[0-9]+\.[0-9]+$')
args = [arg("revision", t=type(""), p="Old Revision: ",
h="revision number")]
def _execute(self, w, **vargs):
if not hasattr(w.buffer, 'path'):
w.set_error("Buffer has no corresponding file")
return
rev = vargs['revision']
if not self.rev_regex.match(rev):
w.set_error("Could not parse revision: %r" % rev)
return
cwd = os.getcwd() + os.path.sep
path = w.buffer.path
if path.startswith(cwd):
path = path[len(cwd):]
#cmd = "cvs diff -r %s -u %r" % (rev, path)
cmd = ["cvs", "diff", "-r", rev, "-u", path]
status, out, err = util.communicate(cmd)
if status == 0:
w.set_error("No difference found")
else:
w.application.data_buffer("*Diff*", out, switch_to=True, modename='diff')
w.set_error("Differences were found")
class CvsDiff3(Method):
'''diff the current file with the version in CVS'''
rev_regex = re.compile('^[0-9]+\.[0-9]+$')
args = [arg("revision1", t=type(""), p="Old Revision: ", h='old revision number'),
arg("revision2", t=type(""), p="New Revision: ", h='new revision number')]
def _execute(self, w, **vargs):
if not hasattr(w.buffer, 'path'):
w.set_error("Buffer has no corresponding file")
return
rev1 = vargs['revision1']
if not self.rev_regex.match(rev1):
w.set_error("Could not parse revision1: %r" % rev)
return
rev2 = vargs['revision2']
if not self.rev_regex.match(rev2):
w.set_error("Could not parse revision2: %r" % rev)
return
cwd = os.getcwd() + os.path.sep
path = w.buffer.path
if path.startswith(cwd):
path = path[len(cwd):]
#cmd = "cvs diff -r %s -r %s -u %r" % (rev1, rev2, path)
cmd = ["cvs", "diff", "-r", rev1, "-r", rev2, "-u", path]
status, out, err = util.communicate(cmd)
if status == 0:
w.set_error("No difference found")
else:
w.application.data_buffer("*Diff*", out, switch_to=True, modename='diff')
w.set_error("Differences were found")
class CvsBlame(Method):
'''show blame output for the current version in CVS'''
line_re = re.compile('^([0-9.]+) +\(*([a-zA-Z0-9_]+) +([-0-9A-Za-z]+)\): (.*)$')
def _get_path(self, w, **vargs):
cwd = os.getcwd() + os.path.sep
path = w.buffer.path
if path.startswith(cwd):
path = path[len(cwd):]
return path
def _get_cmd(self, w, **vargs):
path = self._get_path(w, **vargs)
return ("/usr/bin/cvs", 'annotate', path)
def _execute(self, w, **vargs):
if not hasattr(w.buffer, 'path'):
w.set_error("Buffer has no corresponding file")
return
cmd = self._get_cmd(w, **vargs)
status, out, err = util.communicate(cmd)
linetokens = []
max_rev = 0
max_user = 0
for line in out.split('\n'):
if not line:
continue
m = self.line_re.match(line)
if not m:
raise Exception(repr(line))
(rev, user, date, content) = m.groups()
max_rev = max(max_rev, len(rev))
max_user = max(max_user, len(user))
linetokens.append([rev, user, date, content, []])
lines = [x[3] for x in linetokens]
if w.mode.grammar:
lexer = lex.Lexer(w.mode, w.mode.grammar)
lextokens = [[] for l in lines]
for t in lexer.lex(lines):
linetokens[t.y][4].append(t)
lines = []
for linetoken in linetokens:
(rev, user, date, content, lextokens) = linetoken
prefix = '[b:d:*]%-8s [c:d:*]%-10s [b:d:*]%10s[d:d:*]' % (rev, user, date)
if lextokens:
suffixes = []
for lt in lextokens:
s = lt.string.replace('\\', '\\\\')
s = s.replace('[', '\\[').replace(']', '\\]')
suffixes.append('[%s:%s:*]%s' % (lt.color[0], lt.color[1], s))
suffix = ''.join(suffixes)
else:
suffix = content + '\n'
lines.append('%s %s' % (prefix, suffix))
data = ''.join(lines)
if status == 0:
w.application.color_data_buffer("*Blame*", data, switch_to=True)
else:
w.set_error("There was an error (%s)" % (status))
class CvsBlame2(CvsBlame):
'''show blame output for the given version in CVS'''
args = [arg("revision", t=type(""), p="Revision: ", h="revision number")]
line_re = re.compile('^([0-9.]+) +\(*([a-zA-Z0-9_]+) +([-0-9A-Za-z]+)\): (.*)$')
def _get_cmd(self, w, **vargs):
path = self._get_path(w, **vargs)
return ("/usr/bin/cvs", 'annotate', '-r', vargs['revision'], path)
class CvsRevView(VcRevView):
'''show blame output for the current version in CVS'''
args = [arg("revision", t=type(""), p="Revision: ", h="revision number")]
namebase = 'CVS'
_is_method = True
def _get_cmd(self, w, **vargs):
path = self._get_path(w, **vargs)
return ("/usr/bin/cvs", 'up', '-p', '-r', vargs['revision'], path)
class CvsDateView(VcDateView):
'''show blame output for the current version in CVS'''
args = [arg("date", t=type(""), p="Date: ", h="date specifier")]
namebase = 'CVS'
_is_method = True
def _get_cmd(self, w, **vargs):
path = self._get_path(w, **vargs)
return ("/usr/bin/cvs", 'up', '-p', '-D', vargs['date'], path)