This file is indexed.

/usr/share/perl5/Pinto/Difference.pm is in pinto 0.97+dfsg-2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
# ABSTRACT: Compute difference between two revisions

package Pinto::Difference;

use Moose;
use MooseX::StrictConstructor;
use MooseX::Types::Moose qw(ArrayRef Bool);
use MooseX::MarkAsMethods ( autoclean => 1 );

use Pinto::Util qw(itis);

use overload ( q{""} => 'to_string' );

#------------------------------------------------------------------------------

our $VERSION = '0.097'; # VERSION

#------------------------------------------------------------------------------

has left => (
    is       => 'ro',
    isa      => 'Pinto::Schema::Result::Revision',
    required => 1,
);

has right => (
    is       => 'ro',
    isa      => 'Pinto::Schema::Result::Revision',
    required => 1,
);

has diffs => (
    traits   => [qw(Array)],
    handles  => { diffs => 'elements' },
    isa      => ArrayRef ['Pinto::DifferenceEntry'],
    builder  => '_build_diffs',
    init_arg => undef,
    lazy     => 1,
);

has additions => (
    traits  => [qw(Array)],
    handles => { additions => 'elements' },
    isa     => ArrayRef ['Pinto::Schema::Result::Registration'],
    default => sub {
        [   map  { $_->registration }
            grep { $_->op eq '+' } $_[0]->diffs
        ];
    },
    init_arg => undef,
    lazy     => 1,
);

has deletions => (
    traits  => [qw(Array)],
    handles => { deletions => 'elements' },
    isa     => ArrayRef ['Pinto::Schema::Result::Registration'],
    default => sub {
        [   map  { $_->registration }
            grep { $_->op eq '-' } $_[0]->diffs
        ];
    },
    init_arg => undef,
    lazy     => 1,
);

has is_different => (
    is       => 'ro',
    isa      => Bool,
    init_arg => undef,
    default  => sub { shift->diffs > 0 },
    lazy     => 1,
);

#------------------------------------------------------------------------------

around BUILDARGS => sub {
    my $orig  = shift;
    my $class = shift;
    my $args  = $class->$orig(@_);

    # The left and right attributes can also be Stack objects.
    # In those cases, we just use the head revision of the Stack

    for my $side (qw(left right)) {
        if ( $args->{$side}->isa('Pinto::Schema::Result::Stack') ) {
            $args->{$side} = $args->{$side}->head;
        }
    }

    return $args;
};

#------------------------------------------------------------------------------

sub _build_diffs {
    my ($self) = @_;

    # We want to find the registrations that are "different" in either
    # side.  Two registrations are the same if they have the same values in
    # the package, distribution, and is_pinned columns.  So we use these
    # columns to construct the keys of a hash.  The value is the id of
    # the registration.

    my @fields = qw(distribution package is_pinned);

    my $cb = sub {
        my $value = $_[0]->id;
        my $key = join '|', map { $_[0]->get_column($_) } @fields;
        return ( $key => $value );
    };

    my $attrs = { select => [ 'id', @fields ] };
    my %left = $self->left->registrations( {}, $attrs )->as_hash($cb);
    my %right = $self->right->registrations( {}, $attrs )->as_hash($cb);

    # Now that we have hashes representing the left and right, we use
    # the keys as "sets" and compute the difference between them.  Keys
    # present on the right but not on the left have been added.  And
    # those present on left but not on the right have been deleted.

    my @add_ids = @right{ grep { not exists $left{$_} } keys %right };
    my @del_ids = @left{ grep  { not exists $right{$_} } keys %left };

    # Now we have the ids of all the registrations that were added or
    # deleted between the left and right revisions.  We use those ids to
    # requery the database and construct full objects for each of them.

    my @adds = $self->_create_entries( '+', $self->right, \@add_ids );
    my @dels = $self->_create_entries( '-', $self->left,  \@del_ids );

    # Strictly speaking, the registrations are an unordered list.  But
    # the diff is more readable if we group registrations together by
    # distribution name.

    my @diffs = sort @adds, @dels;

    return \@diffs;
}

#------------------------------------------------------------------------------

sub _create_entries {
    my ( $self, $type, $side, $ids ) = @_;

    # The number of ids is potentially pretty big (1000's) and we
    # can't use that many values in an IN clause.  So we insert all
    # those ids into a temporary table.

    my $tmp_tbl = "__diff_${$}__";
    my $dbh     = $self->right->result_source->schema->storage->dbh;
    $dbh->do("CREATE TEMP TABLE $tmp_tbl (reg INTEGER NOT NULL)");

    my $sth = $dbh->prepare("INSERT INTO $tmp_tbl VALUES( ? )");
    $sth->execute($_) for @{$ids};

    # Now fetch the actual Registration objects (with all their
    # related objects) for each id in the temp table.  Finally,
    # map all the Registrations into DifferenceEntry objects.

    my $where   = { 'me.id' => { in => \"SELECT reg from $tmp_tbl" } };
    my $reg_rs  = $side->registrations($where)->with_distribution->with_package;
    my @entries = map { Pinto::DifferenceEntry->new( op => $type, registration => $_ ) } $reg_rs->all;

    $dbh->do("DROP TABLE $tmp_tbl");

    return @entries;
}

#------------------------------------------------------------------------------

sub foreach {
    my ( $self, $cb ) = @_;

    $cb->($_) for $self->diffs;

    return $self;
}

#------------------------------------------------------------------------------

sub to_string {
    my ($self) = @_;

    return join '', $self->diffs;
}

#------------------------------------------------------------------------------

__PACKAGE__->meta->make_immutable;

###############################################################################
###############################################################################

package Pinto::DifferenceEntry;

use Moose;
use MooseX::StrictConstructor;
use MooseX::MarkAsMethods ( autoclean => 1 );
use MooseX::Types::Moose qw(Str);

use overload (
    q{""} => 'to_string',
    'cmp' => 'string_compare',
);

#------------------------------------------------------------------------------

our $VERSION = '0.097'; # VERSION

#------------------------------------------------------------------------------

has op => (
    is       => 'ro',
    isa      => Str,
    required => 1
);

has registration => (
    is       => 'ro',
    isa      => 'Pinto::Schema::Result::Registration',
    required => 1,
);

#------------------------------------------------------------------------------

sub to_string {
    my ($self) = @_;

    my $format = "[%F] %-40p %12v %a/%f\n";
    return $self->op . $self->registration->to_string($format);
}

#------------------------------------------------------------------------------

sub string_compare {
    my ( $self, $other ) = @_;

    return ( $self->registration->distribution->name cmp $other->registration->distribution->name );
}

#------------------------------------------------------------------------------

__PACKAGE__->meta->make_immutable;

#------------------------------------------------------------------------------
1;

__END__

=pod

=encoding UTF-8

=for :stopwords Jeffrey Ryan Thalhammer

=head1 NAME

Pinto::Difference - Compute difference between two revisions

=head1 VERSION

version 0.097

=head1 AUTHOR

Jeffrey Ryan Thalhammer <jeff@stratopan.com>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2013 by Jeffrey Ryan Thalhammer.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut