X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=rt%2Fsbin%2Frt-dump-metadata.in;fp=rt%2Fsbin%2Frt-dump-metadata.in;h=f58371f5d835fd5580939e315e9987a5deabf57f;hb=6587f6ba7d047ddc1686c080090afe7d53365bd4;hp=0000000000000000000000000000000000000000;hpb=47153aae5c2fc00316654e7277fccd45f72ff611;p=freeside.git diff --git a/rt/sbin/rt-dump-metadata.in b/rt/sbin/rt-dump-metadata.in new file mode 100644 index 000000000..f58371f5d --- /dev/null +++ b/rt/sbin/rt-dump-metadata.in @@ -0,0 +1,251 @@ +#!@PERL@ -w +# BEGIN BPS TAGGED BLOCK {{{ +# +# COPYRIGHT: +# +# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +# +# +# (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 }}} +use strict; + +# As we specify that XML is UTF-8 and we output it to STDOUT, we must be sure +# it is UTF-8 so further XMLin will not break +binmode( STDOUT, ":utf8" ); + +# fix lib paths, some may be relative +BEGIN { + require File::Spec; + my @libs = ( "@RT_LIB_PATH@", "@LOCAL_LIB_PATH@" ); + my $bin_path; + + for my $lib (@libs) { + unless ( File::Spec->file_name_is_absolute($lib) ) { + unless ($bin_path) { + if ( File::Spec->file_name_is_absolute(__FILE__) ) { + $bin_path = ( File::Spec->splitpath(__FILE__) )[1]; + } else { + require FindBin; + no warnings "once"; + $bin_path = $FindBin::Bin; + } + } + $lib = File::Spec->catfile( $bin_path, File::Spec->updir, $lib ); + } + unshift @INC, $lib; + } + +} + +use Getopt::Long; +my %opt; +GetOptions( \%opt, "help|h" ); + +if ( $opt{help} ) { + require Pod::Usage; + Pod::Usage::pod2usage( { verbose => 2 } ); + exit; +} + +require RT; +require XML::Simple; + +RT::LoadConfig(); +RT::Init(); + +my $LocalOnly = @ARGV ? shift(@ARGV) : 1; + +my %RV; +my %Ignore = ( + All => [ + qw( + id Created Creator LastUpdated LastUpdatedBy + ) + ], + Templates => [ + qw( + TranslationOf + ) + ], +); + +my $SystemUserId = RT->SystemUser->Id; +my @classes = qw( + Users Groups Queues ScripActions ScripConditions + Templates Scrips ACL CustomFields + ); +foreach my $class (@classes) { + require "RT/$class.pm"; + my $objects = "RT::$class"->new( RT->SystemUser ); + $objects->{find_disabled_rows} = 1; + $objects->UnLimit; + + if ( $class eq 'CustomFields' ) { + $objects->OrderByCols( + { FIELD => 'LookupType' }, + { FIELD => 'SortOrder' }, + { FIELD => 'Id' }, + ); + } else { + $objects->OrderBy( FIELD => 'Id' ); + } + + if ($LocalOnly) { + next if $class eq 'ACL'; # XXX - would go into infinite loop - XXX + $objects->Limit( + FIELD => 'LastUpdatedBy', + OPERATOR => '!=', + VALUE => $SystemUserId + ) unless $class eq 'Groups'; + $objects->Limit( + FIELD => 'Id', + OPERATOR => '!=', + VALUE => $SystemUserId + ) if $class eq 'Users'; + $objects->Limit( + FIELD => 'Domain', + OPERATOR => '=', + VALUE => 'UserDefined' + ) if $class eq 'Groups'; + } + + my %fields; + while ( my $obj = $objects->Next ) { + next + if $obj->can('LastUpdatedBy') + and $obj->LastUpdatedBy == $SystemUserId; + + if ( !%fields ) { + %fields = map { $_ => 1 } keys %{ $obj->_ClassAccessible }; + delete @fields{ @{ $Ignore{$class} ||= [] }, + @{ $Ignore{All} ||= [] }, }; + } + + my $rv; + + # next if $obj-> # skip default names + foreach my $field ( sort keys %fields ) { + my $value = $obj->__Value($field); + $rv->{$field} = $value if ( defined($value) && length($value) ); + } + delete $rv->{Disabled} unless $rv->{Disabled}; + + foreach my $record ( map { /ACL/ ? 'ACE' : substr( $_, 0, -1 ) } + @classes ) + { + foreach my $key ( map "$record$_", ( '', 'Id' ) ) { + next unless exists $rv->{$key}; + my $id = $rv->{$key} or next; + my $obj = "RT::$record"->new( RT->SystemUser ); + $obj->LoadByCols( Id => $id ) or next; + $rv->{$key} = $obj->__Value('Name') || 0; + } + } + + if ( $class eq 'Users' and defined $obj->Privileged ) { + $rv->{Privileged} = int( $obj->Privileged ); + } elsif ( $class eq 'CustomFields' ) { + my $values = $obj->Values; + while ( my $value = $values->Next ) { + push @{ $rv->{Values} }, { + map { ( $_ => $value->__Value($_) ) } + qw( + Name Description SortOrder + ), + }; + } + } + + if ( eval { require RT::Attributes; 1 } ) { + my $attributes = $obj->Attributes; + while ( my $attribute = $attributes->Next ) { + my $content = $attribute->Content; + $rv->{Attributes}{ $attribute->Name } = $content + if length($content); + } + } + + push @{ $RV{$class} }, $rv; + } +} + +print(<< "."); +no strict; use XML::Simple; *_ = XMLin(do { local \$/; readline(DATA) }, ForceArray => [qw( + @classes Values +)], NoAttr => 1, SuppressEmpty => ''); *\$_ = (\$_{\$_} || []) for keys \%_; 1; # vim: ft=xml +__DATA__ +. + +print XML::Simple::XMLout( + { map { ( $_ => ( $RV{$_} || [] ) ) } @classes }, + RootName => 'InitialData', + NoAttr => 1, + SuppressEmpty => '', + XMLDecl => '', +); + +__END__ + +=head1 NAME + +rt-dump-metadata - dump configuration metadata from an RT database + +=head1 SYNOPSIS + + rt-dump-metdata [ 0 ] + +=head1 DESCRIPTION + +C is a tool that dumps configuration metadata from the +Request Tracker database into XML format, suitable for feeding into +C. To dump and load a full RT database, you should generally +use the native database tools instead, as well as performing any necessary +steps from UPGRADING. + +When run without arguments, the metadata dump will only include 'local' +configuration changes, i.e. those done manually in the web interface. + +When run with the argument '0', the dump will include all configuration +metadata. + +This is NOT a tool for backing up an RT database. +