Move PREFERRED_DEBUGGING_TYPE define in pa64-hpux.h to pa.h
[official-gcc.git] / contrib / gcc-changelog / git_update_version.py
blob1837c1a8d7fafcf658e3a6cf112fcfea12d9e8be
1 #!/usr/bin/env python3
3 # This file is part of GCC.
5 # GCC is free software; you can redistribute it and/or modify it under
6 # the terms of the GNU General Public License as published by the Free
7 # Software Foundation; either version 3, or (at your option) any later
8 # version.
10 # GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 # WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 # for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with GCC; see the file COPYING3. If not see
17 # <http://www.gnu.org/licenses/>. */
19 import argparse
20 import datetime
21 import os
23 from git import Repo
25 from git_repository import parse_git_revisions
27 current_timestamp = datetime.datetime.now().strftime('%Y%m%d\n')
29 # Skip the following commits, they cannot be correctly processed
30 IGNORED_COMMITS = (
31 'c2be82058fb40f3ae891c68d185ff53e07f14f45',
32 '04a040d907a83af54e0a98bdba5bfabc0ef4f700',
33 '2e96b5f14e4025691b57d2301d71aa6092ed44bc')
36 def read_timestamp(path):
37 with open(path) as f:
38 return f.read()
41 def prepend_to_changelog_files(repo, folder, git_commit, add_to_git):
42 if not git_commit.success:
43 for error in git_commit.errors:
44 print(error)
45 raise AssertionError()
46 for entry, output in git_commit.to_changelog_entries(use_commit_ts=True):
47 full_path = os.path.join(folder, entry, 'ChangeLog')
48 print('writing to %s' % full_path)
49 if os.path.exists(full_path):
50 with open(full_path) as f:
51 content = f.read()
52 else:
53 content = ''
54 with open(full_path, 'w+') as f:
55 f.write(output)
56 if content:
57 f.write('\n\n')
58 f.write(content)
59 if add_to_git:
60 repo.git.add(full_path)
63 active_refs = ['master', 'releases/gcc-9', 'releases/gcc-10',
64 'releases/gcc-11']
66 parser = argparse.ArgumentParser(description='Update DATESTAMP and generate '
67 'ChangeLog entries')
68 parser.add_argument('-g', '--git-path', default='.',
69 help='Path to git repository')
70 parser.add_argument('-p', '--push', action='store_true',
71 help='Push updated active branches')
72 parser.add_argument('-d', '--dry-mode',
73 help='Generate patch for ChangeLog entries and do it'
74 ' even if DATESTAMP is unchanged; folder argument'
75 ' is expected')
76 parser.add_argument('-c', '--current', action='store_true',
77 help='Modify current branch (--push argument is ignored)')
78 args = parser.parse_args()
80 repo = Repo(args.git_path)
81 origin = repo.remotes['origin']
84 def update_current_branch(ref_name):
85 commit = repo.head.commit
86 commit_count = 1
87 while commit:
88 if (commit.author.email == 'gccadmin@gcc.gnu.org'
89 and commit.message.strip() == 'Daily bump.'):
90 break
91 # We support merge commits but only with 2 parensts
92 assert len(commit.parents) <= 2
93 commit = commit.parents[-1]
94 commit_count += 1
96 print('%d revisions since last Daily bump' % commit_count)
97 datestamp_path = os.path.join(args.git_path, 'gcc/DATESTAMP')
98 if (read_timestamp(datestamp_path) != current_timestamp
99 or args.dry_mode or args.current):
100 head = repo.head.commit
101 # if HEAD is a merge commit, start with second parent
102 # (branched that is being merged into the current one)
103 assert len(head.parents) <= 2
104 if len(head.parents) == 2:
105 head = head.parents[1]
106 commits = parse_git_revisions(args.git_path, '%s..%s'
107 % (commit.hexsha, head.hexsha), ref_name)
108 commits = [c for c in commits if c.info.hexsha not in IGNORED_COMMITS]
109 for git_commit in reversed(commits):
110 prepend_to_changelog_files(repo, args.git_path, git_commit,
111 not args.dry_mode)
112 if args.dry_mode:
113 diff = repo.git.diff('HEAD')
114 patch = os.path.join(args.dry_mode,
115 branch.name.split('/')[-1] + '.patch')
116 with open(patch, 'w+') as f:
117 f.write(diff)
118 print('branch diff written to %s' % patch)
119 repo.git.checkout(force=True)
120 else:
121 # update timestamp
122 print('DATESTAMP will be changed:')
123 with open(datestamp_path, 'w+') as f:
124 f.write(current_timestamp)
125 repo.git.add(datestamp_path)
126 if not args.current:
127 repo.index.commit('Daily bump.')
128 if args.push:
129 repo.git.push('origin', branch)
130 print('branch is pushed')
131 else:
132 print('DATESTAMP unchanged')
135 if args.current:
136 print('=== Working on the current branch ===', flush=True)
137 update_current_branch()
138 else:
139 for ref in origin.refs:
140 assert ref.name.startswith('origin/')
141 name = ref.name[len('origin/'):]
142 if name in active_refs:
143 if name in repo.branches:
144 branch = repo.branches[name]
145 else:
146 branch = repo.create_head(name, ref).set_tracking_branch(ref)
147 print('=== Working on: %s ===' % branch, flush=True)
148 branch.checkout()
149 origin.pull(rebase=True)
150 print('branch pulled and checked out')
151 update_current_branch(name)
152 assert not repo.index.diff(None)
153 print('branch is done\n', flush=True)