contrib: Wrap git repo access in gcc-changelog.

Message ID D8F28VOQLJU9.31RBM2RIYTU3R@gmail.com
State New
Headers
Series contrib: Wrap git repo access in gcc-changelog. |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_gcc_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_simplebootstrap_build--master-arm-bootstrap success Build passed
linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 success Test passed
linaro-tcwg-bot/tcwg_simplebootstrap_build--master-aarch64-bootstrap success Build passed

Commit Message

Robin Dapp March 13, 2025, 10:19 a.m. UTC
  Hi,

since updating to Fedora 41 I have been seeing ignored python exceptions
like the following when using 'git gcc-verify' = 
contrib/gcc_changelog/git_check_commit.py.

Checking 90fcc1f4f1a5537e8d30628895a07cbb2e7e16ff: OK
Exception ignored in: <function Git.AutoInterrupt.__del__ at 0x7ff88dd01440>
Traceback (most recent call last):
  File "/usr/lib/python3.13/site-packages/git/cmd.py", line 563, in __del__
  File "/usr/lib/python3.13/site-packages/git/cmd.py", line 544, in _terminate
  File "/usr/lib64/python3.13/subprocess.py", line 2227, in terminate
ImportError: sys.meta_path is None, Python is likely shutting down

This patch uses a simple fix found on the kernel mailing list [1].  All it does
is wrap the repository access in a with clause and indent the remaining code.  
With that the output is as expected again:

Checking 90fcc1f4f1a5537e8d30628895a07cbb2e7e16ff: OK

git_update_version.py also uses an unwrapped "Repo" but as I'm not using that 
regularly I refrained from touching it.

Regards
 Robin

[1] https://lkml.org/lkml/2025/2/25/1062

contrib/ChangeLog:

	* gcc-changelog/git_repository.py: Use with Repo(repo_path).
---
 contrib/gcc-changelog/git_repository.py | 86 +++++++++++++------------
 1 file changed, 44 insertions(+), 42 deletions(-)
  

Comments

Sam James March 15, 2025, 8:02 a.m. UTC | #1
"Robin Dapp" <rdapp.gcc@gmail.com> writes:

> Hi,
>
> since updating to Fedora 41 I have been seeing ignored python exceptions
> like the following when using 'git gcc-verify' = 
> contrib/gcc_changelog/git_check_commit.py.
>
> Checking 90fcc1f4f1a5537e8d30628895a07cbb2e7e16ff: OK
> Exception ignored in: <function Git.AutoInterrupt.__del__ at 0x7ff88dd01440>
> Traceback (most recent call last):
>   File "/usr/lib/python3.13/site-packages/git/cmd.py", line 563, in __del__
>   File "/usr/lib/python3.13/site-packages/git/cmd.py", line 544, in _terminate
>   File "/usr/lib64/python3.13/subprocess.py", line 2227, in terminate
> ImportError: sys.meta_path is None, Python is likely shutting down
>
> This patch uses a simple fix found on the kernel mailing list [1].  All it does
> is wrap the repository access in a with clause and indent the remaining code.  
> With that the output is as expected again:
>
> Checking 90fcc1f4f1a5537e8d30628895a07cbb2e7e16ff: OK
>
> git_update_version.py also uses an unwrapped "Repo" but as I'm not using that 
> regularly I refrained from touching it.
>
> Regards
>  Robin
>
> [1] https://lkml.org/lkml/2025/2/25/1062

I've no idea who can approve this but it looks good -- with the
excpetion that I think it'd be cleaner to create a Repo outside and call
parse_git_revisions with a context instead, rather than having
everything indented by another level.

Tobias pushed an explicit .close() just now which is also fine (in
r15-8068-g254549d2bb9bb3), but we should still change to the context
manager as your patch does.

>
> contrib/ChangeLog:
>
> 	* gcc-changelog/git_repository.py: Use with Repo(repo_path).
> ---
>  contrib/gcc-changelog/git_repository.py | 86 +++++++++++++------------
>  1 file changed, 44 insertions(+), 42 deletions(-)
>
> diff --git a/contrib/gcc-changelog/git_repository.py b/contrib/gcc-changelog/git_repository.py
> index d7650c65e21..c3c47236b32 100755
> --- a/contrib/gcc-changelog/git_repository.py
> +++ b/contrib/gcc-changelog/git_repository.py
> @@ -32,50 +32,52 @@ from git_commit import GitCommit, GitInfo, decode_path
>  
>  
>  def parse_git_revisions(repo_path, revisions, ref_name=None):
> -    repo = Repo(repo_path)
>  
> -    def commit_to_info(commit):
> -        try:
> -            c = repo.commit(commit)
> -            diff = repo.commit(commit + '~').diff(commit)
> +    with Repo(repo_path) as repo:
> +        assert not repo.bare
>  
> -            modified_files = []
> -            for file in diff:
> -                if hasattr(file, 'renamed_file'):
> -                    is_renamed = file.renamed_file
> -                else:
> -                    is_renamed = file.renamed
> -                if file.new_file:
> -                    t = 'A'
> -                elif file.deleted_file:
> -                    t = 'D'
> -                elif is_renamed:
> -                    # Consider that renamed files are two operations:
> -                    # the deletion of the original name
> -                    # and the addition of the new one.
> -                    modified_files.append((decode_path(file.a_path), 'D'))
> -                    t = 'A'
> -                else:
> -                    t = 'M'
> -                modified_files.append((decode_path(file.b_path), t))
> +        def commit_to_info(commit):
> +            try:
> +                c = repo.commit(commit)
> +                diff = repo.commit(commit + '~').diff(commit)
>  
> -            date = datetime.utcfromtimestamp(c.committed_date)
> -            author = '%s  <%s>' % (c.author.name, c.author.email)
> -            git_info = GitInfo(c.hexsha, date, author,
> -                               c.message.split('\n'), modified_files)
> -            return git_info
> -        except ValueError:
> -            return None
> +                modified_files = []
> +                for file in diff:
> +                    if hasattr(file, 'renamed_file'):
> +                        is_renamed = file.renamed_file
> +                    else:
> +                        is_renamed = file.renamed
> +                    if file.new_file:
> +                        t = 'A'
> +                    elif file.deleted_file:
> +                        t = 'D'
> +                    elif is_renamed:
> +                        # Consider that renamed files are two operations:
> +                        # the deletion of the original name
> +                        # and the addition of the new one.
> +                        modified_files.append((decode_path(file.a_path), 'D'))
> +                        t = 'A'
> +                    else:
> +                        t = 'M'
> +                    modified_files.append((decode_path(file.b_path), t))
>  
> -    parsed_commits = []
> -    if '..' in revisions:
> -        commits = list(repo.iter_commits(revisions))
> -    else:
> -        commits = [repo.commit(revisions)]
> +                date = datetime.utcfromtimestamp(c.committed_date)
> +                author = '%s  <%s>' % (c.author.name, c.author.email)
> +                git_info = GitInfo(c.hexsha, date, author,
> +                                   c.message.split('\n'), modified_files)
> +                return git_info
> +            except ValueError:
> +                return None
>  
> -    for commit in commits:
> -        git_commit = GitCommit(commit_to_info(commit.hexsha),
> -                               commit_to_info_hook=commit_to_info,
> -                               ref_name=ref_name)
> -        parsed_commits.append(git_commit)
> -    return parsed_commits
> +        parsed_commits = []
> +        if '..' in revisions:
> +            commits = list(repo.iter_commits(revisions))
> +        else:
> +            commits = [repo.commit(revisions)]
> +
> +        for commit in commits:
> +            git_commit = GitCommit(commit_to_info(commit.hexsha),
> +                                   commit_to_info_hook=commit_to_info,
> +                                   ref_name=ref_name)
> +            parsed_commits.append(git_commit)
> +        return parsed_commits
  
Jeff Law March 15, 2025, 6:50 p.m. UTC | #2
On 3/13/25 4:19 AM, Robin Dapp wrote:
> Hi,
> 
> since updating to Fedora 41 I have been seeing ignored python exceptions
> like the following when using 'git gcc-verify' = contrib/gcc_changelog/ 
> git_check_commit.py.
> 
> Checking 90fcc1f4f1a5537e8d30628895a07cbb2e7e16ff: OK
> Exception ignored in: <function Git.AutoInterrupt.__del__ at 
> 0x7ff88dd01440>
> Traceback (most recent call last):
>   File "/usr/lib/python3.13/site-packages/git/cmd.py", line 563, in __del__
>   File "/usr/lib/python3.13/site-packages/git/cmd.py", line 544, in 
> _terminate
>   File "/usr/lib64/python3.13/subprocess.py", line 2227, in terminate
> ImportError: sys.meta_path is None, Python is likely shutting down
> 
> This patch uses a simple fix found on the kernel mailing list [1].  All 
> it does
> is wrap the repository access in a with clause and indent the remaining 
> code. With that the output is as expected again:
> 
> Checking 90fcc1f4f1a5537e8d30628895a07cbb2e7e16ff: OK
> 
> git_update_version.py also uses an unwrapped "Repo" but as I'm not using 
> that regularly I refrained from touching it.
> 
> Regards
> Robin
> 
> [1] https://lkml.org/lkml/2025/2/25/1062
> 
> contrib/ChangeLog:
> 
>      * gcc-changelog/git_repository.py: Use with Repo(repo_path).
OK
jeff
  

Patch

diff --git a/contrib/gcc-changelog/git_repository.py b/contrib/gcc-changelog/git_repository.py
index d7650c65e21..c3c47236b32 100755
--- a/contrib/gcc-changelog/git_repository.py
+++ b/contrib/gcc-changelog/git_repository.py
@@ -32,50 +32,52 @@  from git_commit import GitCommit, GitInfo, decode_path
 
 
 def parse_git_revisions(repo_path, revisions, ref_name=None):
-    repo = Repo(repo_path)
 
-    def commit_to_info(commit):
-        try:
-            c = repo.commit(commit)
-            diff = repo.commit(commit + '~').diff(commit)
+    with Repo(repo_path) as repo:
+        assert not repo.bare
 
-            modified_files = []
-            for file in diff:
-                if hasattr(file, 'renamed_file'):
-                    is_renamed = file.renamed_file
-                else:
-                    is_renamed = file.renamed
-                if file.new_file:
-                    t = 'A'
-                elif file.deleted_file:
-                    t = 'D'
-                elif is_renamed:
-                    # Consider that renamed files are two operations:
-                    # the deletion of the original name
-                    # and the addition of the new one.
-                    modified_files.append((decode_path(file.a_path), 'D'))
-                    t = 'A'
-                else:
-                    t = 'M'
-                modified_files.append((decode_path(file.b_path), t))
+        def commit_to_info(commit):
+            try:
+                c = repo.commit(commit)
+                diff = repo.commit(commit + '~').diff(commit)
 
-            date = datetime.utcfromtimestamp(c.committed_date)
-            author = '%s  <%s>' % (c.author.name, c.author.email)
-            git_info = GitInfo(c.hexsha, date, author,
-                               c.message.split('\n'), modified_files)
-            return git_info
-        except ValueError:
-            return None
+                modified_files = []
+                for file in diff:
+                    if hasattr(file, 'renamed_file'):
+                        is_renamed = file.renamed_file
+                    else:
+                        is_renamed = file.renamed
+                    if file.new_file:
+                        t = 'A'
+                    elif file.deleted_file:
+                        t = 'D'
+                    elif is_renamed:
+                        # Consider that renamed files are two operations:
+                        # the deletion of the original name
+                        # and the addition of the new one.
+                        modified_files.append((decode_path(file.a_path), 'D'))
+                        t = 'A'
+                    else:
+                        t = 'M'
+                    modified_files.append((decode_path(file.b_path), t))
 
-    parsed_commits = []
-    if '..' in revisions:
-        commits = list(repo.iter_commits(revisions))
-    else:
-        commits = [repo.commit(revisions)]
+                date = datetime.utcfromtimestamp(c.committed_date)
+                author = '%s  <%s>' % (c.author.name, c.author.email)
+                git_info = GitInfo(c.hexsha, date, author,
+                                   c.message.split('\n'), modified_files)
+                return git_info
+            except ValueError:
+                return None
 
-    for commit in commits:
-        git_commit = GitCommit(commit_to_info(commit.hexsha),
-                               commit_to_info_hook=commit_to_info,
-                               ref_name=ref_name)
-        parsed_commits.append(git_commit)
-    return parsed_commits
+        parsed_commits = []
+        if '..' in revisions:
+            commits = list(repo.iter_commits(revisions))
+        else:
+            commits = [repo.commit(revisions)]
+
+        for commit in commits:
+            git_commit = GitCommit(commit_to_info(commit.hexsha),
+                                   commit_to_info_hook=commit_to_info,
+                                   ref_name=ref_name)
+            parsed_commits.append(git_commit)
+        return parsed_commits