Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Tom de Vries <tdevries@suse.de>
To: gdb-patches@sourceware.org
Subject: Re: [PATCH] [pre-commit] Don't allow pre-release revisions
Date: Thu, 27 Aug 2026 11:21:40 +0200	[thread overview]
Message-ID: <8be2c9d5-8003-44ed-8478-76c19c226fe9@suse.de> (raw)
In-Reply-To: <20260813152834.2591696-1-tdevries@suse.de>

On 8/13/26 5:28 PM, Tom de Vries wrote:
> Pre-commit has a convenient autoupdate command.  The default behavior is:
> update to the latest tagged version.
> 
> For most tools this is fine, and not too frequent.
> 
> Isort however also tags pre-releases, so that has resulted in more frequent
> updates:
> ...
> $ git log .pre-commit-config.yaml | grep "Bump isort"
>      [pre-commit] Bump isort to 9.0.0b1
>      [pre-commit] Bump isort to 9.0.0a3
>      [pre-commit] Bump isort to 9.0.0a2
>      [pre-commit] Bump isort to 8.0.1
>      [pre-commit] Bump isort to 8.0.0
> ...
> 
> Add a script gdb/contrib/pre-commit.py that for --config-check checks the
> revision numbers of all repos, and errors out when finding something like
> 9.0.0b1:
> ...
> $ ./gdb/contrib/pre-commit.py --config-check
> Revision 9.0.0b1 for repo https://github.com/pycqa/isort not allowed.
> ...
> 
> Add a corresponding pre-commit check, and revert isort back to the last stable
> release: 8.0.1, to make the check pass.
> 
> Consequently, pre-commit autoupdate now breaks the pre-commit check:
> ...
> $ pre-commit autoupdate
> [https://github.com/psf/black-pre-commit-mirror] already up to date!
> [https://github.com/pycqa/flake8] already up to date!
> [https://github.com/pycqa/isort] updating 8.0.1 -> 9.0.0b2
> [https://github.com/codespell-project/codespell] already up to date!
> [https://github.com/nmoroze/tclint] already up to date!
> [https://github.com/adrienverge/yamllint.git] already up to date!
> $ ./gdb/contrib/pre-commit.py --config-check
> Revision 9.0.0b2 for repo https://github.com/pycqa/isort not allowed.
> ...
> so add gdb/contrib/pre-commit.py --autoupdate that can be used instead:
> ...
> $ ./gdb/contrib/pre-commit.py --autoupdate
> [https://github.com/psf/black-pre-commit-mirror] already up to date!
> [https://github.com/pycqa/flake8] already up to date!
> [https://github.com/pycqa/isort] updating 8.0.1 -> 9.0.0b2
> Revision 9.0.0b2 for repo https://github.com/pycqa/isort not allowed.
> [https://github.com/codespell-project/codespell] already up to date!
> [https://github.com/nmoroze/tclint] already up to date!
> [https://github.com/adrienverge/yamllint.git] already up to date!
> ...
> 
> The script could be extended to check that frozen revs stay frozen, but that's
> currently not needed.
> 

I've pushed this, after fixing some nits Claude Code pointed out.

Then I ran the script, and pushed the resulting commit updating isort to 
9.0.0.

Thanks,
- Tom

> Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=34393
> ---
>   .pre-commit-config.yaml   |   9 ++-
>   gdb/contrib/pre-commit.py | 154 ++++++++++++++++++++++++++++++++++++++
>   2 files changed, 162 insertions(+), 1 deletion(-)
>   create mode 100755 gdb/contrib/pre-commit.py
> 
> diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
> index 3cccec45ef7..7b97b9a0ce8 100644
> --- a/.pre-commit-config.yaml
> +++ b/.pre-commit-config.yaml
> @@ -70,7 +70,7 @@ repos:
>           files: *gdb_python_files
>           args: [--config, gdb/setup.cfg]
>     - repo: https://github.com/pycqa/isort
> -    rev: 9.0.0b1
> +    rev: 8.0.1
>       hooks:
>         - id: isort
>           types_or: *gdb_python_types
> @@ -147,6 +147,13 @@ repos:
>           language: unsupported_script
>           entry: gdb/contrib/check-file-mode.sh
>           files: *gdb_files
> +      - id: &id5 pre-commit-config-check
> +        name: *id5
> +        language: python
> +        entry: gdb/contrib/pre-commit.py
> +        args: [--config-check]
> +        additional_dependencies: ["pyyaml"]
> +        files: '^\.pre-commit-config.yaml$'
>   
>   # Local Variables:
>   # indent-tabs-mode: nil
> diff --git a/gdb/contrib/pre-commit.py b/gdb/contrib/pre-commit.py
> new file mode 100755
> index 00000000000..9ab746c7355
> --- /dev/null
> +++ b/gdb/contrib/pre-commit.py
> @@ -0,0 +1,154 @@
> +#!/usr/bin/env python3
> +
> +# Copyright (C) 2026 Free Software Foundation, Inc.
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program.  If not, see <http://www.gnu.org/licenses/>.
> +
> +import re
> +import subprocess
> +import sys
> +
> +import yaml
> +
> +
> +def get_repos(cfg):
> +    with open(cfg, "r") as f:
> +        data = yaml.safe_load(f)
> +        repos = data.get("repos")
> +        if not repos:
> +            raise RuntimeError("repos missing")
> +        return repos
> +
> +
> +def config_check_repo(repo):
> +    name = repo.get("repo")
> +    if not name:
> +        raise RuntimeError("no repo")
> +    if name == "local":
> +        # Skip local repo, there's no revision to check.
> +        return True
> +
> +    # Get the revision.
> +    rev = repo["rev"]
> +    if not rev or rev == "":
> +        raise RuntimeError("empty revision")
> +
> +    # Normalize revision: skip 'v' prefix.
> +    if rev[0].lower() == "v":
> +        rev = rev[1:]
> +
> +    # Check version number.  Don't allow pre-releases like 9.0.0b1.
> +    # We currently only need to support x.y.z, but that could change.
> +    if not re.fullmatch(r"\d+[.]\d+[.]\d+", rev):
> +        print("Revision %s for repo %s not allowed." % (rev, name))
> +        return False
> +
> +    return True
> +
> +
> +def config_check(cfg):
> +    for repo in get_repos(cfg):
> +        if not config_check_repo(repo):
> +            sys.exit(1)
> +
> +
> +def run_cmd(cmd, **kwargs):
> +    res = subprocess.run(cmd, **kwargs)
> +    if res.returncode != 0:
> +        raise RuntimeError(
> +            "command %s failed with exit status %s" % (cmd, res.returncode)
> +        )
> +    return res
> +
> +
> +def autoupdate_repo(cfg, repo):
> +    name = repo["repo"]
> +    if name == "local":
> +        # Skip local repo, there's no revision to update.
> +        return
> +
> +    cmd = ["pre-commit", "autoupdate", "--repo", name]
> +    run_cmd(cmd)
> +
> +    cmd = ["git", "status", "--porcelain", cfg]
> +    res = run_cmd(cmd, capture_output=True, text=True)
> +    if res.stdout == "":
> +        # No autoupdate changes.
> +        return
> +
> +    rev = repo["rev"]
> +
> +    # Config has changed, refresh repo.
> +    found = False
> +    for new_repo in get_repos(cfg):
> +        if new_repo["repo"] == name:
> +            found = True
> +            break
> +    if not found:
> +        raise RuntimeError("Repo not found in updated %s" % cfg)
> +    repo = new_repo
> +
> +    new_rev = repo["rev"]
> +
> +    if not config_check_repo(repo):
> +        # Reject autoupdate for this repo.
> +        cmd = ["git", "checkout", "-f", cfg]
> +        # Capture and ignore output.
> +        run_cmd(cmd, capture_output=True, text=True)
> +        return
> +
> +    # Commit autoupdate for this repo.
> +    try:
> +        name_for_msg = repo["hooks"][0]["id"]
> +    except (KeyError, IndexError):
> +        name_for_msg = name
> +    msg = "Update %s: %s -> %s" % (name_for_msg, rev, new_rev)
> +    cmd = ["git", "commit", "-m", msg, cfg]
> +    run_cmd(cmd)
> +
> +
> +def autoupdate(cfg):
> +    for repo in get_repos(cfg):
> +        autoupdate_repo(cfg, repo)
> +
> +
> +def usage():
> +    print("Usage: pre-commit.py --config-check [<file>]")
> +    print("                     --autoupdate")
> +    sys.exit(1)
> +
> +
> +def main():
> +    if len(sys.argv) < 2:
> +        usage()
> +
> +    cfg = ".pre-commit-config.yaml"
> +
> +    if sys.argv[1] == "--config-check":
> +        if len(sys.argv) not in [2, 3]:
> +            usage()
> +        if len(sys.argv) == 3:
> +            cfg = sys.argv[2]
> +        config_check(cfg)
> +        return
> +
> +    if sys.argv[1] == "--autoupdate":
> +        if len(sys.argv) != 2:
> +            usage()
> +        autoupdate(cfg)
> +        return
> +
> +    usage()
> +
> +
> +main()
> 
> base-commit: 1686e21559a7812ebbc05f57372cc30880768bf7


      reply	other threads:[~2026-08-27  9:22 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-13 15:28 Tom de Vries
2026-08-27  9:21 ` Tom de Vries [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=8be2c9d5-8003-44ed-8478-76c19c226fe9@suse.de \
    --to=tdevries@suse.de \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox