Skip to content

Commit 936e093

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 936e093

2 files changed

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

0 commit comments

Comments
 (0)