Skip to content

Commit 98388b1

Browse files
committed
[LTR] Use update_lt_spec.py for spec update
Python will be easier to extend in the future when we need to update the spec for more than just rebases.
1 parent 162aa30 commit 98388b1

2 files changed

Lines changed: 260 additions & 51 deletions

File tree

lt_rebase.sh

Lines changed: 20 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -150,66 +150,35 @@ fi
150150

151151
SPEC_FILE="./ciq/SPECS/kernel.spec"
152152
if [ -f "$SPEC_FILE" ] ; then
153-
UPSTREAM_TAG=$(git describe --tags --abbrev=0)
154-
if [ -z "$UPSTREAM_TAG" ]; then
155-
echo "ERROR: Could not determine upstream tag via git describe. Cannot update spec."
156-
exit 1
157-
fi
158-
FULL_KERNEL_VERSION=${UPSTREAM_TAG#v}
159-
TAG_VERSION="${FULL_KERNEL_VERSION}-1"
160-
NEW_TAG="ciq_kernel-${TAG_VERSION}"
153+
echo "Updating kernel.spec version variables and changelog..."
154+
155+
# Set default values for DISTLOCALVERSION and DIST if not set
161156
DISTLOCALVERSION=${DISTLOCALVERSION:-".1.0.0"}
162157
DIST=${DIST:-".el9_clk"}
163-
SPECTARFILE_RELEASE=${TAG_VERSION}$DISTLOCALVERSION$DIST
164158

165-
echo "Updating kernel.spec version variables and changelog..."
159+
# Get the directory where this script is located
160+
SCRIPT_DIR="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"
166161

167-
# Update version variables
168-
sed -i -e "s/^%define specrpmversion .*/%define specrpmversion $FULL_KERNEL_VERSION/" \
169-
-e "s/^%define specversion .*/%define specversion $FULL_KERNEL_VERSION/" \
170-
-e "s/^%define tarfile_release .*/%define tarfile_release $SPECTARFILE_RELEASE/" \
171-
"$SPEC_FILE"
172-
173-
# Generate changelog
174-
# Extract major version (e.g., 6 from 6.12.74)
175-
MAJOR_VERSION=${FULL_KERNEL_VERSION%%.*}
176-
CHANGELOG_DATE=$(date '+%a %b %d %Y')
177-
CHANGELOG_HEADER="* $CHANGELOG_DATE $(git config user.name) <$(git config user.email)> - ${TAG_VERSION}${DISTLOCALVERSION}${DIST}"
178-
TEMP_CHANGELOG=$(mktemp)
179-
TEMP_COMMENTS=$(mktemp)
180-
181-
# Full changelog for new kernel version or initial spec update
182-
echo "$CHANGELOG_HEADER" > "$TEMP_CHANGELOG"
183-
echo "-- Rebased changes for Linux $FULL_KERNEL_VERSION (https://github.com/ctrliq/kernel-src-tree/releases/tag/$NEW_TAG)" >> "$TEMP_CHANGELOG"
184-
git log --no-merges --pretty=format:"-- %s (%an)" ${UPSTREAM_TAG}..HEAD >> "$TEMP_CHANGELOG"
185-
echo "" >> "$TEMP_CHANGELOG"
186-
echo "-- Linux $FULL_KERNEL_VERSION (https://cdn.kernel.org/pub/linux/kernel/v$MAJOR_VERSION.x/ChangeLog-$FULL_KERNEL_VERSION)" >> "$TEMP_CHANGELOG"
187-
echo "" >> "$TEMP_CHANGELOG"
188-
echo "" >> "$TEMP_CHANGELOG"
189-
190-
# Extract trailing comments (lines starting with # after %changelog)
191-
awk '/^%changelog$/,0 {if (/^#/ || /^###/) print}' "$SPEC_FILE" > "$TEMP_COMMENTS"
192-
193-
# Rebuild changelog section
194-
if ! grep -q '^%changelog$' "$SPEC_FILE"; then
195-
echo "ERROR: %changelog section not found in $SPEC_FILE. Cannot update spec."
162+
# Path to update_lt_spec.py in the same directory as this script
163+
UPDATE_LT_SPEC="$SCRIPT_DIR/update_lt_spec.py"
164+
165+
if [ ! -f "$UPDATE_LT_SPEC" ]; then
166+
echo "ERROR: update_lt_spec.py not found at $UPDATE_LT_SPEC"
196167
exit 1
197168
fi
198-
# Remove everything from %changelog onwards
199-
sed -i '/^%changelog$/q' "$SPEC_FILE"
200169

201-
# Add new changelog entry
202-
cat "$TEMP_CHANGELOG" >> "$SPEC_FILE"
170+
# Call update_lt_spec.py to update the spec file
171+
python "$UPDATE_LT_SPEC" \
172+
--srcgit . \
173+
--spec-file "$SPEC_FILE" \
174+
--distlocalversion "$DISTLOCALVERSION" \
175+
--dist "$DIST" \
176+
--commit
203177

204-
# Add trailing comments if any
205-
if [ -s "$TEMP_COMMENTS" ]; then
206-
cat "$TEMP_COMMENTS" >> "$SPEC_FILE"
178+
if [ $? -ne 0 ]; then
179+
echo "ERROR: update_lt_spec.py failed"
180+
exit 1
207181
fi
208182

209-
rm -f "$TEMP_CHANGELOG" "$TEMP_COMMENTS"
210-
211-
git add "$SPEC_FILE"
212-
git commit -m "[CIQ] $(git describe --tags --abbrev=0) - updated spec"
213-
214183
echo "Spec file updated successfully"
215184
fi

update_lt_spec.py

Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
#!/usr/bin/env python3
2+
#
3+
# coding: utf-8
4+
#
5+
# Update kernel.spec for LT (Long Term) kernel rebases.
6+
# This script updates version variables and replaces the changelog
7+
# to reflect the new upstream kernel version.
8+
9+
import argparse
10+
import os
11+
import re
12+
import sys
13+
import time
14+
15+
from ciq_helpers import last_git_tag
16+
17+
try:
18+
import git
19+
except ImportError:
20+
print('ERROR: GitPython is not installed. Install it with: pip install GitPython')
21+
sys.exit(1)
22+
23+
24+
def calculate_lt_rebase_versions(upstream_tag, distlocalversion, dist):
25+
"""Calculate version strings for LT rebase.
26+
27+
Arguments:
28+
upstream_tag: Git tag from git describe (e.g., 'v6.12.74')
29+
distlocalversion: DISTLOCALVERSION string (e.g., '.1.0.0')
30+
dist: DIST string (e.g., '.el9_clk')
31+
32+
Returns:
33+
Tuple of (full_kernel_version, tag_version, spectarfile_release, new_tag, major_version)
34+
"""
35+
# Remove 'v' prefix if present
36+
full_kernel_version = upstream_tag.lstrip('v')
37+
tag_version = f"{full_kernel_version}-1"
38+
spectarfile_release = f"{tag_version}{distlocalversion}{dist}"
39+
new_tag = f"ciq_kernel-{tag_version}"
40+
major_version = full_kernel_version.split('.')[0]
41+
42+
return full_kernel_version, tag_version, spectarfile_release, new_tag, major_version
43+
44+
45+
def update_spec_file(spec_path, full_kernel_version, spectarfile_release,
46+
lt_tag_version, lt_new_tag, lt_major_version,
47+
upstream_tag, srcgit, distlocalversion, dist):
48+
"""Update the spec file with new version information and changelog.
49+
50+
Arguments:
51+
spec_path: Path to kernel.spec file
52+
full_kernel_version: Full kernel version (e.g., '6.12.77')
53+
spectarfile_release: Value for tarfile_release variable
54+
lt_tag_version: Tag version (e.g., '6.12.77-1')
55+
lt_new_tag: New tag name (e.g., 'ciq_kernel-6.12.77-1')
56+
lt_major_version: Major version number (e.g., '6')
57+
upstream_tag: Git tag name (e.g., 'v6.12.77')
58+
srcgit: Git repository object
59+
distlocalversion: DISTLOCALVERSION string
60+
dist: DIST string
61+
"""
62+
# Read the spec file
63+
try:
64+
with open(spec_path, 'r') as f:
65+
spec = f.read().splitlines()
66+
except IOError as e:
67+
print(f'ERROR: Failed to read spec file {spec_path}: {e}')
68+
sys.exit(1)
69+
70+
# Get git user info
71+
try:
72+
config = srcgit.config_reader()
73+
name = config.get_value("user", "name")
74+
email = config.get_value("user", "email")
75+
except Exception as e:
76+
print(f'ERROR: Failed to read git config. Please ensure user.name and user.email are configured.')
77+
print(f' Run: git config --global user.name "Your Name"')
78+
print(f' Run: git config --global user.email "your.email@example.com"')
79+
print(f' Error details: {e}')
80+
sys.exit(1)
81+
82+
new_spec = []
83+
for line in spec:
84+
# Update version variables
85+
if line.startswith('%define specrpmversion'):
86+
line = f'%define specrpmversion {full_kernel_version}'
87+
new_spec.append(line)
88+
continue
89+
90+
if line.startswith('%define specversion'):
91+
line = f'%define specversion {full_kernel_version}'
92+
new_spec.append(line)
93+
continue
94+
95+
if line.startswith('%define tarfile_release'):
96+
line = f'%define tarfile_release {spectarfile_release}'
97+
new_spec.append(line)
98+
continue
99+
100+
# Replace changelog
101+
if line.startswith('%changelog'):
102+
new_spec.append(line)
103+
104+
# Generate changelog header
105+
changelog_date = time.strftime('%a %b %d %Y')
106+
changelog_header = f'* {changelog_date} {name} <{email}> - {lt_tag_version}{distlocalversion}{dist}'
107+
new_spec.append(changelog_header)
108+
new_spec.append(f'-- Rebased changes for Linux {full_kernel_version} (https://github.com/ctrliq/kernel-src-tree/releases/tag/{lt_new_tag})')
109+
110+
# Add all commits from upstream tag to HEAD
111+
try:
112+
commit_logs = srcgit.git.log('--no-merges', '--pretty=format:-- %s (%an)', f'{upstream_tag}..HEAD')
113+
for log_line in commit_logs.split('\n'):
114+
if log_line.strip():
115+
new_spec.append(log_line)
116+
except git.exc.GitCommandError as e:
117+
print(f'ERROR: Failed to get git log from {upstream_tag}..HEAD: {e}')
118+
sys.exit(1)
119+
120+
new_spec.append('')
121+
new_spec.append(f'-- Linux {full_kernel_version} (https://cdn.kernel.org/pub/linux/kernel/v{lt_major_version}.x/ChangeLog-{full_kernel_version})')
122+
new_spec.append('')
123+
new_spec.append('')
124+
125+
# Preserve trailing comments from original spec file
126+
in_changelog = False
127+
for orig_line in spec:
128+
if orig_line.startswith('%changelog'):
129+
in_changelog = True
130+
continue
131+
if in_changelog and (orig_line.startswith('#') or orig_line.startswith('###')):
132+
new_spec.append(orig_line)
133+
134+
# Skip the rest of the original changelog
135+
break
136+
137+
new_spec.append(line)
138+
139+
# Write the updated spec file
140+
try:
141+
with open(spec_path, 'w') as f:
142+
for line in new_spec:
143+
f.write(line + '\n')
144+
except IOError as e:
145+
print(f'ERROR: Failed to write spec file {spec_path}: {e}')
146+
sys.exit(1)
147+
148+
149+
if __name__ == "__main__":
150+
parser = argparse.ArgumentParser(description='Update kernel.spec for LT kernel rebase')
151+
parser.add_argument('--srcgit', required=True, help='Location of srcgit repository')
152+
parser.add_argument('--spec-file', required=True, help='Path to kernel.spec file')
153+
parser.add_argument('--distlocalversion', default='.1.0.0',
154+
help='DISTLOCALVERSION for tarfile_release (default: .1.0.0)')
155+
parser.add_argument('--dist', default='.el9_clk',
156+
help='DIST for tarfile_release (default: .el9_clk)')
157+
parser.add_argument('--commit', action='store_true',
158+
help='Commit the spec file changes to git')
159+
args = parser.parse_args()
160+
161+
# Initialize git repository
162+
srcgit_path = os.path.abspath(args.srcgit)
163+
try:
164+
srcgit = git.Repo(srcgit_path)
165+
except git.exc.InvalidGitRepositoryError:
166+
print(f'ERROR: {srcgit_path} is not a valid git repository')
167+
sys.exit(1)
168+
except git.exc.NoSuchPathError:
169+
print(f'ERROR: Path does not exist: {srcgit_path}')
170+
sys.exit(1)
171+
172+
# Get the last git tag
173+
try:
174+
upstream_tag = last_git_tag(srcgit)
175+
except Exception as e:
176+
print(f'ERROR: Failed to get last git tag: {e}')
177+
sys.exit(1)
178+
179+
print(f'Using last tag: {upstream_tag}')
180+
181+
# Validate tag format (should be like 'v6.12.74' or '6.12.74')
182+
tag_without_v = upstream_tag.lstrip('v')
183+
tag_parts = tag_without_v.split('.')
184+
if len(tag_parts) < 2:
185+
print(f'ERROR: Invalid tag format: {upstream_tag}')
186+
print(f' Expected format: vX.Y.Z or X.Y.Z (e.g., v6.12.74)')
187+
sys.exit(1)
188+
189+
# Validate that parts are numeric
190+
try:
191+
for part in tag_parts:
192+
int(part)
193+
except ValueError:
194+
print(f'ERROR: Invalid tag format: {upstream_tag}')
195+
print(f' Tag version parts must be numeric')
196+
sys.exit(1)
197+
198+
# Calculate version strings
199+
full_kernel_version, tag_version, spectarfile_release, new_tag, major_version = \
200+
calculate_lt_rebase_versions(upstream_tag, args.distlocalversion, args.dist)
201+
202+
print(f'\nLT Rebase Version Information:')
203+
print(f' Full Kernel Version: {full_kernel_version}')
204+
print(f' Tag Version: {tag_version}')
205+
print(f' Spec tarfile_release: {spectarfile_release}')
206+
print(f' New Tag: {new_tag}')
207+
print(f' Major Version: {major_version}\n')
208+
209+
# Verify spec file exists
210+
spec_path = os.path.abspath(args.spec_file)
211+
if not os.path.exists(spec_path):
212+
print(f'ERROR: Spec file not found: {spec_path}')
213+
sys.exit(1)
214+
215+
# Update the spec file
216+
print(f'Updating spec file: {spec_path}')
217+
update_spec_file(spec_path, full_kernel_version, spectarfile_release,
218+
tag_version, new_tag, major_version,
219+
upstream_tag, srcgit, args.distlocalversion, args.dist)
220+
221+
print('Spec file updated successfully')
222+
223+
# Optionally commit the changes
224+
if args.commit:
225+
print('Committing changes...')
226+
srcgit.git.add(spec_path)
227+
228+
# Check if there are changes to commit
229+
if srcgit.is_dirty(path=spec_path):
230+
commit_message = f'[CIQ] {upstream_tag} - updated spec'
231+
try:
232+
srcgit.git.commit('-m', commit_message)
233+
print(f'Committed: {commit_message}')
234+
except git.exc.GitCommandError as e:
235+
print(f'ERROR: Failed to commit changes: {e}')
236+
sys.exit(1)
237+
else:
238+
print('No changes to commit')
239+
240+
print('\nDone!')

0 commit comments

Comments
 (0)