When templates recursively include other templates, a diamond problem,
similar to multiple inheritance, may occur. It is illustrated in the
test case. As templates may consist of arbitrary code, it may be
unwanted to execute a template twice. This patch provides a solution to
some simple cases of this problem by completely ignoring every template
occurrence but the first for each template name.
Signed-off-by: Dominik Fischer <d.f.fischer(a)web.de>
---
doc/makepkg-template.1.txt | 6 ++++++
scripts/makepkg-template.pl.in | 12 ++++++++++++
.../makepkg-template-tests/diamond-input/PKGBUILD | 5 +++++
.../diamond-input/PKGBUILD.expanded | 13 +++++++++++++
.../diamond-input/templates/base-1.template | 1 +
.../diamond-input/templates/first-include-1.template | 1 +
.../diamond-input/templates/second-include-1.template | 1 +
.../diamond-input/testcase-config | 18 ++++++++++++++++++
8 files changed, 57 insertions(+)
create mode 100644 test/scripts/makepkg-template-tests/diamond-input/PKGBUILD
create mode 100644 test/scripts/makepkg-template-tests/diamond-input/PKGBUILD.expanded
create mode 100644 test/scripts/makepkg-template-tests/diamond-input/templates/base-1.template
create mode 100644 test/scripts/makepkg-template-tests/diamond-input/templates/first-include-1.template
create mode 100644 test/scripts/makepkg-template-tests/diamond-input/templates/second-include-1.template
create mode 100644 test/scripts/makepkg-template-tests/diamond-input/testcase-config
diff --git a/doc/makepkg-template.1.txt b/doc/makepkg-template.1.txt
index 03b2a38..bd2355c 100644
--- a/doc/makepkg-template.1.txt
+++ b/doc/makepkg-template.1.txt
@@ -76,6 +76,12 @@ Options
given multiple times in which case files found in directory given last will
take precedence.
+*-t, \--no-duplicates*::
+ Do not include any template twice, even when templates recursively include
+ other templates. Only the first occurrence of each template will be
+ expanded, all further references to the same name, also with different
+ version numbers, will be ignored.
+
Example PKGBUILD
----------------
diff --git a/scripts/makepkg-template.pl.in b/scripts/makepkg-template.pl.in
index 9877796..e9f6e08 100755
--- a/scripts/makepkg-template.pl.in
+++ b/scripts/makepkg-template.pl.in
@@ -33,6 +33,8 @@ my %opts = (
my $template_name_charset = qr/[[:alnum:]+_.@-]/;
my $template_marker = qr/# template/;
+my %seen = ();
+
# runtime loading to avoid dependency on cpan since this is the only non-core module
my $loaded_gettext = can_load(modules => {'Locale::gettext' => undef});
if ($loaded_gettext) {
@@ -96,6 +98,15 @@ sub parse_template_line {
sub load_template {
my ($values) = @_;
+ if ($opts{dups}) {
+ # omit already included templates.
+ if (exists $seen{$values->{name}}) {
+ return "";
+ } else {
+ $seen{$values->{name}} = ();
+ }
+ }
+
my $ret = "";
my $template_name = "$values->{name}";
@@ -205,6 +216,7 @@ GetOptions(
"output|o=s" => \$opts{output},
"newest|n" => \$opts{newest},
"template-dir=s@" => \$opts{template_dir},
+ "no-duplicates|t" => \$opts{dups},
) or usage(1);
$opts{output} = $opts{input} unless $opts{output};
diff --git a/test/scripts/makepkg-template-tests/diamond-input/PKGBUILD b/test/scripts/makepkg-template-tests/diamond-input/PKGBUILD
new file mode 100644
index 0000000..6bb4fa5
--- /dev/null
+++ b/test/scripts/makepkg-template-tests/diamond-input/PKGBUILD
@@ -0,0 +1,5 @@
+pkgname=foo
+pkgver=1
+
+# template input; name=first-include; version=1;
+# template input; name=second-include; version=1;
diff --git a/test/scripts/makepkg-template-tests/diamond-input/PKGBUILD.expanded b/test/scripts/makepkg-template-tests/diamond-input/PKGBUILD.expanded
new file mode 100644
index 0000000..8077581
--- /dev/null
+++ b/test/scripts/makepkg-template-tests/diamond-input/PKGBUILD.expanded
@@ -0,0 +1,13 @@
+pkgname=foo
+pkgver=1
+
+# template start; name=first-include; version=1;
+# template start; name=base; version=1;
+package() {}
+# template end;
+# template end;
+# template start; name=second-include; version=1;
+# template start; name=base; version=1;
+package() {}
+# template end;
+# template end;
diff --git a/test/scripts/makepkg-template-tests/diamond-input/templates/base-1.template b/test/scripts/makepkg-template-tests/diamond-input/templates/base-1.template
new file mode 100644
index 0000000..056096f
--- /dev/null
+++ b/test/scripts/makepkg-template-tests/diamond-input/templates/base-1.template
@@ -0,0 +1 @@
+package() {}
diff --git a/test/scripts/makepkg-template-tests/diamond-input/templates/first-include-1.template b/test/scripts/makepkg-template-tests/diamond-input/templates/first-include-1.template
new file mode 100644
index 0000000..9916370
--- /dev/null
+++ b/test/scripts/makepkg-template-tests/diamond-input/templates/first-include-1.template
@@ -0,0 +1 @@
+# template input; name=base; version=1;
diff --git a/test/scripts/makepkg-template-tests/diamond-input/templates/second-include-1.template b/test/scripts/makepkg-template-tests/diamond-input/templates/second-include-1.template
new file mode 100644
index 0000000..9916370
--- /dev/null
+++ b/test/scripts/makepkg-template-tests/diamond-input/templates/second-include-1.template
@@ -0,0 +1 @@
+# template input; name=base; version=1;
diff --git a/test/scripts/makepkg-template-tests/diamond-input/testcase-config b/test/scripts/makepkg-template-tests/diamond-input/testcase-config
new file mode 100644
index 0000000..65bb8d0
--- /dev/null
+++ b/test/scripts/makepkg-template-tests/diamond-input/testcase-config
@@ -0,0 +1,18 @@
+arguments+=(-t)
+expected_exitcode=0
+
+IFS="" read -d '' expected_output <<'EOF'
+EOF
+
+IFS="" read -d '' expected_result <<'EOF'
+pkgname=foo
+pkgver=1
+
+# template start; name=first-include; version=1;
+# template start; name=base; version=1;
+package() {}
+# template end;
+# template end;
+# template start; name=second-include; version=1;
+# template end;
+EOF
--
2.4.2