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