These files are a subset of the python-2.7.2.tgz distribution from python.org. Changed files from PyMod-2.7.2 have been copied into the corresponding directories of this tree, replacing the original files in the distribution. Signed-off-by: daryl.mcdaniel@intel.com git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13197 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			186 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			186 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| #! /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.
 | |
| 
 | |
| The -r option reverses the output (oldest first; the default is oldest
 | |
| last).
 | |
| 
 | |
| The -b tag option restricts the output to *only* checkin messages
 | |
| belonging to the given branch tag.  The form -b HEAD restricts the
 | |
| output to checkin messages belonging to the CVS head (trunk).  (It
 | |
| produces some output if tag is a non-branch tag, but this output is
 | |
| not very useful.)
 | |
| 
 | |
| -h prints this message and exits.
 | |
| 
 | |
| XXX This code was created by reverse engineering CVS 1.9 and RCS 5.7
 | |
| from their output.
 | |
| """
 | |
| 
 | |
| import sys, errno, getopt, re
 | |
| 
 | |
| sep1 = '='*77 + '\n'                    # file separator
 | |
| sep2 = '-'*28 + '\n'                    # revision separator
 | |
| 
 | |
| def main():
 | |
|     """Main program"""
 | |
|     truncate_last = 0
 | |
|     reverse = 0
 | |
|     branch = None
 | |
|     opts, args = getopt.getopt(sys.argv[1:], "trb:h")
 | |
|     for o, a in opts:
 | |
|         if o == '-t':
 | |
|             truncate_last = 1
 | |
|         elif o == '-r':
 | |
|             reverse = 1
 | |
|         elif o == '-b':
 | |
|             branch = a
 | |
|         elif o == '-h':
 | |
|             print __doc__
 | |
|             sys.exit(0)
 | |
|     database = []
 | |
|     while 1:
 | |
|         chunk = read_chunk(sys.stdin)
 | |
|         if not chunk:
 | |
|             break
 | |
|         records = digest_chunk(chunk, branch)
 | |
|         if truncate_last:
 | |
|             del records[-1]
 | |
|         database[len(database):] = records
 | |
|     database.sort()
 | |
|     if not reverse:
 | |
|         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, branch=None):
 | |
|     """Digest a chunk -- extract working file name and revisions"""
 | |
|     lines = chunk[0]
 | |
|     key = 'Working file:'
 | |
|     keylen = len(key)
 | |
|     for line in lines:
 | |
|         if line[:keylen] == key:
 | |
|             working_file = line[keylen:].strip()
 | |
|             break
 | |
|     else:
 | |
|         working_file = None
 | |
|     if branch is None:
 | |
|         pass
 | |
|     elif branch == "HEAD":
 | |
|         branch = re.compile(r"^\d+\.\d+$")
 | |
|     else:
 | |
|         revisions = {}
 | |
|         key = 'symbolic names:\n'
 | |
|         found = 0
 | |
|         for line in lines:
 | |
|             if line == key:
 | |
|                 found = 1
 | |
|             elif found:
 | |
|                 if line[0] in '\t ':
 | |
|                     tag, rev = line.split()
 | |
|                     if tag[-1] == ':':
 | |
|                         tag = tag[:-1]
 | |
|                     revisions[tag] = rev
 | |
|                 else:
 | |
|                     found = 0
 | |
|         rev = revisions.get(branch)
 | |
|         branch = re.compile(r"^<>$") # <> to force a mismatch by default
 | |
|         if rev:
 | |
|             if rev.find('.0.') >= 0:
 | |
|                 rev = rev.replace('.0.', '.')
 | |
|                 branch = re.compile(r"^" + re.escape(rev) + r"\.\d+$")
 | |
|     records = []
 | |
|     for lines in chunk[1:]:
 | |
|         revline = lines[0]
 | |
|         dateline = lines[1]
 | |
|         text = lines[2:]
 | |
|         words = dateline.split()
 | |
|         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 = revline.split()
 | |
|         if len(words) >= 2 and words[0] == 'revision':
 | |
|             rev = words[1]
 | |
|         else:
 | |
|             # No 'revision' line -- weird...
 | |
|             rev = None
 | |
|             text.insert(0, revline)
 | |
|         if branch:
 | |
|             if rev is None or not branch.match(rev):
 | |
|                 continue
 | |
|         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, p_rev
 | |
|                 sys.stdout.writelines(prevtext)
 | |
|             prev = []
 | |
|         prev.append((date, working_file, rev, author))
 | |
|         prevtext = text
 | |
| 
 | |
| if __name__ == '__main__':
 | |
|     try:
 | |
|         main()
 | |
|     except IOError, e:
 | |
|         if e.errno != errno.EPIPE:
 | |
|             raise
 |