📄 blame.py
字号:
else: # Symbolic tag or specific revision number specified. revision = self.map_tag_to_revision(opt_rev) if revision == '': raise RuntimeError, 'error: -r: No such revision: ' + opt_rev # The primordial revision is not always 1.1! Go find it. primordial = revision while self.prev_revision.get(primordial): primordial = self.prev_revision[primordial] # Don't display file at all, if -m option is specified and no # changes have been made in the specified file. if opt_m_timestamp and self.timestamp[revision] < opt_m_timestamp: return '' # Figure out how many lines were in the primordial, i.e. version 1.1, # check-in by moving backward in time from the head revision to the # first revision. line_count = 0 if self.revision_deltatext.get(self.head_revision): tmp_array = self.deltatext_split(self.head_revision) line_count = len(tmp_array) skip = 0 rev = self.prev_revision.get(self.head_revision) while rev: diffs = self.deltatext_split(rev) for command in diffs: dmatch = self.d_command.match(command) amatch = self.a_command.match(command) if skip > 0: # Skip insertion lines from a prior "a" command skip = skip - 1 elif dmatch: # "d" - Delete command start_line = string.atoi(dmatch.group(1)) count = string.atoi(dmatch.group(2)) line_count = line_count - count elif amatch: # "a" - Add command start_line = string.atoi(amatch.group(1)) count = string.atoi(amatch.group(2)) skip = count; line_count = line_count + count else: raise RuntimeError, 'error: illegal RCS file' rev = self.prev_revision.get(rev) # Now, play the delta edit commands *backwards* from the primordial # revision forward, but rather than applying the deltas to the text of # each revision, apply the changes to an array of revision numbers. # This creates a "revision map" -- an array where each element # represents a line of text in the given revision but contains only # the revision number in which the line was introduced rather than # the line text itself. # # Note: These are backward deltas for revisions on the trunk and # forward deltas for branch revisions. # Create initial revision map for primordial version. self.revision_map = [primordial] * line_count ancestors = [revision, ] + self.ancestor_revisions(revision) ancestors = ancestors[:-1] # Remove "1.1" last_revision = primordial ancestors.reverse() for revision in ancestors: is_trunk_revision = self.trunk_rev.match(revision) is not None if is_trunk_revision: diffs = self.deltatext_split(last_revision) # Revisions on the trunk specify deltas that transform a # revision into an earlier revision, so invert the translation # of the 'diff' commands. for command in diffs: if skip > 0: skip = skip - 1 else: dmatch = self.d_command.match(command) amatch = self.a_command.match(command) if dmatch: start_line = string.atoi(dmatch.group(1)) count = string.atoi(dmatch.group(2)) temp = [] while count > 0: temp.append(revision) count = count - 1 self.revision_map = (self.revision_map[:start_line - 1] + temp + self.revision_map[start_line - 1:]) elif amatch: start_line = string.atoi(amatch.group(1)) count = string.atoi(amatch.group(2)) del self.revision_map[start_line:start_line + count] skip = count else: raise RuntimeError, 'Error parsing diff commands' else: # Revisions on a branch are arranged backwards from those on # the trunk. They specify deltas that transform a revision # into a later revision. adjust = 0 diffs = self.deltatext_split(revision) for command in diffs: if skip > 0: skip = skip - 1 else: dmatch = self.d_command.match(command) amatch = self.a_command.match(command) if dmatch: start_line = string.atoi(dmatch.group(1)) count = string.atoi(dmatch.group(2)) del self.revision_map[start_line + adjust - 1:start_line + adjust - 1 + count] adjust = adjust - count elif amatch: start_line = string.atoi(amatch.group(1)) count = string.atoi(amatch.group(2)) skip = count temp = [] while count > 0: temp.append(revision) count = count - 1 self.revision_map = (self.revision_map[:start_line + adjust] + temp + self.revision_map[start_line + adjust:]) adjust = adjust + skip else: raise RuntimeError, 'Error parsing diff commands' last_revision = revision return revisionre_includes = re.compile('\\#(\\s*)include(\\s*)"(.*?)"')re_filename = re.compile('(.*[\\\\/])?(.+)')def link_includes(text, root, rcs_path, sticky = None): match = re_includes.match(text) if match: incfile = match.group(3) for rel_path in ('', 'Attic', '..'): trial_root = os.path.join(rcs_path, rel_path) file = os.path.join(root, trial_root) file = os.path.normpath(os.path.join(file, incfile + ',v')) if os.access(file, os.F_OK): url = os.path.join(rel_path, incfile) if sticky: url = url + '?' + sticky return '#%sinclude%s"<a href="%s">%s</a>"' % \ (match.group(1), match.group(2), url, incfile) return textdef make_html(root, rcs_path, opt_rev = None, sticky = None): filename = os.path.join(root, rcs_path) parser = CVSParser() revision = parser.parse_cvs_file(filename, opt_rev) count = len(parser.revision_map) text = parser.extract_revision(revision) if len(text) != count: raise RuntimeError, 'Internal consistency error' match = re_filename.match(rcs_path) if not match: raise RuntimeError, 'Unable to parse filename' file_head = match.group(1) file_tail = match.group(2) open_table_tag = '<table border=0 cellpadding=0 cellspacing=0 width="100%">' startOfRow = '<tr><td colspan=3%s><pre>' endOfRow = '</td></tr>' print open_table_tag + (startOfRow % '') if count == 0: count = 1 line_num_width = int(math.log10(count)) + 1 revision_width = 3 author_width = 5 line = 0 usedlog = {} usedlog[revision] = 1 old_revision = 0 row_color = '' lines_in_table = 0 inMark = 0 rev_count = 0 for revision in parser.revision_map: thisline = text[line] line = line + 1 usedlog[revision] = 1 line_in_table = lines_in_table + 1 # Escape HTML meta-characters thisline = cgi.escape(thisline) # Add a link to traverse to included files if 1: # opt_includes thisline = link_includes(thisline, root, file_head, sticky) output = '' # Highlight lines #mark_cmd; #if (defined($mark_cmd = $mark_line{$line}) and mark_cmd != 'end': # output = output + endOfRow + '<tr><td bgcolor=LIGHTGREEN width="100%"><pre>' # inMark = 1 if old_revision != revision and line != 1: if row_color == '': row_color = ' bgcolor="#e7e7e7"' else: row_color = '' if not inMark: if lines_in_table > 100: output = output + endOfRow + '</table>' + open_table_tag + (startOfRow % row_color) lines_in_table = 0 else: output = output + endOfRow + (startOfRow % row_color) elif lines_in_table > 200 and not inMark: output = output + endOfRow + '</table>' + open_table_tag + (startOfRow % row_color) lines_in_table = 0 output = output + "<a name=%d></a>" % (line, ) if 1: # opt_line_nums output = output + ('%%%dd' % (line_num_width, )) % (line, ) if old_revision != revision or rev_count > 20: revision_width = max(revision_width, len(revision)) if parser.prev_revision.get(revision): fname = file_tail[:-2] # strip the ",v" url = '%s.diff?r1=%s&r2=%s' % \ (fname, parser.prev_revision[revision], revision) if sticky: url = url + '&' + sticky output = output + ' <a href="%s"' % (url, ) if 0: # use_layers output = output + " onmouseover='return log(event,\"%s\",\"%s\");'" % ( parser.prev_revision[revision], revision) output = output + ">" else: output = output + " " parser.prev_revision[revision] = '' author = parser.revision_author[revision] # $author =~ s/%.*$//; author_width = max(author_width, len(author)) output = output + ('%%-%ds ' % (author_width, )) % (author, ) output = output + revision if parser.prev_revision.get(revision): output = output + '</a>' output = output + (' ' * (revision_width - len(revision) + 1)) old_revision = revision rev_count = 0 else: output = output + ' ' + (' ' * (author_width + revision_width)) rev_count = rev_count + 1 output = output + thisline # Close the highlighted section #if (defined $mark_cmd and mark_cmd != 'begin'): # chop($output) # output = output + endOfRow + (startOfRow % row_color) # inMark = 0 print output print endOfRow + '</table>'def main(): if len(sys.argv) != 3: print 'USAGE: %s cvsroot rcs-file' % sys.argv[0] sys.exit(1) make_html(sys.argv[1], sys.argv[2])if __name__ == '__main__': main()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -