line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package CPANPLUS::Shell::Default::Plugins::Diff; |
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
587
|
use strict; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
39
|
|
4
|
1
|
|
|
1
|
|
12712
|
use Text::Diff (); |
|
1
|
|
|
|
|
23905
|
|
|
1
|
|
|
|
|
26
|
|
5
|
1
|
|
|
1
|
|
1049
|
use Data::Dumper; |
|
1
|
|
|
|
|
8409
|
|
|
1
|
|
|
|
|
189
|
|
6
|
1
|
|
|
1
|
|
11
|
use File::Basename; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
63
|
|
7
|
1
|
|
|
1
|
|
985
|
use Params::Check qw[check]; |
|
1
|
|
|
|
|
5475
|
|
|
1
|
|
|
|
|
98
|
|
8
|
1
|
|
|
1
|
|
1009
|
use CPANPLUS::Error qw[error msg]; |
|
1
|
|
|
|
|
32151
|
|
|
1
|
|
|
|
|
86
|
|
9
|
1
|
|
|
1
|
|
12
|
use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
6
|
|
10
|
|
|
|
|
|
|
|
11
|
1
|
|
|
1
|
|
497
|
use vars qw[$VERSION]; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
1098
|
|
12
|
|
|
|
|
|
|
$VERSION = '0.01'; |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
local $Data::Dumper::Indent = 1; |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
=head1 NAME |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
CPANPLUS::Shell::Default::Plugins::Diff |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
=head1 SYNOPSIS |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
### diff version 1.3 and 1.4 |
23
|
|
|
|
|
|
|
CPAN Terminal> /diff DBI 1.3 1.4 |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
### diff version 1.3 against the most recent on CPAN |
26
|
|
|
|
|
|
|
CPAN Terminal> /diff DBI 1.3 |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
### diff your installed version against the most |
29
|
|
|
|
|
|
|
### recent on CPAN |
30
|
|
|
|
|
|
|
CPAN Terminal> /diff DBI |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
### use context style diff |
33
|
|
|
|
|
|
|
### other options are: Unified, OldStyle |
34
|
|
|
|
|
|
|
CPAN Terminal> /diff DBI --style=Context |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
### list help from withing the shell: |
37
|
|
|
|
|
|
|
CPAN Terminal> /? diff |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
=head1 DESCRIPTION |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
This plugin allows you to diff 2 versions of modules and see what |
42
|
|
|
|
|
|
|
code changes have taken place. |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
=cut |
45
|
|
|
|
|
|
|
|
46
|
1
|
|
|
1
|
0
|
744
|
sub plugins { return ( diff => 'diff' ) } |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
sub diff { |
49
|
0
|
|
|
0
|
0
|
|
my $class = shift; |
50
|
0
|
|
|
|
|
|
my $shell = shift; |
51
|
0
|
|
|
|
|
|
my $cb = shift; |
52
|
0
|
|
|
|
|
|
my $cmd = shift; |
53
|
0
|
|
0
|
|
|
|
my $input = shift || ''; |
54
|
0
|
|
0
|
|
|
|
my $opts = shift || {}; |
55
|
0
|
|
|
|
|
|
my $verbose = $cb->configure_object->get_conf('verbose'); |
56
|
|
|
|
|
|
|
|
57
|
0
|
|
|
|
|
|
my($name, $from, $to) = split /\s+/, $input; |
58
|
|
|
|
|
|
|
|
59
|
0
|
|
|
|
|
|
my $style; |
60
|
0
|
|
|
|
|
|
{ my $tmpl = { |
|
0
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
style => { default => "Unified", store => \$style, |
62
|
|
|
|
|
|
|
allow => [qw|Unified Context OldStyle|] }, |
63
|
|
|
|
|
|
|
}; |
64
|
|
|
|
|
|
|
|
65
|
0
|
0
|
|
|
|
|
check( $tmpl, $opts, 1 ) or return; |
66
|
|
|
|
|
|
|
} |
67
|
|
|
|
|
|
|
|
68
|
0
|
0
|
|
|
|
|
error(loc("No module supplied")), return unless $name; |
69
|
|
|
|
|
|
|
|
70
|
0
|
0
|
|
|
|
|
my $mod = $cb->parse_module( module => $name ) or ( |
71
|
|
|
|
|
|
|
error(loc("Could not parse module name '%1'"), $name), |
72
|
|
|
|
|
|
|
return |
73
|
|
|
|
|
|
|
); |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
### no 'from'? |
76
|
0
|
0
|
0
|
|
|
|
unless( defined $from && length $from ) { |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
### not installed? |
79
|
0
|
0
|
|
|
|
|
unless( $mod->installed_file ) { |
80
|
0
|
|
|
|
|
|
error(loc("'%1' is not installed, need %2 version", $name, 'FROM')); |
81
|
0
|
|
|
|
|
|
return; |
82
|
|
|
|
|
|
|
} |
83
|
|
|
|
|
|
|
|
84
|
0
|
|
|
|
|
|
$from = $mod->installed_version; |
85
|
|
|
|
|
|
|
} |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
### no 'to'? |
88
|
0
|
0
|
0
|
|
|
|
$to = $mod->version unless defined $to && length $to; |
89
|
|
|
|
|
|
|
|
90
|
0
|
|
|
|
|
|
msg(loc("Diffing '%1' version '%2' against version '%3'", |
91
|
|
|
|
|
|
|
$name, $from, $to), $verbose); |
92
|
|
|
|
|
|
|
|
93
|
0
|
0
|
|
|
|
|
if( "$to" eq "$from" ) { |
94
|
0
|
|
|
|
|
|
error(loc("TO ('%1') and FROM ('%2') are identical", $to, $from)); |
95
|
0
|
|
|
|
|
|
return; |
96
|
|
|
|
|
|
|
} |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
### fetch them, extract, and store |
99
|
0
|
|
|
|
|
|
my $href = {}; |
100
|
0
|
|
|
|
|
|
{ my %map = ( FROM => $from, TO => $to ); |
|
0
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
|
102
|
0
|
|
|
|
|
|
while ( my($txt,$ver) = each %map ) { |
103
|
0
|
|
|
|
|
|
my $obj = $cb->parse_module( |
104
|
|
|
|
|
|
|
module => $mod->package_name . '-' . $ver ); |
105
|
0
|
0
|
|
|
|
|
error(loc("Couldn't create '%1' object'",'FROM')), return |
106
|
|
|
|
|
|
|
unless $obj; |
107
|
|
|
|
|
|
|
|
108
|
0
|
0
|
|
|
|
|
$obj->fetch |
109
|
|
|
|
|
|
|
or error(loc("Could not fetch '%1'",$txt)), return; |
110
|
0
|
0
|
|
|
|
|
$obj->extract |
111
|
|
|
|
|
|
|
or error(loc("Could not extract '%1'",$txt)), return; |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
|
114
|
0
|
|
|
|
|
|
$href->{$txt} = $obj; |
115
|
|
|
|
|
|
|
} |
116
|
|
|
|
|
|
|
} |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
### make 2 hashes of the files in each tree... |
120
|
|
|
|
|
|
|
### be sure to strip the leading extract dir, as that will |
121
|
|
|
|
|
|
|
### cause mismatches further down. IE: |
122
|
|
|
|
|
|
|
### foo-bar-0.1/README vs foo-bar-0.2/README |
123
|
|
|
|
|
|
|
### the 'foo-bar' part is also present in the 'extract' status |
124
|
|
|
|
|
|
|
### so one of the 2 has to be removed either way. |
125
|
|
|
|
|
|
|
### use index 1 rather than 0, as 0 will usually hold just a dirname |
126
|
|
|
|
|
|
|
### which will mess up dirname() and return undef... |
127
|
|
|
|
|
|
|
|
128
|
0
|
|
|
|
|
|
my $fstatus = $href->{FROM}->status; |
129
|
0
|
|
|
|
|
|
my $fbase = dirname( $fstatus->files->[1] ); |
130
|
|
|
|
|
|
|
|
131
|
0
|
|
|
|
|
|
my $tstatus = $href->{ TO }->status; |
132
|
0
|
|
|
|
|
|
my $tbase = dirname( $tstatus->files->[1] ); |
133
|
|
|
|
|
|
|
|
134
|
0
|
|
|
|
|
|
my %old = map { s/^$fbase//; $_ => $_ } @{ $fstatus->files }; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
135
|
0
|
|
|
|
|
|
my %new = map { s/^$tbase//; $_ => $_ } @{ $tstatus->files }; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
|
137
|
0
|
|
|
|
|
|
my $diff; |
138
|
|
|
|
|
|
|
|
139
|
0
|
|
|
|
|
|
for my $file ( sort keys %old ) { |
140
|
|
|
|
|
|
|
|
141
|
0
|
|
|
|
|
|
my $exists = delete $new{$file}; |
142
|
0
|
|
|
|
|
|
my $from_file = File::Spec->catfile( $fstatus->extract, $file ); |
143
|
0
|
|
|
|
|
|
my $to_file = File::Spec->catfile( $tstatus->extract, $file ); |
144
|
|
|
|
|
|
|
|
145
|
0
|
0
|
|
|
|
|
next if -d $from_file; |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
### if the file doesn't exist in the target 'to' dir, |
148
|
|
|
|
|
|
|
### pass a reference to 'undef' |
149
|
0
|
0
|
|
|
|
|
$diff .= Text::Diff::diff( |
|
|
0
|
|
|
|
|
|
150
|
|
|
|
|
|
|
$from_file, |
151
|
|
|
|
|
|
|
$exists ? $to_file : \undef, |
152
|
|
|
|
|
|
|
{ FILENAME_A => $from_file, |
153
|
|
|
|
|
|
|
FILENAME_B => $exists ? $to_file : '/dev/null', |
154
|
|
|
|
|
|
|
STYLE => $style, |
155
|
|
|
|
|
|
|
} |
156
|
|
|
|
|
|
|
); |
157
|
|
|
|
|
|
|
} |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
### any files left in 'new' are new files, treat 'm as such |
160
|
0
|
|
|
|
|
|
for my $file ( sort keys %new ) { |
161
|
0
|
|
|
|
|
|
my $to_file = File::Spec->catfile( $tstatus->extract, $file ); |
162
|
|
|
|
|
|
|
|
163
|
0
|
0
|
|
|
|
|
next if -d $to_file; |
164
|
|
|
|
|
|
|
|
165
|
0
|
|
|
|
|
|
$diff .= Text::Diff::diff( |
166
|
|
|
|
|
|
|
\undef, |
167
|
|
|
|
|
|
|
$to_file, |
168
|
|
|
|
|
|
|
{ FILENAME_A => '/dev/null', |
169
|
|
|
|
|
|
|
FILENAME_B => $file, |
170
|
|
|
|
|
|
|
STYLE => $style, |
171
|
|
|
|
|
|
|
} |
172
|
|
|
|
|
|
|
); |
173
|
|
|
|
|
|
|
} |
174
|
|
|
|
|
|
|
|
175
|
0
|
0
|
|
|
|
|
$shell->_pager_open if $diff =~ tr/\n/\n/ > $shell->_term_rowcount; |
176
|
0
|
|
|
|
|
|
print $diff; |
177
|
0
|
|
|
|
|
|
$shell->_pager_close; |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
} |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
sub diff_help { |
182
|
0
|
|
|
0
|
0
|
|
return loc( |
183
|
|
|
|
|
|
|
" /diff Module [[FROM] TO] [--style=STYLE]\n" . |
184
|
|
|
|
|
|
|
" Diffs the contents of 2 releases\n". |
185
|
|
|
|
|
|
|
" if TO is not supplied, the most recent release is used\n". |
186
|
|
|
|
|
|
|
" if FROM is not supplied, the currently installed version,\n" . |
187
|
|
|
|
|
|
|
" if any, is used\n". |
188
|
|
|
|
|
|
|
" Valid values for STYLE are: 'Unified', 'Context', 'OldStyle'\n" |
189
|
|
|
|
|
|
|
); |
190
|
|
|
|
|
|
|
} |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
1; |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
=pod |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
=head1 AUTHOR |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
This module by |
200
|
|
|
|
|
|
|
Jos Boumans Ekane@cpan.orgE. |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
=head1 COPYRIGHT |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
Copyright (c) 2005, Jos Boumans Ekane@cpan.orgE. |
205
|
|
|
|
|
|
|
All rights reserved. |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
This library is free software; |
208
|
|
|
|
|
|
|
you may redistribute and/or modify it under the same |
209
|
|
|
|
|
|
|
terms as Perl itself. |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
=head1 SEE ALSO |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
L, L, |
214
|
|
|
|
|
|
|
L |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
=cut |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
# Local variables: |
219
|
|
|
|
|
|
|
# c-indentation-style: bsd |
220
|
|
|
|
|
|
|
# c-basic-offset: 4 |
221
|
|
|
|
|
|
|
# indent-tabs-mode: nil |
222
|
|
|
|
|
|
|
# End: |
223
|
|
|
|
|
|
|
# vim: expandtab shiftwidth=4: |