mirror of
https://github.com/rpm-software-management/tito.git
synced 2025-02-23 20:22:46 +00:00
add new build class distributionbuilder
This commit is contained in:
parent
8c812d0854
commit
64fdac6c79
5 changed files with 223 additions and 30 deletions
139
bin/generate-patches.pl
Executable file
139
bin/generate-patches.pl
Executable file
|
@ -0,0 +1,139 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings FATAL => 'all';
|
||||||
|
|
||||||
|
use Getopt::Long ();
|
||||||
|
use IPC::Open3 ();
|
||||||
|
|
||||||
|
my $target_directory;
|
||||||
|
|
||||||
|
sub usage {
|
||||||
|
die "Usage: $0 -d target_directory package_name start_version_release end_version_release [commit_id]\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
sub check_git_tag {
|
||||||
|
my $tag = join_tag_parts(@_);
|
||||||
|
my ($wtr, $rdr);
|
||||||
|
|
||||||
|
my $pid = IPC::Open3::open3($wtr, $rdr, undef, 'git', 'tag', '-l', $tag);
|
||||||
|
close($wtr);
|
||||||
|
my $check = <$rdr>;
|
||||||
|
close($rdr);
|
||||||
|
if (waitpid($pid, 0) < 0) {
|
||||||
|
die "Error checking for tag [$tag], process died: $!\n";
|
||||||
|
}
|
||||||
|
if (not defined $check) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
chomp $check;
|
||||||
|
if ($check eq $tag) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub split_version_to_parts {
|
||||||
|
my $version = shift;
|
||||||
|
my @parts1 = split /-/, $version;
|
||||||
|
my @parts2;
|
||||||
|
for my $p (@parts1) {
|
||||||
|
push @parts2, [ split /\./, $p ];
|
||||||
|
}
|
||||||
|
return @parts2;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub join_tag_parts {
|
||||||
|
my @parts = @_;
|
||||||
|
for my $p (@parts) {
|
||||||
|
if (ref $p) {
|
||||||
|
$p = join '.', @$p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return join '-', @parts;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not Getopt::Long::GetOptions('dir=s' => \$target_directory)) {
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not defined $target_directory) {
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
my ($package, $start_version, $end_version, $commit_id) = @ARGV;
|
||||||
|
|
||||||
|
if (not defined $end_version) {
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not -d $target_directory) {
|
||||||
|
die "The target directory [$target_directory] does not exist.\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not check_git_tag($package, $start_version)) {
|
||||||
|
die "Start tag [$package-$start_version] does not exist.\n";
|
||||||
|
}
|
||||||
|
if (not check_git_tag($package, $end_version)) {
|
||||||
|
die "End tag [$package-$end_version] does not exist.\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
my @start_version = split_version_to_parts($start_version);
|
||||||
|
my @end_version = split_version_to_parts($end_version);
|
||||||
|
|
||||||
|
if (@start_version != 2) {
|
||||||
|
die "Start version needs to have two segments (version-release).\n";
|
||||||
|
}
|
||||||
|
if ("@{$start_version[1]}" ne "1") {
|
||||||
|
die "The start second segment (release) has to be 1.\n";
|
||||||
|
}
|
||||||
|
if (@end_version < @start_version) {
|
||||||
|
die "End version needs to have the same or more segments than the start version..\n";
|
||||||
|
}
|
||||||
|
if ("@{$start_version[0]}" ne "@{$end_version[0]}") {
|
||||||
|
die "The first segment (version) has to match.\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
my @path;
|
||||||
|
|
||||||
|
unshift @path, join_tag_parts($package, @end_version);
|
||||||
|
while ("@{$end_version[1]}" ne "1") {
|
||||||
|
my @release = @{$end_version[1]};
|
||||||
|
if ($release[-1] eq '0') {
|
||||||
|
splice @release, $#release;
|
||||||
|
} elsif ($release[-1] =~ /^[0-9]+$/) {
|
||||||
|
$release[-1] -= 1;
|
||||||
|
} else {
|
||||||
|
# drop non-numerical segment
|
||||||
|
splice @release, $#release;
|
||||||
|
}
|
||||||
|
$end_version[1] = \@release;
|
||||||
|
my $tag = join_tag_parts($package, @end_version);
|
||||||
|
if (check_git_tag($tag)) {
|
||||||
|
unshift @path, $tag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (@end_version > @start_version) {
|
||||||
|
splice @end_version, $#end_version;
|
||||||
|
my $tag = join_tag_parts($package, @end_version);
|
||||||
|
if (check_git_tag($tag)) {
|
||||||
|
unshift @path, $tag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (my $i = 0; $i < @path - 1; $i++) {
|
||||||
|
my $patch_name = "$path[$i]-to-$path[$i + 1].patch";
|
||||||
|
system "git diff --relative $path[$i]..$path[$i + 1] > $target_directory/$patch_name";
|
||||||
|
print "$patch_name\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defined $commit_id) {
|
||||||
|
my $patch_name = "$path[$#path]-to-$package-git-$commit_id.patch";
|
||||||
|
system "git diff --relative $path[$#path]..$commit_id > $target_directory/$patch_name";
|
||||||
|
if (-s "$target_directory/$patch_name") {
|
||||||
|
print "$patch_name\n";
|
||||||
|
} else {
|
||||||
|
unlink "$target_directory/$patch_name";
|
||||||
|
}
|
||||||
|
}
|
1
setup.py
1
setup.py
|
@ -40,6 +40,7 @@ setup(
|
||||||
'bin/bump-version.pl',
|
'bin/bump-version.pl',
|
||||||
'bin/tar-fixup-stamp-comment.pl',
|
'bin/tar-fixup-stamp-comment.pl',
|
||||||
'bin/test-setup-specfile.pl',
|
'bin/test-setup-specfile.pl',
|
||||||
|
'bin/generate-patches.pl'
|
||||||
],
|
],
|
||||||
|
|
||||||
classifiers = [
|
classifiers = [
|
||||||
|
|
|
@ -933,37 +933,10 @@ class UpstreamBuilder(NoTgzBuilder):
|
||||||
|
|
||||||
self.patch_upstream()
|
self.patch_upstream()
|
||||||
|
|
||||||
def patch_upstream(self):
|
def _patch_upstream(self):
|
||||||
|
""" Insert patches into the spec file we'll be building
|
||||||
|
returns (patch_number, patch_insert_index, patch_apply_index, lines)
|
||||||
"""
|
"""
|
||||||
Generate patches for any differences between our tag and the
|
|
||||||
upstream tag, and apply them into an exported copy of the
|
|
||||||
spec file.
|
|
||||||
"""
|
|
||||||
patch_filename = "%s-to-%s-%s.patch" % (self.upstream_tag,
|
|
||||||
self.project_name, self.build_version)
|
|
||||||
patch_file = os.path.join(self.rpmbuild_gitcopy,
|
|
||||||
patch_filename)
|
|
||||||
patch_dir = self.git_root
|
|
||||||
if self.relative_project_dir != "/":
|
|
||||||
patch_dir = os.path.join(self.git_root,
|
|
||||||
self.relative_project_dir)
|
|
||||||
os.chdir(patch_dir)
|
|
||||||
debug("patch dir = %s" % patch_dir)
|
|
||||||
print("Generating patch [%s]" % patch_filename)
|
|
||||||
debug("Patch: %s" % patch_file)
|
|
||||||
patch_command = "git diff --relative %s..%s > %s" % \
|
|
||||||
(self.upstream_tag, self.git_commit_id,
|
|
||||||
patch_file)
|
|
||||||
debug("Generating patch with: %s" % patch_command)
|
|
||||||
output = run_command(patch_command)
|
|
||||||
print(output)
|
|
||||||
# Creating two copies of the patch here in the temp build directories
|
|
||||||
# just out of laziness. Some builders need sources in SOURCES and
|
|
||||||
# others need them in the git copy. Being lazy here avoids one-off
|
|
||||||
# hacks and both copies get cleaned up anyhow.
|
|
||||||
run_command("cp %s %s" % (patch_file, self.rpmbuild_sourcedir))
|
|
||||||
|
|
||||||
# Insert patches into the spec file we'll be building:
|
|
||||||
f = open(self.spec_file, 'r')
|
f = open(self.spec_file, 'r')
|
||||||
lines = f.readlines()
|
lines = f.readlines()
|
||||||
f.close()
|
f.close()
|
||||||
|
@ -998,11 +971,47 @@ class UpstreamBuilder(NoTgzBuilder):
|
||||||
debug("patch_apply_index = %s" % patch_apply_index)
|
debug("patch_apply_index = %s" % patch_apply_index)
|
||||||
if patch_insert_index == 0 or patch_apply_index == 0:
|
if patch_insert_index == 0 or patch_apply_index == 0:
|
||||||
error_out("Unable to insert PatchX or %patchX lines in spec file")
|
error_out("Unable to insert PatchX or %patchX lines in spec file")
|
||||||
|
return (patch_number, patch_insert_index, patch_apply_index, lines)
|
||||||
|
|
||||||
|
def patch_upstream(self):
|
||||||
|
"""
|
||||||
|
Generate patches for any differences between our tag and the
|
||||||
|
upstream tag, and apply them into an exported copy of the
|
||||||
|
spec file.
|
||||||
|
"""
|
||||||
|
patch_filename = "%s-to-%s-%s.patch" % (self.upstream_tag,
|
||||||
|
self.project_name, self.build_version)
|
||||||
|
patch_file = os.path.join(self.rpmbuild_gitcopy,
|
||||||
|
patch_filename)
|
||||||
|
patch_dir = self.git_root
|
||||||
|
if self.relative_project_dir != "/":
|
||||||
|
patch_dir = os.path.join(self.git_root,
|
||||||
|
self.relative_project_dir)
|
||||||
|
os.chdir(patch_dir)
|
||||||
|
debug("patch dir = %s" % patch_dir)
|
||||||
|
print("Generating patch [%s]" % patch_filename)
|
||||||
|
debug("Patch: %s" % patch_file)
|
||||||
|
patch_command = "git diff --relative %s..%s > %s" % \
|
||||||
|
(self.upstream_tag, self.git_commit_id,
|
||||||
|
patch_file)
|
||||||
|
debug("Generating patch with: %s" % patch_command)
|
||||||
|
output = run_command(patch_command)
|
||||||
|
print(output)
|
||||||
|
# Creating two copies of the patch here in the temp build directories
|
||||||
|
# just out of laziness. Some builders need sources in SOURCES and
|
||||||
|
# others need them in the git copy. Being lazy here avoids one-off
|
||||||
|
# hacks and both copies get cleaned up anyhow.
|
||||||
|
run_command("cp %s %s" % (patch_file, self.rpmbuild_sourcedir))
|
||||||
|
|
||||||
|
(patch_number, patch_insert_index, patch_apply_index, lines) = self._patch_upstream()
|
||||||
|
|
||||||
lines.insert(patch_insert_index, "Patch%s: %s\n" % (patch_number,
|
lines.insert(patch_insert_index, "Patch%s: %s\n" % (patch_number,
|
||||||
patch_filename))
|
patch_filename))
|
||||||
lines.insert(patch_apply_index, "%%patch%s -p1\n" % (patch_number))
|
lines.insert(patch_apply_index, "%%patch%s -p1\n" % (patch_number))
|
||||||
|
self._write_spec(lines)
|
||||||
|
|
||||||
|
def _write_spec(self, lines):
|
||||||
|
""" Write 'lines' to self.spec_file """
|
||||||
# Now write out the modified lines to the spec file copy:
|
# Now write out the modified lines to the spec file copy:
|
||||||
f = open(self.spec_file, 'w')
|
f = open(self.spec_file, 'w')
|
||||||
for line in lines:
|
for line in lines:
|
||||||
|
|
43
src/tito/distributionbuilder.py
Normal file
43
src/tito/distributionbuilder.py
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
import os
|
||||||
|
|
||||||
|
from tito.builder import UpstreamBuilder
|
||||||
|
from tito.common import debug, run_command
|
||||||
|
|
||||||
|
class DistributionBuilder(UpstreamBuilder):
|
||||||
|
""" This class is used for building packages for distributions.
|
||||||
|
Parent class UpstreamBuilder build one big patch from upstream and create e.g.:
|
||||||
|
Patch0: foo-1.2.13-1-to-foo-1.2.13-3-sat.patch
|
||||||
|
This class create one patch per each release. E.g.:
|
||||||
|
Patch0: foo-1.2.13-1-to-foo-1.2.13-2-sat.patch
|
||||||
|
Patch1: foo-1.2.13-2-to-foo-1.2.13-3-sat.patch
|
||||||
|
"""
|
||||||
|
def __init__(self, name=None, version=None, tag=None, build_dir=None,
|
||||||
|
pkg_config=None, global_config=None, user_config=None, dist=None,
|
||||||
|
test=False, offline=False, auto_install=False,
|
||||||
|
rpmbuild_options=None):
|
||||||
|
UpstreamBuilder.__init__(self, name, version, tag, build_dir, pkg_config,
|
||||||
|
global_config, user_config, dist, test, offline, auto_install, rpmbuild_options)
|
||||||
|
self.patch_files = []
|
||||||
|
|
||||||
|
def patch_upstream(self):
|
||||||
|
""" Create one patch per each release """
|
||||||
|
os.chdir(os.path.join(self.git_root, self.relative_project_dir))
|
||||||
|
debug("Running /usr/bin/generate-patches.pl -d %s %s %s-1 %s %s" \
|
||||||
|
% self.rpmbuild_gitcopy, self.project_name, self.upstream_version, self.build_version, self.git_commit_id)
|
||||||
|
output = run_command("/usr/bin/generate-patches.pl -d %s %s %s-1 %s %s" \
|
||||||
|
% self.rpmbuild_gitcopy, self.project_name, self.upstream_version, self.build_version, self.git_commit_id)
|
||||||
|
self.patch_files = output.split("\n")
|
||||||
|
for p_file in self.patch_files:
|
||||||
|
run_command("cp %s/%s %s" % (self.rpmbuild_gitcopy, p_file, self.rpmbuild_sourcedir))
|
||||||
|
|
||||||
|
(patch_number, patch_insert_index, patch_apply_index, lines) = self._patch_upstream()
|
||||||
|
|
||||||
|
for patch in self.patch_files:
|
||||||
|
lines.insert(patch_insert_index, "Patch%s: %s\n" % (patch_number, patch))
|
||||||
|
lines.insert(patch_apply_index, "%%patch%s -p1\n" % (patch_number))
|
||||||
|
patch_number += 1
|
||||||
|
patch_insert_index += 1
|
||||||
|
patch_apply_index += 2
|
||||||
|
self._write_spec(lines)
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,7 @@ rm -rf $RPM_BUILD_ROOT
|
||||||
%{_bindir}/bump-version.pl
|
%{_bindir}/bump-version.pl
|
||||||
%{_bindir}/tar-fixup-stamp-comment.pl
|
%{_bindir}/tar-fixup-stamp-comment.pl
|
||||||
%{_bindir}/test-setup-specfile.pl
|
%{_bindir}/test-setup-specfile.pl
|
||||||
|
%{_bindir}/generate-patches.pl
|
||||||
%dir %{python_sitelib}/tito
|
%dir %{python_sitelib}/tito
|
||||||
%{python_sitelib}/tito/*
|
%{python_sitelib}/tito/*
|
||||||
%{python_sitelib}/tito-*.egg-info
|
%{python_sitelib}/tito-*.egg-info
|
||||||
|
|
Loading…
Add table
Reference in a new issue