Revert "... and stop calling the blobtracker"
[trackgit.git] / patch.py
blob5e09aa8f10e0fb59b0e2b898c7a9d730fec71435
1 #!/usr/bin/python
3 import re
4 import sys
5 import os.path
7 import db
8 import dbcache
9 from git import git
11 _boundary_line_regex = re.compile(r'^---')
12 _diff_head_regex = re.compile(r'^diff --git a/(.*) b/(.*)$')
13 _index_line_regex = re.compile(r'^index ([a-f0-9]{7,})\.\.([a-f0-9]{7,}) ')
14 _all_zeros_regex = re.compile(r'^0+$')
16 class PatchError(Exception):
17 pass
19 class Patch(object):
21 def __init__(self, data):
22 self.blobs_pre = set()
23 self.blobs_post = set()
24 self.missing_files = False
25 self.data = data
26 self.notes = None
27 self._parse(data)
29 def _parse(self, data):
30 boundary_seen = False
31 diff_seen = False
32 filename = None
33 notes = []
34 for line in data.splitlines(True):
35 if _boundary_line_regex.match(line):
36 boundary_seen = True
37 continue
38 m = _diff_head_regex.match(line)
39 if m:
40 diff_seen = True
41 # at least the 'pre' filename should exist
42 filename = m.group(1)
43 continue
44 if diff_seen:
45 m = _index_line_regex.match(line)
46 if m:
47 if not _all_zeros_regex.match(m.group(1)):
48 self.blobs_pre.add(m.group(1))
49 self._check_file(filename)
50 self.blobs_post.add(m.group(2))
51 continue
52 if boundary_seen:
53 notes.append(line)
54 if diff_seen:
55 self.notes = ''.join(notes)
57 def _check_file(self, name):
58 if os.path.basename(name) not in dbcache.file_cache:
59 self.missing_files = True
60 print 'patch for missing file "%s"' % name
62 def apply(self):
63 output, ret = git('am', '-3', input=self.data)
64 if ret != 0:
65 # clean up
66 git('am', '-3', '--abort')
67 git('reset', '--hard')
68 raise PatchError()
69 return output
71 def fast_patch_id(self):
72 data = self.data
73 try:
74 i = data.rfind('\n-- \n')
75 data = data[:i+1]
76 except IndexError:
77 pass
78 output = git('patch-id', input=data)[0]
79 if not output:
80 return
81 try:
82 patch_id, commit_id = output.split()
83 return patch_id
84 except ValueError:
85 return