]>
git.ipfire.org Git - thirdparty/gcc.git/blob - contrib/gcc-changelog/git_update_version.py
3 # Copyright (C) 2020-2024 Free Software Foundation, Inc.
5 # This file is part of GCC.
7 # GCC is free software; you can redistribute it and/or modify it under
8 # the terms of the GNU General Public License as published by the Free
9 # Software Foundation; either version 3, or (at your option) any later
12 # GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 # WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 # You should have received a copy of the GNU General Public License
18 # along with GCC; see the file COPYING3. If not see
19 # <http://www.gnu.org/licenses/>.
28 from git_repository
import parse_git_revisions
30 current_timestamp
= datetime
.datetime
.now().strftime('%Y%m%d\n')
32 # Skip the following commits, they cannot be correctly processed
34 'c2be82058fb40f3ae891c68d185ff53e07f14f45',
35 '04a040d907a83af54e0a98bdba5bfabc0ef4f700',
36 '2e96b5f14e4025691b57d2301d71aa6092ed44bc',
37 '3ab5c8cd03d92bf4ec41e351820349d92fbc40c4',
38 '86d8e0c0652ef5236a460b75c25e4f7093cc0651',
39 'e4cba49413ca429dc82f6aa2e88129ecb3fdd943',
40 '1957bedf29a1b2cc231972aba680fe80199d5498',
41 '040e5b0edbca861196d9e2ea2af5e805769c8d5d',
42 '8057f9aa1f7e70490064de796d7a8d42d446caf8',
43 '109f1b28fc94c93096506e3df0c25e331cef19d0',
44 '39f81924d88e3cc197fc3df74204c9b5e01e12f7')
46 FORMAT
= '%(asctime)s:%(levelname)s:%(name)s:%(message)s'
47 logging
.basicConfig(level
=logging
.INFO
, format
=FORMAT
,
49 logging
.FileHandler('/tmp/git_update_version.txt'),
50 logging
.StreamHandler()
54 def read_timestamp(path
):
59 def prepend_to_changelog_files(repo
, folder
, git_commit
, add_to_git
):
60 if not git_commit
.success
:
61 for error
in git_commit
.errors
:
63 raise AssertionError()
64 for entry
, output
in git_commit
.to_changelog_entries(use_commit_ts
=True):
65 full_path
= os
.path
.join(folder
, entry
, 'ChangeLog')
66 logging
.info('writing to %s' % full_path
)
67 if os
.path
.exists(full_path
):
68 with
open(full_path
) as f
:
72 with
open(full_path
, 'w+') as f
:
78 repo
.git
.add(full_path
)
81 active_refs
= ['master', 'releases/gcc-11',
82 'releases/gcc-12', 'releases/gcc-13', 'releases/gcc-14']
84 parser
= argparse
.ArgumentParser(description
='Update DATESTAMP and generate '
86 parser
.add_argument('-g', '--git-path', default
='.',
87 help='Path to git repository')
88 parser
.add_argument('-p', '--push', action
='store_true',
89 help='Push updated active branches')
90 parser
.add_argument('-d', '--dry-mode',
91 help='Generate patch for ChangeLog entries and do it'
92 ' even if DATESTAMP is unchanged; folder argument'
94 parser
.add_argument('-c', '--current', action
='store_true',
95 help='Modify current branch (--push argument is ignored)')
96 args
= parser
.parse_args()
98 repo
= Repo(args
.git_path
)
99 origin
= repo
.remotes
['origin']
102 def update_current_branch(ref_name
):
103 commit
= repo
.head
.commit
106 if (commit
.author
.email
== 'gccadmin@gcc.gnu.org'
107 and commit
.message
.strip() == 'Daily bump.'):
109 # We support merge commits but only with 2 parensts
110 assert len(commit
.parents
) <= 2
111 commit
= commit
.parents
[-1]
114 logging
.info('%d revisions since last Daily bump' % commit_count
)
115 datestamp_path
= os
.path
.join(args
.git_path
, 'gcc/DATESTAMP')
116 if (read_timestamp(datestamp_path
) != current_timestamp
117 or args
.dry_mode
or args
.current
):
118 head
= repo
.head
.commit
119 # if HEAD is a merge commit, start with second parent
120 # (branched that is being merged into the current one)
121 assert len(head
.parents
) <= 2
122 if len(head
.parents
) == 2:
123 head
= head
.parents
[1]
124 commits
= parse_git_revisions(args
.git_path
, '%s..%s'
125 % (commit
.hexsha
, head
.hexsha
), ref_name
)
126 commits
= [c
for c
in commits
if c
.info
.hexsha
not in IGNORED_COMMITS
]
127 for git_commit
in reversed(commits
):
128 prepend_to_changelog_files(repo
, args
.git_path
, git_commit
,
131 diff
= repo
.git
.diff('HEAD')
132 patch
= os
.path
.join(args
.dry_mode
,
133 branch
.name
.split('/')[-1] + '.patch')
134 with
open(patch
, 'w+') as f
:
136 logging
.info('branch diff written to %s' % patch
)
137 repo
.git
.checkout(force
=True)
140 logging
.info('DATESTAMP will be changed:')
141 with
open(datestamp_path
, 'w+') as f
:
142 f
.write(current_timestamp
)
143 repo
.git
.add(datestamp_path
)
145 repo
.index
.commit('Daily bump.')
146 logging
.info('commit is done')
149 repo
.git
.push('origin', branch
)
150 logging
.info('branch is pushed')
152 logging
.exception('git push failed')
154 logging
.info('DATESTAMP unchanged')
158 logging
.info('=== Working on the current branch ===')
159 update_current_branch()
161 for ref
in origin
.refs
:
162 assert ref
.name
.startswith('origin/')
163 name
= ref
.name
[len('origin/'):]
164 if name
in active_refs
:
165 if name
in repo
.branches
:
166 branch
= repo
.branches
[name
]
168 branch
= repo
.create_head(name
, ref
).set_tracking_branch(ref
)
169 logging
.info('=== Working on: %s ===' % branch
)
171 origin
.pull(rebase
=True)
172 logging
.info('branch pulled and checked out')
173 update_current_branch(name
)
174 assert not repo
.index
.diff(None)
175 logging
.info('branch is done')