releasesystem

 view release on metacpan or  search on metacpan

devmgr/dev_rls_tool  view on Meta::CPAN

$VERSION = do {my @r=(q$Revision: 1.14 $=~/\d+/g);sprintf "%d."."%02d"x$#r,@r};
$revision = q{$Id: dev_rls_tool,v 1.14 2000/05/26 21:48:31 idsweb Exp $ };

exit show_version if (grep(/-version/i, @ARGV));

#
# These are the names that the tool is known by. These pseudo-constants are
# used instead of strings so that changes can be made, here, once.
#
$MAIN     = 'dev_rls_tool';
$STAGE    = 'stage';
$POPULATE = 'populate';
$RELEASE  = 'release';

#
# Set up a hash table for the valid lists of options keyed by the command name.
# In case of failure or -h, call a subroutine. With four different names to be
# called by, a traditional $USAGE string just doesn't hack it...
#
%valid_opts = (
               $RELEASE  => [ qw(-u=s -save -noxfer -update -stage -prod) ],
               $STAGE    => [ qw(-t=s -r=s -full -notag) ],
               $POPULATE => [ qw(-t=s -r=s) ],
               $MAIN     => [ qw(-d=s) ],
              );
Getopt::Long::config 'no_ignore_case';
exists($valid_opts{$cmd}) or die usage('unknown');
GetOptions(\%opts, (@{$valid_opts{$cmd}},
                    # These are common options to all forms
                    qw(-D=i -h -e=s -force -cvsroot=s -debug -verbose -terse
                       -log=s)))
    or die usage($cmd) . "\nStopped";
if ((defined $opts{h} and $opts{h}) or ($cmd ne $MAIN and ! @ARGV))
{
    print STDOUT usage($cmd) . "\n";
    exit 0;
}

#
# Force a false for all the boolean options, so that tests involving them
# don't produce "use of uninitialized value" warnings
#
grep($opts{$_} |= 0, qw(update stage prod force debug verbose terse));

#
# Simple default values used pretty much globally
#
$bin_dir = dirname $0;
($log_dir = $bin_dir) =~ s/ahp-bin/local/o;
$log_dir =~ s{/?suid_scripts}{};
$LOGFILE = $opts{'log'} || "$log_dir/dev_release.log";
# Undocumented incremental debugging option:
$DEBUG = $opts{D} || 0;
$DEBUG |= 1 if ($opts{debug});
STDOUT->autoflush;

#
# Save ourselves some repeated primitive operations by caching them here:
#
$opts{date} = scalar localtime;
$opts{user} = $ENV{LOGNAME} || (getpwuid($>))[0] || getlogin;
$opts{wmpassword} = $ENV{WMPASSWD} || '';

#
# Set up more extensive die()- and warn()-handlers
#
$SIG{__DIE__}  = sub {
                     chomp $_[0];
                     write_log_line($LOGFILE, "$opts{date} [$$] $_[0]");
                     die "$_[0]\n";
                 };
$SIG{INT}  = sub {
                     chomp $_[0];
                     write_log_line($LOGFILE, "$opts{date} [$$] $_[0]");
                     die "$_[0]\n";
                 };
$SIG{HUP}  = sub {
                     chomp $_[0];
                     write_log_line($LOGFILE, "$opts{date} [$$] $_[0]");
                     die "$_[0]\n";
                 };
$SIG{__WARN__} = sub {
                     chomp $_[0];
                     write_log_line($LOGFILE, "$opts{date} [$$] $_[0]");
                     warn "$_[0]\n";
                 };

#
# Special case: some of the steps below can only be done after the tool is
# initialized, so we handle the "main" cases specially
#
exit (do_admin(@ARGV)) if ($cmd eq $MAIN);

#
# Set this up so that an error condition doesn't inadvertently leave the 
# project in a locked state
#
END
{
    #
    # This relies on the various do_* routines to put the lockfile name into
    # %CONFIG under this name.
    #
    if (defined($CONFIG{lockfile}) and $CONFIG{lockfile})
    {
        unlink $CONFIG{lockfile};
    }
}

#
# Get any host-specific configuration:
#
read_config_file \%CONFIG;

#
# Set the value that the ACL modules used for a base directory:
#
if (defined $CONFIG{ACL_DIR})
{
    if ($CONFIG{ACL_DIR} !~ m|^/|)
    {
        my $homedir = ($CONFIG{OWNER} =~ /^\d+$/) ?
            (getpwuid($CONFIG{OWNER}))[7] :
            (getpwnam($CONFIG{OWNER}))[7];

        $CONFIG{ACL_DIR} = "$homedir/$CONFIG{ACL_DIR}";
    }

    ACL_dir $CONFIG{ACL_DIR};
}
elsif (-d "$log_dir/etc/acl")
{
    ACL_dir "$log_dir/etc/acl";
}
# Else use the default from IMS::ReleaseMgr::Access

#
# Read the release-host information from the database:
#
read_hostconfig \%HOSTS;

#
# Create the table of files that should be excluded, including a special regex
# for some cases.
#
for (qw(TOPICLIST WEBLIST RELEASE BUILDLIST))
{
    unless (exists $CONFIG{$_})
    {
        $CONFIG{$_} = '.' . lc $_;
    }
    $exclude_files{$CONFIG{$_}} = 1;
}
# Regex
$exclude_files{__RE__} = '(^#.*|~$)';

#
# Assign any other default %CONFIG values
#
$CONFIG{CVS} = $CONFIG{CVS} || 'cvs';

#
# Force the CVS root to be in the environment variable CVSROOT. This saves a
# fair amount of overhead in terms of always testing the config/env values.
#
if (defined($opts{cvsroot}) and $opts{cvsroot})
{
    $ENV{CVSROOT} = $opts{cvsroot};
}
elsif (defined($CONFIG{CVSROOT}) and $CONFIG{CVSROOT})
{
    $ENV{CVSROOT} = $CONFIG{CVSROOT};
}
elsif (! defined($ENV{CVSROOT}))
{
    die "$cmd: No CVSROOT found, please set the environment or use -cvsroot\n";
}

#
# Use this table to call the apropos routine based on the name by which this
# tool was called. "$MAIN" was handled earlier, so it is absent here.
#
%called_as = (

devmgr/dev_rls_tool  view on Meta::CPAN

#
#   Returns:        Success:    void
#                   Failure:    dies
#
###############################################################################
sub read_hostconfig
{
    my $table = shift;

    my ($buf, $data);

    $data = DBI_all_mirrors;
    unless (defined $data)
    {
        die "$cmd: read_hostconfig: Error getting full mirror data table: " .
            DBI_error . "\n";
    }
    write_log_line($LOGFILE,
                   sprintf("$opts{date} [$$] DBI mirror data read: %d hosts",
                           scalar(keys %$data)))
        if ($DEBUG & 14); # bxxxx111x

    %$table = %$data;
    return;
}

###############################################################################
#
#   Sub Name:       test_for_halt
#
#                   Since this routine is called for almost all invocations,
#                   it is not in the SelfLoader section.
#
#   Description:    Check to see if this particular command has been 
#                   temporarily disabled with a halt-file. If it has, display
#                   the halt-file contents (if any) on STDOUT.
#
#   Arguments:      NAME      IN/OUT  TYPE      DESCRIPTION
#                   $cmd      in      scalar    Name by which we were called
#
#   Globals:        $LOGFILE
#                   $DEBUG
#                   %opts
#                   %CONFIG
#
#   Environment:    None.
#
#                   NOTE NON-STANDARD RETURN LOGIC
#   Returns:        Success:    0, no halt file
#                   Failure:    1, program needs to stop
#
###############################################################################
sub test_for_halt
{
    my $cmd = shift;

    my $prefix = $CONFIG{HALTFILE_PREFIX};
    unless (defined $prefix and $prefix)
    {
        my $home = ($CONFIG{OWNER} =~ /^\d+$/o) ?
            (getpwuid($CONFIG{OWNER}))[7] : (getpwnam($CONFIG{OWNER}))[7];
        unless (defined $home and $home)
        {
            warn "$cmd: test_for_halt: Could not find haltfiles area, " .
                "skipping\n";
            return 0;
        }

        $prefix = "$home/etc/halt-";
    }
    if (! $prefix =~ m|^/|o)
    {
        my $home = ($CONFIG{OWNER} =~ /^\d+$/o) ?
            (getpwuid($CONFIG{OWNER}))[7] : (getpwnam($CONFIG{OWNER}))[7];
        unless (defined $home and $home)
        {
            warn "$cmd: test_for_halt: Could not find haltfiles area, " .
                "skipping\n";
            return 0;
        }

        $prefix = "$home/$prefix";
    }

    my $file = "${prefix}$cmd";
    if (-e $file)
    {
        #
        # There is a haltfile. If it is not zero-length, echo it to STDOUT. If
        # the user is a member of group $CONFIG{GROUP}, they can use -force to
        # override this.
        #
        if (defined $opts{force})
        {
            my $userlist = ($CONFIG{GROUP} =~ /^\d+$/o) ?
                (getgrgid($CONFIG{GROUP}))[3] : (getgrnam($CONFIG{GROUP}))[3];
            my @userlist = split(/ /, $userlist);

            return 0 if (grep($_ eq $opts{user}, @userlist));
            warn "$cmd: You are not authorized to use the -force option\n";
        }
        if (-s $file) # size != 0
        {
            my $fh = new IO::File "< $file";

            if (! defined $fh)
            {
                warn "$cmd haltfile $file exists but is unreadable: $!\n";
                return 1;
            }

            print STDOUT "Command $cmd currently under a halt:\n\n";
            print STDOUT <$fh>;
            print STDOUT "\nMembers of group $CONFIG{GROUP} can use -force\n";
            print STDOUT "to override this.\n";
            $fh->close;
        }

        return 1;
    }

    # No haltfile, no worries
    0;
}

__END__

###############################################################################
#
#   Sub Name:       deduce_host
#
#   Description:    Using the known hosts in the global hash %HOSTS, try to
#                   find the most-recently-staged host for $project
#



( run in 0.675 second using v1.01-cache-2.11-cpan-97f6503c9c8 )