#!/usr/bin/perl
eval 'exec /usr/bin/perl -S $0 ${1+"$@"}' if $running_under_some_shell; #!/usr/bin/perl
use strict;
use File::Copy;
use File::Temp qw/ tempfile tempdir /;
my %module_dirname = ( "core" => "", "dictionaries" => "dictionaries", "help" => "helpcontent2", "translations" => "translations"
);
my $lo_topdir_name;
# get libreoffice-build version from the given libreoffice-build sources
sub get_config_version($)
{
my ($lo_core_dir) = @_;
my $version;
open (CONFIGURE, "$lo_core_dir/configure.ac") ||
die "can't open \"$lo_core_dir/configure.ac\" for reading: $!\n";
while (my $line = <CONFIGURE>) {
chomp $line;
if ($line =~ /AC_INIT\s*\(\s*libreoffice-build\s*,\s*([\w\.]*)\)/) {
$version="$1";
}
}
close (CONFIGURE); return $version;
}
# increment the version for a test build: # + add 'a' if the version ended with a number # + bump the letter otherwise
sub inc_test_version($)
{
my ($version) = @_;
my $lastchar = chop $version;
my $new_version;
if ($lastchar =~ /\d/) { return"$version" . "$lastchar" . "a";
} elsif ($lastchar =~ /\w/) { # select next letter alphabetically: a->b, b->c, ...
$lastchar =~ tr/0a-zA-Z/a-zA-Z0/; return"$version" . "$lastchar";
} else {
die "Can't generate test version from \"$version$lastchar\n";
}
}
sub get_release_version($$$$)
{
my ($config_version, $state_config_version, $state_release_version, $inc_version) = @_;
my $release_version;
if ( defined $inc_version ) {
$release_version = inc_test_version($release_version);
}
return $release_version;
}
# copy files to temp dir; showing a progress; using a black list
sub copy_dir_filter_and_show_progress($$)
{
my ($source_dir, $target_dir) = @_;
print "Copying \"$source_dir\" -> \"$target_dir\"..."; # copy sources from git and show progress
system ("cd $source_dir && " . "git archive --format=tar HEAD | " . " tar -xf - -C $target_dir ") &&
die "Error: copying failed: $!\n";
print "\n";
}
# copy files to temp dir; showing a progress; using a black list
sub remove_empty_submodules($)
{
my ($target_topdir) = @_;
foreach my $submodule (sort values %module_dirname) {
next unless ($submodule);
print "Removing empty submodule: $submodule...\n";
rmdir "$target_topdir/$submodule" || die "Error: Can't remove submodule directory: $target_topdir/$submodule";
}
}
# copy the source directory into a tmp directory # omit the .git subdirectories
sub copy_lo_module_to_tempdir($$$)
{
my ($source_dir, $module, $lo_topdir_name) = @_;
my $tempdir = tempdir( 'libreoffice-XXXXXX', DIR => File::Spec->tmpdir );
mkdir "$tempdir/$lo_topdir_name" || die "Can't create directory \"$tempdir/$lo_topdir_name\": $!\n";
mkdir "$tempdir/$lo_topdir_name/$module_dirname{$module}" || die "Can't create directory \"$tempdir/$lo_topdir_name/$module_dirname{$module}\": $!\n"if ($module_dirname{$module});
copy_dir_filter_and_show_progress("$source_dir/$module_dirname{$module}", "$tempdir/$lo_topdir_name/$module_dirname{$module}");
remove_empty_submodules("$tempdir/$lo_topdir_name/") if ($module eq "core");
return $tempdir;
}
sub generate_lo_module_changelog($$$)
{
my ($source_dir, $lo_module_release_topdir, $module) = @_;
my $log_name = "ChangeLog";
$log_name .= "-$module_dirname{$module}"if ($module_dirname{$module});
print "Generating changelog for $module...\n";
system ("cd $source_dir/$module_dirname{$module} && " . "git log --date=short --pretty='format:%cd %an <%ae> [%H]%n%n%w(0,8,8)%s%n%e%+b' " . ">$lo_module_release_topdir/$log_name" ) &&
die "Error: generating failed: $!\n";
}
sub generate_tarball($$$)
{
my ($dir, $tarball, $compressor_option) = @_;
print "Creating $tarball..."; # generate the tarball in the current directory; avoid "./" prefix in the stored paths; show progress
system ("tar -c -C $dir $lo_topdir_name | $compressor_option $tarball") &&
die "Error: releasing failed: $!\n";
print "\n";
}
sub generate_md5($)
{
my ($filename) = @_;
print "Generating MD5...\n";
system ("md5sum $filename >$filename.md5") &&
die "Error: releasing failed: $!\n";
}
sub default_releases_state_file($)
{
my ($lo_core_dir) = @_;
my $rootdir = $lo_core_dir;
$rootdir =~ s/^(.*?)\/?[^\/]+\/?$/$1/;
my $releases_state_file; if ($rootdir) {
$releases_state_file = "$rootdir/.releases";
} else {
$releases_state_file = ".releases";
}
return"$releases_state_file";
}
sub load_releases_state($)
{
my ($releases_state_file) = @_;
my $state_config_version;
my $state_release_version;
sub save_releases_state($$$)
{
my ($releases_state_file, $config_version, $release_version) = @_;
open (STATE, '>', "$releases_state_file") ||
die "Can't open \"$releases_state_file\" for writing: $!\n";
print STATE "configure_version = $config_version\n";
print STATE "released_version = $release_version\n";
close (STATE);
}
sub remove_tempdir($)
{
my ($tempdir) = @_;
# print "Cleaning $tempdir...\n";
system ("rm -rf $tempdir") && die "Error: rm failed: $!\n";
}
sub check_if_file_exists($$)
{
my ($file, $force) = @_;
if (-e $file) { if (defined $force) {
print "Warning: $file already exists and will be replaced!\n";
} else {
die "Error: $file already exists.\n". " Use --force if you want to replace it.\n";
}
}
}
sub check_if_already_released($$$$$$)
{
my ($p_module_tarball_name, $force, $bzip2, $xz, $pack_lo_core, $pack_lo_modules) = @_;
foreach my $tarball_name ( sort values %{$p_module_tarball_name} ) {
check_if_file_exists("$tarball_name.tar.bz2", $force) if (defined $bzip2);
check_if_file_exists("$tarball_name.tar.xz", $force) if (defined $xz);
}
}
sub prepare_module_sources($$$$)
{
my ($source_dir, $release_version, $module, $lo_topdir_name) = @_;
# prepare sources
my $temp_dir = copy_lo_module_to_tempdir($source_dir, $module, $lo_topdir_name);
generate_lo_module_changelog($source_dir, "$temp_dir/$lo_topdir_name", $module);
run_autogen("$temp_dir/$lo_topdir_name", $module) if ($module eq 'core');
generate_sources_version_file("$temp_dir/$lo_topdir_name", $release_version) if ($module eq 'core');
return $temp_dir;
}
sub pack_module_sources($$$$)
{
my ($temp_dir, $md5, $tarball, $compressor_option) = @_;
generate_tarball($temp_dir, $tarball, $compressor_option);
generate_md5($tarball) if (defined $md5);
}
sub generate_module_tarball($$$$$$$$)
{
my ($source_dir, $release_version, $module, $md5, $bzip2, $xz, $lo_topdir_name, $module_tarball_name) = @_;
my $PARALLELISM = $ENV{'PARALLELISM'};
my $CPUS_XZ = 0;
my $CPUS_BZ2 = "";
my $bzip_arguments;
# Set CPUS_ to the number of CPUs that should be used. If PARALLELISM # is set then this is used otherwise autodetect is used. if (defined $PARALLELISM) { if ($PARALLELISM > 0) {
$CPUS_XZ = $PARALLELISM;
$CPUS_BZ2 = "-p$PARALLELISM";
} else {
$CPUS_XZ = 1;
$CPUS_BZ2 = "-p1";
}
}
if (defined $bzip2) {
my $exit_code = system("pbzip2 --version >/dev/null 2>&1"); if ($exit_code == 0) {
$bzip_arguments = "pbzip2 -z -b20 $CPUS_BZ2";
} else {
$bzip_arguments = "bzip2 -z --best";
print("Consider installing pbzip2, using bzip2 now.\n");
}
}
my $temp_dir = prepare_module_sources($source_dir, $release_version, $module, $lo_topdir_name);
pack_module_sources($temp_dir, $md5, "$module_tarball_name.tar.bz2", "$bzip_arguments > ") if (defined $bzip2);
pack_module_sources($temp_dir, $md5, "$module_tarball_name.tar.xz", "xz -z -T$CPUS_XZ -e > ") if (defined $xz);
remove_tempdir($temp_dir);
}
sub generate_tarballs($$$$$$$$$)
{
my ($source_dir, $release_version, $md5, $bzip2, $xz, $lo_topdir_name, $p_module_tarball_name, $pack_lo_core, $pack_lo_modules) = @_;
"Options:\n\n" . "\t--help: print this help\n" . "\t--force: replace an already existing release of the same version\n" . "\t--md5: generate md5 sum for the final tarball\n" . "\t--bzip2: generate tarballs compressed by bzip2\n" . "\t--xz: generate tarballs compressed by xz (default)\n" . "\t--version: just print version of the released package but do not\n" . "\t\trelease it; the version is affected by the other options, e.g.\n" . "\t\t--inc-version\n" . "\t--set-version: force another version\n" . "\t--inc-version: increment the latest version; there is a difference\n" . "\t\tbetween test release (default) and final (not yet supported)\n" . "\t--no-submodule: do not pack sources from git submodules\n" . "\t--module=<module>: pack just a single module, use \"core\"\n" . "\t\tfor the main git repo,\n" . "\tdir: path of the source directory, either libreoffice-build or module\n";
}
my $module;
my $ptf;
my $md5;
my $bzip2;
my $xz;
my $inc_version;
my $config_version;
my $set_version;
my $get_config_version;
my $release_version;
my $pack_lo_core=1;
my $pack_lo_modules=1;
my $source_dir;
my $releases_state_file;
my $state_config_version;
my $state_release_version;
my $lo_core_tempdir;
my $force;
my $verbose=1;
my %module_tarball_name;
unless ( defined $source_dir ) {
die "Error: undefined source directory, try --help\n";
}
unless ( -d "$source_dir" ) {
die "Error: is not a directory: $source_dir\n";
}
# check if it is a valid libreoffice-core directory
unless (-f "$source_dir/autogen.sh" && -f "$source_dir/config_host.mk.in") {
die "Error: \"$source_dir\" is not a valid libreoffice-core directory\n";
}
if (defined $set_version && defined $inc_version) {
die "Error: --set-version and --inc-version options can't be used together\n";
}
# define tarball names
print "Detected module:\n";
foreach my $module (sort keys %module_dirname) { if (-e "$source_dir/$module_dirname{$module}/.git") {
print " $module\n"; if ($module eq "core") {
$module_tarball_name{$module} = "libreoffice-$release_version";
} else {
$module_tarball_name{$module} = "libreoffice-$module-$release_version";
}
} else {
print "did not found: $source_dir/$module_dirname{$module}/.git\n";
print "Warning: $module sources are not available -> skipping\n";
}
}
# top directory inside the source tarballs
$lo_topdir_name = "libreoffice-$release_version";
print "Default version : $config_version\n"if ($verbose && defined $config_version);
print "Last used version : $state_release_version\n"if ($verbose && defined $state_release_version);
print "New version : $release_version\n"if ($verbose);
# do the real job if ( defined $get_config_version ) {
print "$release_version\n";
} else {
check_if_already_released(\%module_tarball_name, $force, $bzip2, $xz, $pack_lo_core, $pack_lo_modules);
# give a chance to stop the process
print ("\nWaiting 3 seconds...\n");
sleep 3;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.