Merge branch 'master' into squeeze
[debian/amanda] / packaging / common / substitute.pl
diff --git a/packaging/common/substitute.pl b/packaging/common/substitute.pl
new file mode 100755 (executable)
index 0000000..680d4ac
--- /dev/null
@@ -0,0 +1,210 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+use POSIX;
+# Used by make to replace tags delimited by pairs of '%%'.  Each tag should be
+# listed below.  Remember, the script reads from the environment for $pkg_type
+
+# ARGV[0] = Source file (ends in .src)
+# ARGV[1] = Destination file (usually ARGV[0] - ".src"
+
+#### Checks
+# We must run from the root of a source tree, but we can only check that the 
+# common files are in the right places
+if ( not -e "packaging/common/substitute.pl" ) {
+    die "Error: 'substitute.pl' must be run from the root of a source tree"
+}
+
+sub get_date {
+    my $date;
+    # Set the date using date -r
+    open(my $DATE_PIPE, "-|", "/bin/date '+%a, %d %b %Y %T %z'");
+    [ $? == 0 ] or die "could not read output of date '+%a, %d %b %Y %T %z'";
+    chomp($date = <$DATE_PIPE>);
+    close($DATE_PIPE);
+    return $date;
+};
+
+sub get_arch {
+    my @u = POSIX::uname();
+    return $u[4];
+};
+
+sub read_file {
+       # $1 is the file name and must exist.
+       my $contents;
+       my $file = "$_[0]";
+       my $f_handle;
+       # Autogen has been run, the file will be there.
+       if (-e $file) {
+               open($f_handle, "<", "$file") or
+                   die "Could not open $file.";
+               chomp($contents = <$f_handle>);
+               close($f_handle);
+               
+       } else {
+               die "Could not find $file file. run config/set_full_version or ./autogen";
+       }
+       return $contents;
+}
+
+sub fix_pkg_rev {
+    my $pkg_rev = "$_[0]";
+    # $1 should be a package type, and we build the rest of the regex string
+    # here for simplicity
+    my $type_match_str = "$_[1]0?";
+    # strip pkg_type and maybe a zero, else assign pkg_rev = 1
+    $pkg_rev = $pkg_rev =~ s/$type_match_str// || 1;
+    return $pkg_rev;
+    }
+
+my $pkg_type;
+# Check environment to see if it's something else.
+if (defined($ENV{'pkg_type'})) {
+       $pkg_type = $ENV{"pkg_type"};
+}
+# Check the file name for a clue
+elsif ( $ARGV[0] =~ /deb/ ) {
+       $pkg_type = "deb";
+}
+elsif ( $ARGV[0] =~ /rpm/ ) {
+       $pkg_type = "rpm";
+}
+elsif ( $ARGV[0] =~ /sun/ ) {
+       $pkg_type = "sun";
+}
+else {
+    die "Could not determine pkg_type either by environment variable, or
+       pathname of files to substitute ($ARGV[0]).";
+}
+
+# The keys to the hashes used are the "tags" we try to substitute.  Each
+# tag should be on a line by itself in the package file, as the whole line is
+# replaced by a set of lines.  The line may be commented.
+my %replacement_filenames = (
+       "%%COMMON_FUNCTIONS%%" => "packaging/common/common_functions.sh",
+       "%%PRE_INST_FUNCTIONS%%" => "packaging/common/pre_inst_functions.sh",
+       "%%POST_INST_FUNCTIONS%%" => "packaging/common/post_inst_functions.sh",
+       "%%POST_RM_FUNCTIONS%%" => "packaging/common/post_rm_functions.sh",
+# TODO: PRE_UNINST?
+);
+
+# These are handled slightly differently: The surrounding line is preserved, 
+# and only the tag is replaced.  This behavior is somewhat arbitrary, but
+# hopefully keeps replacements in comments syntax legal.
+my %replacement_strings_common = (
+       "%%VERSION%%" => read_file("FULL_VERSION"),
+       "%%PKG_REV%%" => read_file("PKG_REV"),
+       "%%AMANDAHOMEDIR%%" => "/var/lib/amanda",
+       "%%LOGDIR%%" => "/var/log/amanda",
+);
+
+my %replacement_strings_deb = (
+       # Used in debian changelog
+       "%%DISTRO%%" => "",
+       # Used in changelog
+       "%%DEB_REL%%" => "",
+       "%%DATE%%" => "",
+       # Used in rules
+       "%%PERL%%" => "",
+);
+
+my %replacement_strings_rpm = (
+);
+
+my %replacement_strings_sun = (
+    "%%ARCH%%" => "",
+);
+
+my %replacement_strings;
+if ( $pkg_type eq "deb" ) {
+       %replacement_strings = ( %replacement_strings_deb,
+                                %replacement_strings_common );
+        $replacement_strings{"%%PKG_REV%%"} =
+            fix_pkg_rev($replacement_strings{"%%PKG_REV%%"}, "deb");
+       # Let's determine the distro:
+       # Ubuntu has /etc/lsb-release, debian does not
+       open(my $LSB_RELEASE, "<", "/etc/lsb-release") or 
+               $replacement_strings{"%%DISTRO%%"} = "Debian";
+       my $line;
+       if ( $replacement_strings{"%%DISTRO%%"} ne "Debian" ) {
+               $replacement_strings{"%%DISTRO%%"} = "Ubuntu";
+               # We want the 2nd line
+               <$LSB_RELEASE>;
+               my @line = split /=/, <$LSB_RELEASE>;
+               chomp($line[1]);
+               $line[1] =~ s/\.//;
+               $replacement_strings{"%%DEB_REL%%"} = $line[1];
+               close($LSB_RELEASE);
+       } else {
+               open(my $DEB_RELEASE, "<", "/etc/debian_version") or die "could not read \"/etc/debian_version\": $!";
+               chomp($line = <$DEB_RELEASE>);
+               # Releases can have 3 fields.  we want the first 2.
+               $line =~ s/(\d+)\.(\d+).*/$1$2/;
+               $replacement_strings{"%%DEB_REL%%"} = $line;
+               close($DEB_RELEASE);
+       }
+       $replacement_strings{"%%DATE%%"} = get_date();
+       # 32bit should use bitrock perl, while 64bit should use builtin.  we 
+       # live on the edge and assume it's there.
+       my $arch = get_arch();
+       if ( $arch eq "x86_64" ) {
+               $replacement_strings{"%%PERL%%"} = $^X;
+       }
+       else {
+               $replacement_strings{"%%PERL%%"} = "/opt/zmanda/amanda/perl/bin/perl";
+       }
+}
+elsif ( $pkg_type eq "rpm" ){
+       %replacement_strings = ( %replacement_strings_rpm,
+                                %replacement_strings_common );
+        $replacement_strings{"%%PKG_REV%%"} =
+            fix_pkg_rev($replacement_strings{"%%PKG_REV%%"}, "rpm");
+}
+else {
+       %replacement_strings = ( %replacement_strings_sun,
+                                %replacement_strings_common );
+        $replacement_strings{"%%PKG_REV%%"} =
+            fix_pkg_rev($replacement_strings{"%%PKG_REV%%"}, "sun");
+       $replacement_strings{"%%DATE%%"} = get_date();
+       my $arch = get_arch();
+       if ( $arch eq "sun4u" ) {
+           $replacement_strings{"%%ARCH%%"} = "sparc";
+       }
+       elsif ( $arch eq "i86pc" ) {
+           $replacement_strings{"%%ARCH%%"} = "intel";
+       }
+       else {
+           die "Unknown solaris platform!";
+       }
+}
+
+# Make a hash of tags and the contents of replacement files
+my %replacement_data;
+while (my ($tag, $filename) = each %replacement_filenames) {
+       open(my $file, "<", $filename) or die "could not read \"$filename\": $!";
+       $replacement_data{$tag} = join "", <$file>;
+       close($file);
+}
+open my $src, "<", $ARGV[0] or die "could not read $ARGV[0]: $!";
+open my $dst, ">", $ARGV[1] or die "could not write $ARGV[1]: $!";
+select $dst;
+while (<$src>) {
+       chomp;
+       # check for tags, using non greedy matching
+       if ( m/(%%.+?%%)/ ) {
+               # Data replaces the line
+               if ( defined($replacement_data{$1})) {
+                       print $replacement_data{$1};
+               } 
+               # strings just replace the tag.
+               elsif ( defined($replacement_strings{$1})) {
+                       s/(%%.+?%%)/$replacement_strings{$1}/g;
+                       print "$_\n";
+               }
+       }
+       else {
+               # If we got here, print the line unmolested
+               print "$_\n";
+       }
+}