def __call__(self, output, path, revision): # pylint:disable=W if not output: return None blame = Blame(revision, path) commit_info = defaultdict(dict) region_info = None for line in output.splitlines(): # Sample: ec3ed6... 2 1 7. match = REGION_START_COUNT_PATTERN.match(line) if match: if region_info: blame.AddRegion( Region( region_info.start, region_info.count, region_info.revision, commit_info[region_info.revision]['author_name'], commit_info[region_info.revision]['author_email'], commit_info[region_info.revision]['author_time'])) region_info = RegionInfo(start=int(match.group(2)), count=int(match.group(3)), revision=match.group(1)) elif region_info: # Sample: author [email protected]. if AUTHOR_NAME_PATTERN.match(line): commit_info[region_info.revision]['author_name'] = ( AUTHOR_NAME_PATTERN.match(line).group(1)) # Sample: author-mail <[email protected]@2eff-a529-9590-31e7-b00076f81>. elif AUTHOR_MAIL_PATTERN.match(line): commit_info[region_info.revision]['author_email'] = ( commit_util.NormalizeEmail( AUTHOR_MAIL_PATTERN.match(line).group(1).replace( '<', '').replace('>', ''))) # Sample: author-time 1311863160. elif AUTHOR_TIME_PATTERN.match(line): commit_info[region_info.revision]['author_time'] = ( AUTHOR_TIME_PATTERN.match(line).group(1)) # Sample: author-tz +0800. elif AUTHOR_TIMEZONE_PATTERN.match(line): time_zone = time_util.TimeZoneInfo( AUTHOR_TIMEZONE_PATTERN.match(line).group(1)) commit_info[region_info.revision]['author_time'] = ( time_zone.LocalToUTC( datetime.fromtimestamp( int(commit_info[region_info.revision] ['author_time'])))) if region_info: blame.AddRegion( Region(region_info.start, region_info.count, region_info.revision, commit_info[region_info.revision]['author_name'], commit_info[region_info.revision]['author_email'], commit_info[region_info.revision]['author_time'])) return blame if blame else None
def testAddRegions(self): blame1 = Blame('def', 'a/c.cc') blame1.AddRegions([self.REGION1, self.REGION2]) blame2 = Blame('def', 'a/c.cc') blame2.AddRegion(self.REGION1) blame2.AddRegion(self.REGION2) self.assertEqual(blame1, blame2)
def testGetSuspectedRevisions(self): region_1 = Region(1, 5, 'r1', 'a', '*****@*****.**', '2017-08-11 19:38:42') region_2 = Region(6, 10, 'r2', 'b', '*****@*****.**', '2017-08-12 19:38:42') blame = Blame('r2', 'a.cc') blame.AddRegion(region_1) blame.AddRegion(region_2) revision_range = ['r2', 'r3'] expected_suspected_revisions = ['r2'] self.assertEqual( expected_suspected_revisions, heuristic_analysis.GetSuspectedRevisions(blame, revision_range)) self.assertEqual([], heuristic_analysis.GetSuspectedRevisions([], ['r1'])) self.assertEqual([], heuristic_analysis.GetSuspectedRevisions( blame, ['r4'])) self.assertEqual([], heuristic_analysis.GetSuspectedRevisions(None, None))
def GetBlame(self, path, revision): """Returns blame of the file at ``path`` of the given revision.""" url = '%s/+blame/%s/%s' % (self.repo_url, revision, path) data = self._SendRequestForJsonResponse(url) if not data: return None blame = Blame(revision, path) for region in data['regions']: author_time = self._GetDateTimeFromString(region['author']['time'], '%Y-%m-%d %H:%M:%S') blame.AddRegion( Region(region['start'], region['count'], region['commit'], region['author']['name'], commit_util.NormalizeEmail(region['author']['email']), author_time)) return blame