-
Notifications
You must be signed in to change notification settings - Fork 224
/
git_gutter_handler.py
116 lines (107 loc) · 3.91 KB
/
git_gutter_handler.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import git_helper
import os
import sublime
import subprocess
import re
from view_collection import ViewCollection
class GitGutterHandler:
def __init__(self, view):
self.view = view
self.git_temp_file = ViewCollection.git_tmp_file(self.view)
self.buf_temp_file = ViewCollection.buf_tmp_file(self.view)
if self.on_disk():
self.git_tree = git_helper.git_tree(self.view)
self.git_dir = git_helper.git_dir(self.git_tree)
self.git_path = git_helper.git_file_path(self.view, self.git_tree)
def on_disk(self):
# if the view is saved to disk
return self.view.file_name() is not None
def reset(self):
if self.on_disk() and self.git_path:
self.view.run_command('git_gutter')
def get_git_path(self):
return self.git_path
def update_buf_file(self):
chars = self.view.size()
region = sublime.Region(0, chars)
contents = self.view.substr(region).encode('utf-8')
contents = contents.replace('\r\n', '\n')
contents = contents.replace('\r', '\n')
f = open(self.buf_temp_file.name, 'w')
f.write(contents)
f.close()
def update_git_file(self):
# the git repo won't change that often
# so we can easily wait 5 seconds
# between updates for performance
if ViewCollection.git_time(self.view) > 5:
open(self.git_temp_file.name, 'w').close()
args = [
'git',
'--git-dir=' + self.git_dir,
'--work-tree=' + self.git_tree,
'show',
'HEAD:' + self.git_path,
]
try:
contents = self.run_command(args)
contents = contents.replace('\r\n', '\n')
contents = contents.replace('\r', '\n')
f = open(self.git_temp_file.name, 'w')
f.write(contents)
f.close()
ViewCollection.update_git_time(self.view)
except Exception:
pass
def process_diff(self, diff_str):
inserted = []
modified = []
deleted = []
pattern = re.compile(r'(\d+),?(\d*)(.)(\d+),?(\d*)')
lines = diff_str.splitlines()
for line in lines:
m = pattern.match(line)
if not m:
continue
kind = m.group(3)
original_line_start = int(m.group(1))
if len(m.group(2)) > 0:
original_line_end = int(m.group(2))
else:
original_line_end = original_line_start
line_start = int(m.group(4))
if len(m.group(5)) > 0:
line_end = int(m.group(5))
else:
line_end = line_start
if kind == 'c':
modified += range(line_start, line_end + 1)
elif kind == 'a':
inserted += range(line_start, line_end + 1)
elif kind == 'd':
if line == 1:
deleted.append(line_start)
else:
deleted.append(line_start + 1)
return (inserted, modified, deleted)
def diff(self):
if self.on_disk() and self.git_path:
self.update_git_file()
self.update_buf_file()
args = [
'diff',
self.git_temp_file.name,
self.buf_temp_file.name,
]
results = self.run_command(args)
return self.process_diff(results)
else:
return ([], [], [])
def run_command(self, args):
startupinfo = None
if os.name == 'nt':
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
proc = subprocess.Popen(args, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT, startupinfo=startupinfo)
return proc.stdout.read()