123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- '''
- A tool to create/update the mailmap file
- The command 'git shortlog' summarizes git log output in a format suitable
- for inclusion in release announcements. Each commit will be grouped by
- author and title.
- One problem is that the authors' name and/or email address is sometimes
- spelled differently. The .mailmap feature can be used to coalesce together
- commits by the same persion.
- (See 'man git-shortlog' for furthur information of this feature.)
- This tool helps to create/update the mailmap file.
- It runs 'git shortlog' internally and searches differently spelled author
- names which share the same email address. The author name with the most
- commits is asuumed to be a canonical real name. If the number of commits
- from the cananonical name is equal to or greater than 'MIN_COMMITS',
- the entry for the cananical name will be output. ('MIN_COMMITS' is used
- here because we do not want to create a fat mailmap by adding every author
- with only a few commits.)
- If there exists a mailmap file specified by the mailmap.file configuration
- options or '.mailmap' at the toplevel of the repository, it is used as
- a base file. (The mailmap.file configuration takes precedence over the
- '.mailmap' file if both exist.)
- The base file and the newly added entries are merged together and sorted
- alphabetically (but the comment block is kept untouched), and then printed
- to standard output.
- Usage
- -----
- scripts/mailmapper
- prints the mailmapping to standard output.
- scripts/mailmapper > tmp; mv tmp .mailmap
- will be useful for updating '.mailmap' file.
- '''
- import sys
- import os
- import subprocess
- MIN_COMMITS = 50
- try:
- toplevel = subprocess.check_output(['git', 'rev-parse', '--show-toplevel'])
- except subprocess.CalledProcessError:
- sys.exit('Please run in a git repository.')
- toplevel = toplevel.rstrip()
- os.chdir(toplevel)
- shortlog = subprocess.check_output(['git', 'shortlog', '-s', '-n'])
- commits_per_name = {}
- for line in shortlog.splitlines():
- try:
- commits, name = line.split(None, 1)
- except ValueError:
-
- pass
- commits_per_name[name] = int(commits)
- shortlog = subprocess.check_output(['git', 'shortlog', '-s', '-n', '-e'])
- mail_vs_name = {}
- output = {}
- for line in shortlog.splitlines():
-
-
- tmp, mail = line.split('<')
- mail = '<' + mail.rstrip()
- try:
- _, name = tmp.rstrip().split(None, 1)
- except ValueError:
-
- name = ''
- if mail in mail_vs_name:
-
- prev_name = mail_vs_name[mail]
-
- major_name = sorted([prev_name, name],
- key=lambda x: commits_per_name[x] if x else 0)[1]
- mail_vs_name[mail] = major_name
- if commits_per_name[major_name] > MIN_COMMITS:
- output[mail] = major_name
- else:
- mail_vs_name[mail] = name
- mailmap_files = []
- try:
- config_mailmap = subprocess.check_output(['git', 'config', 'mailmap.file'])
- except subprocess.CalledProcessError:
- config_mailmap = ''
- config_mailmap = config_mailmap.rstrip()
- if config_mailmap:
- mailmap_files.append(config_mailmap)
- mailmap_files.append('.mailmap')
- infile = None
- for map_file in mailmap_files:
- try:
- infile = open(map_file)
- except:
-
- continue
- break
- comment_block = []
- output_lines = []
- if infile:
- for line in infile:
- if line[0] == '#' or line[0] == '\n':
- comment_block.append(line)
- else:
- output_lines.append(line)
- break
- for line in infile:
- output_lines.append(line)
- infile.close()
- for mail, name in output.items():
- output_lines.append(name + ' ' + mail + '\n')
- output_lines.sort()
- sys.stdout.write(''.join(comment_block + output_lines))
|