@@ -15,6 +15,12 @@ class Blob(object):
15
15
"""A Blob encapsulates a git blob object"""
16
16
DEFAULT_MIME_TYPE = "text/plain"
17
17
18
+ # precompiled regex
19
+ re_whitespace = re .compile (r'\s+' )
20
+ re_hexsha_only = re .compile ('^[0-9A-Fa-f]{40}$' )
21
+ re_author_committer_start = re .compile (r'^(author|committer)' )
22
+ re_tab_full_line = re .compile (r'^\t(.*)$' )
23
+
18
24
def __init__ (self , repo , id , mode = None , path = None ):
19
25
"""
20
26
Create an unbaked Blob containing just the specified attributes
@@ -112,49 +118,68 @@ def blame(cls, repo, commit, file):
112
118
info = None
113
119
114
120
for line in data .splitlines ():
115
- parts = re .split (r'\s+' , line , 1 )
116
- if re .search (r'^[0-9A-Fa-f]{40}$' , parts [0 ]):
117
- if re .search (r'^([0-9A-Fa-f]{40}) (\d+) (\d+) (\d+)$' , line ):
118
- m = re .search (r'^([0-9A-Fa-f]{40}) (\d+) (\d+) (\d+)$' , line )
119
- id , origin_line , final_line , group_lines = m .groups ()
120
- info = {'id' : id }
121
- blames .append ([None , []])
122
- elif re .search (r'^([0-9A-Fa-f]{40}) (\d+) (\d+)$' , line ):
123
- m = re .search (r'^([0-9A-Fa-f]{40}) (\d+) (\d+)$' , line )
124
- id , origin_line , final_line = m .groups ()
125
- info = {'id' : id }
126
- elif re .search (r'^(author|committer)' , parts [0 ]):
127
- if re .search (r'^(.+)-mail$' , parts [0 ]):
128
- m = re .search (r'^(.+)-mail$' , parts [0 ])
129
- info ["%s_email" % m .groups ()[0 ]] = parts [- 1 ]
130
- elif re .search (r'^(.+)-time$' , parts [0 ]):
131
- m = re .search (r'^(.+)-time$' , parts [0 ])
132
- info ["%s_date" % m .groups ()[0 ]] = time .gmtime (int (parts [- 1 ]))
133
- elif re .search (r'^(author|committer)$' , parts [0 ]):
134
- m = re .search (r'^(author|committer)$' , parts [0 ])
135
- info [m .groups ()[0 ]] = parts [- 1 ]
136
- elif re .search (r'^filename' , parts [0 ]):
137
- info ['filename' ] = parts [- 1 ]
138
- elif re .search (r'^summary' , parts [0 ]):
139
- info ['summary' ] = parts [- 1 ]
140
- elif parts [0 ] == '' :
141
- if info :
142
- c = commits .has_key (info ['id' ]) and commits [info ['id' ]]
143
- if not c :
144
- c = Commit (repo , id = info ['id' ],
145
- author = Actor .from_string (info ['author' ] + ' ' + info ['author_email' ]),
146
- authored_date = info ['author_date' ],
147
- committer = Actor .from_string (info ['committer' ] + ' ' + info ['committer_email' ]),
148
- committed_date = info ['committer_date' ],
149
- message = info ['summary' ])
150
- commits [info ['id' ]] = c
151
-
152
- m = re .search (r'^\t(.*)$' , line )
153
- text , = m .groups ()
154
- blames [- 1 ][0 ] = c
155
- blames [- 1 ][1 ].append ( text )
156
- info = None
157
-
121
+ parts = cls .re_whitespace .split (line , 1 )
122
+ firstpart = parts [0 ]
123
+ if cls .re_hexsha_only .search (firstpart ):
124
+ # handles
125
+ # 634396b2f541a9f2d58b00be1a07f0c358b999b3 1 1 7 - indicates blame-data start
126
+ # 634396b2f541a9f2d58b00be1a07f0c358b999b3 2 2
127
+ digits = parts [- 1 ].split (" " )
128
+ if len (digits ) == 3 :
129
+ info = {'id' : firstpart }
130
+ blames .append ([None , []])
131
+ # END blame data initialization
132
+ else :
133
+ m = cls .re_author_committer_start .search (firstpart )
134
+ if m :
135
+ # handles:
136
+ # author Tom Preston-Werner
137
+
138
+ # author-time 1192271832
139
+ # author-tz -0700
140
+ # committer Tom Preston-Werner
141
+ # committer-mail <[email protected] >
142
+ # committer-time 1192271832
143
+ # committer-tz -0700 - IGNORED BY US
144
+ role = m .group (0 )
145
+ if firstpart .endswith ('-mail' ):
146
+ info ["%s_email" % role ] = parts [- 1 ]
147
+ elif firstpart .endswith ('-time' ):
148
+ info ["%s_date" % role ] = time .gmtime (int (parts [- 1 ]))
149
+ elif role == firstpart :
150
+ info [role ] = parts [- 1 ]
151
+ # END distinguish mail,time,name
152
+ else :
153
+ # handle
154
+ # filename lib/grit.rb
155
+ # summary add Blob
156
+ # <and rest>
157
+ if firstpart .startswith ('filename' ):
158
+ info ['filename' ] = parts [- 1 ]
159
+ elif firstpart .startswith ('summary' ):
160
+ info ['summary' ] = parts [- 1 ]
161
+ elif firstpart == '' :
162
+ if info :
163
+ sha = info ['id' ]
164
+ c = commits .get (sha )
165
+ if c is None :
166
+ c = Commit ( repo , id = sha ,
167
+ author = Actor .from_string (info ['author' ] + ' ' + info ['author_email' ]),
168
+ authored_date = info ['author_date' ],
169
+ committer = Actor .from_string (info ['committer' ] + ' ' + info ['committer_email' ]),
170
+ committed_date = info ['committer_date' ],
171
+ message = info ['summary' ])
172
+ commits [sha ] = c
173
+ # END if commit objects needs initial creation
174
+ m = cls .re_tab_full_line .search (line )
175
+ text , = m .groups ()
176
+ blames [- 1 ][0 ] = c
177
+ blames [- 1 ][1 ].append ( text )
178
+ info = None
179
+ # END if we collected commit info
180
+ # END distinguish filename,summary,rest
181
+ # END distinguish author|committer vs filename,summary,rest
182
+ # END distinguish hexsha vs other information
158
183
return blames
159
184
160
185
def __repr__ (self ):
0 commit comments