File Coverage

blib/lib/Vcdiff/Xdelta3.pm
Criterion Covered Total %
statement 51 56 91.0
branch 31 44 70.4
condition 6 18 33.3
subroutine 6 6 100.0
pod 0 2 0.0
total 94 126 74.6


line stmt bran cond sub pod time code
1             package Vcdiff::Xdelta3;
2              
3 2     2   61005 use strict;
  2         3  
  2         76  
4              
5 2     2   10 use Carp;
  2         4  
  2         152  
6              
7 2     2   2236 use Vcdiff;
  2         5371  
  2         2039  
8              
9             our $VERSION = '0.104';
10              
11             require XSLoader;
12             XSLoader::load('Vcdiff::Xdelta3', $VERSION);
13              
14              
15              
16             sub diff {
17 65     65 0 125000 my ($source, $input, $output) = @_;
18              
19 65         111 my ($source_fileno, $source_str, $input_fileno, $input_str, $output_fileno, $output_str);
20              
21 65         105 $source_fileno = $input_fileno = $output_fileno = -1;
22              
23 65 50       217 if (!defined $source) {
    100          
24 0         0 croak "diff needs source argument";
25             } elsif (ref $source eq 'GLOB') {
26 33         70 $source_fileno = fileno($source);
27 33 50 33     209 croak "source file handle is closed or invalid" if !defined $source_fileno || $source_fileno == -1;
28             } else {
29 32         41 $source_str = $source;
30             }
31              
32 65 50       196 if (!defined $input) {
    100          
33 0         0 croak "diff needs target argument";
34             } elsif (ref $input eq 'GLOB') {
35 32         57 $input_fileno = fileno($input);
36 32 50 33     166 croak "target file handle is closed or invalid" if !defined $input_fileno || $input_fileno == -1;
37             } else {
38 33         45 $input_str = $input;
39             }
40              
41 65 100       114 if (defined $output) {
42 32 50       95 croak "output argument to diff should be a file handle or undef"
43             if ref $output ne 'GLOB';
44              
45 32         48 $output_fileno = fileno($output);
46 32 50 33     155 croak "output file handle is closed or invalid" if !defined $output_fileno || $output_fileno == -1;
47             } else {
48 33         41 $output_str = '';
49             }
50              
51 65         84338 my $ret = _encode($source_fileno, $source_str, $input_fileno, $input_str, $output_fileno, $output_str);
52              
53 65         184 _check_ret($ret, 'diff');
54              
55 64 100       371 return $output_str if !defined $output;
56             }
57              
58              
59             sub patch {
60 64     64 0 6356 my ($source, $input, $output) = @_;
61              
62 64         92 my ($source_fileno, $source_str, $input_fileno, $input_str, $output_fileno, $output_str);
63              
64 64         257 $source_fileno = $input_fileno = $output_fileno = -1;
65              
66 64 50       207 if (!defined $source) {
    100          
67 0         0 croak "patch needs source argument";
68             } elsif (ref $source eq 'GLOB') {
69 32         50 $source_fileno = fileno($source);
70 32 50 33     166 croak "source file handle is closed or invalid" if !defined $source_fileno || $source_fileno == -1;
71             } else {
72 32         46 $source_str = $source;
73             }
74              
75 64 50       696 if (!defined $input) {
    100          
76 0         0 croak "patch needs delta argument";
77             } elsif (ref $input eq 'GLOB') {
78 32         59 $input_fileno = fileno($input);
79 32 50 33     307 croak "delta file handle is closed or invalid" if !defined $input_fileno || $input_fileno == -1;
80             } else {
81 32         36 $input_str = $input;
82             }
83              
84 64 100       119 if (defined $output) {
85 32 50       89 croak "output argument to patch should be a file handle or undef"
86             if ref $output ne 'GLOB';
87              
88 32         45 $output_fileno = fileno($output);
89 32 50 33     321 croak "output file handle is closed or invalid" if !defined $output_fileno || $output_fileno == -1;
90             } else {
91 32         34 $output_str = '';
92             }
93              
94 64         12669 my $ret = _decode($source_fileno, $source_str, $input_fileno, $input_str, $output_fileno, $output_str);
95              
96 64         333 _check_ret($ret, 'patch');
97              
98 64 100       2981 return $output_str if !defined $output;
99             }
100              
101              
102              
103             my $exception_map = {
104             1 => 'xd3_config_stream',
105             2 => 'unable to allocate memory for source.blksize',
106             3 => 'source is not lseek()able (must be a regular file, not a pipe/socket)',
107             4 => 'error reading from source',
108             5 => 'unable to allocate memory for ibuf',
109             6 => 'error reading from target/delta',
110             7 => 'error writing to output',
111             8 => 'xd3_close_stream',
112             };
113              
114             sub _check_ret {
115 129     129   179 my ($ret, $func) = @_;
116              
117 129 100       872 return unless $ret;
118              
119 1         5 my $exception = $exception_map->{$ret};
120              
121 1 50       235 croak "error in Vcdiff::Xdelta3::$func: $exception" if $exception;
122              
123 0           croak "unknown error in Vcdiff::Xdelta3::$func ($ret)";
124             }
125              
126              
127             1;
128              
129              
130              
131              
132             =head1 NAME
133              
134             Vcdiff::Xdelta3 - Xdelta3 backend for Vcdiff
135              
136             =head1 SYNOPSIS
137              
138             use Vcdiff::Xdelta3;
139              
140             my $delta = Vcdiff::Xdelta3::diff($source, $target);
141              
142             my $target2 = Vcdiff::Xdelta3::patch($source, $delta);
143              
144             ## $target2 eq $target
145              
146             This module is a backend to the L module and isn't usually used directly.
147              
148              
149             =head1 DESCRIPTION
150              
151             Xdelta3 is a delta encoding library by Joshua MacDonald. The Xdelta3 source code is embedded into this module and built as a shared object. The C command-line binary is not built.
152              
153              
154             =head1 PROS
155              
156             =over
157              
158             =item *
159              
160             Doesn't have arbitrary size limitations on source, target, or delta files.
161              
162             =item *
163              
164             Has a really neat feature that lets you merge VCDIFF deltas into a single delta. Unfortunately this module doesn't expose that yet.
165              
166             =back
167              
168              
169             =head1 CONS
170              
171             =over
172              
173             =item *
174              
175             GPL licensed
176              
177             =item *
178              
179             Build system is really weird. I didn't bother figuring out how to run Xdelta3's test-suite when installing the CPAN module which is unfortunate. Note that installing this module does still run the shared test-suite in L.
180              
181             =back
182              
183              
184             =head1 SEE ALSO
185              
186             L
187              
188             L
189              
190             L
191              
192              
193             =head1 AUTHOR
194              
195             Doug Hoyte, C<< >>
196              
197              
198             =head1 COPYRIGHT & LICENSE
199              
200             Copyright 2013 Doug Hoyte.
201              
202             This module includes xdelta3 which is copyright Joshua P. MacDonald. xdelta3 is licensed under the GNU GPL 2 which can be found in the inc/COPYING file of this distribution.
203              
204             Because of xdelta3's license, this module is licensed under the GNU GPL 2.