X-Git-Url: http://git.samba.org/?p=metze%2Fwireshark%2Fwip.git;a=blobdiff_plain;f=make-version.pl;h=13f3b7f3097e68af52ebe8285d899c62819f7c59;hp=93d0f5ceb3d6c24861b041123a5d29b1f5eae3b4;hb=8f21bfe46f49c8eaec444622b6d0fb56299a8ba3;hpb=8a8b8834500043ea4f7d818aafa2b1edb353563a diff --git a/make-version.pl b/make-version.pl index 93d0f5ceb3..13f3b7f309 100755 --- a/make-version.pl +++ b/make-version.pl @@ -1,11 +1,11 @@ #!/usr/bin/perl -w # -# Copyright 2004 Jörg Mayer (see AUTHORS file) +# Copyright 2004 Jörg Mayer (see AUTHORS file) # # $Id$ # -# Ethereal - Network traffic analyzer -# By Gerald Combs +# Wireshark - Network traffic analyzer +# By Gerald Combs # Copyright 1998 Gerald Combs # # This program is free software; you can redistribute it and/or @@ -20,89 +20,561 @@ # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# usage: ./make-version.pl +# See below for usage # -# If "version.conf" is present, it is parsed for configuration values. +# If "version.conf" is present, it is parsed for configuration values. # Possible values are: # -# enable - Enable or disable versioning. Zero (0) disables, nonzero -# enables. -# format - A strftime() formatted string to use as a template for the -# version string. +# enable - Enable or disable versioning. Zero (0) disables, nonzero +# enables. +# svn_client - Use svn client i.s.o. ugly internal SVN file hack +# format - A strftime() formatted string to use as a template for +# the version string. The sequence "%#" will substitute +# the SVN revision number. +# pkg_enable - Enable or disable local package versioning. +# pkg_format - Like "format", but used for the local package version. +# +# If run with the "-r" or "--set-release" argument the AC_INIT macro in +# configure.ac and the VERSION macro in config.nmake will have the +# pkg_format template appended to the version number. svnversion.h will +# _not_ be generated if either argument is present. # # Default configuration: # # enable: 1 +# svn_client: 1 # format: SVN %Y%m%d%H%M%S +# pkg_enable: 1 +# pkg_format: -SVN-%# + +# XXX - We're pretty dumb about the "%#" substitution, and about having +# spaces in the package format. use strict; use Time::Local; use POSIX qw(strftime); +use Getopt::Long; +use Pod::Usage; +use IO::Handle; +use English; my $version_file = 'svnversion.h'; +my $package_string = ""; my $vconf_file = 'version.conf'; -my $last = 0; -my %version_pref = ("enable" => 1, "format" => "SVN %Y%m%d%H%M%S"); +my $tortoise_file = "tortoise_template"; +my $last_change = 0; +my $revision = 0; +my $repo_path = "unknown"; +my $get_svn = 0; +my $set_svn = 0; +my $set_version = 0; +my $set_release = 0; +my %version_pref = ( + "version_major" => 1, + "version_minor" => 11, + "version_micro" => 1, + "version_build" => 0, + + "enable" => 1, + "svn_client" => 1, + "tortoise_svn" => 0, + "format" => "SVN %Y%m%d%H%M%S", + "is_release" => 0, + + # Normal development builds + "pkg_enable" => 1, + "pkg_format" => "-SVN-%#", + # Development releases + #"pkg_enable" => 0, + #"pkg_format" => "", + ); +my $srcdir = "."; +my $info_cmd = ""; -# Recursively find all SVN Entries files starting from the given directory, -# and compute the modification time of the most recently modified Entries file. +# Ensure we run with correct locale +$ENV{LANG} = "C"; +$ENV{LC_ALL} = "C"; + +# Run "svn info". Parse out the most recent modification time and the +# revision number. sub read_svn_info { my $line; + my $version_format = $version_pref{"format"}; + my $package_format = ""; + my $in_entries = 0; + my $svn_name; + my $repo_version; + my $repo_root = undef; + my $repo_url = undef; + my $do_hack = 1; + my $info_source = "Unknown"; + + if ($version_pref{"pkg_enable"}) { + $package_format = $version_pref{"pkg_format"}; + } + + if (-d "$srcdir/.svn" or -d "$srcdir/../.svn") { + $info_source = "Command line (svn info)"; + $info_cmd = "svn info $srcdir"; + } elsif (-d "$srcdir/.git/svn") { + $info_source = "Command line (git-svn)"; + $info_cmd = "(cd $srcdir; git svn info)"; + } + + if ($version_pref{"svn_client"}) { + eval { + use warnings "all"; + no warnings "all"; + $line = qx{$info_cmd}; + if (defined($line)) { + if ($line =~ /Last Changed Date: (\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)/) { + $last_change = timegm($6, $5, $4, $3, $2 - 1, $1); + } + if ($line =~ /Last Changed Rev: (\d+)/) { + $revision = $1; + } + if ($line =~ /URL: (\S+)/) { + $repo_url = $1; + } + if ($line =~ /Repository Root: (\S+)/) { + $repo_root = $1; + } + } + 1; + }; + + if ($last_change && $revision && $repo_url && $repo_root) { + $do_hack = 0; + } + } elsif ($version_pref{"tortoise_svn"}) { + # Dynamically generic template file needed by TortoiseSVN + open(TORTOISE, ">$tortoise_file"); + print TORTOISE "#define SVNVERSION \"\$WCREV\$\"\r\n"; + print TORTOISE "#define SVNPATH \"\$WCURL\$\"\r\n"; + close(TORTOISE); + + $info_source = "Command line (SubWCRev)"; + $info_cmd = "SubWCRev $srcdir $tortoise_file $version_file"; + my $tortoise = system($info_cmd); + if ($tortoise == 0) { + $do_hack = 0; + } + + #clean up the template file + unlink($tortoise_file); + } + + if ($revision == 0) { + # Fall back to config.nmake + $info_source = "Prodding config.nmake"; + my $filepath = "$srcdir/config.nmake"; + open(CFGNMAKE, "< $filepath") || die "Can't read $filepath!"; + while ($line = ) { + if ($line =~ /^SVN_REVISION=(\d+)/) { + $revision = $1; + $do_hack = 0; + last; + } + } + close (CFGNMAKE); + } + if ($revision == 0 and -d "$srcdir/.git") { + + # Try git... + eval { + use warnings "all"; + no warnings "all"; + # If someone had properly tagged 1.9.0 we could also use + # "git describe --abbrev=1 --tags HEAD" + + $info_cmd = "(cd $srcdir; git log --format='%b' -n 1)"; + $line = qx{$info_cmd}; + if (defined($line)) { + if ($line =~ /svn path=.*; revision=(\d+)/) { + $revision = $1; + } + } + $info_cmd = "(cd $srcdir; git log --format='%ad' -n 1 --date=iso)"; + $line = qx{$info_cmd}; + if (defined($line)) { + if ($line =~ /(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)/) { + $last_change = timegm($6, $5, $4, $3, $2 - 1, $1); + } + } + $info_cmd = "(cd $srcdir; git branch)"; + $line = qx{$info_cmd}; + if (defined($line)) { + if ($line =~ /\* (\S+)/) { + $repo_path = $1; + } + } + 1; + }; + } + if ($revision == 0 and -d "$srcdir/.bzr") { + + # Try bzr... + eval { + use warnings "all"; + no warnings "all"; + $info_cmd = "(cd $srcdir; bzr log -l 1)"; + $line = qx{$info_cmd}; + if (defined($line)) { + if ($line =~ /timestamp: \S+ (\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)/) { + $last_change = timegm($6, $5, $4, $3, $2 - 1, $1); + } + if ($line =~ /svn revno: (\d+) \(on (\S+)\)/) { + $revision = $1; + $repo_path = $2; + } + } + 1; + }; + } + + + # 'svn info' failed or the user really wants us to dig around in .svn/entries + if ($do_hack) { + # Start of ugly internal SVN file hack + if (! open (ENTRIES, "< $srcdir/.svn/entries")) { + print ("Unable to open $srcdir/.svn/entries\n"); + } else { + $info_source = "Prodding .svn"; + # We need to find out whether our parser can handle the entries file + $line = ; + chomp $line; + if ($line eq '') { + $repo_version = "pre1.4"; + } elsif ($line =~ /^8$/) { + $repo_version = "1.4"; + } else { + $repo_version = "unknown"; + } + + if ($repo_version eq "pre1.4") { + # The entries schema is flat, so we can use regexes to parse its contents. + while ($line = ) { + if ($line =~ //) { + if (($svn_name eq "" || $svn_name eq "svn:this_dir") && + $last_change && $revision) { + $in_entries = 0; + last; + } + } + # XXX - Fetch the repository root & URL + } + } + close ENTRIES; + } + } + + # If we picked up the revision and modification time, + # generate our strings. + if ($revision && $last_change) { + $version_format =~ s/%#/$revision/; + $package_format =~ s/%#/$revision/; + $package_string = strftime($package_format, gmtime($last_change)); + } + + if ($repo_url && $repo_root && index($repo_url, $repo_root) == 0) { + $repo_path = substr($repo_url, length($repo_root)); + } + + if ($get_svn) { + print <<"Fin"; +SVN revision : $revision +Revision source : $info_source +Release stamp : $package_string +Fin + } +} + + +# Read configure.ac, then write it back out with an updated +# "AC_INIT" line. +sub update_configure_ac +{ + my $line; + my $contents = ""; + my $version = ""; + my $filepath = "$srcdir/configure.ac"; - open(SVNINFO, "svn info |") || return; - while ($line = ) { - if ($line =~ /^Last Changed Date: (\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)/) { - $last = timegm($6, $5, $4, $3, $2 - 1, $1); + return if (!$set_version && $package_string eq ""); + + open(CFGIN, "< $filepath") || die "Can't read $filepath!"; + while ($line = ) { + if ($line =~ /^m4_define\( *\[?version_major\]? *,.*([\r\n]+)$/) { + $line = sprintf("m4_define([version_major], [%d])$1", $version_pref{"version_major"}); + } elsif ($line =~ /^m4_define\( *\[?version_minor\]? *,.*([\r\n]+)$/) { + $line = sprintf("m4_define([version_minor], [%d])$1", $version_pref{"version_minor"}); + } elsif ($line =~ /^m4_define\( *\[?version_micro\]? *,.*([\r\n]+)$/) { + $line = sprintf("m4_define([version_micro], [%d])$1", $version_pref{"version_micro"}); + } elsif ($line =~ /^m4_append\( *\[?version_micro_extra\]? *,.*([\r\n]+)$/) { + $line = sprintf("m4_append([version_micro_extra], [%s])$1", $package_string); } + $contents .= $line } - close SVNINFO; + + open(CFGIN, "> $filepath") || die "Can't write $filepath!"; + print(CFGIN $contents); + close(CFGIN); + print "$filepath has been updated.\n"; } +# Read config.nmake, then write it back out with an updated +# "VERSION" line. +sub update_config_nmake +{ + my $line; + my $contents = ""; + my $version = ""; + my $filepath = "$srcdir/config.nmake"; + + open(CFGNMAKE, "< $filepath") || die "Can't read $filepath!"; + while ($line = ) { + if ($line =~ /^SVN_REVISION=.*([\r\n]+)$/) { + $line = sprintf("SVN_REVISION=%d$1", $revision); + } elsif ($set_version && $line =~ /^VERSION_MAJOR=.*([\r\n]+)$/) { + $line = sprintf("VERSION_MAJOR=%d$1", $version_pref{"version_major"}); + } elsif ($set_version && $line =~ /^VERSION_MINOR=.*([\r\n]+)$/) { + $line = sprintf("VERSION_MINOR=%d$1", $version_pref{"version_minor"}); + } elsif ($set_version && $line =~ /^VERSION_MICRO=.*([\r\n]+)$/) { + $line = sprintf("VERSION_MICRO=%d$1", $version_pref{"version_micro"}); + } elsif ($line =~ /^VERSION_EXTRA=.*([\r\n]+)$/) { + $line = "VERSION_EXTRA=$package_string$1"; + } + $contents .= $line + } + + open(CFGNMAKE, "> $filepath") || die "Can't write $filepath!"; + print(CFGNMAKE $contents); + close(CFGNMAKE); + print "$filepath has been updated.\n"; +} + +# Read docbook/asciidoc.conf, then write it back out with an updated +# wireshark-version replacement line. +sub update_release_notes +{ + my $line; + my $contents = ""; + my $version = ""; + my $filepath = "$srcdir/docbook/asciidoc.conf"; + + return if (!$set_version); + + open(ADOC_CONF, "< $filepath") || die "Can't read $filepath!"; + while ($line = ) { + # wireshark-version:\[\]=1.9.1 + + if ($line =~ /^wireshark-version:\\\[\\\]=.*([\r\n]+)$/) { + $line = sprintf("wireshark-version:\\\[\\\]=%d.%d.%d$1", + $version_pref{"version_major"}, + $version_pref{"version_minor"}, + $version_pref{"version_micro"}, + ); + } + $contents .= $line + } + + open(ADOC_CONF, "> $filepath") || die "Can't write $filepath!"; + print(ADOC_CONF $contents); + close(ADOC_CONF); + print "$filepath has been updated.\n"; +} + +# Read debian/changelog, then write back out an updated version. +sub update_debian_changelog +{ + my $line; + my $contents = ""; + my $version = ""; + my $filepath = "$srcdir/debian/changelog"; + + return if ($set_version == 0); + + open(CHANGELOG, "< $filepath") || die "Can't read $filepath!"; + while ($line = ) { + if ($set_version && CHANGELOG->input_line_number() == 1) { + $line = sprintf("wireshark (%d.%d.%d) unstable; urgency=low\n", + $version_pref{"version_major"}, + $version_pref{"version_minor"}, + $version_pref{"version_micro"}, + ); + } + $contents .= $line + } + + open(CHANGELOG, "> $filepath") || die "Can't write $filepath!"; + print(CHANGELOG $contents); + close(CHANGELOG); + print "$filepath has been updated.\n"; +} + +# Read debian/wireshark-common.files, then write back out an updated version. +# The libraries updated here MUST match the updates made by update_lib_releases +# below. We should do this automatically. +sub update_debian_wcf +{ + my $line; + my $contents = ""; + my $version = ""; + my $filepath = "$srcdir/debian/wireshark-common.files"; + + return if (!$set_version); + + open(DWCF, "< $filepath") || die "Can't read $filepath!"; + while ($line = ) { + # /usr/lib/wireshark/libwireshark.so.1.1.0 + + if ($line =~ qr{^(/usr/lib/wireshark/lib(wireshark|wiretap).so\.\d+\.\d+\.)\d+$}) { + $line = sprintf("$1%d\n", $version_pref{"version_micro"}); + } + $contents .= $line + } + + open(DWCF, "> $filepath") || die "Can't write $filepath!"; + print(DWCF $contents); + close(DWCF); + print "$filepath has been updated.\n"; +} + +# Read Makefile.am for each library, then write back out an updated version. +sub update_lib_releases +{ + my $line; + my $contents = ""; + my $version = ""; + my $filedir; + my $filepath; + + return if (!$set_version); + + # The Libtool manual says + # "If the library source code has changed at all since the last + # update, then increment revision (‘c:r:a’ becomes ‘c:r+1:a’)." + # epan changes with each minor release, almost by definition. wiretap + # changes with *most* releases. + # + # http://www.gnu.org/software/libtool/manual/libtool.html#Updating-version-info + for $filedir ("epan", "wiretap") { # "wsutil" + $contents = ""; + $filepath = $filedir . "/Makefile.am"; + open(MAKEFILE_AM, "< $filepath") || die "Can't read $filepath!"; + while ($line = ) { + # libwireshark_la_LDFLAGS = -version-info 2:1:1 -export-symbols + + if ($line =~ /^(lib\w+_la_LDFLAGS.*version-info\s+\d+:)\d+(:\d+.*)/) { + $line = sprintf("$1%d$2\n", $version_pref{"version_micro"}); + } + $contents .= $line + } + + open(MAKEFILE_AM, "> $filepath") || die "Can't write $filepath!"; + print(MAKEFILE_AM $contents); + close(MAKEFILE_AM); + print "$filepath has been updated.\n"; + } +} + +# Update distributed files that contain any version information +sub update_versioned_files +{ + &update_configure_ac; + &update_config_nmake; + &update_release_notes; + &update_debian_changelog; + &update_debian_wcf; + &update_lib_releases; +} # Print the SVN version to $version_file. # Don't change the file if it is not needed. -sub print_svn_version +sub print_svn_revision { - my $svn_version; + my $svn_revision; my $needs_update = 1; - if ($last) { - $svn_version = "#define SVNVERSION \"" . - strftime($version_pref{"format"}, gmtime($last)) . - "\"\n"; + if ($last_change && $revision) { + $svn_revision = "#define SVNVERSION \"SVN Rev " . + $revision . "\"\n" . + "#define SVNPATH \"" . $repo_path . "\"\n"; } else { - $svn_version = "/* #define SVNVERSION \"\" */\n"; + $svn_revision = "#define SVNVERSION \"SVN Rev Unknown\"\n" . + "#define SVNPATH \"unknown\"\n"; } - if (open(OLDVER, "<$version_file")) { - if ( eq $svn_version) { - print "$version_file is up-to-date.\n"; + if (open(OLDREV, "<$version_file")) { + my $old_svn_revision = . ; + if ($old_svn_revision eq $svn_revision) { $needs_update = 0; } - close OLDVER; + close OLDREV; } - if ($needs_update == 1) { - # print "Updating $version_file so it contains:\n$svn_version"; + if (! $set_svn) { return; } + + if ($needs_update) { + # print "Updating $version_file so it contains:\n$svn_revision"; open(VER, ">$version_file") || die ("Cannot write to $version_file ($!)\n"); - print VER "$svn_version"; + print VER "$svn_revision"; close VER; print "$version_file has been updated.\n"; + } else { + print "$version_file unchanged.\n"; } } # Read values from the configuration file, if it exists. sub get_config { - open(FILE, "<$vconf_file") || print STDERR "Version configuration file $vconf_file not found. Using defaults.\n" && return 1; + my $arg; + my $show_help = 0; + + # Get our command-line args + # XXX - Do we need an option to undo --set-release? + GetOptions( + "help|h", \$show_help, + "get-svn|g", \$get_svn, + "set-svn|s", \$set_svn, + "set-version|v", \$set_version, + "set-release|r|package-version|p", \$set_release + ) || pod2usage(2); + + if ($show_help) { pod2usage(1); } + + if ( !( $show_help || $get_svn || $set_svn || $set_version || $set_release ) ) { + $set_svn = 1; + } + + if ($#ARGV >= 0) { + $srcdir = $ARGV[0] + } + + if (! open(FILE, "<$vconf_file")) { + print STDERR "Version configuration file $vconf_file not " + . "found. Using defaults.\n"; + return 1; + } while () { chomp; next if (/^#/); - next unless (/^(\w+):\s+(\S.*)/); - $version_pref{$1} = $2; + next unless (/^(\w+)(:|=)\s*(\S.*)/); + $version_pref{$1} = $3; } close FILE; return 1; @@ -114,17 +586,68 @@ sub get_config { &get_config(); -if ($version_pref{"enable"} == 0) { - print "Version tag disabled in $vconf_file.\n"; -} elsif (-d "./.svn") { - print "This is a build from SVN (or a SVN snapshot), " - . "SVN version tag will be computed.\n"; - &read_svn_info("."); -} else { - print "This is not a SVN build.\n"; -} +&read_svn_info(); + +&print_svn_revision; + +if ($set_version || $set_release) { + if ($set_version) { + print "Generating version information\n"; + } + + if ($version_pref{"enable"} == 0) { + print "Release information disabled in $vconf_file.\n"; + $set_release = 0; + } + + if ($set_release) { + print "Generating release information\n"; + } else { + print "Resetting release information\n"; + $revision = 0; + $package_string = ""; + } -# Now that we've computed everything, print the SVN version to $version_file -&print_svn_version; + &update_versioned_files; +} __END__ + +=head1 NAM + +make-version.pl - Get and set build-time version information for Wireshark + +=head1 SYNOPSIS + +make-version.pl [options] [source directory] + + Options: + + --help, -h This help message + --get-svn, -g Print the SVN revision and source. + --set-svn, -s Set the information in svnversion.h + --set-version, -v Set the major, minor, and micro versions in + configure.ac, config.nmake, debian/changelog, + and docbook/asciidoc.conf. + Resets the release information when used by + itself. + --set-release, -r Set the release information in configure.ac + and config.nmake + --package-version, -p Deprecated. Same as --set-release. + +Options can be used in any combination. If none are specified B<--set-svn> +is assumed. + +# +# Editor modelines - http://www.wireshark.org/tools/modelines.html +# +# Local variables: +# c-basic-offset: 8 +# tab-width: 8 +# indent-tabs-mode: t +# End: +# +# vi: set shiftwidth=8 tabstop=8 noexpandtab: +# :indentSize=8:tabSize=8:noTabs=false: +# +#