mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 03:44:55 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			131 lines
		
	
	
	
		
			3.2 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			131 lines
		
	
	
	
		
			3.2 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
#! /usr/bin/env python
 | 
						|
 | 
						|
"""Consolidate a bunch of CVS or RCS logs read from stdin.
 | 
						|
 | 
						|
Input should be the output of a CVS or RCS logging command, e.g.
 | 
						|
 | 
						|
    cvs log -rrelease14:
 | 
						|
 | 
						|
which dumps all log messages from release1.4 upwards (assuming that
 | 
						|
release 1.4 was tagged with tag 'release14').  Note the trailing
 | 
						|
colon!
 | 
						|
 | 
						|
This collects all the revision records and outputs them sorted by date
 | 
						|
rather than by file, collapsing duplicate revision record, i.e.,
 | 
						|
records with the same message for different files.
 | 
						|
 | 
						|
The -t option causes it to truncate (discard) the last revision log
 | 
						|
entry; this is useful when using something like the above cvs log
 | 
						|
command, which shows the revisions including the given tag, while you
 | 
						|
probably want everything *since* that tag.
 | 
						|
 | 
						|
XXX This code was created by reverse engineering CVS 1.9 and RCS 5.7
 | 
						|
from their output.
 | 
						|
 | 
						|
"""
 | 
						|
 | 
						|
import os, sys, getopt, string, re
 | 
						|
 | 
						|
sep1 = '='*77 + '\n'			# file separator
 | 
						|
sep2 = '-'*28 + '\n'			# revision separator
 | 
						|
 | 
						|
def main():
 | 
						|
    """Main program"""
 | 
						|
    truncate_last = 0
 | 
						|
    opts, args = getopt.getopt(sys.argv[1:], "-t")
 | 
						|
    for o, a in opts:
 | 
						|
	if o == '-t':
 | 
						|
	    truncate_last = 1
 | 
						|
    database = []
 | 
						|
    while 1:
 | 
						|
	chunk = read_chunk(sys.stdin)
 | 
						|
	if not chunk:
 | 
						|
	    break
 | 
						|
	records = digest_chunk(chunk)
 | 
						|
	if truncate_last:
 | 
						|
	    del records[-1]
 | 
						|
	database[len(database):] = records
 | 
						|
    database.sort()
 | 
						|
    database.reverse()
 | 
						|
    format_output(database)
 | 
						|
 | 
						|
def read_chunk(fp):
 | 
						|
    """Read a chunk -- data for one file, ending with sep1.
 | 
						|
 | 
						|
    Split the chunk in parts separated by sep2.
 | 
						|
 | 
						|
    """
 | 
						|
    chunk = []
 | 
						|
    lines = []
 | 
						|
    while 1:
 | 
						|
	line = fp.readline()
 | 
						|
	if not line:
 | 
						|
	    break
 | 
						|
	if line == sep1:
 | 
						|
	    if lines:
 | 
						|
		chunk.append(lines)
 | 
						|
	    break
 | 
						|
	if line == sep2:
 | 
						|
	    if lines:
 | 
						|
		chunk.append(lines)
 | 
						|
		lines = []
 | 
						|
	else:
 | 
						|
	    lines.append(line)
 | 
						|
    return chunk
 | 
						|
 | 
						|
def digest_chunk(chunk):
 | 
						|
    """Digest a chunk -- extrach working file name and revisions"""
 | 
						|
    lines = chunk[0]
 | 
						|
    key = 'Working file:'
 | 
						|
    keylen = len(key)
 | 
						|
    for line in lines:
 | 
						|
	if line[:keylen] == key:
 | 
						|
	    working_file = string.strip(line[keylen:])
 | 
						|
	    break
 | 
						|
    else:
 | 
						|
	working_file = None
 | 
						|
    records = []
 | 
						|
    for lines in chunk[1:]:
 | 
						|
	revline = lines[0]
 | 
						|
	dateline = lines[1]
 | 
						|
	text = lines[2:]
 | 
						|
	words = string.split(dateline)
 | 
						|
	author = None
 | 
						|
	if len(words) >= 3 and words[0] == 'date:':
 | 
						|
	    dateword = words[1]
 | 
						|
	    timeword = words[2]
 | 
						|
	    if timeword[-1:] == ';':
 | 
						|
		timeword = timeword[:-1]
 | 
						|
	    date = dateword + ' ' + timeword
 | 
						|
	    if len(words) >= 5 and words[3] == 'author:':
 | 
						|
		author = words[4]
 | 
						|
		if author[-1:] == ';':
 | 
						|
		    author = author[:-1]
 | 
						|
	else:
 | 
						|
	    date = None
 | 
						|
	    text.insert(0, revline)
 | 
						|
	words = string.split(revline)
 | 
						|
	if len(words) >= 2 and words[0] == 'revision':
 | 
						|
	    rev = words[1]
 | 
						|
	else:
 | 
						|
	    rev = None
 | 
						|
	    text.insert(0, revline)
 | 
						|
	records.append((date, working_file, rev, author, text))
 | 
						|
    return records
 | 
						|
	
 | 
						|
def format_output(database):
 | 
						|
    prevtext = None
 | 
						|
    prev = []
 | 
						|
    database.append((None, None, None, None, None)) # Sentinel
 | 
						|
    for (date, working_file, rev, author, text) in database:
 | 
						|
	if text != prevtext:
 | 
						|
	    if prev:
 | 
						|
		print sep2,
 | 
						|
		for (p_date, p_working_file, p_rev, p_author) in prev:
 | 
						|
		    print p_date, p_author, p_working_file
 | 
						|
		sys.stdout.writelines(prevtext)
 | 
						|
	    prev = []
 | 
						|
	prev.append((date, working_file, rev, author))
 | 
						|
	prevtext = text
 | 
						|
 | 
						|
main()
 |