#!/usr/bin/perl -w
# set_mav_vsn [-v] [-q|h|s] [ -i|e version]
# install/erase/query maverik version
# called by rpm to manage symlinks for default mav version.

# TODO

$package="Maverik";
$package_basedir="/usr/lib";

$self="Maverik-5.0";
@symlinks= qw/ incl lib man src /;

use Config;
use vars qw( $opt_s $opt_q $opt_v $opt_h $opt_e $opt_i );
use Getopt::Std;

#use this to test the version sorting routine
# @tst_arry= qw( Maverik-3.0b4 Maverik-2.00 Maverik-3.0 Maverik-3.0a11 Maverik-3.11b1 Maverik-4.0 );
# foreach (sort by_version @tst_arry){
#     print "$_\n";
#     }
# exit 0;

getopts("i:e:qsvh") or usage();

# print usage if help, or 

$mutex++ if $opt_q;
$mutex++ if $opt_e;
$mutex++ if $opt_i;
$mutex++ if $opt_h;
$mutex++ if $opt_s;

if ($mutex>1){
    print "\nOnly one of -q -e -i -s -h please\n";
    usage();
    }

# check it's linux
if ($Config{osname} ne "linux"){
    print "set_mav_vsn only runs on linux\n";
    exit 1;
    }

# see which is currently linked version if any
if( $file=readlink "$package_basedir/$package/$symlinks[0]"){
    ($current_vsn)= $file=~m!$package_basedir/$package/$package-([^/]*)/!;
    }
    
# get installed vsns - by looking at dir.
opendir D, "$package_basedir/$package" 
    or die "couldnt read $package_basedir/$package\n";
@vsns_installed= sort by_version grep /^$package/, readdir D;
closedir D;

# print findings if verbose
if($opt_q || $opt_v){
    if($#vsns_installed <0){
	print "there are no installed versions of $package\n";
	}
    else{
	print "Installed versions of $package:\n";
	foreach $vsn (@vsns_installed){
	    if ( defined $current_vsn && ("$package-$current_vsn" eq $vsn)){
		print " * $vsn\n";
		}
	    else{
		print "   $vsn\n";
		}
	    }
	print "   no version is currently active\n" unless $current_vsn;
	}
    exit 0 if $opt_q;
    }


# unfortunately cant do the following, as rpm isnt reentrant.
# fault on the first rpm we did as thats not multi-vsn compat.
# if (grep /^Maverik-3.0b2-1/, `rpm -q Maverik`){
#     print "\n  Oops, sorry you'll need to remove Maverik-3.0b2-1 first,\n";
#     print "  as the directory structures rpm uses for that werent configured\n";
#     print "  to co-reside with multiple versions of Maverik\n";
#     exit 1;
#     }

# we need to be root
$> && die "We need to run as root to do much more.\n";

# erase option - erases all symlinks to given version
if ($opt_e){
    chdir ("$package_basedir/$package") || 
	die "couldnt chdir to $package_basedir/$package\n";

    $erase_version="$package-$opt_e";
    opendir D,"$package_basedir/$package" or
	die "couldnt open $package_basedir/$package dir\n";

    foreach (grep -l,  readdir D){
	if ( (readlink "$package_basedir/$package/$_") =~m!/$erase_version/!){
	    print "unlinking $_ \n" if $opt_v;
	    unlink $_ or die "couldnt unlink $_\n";
	    }
	}
    closedir D;
    exit 0;
    }

# set specific version
# this calls the set_mav_vsn for the nominated version
# so it can install itself.
if($opt_i){

    if ($opt_i =~ /newest/){
	if ($#vsns_installed < 0){
	    die "there is No newest version (none installed)\n";}
	else{
	    $install_version=$vsns_installed[0]; }
	}
    else{
	$install_version="$package-$opt_i";
	}

    print "installing for version $install_version\n" if $opt_v;

    if (! -e "$package_basedir/$package/$install_version"){
	print "Error - $install_version does not exist\n";}

    if (! -x "$package_basedir/$package/$install_version/bin/set_mav_vsn"){
	print "Error - $install_version does not know how to install itself";
	print "        perhaps it's a very early version? if so best remove it.\n";
	exit 1;
	}

    # call set_mav_vsn -s on it to install itself.
    `$package_basedir/$package/$install_version/bin/set_mav_vsn -s`;
    exit 0;
    }

if ($opt_s){
    # do the sym-linking for self version
    chdir("$package_basedir/$package");
    
    #remove existing symlinks if any
    print "Removing existing symlinks..\n" if $opt_v;
    
    opendir D,"$package_basedir/$package" or
	die "couldnt open $package_basedir/$package dir\n";
    foreach (grep -l, readdir D){
	if ((readlink $_) =~ m!$package-!){
	    print "unlinking $_ \n" if $opt_v;
	    unlink $_ or die "couldnt unlink $_\n";}
	}
    closedir D;

    #create links to default package
    print "Setting links to $self\n" if $opt_v;

    foreach (@symlinks){
	if (! -d "$package_basedir/$package/$self/$_"){
	    die "Error - $package_basedir/$package/$self/$_ is not a directory\n";}
	if (-e "$package_basedir/$package/$_"){
	    die "Error - $package_basedir/$package/$_ still exists\n";
	    }

	symlink("$package_basedir/$package/$self/$_","$_")||
	    warn "failed to create symlink to $_\n";
	}
    exit 0;
    }

sub by_version{
    my($a_maj,$a_min,$a_ty,$a_ty_vsn)= $a=~/^[^-]*-(\d*)\.(\d*)(?:([abp])(\d*))?$/;
    my($b_maj,$b_min,$b_ty,$b_ty_vsn)= $b=~/^[^-]*-(\d*)\.(\d*)(?:([abp])(\d*))?$/;
    if (!defined $a_ty){
	$a_ty="p";
	$a_ty_vsn=0;}
    if (!defined $b_ty){
	$b_ty="p";
	$b_ty_vsn=0;
	}
    $b_maj <=> $a_maj
	or
    $b_min <=> $a_min
	or
    $b_ty cmp $a_ty
	or
    $b_ty_vsn <=> $a_ty_vsn
	or
    $b cmp $a;
    }

sub usage{
    print <<EOT;

usage:
set_mav_vsn [-v] [q|h|s|-i vsn |-e vsn] 

  Set active maverik version.
  Sets up the symlinks in the /usr/lib/Maverik/ directory to point to the
  desired installed maverik version. No args implies most recent.

  options:
      -h       -> this help
      -e vsnno -> remove symlinks for vsnno if any.
      -i vsnno -> set version to vsnno (e.g. 3.0b4)
                  using "newest" for vsnno will use the newest instaled
                  version.
      -s       -> install self. Install the mav vsn that
	          this set_mav_vsn belongs to.
      -q       -> query vsn - prints info on installed vsns
      -v       -> verbose
EOT
exit 0;

    }

# pod documentation

=head1 NAME

set_mav_vsn - setup symlinks to maverik version.

=head1 SYNOPSIS

    set_mav_vsn [-v] [-h|-q|-s|-i vsnno|-e vsnno]

=head1 DESCRIPTION

B<set_mav_vsn> is really intended to be used by the install scripts of a
maverik rpm package. It sets up the symlinks in the Maverik directory (e.g. bin,
incl...) to point to a particular maveric version. This facilitates
installation of co-resident versions of maverik.

Maverik uses a "Maverik" directory with specific installed versions
underneath that, and symlinks in the Maverik directory to point at the
components of the desired default version. As its messing with the
symlinks in /usr/lib/Maverik, B<set_mav_vsn> needs to be run as root.

When using C<-i> to install a given vsn, B<set_mav_vsn> finds the appropriate
maverik version and then calls its B<set_mav_vsn> with the C<-s> option to 
install that specific version.

Though you can install multiple versions of maverik, you shouldnt install
multiple rpm releases of the same version (e.g. Maverik-3.0b4-1 and
Maverik-3.0b4-2) as those are really exactly the same versions (with
modified packaging) so would cause some confusion. If you get into that
state, just rpm B<-e> those versions and install the latest.

Note that this wont work with Maverik-3.0b2-1 (the very first maverik
rpm package), as it didnt use the now conventional directory structure
for co-resident packages, so you should remove that first.

=head1 OPTIONS

=over 4


=item -q 

query. Prints info on exising maverik versions. This is determined
by searching the Maverik directory for installed versions.

=item -i version

Set to specified version. Version is the number that the
installed packages directory uses, so for example with
the Maverik package its directory structure is
/usr/lib/Maverik/Maverik-3.0b4/... so an option of 
C<-v 3.0b4> will set the symlinks in /usr/lib/Maverik to
point at the necessary Maverik-3.0b4 components.

If the special version B<newest> is used, then the most recent
(highest) version number will be set up as the current maverik
installation.

=item -e version

erases the Maverik symlinks to version if any. This is used as
a step in uninstalling a package. Have a look at the spec file
if you want to see the detail.

=item -s

install self. Set up symlinks to point to the maverik version
that this particular set_mav_vsn belongs to. The idea is that
any set_mav_vsn asked to install a specific version with C<-i> will
find the directory for that version and then call its set_mav_vsn
script with C<-s>, as that script will know which symlinks that
version requires. Sort of future proof.

=item -v

be verbose.

=item -h

helpful usage message

=back

=head1 AUTHOR

ajw

=cut

# to make the man page, 
# /usr/bin/pod2man --center="Maverik" --release="Maverik-5.0" set_mav_vsn |/usr/bin/groff -Tascii -mandoc >set_mav_vsn.3

