Update of /cvsroot/fink/fink/perlmod/Fink/Finally
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv19510/perlmod/Fink/Finally
Added Files:
BuildConflicts.pm Buildlock.pm
Log Message:
new Finally work
--- NEW FILE: Buildlock.pm ---
# -*- mode: Perl; tab-width: 4; -*-
#
# Fink::Finally::Buildlock module
#
# Fink - a package manager that downloads source and installs it
# Copyright (c) 2006 The Fink Package Manager Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# 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.
#
package Fink::Finally::Buildlock;
use base 'Fink::Finally';
use warnings;
use strict;
use POSIX qw(strftime);
use Fink::Command qw(mkdir_p rm_rf rm_f);
use Fink::Config qw($basepath $debarch $config $buildpath);
use Fink::PkgVersion;
use Fink::Services qw( lock_wait lol2pkglist execute dpkg_lockwait
apt_available );
=head1 NAME
Fink::Finally::Buildlock - Ensure that builds don't interfere.
=head1 DESCRIPTION
Buildlocks are designed to prevent concurrent fink processes from interfering
with each other's dependencies.
For example, if one fink process is compiling a package "foo" that has a
build-time dependency on the package "bar-dev", that fink process will set a
build-lock that prevents another fink (or dpkg or apt or...) from removing the
bar-dev package until the first fink process finishes building the package foo.
In addition, buildlocks prevent concurrent builds of any given package
(name-version-revision) to prevent the build processes from over-writing each
other's files.
See L<http://wiki.opendarwin.org/index.php/Fink:buildlocks> for more
information.
=head1 CLASS METHODS
=over 4
=item new
my $bl = Fink::Finally::Buildlock->new($pv);
Put a buildlock on the Fink::PkgVersion object I<$pv>. The lock will be
removed when I<$bl> goes out of scope.
=cut
# create an exclusive lock for the %f of the parent using dpkg
sub initialize {
my ($self, $pv) = @_;
# allow over-ride
return if Fink::Config::get_option("no_buildlock");
# lock on parent pkg
$pv = $pv->get_parent if $pv->has_parent;
$self->{_pv} = $pv;
# bootstrapping occurs before we have package-management tools
# needed for buildlocking. If you're bootstrapping into a location
# that already has a running fink, you already know you're gonne
# hose whatever may be running under that fink...
return if $pv->is_bootstrapping;
# The plan: get an exlusive lock for %n-%v-%r_$timestamp that
# automatically goes away when this fink process quit. Install a
# %n-%v-%r package that prohibits removal of itself if that lock
# is present. It's always safe to attempt to remove all installed
# buildlock pkgs since they can each determine if these locks are
# dead. Attempting to install a lockpkg for the same %n-%v-%r
# will cause existing one to attempt to be removed, which will
# fail iff its lock is still alive. Fallback to the newer pkg's
# prerm is okay because that will also be blocked by its own live
# lock.
print "Setting runtime build-lock...\n";
my $lockdir = "$basepath/var/run/fink/buildlock";
mkdir_p $lockdir or
die "can't create $lockdir directory for buildlocks\n";
my $timestamp = strftime "%Y.%m.%d-%H.%M.%S", localtime;
my $lockfile = $self->{_lockfile} = $lockdir . '/' . $pv->get_fullname()
. "_$timestamp.lock";
my $lock_FH = $self->{_lock_fh} = lock_wait($lockfile, exclusive => 1);
my $pkgname = $pv->get_name();
my $pkgvers = $pv->get_fullversion();
my $lockpkg = $self->{_lockpkg} = 'fink-buildlock-' .
$pv->get_fullname();
my $destdir = Fink::PkgVersion->get_install_directory($lockpkg);
if (not -d "$destdir/DEBIAN") {
mkdir_p "$destdir/DEBIAN" or
die "can't create directory for control files for
package $lockpkg\n";
}
# generate dpkg "control" file
my $control = <<EOF;
Package: $lockpkg
Source: fink
Version: $timestamp
Section: unknown
Installed-Size: 0
Architecture: $debarch
Description: Package compile-time lockfile
This package represents the compile-time dependencies of a
package being compiled by fink. The package being compiled is:
$pkgname ($pkgvers)
and the build process begun at $timestamp
.
Web site: http://wiki.opendarwin.org/index.php/Fink:buildlocks
.
Maintainer: Fink Core Group <[EMAIL PROTECTED]>
Maintainer: Fink Core Group <[EMAIL PROTECTED]>
Provides: fink-buildlock
EOF
# buildtime (anti)dependencies of pkg are runtime (anti)dependencies of
lockpkg
my $depfield;
$depfield = &lol2pkglist($pv->get_depends(1, 1));
if (length $depfield) {
$control .= "Conflicts: $depfield\n";
}
$depfield = &lol2pkglist($pv->get_depends(1, 0));
if (length $depfield) {
$control .= "Depends: $depfield\n";
}
### write "control" file
if (open my $controlfh, '>', "$destdir/DEBIAN/control") {
print $controlfh $control;
close $controlfh or die "can't write control file for $lockpkg:
$!\n";
} else {
die "can't write control file for $lockpkg: $!\n";
}
### set up the lockfile interlocking
# this is implemented in perl but PreRm is in bash so we gonna in-line
it
my $prerm = <<EOF;
#!/bin/bash -e
if [ failed-upgrade = "\$1" ]; then
exit 1
fi
if perl -e 'exit 0 unless eval { require Fink::Finally::Buildlock }; \\
exit !Fink::Finally::Buildlock->can_remove("$lockfile")'; then
rm -f $lockfile
exit 0
else
cat <<EOMSG
There is currently an active buildlock for the package
$pkgname ($pkgvers)
meaning some other fink process is currently building it.
EOMSG
exit 1
fi
EOF
### write prerm file
if (open my $prermfh, '>', "$destdir/DEBIAN/prerm") {
print $prermfh $prerm;
close $prermfh or die "can't write PreRm file for $lockpkg:
$!\n";
chmod 0755, "$destdir/DEBIAN/prerm";
} else {
die "can't write PreRm file for $lockpkg: $!\n";
}
### store our PID in a file in the buildlock package
my $deb_piddir = "$destdir$lockdir";
if (not -d $deb_piddir) {
mkdir_p $deb_piddir or
die "can't create directory for lockfile for package
$lockpkg\n";
}
if (open my $lockfh, ">$deb_piddir/" . $pv->get_fullname() . ".pid") {
print $lockfh $$,"\n";
close $lockfh or die "can't create pid file for package
$lockpkg: $!\n";
} else {
die "can't create pid file for package $lockpkg: $!\n";
}
### create .deb using dpkg-deb (in buildpath so apt doesn't see it)
if (&execute("dpkg-deb -b $destdir $buildpath")) {
die "can't create package $lockpkg\n";
}
rm_rf $destdir or
&print_breaking("WARNING: Can't remove package root directory ".
"$destdir. ".
"This is not fatal, but you may
want to remove ".
"the directory manually to save
disk space. ".
"Continuing with normal
procedure.");
# install lockpkg (== set dpkg lock on our deps)
print "Installing build-lock package...\n";
my $debfile =
$buildpath.'/'.$lockpkg.'_'.$timestamp.'_'.$debarch.'.deb';
my $lock_failed = &execute(dpkg_lockwait() . " -i $debfile",
ignore_INT=>1);
Fink::PkgVersion->dpkg_changed;
if ($lock_failed) {
print_breaking rejoin_text <<EOMSG;
Can't set build lock for $pkgname ($pkgvers)
If any of the above dpkg error messages mention conflicting packages or
missing dependencies -- for example, telling you that the package
fink-buildlock-$pkgname-$pkgvers
conflicts with something else -- fink has probably gotten confused by trying
to build many packages at once. Try building just this current package
$pkgname (i.e, "fink build $pkgname"). When that has completed successfully,
you could retry whatever you did that led to the present error.
Regardless of the cause of the lock failure, don't worry: you have not
wasted compiling time! Packages that had been completely built before
this error occurred will not have to be recompiled.
See http://wiki.opendarwin.org/index.php/Fink:buildlocks for more information.
EOMSG
# Failure due to dependency problems leaves lockpkg in an
# "unpacked" state, so try to remove it entirely.
unlink $lockfile;
close $lock_FH;
&execute(dpkg_lockwait() . " -r $lockpkg >/dev/null",
ignore_INT=>1);
}
# Even if installation fails, no reason to keep this around
rm_f $debfile or
&print_breaking("WARNING: Can't remove binary package file ".
"$debfile. ".
"This is not fatal, but you may
want to remove ".
"the file manually to save disk
space. ".
"Continuing with normal
procedure.");
die "buildlock failure\n" if $lock_failed;
# prime for cleanup
$self->SUPER::initialize();
}
sub finalize {
my ($self) = @_;
$self->SUPER::finalize();
# we were locked...
print "Removing runtime build-lock...\n";
close $self->{_lock_fh};
print "Removing build-lock package...\n";
my $lockpkg = $self->{_lockpkg};
# lockpkg's prerm deletes the lockfile
if (&execute(dpkg_lockwait() . " -r $lockpkg", ignore_INT=>1)) {
&print_breaking("WARNING: Can't remove package ".
"$lockpkg. ".
"This is not fatal, but you may
want to remove ".
"the package manually as it may
interfere with ".
"further fink operations. ".
"Continuing with normal
procedure.");
}
Fink::PkgVersion->dpkg_changed;
}
=item can_remove
my $fh = Fink::Finally::Buildlock->can_remove($lockfile);
Test if it is safe to remove a buildlock for a given lock-file.
After calling this, the caller must either close I<$fh> or delete the
lockfile.
=cut
sub can_remove {
my ($class, $lockfile) = @_;
return lock_wait("$lockfile", exclusive => 1, no_block => 1);
}
=back
=cut
1;
--- NEW FILE: BuildConflicts.pm ---
# -*- mode: Perl; tab-width: 4; -*-
#
# Fink::Finally::BuildConflicts module
#
# Fink - a package manager that downloads source and installs it
# Copyright (c) 2006 The Fink Package Manager Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# 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.
#
package Fink::Finally::BuildConflicts;
use base 'Fink::Finally';
use warnings;
use strict;
use Fink::CLI qw(die_breaking print_breaking_stderr);
use Fink::Config;
use Fink::PkgVersion;
=head1 NAME
Fink::Finally::BuildConflicts - Remove and restore BuildConflicts during a
Fink build.
=head1 DESCRIPTION
When a package has BuildConflicts, Fink::Finally::BuildConflicts will
remove any that are installed, and then restore them unconditionally
afterwards.
=head1 CLASS METHODS
=over 4
=item new
my $buildconfs = Fink::Finally::BuildConflicts->new($pvs);
Remove the BuildConflicts packages in the array-ref $pvs, and restore them
when I<$bc> goes out of scope.
=cut
sub initialize {
my ($self, $pvs) = @_;
$self->{remove} = [ grep { $_->is_installed } @$pvs ];
return unless @{$self->{remove}};
my @cant_restore = grep { !$_->is_present } @{$self->{remove}};
if (@cant_restore) {
die_breaking "The following packages must be temporarily
removed, but "
. "there are no .debs to restore them from:\n "
. join(' ', sort map { $_->get_name } @cant_restore);
}
my @names = sort map { $_->get_name } @{$self->{remove}};
my $names = join(' ', @names);
print_breaking_stderr "Temporarily removing BuildConflicts:\n $names";
Fink::PkgVersion::phase_deactivate([EMAIL PROTECTED]);
$self->SUPER::initialize();
}
sub finalize {
my ($self) = @_;
Fink::PkgVersion::phase_activate($self->{remove});
}
=back
=cut
1;
-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642
_______________________________________________
Fink-commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/fink-commits