summaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorDylan William Hardison <dylan@hardison.net>2017-12-13 18:46:26 +0100
committerGitHub <noreply@github.com>2017-12-13 18:46:26 +0100
commit48fe3a1e0a4a833aa14e7f95136d0e4542959eb8 (patch)
tree18f2820200f651e087088ea0e870794ae25f5721 /scripts
parent988a42a2dc199716f5c9c6e371ffcf9493c68112 (diff)
downloadbugzilla-48fe3a1e0a4a833aa14e7f95136d0e4542959eb8.tar.gz
bugzilla-48fe3a1e0a4a833aa14e7f95136d0e4542959eb8.tar.xz
Bug 1424155 - Write scripts to import/export attachments to disk
Diffstat (limited to 'scripts')
-rw-r--r--scripts/attachment-data.pl133
1 files changed, 133 insertions, 0 deletions
diff --git a/scripts/attachment-data.pl b/scripts/attachment-data.pl
new file mode 100644
index 000000000..4a3a1b414
--- /dev/null
+++ b/scripts/attachment-data.pl
@@ -0,0 +1,133 @@
+#!/usr/bin/perl
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+use strict;
+use warnings;
+use 5.10.1;
+
+use File::Basename;
+use File::Spec;
+
+BEGIN {
+ require lib;
+ my $dir = File::Spec->rel2abs( File::Spec->catdir( dirname(__FILE__), '..' ) );
+ lib->import( $dir, File::Spec->catdir( $dir, 'lib' ), File::Spec->catdir( $dir, qw(local lib perl5) ) );
+}
+
+use Bugzilla;
+use Bugzilla::Constants;
+use Bugzilla::Attachment;
+use Bugzilla::Attachment::Archive;
+use Getopt::Long;
+use Pod::Usage;
+
+BEGIN { Bugzilla->extensions }
+
+# set Bugzilla usage mode to USAGE_MODE_CMDLINE
+Bugzilla->usage_mode(USAGE_MODE_CMDLINE);
+
+my ($help, $file);
+GetOptions(
+ 'help|h' => \$help,
+ 'file|f=s' => \$file,
+);
+pod2usage(1) if $help || !$file;
+
+my $archive = Bugzilla::Attachment::Archive->new(file => $file);
+my $cmd = shift @ARGV;
+
+if ($cmd eq 'export') {
+ while ( my $attach_id = <ARGV> ) {
+ chomp $attach_id;
+ my $attachment = Bugzilla::Attachment->new($attach_id);
+ unless ($attachment) {
+ warn "No attachment: $attach_id\n";
+ next;
+ }
+ warn "writing $attach_id\n";
+ $archive->write_attachment($attachment);
+ }
+ $archive->write_checksum;
+}
+elsif ($cmd eq 'import') {
+ while ( my $mem = $archive->read_member ) {
+ warn "read $mem->{attach_id}\n";
+
+ my $attachment = Bugzilla::Attachment->new($mem->{attach_id});
+ next unless $mem->{data_len};
+ next unless check_attachment($attachment, $mem->{bug_id}, $mem->{data_len});
+
+ Bugzilla::Attachment::current_storage()->store( $attachment->id, $mem->{data} );
+ }
+}
+elsif ($cmd eq 'check') {
+ while ( my $mem = $archive->read_member() ) {
+ warn "checking $mem->{attach_id}\n";
+ my $attachment = Bugzilla::Attachment->new($mem->{attach_id});
+ next unless $mem->{data_len};
+ die "bad attachment\n" unless check_attachment($attachment, $mem->{bug_id}, $mem->{data_len});
+ }
+}
+elsif ($cmd eq 'remove') {
+ my %remove_ok;
+ while ( my $mem = $archive->read_member ) {
+ warn "checking $mem->{attach_id}\n";
+
+ my $attachment = Bugzilla::Attachment->new($mem->{attach_id});
+ die "bad attachment\n" unless check_attachment($attachment, $mem->{bug_id}, $mem->{data_len});
+ $remove_ok{$mem->{attach_id}} = 1;
+ }
+ while ( my $attach_id = <ARGV> ) {
+ chomp $attach_id;
+ if ($remove_ok{$attach_id}) {
+ warn "removing $attach_id\n";
+ Bugzilla::Attachment::current_storage()->remove( $attach_id );
+ }
+ else {
+ warn "Unable to remove $attach_id, as it did not occur in the archive.\n";
+ }
+ }
+}
+
+sub check_attachment {
+ my ($attachment, $bug_id, $data_len) = @_;
+
+ unless ($attachment) {
+ warn "No attachment found. Skipping record.\n";
+ return 0;
+ }
+ unless ( $attachment->bug_id == $bug_id ) {
+ warn 'Wrong bug id (should be ' . $attachment->bug_id . ")\n";
+ return 0;
+ }
+ unless ( $attachment->datasize == $data_len ) {
+ warn 'Wrong size (should be ' . $attachment->datasize . ")\n";
+ return 0;
+ }
+
+ return 1;
+}
+
+
+__DATA__
+
+=head1 NAME
+
+attachment-data.pl - import, export, and purge attachment data
+
+=head1 SYNOPSIS
+
+ ./scripts/attachment-data.pl export -f attachments.dat < attachment-ids.txt
+ ./scripts/attachment-data.pl remove -f attachments.dat < attachment-ids.txt
+ ./scripts/attachment-data.pl import -f attachments.dat
+
+
+=head1 SEE ALSO
+
+L<./scripts/attachment-export.pl>
+
+