diff --git a/lib/Devel/AssertOS/Linux/Ubuntu.pm b/lib/Devel/AssertOS/Linux/Ubuntu.pm index 036fc26..428a6d3 100644 --- a/lib/Devel/AssertOS/Linux/Ubuntu.pm +++ b/lib/Devel/AssertOS/Linux/Ubuntu.pm @@ -3,18 +3,21 @@ package Devel::AssertOS::Linux::Ubuntu; use Devel::CheckOS; use strict; use warnings; + +use Devel::AssertOS::OSFeatures::Release 'distributor_id'; + no warnings 'redefine'; -our $VERSION = '1.0'; +our $VERSION = '1.1'; sub os_is { - Devel::CheckOS::os_is('Linux') && - `lsb_release -i 2>/dev/null` =~ /Ubuntu/ + my $id = distributor_id; + Devel::CheckOS::os_is('Linux') && defined($id) && $id =~ /Ubuntu/; } sub expn { "The operating system is some version of Ubuntu" } -Devel::CheckOS::die_unsupported() unless(os_is()); +Devel::CheckOS::die_unsupported() unless ( os_is() ); =head1 COPYRIGHT and LICENCE diff --git a/lib/Devel/AssertOS/OSFeatures/Release.pm b/lib/Devel/AssertOS/OSFeatures/Release.pm new file mode 100644 index 0000000..bfdb96d --- /dev/null +++ b/lib/Devel/AssertOS/OSFeatures/Release.pm @@ -0,0 +1,83 @@ +package Devel::AssertOS::OSFeatures::Release; + +use strict; +use warnings; +use File::Spec; +use parent 'Exporter'; + +our $VERSION = '1.0'; +our @EXPORT_OK = qw(distributor_id); + +=pod + +=head1 NAME + +Devel::AssertOS::OSFeatures::Release - functions to manipulate os-release file + +=head1 SYNOPSIS + + use Devel::AssertOS::OSFeatures::Release 'distributor_id'; + my $id = distributor_id; + +=head1 DESCRIPTION + +This module exports functions to handle text files related to Debian-like +distributions. + +=head1 EXPORTED + +The following subs are exported. + +=head2 distributor_id + +Retrieves and returns the distributor ID from the F file. + +It is expected that the file exists, it is readable and have the following +(minimum) content format: + + NAME="Ubuntu" + VERSION_ID="22.04" + VERSION="22.04.4 LTS (Jammy Jellyfish)" + VERSION_CODENAME=jammy + ID=ubuntu + ID_LIKE=debian + HOME_URL="https://www.ubuntu.com/" + +This excerpt is from Ubuntu 22.04, but other distributions might have fewer, +more or different fields and values. + +It returns the value of C or C, if the conditions are not those +specified above. + +=cut + +sub distributor_id { + my $filename = 'os-release'; + my $file_path = File::Spec->catfile( ( '', 'etc' ), $filename ); + my $regex = qr/^ID\=(\w+)/; + my $dist_id = undef; + + if ( -r $file_path ) { + open my $in, '<', $file_path or die "Cannot read $file_path: $!"; + while (<$in>) { + chomp; + if ( $_ =~ $regex ) { + $dist_id = ucfirst(lc $1) if (defined($1)); + last; + } + } + close($in) or die "Cannot close $file_path: $!"; + } + + return $dist_id; +} + +=head1 COPYRIGHT and LICENCE + +Copyright 2024 David Cantrell + +This software is free-as-in-speech software, and may be used, distributed, and modified under the terms of either the GNU General Public Licence version 2 or the Artistic Licence. It's up to you which one you use. The full text of the licences can be found in the files GPL2.txt and ARTISTIC.txt, respectively. + +=cut + +1; diff --git a/t/os-release.t b/t/os-release.t new file mode 100644 index 0000000..d9968ce --- /dev/null +++ b/t/os-release.t @@ -0,0 +1,17 @@ +use warnings; +use strict; +use Test::More; +use Devel::AssertOS::OSFeatures::Release 'distributor_id'; + +my $total_tests = 3; +plan tests => $total_tests; + +SKIP: { + skip 'Not a Linux distribution', $total_tests unless ( $^O eq 'linux' ); + my $id = distributor_id(); + ok( $id, 'can fetch the distribution ID' ) + or BAIL_OUT('No use to keep testing with ID = undef'); + like $id, qr/^\w+$/, 'ID looks like a string'; + my $copy = ucfirst( lc $id ); + is( $id, $copy, 'ID is returned with first character in uppercase' ); +}