-
Notifications
You must be signed in to change notification settings - Fork 194
/
Copy pathArchive.pm
174 lines (133 loc) · 3.67 KB
/
Archive.pm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
package MetaCPAN::Model::Archive;
use v5.10;
use Moose;
use MooseX::StrictConstructor;
use MetaCPAN::Types::TypeTiny qw( AbsPath ArrayRef Bool InstanceOf Str );
use Archive::Any ();
use Carp qw( croak );
use Digest::file qw( digest_file_hex );
use Path::Tiny qw( path );
=head1 NAME
MetaCPAN::Model::Archive - Inspect and extract archive files
=head1 SYNOPSIS
use MetaCPAN::Model::Archive;
my $archive = MetaCPAN::Model::Archive->new( file => $some_file );
my $files = $archive->files;
my $extraction_dir = $archive->extract;
=head1 DESCRIPTION
This class manages getting information about and extraction of archive
files (tarballs, zipfiles, etc...) and their extraction directories.
The object is read-only and will only extract once. If you alter the
extraction directory and want a fresh one, make a new object.
The Archive will clean up its extraction directory upon destruction.
=head1 ATTRIBUTES
=head3 archive
I<Required>
The file to be extracted. It will be returned as a Path::Tiny
object.
=cut
has file => (
is => 'ro',
isa => AbsPath,
coerce => 1,
required => 1,
);
has _extractor => (
is => 'ro',
isa => InstanceOf ['Archive::Any'],
handles => [ qw(
is_impolite
is_naughty
) ],
init_arg => undef,
lazy => 1,
default => sub {
my $self = shift;
croak $self->file . ' does not exist' unless -e $self->file;
return Archive::Any->new( $self->file );
},
);
# MD5 digest for the archive file
has file_digest_md5 => (
is => 'ro',
isa => Str,
lazy => 1,
default => sub {
my $self = shift;
digest_file_hex( $self->file, 'MD5' );
},
);
# SHA256 digest for the archive file
has file_digest_sha256 => (
is => 'ro',
isa => Str,
lazy => 1,
default => sub {
my $self = shift;
digest_file_hex( $self->file, 'SHA-256' );
},
);
# Holding the File::Temp::Dir object here is necessary to keep it
# alive until the object is destroyed.
has _tempdir => (
is => 'ro',
isa => AbsPath,
init_arg => undef,
lazy => 1,
default => sub {
my $scratch_disk = '/mnt/scratch_disk';
return -d $scratch_disk
? Path::Tiny->tempdir('/mnt/scratch_disk/tempXXXXX')
: Path::Tiny->tempdir;
},
);
has extract_dir => (
is => 'ro',
isa => AbsPath,
lazy => 1,
coerce => 1,
default => sub {
my $self = shift;
return path( $self->_tempdir );
},
);
has _has_extracted => (
is => 'ro',
isa => Bool,
init_arg => undef,
default => 0,
writer => '_set_has_extracted',
);
=head1 METHODS
=head3 files
my $files = $archive->files;
A list of the files in the archive as an array ref.
=cut
# A cheap way to cache the result.
has files => (
is => 'ro',
isa => ArrayRef,
init_arg => undef,
lazy => 1,
default => sub {
my $self = shift;
return [ $self->_extractor->files ];
},
);
=head3 extract
my $extract_dir = $archive->extract;
Extract the archive into a temp directory. The directory will be a
L<Path::Tiny> object.
Only the first call to extract will perform the extraction. After
that it will just return the extraction directory. If you want to
re-extract the archive, create a new object.
The extraction directory will be cleaned up when the object is destroyed.
=cut
sub extract {
my $self = shift;
return $self->extract_dir if $self->_has_extracted;
$self->_extractor->extract( $self->extract_dir );
$self->_set_has_extracted(1);
return $self->extract_dir;
}
1;