[kdesrc-build] /: Add support library for handling /etc/os-release.

Michael Pyne null at kde.org
Sun Oct 14 23:44:34 BST 2018


Git commit f3f100de6410d5ad9b84bef2d237ee2540e0f043 by Michael Pyne.
Committed on 14/10/2018 at 22:41.
Pushed by mpyne into branch 'master'.

Add support library for handling /etc/os-release.

This gets me just that little itty bitty step farther towards
implementing support for distro-specific things (like listing Perl
dependencies, build dependencies, etc.)

See also https://phabricator.kde.org/T9507

M  +1    -0    CMakeLists.txt
M  +10   -0    doc/index.docbook
M  +14   -0    doc/man-kdesrc-build.1.docbook
M  +4    -1    modules/ksb/Application.pm
A  +130  -0    modules/ksb/OSSupport.pm
A  +10   -0    t/data/os-release
A  +30   -0    t/os-release-basics.t

https://commits.kde.org/kdesrc-build/f3f100de6410d5ad9b84bef2d237ee2540e0f043

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8e762ae..1ea5bca 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -45,6 +45,7 @@ if (KDESRC_BUILD_INSTALL_MODULES)
         modules/ksb/ModuleResolver.pm
         modules/ksb/ModuleSet.pm
         modules/ksb/OptionsBase.pm
+        modules/ksb/OSSupport.pm
         modules/ksb/PhaseList.pm
         modules/ksb/RecursiveFH.pm
         modules/ksb/StatusView.pm
diff --git a/doc/index.docbook b/doc/index.docbook
index 64dc4c7..6e8c40c 100644
--- a/doc/index.docbook
+++ b/doc/index.docbook
@@ -3001,6 +3001,16 @@ Display the program version.
 </para></listitem>
 </varlistentry>
 
+<varlistentry id="cmdline-show-info">
+<term><parameter>--show-info</parameter></term>
+<listitem><para>
+Displays information about &kdesrc-build; and the operating system, that may
+prove useful in bug reports or when asking for help in forums or mailing lists.
+</para>
+<para>Available since version 18.11.</para>
+</listitem>
+</varlistentry>
+
 <varlistentry id="cmdline-author">
 <term><parameter>--author</parameter></term>
 <listitem><para>
diff --git a/doc/man-kdesrc-build.1.docbook b/doc/man-kdesrc-build.1.docbook
index 539b54a..4872534 100644
--- a/doc/man-kdesrc-build.1.docbook
+++ b/doc/man-kdesrc-build.1.docbook
@@ -102,6 +102,20 @@ combining short options into one at this point. (E.g. running
 </listitem>
 </varlistentry>
 
+<varlistentry>
+<term>
+<option>--show-info</option>
+</term>
+
+<listitem>
+<para>
+    Shows information about &kdesrc-build; and the operating system which may
+    be useful in bug reports or when requesting help on forums or mailing
+    lists.
+</para>
+</listitem>
+</varlistentry>
+
 <varlistentry>
 <term>
 <option>-p, --pretend</option>
diff --git a/modules/ksb/Application.pm b/modules/ksb/Application.pm
index 8e720b9..259be35 100644
--- a/modules/ksb/Application.pm
+++ b/modules/ksb/Application.pm
@@ -19,6 +19,7 @@ use ksb::Module;
 use ksb::ModuleResolver 0.20;
 use ksb::ModuleSet 0.20;
 use ksb::ModuleSet::KDEProjects;
+use ksb::OSSupport;
 use ksb::RecursiveFH;
 use ksb::DependencyResolver 0.20;
 use ksb::IPC::Pipe 0.20;
@@ -133,6 +134,7 @@ sub _readCommandLineOptionsAndSelectors
     my ($cmdlineOptionsRef, $selectorsRef, $ctx, @options) = @_;
     my $phases = $ctx->phases();
     my @savedOptions = @options; # Copied for use in debugging.
+    my $os = ksb::OSSupport->new;
     my $version = "kdesrc-build " . scriptVersion();
     my $author = <<DONE;
 $version was written (mostly) by:
@@ -152,6 +154,7 @@ DONE
     %foundOptions = (
         version => sub { say $version; exit },
         author  => sub { say $author;  exit },
+        'show-info' => sub { say $version; say "OS: ", $os->vendorID(); exit },
         help    => sub { _showHelpMessage(); exit 0 },
         install => sub {
             $self->{run_mode} = 'install';
@@ -276,7 +279,7 @@ DONE
 
     # Actually read the options.
     my $optsSuccess = GetOptionsFromArray(\@options, \%foundOptions,
-        'version', 'author', 'help', 'disable-snapshots|no-snapshots',
+        'version', 'author', 'help', 'show-info', 'disable-snapshots|no-snapshots',
         'install', 'uninstall', 'no-src|no-svn', 'no-install', 'no-build',
         'no-tests', 'build-when-unchanged|force-build', 'no-metadata',
         'verbose|v', 'quiet|quite|q', 'really-quiet', 'debug',
diff --git a/modules/ksb/OSSupport.pm b/modules/ksb/OSSupport.pm
new file mode 100644
index 0000000..c7414f8
--- /dev/null
+++ b/modules/ksb/OSSupport.pm
@@ -0,0 +1,130 @@
+package ksb::OSSupport 0.10;
+
+use ksb::Util qw(croak_runtime);
+
+use Text::ParseWords qw(nested_quotewords);
+use List::Util qw(first);
+
+=head1 NAME
+
+ksb::OSSupport
+
+=head1 DESCRIPTION
+
+Provides support code for handling distro-specific functionality, such as lists
+of package dependencies, command lines to update packages in the first place,
+and so on.
+
+See L<https://www.freedesktop.org/software/systemd/man/os-release.html> for the
+relevant specification.
+
+=head1 SYNOPSIS
+
+    my $os = ksb::OSSupport->new; # Autodetects info on running system
+    say "Current OS is: ", $os->vendorID;
+
+=cut
+
+=head1 METHODS
+
+=head2 new
+
+    $os = ksb::OSSupport->new;
+
+    # Manually point to os-release
+    $os = ksb::OSSupport->new('/usr/lib/os-release');
+
+Creates a new object. Required for other methods.
+
+=cut
+
+sub new
+{
+    my ($class, $file) = @_;
+
+    my $self = bless {
+    }, $class;
+
+    # $file might be undef
+    my @kvListRef = $self->_readOSRelease($file);
+
+    # Result comes in a listref which itself contains 2-elem
+    # lists... flatten list so it can be assigned to the hash
+    %{$self} = map { @{$_}[0,1] } @kvListRef;
+
+    return $self;
+}
+
+=head2 vendorID
+
+    my $vendor = $os->vendorID; # 'gentoo', 'debian', etc.
+
+Returns the vendor ID from the I<os-release> specification.
+
+=cut
+
+sub vendorID
+{
+    my $self = shift;
+    return $self->{ID} // 'unknown';
+}
+
+=head2 bestDistroMatch
+
+    # Might return 'fedora' if running on Scientific Linux
+    my $distro = $os->bestDistroMatch(qw/ubuntu fedora arch debian/);
+
+This uses the ID (and if needed, ID_LIKE) parameter in
+/etc/os-release to find the best possible match amongst the
+provided distro IDs. The list of distros should be ordered with
+most specific distro first.
+
+If no match is found, returns 'linux' (B<not> undef, '', or
+similar)
+
+=cut
+
+sub bestDistroMatch
+{
+    my ($self, @distros) = @_;
+    my @ids = $self->vendorID;
+
+    if (my $likeDistros = $self->{ID_LIKE} // '') {
+        push @ids, split(' ', $likeDistros);
+    }
+
+    foreach my $distro (@distros) {
+        return $distro if first { $distro eq $_ } @ids;
+    }
+
+    return 'linux';
+}
+
+sub _readOSRelease
+{
+    my ($self, $fileName) = @_;
+    my @files = $fileName ? $fileName : qw(/etc/os-release /usr/lib/os-release);
+    my ($fh, $error);
+
+    while (!$fh && @files) {
+        my $file = shift @files;
+        open $fh, '<:encoding(UTF-8)', $file and last;
+        $error = $!;
+    }
+
+    croak_runtime("Can't open os-release! $error")
+        unless $fh;
+
+    # skip comments and blank lines, and whitespace-only lines
+    my @lines = grep { ! /^\s*(?:#.*)?\s*$/ }
+                map  { chomp; $_ }
+                    <$fh>;
+    close $fh;
+
+    # 0 allows discarding the delimiter and any quotes
+    # Return should be one list per line, hopefully each list has
+    # exactly 2 values ([$key, $value]).
+    return nested_quotewords('=', 0, @lines);
+}
+
+1;
diff --git a/t/data/os-release b/t/data/os-release
new file mode 100644
index 0000000..16f282e
--- /dev/null
+++ b/t/data/os-release
@@ -0,0 +1,10 @@
+# See https://www.freedesktop.org/software/systemd/man/os-release.html for format
+NAME="Totally Valid Name"
+
+# inline comments are not allowed, a comment must be alone on a line
+ID=kdesrc-build
+
+ID_LIKE="sabayon gentoo-hardened gentoo"
+
+# Test shell quoting
+SPECIAL="\$VAR \\ \` \" is set"
diff --git a/t/os-release-basics.t b/t/os-release-basics.t
new file mode 100644
index 0000000..afe87bf
--- /dev/null
+++ b/t/os-release-basics.t
@@ -0,0 +1,30 @@
+use 5.014;
+use strict;
+use warnings;
+
+# Test ksb::OSSupport
+
+use Test::More;
+
+use ksb::OSSupport;
+
+# Unit test of _readOSRelease
+my @kvPairs = ksb::OSSupport->_readOSRelease('t/data/os-release');
+
+is(scalar @kvPairs, 4, 'Right number of key/value pairs');
+
+my %opts = map { @{$_}[0,1] } @kvPairs;
+
+is($opts{NAME}, 'Totally Valid Name', 'Right NAME');
+is($opts{ID}, 'kdesrc-build', 'Right ID');
+is($opts{ID_LIKE}, 'sabayon gentoo-hardened gentoo', 'Right ID_LIKE');
+is($opts{SPECIAL}, '$VAR \\ ` " is set', 'Right SPECIAL');
+
+# Use tests
+my $os = new_ok('ksb::OSSupport', ['t/data/os-release']);
+is($os->bestDistroMatch(qw/arch kdesrc-build sabayon/), 'kdesrc-build', 'ID preferred');
+is($os->bestDistroMatch(qw/ubuntu fedora gentoo/), 'gentoo', 'ID_LIKE respected');
+is($os->bestDistroMatch(qw/fedora gentoo gentoo-hardened sabayon/), 'gentoo', 'ID_LIKE preference order proper');
+is($os->vendorID, 'kdesrc-build', 'Right ID');
+
+done_testing();


More information about the kde-doc-english mailing list