add ppport checks and commands
[p5sagit/Distar.git] / lib / Distar / helpers / ppport
CommitLineData
d7576b81 1#!/usr/bin/env perl
2use strict;
3use warnings;
4
5sub filter_file {
6 my ($old, $filter) = @_;
7 my $new = "$old.$$.new";
8 $filter ||= sub { shift };
9
10 open my $in, '<', $old,
11 or die "unable to read $old: $!";
12 open my $out, '>', $new
13 or die "unable to write $new: $!";
14
15 while (<$in>) {
16 print $out $filter->($_);
17 }
18 close $in;
19 close $out;
20 rename $new, $old
21 or die "Unable to update $old: $!";
22}
23
24my $command = shift;
25my $ppport = shift;
26
27if ($command eq 'update') {
28 if (!eval { require Devel::PPPort }) {
29 print STDERR "Devel::PPPort not installed, cannot update!\n";
30 exit 1;
31 }
32
33 require HTTP::Tiny;
34 require version;
35 require JSON::PP;
36
37 my $local_ppport_version;
38 my $installed_ppport_version = Devel::PPPort->VERSION;
39 my $remote_ppport_version;
40
41 {
42 my $ua = HTTP::Tiny->new(verify_SSL => 1);
43 my $proto = eval { HTTP::Tiny->can_ssl } ? 'https' : 'http';
44 my $res = $ua->get("$proto://fastapi.metacpan.org/v1/module/Devel::PPPort");
45 if ($res->{success}) {
46 my $content = $res->{content};
47 my $data = JSON::PP::decode_json($content);
48 if (my $v = $data->{version}) {
49 $remote_ppport_version = version->new($v);
50 }
51 }
52 }
53
54 if ($remote_ppport_version) {
55 if ($remote_ppport_version > $installed_ppport_version) {
56 print STDERR "Updated version of Devel::PPPort ($remote_ppport_version) is available!\n";
57 print STDERR "Installed version is $installed_ppport_version.\n";
58 }
59 }
60 else {
61 print STDERR "Unable to check latest version of Devel::PPPort!\n";
62 }
63
64 if (-f $ppport and my $v = `"$^X" "$ppport" --version`) {
65 if ($v =~ /\AThis is .* (v?\d+(?:\.\d+)*)\.?\n?\z/) {
66 $local_ppport_version = version->new($1);
67 }
68 elsif ($v =~ /stripped/) {
69 print "Updating stripped $ppport to $installed_ppport_version.\n";
70 exec $^X, $ppport, '--unstrip';
71 }
72 }
73
74 if ($local_ppport_version > $installed_ppport_version) {
75 print STDERR "Refusing to downgrade $ppport $local_ppport_version using Devel::PPPort $installed_ppport_version.\n";
76 exit 1;
77 }
78 elsif ($local_ppport_version < $installed_ppport_version) {
79 print "Updating $ppport from $local_ppport_version to $installed_ppport_version.\n";
80 Devel::PPPort::WriteFile($ppport);
81 }
82 else {
83 print "$ppport ($local_ppport_version) is up to date.\n";
84 }
85}
86elsif ($command eq 'diff') {
87 exec $^X, $ppport, '--quiet', @ARGV;
88}
89elsif ($command eq 'check') {
90 my @args = @ARGV;
91 my $args = join ' ', map qq{"$_"}, @args;
92 my $output = `"$^X" "$ppport" --quiet $args`;
93 if ($output =~ /\S/) {
94 print STDERR "$ppport requires changes:\n";
95 print $output;
96 exit 1;
97 }
98}
99elsif ($command eq 'patch') {
100 my @args = @ARGV;
101 my @files = grep -f, @args;
102 my $out = system $^X, $ppport, '--copy=.pppatch', @args;
103 for my $file (@files) {
104 my $patched = "$file.pppatch";
105 if (-e $patched) {
106 rename $patched, $file;
107 }
108 }
109 exit $out;
110}
111elsif ($command eq 'strip') {
112 if (!-f $ppport) {
113 exit 0;
114 }
115
116 my @files = @ARGV;
117 my $have_ppport;
118 XS_FILES: for my $file (@files) {
119 open my $fh, '<', $file
120 or die "unable to read $file: $!";
121 while (<$fh>) {
122 if (m{^\s*#include "(?:\.\.?/)*\Q$ppport\E"}) {
123 $have_ppport = 1;
124 last XS_FILES;
125 }
126 }
127 close $fh;
128 }
129 if ($have_ppport) {
130 print "Stripping $ppport\n";
131
132 # break hardlinks
133 filter_file($ppport);
134
135 system $^X, $ppport, '--strip';
136 }
137 else {
138 print "Removing unused ppport.h";
139
140 filter_file('MANIFEST', sub {
141 my $line = shift;
142 $line =~ /\A\Q$ppport\E\s/ ? '' : $line;
143 });
144
145 unlink $ppport
146 or die "Unable to delete $ppport: $!";
147 }
148 exit 0;
149}
150else {
151 die "Invalid command!\n";
152}