diff options
author | Petr Mladek <pmladek@suse.cz> | 2011-04-11 14:43:06 +0200 |
---|---|---|
committer | Petr Mladek <pmladek@suse.cz> | 2011-04-11 14:43:06 +0200 |
commit | f7b5f014bcc2e5b708099bbc7e2b895e8266a713 (patch) | |
tree | ec42fc7ae043d08a5e3714c60dcae3c08f918ef9 /bin | |
parent | 5aa623271dc15bc4b2ccf1326980cd1a6450cc63 (diff) |
lo-pack-sources: new script to generate source tarballs
based on libreoffice/build/bin/lo-pack-sources; still need some clean up
Diffstat (limited to 'bin')
-rwxr-xr-x | bin/lo-pack-sources | 638 |
1 files changed, 638 insertions, 0 deletions
diff --git a/bin/lo-pack-sources b/bin/lo-pack-sources new file mode 100755 index 000000000000..5504aad83ad1 --- /dev/null +++ b/bin/lo-pack-sources @@ -0,0 +1,638 @@ +#!/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 /; + +# get libreoffice-build version from the given libreoffice-build sources +sub get_config_version($) +{ + my ($lo_build_dir) = @_; + my $version; + + open (CONFIGURE, "$lo_build_dir/configure.in") || + die "can't open \"$lo_build_dir/configure.in\" 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; +} + +# set libreoffice-build version in the given libreoffice-build sources +sub set_config_version($$) +{ + my ($lo_build_dir, $version) = @_; + my $configure = "$lo_build_dir/configure.in"; + + open (CONFIGURE, "$configure") || + die "can't open \"$configure\" for reading: $!\n"; + + my ( $tmp_fh, $tmp_filename ) = tempfile( "$configure.XXXXXX" ); + if ( !defined $tmp_fh ) { + close (CONFIGURE); + die "Error: can't create temporary file: \"$configure.XXXXXX\"\n"; + } + + while (my $line = <CONFIGURE>) { + chomp $line; + + if ($line =~ /^(\s*AC_INIT\s*\(\s*libreoffice-build\s*,\s*)([\w\.]*)(\s*\)\s*)$/) { + print ${tmp_fh} "$1$version$3\n"; + } else { + print ${tmp_fh} "$line\n"; + } + } + close (CONFIGURE); + close (${tmp_fh}); + + # preserve permissions on target file by applying them to temp file + my ( $mode, $uid, $gid ) = ( stat($configure) )[ 2, 4, 5 ]; + $mode = $mode & 07777; + + chmod $mode, $tmp_filename; + chown $uid, $gid, $tmp_filename; + + rename ($tmp_filename, $configure) || + die "Can't rename \"$tmp_filename\" to \"$configure\": $!\n"; +} + +# 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 alhabeticaly: 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 $state_config_version && + defined $state_release_version && + "$state_config_version" eq "$config_version") { + $release_version = "$state_release_version"; + } else { + $release_version = "$config_version"; + } + + if ( defined $inc_version ) { + $release_version = inc_test_version($release_version); + } + + return $release_version; +} + + +sub generate_lo_build_blacklist($) +{ + my ($blacklist) = @_; + + # FIXME: crazy hacks to copy libreoffice-build without too big and useless subdirectories and to show a progress + open (BLACKLIST, ">$blacklist") || die "Can't open $blacklist: $!\n"; + + # IMPORTANT: Do not remove .git directories because "git log" is called during "make dist" + print BLACKLIST "*/.svn\n"; + print BLACKLIST "rawbuild/*\n"; + print BLACKLIST "build/*\n"; + print BLACKLIST "clone/*\n"; + print BLACKLIST "src/libreoffice-*.tar.bz2\n"; + print BLACKLIST "src/????????????????????????????????-*\n"; + + close BLACKLIST; +} + +sub generate_lo_piece_blacklist($) +{ + my ($blacklist) = @_; + + # FIXME: crazy hacks to copy libreoffice-build without too big and useless subdirectories and to show a progress + open (BLACKLIST, ">$blacklist") || die "Can't open $blacklist: $!\n"; + + # IMPORTANT: Do not remove .git directories because "git log" is called during "make dist" + print BLACKLIST ".git\n"; + print BLACKLIST ".gitignore\n"; + print BLACKLIST ".gitattributes\n"; + print BLACKLIST "autom4te.cache/*\n"; + print BLACKLIST "autom4te.cache\n"; + print BLACKLIST "autogen.lastrun\n"; + print BLACKLIST "clone/*\n"; + print BLACKLIST "config.log\n"; + print BLACKLIST "config.parms\n"; + print BLACKLIST "git-hooks\n"; + print BLACKLIST "Linux*Env.Set.sh\n"; + print BLACKLIST "warn\n"; + + close BLACKLIST; +} + +# remove symlinks to clone subdir +sub remove_module_symlinks($$) +{ + my ($tempdir, $piece_tarball_name) = @_; + + print STDERR "find $tempdir/$piece_tarball_name -mindepth 1 -maxdepth 1 -type l -exec rm {} \\;\n"; + system ("find $tempdir/$piece_tarball_name -mindepth 1 -maxdepth 1 -type l -exec rm {} \\;") && + die "Error: can't delete symlinks to clone dir in $tempdir: $!\n"; +} + + +# copy files to temp dir; showing a progress; using a black list +sub copy_dir_filter_and_show_progress($$$) +{ + my ($source_dir, $target_dir, $blacklist) = @_; + + print "Copying \"$source_dir\" -> \"$target_dir\"..."; + # FIXME: crazy hacks to copy dir with a blacklist and showing a progress + system ("tar -cf - -C $source_dir -X $blacklist \.\/ | " . + "tar -xf - -C $target_dir --checkpoint 2>&1 | " . + "awk '{ ORS=\"\" ; if (++nlines\%50 == 0) printf \".\"; fflush() }'") && + die "Error: copying failed: $!\n"; + print "\n"; +} + +# copy the local version of libreoffice-build into a tmp directory +# omit the .svn subdirectories +sub copy_lo_build_to_tempdir($) +{ + my ($lo_build_dir) = @_; + + my $tempdir = tempdir( 'libreoffice-XXXXXX', DIR => File::Spec->tmpdir ); + my $blacklist = "$tempdir/libreoffice-build.copy.blacklist"; + + generate_lo_build_blacklist($blacklist); + copy_dir_filter_and_show_progress($lo_build_dir, $tempdir, $blacklist); + + unlink $blacklist; + + return $tempdir; +} + +# copy the piece lo source directory into a tmp directory +# omit the .git subdirectories +sub copy_lo_piece_to_tempdir($$$) +{ + my ($piece_dir, $piece, $piece_tarball_name) = @_; + + + my $tempdir = tempdir( 'libreoffice-XXXXXX', DIR => File::Spec->tmpdir ); + my $blacklist = "$tempdir/libreoffice-$piece.copy.blacklist"; + + mkdir "$tempdir/$piece_tarball_name" || die "Can't create directory \"$tempdir/$piece_tarball_name\": $!\n"; + + generate_lo_piece_blacklist($blacklist); + copy_dir_filter_and_show_progress("$piece_dir", "$tempdir/$piece_tarball_name", $blacklist); + remove_module_symlinks($tempdir, $piece_tarball_name); + + unlink $blacklist; + + return $tempdir; +} + +sub generate_lo_piece_changelog($$$) +{ + my ($lo_piece_clone, $lo_piece_release_dir, $piece) = @_; + print "Generating changelog for $piece...\n"; + print "1:$lo_piece_clone, 2:$lo_piece_release_dir, 3:$piece\n"; + # FIXME: crazy hacks to copy dir with a blacklist and showing a progress + system ("cd $lo_piece_clone && " . + "git log --date=short --pretty='format:@%cd %an <%ae> [%H]%n%n%s%n%n%e%b' | " . + " sed -e 's|^\([^@]\)|\t\1|' -e 's|^@||' >$lo_piece_release_dir/ChangeLog" ) && + die "Error: generating failed: $!\n"; +} + +sub run_autoreconf($$) +{ + my ($dir, $piece) = @_; + + print "Running autoreconf for $piece...\n"; + system ("cd $dir && " . + "autoreconf -f -i && " . + "rm -rf autom4te.cache && " . + "cd - >/dev/null 2>&1") && die "Error: autoreconf failed: $!\n"; +} + +sub release_lo_build($) +{ + my ($lo_build_dir) = @_; + + print "Creating libreoffice-build tarball...\n"; + system ("cd $lo_build_dir && " . + "./autogen.sh --with-distro=GoOoLinux && " . + "make dist && " . + "cd - >/dev/null 2>&1") && die "Error: releasing failed: $!\n"; +} + +sub release_lo_piece($$) +{ + my ($lo_piece_dir, $piece_tarball_name) = @_; + + print "Creating $piece_tarball_name.tar.bz2..."; + system ("cd $lo_piece_dir && " . + "tar -cjf $piece_tarball_name.tar.bz2 --checkpoint * 2>&1 | awk '{ ORS=\"\" ; if (++nlines\%50 == 0) printf \".\"; fflush() }' && " . + "cd - >/dev/null 2>&1") && die "Error: releasing failed: $!\n"; + print "\n"; +} + +sub generate_md5($$$) +{ + my ($dir, $tarball_name, $tarball_suffix) = @_; + + print "Generating MD5...\n"; + system ("cd $dir && " . + "md5sum $tarball_name$tarball_suffix >$tarball_name$tarball_suffix.md5 && " . + "cd - >/dev/null 2>&1") && die "Error: releasing failed: $!\n"; +} + +sub default_releases_state_file($) +{ + my ($lo_build_dir) = @_; + + my $rootdir = $lo_build_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 default_releases_archive($) +{ + my ($lo_build_dir) = @_; + + my $rootdir = $lo_build_dir; + $rootdir =~ s/^(.*?)\/?[^\/]+\/?$/$1/; + + my $releases_archive_dir; + if ($rootdir) { + $releases_archive_dir = "$rootdir/archive"; + } else { + $releases_archive_dir = "archive"; + } + + return "$releases_archive_dir"; +} + +sub load_releases_state($) +{ + my ($releases_state_file) = @_; + + my $state_config_version; + my $state_release_version; + + if (open (STATE, "$releases_state_file")) { + + while (my $line = <STATE>) { + chomp $line; + + if ($line =~ /^\s*configure_version\s*=\s*(.*)$/) { + $state_config_version = "$1"; + } elsif ($line =~ /^\s*released_version\s*=\s*(.*)$/) { + $state_release_version = "$1"; + } + } + close (STATE); + } + + return $state_config_version, $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 save_file($$$) +{ + my ($source_dir, $target_dir, $file) = @_; + + unless ( -d "$target_dir" ) { + mkdir ("$target_dir") || + die "Can't create directory \"$target_dir\": $!\n"; + } + + if ( -f "$target_dir/$file" ) { + print "Warning: $target_dir/$file already exists and will be replaced\n"; + unlink ("$target_dir/$file"); + } + + print "Copying into archive: $target_dir/$file ...\n"; + copy ("$source_dir/$file", "$target_dir/$file") || + die "Error: Can't copy $source_dir/$file to $target_dir/$file: $!\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 alrady exists.\n". + " Use --force if you want to replace it.\n"; + } + } +} + +sub check_if_tarball_already_released($$$) +{ + my ($tarball, $releases_archive_dir, $force) = @_; + + check_if_file_exists($tarball, $force); + check_if_file_exists("$releases_archive_dir/$tarball", $force) if (defined $releases_archive_dir); +} + +sub check_if_already_released($$$$$$) +{ + my ($lo_build_tarball_name, $p_piece_tarball_name, $releases_archive_dir, $force, $pack_lo_build, $pack_lo_pieces) = @_; + + check_if_tarball_already_released("$lo_build_tarball_name.tar.gz", $releases_archive_dir, $force) if ($pack_lo_build); + + if ($pack_lo_pieces) { + foreach my $tarball_name ( values %{$p_piece_tarball_name} ) { + check_if_tarball_already_released("$tarball_name.tar.bz2", $releases_archive_dir, $force); + } + } +} + +sub prepare_lo_build_tarball($$$$) +{ + my ($lo_build_dir, $release_version, $md5, $lo_build_tarball_name) = @_; + + my $temp_dir = copy_lo_build_to_tempdir("$lo_build_dir"); + set_config_version($temp_dir, $release_version); + release_lo_build($temp_dir); + generate_md5($temp_dir, $lo_build_tarball_name, ".tar.gz") if (defined $md5); + + return $temp_dir; +} + +sub prepare_lo_piece_tarball($$$$$) +{ + my ($piece_dir, $release_version, $md5, $piece, $piece_tarball_name) = @_; + + my $temp_dir = copy_lo_piece_to_tempdir($piece_dir, $piece, $piece_tarball_name); + generate_lo_piece_changelog($piece_dir, "$temp_dir/$piece_tarball_name", $piece); + run_autoreconf("$temp_dir/$piece_tarball_name", $piece) if ($piece eq 'bootstrap'); + release_lo_piece($temp_dir, $piece_tarball_name); + generate_md5($temp_dir, $piece_tarball_name, ".tar.bz2") if (defined $md5); + + return $temp_dir; +} + +sub move_tarball_to_final_location($$$$) +{ + my ($temp_dir, $releases_archive_dir, $md5, $tarball) = @_; + + save_file($temp_dir, ".", "$tarball"); + save_file($temp_dir, ".", "$tarball.md5") if (defined $md5); + if ( defined $releases_archive_dir ) { + save_file($temp_dir, $releases_archive_dir, "$tarball"); + save_file($temp_dir, $releases_archive_dir, "$tarball.md5") if (defined $md5); + } + + remove_tempdir($temp_dir); +} + + +sub generate_tarballs($$$$$$$$$) +{ + my ($source_dir, $releases_archive_dir, $release_version, $md5, $lo_build_tarball_name, $p_piece_tarball_name, $pack_lo_build, $pack_lo_pieces, $is_lo_build_dir) = @_; + + if ($pack_lo_build) { +# my $temp_dir=prepare_lo_build_tarball($source_dir, $release_version, $md5, $lo_build_tarball_name); +# move_tarball_to_final_location($temp_dir, $releases_archive_dir, $md5, "$lo_build_tarball_name.tar.gz"); + my $temp_dir=prepare_lo_piece_tarball($source_dir, $release_version, $md5, "bootstrap", $lo_build_tarball_name); + move_tarball_to_final_location($temp_dir, $releases_archive_dir, $md5, "$lo_build_tarball_name.tar.bz2"); + } + + if ($pack_lo_pieces) { + my $piece_dir = $source_dir; + foreach my $piece ( keys %{$p_piece_tarball_name} ) { + print "\n--- Generating $piece ---\n"; + $piece_dir = "$source_dir/clone/$piece" if ($is_lo_build_dir); + my $temp_dir=prepare_lo_piece_tarball($piece_dir, $release_version, $md5, $piece, $p_piece_tarball_name->{$piece}); + move_tarball_to_final_location($temp_dir, $releases_archive_dir, $md5, "$p_piece_tarball_name->{$piece}.tar.bz2"); + } + } + +} + + +sub usage() +{ + print "This tool helps to pack the libreoffice-build and piece sources\n\n" . + + "Usage:\n". + "\tlo-pack-sources [--help] [--force] [--version]\n" . + "\t [--set-version=<ver>] [--inc-version] [--md5]\n" . + "\t [--no-lo-build] [--no-lo-pieces] [--piece=<piece>]\n" . + "\t [dir]\n\n" . + + "Options:\n\n" . + "\t--help: print this help\n" . + "\t--force: replace an already existing release of the same version\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--md5: generate md5 sum for the final tarball\n" . + "\t--no-lo-build: do not pack the libreoffice-build tarball\n" . + "\t--no-lo-pieces: do not pack the libreoffice-build piece sources\n" . + "\t--piece=<piece>: pack just a single piece, .e.g. \"writer\",\n" . + "\tdir: path of the source directory, either libreoffice-build or piece\n"; +} + + +my $ptf; +my $md5; +my $inc_version; +my $config_version; +my $set_version; +my $get_config_version; +my $release_version; +my $pack_lo_build=1; +my $pack_lo_pieces=1; +my $source_dir; +my $releases_archive_dir; +my $releases_state_file; +my $state_config_version; +my $state_release_version; +my $lo_build_tarball_name; +my $lo_build_tempdir; +my $force; +my $verbose=1; +my $is_lo_build_dir=0; +my @pieces=("artwork", "base", "calc", "components", + "extensions", "extras", "filters", "help", "impress", + "libs-core", "libs-extern", "libs-extern-sys", "libs-gui", + "postprocess", "sdk", "testing", "translations", "ure", "writer"); +my %piece_tarball_name; + +################### +# Arguments parsing +################### + +for my $arg (@ARGV) { + if ($arg eq '--help' || $arg eq '-h') { + usage; + exit 0; + } elsif ($arg eq '--force') { + $force=1; + } elsif ($arg eq '--md5') { + $md5=1; + } elsif ($arg eq '--version') { + $get_config_version=1; + $verbose = undef; + } elsif ($arg eq '--inc-version') { + $inc_version=1 + } elsif ($arg =~ m/--set-version=(.*)/) { + $set_version="$1"; + } elsif ($arg eq '--no-lo-build') { + $pack_lo_build=0; + } elsif ($arg eq '--no-lo-pieces') { + $pack_lo_pieces=0; + } elsif ($arg =~ m/--piece=(.*)/) { + # process just one piece and do not pack libreoffice-build + @pieces=(); + push @pieces, "$1"; + $pack_lo_build=0; + } elsif ($arg =~ /^-/ ) { + die "Error: unknown option: $arg\n"; + } else { + if (! defined $source_dir) { + $source_dir = $arg; + } else { + die "Error: Too many arguments $arg\n"; + } + } +} + +################### +# Initial checks +################### + +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-bootstrap directory +$is_lo_build_dir=1 if (-f "$source_dir/autogen.sh" && -f "$source_dir/set_soenv.in"); + +# all tarballs are generated from the libreoffice-bootstrap directory +if (@pieces > 1 && $is_lo_build_dir == 0 ) { + die "Error: \"$source_dir\" is not a valid libreoffice-bootstrap directory\n"; +} + +# just a single piece tarball can be generated from piece directory; version must be explicitely set in this case +if (@pieces == 1 && $is_lo_build_dir == 0 && ! defined $set_version ) { + die "Error: version must be set using the --set-version=<version> option\n" unless (defined $set_version); +} + +if (defined $set_version && defined $inc_version) { + die "Error: --set-version and --inc-version options can't be used together\n"; +} + + +################### +# Main logic +################### + + +print "Source: $source_dir\n" if ($verbose); + +if ($is_lo_build_dir) { + # detect some paths + $releases_state_file = default_releases_state_file($source_dir) unless (defined $releases_state_file); + $releases_archive_dir = default_releases_archive($source_dir) unless (defined $releases_archive_dir); + + # detect versions + $config_version = get_config_version($source_dir); + ($state_config_version, $state_release_version) = load_releases_state($releases_state_file); + if (defined $set_version) { + $release_version = "$set_version"; + } else { + $release_version = get_release_version($config_version, $state_config_version, $state_release_version, $inc_version); + } +} else { + # must be single piece release with predefined version + $release_version = "$set_version"; +} + +# define tarball names +$lo_build_tarball_name = "libreoffice-bootstrap-$release_version"; +foreach my $piece (@pieces) { + $piece_tarball_name{$piece} = "libreoffice-$piece-$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($lo_build_tarball_name, \%piece_tarball_name, $releases_archive_dir, $force, $pack_lo_build, $pack_lo_pieces); + + # give a chance to stop the process + print ("\nWaiting 3 seconds...\n"); + sleep 3; + + generate_tarballs($source_dir, $releases_archive_dir, $release_version, $md5, $lo_build_tarball_name, \%piece_tarball_name, $pack_lo_build, $pack_lo_pieces, $is_lo_build_dir); + + if ( defined $releases_state_file ) { + save_releases_state($releases_state_file, $config_version, $release_version); + } +} |