in reply to Re^6: manipulating cpio archive
in thread manipulating cpio archive

I would asume that this is a bug in Archive::Cpio. The ->remove subroutine treats $archive->{list} as an array of strings (as do the examples), but it contains Archive::Cpio::File objects that don't seem to have stringification overload.

You'll likely need to rewrite the ->remove method to actually remove elements by their ->name (and raise a bug against the module, please).

The test suite only tests that the (main) module can be loaded and tests no functionality at all, so adding a test for ->remove wouldn't hurt either.

Replies are listed 'Best First'.
Re^8: manipulating cpio archive
by momo33 (Beadle) on Jan 17, 2011 at 20:41 UTC
    Thank you.
    You put it more precise, but I already concluded that the code could not be right. I hope a fix will be made, there is an outstanding bug 2 years old. This code is a bit over my head.
      As I already wrote, this code is over my head. I would like to fix the old code temporarily
      OLD BUGGED CODE: sub remove { my ($cpio, @filenames) = @_; $cpio->{list} or die "can't remove from nothing\n"; my %filenames = map { $_ => 1 } @filenames; @{$cpio->{list}} = grep { !$filenames{$_} } @{$cpio->{list}}; }
      with something like this
      WRONG NEW CODE sub remove { my ($cpio, @filenames) = @_; $cpio->{list} or die "can't remove from nothing\n"; foreach $item (@{$cpio->{list}}) { foreach $file (@filesnames) { if ($item->{name} eq $file){ delete @{$cpio2->{list}->{$item}}; } } } return; }
      How should this be done?

        The only flaw of the old code is that it directly compares elements from @{ $cpio->{list} } against the filenames. That is wrong because the elements in @{ $cpio->{list} } are Archive::Cpio::File objects. Instead, it should compare the elements against the ->name property. Most likely (but untested) like so:

        sub remove { my ($cpio, @filenames) = @_; $cpio->{list} or die "can't remove from nothing\n"; # Create a lookup table of names to be removed my %filenames = map { $_ => 1 } @filenames; # This was the old, buggy code # @{$cpio->{list}} = grep { !$filenames{$_} } @{$cpio->{list}}; # Remove the elements according to their name: @{$cpio->{list}} = grep { !$filenames{$_->name} } @{$cpio->{list}} +; }