| 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: |