File Coverage

blib/lib/DBIx/Class/Schema/Diff.pm
Criterion Covered Total %
statement 62 62 100.0
branch 11 12 91.6
condition 10 15 66.6
subroutine 14 14 100.0
pod 2 2 100.0
total 99 105 94.2


line stmt bran cond sub pod time code
1             package DBIx::Class::Schema::Diff;
2 5     5   631880 use strict;
  5         53  
  5         148  
3 5     5   29 use warnings;
  5         9  
  5         198  
4              
5             # ABSTRACT: Simple Diffing of DBIC Schemas
6              
7             our $VERSION = '1.10';
8              
9 5     5   2634 use Moo;
  5         46666  
  5         24  
10             with 'DBIx::Class::Schema::Diff::Role::Common';
11              
12 5     5   10509 use Types::Standard qw(:all);
  5         409478  
  5         61  
13 5     5   243795 use Module::Runtime;
  5         17  
  5         54  
14 5     5   2103 use Try::Tiny;
  5         4446  
  5         352  
15 5     5   41 use List::Util;
  5         13  
  5         410  
16 5     5   3045 use Hash::Layout 2.00;
  5         760013  
  5         180  
17 5     5   2306 use Array::Diff;
  5         54378  
  5         39  
18              
19 5     5   2694 use DBIx::Class::Schema::Diff::Schema;
  5         27  
  5         220  
20 5     5   2839 use DBIx::Class::Schema::Diff::Filter;
  5         24  
  5         4389  
21              
22             has '_schema_diff', required => 1, is => 'ro', isa => InstanceOf[
23             'DBIx::Class::Schema::Diff::Schema'
24             ], coerce => \&_coerce_schema_diff;
25              
26             has 'diff', is => 'ro', lazy => 1, default => sub {
27             (shift)->_schema_diff->diff
28             }, isa => Maybe[HashRef];
29              
30             has 'MatchLayout', is => 'ro', lazy => 1, default => sub {
31             my $self = shift;
32            
33             Hash::Layout->new({
34             default_key => '*',
35             default_value => 1,
36             levels => [
37             {
38             name => 'source',
39             delimiter => ':',
40             registered_keys => [$self->_schema_diff->all_source_names]
41             },{
42             name => 'type',
43             delimiter => '/',
44             registered_keys => [&_types_list]
45             },{
46             name => 'id',
47             }
48             ]
49             });
50              
51             }, init_arg => undef, isa => InstanceOf['Hash::Layout'];
52              
53              
54             around BUILDARGS => sub {
55             my ($orig, $self, @args) = @_;
56             my %opt = (ref($args[0]) eq 'HASH') ? %{ $args[0] } : @args; # <-- arg as hash or hashref
57            
58             return $opt{_schema_diff} ? $self->$orig(%opt) : $self->$orig( _schema_diff => \%opt );
59             };
60              
61              
62             sub filter {
63 76     76 1 88075 my ($self,@args) = @_;
64 76         351 my $params = $self->_coerce_filter_args(@args);
65            
66 76         96698 my $Filter = DBIx::Class::Schema::Diff::Filter->new( $params ) ;
67 76         3510 my $diff = $Filter->filter( $self->diff );
68            
69             # Make a second pass, using the actual matched paths to filter out
70             # the intermediate paths that didn't actually match anything:
71             # (update: unless this is an empty match, in which case we will just
72             # return the whole diff as-is)
73 76 100 100     1437 if($Filter->mode eq 'limit' && ! $Filter->empty_match) {
74 52 100       569 if(scalar(@{$Filter->matched_paths}) > 0) {
  52         256  
75             $params->{match} = $Filter->match->clone->reset->load( map {
76 284         5603 $Filter->match->path_to_composite_key(@$_)
77 51         244 } @{$Filter->matched_paths} );
  51         9082  
78 51         128035 $Filter = DBIx::Class::Schema::Diff::Filter->new( $params ) ;
79 51         2530 $diff = $Filter->filter( $diff );
80             }
81             else {
82             # If nothing was matched, in limit mode, the diff is undef:
83 1         8 $diff = undef;
84             }
85             }
86            
87 76         2339 return __PACKAGE__->new({
88             _schema_diff => $self->_schema_diff,
89             diff => $diff
90             });
91             }
92              
93             sub filter_out {
94 19     19 1 8566 my ($self,@args) = @_;
95 19         93 my $params = $self->_coerce_filter_args(@args);
96 19         54823 $params->{mode} = 'ignore';
97 19         93 return $self->filter( $params );
98             }
99              
100              
101             sub _coerce_filter_args {
102 95     95   266 my ($self,@args) = @_;
103            
104             # This is the cleanest solution for wildcards to match as expected, not requiring the
105             # user to append a trailing '*' since they don't have to when doing an exact match
106             @args = map {
107 95 100 66     325 my ($one,$two) = ($_ && ! ref($_)) ? split (/\:/,$_,2) : ();
  127         939  
108             (
109 127 50 33     990 $one && $two && $one ne '*' && ($one =~ /\*/)
110             && ($two eq 'columns' || $two eq 'relationships' || $two eq 'constraints')
111             ) ? $_.'*' : $_
112             } @args;
113            
114 95 100 66     775 my $params = (
115             scalar(@args) > 1
116             || ! ref($args[0])
117             || ref($args[0]) ne 'HASH'
118             ) ? { match => \@args } : $args[0];
119            
120 95 100       369 unless (exists $params->{match}) {
121 10         38 my $n = { match => $params };
122 10         31 my @othr = qw(events source_events);
123 10   66     80 exists $n->{match}{$_} and $n->{$_} = delete $n->{match}{$_} for (@othr);
124 10         25 $params = $n;
125             }
126              
127             return {
128             %$params,
129             match => $self->MatchLayout->coerce($params->{match})
130 95         2521 };
131             }
132              
133              
134             1;
135              
136              
137             __END__