Skip to content

Commit 68875b1

Browse files
committed
Add support for _manifest files
1 parent a0a2011 commit 68875b1

File tree

4 files changed

+106
-14
lines changed

4 files changed

+106
-14
lines changed

PBuild/Manifest.pm

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
################################################################
2+
#
3+
# Copyright (c) 2026 SUSE LLC
4+
#
5+
# This program is free software; you can redistribute it and/or modify
6+
# it under the terms of the GNU General Public License version 2 or 3 as
7+
# published by the Free Software Foundation.
8+
#
9+
# This program is distributed in the hope that it will be useful,
10+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
# GNU General Public License for more details.
13+
#
14+
# You should have received a copy of the GNU General Public License
15+
# along with this program (see the file COPYING); if not, write to the
16+
# Free Software Foundation, Inc.,
17+
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
18+
#
19+
################################################################
20+
21+
package PBuild::Manifest;
22+
23+
use PBuild::Util;
24+
use PBuild::Source;
25+
26+
sub read_manifest {
27+
my ($dir) = @_;
28+
eval { require YAML::XS; $YAML::XS::LoadBlessed = 0; };
29+
die("Need YAML::XS to parse the _manifest file\n") unless defined &YAML::XS::LoadFile;
30+
my $manifest = eval { YAML::XS::LoadFile("$dir/_manifest") };
31+
die("Could not parse _manifest file: $@") if $@;
32+
die("Bad _manifest file\n") unless ref($manifest) eq 'HASH';
33+
return $manifest;
34+
}
35+
36+
sub find_packages {
37+
my ($root_dir, $pkg_dirs) = @_;
38+
$seend_sd ||= {};
39+
my $manifest = read_manifest($root_dir);
40+
my @pkgs;
41+
my @skippkgs;
42+
if (ref($manifest->{'packages'}) eq 'ARRAY') {
43+
for my $pkg (@{$manifest->{'packages'}}) {
44+
next if !defined($pkg) || ref($pkg) || $pkg eq '' || $pkg eq '.' || $pkg eq '..' || $pkg =~ /^\//;
45+
my $pkgdir = "$root_dir/$pkg";
46+
push @skippkgs, $1 if $pkg =~ /^([^\/]+)\//;
47+
$pkg =~ s/.*\///;
48+
next if $pkg eq '' || $pkg =~ /^[\._]/;
49+
next if $pkg_dirs->{$pkg} || !-d $pkgdir;
50+
push @pkgs, $pkg;
51+
$pkg_dirs->{$pkg} = $pkgdir;
52+
}
53+
}
54+
if (ref($manifest->{'subdirectories'}) eq 'ARRAY') {
55+
for my $sd (@{$manifest->{'subdirectories'}}) {
56+
next if !defined($sd) || ref($sd) || $sd eq '' || $sd eq '.' || $sd eq '..' || $sd =~ /^\//;
57+
next unless -d "$root_dir/$sd";
58+
push @skippkgs, $1 if $sd =~ /^([^\/]+)/;
59+
push @pkgs, find_packages("$root_dir/$sd", $pkg_dirs);
60+
}
61+
}
62+
if (!exists($manifest->{'packages'})) {
63+
@skippkgs = grep {!$pkg_dirs->{$_}} PBuild::Util::unify(@skippkgs);
64+
$pkg_dirs->{$_} = 1 for @skippkgs;
65+
push @pkgs, PBuild::Source::find_packages($root_dir, $pkg_dirs);
66+
delete $pkg_dirs->{$_} for @skippkgs;
67+
}
68+
return @pkgs;
69+
}
70+
71+
1;

PBuild/Recipe.pm

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -206,12 +206,6 @@ sub split_hostdeps {
206206

207207
sub looks_like_packagedir {
208208
my ($dir) = @_;
209-
return 0 if -d "$dir/.pbuild";
210-
return 0 if -d "$dir/_pbuild";
211-
return 0 if -d "$dir/_config";
212-
return 1 if -d "$dir/../.pbuild";
213-
return 1 if -d "$dir/../_pbuild";
214-
return 1 if -d "$dir/../_config";
215209
my @files = PBuild::Util::ls($dir);
216210
return 0 if grep {/^_build\./} @files;
217211
for my $file (@files) {

PBuild/Source.pm

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,30 @@ use Digest::MD5;
2525

2626
use PBuild::Util;
2727

28-
sub find_packages {
28+
sub find_root_dir {
2929
my ($dir) = @_;
30+
return undef unless $dir =~ /^\//;
31+
my $configdir;
32+
for my $i (1..3) {
33+
last if $dir eq '' || $dir eq '/';
34+
return $dir if -e "$dir/.pbuild";
35+
return $dir if -e "$dir/_pbuild";
36+
return $dir if -e "$dir/_manifest";
37+
$configdir = $dir if -e "$dir/_config";
38+
last unless $dir =~ s/\/[^\/]*$//;
39+
}
40+
return $configdir;
41+
}
42+
43+
sub find_packages {
44+
my ($root_dir, $pkgdirs) = @_;
3045
my @pkgs;
31-
for my $pkg (sort(PBuild::Util::ls($dir))) {
46+
for my $pkg (sort(PBuild::Util::ls($root_dir))) {
3247
next if $pkg =~ /^[\._]/;
33-
next unless -d "$dir/$pkg";
48+
next unless -d "$root_dir/$pkg";
49+
next if $pkgdirs->{$pkg}; # only one package please
3450
push @pkgs, $pkg;
51+
$pkgdirs->{$pkg} = "$root_dir/$pkg";
3552
}
3653
return @pkgs;
3754
}

pbuild

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ use Build;
3838

3939
use PBuild::Source;
4040
use PBuild::Recipe;
41+
use PBuild::Manifest;
4142
use PBuild::AssetMgr;
4243
use PBuild::RepoMgr;
4344
use PBuild::LocalRepo;
@@ -62,9 +63,12 @@ my $dir = @dirs ? $dirs[0] : '.';
6263
$dir = Cwd::abs_path($dir) if $dir !~ /^\//;
6364
$dir =~ s/(.)\/+$/$1/s;
6465

65-
# autodetect single mode
66-
if (!exists($opts->{'single'}) && PBuild::Recipe::looks_like_packagedir($dir)) {
67-
$opts->{'single'} = $1 if $dir =~ s/\/([^\/]+)$//;
66+
# find root directory and autodetect single mode
67+
my $root_dir = PBuild::Source::find_root_dir($dir);
68+
$root_dir = $1 if !$root_dir && PBuild::Recipe::looks_like_packagedir($dir) && $dir =~ /^(.*)\/[^\/]+$/;
69+
if ($root_dir && $dir ne $root_dir) {
70+
$opts->{'single'} = $1 if !exists($opts->{'single'}) && $dir =~ /\/([^\/]+)$/;
71+
$dir = $root_dir;
6872
}
6973

7074
if ($opts->{'list-presets'}) {
@@ -274,7 +278,13 @@ if ($cross && @{$opts->{'hostrepo'} || []}) {
274278
print " - $_\n" for @{$opts->{'hostrepo'}};
275279
}
276280
print "searching for packages\n";
277-
my @pkgs = PBuild::Source::find_packages($dir);
281+
my %pkgdirs;
282+
my @pkgs;
283+
if (-s "$dir/_manifest") {
284+
@pkgs = PBuild::Manifest::find_packages($dir, \%pkgdirs);
285+
} else {
286+
@pkgs = PBuild::Source::find_packages($dir, \%pkgdirs);
287+
}
278288
die("no packages found in '$dir'\n") unless @pkgs || $opts->{'repoquery'} || $opts->{'repoquery-host'};
279289
print "found ".PBuild::Util::plural(scalar(@pkgs), 'package')."\n";
280290

@@ -289,7 +299,7 @@ for my $pkg (@pkgs) {
289299
my ($files, $source_assets) = PBuild::Source::list_package("$dir/$pkg");
290300
my $p = {
291301
'pkg' => $pkg,
292-
'dir' => "$dir/$pkg",
302+
'dir' => $pkgdirs{$pkg},
293303
'files' => $files,
294304
'srcmd5' => PBuild::Source::calc_srcmd5($files),
295305
'srcmd5' => PBuild::Source::calc_srcmd5($files),

0 commit comments

Comments
 (0)