find upgradable packages and optionally update apt index
[scpubgit/System-Introspector.git] / lib / System / Introspector / Probe / Packages / Apt.pm
1 package System::Introspector::Probe::Packages::Apt;
2 use Moo;
3
4 use System::Introspector::Util qw(
5     handle_from_command
6     transform_exceptions
7 );
8
9 has apt_lists_dir => (is => 'ro', builder => 1);
10 has apt_update_after => (is => 'ro', default => sub { 86400 });
11 has apt_update => (is => 'ro');
12
13 sub _build_apt_lists_dir { '/var/lib/apt/lists' }
14
15 sub gather {
16     my ($self) = @_;
17     return {
18         update => {
19             last => $self->_last_apt_update,
20             run => transform_exceptions {
21                 return { result => $self->_check_apt_state };
22             },
23         },
24         installed => transform_exceptions {
25             return { packages => $self->_gather_installed };
26         },
27         upgradable => transform_exceptions {
28             return { actions => $self->_gather_upgradable };
29         },
30     };
31 }
32
33 sub _last_apt_update {
34     my ($self) = @_;
35     return scalar( (stat($self->apt_lists_dir))[9] );
36 }
37
38 sub _check_apt_state {
39     my ($self) = @_;
40     return 'disabled' unless $self->apt_update;
41     my $threshold   = $self->apt_update_after;
42     my $last_change = $self->_last_apt_update;
43     return 'no'if ($last_change + $threshold) > time;
44     handle_from_command 'apt-get update';
45     return 'yes';
46 }
47
48 sub _open_dpkg_query_pipe {
49     my ($self) = @_;
50     return handle_from_command 'dpkg-query --show';
51 }
52
53 sub _open_apt_get_upgrade_simulation_pipe {
54     my ($self) = @_;
55     return handle_from_command 'apt-get -s upgrade';
56 }
57
58 sub _gather_upgradable {
59     my ($self) = @_;
60     my $pipe = $self->_open_apt_get_upgrade_simulation_pipe;
61     my %action;
62     while (defined( my $line = <$pipe> )) {
63         chomp $line;
64         if ($line =~ m{^(inst|remv)\s+(\S+)\s+(.+)$}i) {
65             $action{ lc($1) }{ $2 } = $3;
66         }
67     }
68     return \%action;
69 }
70
71 sub _gather_installed {
72     my ($self) = @_;
73     my $pipe = $self->_open_dpkg_query_pipe;
74     my %package;
75     while (defined( my $line = <$pipe> )) {
76         chomp $line;
77         my ($package, $version) = split m{\s+}, $line;
78         $package{ $package } = {
79             version => $version,
80         };
81     }
82     return \%package;
83 }
84
85 1;
86
87 __END__
88
89 =head1 NAME
90
91 System::Introspector::Packages::Apt - Gather APT package status
92
93 =head1 DESCRIPTION
94
95 Uses C<dpkg-query> to list all installed packages.
96
97 =head1 SEE ALSO
98
99 =over
100
101 =item L<System::Introspector>
102
103 =back
104
105 =cut