File Coverage

blib/lib/Filename/Archive.pm
Criterion Covered Total %
statement 31 32 96.8
branch 8 10 80.0
condition 1 2 50.0
subroutine 4 4 100.0
pod 1 1 100.0
total 45 49 91.8


line stmt bran cond sub pod time code
1             package Filename::Archive;
2              
3             our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
4             our $DATE = '2020-06-02'; # DATE
5             our $DIST = 'Filename-Archive'; # DIST
6             our $VERSION = '0.031'; # VERSION
7              
8 1     1   602 use 5.010001;
  1         9  
9 1     1   6 use strict;
  1         2  
  1         19  
10 1     1   5 use warnings;
  1         16  
  1         611  
11              
12             require Exporter;
13             our @ISA = qw(Exporter);
14             our @EXPORT_OK = qw(check_archive_filename);
15             #list_archive_suffixes
16              
17             # XXX multi-part archive?
18              
19             our %SUFFIXES = (
20             '.7z' => {name=>'7-zip'},
21             '.cb7' => {name=>'7-zip'},
22              
23             '.zip' => {name=>'Zip'},
24             '.cbz' => {name=>'Zip'},
25              
26             '.rar' => {name=>'RAR'},
27             '.cbr' => {name=>'RAR'},
28              
29             '.tar' => {name=>'tar'},
30             '.cbt' => {name=>'tar'},
31              
32             '.tgz' => {name=>'tar+gzip'},
33             '.tbz' => {name=>'tar+bzip2'},
34              
35             '.ace' => {name=>'ACE'},
36             '.cba' => {name=>'ACE'},
37              
38             '.arj' => {name=>'arj'},
39             # XXX other older/less popular: lha, zoo
40             # XXX windows: cab
41             # XXX zip-based archives: war, etc
42             # XXX tar-based archives: linux packages
43             );
44              
45             our %ARCHIVES = (
46             'arj' => {
47             },
48             '7-zip' => {
49             },
50             Zip => {
51             # all programs mentioned here must accept filename(s) as arguments.
52             # preferably CLI. XXX specify capabilities (password-protection, unix
53             # permission, etc). XXX specify how to create (with password, etc). XXX
54             # specify how to extract.
55             archiver_programs => [
56             {name => 'zip', opts => ''},
57             ],
58             extractor_programs => [
59             {name => 'zip', opts => ''},
60             {name => 'unzip', opts => ''},
61             ],
62             },
63             RAR => {
64             },
65             tar => {
66             },
67             'tar+gzip' => {
68             },
69             'tar+bzip2' => {
70             },
71             ace => {
72             extractor_programs => [
73             {name => 'unace', opts => ''},
74             ],
75             },
76             );
77              
78             our %SPEC;
79              
80             $SPEC{check_archive_filename} = {
81             v => 1.1,
82             summary => 'Check whether filename indicates being an archive file',
83             description => <<'_',
84              
85              
86             _
87             args => {
88             filename => {
89             schema => 'str*',
90             req => 1,
91             pos => 0,
92             },
93             # XXX recurse?
94             ci => {
95             summary => 'Whether to match case-insensitively',
96             schema => 'bool',
97             default => 1,
98             },
99             },
100             result_naked => 1,
101             result => {
102             schema => ['any*', of=>['bool*', 'hash*']],
103             description => <<'_',
104              
105             Return false if no archive suffixes detected. Otherwise return a hash of
106             information, which contains these keys: `archive_name`, `archive_suffix`,
107             `compressor_info`.
108              
109             _
110             },
111             };
112             sub check_archive_filename {
113 4     4 1 573 require Filename::Compressed;
114              
115 4         578 my %args = @_;
116              
117 4         8 my $filename = $args{filename};
118 4   50     19 my $ci = $args{ci} // 1;
119              
120 4         9 my @compressor_info;
121 4         5 while (1) {
122 7         19 my $res = Filename::Compressed::check_compressed_filename(
123             filename => $filename, ci => $ci);
124 7 100       211 if ($res) {
125 3         6 push @compressor_info, $res;
126 3         5 $filename = $res->{uncompressed_filename};
127 3         5 next;
128             } else {
129 4         8 last;
130             }
131             }
132              
133 4 50       16 $filename =~ /(\.\w+)\z/ or return 0;
134 4         9 my $suffix = $1;
135              
136 4         5 my $spec;
137 4 50       8 if ($ci) {
138 4         7 my $suffix_lc = lc($suffix);
139 4         15 for (keys %SUFFIXES) {
140 38 100       84 if (lc($_) eq $suffix_lc) {
141 3         5 $spec = $SUFFIXES{$_};
142 3         5 last;
143             }
144             }
145             } else {
146 0         0 $spec = $SUFFIXES{$suffix};
147             }
148 4 100       31 return 0 unless $spec;
149              
150             return {
151             archive_name => $spec->{name},
152 3         37 archive_suffix => $suffix,
153             (compressor_info => \@compressor_info) x !!@compressor_info,
154             };
155             }
156              
157             1;
158             # ABSTRACT: Check whether filename indicates being an archive file
159              
160             __END__