Files
ChocolateyPackages/EthanBrown.SublimeText2.GitPackages/tools/PackageCache/SideBarGit/SideBarGitGutterDiff.txt
2013-04-04 08:55:33 -04:00

170 lines
4.8 KiB
Plaintext

import sublime
import sublime_plugin
import functools
import threading
import subprocess
import sys
import re
import tempfile
import codecs
import os
import time
from SideBarGit import SideBarGit
from SideBarItem import SideBarItem
from Utils import Object
Object.running = False
Object.timing = time.time()
class SideBarGitGutterDiff(sublime_plugin.EventListener):
def on_load(self, view):
self.run(view)
def on_modified(self, view):
now = time.time()
if now - Object.timing > 0.1:
Object.timing = now
self.run(view)
else:
Object.timing = now
def on_post_save(self, view):
self.run(view)
def run(self, view):
if Object.running == False and view.file_name() != None and view.file_name() != '':
Object.running = True
# cache file repository ( if any )
if not view.settings().has('SideBarGitGutterRepository'):
item = SideBarItem(view.file_name(), False)
_item = SideBarItem(view.file_name(), False)
repos = SideBarGit().getSelectedRepos([_item])
if len(repos) > 0:
view.settings().set('SideBarGitGutterRepository', repos[0].repository.path())
view.settings().set('SideBarGitGutterCWD', repos[0].repository.path())
view.settings().set('SideBarGitGutterPath', item.forCwdSystemPathRelativeFrom(repos[0].repository.path()))
else:
view.settings().set('SideBarGitGutterRepository', '')
# if in a repo check for modifications
repo = view.settings().get('SideBarGitGutterRepository')
if repo != '':
SideBarGitGutterDiffThread(
view,
repo,
view.settings().get('SideBarGitGutterCWD'),
view.settings().get('SideBarGitGutterPath'),
view.substr(sublime.Region(0, view.size()))
).start()
else:
Object.running = False
class SideBarGitGutterDiffThread(threading.Thread):
def __init__(self, view, repo, cwd, path, content):
threading.Thread.__init__(self)
self.view = view
self.repo = repo
self.cwd = cwd
self.path = path
self.content = content
def run(self):
tmp = tempfile.NamedTemporaryFile(delete=False)
codecs.open(tmp.name, 'w+', 'utf-8').write(self.content)
comand = ['git', 'diff', '-p', '--unified=0', '--no-color', '--ignore-all-space', '--ignore-space-at-eol', '--ignore-space-change', 'HEAD:'+self.path, tmp.name]
process = subprocess.Popen(
comand,
cwd=self.cwd,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
shell=sys.platform == 'win32',
universal_newlines=True)
stdout, stderr = process.communicate()
if stdout != '' and stdout.find('fatal:') != 0:
hunk = re.finditer('\n@@ -([0-9]+),?([0-9]*) \+([0-9]+),?([0-9]*) @@', stdout)
additions = []
deletions = []
changes = []
for change in hunk:
g = []
for group in change.groups():
if group == '':
g.append(1)
else:
g.append(int(group))
deleted = g[1]
added = g[3]
if deleted == added and added == 1:
changes.append([g[2]-1, g[2]]);
else:
if deleted > 0:
if deleted == 1:
if added > deleted:
deletions.append([g[2], g[2]+deleted-added]);
else:
deletions.append([g[2], g[2]+1]);
else:
deletions.append([g[2]-1, g[2]+deleted-1])
if added > 0:
if added == 1:
additions.append([g[2], g[2]+added]);
else:
additions.append([g[2]-1, g[2]+added-1])
tmp.close();
os.remove(tmp.name)
sublime.set_timeout(functools.partial(self.add_regions, additions, deletions, changes), 0)
else:
tmp.close();
os.remove(tmp.name)
sublime.set_timeout(functools.partial(self.erase_regions), 0)
if stdout.find('fatal:'):
sublime.set_timeout(functools.partial(self.mark_not_in_a_repository), 0)
Object.running = False
def add_regions(self, additions, deletions, changes):
self.erase_regions()
rs = []
for r in additions:
while r[0] != r[1]:
rs.append(sublime.Region(self.view.text_point(r[0], 0)))
r[0] = r[0]+1
if len(rs):
self.view.add_regions("git.diff.additions", rs, "number", "dot", sublime.HIDDEN)
rs = []
for r in deletions:
while r[0] != r[1]:
rs.append(sublime.Region(self.view.text_point(r[0], 0)))
r[0] = r[0]+1
if len(rs):
self.view.add_regions("git.diff.deletions", rs, "entity.name.class", "dot", sublime.HIDDEN)
rs = []
for r in changes:
while r[0] != r[1]:
rs.append(sublime.Region(self.view.text_point(r[0], 0)))
r[0] = r[0]+1
if len(rs):
self.view.add_regions("git.diff.changes", rs, "string", "dot", sublime.HIDDEN)
def erase_regions(self):
self.view.erase_regions("git.diff.additions")
self.view.erase_regions("git.diff.deletions")
self.view.erase_regions("git.diff.changes")
def mark_not_in_a_repository(self):
self.view.settings().set('SideBarGitGutterRepository', '')