add new build class distributionbuilder

This commit is contained in:
Miroslav Suchý 2010-11-25 17:57:00 +01:00
parent 8c812d0854
commit 64fdac6c79
5 changed files with 223 additions and 30 deletions

139
bin/generate-patches.pl Executable file
View 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";
}
}

View file

@ -40,6 +40,7 @@ setup(
'bin/bump-version.pl',
'bin/tar-fixup-stamp-comment.pl',
'bin/test-setup-specfile.pl',
'bin/generate-patches.pl'
],
classifiers = [

View file

@ -933,37 +933,10 @@ class UpstreamBuilder(NoTgzBuilder):
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')
lines = f.readlines()
f.close()
@ -998,11 +971,47 @@ class UpstreamBuilder(NoTgzBuilder):
debug("patch_apply_index = %s" % patch_apply_index)
if patch_insert_index == 0 or patch_apply_index == 0:
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,
patch_filename))
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:
f = open(self.spec_file, 'w')
for line in lines:

View 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)

View file

@ -60,6 +60,7 @@ rm -rf $RPM_BUILD_ROOT
%{_bindir}/bump-version.pl
%{_bindir}/tar-fixup-stamp-comment.pl
%{_bindir}/test-setup-specfile.pl
%{_bindir}/generate-patches.pl
%dir %{python_sitelib}/tito
%{python_sitelib}/tito/*
%{python_sitelib}/tito-*.egg-info