File Coverage

blib/lib/App/ArduinoBuilder/FilePath.pm
Criterion Covered Total %
statement 41 69 59.4
branch 7 22 31.8
condition 2 11 18.1
subroutine 12 15 80.0
pod 0 3 0.0
total 62 120 51.6


line stmt bran cond sub pod time code
1             package App::ArduinoBuilder::FilePath;
2              
3 1     1   225482 use strict;
  1         8  
  1         28  
4 1     1   4 use warnings;
  1         2  
  1         23  
5 1     1   4 use utf8;
  1         2  
  1         4  
6              
7 1     1   407 use App::ArduinoBuilder::Logger;
  1         2  
  1         71  
8 1     1   400 use App::ArduinoBuilder::System 'system_canonpath';
  1         9  
  1         58  
9 1     1   7 use Exporter 'import';
  1         4  
  1         24  
10 1     1   5 use File::Find;
  1         1  
  1         60  
11 1     1   6 use File::Spec::Functions 'catdir';
  1         2  
  1         38  
12 1     1   5 use List::Util 'min', 'any';
  1         7  
  1         833  
13              
14             our @EXPORT_OK = qw(find_latest_revision_dir list_sub_directories find_all_files_with_extensions);
15              
16             sub _compare_version_string {
17 89     89   453 my @la = split /\.|-/, $a;
18 89         288 my @lb = split /\.|-/, $b;
19 89         344 for my $i (0..min($#la, $#lb)) {
20             # Let’s try to handle things like: 1.5.0-b
21 178   66     603 my $c = $la[$i] <=> $lb[$i] || $la[$i] cmp $lb[$i];
22 178 100       537 return $c if $c;
23             }
24 31         124 return $#la <=> $#lb;
25             }
26              
27             sub _pick_highest_version_string {
28 41     41   3692 return (sort _compare_version_string @_)[-1];
29             }
30              
31             # find_latest_revision('/path/to/dir') --> '/path/to/dir/9.8.2'
32             # Returns the input if there are no sub-directories looking like revisions in
33             # the given directory.
34             sub find_latest_revision_dir {
35 2     2 0 383 my ($dir) = @_;
36 2 50       100 opendir my $dh, $dir or fatal "Can’t open dir '$dir': $!";
37 2 100       60 my @revs_dir = grep { -d catdir($dir, $_) && m/^\d+(?:\.\d+)?(?:-.*)?/ } readdir($dh);
  9         189  
38 2         26 closedir $dh;
39 2 100       18 return $dir unless @revs_dir;
40 1         4 return catdir($dir, _pick_highest_version_string(@revs_dir));
41             }
42              
43             sub list_sub_directories {
44 0     0 0   my ($dir) = @_;
45 0 0         opendir my $dh, $dir or fatal "Can’t open dir '$dir': $!";
46 0 0         my @sub_dirs = grep { -d catdir($dir, $_) && ! m/^\./ } readdir($dh);
  0            
47 0           closedir $dh;
48 0           return @sub_dirs;
49             }
50              
51             # $dir can be a single directory to search or an array ref.
52             # excluded_dirs must be an array_ref
53             sub find_all_files_with_extensions {
54 0     0 0   my ($dir, $exts, $excluded_dirs, $no_recurse) = @_;
55 0           my $exts_re = join('|', @{$exts});
  0            
56 0   0       my @excluded_dirs = map { system_canonpath($_) } @{$excluded_dirs // []};
  0            
  0            
57 0           my @found;
58 0 0         my @dirs = ref $dir ? @{$dir} : $dir;
  0            
59 0           for my $d (@dirs) {
60 0 0 0 0     find(sub { push @found, $File::Find::name if -f && m/\.(?:$exts_re)$/;
61 0 0         if (-d) {
62             # $_ eq '.' only on the first, root directly that we are crawling.
63 0 0 0       if ($no_recurse && $_ ne '.') {
    0          
64 0           $File::Find::prune = 1;
65 0           return;
66             } elsif (/^\..+/) {
67 0           $File::Find::prune = 1;
68 0           return;
69             }
70 0           my $a = system_canonpath($_);
71 0           $File::Find::prune = any { $_ eq $a } @excluded_dirs;
  0            
72             }
73 0           }, $d);
74             }
75 0           return @found;
76             }
77              
78             1;