-
Notifications
You must be signed in to change notification settings - Fork 0
/
git-vd
executable file
·92 lines (78 loc) · 2.58 KB
/
git-vd
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
#!/usr/bin/env python
import os
import subprocess
import os.path
import shutil
import sys
import tempfile
def exec_stdout(cmd):
return os.popen(cmd).read()
def grab_revision(repo_topdir, git_path, rev, dest_topdir):
dest_path = os.path.join(dest_topdir, git_path)
dest_dirname = os.path.dirname(dest_path)
if not os.path.exists(dest_dirname):
os.makedirs(dest_dirname)
if rev == '':
src_path = os.path.join(repo_topdir, git_path)
shutil.copyfile(src_path, dest_path)
else:
with open(dest_path, 'w') as f:
subprocess.call(['git', 'cat-file', 'blob', rev + ':' + git_path], stdout=f)
class DirDiff:
def __init__(self, left_rev, right_rev):
""""empty rev means work tree"""
self.repo_topdir = exec_stdout('git rev-parse --show-cdup').rstrip("\n")
self.left_rev = left_rev
self.right_rev = right_rev
def prepare_dirs(self):
self.left_dir = tempfile.mkdtemp()
self.right_dir = tempfile.mkdtemp()
if not self.right_rev:
diff_cmd = 'git diff-index -z --diff-filter=ADM --no-renames ' + self.left_rev
else:
diff_cmd = 'git diff-tree -z -r --diff-filter=ADM --no-renames %s %s' % (self.left_rev, self.right_rev)
diff = exec_stdout(diff_cmd)
entries = diff.split("\0")
i = 0
while i < len(entries) - 1:
status, path = entries[i], entries[i+1]
i += 2
mode = status[97]
if mode == 'D':
self.process_deleted(path)
elif mode == 'A':
self.process_added(path)
elif mode == 'M':
self.process_modified(path)
def delete_dirs(self):
shutil.rmtree(self.left_dir)
shutil.rmtree(self.right_dir)
def _grab_left_version(self, path):
grab_revision(self.repo_topdir, path, self.left_rev, self.left_dir)
def _grab_right_version(self, path):
grab_revision(self.repo_topdir, path, self.right_rev, self.right_dir)
def process_deleted(self, path):
self._grab_left_version(path)
def process_added(self, path):
self._grab_right_version(path)
def process_modified(self, path):
self._grab_right_version(path)
self._grab_left_version(path)
def kdiff3(self):
try:
self.prepare_dirs()
print self.left_dir, self.right_dir
os.system('kdiff3 %s %s' % (self.left_dir, self.right_dir))
finally:
self.delete_dirs()
if __name__ == "__main__":
if exec_stdout('git rev-parse --is-inside-work-tree').rstrip("\n") != "true":
print "Not inside a work tree."
else:
left = "HEAD"
right = ""
if len(sys.argv) >= 2:
left = sys.argv[1]
if len(sys.argv) >= 3:
right = sys.argv[2]
DirDiff(left, right).kdiff3()