forked from openSUSE/osc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbuild_rpm.py
executable file
·150 lines (124 loc) · 4.54 KB
/
build_rpm.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#!/usr/bin/python3
import argparse
import glob
import os
import re
from subprocess import check_output, run
PACKAGE_PRERELEASE_RE = re.compile(r"(?<=[\.\d])(?P<prerelease>a|alpha|b|beta|c|rc|pre|preview)(?P<num>\d*)$")
SPEC_VERSION_RE = re.compile(r"^(?P<version_tag>Version:[ \t]*).*", re.M)
class Git:
def __init__(self, workdir=None):
self.workdir = workdir
self._topdir = None
@property
def topdir(self):
if not self._topdir:
cmd = ["git", "rev-parse", "--show-toplevel"]
self._topdir = check_output(cmd, cwd=self.workdir, encoding="utf-8").strip()
return self._topdir
def describe(self):
cmd = ["git", "describe", "--tags", "--abbrev=0"]
git_tag = check_output(cmd, cwd=self.workdir, encoding="utf-8").strip()
cmd = ["git", "describe", "--tags"]
desc = check_output(cmd, cwd=self.workdir, encoding="utf-8").strip()
if desc == git_tag:
# we're at the latest git tag
git_commits = 0
git_hash = None
else:
# there are additional commits on top of the latest tag
_, git_commits, git_hash = desc.rsplit("-", 2)
git_commits = int(git_commits)
git_hash = git_hash[1:]
return git_tag, git_commits, git_hash
def get_package_version(self):
"""
Return package version based on a git tag.
Pre-releases will be prefixed with '~' to comply with RPM pre-release versioning.
"""
git_tag, git_commits, git_hash = self.describe()
version = PACKAGE_PRERELEASE_RE.sub(r"~\g<prerelease>\g<num>", git_tag)
if git_commits:
version += f".{git_commits}.g{git_hash}"
return version
def archive(self, pkg_name, destdir=None):
pkg_version = self.get_package_version()
prefix = f"{pkg_name}-{pkg_version}"
destdir = destdir or self.topdir
tar_path = os.path.abspath(os.path.join(destdir, f"{prefix}.tar.gz"))
cmd = ["git", "archive", "--format=tar.gz", f"--prefix={prefix}/", "HEAD", f"--output={tar_path}"]
run(cmd, check=True, cwd=self.topdir)
return tar_path
class Spec:
@classmethod
def find(cls, topdir):
paths = ["", "contrib"]
for path in paths:
spec_paths = glob.glob(os.path.join(topdir, path, "*.spec"))
if spec_paths:
return cls(spec_paths[0])
raise RuntimeError(f"Couldn't find spec under {topdir}")
def __init__(self, path):
self.path = os.path.abspath(path)
self.topdir = os.path.dirname(self.path)
self._name = None
@property
def name(self):
if not self._name:
cmd = ["rpmspec", self.path, "-q", "--qf=%{name}"]
self._name = check_output(cmd, encoding="utf-8").strip()
return self._name
def set_version(self, version):
with open(self.path, "r+", encoding="utf-8") as f:
data = f.read()
new_data = SPEC_VERSION_RE.sub(fr"\g<version_tag>{version}", data)
f.seek(0)
f.write(new_data)
f.truncate()
def build(self, srpm=True, rpm=True, nodeps=False):
cmd = [
"rpmbuild",
self.path,
"--define", f"_sourcedir {self.topdir}",
"--define", f"_srcrpmdir {self.topdir}",
"--define", f"_rpmdir {self.topdir}",
]
if srpm and rpm:
cmd.append("-ba")
elif srpm:
cmd.append("-bs")
elif rpm:
cmd.append("-bb")
if nodeps:
cmd.append("--nodeps")
env = os.environ.copy()
env["LC_ALL"] = "C.UTF-8"
env["LANGUAGE"] = "C"
run(cmd, check=True, encoding="utf-8", cwd=self.topdir, env=env)
def main():
parser = argparse.ArgumentParser()
parser.add_argument(
"--rpm",
action="store_true",
help="Build binary RPMs",
)
parser.add_argument(
"--srpm",
action="store_true",
help="Build source RPM",
)
parser.add_argument(
"--nodeps",
action="store_true",
help="Do not verify build dependencies",
)
args = parser.parse_args()
if not args.rpm and not args.srpm:
parser.error('No build output specified. Please specify --rpm, --srpm or both.')
git = Git()
spec = Spec.find(git.topdir)
git.archive(spec.name, destdir=spec.topdir)
spec.set_version(git.get_package_version())
spec.build(srpm=args.srpm, rpm=args.rpm, nodeps=args.nodeps)
if __name__ == "__main__":
main()