File: Util.pm

package info (click to toggle)
perlbrew 1.01-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 744 kB
  • sloc: perl: 9,241; makefile: 7; sh: 1
file content (154 lines) | stat: -rw-r--r-- 3,868 bytes parent folder | download | duplicates (2)
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
package App::Perlbrew::Util;
use strict;
use warnings;
use 5.008;

use Exporter 'import';
our @EXPORT = qw( uniq min editdist files_are_the_same perl_version_to_integer );
our @EXPORT_OK = qw(
    find_similar_tokens
    looks_like_url_of_skaji_relocatable_perl
    looks_like_sys_would_be_compatible_with_skaji_relocatable_perl
    make_skaji_relocatable_perl_url
);

sub uniq {
    my %seen;
    grep { !$seen{$_}++ } @_;
}

sub min(@) {
    my $m = $_[0];
    for(@_) {
        $m = $_ if $_ < $m;
    }
    return $m;
}

# straight copy of Wikipedia's "Levenshtein Distance"
sub editdist {
    my @a = split //, shift;
    my @b = split //, shift;

    # There is an extra row and column in the matrix. This is the
    # distance from the empty string to a substring of the target.
    my @d;
    $d[$_][0] = $_ for (0 .. @a);
    $d[0][$_] = $_ for (0 .. @b);

    for my $i (1 .. @a) {
        for my $j (1 .. @b) {
            $d[$i][$j] = ($a[$i-1] eq $b[$j-1] ? $d[$i-1][$j-1]
                : 1 + min($d[$i-1][$j], $d[$i][$j-1], $d[$i-1][$j-1]));
        }
    }

    return $d[@a][@b];
}

sub files_are_the_same {
    ## Check dev and inode num. Not useful on Win32.
    ## The for loop should always return false on Win32, as a result.

    my @files = @_;
    my @stats = map {[ stat($_) ]} @files;

    my $stats0 = join " ", @{$stats[0]}[0,1];
    for (@stats) {
        return 0 if ((! defined($_->[1])) || $_->[1] == 0);
        unless ($stats0 eq join(" ", $_->[0], $_->[1])) {
            return 0;
        }
    }
    return 1
}

sub perl_version_to_integer {
    my $version = shift;

    my @v;
    if ($version eq 'blead') {
        @v = (999,999,999);
    } else {
        @v = split(/[\.\-_]/, $version);
    }
    return undef if @v < 2;

    if ($v[1] <= 5) {
        $v[2] ||= 0;
        $v[3] = 0;
    }
    else {
        $v[3] ||= $v[1] >= 6 ? 9 : 0;
        $v[3] =~ s/[^0-9]//g;
    }

    return $v[1]*1000000 + $v[2]*1000 + $v[3];
}

sub find_similar_tokens {
    my ($token, $tokens) = @_;
    my $SIMILAR_DISTANCE = 6;

    my @similar_tokens = sort { $a->[1] <=> $b->[1] } map {
        my $d = editdist( $_, $token );
        ( ( $d < $SIMILAR_DISTANCE ) ? [$_, $d] : () )
    } @$tokens;

    if (@similar_tokens) {
        my $best_score = $similar_tokens[0][1];
        @similar_tokens = map { $_->[0] } grep { $_->[1] == $best_score } @similar_tokens;
    }

    return \@similar_tokens;
}

sub looks_like_url_of_skaji_relocatable_perl  {
    my ($str) = @_;
    # https://github.com/skaji/relocatable-perl/releases/download/5.40.0.0/perl-linux-amd64.tar.gz
    my $prefix = "https://github.com/skaji/relocatable-perl/releases/download";
    my $version_re = qr/(5\.[0-9][0-9]\.[0-9][0-9]?.[0-9])/;
    my $name_re = qr/perl-(linux|darwin)-(amd64|arm64)\.tar\.gz/;
    return undef unless $str =~ m{ \Q$prefix\E / $version_re / $name_re }x;
    return {
        url => $str,
        version => $1,
        os => $2,
        arch => $3,
        original_filename => "perl-$2-$3.tar.gz",
    };
}


sub _arch_compat {
    my ($arch) = @_;
    my $compat = {
        x86_64 => "amd64",
        i386   => "amd64",
    };
    return $compat->{$arch} || $arch;
}

sub looks_like_sys_would_be_compatible_with_skaji_relocatable_perl {
    my ($detail, $sys) = @_;

    return (
        ($detail->{os} eq $sys->os)
        && (_arch_compat($detail->{arch}) eq _arch_compat($sys->arch))
    );
}

sub make_skaji_relocatable_perl_url {
    my ($str, $sys) = @_;
    if ($str =~ m/\Askaji-relocatable-perl-(5\.[0-9][0-9]\.[0-9][0-9]?.[0-9])\z/) {
        my $version = $1;
        my $os = $sys->os;
        my $arch = $sys->arch;
        $arch = "amd64" if $arch eq 'x86_64' || $arch eq 'i386';

        return "https://github.com/skaji/relocatable-perl/releases/download/$version/perl-$os-$arch.tar.gz";
    }
    return undef;
}

1;