Mercurial > hg
view contrib/relnotes @ 46925:b5e8bf10436e
rhg: Make `files` work on repo-relative paths when possible
When the current directory is outside of the repository we need to turn
everything into absolute filesystem paths in order to compute correct
relative paths.
This was previously done unconditionally, but is not necessary when
the current directory is inside the repository.
With this change `rhg files > /dev/null` at the root of a mozilla-central
snapshot goes from ~150 ms to ~70 ms. My repository is located at a
somewhat long path though (93 bytes). The effect may not be as pronounced
at a shorter path.
Differential Revision: https://phab.mercurial-scm.org/D10200
author | Simon Sapin <simon.sapin@octobus.net> |
---|---|
date | Sat, 13 Mar 2021 09:50:34 +0100 |
parents | 99e231afc29c |
children |
line wrap: on
line source
#!/usr/bin/env python3 """Generate release notes from our commit log. This uses the relnotes extension directives when they're available, and falls back to our old pre-relnotes logic that used to live in the release-tools repo. """ import argparse import re import subprocess rules = { # keep r"\(issue": 100, r"\(BC\)": 100, r"\(API\)": 100, r"\(SEC\)": 100, # core commands, bump up r"(commit|files|log|pull|push|patch|status|tag|summary)(|s|es):": 20, r"(annotate|alias|branch|bookmark|clone|graft|import|verify).*:": 20, # extensions, bump up r"(mq|shelve|rebase):": 20, # newsy r": deprecate": 20, r": new.*(extension|flag|module)": 10, r"( ability|command|feature|option|support)": 10, # experimental r"hg-experimental": 20, r"(from|graduate).*experimental": 15, r"(hide|mark).*experimental": -10, # bug-like? r"(fix|don't break|improve)": 7, r"(not|n't|avoid|fix|prevent).*crash": 10, r"vulnerab": 10, # boring stuff, bump down r"^contrib": -5, r"debug": -5, r"help": -5, r"minor": -5, r"(doc|metavar|bundle2|obsolete|obsmarker|rpm|setup|debug\S+:)": -15, r"(check-code|check-commit|check-config|import-checker)": -20, r"(flake8|lintian|pyflakes|pylint)": -20, # cleanups and refactoring r"(clean ?up|white ?space|spelling|quoting)": -20, r"(flatten|dedent|indent|nesting|unnest)": -20, r"(typo|hint|note|comment|TODO|FIXME)": -20, r"(style:|convention|one-?liner)": -20, r"(argument|absolute_import|attribute|assignment|mutable)": -15, r"(scope|True|False)": -10, r"(unused|useless|unnecessar|superfluous|duplicate|deprecated)": -10, r"(redundant|pointless|confusing|uninitialized|meaningless|dead)": -10, r": (drop|remove|delete|rip out)": -10, r": (inherit|rename|simplify|naming|inline)": -10, r"(correct doc|docstring|document .* method)": -20, r"(abstract|factor|extract|prepare|split|replace| import)": -20, r": add.*(function|method|implementation|example)": -10, r": (move|extract) .* (to|into|from|out of)": -20, r": implement ": -5, r": use .* implementation": -20, r": use .* instead of": -20, # code r"_": -10, r"__": -5, r"\(\)": -5, r"\S\S\S+\.\S\S\S\S+": -5, # dumb keywords r"\S+/\S+:": -10, r"\S+\.\S+:": -10, # python compatibility r"[Pp]y(|thon) ?[23]": -20, r"pycompat": -20, r"(coerce|convert|encode) .*to (byte|sys|)(s|str|string)": -20, # tests r"^test(|s|ing|runner|-\S+):": -20, r"^(f|hghave|run-tests):": -20, r"add.* tests?": -20, r"(buildbot|fuzz|mock|ratchet)": -10, # drop r"^i18n-": -50, r"^i18n:.*(hint|comment)": -50, r"perf:": -50, r"Added.*for changeset": -50, r"^_": -50, } cutoff = 10 commits = [] groupings = [ (r"util|parsers|repo|ctx|context|revlog|filelog|alias|cmdutil", "core"), (r"revset|template|ui|dirstate|hook|i18n|transaction|wire|vfs", "core"), (r"dispatch|exchange|localrepo|streamclone|color|pager", "core"), (r"hgweb|paper|coal|gitweb|monoblue|spartan", "hgweb"), (r"pull|push|revert|resolve|annotate|bookmark|branch|clone", "commands"), (r"commands|commit|config|files|graft|import|log|merge|patch", "commands"), (r"phases|status|summary|amend|tag|help|verify", "commands"), (r"rebase|mq|convert|eol|histedit|largefiles", "extensions"), (r"shelve|unshelve", "extensions"), ] def wikify(desc): desc = desc.replace("(issue", "(Bts:issue") desc = re.sub(r"\b([0-9a-f]{12})\b", r"Cset:\1", desc) # stop ParseError from being recognized as a (nonexistent) wiki page desc = re.sub(r" ([A-Z][a-z]+[A-Z][a-z]+)\b", r" !\1", desc) # prevent wiki markup of magic methods desc = re.sub(r"\b(\S*__\S*)\b", r"`\1`", desc) return desc def main(): desc = "example: %(prog)s 4.7.2 --stoprev 4.8rc0" ap = argparse.ArgumentParser(description=desc) ap.add_argument( "startrev", metavar="REV", type=str, help=( "Starting revision for the release notes. This revision " "won't be included, but later revisions will." ), ) ap.add_argument( "--stoprev", metavar="REV", type=str, default="@", help=( "Stop revision for release notes. This revision will be included," " but no later revisions will. This revision needs to be " "a descendant of startrev." ), ) args = ap.parse_args() fromext = subprocess.check_output( [ "hg", "--config", "extensions.releasenotes=", "releasenotes", "-r", "only(%s, %s)" % (args.stoprev, args.startrev), ] ).decode("utf-8") # Find all release notes from un-relnotes-flagged commits. for entry in sorted( subprocess.check_output( [ "hg", "log", "-r", "only(%s, %s) - merge()" % (args.stoprev, args.startrev), "-T", r"{desc|firstline}\n", ] ) .decode("utf-8") .splitlines() ): desc = entry.replace("`", "'") score = 0 for rule, val in rules.items(): if re.search(rule, desc): score += val if score >= cutoff: commits.append(wikify(desc)) # Group unflagged notes. groups = {} bcs = [] apis = [] for d in commits: if "(BC)" in d: bcs.append(d) if "(API)" in d: apis.append(d) for rule, g in groupings: if re.match(rule, d): groups.setdefault(g, []).append(d) break else: groups.setdefault("unsorted", []).append(d) print(fromext) # print legacy release notes sections for g in sorted(groups): print("\n=== %s ===" % g) for d in sorted(groups[g]): print(" * %s" % d) if bcs: print("\n=== Behavior Changes ===\n") for d in sorted(bcs): print(" * %s" % d) if apis: print("\n=== Internal API Changes ===\n") for d in sorted(apis): print(" * %s" % d) if __name__ == "__main__": main()