pmacs3/method/svn.py

233 lines
8.2 KiB
Python

import os, commands, re, sets, tempfile
from subprocess import Popen, PIPE, STDOUT
import buffer, default, dirutil, lex, regex, util, window
from point import Point
from method import DATATYPES, Method, Argument
class SvnCommit(Method):
'''diff the current file with the version in SVN'''
args = [Argument("msg", type=type(""), prompt="Commit Message: ")]
regex = re.compile(r'^Committed 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 = "svn ci -m %r %r" % (vargs['msg'], path)
(status, data) = commands.getstatusoutput(cmd)
status = status >> 8
lines = data.split('\n')
if status == 0:
try:
for line in lines:
m = self.regex.match(line)
if m:
w.set_error("Committed [%s]" % (m.group(1)))
return
except:
pass
w.set_error("Problems with SVN commit: %d" % status)
w.application.data_buffer("*Commit*", repr(lines), switch_to=True)
class SvnStatus(Method):
column = {
' ': 'Unmodified',
'A': 'Added',
'C': 'Conflicted',
'D': 'Deleted',
'I': 'Ignored',
'M': 'Modified',
'R': 'Replaced',
'X': 'External',
'?': 'Unknown',
'!': 'Missing',
'~': 'Obstructed',
}
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 = "svn status -v %r" % path
(status, data) = commands.getstatusoutput(cmd)
status = status >> 8
if status != 0:
w.set_error("Problems with 'svn status': %d" % status)
return
c = data[0]
status = self.column.get(c, 'Error (%s)' % c)
fields = data[6:].split()
try:
(rrev, lrev, lauthor, filename) = fields
except:
raise Exception, '%r %r' % (fields, data[6:])
w.set_error('%s %s %s/%s [%s]' % (filename, status, rrev, lrev, lauthor))
class SvnDiff(Method):
'''diff the current file with the version in SVN'''
def _execute(self, w, **vargs):
if not hasattr(w.buffer, 'path'):
w.set_error("Buffer has no corresponding file")
return
cmd = "svn diff %r" % w.buffer.path
(status, data) = commands.getstatusoutput(cmd)
if status == 0:
if data:
w.application.data_buffer("*Diff*", data, switch_to=True, modename='diff')
w.set_error("Differences were found")
else:
w.set_error("No difference found")
else:
w.set_error("There was an error (%s)" % (status))
class SvnDiff2(Method):
'''diff the current file with the version in SVN'''
rev_regex = re.compile('^[0-9]+$')
args = [Argument("revision", type=type(""), prompt="Old Revision: ")]
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 = "svn diff -r %s %r" % (rev, path)
(status, data) = commands.getstatusoutput(cmd)
status = status >> 8
if data:
w.application.data_buffer("*Diff*", data, switch_to=True, modename='diff')
w.set_error("Differences were found")
else:
w.set_error("No difference found")
class SvnDiff3(Method):
'''diff the current file with the version in SVN'''
rev_regex = re.compile('^[0-9]+$')
args = [Argument("revision1", type=type(""), prompt="Old Revision: "),
Argument("revision2", type=type(""), prompt="New Revision: ")]
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 = "svn diff -r %s -r %s %r" % (rev1, rev2, path)
(status, data) = commands.getstatusoutput(cmd)
status = status >> 8
if data:
w.application.data_buffer("*Diff*", data, switch_to=True, modename='diff')
w.set_error("Differences were found")
else:
w.set_error("No difference found")
class SvnBlame(Method):
'''show blame output for the current version in SVN'''
line_re = re.compile('^ *(\d+) *([a-zA-Z0-9_]+) *([-0-9]+) *([:0-9]+) *(-\d{4}) *\(([^\)]+)\) (.*)$')
def _execute(self, w, **vargs):
if not hasattr(w.buffer, 'path'):
w.set_error("Buffer has no corresponding file")
return
cmd = ("/usr/bin/svn", 'blame', '-v', w.buffer.path)
pipe = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
lines = []
for line in pipe.stdout:
m = self.line_re.match(line)
if not m:
raise Exception, line
(rev, user, date, t, tz, vdate, content) = m.groups()
lines.append("%-4s %-10s %10s %s\n" % (rev, user, date, content))
data = ''.join(lines)
status = pipe.wait() >> 8
if status == 0:
w.application.data_buffer("*Blame*", data, switch_to=True, modename='blame')
else:
w.set_error("There was an error (%s)" % (status))
class SvnBlame2(Method):
'''show blame output for the current version in SVN'''
line_re = re.compile('^ *(\d+) *([a-zA-Z0-9_]+) *([-0-9]+) *([:0-9]+) *(-\d{4}) *\(([^\)]+)\) (.*)\n$')
def _execute(self, w, **vargs):
if not hasattr(w.buffer, 'path'):
w.set_error("Buffer has no corresponding file")
return
cmd = ("/usr/bin/svn", 'blame', '-v', w.buffer.path)
pipe = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
linetokens = []
for line in pipe.stdout:
m = self.line_re.match(line)
if not m:
raise Exception, line
(rev, user, date, t, tz, vdate, content) = m.groups()
linetokens.append([rev, user, date, content, []])
status = pipe.wait() >> 8
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:*]%-4s [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))