+
+## Scan FILE for Author or Maintainer (preferred) headers.
+## Return a list of all email addresses found in MAINTS.
+def scan_file(file, maints):
+
+ try:
+ fd = open( file, 'r')
+ except Exception as err:
+ lfile.write('Error opening file %s: %s\n' % (file, str(err)))
+ return 1
+
+ ## Max number of lines to scan looking for a maintainer.
+ ## (20 seems to be the highest at present).
+ max_lines = 50
+ nline = 0
+ cont = 0
+ type = ""
+
+ for line in fd:
+
+ nline += 1
+
+ if ( nline > max_lines ): break
+
+ ## Try and de-obfuscate. Worth it?
+ line = re.sub( '(?i) AT ', '@', line )
+ line = re.sub( '(?i) DOT ', '.', line )
+
+ if cont: # continued header?
+ reg = re.match( ('%s[ \t]+[^:]*?<?([\w.-]+@[\w.-]+)>?' % prefix), line, re.I )
+ if not reg: # not a continued header
+ cont = 0
+ prefix = ""
+ if ( type == "maint" ): break
+ type = ""
+
+ ## Check for one header immediately after another.
+ if not cont:
+ reg = re.match( '([^ ]+)? *(Author|Maintainer)s?: .*?<?([\w.-]+@[\w.-]+)>?', line, re.I )
+
+
+ if not reg: continue
+
+ if cont:
+ email = reg.group(1)
+ maints.append(email)
+ else:
+ cont = 1
+ prefix = reg.group(1) or ""
+ type = reg.group(2)
+ email = reg.group(3)
+ type = "maint" if re.search( 'Maintainer', type, re.I ) else "auth"
+ ## maints = [] does the wrong thing.
+ if type == "maint": del maints[:]
+ maints.append(email)
+
+ fd.close()
+
+
+## Scan all the files under dir for maintainer information.
+## Write to stdout, or optional argument outfile (which is overwritten).
+def scan_dir(dir, outfile=None):
+
+ dir = re.sub( '/+$', '', dir) + '/' # ensure trailing /
+
+ if not os.path.isdir(dir):
+ sys.stderr.write('No such directory: %s\n' % dir)
+ sys.exit(1)
+
+ fd = 0
+ if outfile:
+ try:
+ fd = open( outfile, 'w' )
+ except Exception as err:
+ sys.stderr.write("Error opening `%s': %s\n" % (outfile, str(err)))
+ sys.exit(1)
+
+
+ for dirpath, dirnames, filenames in os.walk(dir):
+ for file in filenames:
+ path = os.path.join(dirpath, file)
+ maints = []
+ scan_file(path, maints)
+ ## This would skip printing empty maints.
+ ## That would mean we would scan the file each time for no reason.
+ ## But empty maintainers are an error at present.
+ if not maints: continue
+ path = re.sub( '^%s' % dir, '', path )
+ string = "%-50s %s\n" % (path, ",".join(maints))
+ if fd:
+ fd.write(string)
+ else:
+ print string,
+
+ if fd: fd.close()
+
+
+usage="""usage: %prog <-p /path/to/packages> <-m maintfile>
+ <-l logfile -s sender|--create> [-o overmaintfile] [--prefix prefix]
+ [--sendmail] [--debug]
+Take an emacs-diffs mail on stdin, and forward it to the maintainer(s)."""