mirror of
https://github.com/gcc-mirror/gcc.git
synced 2024-11-21 13:40:47 +00:00
e5d6e857af
* gcc-changelog/git_update_version.py (ignored_commits): Add another ignored commit.
189 lines
7.2 KiB
Python
Executable File
189 lines
7.2 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
# Copyright (C) 2020-2024 Free Software Foundation, Inc.
|
|
#
|
|
# This file is part of GCC.
|
|
#
|
|
# GCC 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, or (at your option) any later
|
|
# version.
|
|
#
|
|
# GCC 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 GCC; see the file COPYING3. If not see
|
|
# <http://www.gnu.org/licenses/>.
|
|
|
|
import argparse
|
|
import datetime
|
|
import logging
|
|
import os
|
|
import re
|
|
|
|
from git import Repo
|
|
|
|
from git_repository import parse_git_revisions
|
|
|
|
current_timestamp = datetime.datetime.now().strftime('%Y%m%d\n')
|
|
|
|
# Skip the following commits, they cannot be correctly processed
|
|
ignored_commits = {
|
|
'c2be82058fb40f3ae891c68d185ff53e07f14f45',
|
|
'04a040d907a83af54e0a98bdba5bfabc0ef4f700',
|
|
'2e96b5f14e4025691b57d2301d71aa6092ed44bc',
|
|
'3ab5c8cd03d92bf4ec41e351820349d92fbc40c4',
|
|
'86d8e0c0652ef5236a460b75c25e4f7093cc0651',
|
|
'e4cba49413ca429dc82f6aa2e88129ecb3fdd943',
|
|
'1957bedf29a1b2cc231972aba680fe80199d5498',
|
|
'040e5b0edbca861196d9e2ea2af5e805769c8d5d',
|
|
'8057f9aa1f7e70490064de796d7a8d42d446caf8',
|
|
'109f1b28fc94c93096506e3df0c25e331cef19d0',
|
|
'39f81924d88e3cc197fc3df74204c9b5e01e12f7',
|
|
'8e6a25b01becf449d54154b7e83de5f4955cba37',
|
|
'72677e1119dc40aa680755d009e079ad49446c46',
|
|
'10d76b7f1e5b63ad6d2b92940c39007913ced037',
|
|
'de3b277247ce98d189f121155b75f490725a42f6',
|
|
'13cf22eb557eb5e3d796822247d8d4957bdb25da'}
|
|
|
|
FORMAT = '%(asctime)s:%(levelname)s:%(name)s:%(message)s'
|
|
logging.basicConfig(level=logging.INFO, format=FORMAT,
|
|
handlers=[
|
|
logging.FileHandler('/tmp/git_update_version.txt'),
|
|
logging.StreamHandler()
|
|
])
|
|
|
|
|
|
def read_timestamp(path):
|
|
with open(path) as f:
|
|
return f.read()
|
|
|
|
|
|
def prepend_to_changelog_files(repo, folder, git_commit, add_to_git):
|
|
if not git_commit.success:
|
|
logging.info(f"While processing {git_commit.info.hexsha}:")
|
|
for error in git_commit.errors:
|
|
logging.info(error)
|
|
raise AssertionError()
|
|
for entry, output in git_commit.to_changelog_entries(use_commit_ts=True):
|
|
full_path = os.path.join(folder, entry, 'ChangeLog')
|
|
logging.info('writing to %s' % full_path)
|
|
if os.path.exists(full_path):
|
|
with open(full_path) as f:
|
|
content = f.read()
|
|
else:
|
|
content = ''
|
|
with open(full_path, 'w+') as f:
|
|
f.write(output)
|
|
if content:
|
|
f.write('\n\n')
|
|
f.write(content)
|
|
if add_to_git:
|
|
repo.git.add(full_path)
|
|
|
|
|
|
active_refs = ['master',
|
|
'releases/gcc-12', 'releases/gcc-13', 'releases/gcc-14']
|
|
|
|
parser = argparse.ArgumentParser(description='Update DATESTAMP and generate '
|
|
'ChangeLog entries')
|
|
parser.add_argument('-g', '--git-path', default='.',
|
|
help='Path to git repository')
|
|
parser.add_argument('-p', '--push', action='store_true',
|
|
help='Push updated active branches')
|
|
parser.add_argument('-d', '--dry-mode',
|
|
help='Generate patch for ChangeLog entries and do it'
|
|
' even if DATESTAMP is unchanged; folder argument'
|
|
' is expected')
|
|
parser.add_argument('-c', '--current', action='store_true',
|
|
help='Modify current branch (--push argument is ignored)')
|
|
parser.add_argument('-i', '--ignore', action='append',
|
|
help='list of commits to ignore')
|
|
args = parser.parse_args()
|
|
|
|
repo = Repo(args.git_path)
|
|
origin = repo.remotes['origin']
|
|
|
|
|
|
def update_current_branch(ref_name=None):
|
|
commit = repo.head.commit
|
|
commit_count = 1
|
|
while commit:
|
|
if (commit.author.email == 'gccadmin@gcc.gnu.org'
|
|
and commit.message.strip() == 'Daily bump.'):
|
|
break
|
|
# We support merge commits but only with 2 parensts
|
|
assert len(commit.parents) <= 2
|
|
commit = commit.parents[-1]
|
|
commit_count += 1
|
|
|
|
logging.info('%d revisions since last Daily bump' % commit_count)
|
|
datestamp_path = os.path.join(args.git_path, 'gcc/DATESTAMP')
|
|
if (read_timestamp(datestamp_path) != current_timestamp
|
|
or args.dry_mode or args.current):
|
|
head = repo.head.commit
|
|
# if HEAD is a merge commit, start with second parent
|
|
# (branched that is being merged into the current one)
|
|
assert len(head.parents) <= 2
|
|
if len(head.parents) == 2:
|
|
head = head.parents[1]
|
|
commits = parse_git_revisions(args.git_path, '%s..%s'
|
|
% (commit.hexsha, head.hexsha), ref_name)
|
|
commits = [c for c in commits if c.info.hexsha not in ignored_commits]
|
|
for git_commit in reversed(commits):
|
|
prepend_to_changelog_files(repo, args.git_path, git_commit,
|
|
not args.dry_mode)
|
|
if args.dry_mode:
|
|
diff = repo.git.diff('HEAD')
|
|
patch = os.path.join(args.dry_mode,
|
|
branch.name.split('/')[-1] + '.patch')
|
|
with open(patch, 'w+') as f:
|
|
f.write(diff)
|
|
logging.info('branch diff written to %s' % patch)
|
|
repo.git.checkout(force=True)
|
|
else:
|
|
# update timestamp
|
|
logging.info('DATESTAMP will be changed:')
|
|
with open(datestamp_path, 'w+') as f:
|
|
f.write(current_timestamp)
|
|
repo.git.add(datestamp_path)
|
|
if not args.current:
|
|
repo.index.commit('Daily bump.')
|
|
logging.info('commit is done')
|
|
if args.push:
|
|
try:
|
|
repo.git.push('origin', branch)
|
|
logging.info('branch is pushed')
|
|
except Exception:
|
|
logging.exception('git push failed')
|
|
else:
|
|
logging.info('DATESTAMP unchanged')
|
|
|
|
if args.ignore is not None:
|
|
for item in args.ignore:
|
|
ignored_commits.update(set(i for i in re.split(r'\s*,\s*|\s+', item)))
|
|
|
|
if args.current:
|
|
logging.info('=== Working on the current branch ===')
|
|
update_current_branch()
|
|
else:
|
|
for ref in origin.refs:
|
|
assert ref.name.startswith('origin/')
|
|
name = ref.name[len('origin/'):]
|
|
if name in active_refs:
|
|
if name in repo.branches:
|
|
branch = repo.branches[name]
|
|
else:
|
|
branch = repo.create_head(name, ref).set_tracking_branch(ref)
|
|
logging.info('=== Working on: %s ===' % branch)
|
|
branch.checkout()
|
|
origin.pull(rebase=True)
|
|
logging.info('branch pulled and checked out')
|
|
update_current_branch(name)
|
|
assert not repo.index.diff(None)
|
|
logging.info('branch is done')
|
|
logging.info('')
|