ubuntu-dev-tools/dch-repeat
2011-01-22 21:58:22 +02:00

193 lines
5.7 KiB
Perl
Executable File

#!/usr/bin/perl
#
# Copyright (C) 2007-2008 Canonical, Ltd.,
# 2011, Stefano Rivera <stefanor@ubuntu.com>
# Author: Kees Cook <kees@ubuntu.com>
#
# ##################################################################
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# See file /usr/share/common-licenses/GPL for more details.
#
# ##################################################################
#
# This script is used to repeat a change log into an older release. It
# expects that --build-tree is laid out with each Ubuntu release as a
# separate directory ("feisty", "edgy", etc).
#
# For example, if gimp had a security update prepared for Feisty in
# $TREE/feisty/gimp-2.2.13, running "dch-repeat" in
# $TREE/edgy/gimp-2.2.13 would pull in the latest changelog from the Feisty
# build.
use strict;
use warnings;
use Getopt::Long;
use Cwd;
use File::Glob ':glob';
sub Usage
{
print <<EOM;
Usage: $0 [OPTIONS]
--build-tree PATH Base of build trees
-s, --source-release RELEASE Which release to snag a changelog from
--target-release RELEASE Which release to build into
--devel-release RELEASE Which release is the devel release
--pocket POCKET Which pocket to use
EOM
exit(0);
}
my @releases = undef;
our $devel_release = undef;
#Getopt::Long::Configure("bundling", "no_ignore_case");
our $opt_build_tree = "/scratch/ubuntu/build";
our $opt_pocket = undef;
our $opt_package = undef;
our $opt_source_release = undef;
our $opt_target_release = undef;
our $opt_help = undef;
our $opt_verbose = undef;
Usage() unless (GetOptions(
"build-tree=s",
"source-release|s=s",
"target-release=s",
"package|p=s",
"help|h",
"verbose|v",
));
Usage() if ($opt_help);
@releases = split(/\s+/, `ubuntu-distro-info --supported`);
$devel_release = `ubuntu-distro-info --devel`;
chomp($devel_release);
sub get_changelog($)
{
my ($path) = @_;
open(LOG,"<$path/debian/changelog") || die "Cannot find changelog for '$path'\n";
my $log="";
my $line="";
# Skip to package name
$line = <LOG>;
# Collect changelog
while ($line=<LOG>) {
last if ($line=~/^\S/); # Stop on next changelog entry
$log.=$line;
}
close(LOG);
return $log;
}
sub replace_changelog($)
{
my ($log) = @_;
open(LOG,"<debian/changelog") || die "Cannot find changelog\n";
open(NEWLOG,">debian/changelog.new") || die "Cannot write changelog\n";
my $line;
while ($line=<LOG>) {
last if ($line =~ /^\s*$/);
print NEWLOG $line || die "Changelog write failed: $!\n";
}
print NEWLOG $log || die "Changelog write failed: $!\n";
# Skip log items
while ($line=<LOG>) {
last if ($line =~ /^\S/);
}
print NEWLOG $line || die "Changelog write failed: $!\n";
while ($line=<LOG>) {
print NEWLOG $line || die "Changelog write failed: $!\n";
}
close(LOG);
close(NEWLOG) || die "Changelog close failed: $!\n";
rename("debian/changelog.new","debian/changelog") || die "Changelog rename failed: $!\n";
}
# By default examine Cwd for target release
if (!defined($opt_target_release)) {
my $dir = getcwd;
if ($dir =~ m#^$opt_build_tree/([^/]+)/[^/]+$#) {
$opt_target_release = $1;
}
else {
die "No --target-release used, or current directory '$dir' outside of --build-tree of '$opt_build_tree'\n";
}
}
warn "target-release: '$opt_target_release'\n" if ($opt_verbose);
# By default, examine changelog for package
if (!defined($opt_package)) {
chomp($opt_package=`dpkg-parsechangelog | grep ^"Source: " | cut -d" " -f2`);
if ($opt_package eq "") {
die "Cannot figure out package name from changelog\n";
}
}
warn "package: '$opt_package\n" if ($opt_verbose);
# By default, take changelog from newer release
if (!defined($opt_source_release)) {
if ($opt_target_release eq $devel_release) {
die "No more recent release than '$devel_release' to take changelog from\n";
}
foreach my $i (0 .. $#releases) {
if ($releases[$i] eq $opt_target_release) {
$opt_source_release = $releases[$i+1];
}
}
if (!defined($opt_source_release)) {
die "Could not locate a newer release than '$releases[$#releases]'";
}
}
warn "source-release: '$opt_source_release\n" if ($opt_verbose);
warn "devel-release: '$devel_release\n" if ($opt_verbose);
# By default, use "security" pocket for non-devel releases
if (!defined($opt_pocket)) {
if ($opt_target_release eq $devel_release) {
$opt_pocket = "";
}
else {
$opt_pocket = "security";
}
}
warn "pocket: '$opt_pocket'\n" if ($opt_verbose);
# Source location
my @dirs = grep((-d $_),bsd_glob("$opt_build_tree/$opt_source_release/$opt_package-*"));
if (scalar(@dirs)==0) {
die "Cannot find '$opt_build_tree/$opt_source_release/$opt_package-*'\n";
}
elsif (scalar(@dirs)>1) {
warn "Multiple possible source dirs, using '$dirs[0]'\n";
}
warn "source dir: '$dirs[0]'\n" if ($opt_verbose);
my $log = get_changelog($dirs[0]);
my $args = "";
if ($opt_pocket ne "") {
$args = "-s -D $opt_target_release-$opt_pocket";
}
else {
$args = "-i";
}
system("dch $args auto-changelog")==0 || die "dch failed: $!\n";
replace_changelog($log);
# Report!
system("dpkg-parsechangelog");
exit(0);