From d20768be59bd9b5caad36adec5a0aa293ba46eda Mon Sep 17 00:00:00 2001 From: Michal Domonkos Date: Sat, 23 Dec 2023 18:42:00 +0100 Subject: [PATCH] Refactor git-changelog --- devel_doc/git-changelog | 174 ++++++++++++++++++++-------------------- 1 file changed, 88 insertions(+), 86 deletions(-) diff --git a/devel_doc/git-changelog b/devel_doc/git-changelog index 905fe6f..5f5e02c 100755 --- a/devel_doc/git-changelog +++ b/devel_doc/git-changelog @@ -10,6 +10,34 @@ import sys from common import shell, backports, changeset, KeyType, GitConfig +def chset_cmp(ch1, ch2): + prefix1, postfix1, title1 = ch1[:3] + prefix2, postfix2, title2 = ch2[:3] + + prefixes = PREFIXES + [''] + postfixes = POSTFIXES + [''] + + prefix1 = prefixes.index(prefix1) + prefix2 = prefixes.index(prefix2) + postfix1 = postfixes.index(postfix1) + postfix2 = postfixes.index(postfix2) + + if prefix1 < prefix2: + return -1 + elif prefix1 == prefix2: + if postfix1 < postfix2: + return -1 + elif postfix1 == postfix2: + if title1 < title2: + return -1 + else: + return 1 + else: + return 1 + else: + return 1 + + class PlainLog(object): def __init__(self, prev, empty, no_preamble, width, *args, **kwargs): self.prev = prev @@ -17,15 +45,15 @@ class PlainLog(object): self.no_preamble = no_preamble self.width = width - def _preamble(self): + def _format_preamble(self): return RELEASE + ' Changelog' - def _section(self, section): + def _format_section(self, section): return HEADINGS[section] + '\n' - def _pull(self, pull): + def _format_changeset(self, chset): fmt = ' * {}{} {}(#{})' - prefix, postfix, title, num, url = pull + prefix, postfix, title, num, url = chset if prefix: prefix = '{}: '.format(HEADINGS[prefix]) if postfix: @@ -34,21 +62,67 @@ class PlainLog(object): self.width - len(fmt.format(prefix, '', postfix, num))) return fmt.format(prefix, title, postfix, num) + @property + def _changesets(self): + changesets = {} + nums = set() + ignore = set(IGNORE) + + for commit in backports(self.prev): + lines = changeset(commit, args.refresh, args.quiet) + if not lines: + continue + title = lines[0].split(':', 1)[1].strip() + labels = set([label.lower() for label in lines[1].split(' ')]) + url = lines[2] + + num = lines[0].split(':')[0][4:] + if num in nums: + continue + nums.add(num) + + for p in PREFIXES: + if p in labels: + prefix = p + break + else: + prefix = '' + + for p in POSTFIXES: + if p in labels: + postfix = p + break + else: + postfix = '' + + labels = set(map(lambda x: ALIASES[x] if x in ALIASES else x, labels)) + if labels & ignore: + continue + labels = labels & HEADINGS.keys() + if not labels: + labels = set(['other']) + + for label in labels: + changesets.setdefault(label, []).append( + (prefix, postfix, title, num, url)) + + return changesets + def __str__(self): out = [] if not self.no_preamble: - out = [self._preamble(), ''] - p = pulls(self.prev) + out = [self._format_preamble(), ''] + changesets = self._changesets last = len(SECTIONS) - 1 for section in SECTIONS: - heading = self._section(section) - if section not in p: + heading = self._format_section(section) + if section not in changesets: if self.empty: out.append(heading) continue out.append(heading) - for pull in sorted(p[section], key=cmp_to_key(pull_cmp)): - out.append(self._pull(pull)) + for chset in sorted(changesets[section], key=cmp_to_key(chset_cmp)): + out.append(self._format_changeset(chset)) out.append('') return '\n'.join(out) @@ -61,92 +135,20 @@ class MarkdownLog(PlainLog): def _heading(self, level, name): return '{} {}'.format('#' * (self.level + level), name) - def _preamble(self): + def _format_preamble(self): return self._heading(1, RELEASE + ' Changelog') - def _section(self, section): + def _format_section(self, section): return self._heading(2, HEADINGS[section]) - def _pull(self, pull): - prefix, postfix, title, num, url = pull + def _format_changeset(self, chset): + prefix, postfix, title, num, url = chset if prefix: prefix = '{}: '.format(HEADINGS[prefix]) if postfix: postfix = '[{}] '.format(HEADINGS[postfix]) return '* {}{} {}([#{}]({}))'.format(prefix, title, postfix, num, url) -def pull_cmp(pull1, pull2): - prefix1, postfix1, title1 = pull1[:3] - prefix2, postfix2, title2 = pull2[:3] - - prefixes = PREFIXES + [''] - postfixes = POSTFIXES + [''] - - prefix1 = prefixes.index(prefix1) - prefix2 = prefixes.index(prefix2) - postfix1 = postfixes.index(postfix1) - postfix2 = postfixes.index(postfix2) - - if prefix1 < prefix2: - return -1 - elif prefix1 == prefix2: - if postfix1 < postfix2: - return -1 - elif postfix1 == postfix2: - if title1 < title2: - return -1 - else: - return 1 - else: - return 1 - else: - return 1 - -def pulls(branch): - pulls = {} - nums = set() - ignore = set(IGNORE) - - for commit in backports(branch): - lines = changeset(commit, args.refresh, args.quiet) - if not lines: - continue - title = lines[0].split(':', 1)[1].strip() - labels = set([label.lower() for label in lines[1].split(' ')]) - url = lines[2] - - num = lines[0].split(':')[0][4:] - if num in nums: - continue - nums.add(num) - - for p in PREFIXES: - if p in labels: - prefix = p - break - else: - prefix = '' - - for p in POSTFIXES: - if p in labels: - postfix = p - break - else: - postfix = '' - - labels = set(map(lambda x: ALIASES[x] if x in ALIASES else x, labels)) - if labels & ignore: - continue - labels = labels & HEADINGS.keys() - if not labels: - labels = set(['other']) - - for label in labels: - pulls.setdefault(label, []).append( - (prefix, postfix, title, num, url)) - - return pulls - CONFIG = GitConfig('changelog') RELEASE = shell("git tag -l --format='%(contents)' $(git describe --abbrev=0)")