Fixes for 1.0007
[dbsrgits/DBM-Deep.git] / utils / upgrade_db.pl
CommitLineData
a423075f 1#!perl
f72b2dfb 2
3use 5.6.0;
4
5use strict;
6use warnings FATAL => 'all';
7
8use FindBin;
9use File::Spec ();
10use lib File::Spec->catdir( $FindBin::Bin, 'lib' );
11
12# This is for the latest version.
13use lib File::Spec->catdir( $FindBin::Bin, '..', 'lib' );
14
15use Getopt::Long qw( GetOptions );
f19b7e37 16use Pod::Usage 1.3;
f72b2dfb 17
18my %headerver_to_module = (
19 '0' => 'DBM::Deep::09830',
da1f1300 20 '2' => 'DBM::Deep::10002',
21 '3' => 'DBM::Deep',
f72b2dfb 22);
23
24my %is_dev = (
25 '1' => 1,
26);
27
28my %opts = (
29 man => 0,
30 help => 0,
f19b7e37 31 version => '1.0007',
da1f1300 32 autobless => 1,
f72b2dfb 33);
34GetOptions( \%opts,
35 'input=s', 'output=s', 'version:s', 'autobless:i',
36 'help|?', 'man',
37) || pod2man(2);
38pod2usage(1) if $opts{help};
39pod2usage(-exitstatus => 0, -verbose => 2) if $opts{man};
40
41pod2usage(-msg => "Missing required parameters.", verbose => 1)
42 unless $opts{input} && $opts{output};
43
44if ( $opts{input} eq $opts{output} ) {
45 _exit( "Cannot use the same filename for both input and output." );
46}
47
48unless ( -f $opts{input} ) {
49 _exit( "'$opts{input}' is not a file." );
50}
51
52my %db;
53{
54 my $ver = _read_file_header( $opts{input} );
55 if ( $is_dev{ $ver } ) {
56 _exit( "'$opts{input}' is a dev release and not supported." );
57 }
58
59 my $mod = $headerver_to_module{ $ver };
60 eval "use $mod;";
2568ec79 61 if ( $@ ) {
62 _exit( "Cannot load '$mod' to read header version '$ver':\n\t$@" );
63 }
f72b2dfb 64 $db{input} = $mod->new({
65 file => $opts{input},
66 locking => 1,
67 autobless => $opts{autobless},
68 });
69 $db{input}->lock;
70}
71
72{
73 my $ver = $opts{version};
f19b7e37 74 if ( $ver =~ /^1\.000[3-7]/) {
75 $ver = 3;
f72b2dfb 76 }
c192d0f5 77 elsif ( $ver =~ /^1\.000?[0-2]?/) {
f72b2dfb 78 $ver = 2;
79 }
f19b7e37 80 elsif ( $ver =~ /^0\.99/) {
81 $ver = 1;
82 }
83 elsif ( $ver =~ /^0\.9[1-8]/ ) {
84 $ver = 0;
da1f1300 85 }
f72b2dfb 86 else {
87 _exit( "'$ver' is an unrecognized version." );
88 }
89
90 if ( $is_dev{ $ver } ) {
91 _exit( "-version '$opts{version}' is a dev release and not supported." );
92 }
93
94 # First thing is to destroy the file, in case it's an incompatible version.
95 unlink $opts{output};
96
97 my $mod = $headerver_to_module{ $ver };
98 eval "use $mod;";
2568ec79 99 if ( $@ ) {
100 _exit( "Cannot load '$mod' to read header version '$ver':\n\t$@" );
101 }
f72b2dfb 102 $db{output} = $mod->new({
103 file => $opts{output},
104 locking => 1,
105 autobless => $opts{autobless},
106 });
107 $db{output}->lock;
108}
109
110# Do the actual conversion. This is the code that compress uses.
111$db{input}->_copy_node( $db{output} );
112undef $db{output};
113
114################################################################################
115
116sub _read_file_header {
117 my ($file) = @_;
118
119 open my $fh, '<', $file
120 or _exit( "Cannot open '$file' for reading: $!" );
121
122 my $buffer = _read_buffer( $fh, 9 );
123 _exit( "'$file' is not a DBM::Deep file." )
124 unless length $buffer == 9;
125
126 my ($file_sig, $header_sig, $header_ver) = unpack( 'A4 A N', $buffer );
127
128 # SIG_FILE == 'DPDB'
129 _exit( "'$file' is not a DBM::Deep file." )
130 unless $file_sig eq 'DPDB';
131
132 # SIG_HEADER == 'h' - this means that this is a pre-1.0 file
133 return 0 unless ($header_sig eq 'h');
134
135 return $header_ver;
136}
137
138sub _read_buffer {
139 my ($fh, $len) = @_;
140 my $buffer;
141 read( $fh, $buffer, $len );
142 return $buffer;
143}
144
145sub _exit {
146 my ($msg) = @_;
147 pod2usage( -verbose => 0, -msg => $msg );
148}
149
150__END__
151
152=head1 NAME
153
154upgrade_db.pl
155
156=head1 SYNOPSIS
157
158 upgrade_db.pl -input <oldfile> -output <newfile>
159
160=head1 DESCRIPTION
161
162This will attempt to upgrade DB files from one version of DBM::Deep to
163another. The version of the input file is detected from the file header. The
164version of the output file defaults to the version of the distro in this file,
165but can be set, if desired.
166
167=head1 OPTIONS
168
169=over 4
170
171=item B<-input> (required)
172
173This is the name of original DB file.
174
175=item B<-output> (required)
176
177This is the name of target output DB file.
178
179=item B<-version>
180
181Optionally, you can specify the version of L<DBM::Deep> for the output file.
182This can either be an upgrade or a downgrade. The minimum version supported is
1830.91.
184
185If the version is the same as the input file, this acts like a compressed copy
186of the database.
187
188=item B<-autobless>
189
da1f1300 190In pre-1.0000 versions, autoblessing was an optional setting defaulting to
191false. Autobless in upgrade_db.pl defaults to true.
f72b2dfb 192
193=item B<-help>
194
195Prints a brief help message, then exits.
196
197=item B<-man>
198
199Prints a much longer message, then exits;
200
201=back
202
203=head1 CAVEATS
204
205The following are known issues with this converter.
206
207=over 4
208
209=item * Diskspace requirements
210
211This will require about twice the diskspace of the input file.
212
213=item * Feature support
214
215Not all versions support the same features. In particular, internal references
da1f1300 216were supported in 0.983, removed in 1.000, and re-added in 1.0003. There is no
f72b2dfb 217detection of this by upgrade_db.pl.
218
219=back
220
221=head1 MAINTAINER(S)
222
223Rob Kinyon, L<rkinyon@cpan.org>
224
225Originally written by Rob Kinyon, L<rkinyon@cpan.org>
226
227=head1 LICENSE
228
229Copyright (c) 2007 Rob Kinyon. All Rights Reserved.
230This is free software, you may use it and distribute it under the
231same terms as Perl itself.
232
233=cut