##// END OF EJS Templates
configitems: declare items in a TOML file...
configitems: declare items in a TOML file Mercurial ships with Rust code that also needs to read from the config. Having a way of presenting `configitems` to both Python and Rust is needed to prevent duplication, drift, and have the appropriate devel warnings. Abstracting away from Python means choosing a config format. No single format is perfect, and I have yet to come across a developer that doesn't hate all of them in some way. Since we have a strict no-dependencies policy for Mercurial, we either need to use whatever comes with Python, vendor a library, or implement a custom format ourselves. Python stdlib means using JSON, which doesn't support comments and isn't great for humans, or `configparser` which is an obscure, untyped format that nobody uses and doesn't have a commonplace Rust parser. Implementing a custom format is error-prone, tedious and subject to the same issues as picking an existing format. Vendoring opens us to the vast array of common config formats. The ones being picked for most modern software are YAML and TOML. YAML is older and common in the Python community, but TOML is much simpler and less error-prone. I would much rather be responsible for the <1000 lines of `tomli`, on top of TOML being the choice of the Rust community, with robust crates for reading it. The structure of `configitems.toml` is explained inline.

File last commit:

r44058:99e231af default
r51655:c51b178b default
Show More
relnotes
207 lines | 6.2 KiB | text/plain | TextLexer
Augie Fackler
contrib: import the relnotes script from the release-tools repo...
r39388 #!/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,
av6
relnotes: more improvements
r41659 r"\(SEC\)": 100,
Augie Fackler
contrib: import the relnotes script from the release-tools repo...
r39388 # 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,
av6
relnotes: more improvements
r41659 r": new.*(extension|flag|module)": 10,
av6
relnotes: various tweaks for release notes...
r40491 r"( ability|command|feature|option|support)": 10,
# experimental
r"hg-experimental": 20,
r"(from|graduate).*experimental": 15,
r"(hide|mark).*experimental": -10,
Augie Fackler
contrib: import the relnotes script from the release-tools repo...
r39388 # bug-like?
r"(fix|don't break|improve)": 7,
av6
relnotes: various tweaks for release notes...
r40491 r"(not|n't|avoid|fix|prevent).*crash": 10,
av6
relnotes: more improvements
r41659 r"vulnerab": 10,
Augie Fackler
contrib: import the relnotes script from the release-tools repo...
r39388 # boring stuff, bump down
r"^contrib": -5,
r"debug": -5,
r"help": -5,
av6
relnotes: more improvements
r41659 r"minor": -5,
av6
relnotes: various tweaks for release notes...
r40491 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,
Augie Fackler
contrib: import the relnotes script from the release-tools repo...
r39388 # cleanups and refactoring
av6
relnotes: more improvements
r41659 r"(clean ?up|white ?space|spelling|quoting)": -20,
av6
relnotes: various tweaks for release notes...
r40491 r"(flatten|dedent|indent|nesting|unnest)": -20,
r"(typo|hint|note|comment|TODO|FIXME)": -20,
r"(style:|convention|one-?liner)": -20,
Augie Fackler
contrib: import the relnotes script from the release-tools repo...
r39388 r"(argument|absolute_import|attribute|assignment|mutable)": -15,
av6
relnotes: various tweaks for release notes...
r40491 r"(scope|True|False)": -10,
av6
relnotes: more improvements
r41659 r"(unused|useless|unnecessar|superfluous|duplicate|deprecated)": -10,
Augie Fackler
contrib: import the relnotes script from the release-tools repo...
r39388 r"(redundant|pointless|confusing|uninitialized|meaningless|dead)": -10,
av6
relnotes: various tweaks for release notes...
r40491 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,
Augie Fackler
contrib: import the relnotes script from the release-tools repo...
r39388 r": implement ": -5,
r": use .* implementation": -20,
av6
relnotes: more improvements
r41659 r": use .* instead of": -20,
# code
r"_": -10,
r"__": -5,
r"\(\)": -5,
Augie Fackler
contrib: import the relnotes script from the release-tools repo...
r39388 r"\S\S\S+\.\S\S\S\S+": -5,
# dumb keywords
r"\S+/\S+:": -10,
r"\S+\.\S+:": -10,
av6
relnotes: various tweaks for release notes...
r40491 # 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,
Augie Fackler
contrib: import the relnotes script from the release-tools repo...
r39388 # 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"),
av6
relnotes: various tweaks for release notes...
r40491 (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"),
Augie Fackler
contrib: import the relnotes script from the release-tools repo...
r39388 (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"),
]
Gregory Szorc
black: blacken scripts...
r44058
av6
relnotes: more improvements
r41659 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
Gregory Szorc
black: blacken scripts...
r44058
Augie Fackler
contrib: import the relnotes script from the release-tools repo...
r39388 def main():
av6
relnotes: various tweaks for release notes...
r40491 desc = "example: %(prog)s 4.7.2 --stoprev 4.8rc0"
ap = argparse.ArgumentParser(description=desc)
Augie Fackler
contrib: import the relnotes script from the release-tools repo...
r39388 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",
Pulkit Goyal
relnotes: enable extension when running releasenotes command...
r39401 "--config",
"extensions.releasenotes=",
Augie Fackler
contrib: import the relnotes script from the release-tools repo...
r39388 "releasenotes",
"-r",
av6
relnotes: various tweaks for release notes...
r40491 "only(%s, %s)" % (args.stoprev, args.startrev),
Augie Fackler
contrib: import the relnotes script from the release-tools repo...
r39388 ]
).decode("utf-8")
# Find all release notes from un-relnotes-flagged commits.
for entry in sorted(
subprocess.check_output(
[
"hg",
"log",
"-r",
av6
relnotes: various tweaks for release notes...
r40491 "only(%s, %s) - merge()" % (args.stoprev, args.startrev),
Augie Fackler
contrib: import the relnotes script from the release-tools repo...
r39388 "-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:
av6
relnotes: more improvements
r41659 commits.append(wikify(desc))
Augie Fackler
contrib: import the relnotes script from the release-tools repo...
r39388 # 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)
av6
relnotes: various tweaks for release notes...
r40491 if bcs:
print("\n=== Behavior Changes ===\n")
Augie Fackler
contrib: import the relnotes script from the release-tools repo...
r39388
for d in sorted(bcs):
print(" * %s" % d)
av6
relnotes: various tweaks for release notes...
r40491 if apis:
print("\n=== Internal API Changes ===\n")
Augie Fackler
contrib: import the relnotes script from the release-tools repo...
r39388
for d in sorted(apis):
print(" * %s" % d)
Gregory Szorc
black: blacken scripts...
r44058
Augie Fackler
contrib: import the relnotes script from the release-tools repo...
r39388 if __name__ == "__main__":
main()