From a3b6027b7c2793bea4107896469de585a9aed305 Mon Sep 17 00:00:00 2001 From: Alad Wenter Date: Wed, 3 Apr 2024 20:22:03 +0200 Subject: [PATCH] Repo.pm: add parse_db_file() * Add a missing waitpid() so that a missing file actually results in an error. * Use `-e` in addition to `length()` as `abs_path` may resolve non-existing paths. --- lib/aur-repo-parse | 45 +++++++++++++++++---------------------------- perl/AUR/Repo.pm | 43 ++++++++++++++++++++++++++++++++++++++----- tests/repo-parse | 2 ++ 3 files changed, 57 insertions(+), 33 deletions(-) diff --git a/lib/aur-repo-parse b/lib/aur-repo-parse index e877400e..7e1576c1 100755 --- a/lib/aur-repo-parse +++ b/lib/aur-repo-parse @@ -3,12 +3,11 @@ use strict; use warnings; use v5.20; -use open ":std", ":encoding(UTF-8)"; use Cwd 'abs_path'; use File::Basename; use AUR::Json qw(write_json); -use AUR::Repo qw(check_attr list_attr parse_db); +use AUR::Repo qw(check_attr list_attr parse_db parse_db_file); my $argv0 = 'repo-parse'; # Handlers for filtering data @@ -221,14 +220,17 @@ unless (caller) { $ignore{$_}++ for (map { split(',', $_) } @opt_ignore); my $ignore_by = check_option($opt_ignore_by, '--ignore-by', 'Name'); + # Chain callbacks + my $handler = sub { + repo_filter($callback, $search, $search_by, \%ignore, $ignore_by, @_); + }; + # Take input from stdin instead of a pacman database if ($opt_stdin) { + # Additional fields for `aur-format` @varargs = ("/dev/stdin", "local") if ($opt_json or $opt_jsonl); - my $count = parse_db(*STDIN, 'FILENAME', sub { - repo_filter($callback, $search, $search_by, \%ignore, $ignore_by, @_); - }, @varargs); - + my $count = parse_db(*STDIN, 'FILENAME', $handler, @varargs); exit(0); } @@ -236,37 +238,24 @@ unless (caller) { # so fork a new process for each specified path. for my $db_path (@opt_db_path) { my $db_abs_path = abs_path($db_path); - my $db_name = basename($db_path); + my $db_name = basename($db_path); - if (not length($db_abs_path)) { - say STDERR $argv0 . ": file path '$db_path' not found"; + if (not length $db_abs_path or not -e $db_abs_path) { + say STDERR $argv0 . ": file '$db_path' not found"; exit(2); } + # Additional fields for `aur-format` + @varargs = ($db_abs_path, $db_name) if ($opt_json or $opt_jsonl); # repo-add(8) only accepts *.db or *.db.tar* extensions if ($db_name =~ /\.(db|files)(\.tar(\.\w+)?)?$/g) { $db_name = substr $db_name, 0, $-[0]; - } else { - say STDERR "$argv0: $db_name does not have a valid database archive extension"; - exit(1); } - - # When parsing the database, do not require a full extraction to either memory or disk - # by reading `tar` output line-by-line. It is not strictly necessary to depend on - # attribute order (i.e. %FILENAME% occuring in first place) while doing so; however, - # the `--verbose` flag printing file names has different behavior for different `tar` - # versions. Specifically, `bsdtar -xv` does not add a newline after the file path, - # while `tar -xv` does. - my $child_pid = open(my $fh, "-|", 'bsdtar', '-Oxf', $db_abs_path) or die $!; - - if ($child_pid) { # parent process - @varargs = ($db_abs_path, $db_name) if ($opt_json or $opt_jsonl); - - my $count = parse_db($fh, 'FILENAME', sub { - repo_filter($callback, $search, $search_by, \%ignore, $ignore_by, @_); - }, @varargs); + else { + say STDERR $argv0 . ": $db_name does not have a valid database archive extension"; + exit(1); } - exit(2) if $?; + my $count = parse_db_file($db_abs_path, 'FILENAME', $handler, @varargs); } } diff --git a/perl/AUR/Repo.pm b/perl/AUR/Repo.pm index 621f97eb..5b905ec2 100644 --- a/perl/AUR/Repo.pm +++ b/perl/AUR/Repo.pm @@ -2,10 +2,11 @@ package AUR::Repo; use strict; use warnings; use v5.20; +use open ":std", ":encoding(UTF-8)"; use Carp; use Exporter qw(import); -our @EXPORT_OK = qw(list_attr check_attr check_type parse_db); +our @EXPORT_OK = qw(list_attr check_attr check_type parse_db parse_db_file); our $VERSION = 'unstable'; =head1 NAME @@ -162,10 +163,42 @@ sub parse_db { return $count; } -# =head2 extract_db() +=head2 parse_db_file() -# =cut +Parameters: + +=over + +=item C<$db_path> + +=item C<$header> + +=item C<$handler> + +=item C<@varargs> -# sub extract_db { +=back + +=cut + +sub parse_db_file { + my ($db_path, $header, $handler, @varargs) = @_; + + # When parsing the database, do not require a full extraction to either memory or disk + # by reading `tar` output line-by-line. It is not strictly necessary to depend on + # attribute order (i.e. %FILENAME% occuring in first place) while doing so; however, + # the `--verbose` flag printing file names has different behavior for different `tar` + # versions. Specifically, `bsdtar -xv` does not add a newline after the file path, + # while `tar -xv` does. + my $child_pid = open(my $fh, "-|", 'bsdtar', '-Oxf', $db_path) or die $!; + my $count; -# } + if ($child_pid) { # parent process + $count = parse_db($fh, $header, $handler, @varargs); + + waitpid($child_pid, 0); + } + exit(2) if $?; + + return $count; +} diff --git a/tests/repo-parse b/tests/repo-parse index 6b37c0f2..540e2449 100755 --- a/tests/repo-parse +++ b/tests/repo-parse @@ -33,6 +33,8 @@ aur repo-parse || err=$? [[ $err == 1 ]] aur repo-parse -p /does/not/exist --list || err=$? [[ $err == 2 ]] +aur repo-parse -p /home/not_a_database.db --list || err=$? +[[ $err == 2 ]] # --json output with varying number of packages core_entries=('acl-*/desc' 'archlinux-keyring-*/desc') -- 2.11.4.GIT