1 package Fedora
::Rebuild
::Package
::StateLock
;
4 use version
0.77; our $VERSION = version
->declare("v0.2.0");
11 use Storable
qw(nstore_fd retrieve);
17 isa
=> 'Fedora::Rebuild::Package',
50 if (! defined $self->state || $self->state eq '') {
51 croak
"Invalid `state' attributed passed to StateLock constructor";
57 return $self->package->packagedir . '/.' . $self->state;
62 return $self->lockfile. '.log';
67 my $file = IO
::Handle
->new();
68 open ($file, '>', $self->logfile) or
69 croak
"Could not create `" . $self->logfile . "' logfile: $!";
73 # Print array into log
75 shift->logfd->print(@_);
78 # Return true if state is finshed, otherwise open log file.
82 if (-e
$self->lockfile) {
90 # Create lock file signalling the state has been finished. is_done() return
91 # true then. Return true if succeeded.
94 my $file = IO
::Handle
->new();
95 open ($file, '>', $self->lockfile) or
96 croak
"Could not open `" . $self->lockfile .
97 "' lockfile for writing: $!";
98 $file->sync && close($file) or
99 croak
"Could not sync and close `" . $self->lockfile .
104 # Close log file. Remove lock file if exist. is_done() return false then.
108 $self->logfd->sync && $self->logfd->close or
109 croak
"Could not sync and close `" . $self->logile . "' logfile: $!";
110 if (-e
$self->lockfile) { unlink $self->lockfile; }
114 # Convert ${^CHILD_ERROR_NATIVE} to string description.
115 # XXX: This is not a method.
116 sub child_error_as_string
{
117 my $reason = ${^CHILD_ERROR_NATIVE
};
118 if (WIFEXITED
($reason)) {
119 $reason = "exit code " . WEXITSTATUS
($reason);
120 } elsif (WIFSIGNALED
($reason)) {
121 $reason = "signal " . WTERMSIG
($reason);
126 # Format array of command with argument as quoted string
127 # XXX: This not a method
129 $Data::Dumper
::Indent
=0;
130 $Data::Dumper
::Terse
=1;
131 return '(' . join(' ', map {Dumper
($_)} @_) . ')';
134 # Run command while appending output to log. Blocks. If workdir is nonempty
135 # string, switch into it befere execution (and opening the log).
136 # Return true if command succeeds.
138 my ($self, $workdir, @command) = @_;
141 open(STDOUT
, '>&', $self->logfd->fileno) and
142 open(STDERR
, '>&STDOUT');
143 print STDERR
"Executing: " . format_command
(@command) . "\n";
144 if (defined $workdir && $workdir ne '' && !chdir $workdir) {
145 print STDERR
"Could not change directory to $workdir: $!\n";
150 my $pid = Proc
::SyncExec
::sync_exec
($redirect, @command);
152 $self->log("Could not execute " . format_command
(@command) . ": $!\n");
155 if ($pid != waitpid($pid, 0) || $?
) {
156 $self->log("Command " . format_command
(@command) . " failed: " .
157 child_error_as_string
. "\n");
160 $self->log("Command " . format_command
(@command) .
161 " returned successfully.\n");
165 # Run command while appending stderr and stdout to log and stdout to refered
166 # output argument. In case of empty command output fill empty string;
167 # Blocks. If workdir is nonempty string, switch into it befere execution
168 # (and opening the log).
169 # Return true if command succeeds.
171 my ($self, $workdir, $output, @command) = @_;
173 my ($parent, $child);
174 if (!pipe $child, $parent) {
175 $self->log("Could not get connected pipes for command " .
176 format_command
(@command) . ": $!\n");
182 open(STDOUT
, '>&', fileno $parent) and
185 open(STDERR
, '>&', $self->logfd->fileno) and
186 print STDERR
"Executing: " . format_command
(@command) . "\n";
187 if (defined $workdir && $workdir ne '' && !chdir $workdir) {
188 print STDERR
"Could not change directory to $workdir: $!\n";
193 my $pid = Proc
::SyncExec
::sync_exec
($redirect, @command);
200 $self->log("Could not execute " . format_command
(@command) . ": $!\n");
204 for ($$output = ''; local $_ = <$child>;) {
209 if ($pid != waitpid($pid, 0) || $?
) {
210 $self->log("Command " . format_command
(@command) . " failed: " .
211 child_error_as_string
. "\n");
215 $self->log("Command " . format_command
(@command) .
216 " returned successfully.\n");
220 # Serialize referenced variable into file identified by name.
221 # The file is recreated.
222 # Return true if command succeeds, otherwise false;
223 sub nstorereference
{
224 my ($self, $reference, $filename) = @_;
227 my $file = IO
::Handle
->new();
228 if (! open($file, '>', $filename)) {
229 $self->log("Could not open `" . $filename . "' file for writing: $!\n");
232 if (! eval { nstore_fd
($reference, $file); }) {
233 $self->log("Could not store variable into `" . $filename .
238 if (!$file->sync or !close($file)) {
239 $self->log("Could not sync and close `" . $filename . "' file: $!\n");
246 # Load serialized variable from file identified by name.
247 # Return reference to the variable or undef in case of error.
248 sub retrievereference
{
249 my ($self, $filename) = @_;
252 if (! eval { $reference = retrieve
($filename); } || !$reference) {
253 $self->log("Could not load variable from `" . $filename .