<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;"># Copyright Â© 2014-2015 Guillem Jover &lt;guillem@debian.org&gt;
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program 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, see &lt;https://www.gnu.org/licenses/&gt;.

=encoding utf8

=head1 NAME

Dpkg::Dist::Files - handle built artifacts to distribute

=head1 DESCRIPTION

This module provides a class used to parse and write the F&lt;debian/files&gt;
file, as part of the list of built artifacts to include in an upload.

B&lt;Note&gt;: This is a private module, its API can change at any time.

=cut

package Dpkg::Dist::Files 0.01;

use strict;
use warnings;

use IO::Dir;

use Dpkg::Gettext;
use Dpkg::ErrorHandling;

use parent qw(Dpkg::Interface::Storable);

sub new {
    my ($this, %opts) = @_;
    my $class = ref($this) || $this;

    my $self = {
        options =&gt; [],
        files =&gt; {},
    };
    foreach my $opt (keys %opts) {
        $self-&gt;{$opt} = $opts{$opt};
    }
    bless $self, $class;

    return $self;
}

sub reset {
    my $self = shift;

    $self-&gt;{files} = {};
}

sub parse_filename {
    my ($self, $fn) = @_;

    my $file;

    if ($fn =~ m/^(([-+:.0-9a-z]+)_([^_]+)_([-\w]+)\.([a-z0-9.]+))$/) {
        # Artifact using the common &lt;name&gt;_&lt;version&gt;_&lt;arch&gt;.&lt;type&gt; pattern.
        $file-&gt;{filename} = $1;
        $file-&gt;{package} = $2;
        $file-&gt;{version} = $3;
        $file-&gt;{arch} = $4;
        $file-&gt;{package_type} = $5;
    } elsif ($fn =~ m/^([-+:.,_0-9a-zA-Z~]+)$/) {
        # Artifact with no common pattern, usually called byhand or raw, as
        # they might require manual processing on the server side, or custom
        # actions per file type.
        $file-&gt;{filename} = $1;
    } else {
        $file = undef;
    }

    return $file;
}

sub parse {
    my ($self, $fh, $desc) = @_;
    my $count = 0;

    local $_;
    binmode $fh;

    while (&lt;$fh&gt;) {
        chomp;

        my $file;

        if (m/^(\S+) (\S+) (\S+)((?:\s+[0-9a-z-]+=\S+)*)$/) {
            $file = $self-&gt;parse_filename($1);
            error(g_('badly formed file name in files list file, line %d'), $.)
                unless defined $file;
            $file-&gt;{section} = $2;
            $file-&gt;{priority} = $3;
            my $attrs = $4;
            $file-&gt;{attrs} = { map { split /=/ } split ' ', $attrs };
        } else {
            error(g_('badly formed line in files list file, line %d'), $.);
        }

        if (defined $self-&gt;{files}-&gt;{$file-&gt;{filename}}) {
            warning(g_('duplicate files list entry for file %s (line %d)'),
                    $file-&gt;{filename}, $.);
        } else {
            $count++;
            $self-&gt;{files}-&gt;{$file-&gt;{filename}} = $file;
        }
    }

    return $count;
}

sub load_dir {
    my ($self, $dir) = @_;

    my $count = 0;
    my $dh = IO::Dir-&gt;new($dir) or syserr(g_('cannot open directory %s'), $dir);

    while (defined(my $file = $dh-&gt;read)) {
        my $pathname = "$dir/$file";
        next unless -f $pathname;
        $count += $self-&gt;load($pathname);
    }

    return $count;
}

sub get_files {
    my $self = shift;

    return map { $self-&gt;{files}-&gt;{$_} } sort keys %{$self-&gt;{files}};
}

sub get_file {
    my ($self, $filename) = @_;

    return $self-&gt;{files}-&gt;{$filename};
}

sub add_file {
    my ($self, $filename, $section, $priority, %attrs) = @_;

    my $file = $self-&gt;parse_filename($filename);
    error(g_('invalid filename %s'), $filename) unless defined $file;
    $file-&gt;{section} = $section;
    $file-&gt;{priority} = $priority;
    $file-&gt;{attrs} = \%attrs;

    $self-&gt;{files}-&gt;{$filename} = $file;

    return $file;
}

sub del_file {
    my ($self, $filename) = @_;

    delete $self-&gt;{files}-&gt;{$filename};
}

sub filter {
    my ($self, %opts) = @_;
    my $remove = $opts{remove} // sub { 0 };
    my $keep = $opts{keep} // sub { 1 };

    foreach my $filename (keys %{$self-&gt;{files}}) {
        my $file = $self-&gt;{files}-&gt;{$filename};

        if (not $keep-&gt;($file) or $remove-&gt;($file)) {
            delete $self-&gt;{files}-&gt;{$filename};
        }
    }
}

sub output {
    my ($self, $fh) = @_;
    my $str = '';

    binmode $fh if defined $fh;

    foreach my $filename (sort keys %{$self-&gt;{files}}) {
        my $file = $self-&gt;{files}-&gt;{$filename};
        my $entry = "$filename $file-&gt;{section} $file-&gt;{priority}";

        if (exists $file-&gt;{attrs}) {
            foreach my $attr (sort keys %{$file-&gt;{attrs}}) {
                $entry .= " $attr=$file-&gt;{attrs}-&gt;{$attr}";
            }
        }

        $entry .= "\n";

        print { $fh } $entry if defined $fh;
        $str .= $entry;
    }

    return $str;
}

=head1 CHANGES

=head2 Version 0.xx

This is a private module.

=cut

1;
</pre></body></html>