[Rt-commit] rt branch, 4.4/serialize-json-initialdata, created. rt-4.4.1-323-gc3ba1a4

Shawn Moore shawn at bestpractical.com
Tue Mar 14 15:34:51 EDT 2017


The branch, 4.4/serialize-json-initialdata has been created
        at  c3ba1a4c872fcb6787cc7450a08a1d8f5652edd6 (commit)

- Log -----------------------------------------------------------------
commit 2bf6e1f55edf050cda68131431f3f0d38f9f9484
Author: Shawn M Moore <shawn at bestpractical.com>
Date:   Tue Mar 14 19:15:08 2017 +0000

    Migrate Storable-related concerns from Serializer to File

diff --git a/lib/RT/Migrate/Serializer.pm b/lib/RT/Migrate/Serializer.pm
index c979456..db1440c 100644
--- a/lib/RT/Migrate/Serializer.pm
+++ b/lib/RT/Migrate/Serializer.pm
@@ -53,7 +53,6 @@ use warnings;
 
 use base 'RT::DependencyWalker';
 
-use Storable qw//;
 sub cmp_version($$) { RT::Handle::cmp_version($_[0],$_[1]) };
 use RT::Migrate::Incremental;
 use RT::Migrate::Serializer::IncrementalRecord;
@@ -299,11 +298,8 @@ sub PushBasics {
 sub InitStream {
     my $self = shift;
 
-    # Write the initial metadata
     my $meta = $self->Metadata;
-    $! = 0;
-    Storable::nstore_fd( $meta, $self->{Filehandle} );
-    die "Failed to write metadata: $!" if $!;
+    $self->WriteMetadata($meta);
 
     return unless cmp_version($meta->{VersionFrom}, $meta->{Version}) < 0;
 
@@ -452,9 +448,7 @@ sub Visit {
         if ($self->{Transform}{"+$class"}) {
             my @extra = $self->{Transform}{"+$class"}->(\%data,\$class);
             for my $e (@extra) {
-                $! = 0;
-                Storable::nstore_fd($e, $self->{Filehandle});
-                die "Failed to write: $!" if $!;
+                $self->WriteRecord($e);
                 $self->{ObjectCount}{$e->[0]}++;
             }
         }
@@ -480,11 +474,7 @@ sub Visit {
         );
     }
 
-    # Write it out; nstore_fd doesn't trap failures to write, so we have
-    # to; by clearing $! and checking it afterwards.
-    $! = 0;
-    Storable::nstore_fd(\@store, $self->{Filehandle});
-    die "Failed to write: $!" if $!;
+    $self->WriteRecord(\@store);
 
     $self->{ObjectCount}{$store[0]}++;
 }
diff --git a/lib/RT/Migrate/Serializer/File.pm b/lib/RT/Migrate/Serializer/File.pm
index f5f503e..781fa98 100644
--- a/lib/RT/Migrate/Serializer/File.pm
+++ b/lib/RT/Migrate/Serializer/File.pm
@@ -51,6 +51,8 @@ package RT::Migrate::Serializer::File;
 use strict;
 use warnings;
 
+use Storable qw//;
+
 use base 'RT::Migrate::Serializer';
 
 sub Init {
@@ -168,4 +170,22 @@ sub RotateFile {
     $self->OpenFile;
 }
 
+sub WriteMetadata {
+    my $self = shift;
+    my $meta = shift;
+    Storable::nstore_fd( $meta, $self->{Filehandle} );
+    die "Failed to write metadata: $!" if $!;
+}
+
+sub WriteRecord {
+    my $self = shift;
+    my $record = shift;
+
+    # Write it out; nstore_fd doesn't trap failures to write, so we have
+    # to; by clearing $! and checking it afterwards.
+    $! = 0;
+    Storable::nstore_fd($record, $self->{Filehandle});
+    die "Failed to write: $!" if $!;
+}
+
 1;

commit c3ba1a4c872fcb6787cc7450a08a1d8f5652edd6
Author: Shawn M Moore <shawn at bestpractical.com>
Date:   Tue Mar 14 19:33:38 2017 +0000

    First pass at initialdata.json serializer export format

diff --git a/lib/RT/Migrate/Serializer/JSON.pm b/lib/RT/Migrate/Serializer/JSON.pm
new file mode 100644
index 0000000..0bf16d5
--- /dev/null
+++ b/lib/RT/Migrate/Serializer/JSON.pm
@@ -0,0 +1,176 @@
+# BEGIN BPS TAGGED BLOCK {{{
+#
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2017 Best Practical Solutions, LLC
+#                                          <sales at bestpractical.com>
+#
+# (Except where explicitly superseded by other copyright notices)
+#
+#
+# LICENSE:
+#
+# This work is made available to you under the terms of Version 2 of
+# the GNU General Public License. A copy of that license should have
+# been provided with this software, but in any event can be snarfed
+# from www.gnu.org.
+#
+# This work is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301 or visit their web page on the internet at
+# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
+#
+#
+# CONTRIBUTION SUBMISSION POLICY:
+#
+# (The following paragraph is not intended to limit the rights granted
+# to you to modify and distribute this software under the terms of
+# the GNU General Public License and is only of importance to you if
+# you choose to contribute your changes and enhancements to the
+# community by submitting them to Best Practical Solutions, LLC.)
+#
+# By intentionally submitting any modifications, corrections or
+# derivatives to this work, or any other work intended for use with
+# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+# you are the copyright holder for those contributions and you grant
+# Best Practical Solutions,  LLC a nonexclusive, worldwide, irrevocable,
+# royalty-free, perpetual, license to use, copy, create derivative
+# works based on those contributions, and sublicense and distribute
+# those contributions and any derivatives thereof.
+#
+# END BPS TAGGED BLOCK }}}
+
+package RT::Migrate::Serializer::JSON;
+
+use strict;
+use warnings;
+use JSON qw//;
+
+use base 'RT::Migrate::Serializer';
+
+sub Init {
+    my $self = shift;
+
+    my %args = (
+        Directory   => undef,
+        Force       => undef,
+
+        @_,
+    );
+
+    # Set up the output directory we'll be writing to
+    my ($y,$m,$d) = (localtime)[5,4,3];
+    $args{Directory} = $RT::Organization .
+        sprintf(":%d-%02d-%02d",$y+1900,$m+1,$d)
+        unless defined $args{Directory};
+    system("rm", "-rf", $args{Directory}) if $args{Force};
+    die "Output directory $args{Directory} already exists"
+        if -d $args{Directory};
+    mkdir $args{Directory}
+        or die "Can't create output directory $args{Directory}: $!\n";
+    $self->{Directory} = delete $args{Directory};
+
+    $self->{Records} = {};
+
+    $self->SUPER::Init(@_);
+}
+
+sub Export {
+    my $self = shift;
+
+    # Write the initial metadata
+    $self->InitStream;
+
+    # Walk the objects
+    $self->Walk( @_ );
+
+    # Set up our output file
+    $self->OpenFile;
+
+    # Write out the initialdata
+    $self->WriteFile;
+
+    # Close everything back up
+    $self->CloseFile;
+
+    return $self->ObjectCount;
+}
+
+sub Files {
+    my $self = shift;
+    return ($self->Filename);
+}
+
+sub Filename {
+    my $self = shift;
+    return sprintf(
+        "%s/initialdata.json",
+        $self->{Directory},
+    );
+}
+
+sub Directory {
+    my $self = shift;
+    return $self->{Directory};
+}
+
+sub JSON {
+    my $self = shift;
+    return $self->{JSON} ||= JSON->new->pretty;
+}
+
+sub OpenFile {
+    my $self = shift;
+    open($self->{Filehandle}, ">", $self->Filename)
+        or die "Can't write to file @{[$self->Filename]}: $!";
+}
+
+sub CloseFile {
+    my $self = shift;
+    close($self->{Filehandle})
+        or die "Can't close @{[$self->Filename]}: $!";
+}
+
+sub WriteMetadata {
+    my $self = shift;
+    my $meta = shift;
+
+    # no need to write metadata
+    return;
+}
+
+sub WriteRecord {
+    my $self = shift;
+    my $record = shift;
+
+    my $type = $record->[0];
+    $type =~ s/^RT:://;
+
+    push @{ $self->{Records}{ $type } }, $record->[2];
+}
+
+sub WriteFile {
+    my $self = shift;
+    my %output;
+
+    for my $type (keys %{ $self->{Records} }) {
+        for my $record (@{ $self->{Records}{$type} }) {
+            for my $key (keys %$record) {
+                if (ref($record->{$key}) eq 'SCALAR') {
+                    delete $record->{$key};
+                }
+            }
+            push @{ $output{$type} }, $record;
+        }
+    }
+
+    print { $self->{Filehandle} } $self->JSON->encode(\%output);
+}
+
+1;
diff --git a/sbin/rt-serializer.in b/sbin/rt-serializer.in
index dd55710..29c1ca2 100644
--- a/sbin/rt-serializer.in
+++ b/sbin/rt-serializer.in
@@ -96,6 +96,7 @@ GetOptions(
     "directory|d=s",
     "force|f!",
     "size|s=i",
+    "format=s",
 
     "users!",
     "groups!",
@@ -157,7 +158,11 @@ if (-t STDOUT and not $OPT{verbose} and not $OPT{quiet}) {
 $args{Verbose} = 0 if $OPT{quiet};
 
 
-$walker = RT::Migrate::Serializer::File->new( %args );
+my $walker_class = "RT::Migrate::Serializer::" . ($OPT{format} || 'File');
+$walker_class->require
+    or die "Failed to load $walker_class for format $OPT{format}: $@";
+
+$walker = $walker_class->new( %args );
 
 my $log = RT::Migrate::setup_logging( $walker->{Directory} => 'serializer.log' );
 print "Logging warnings and errors to $log\n" if $log;
@@ -290,6 +295,12 @@ size, in megabytes.  Note that this is the threshold after which it
 rotates to writing a new file, and is as such the I<lower bound> on the
 size of each output file.
 
+=item B<--format> I<format>
+
+By default, C<rt-serializer> writes Storable-encoded files
+(C<--format File>). You can choose to export an F<initialdata.json>
+instead by passing C<--format JSON>.
+
 =item B<--no-users>
 
 By default, all privileged users are serialized; passing C<--no-users>

-----------------------------------------------------------------------


More information about the rt-commit mailing list