summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPanu Matilainen <pmatilai@redhat.com>2022-03-25 11:32:27 +0200
committerPanu Matilainen <pmatilai@redhat.com>2022-04-04 10:04:25 +0300
commitcd5d667e99f931504a512b591fcde7ed92cee344 (patch)
tree881d7669f1d6301db95b775153b086782a8f5cc2
parent96de5c1f02e69a7ae37bcc8437451dfa35c87ae1 (diff)
downloadrpm-cd5d667e99f931504a512b591fcde7ed92cee344.tar.gz
Move source uncompress logic from spec parse to build time
Traditionally, %setup processing has figured out the commands needed to extract the source in question. The problem with this is that it happens at spec parse time, requiring access to sources that may not even be there in plain spec queries. Move the unpack logic from %setup internals to an `rpmuncompress` helper executable which is now the only command %setup needs to know. This way, spec parsing never needs to look at the actual source files, their presence is only required for an actual build. Another advantage is that the extraction machinery is now available to packagers without having to call %setup with its side-effects on %buildsubdir and such. Split the rpmbuild -ba test on missing sources into separate -bb and -bs tests as these are now rather different: binary build only tests for source presence if %prep is actually executed, and missing files at source build stage are discovered at a later stage as well.
-rw-r--r--Makefile.am4
-rw-r--r--build/parsePrep.c91
-rw-r--r--macros.in1
-rw-r--r--po/POTFILES.in1
-rw-r--r--tests/rpmbuild.at22
-rw-r--r--tools/rpmuncompress.c156
6 files changed, 189 insertions, 86 deletions
diff --git a/Makefile.am b/Makefile.am
index 3cbc4ce6d..72ad4b36b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -177,6 +177,10 @@ rpmlibexec_PROGRAMS += rpmdeps
rpmdeps_SOURCES = tools/rpmdeps.c
rpmdeps_LDADD = lib/librpm.la rpmio/librpmio.la build/librpmbuild.la @WITH_POPT_LIB@
+rpmlibexec_PROGRAMS += rpmuncompress
+rpmuncompress_SOURCES = tools/rpmuncompress.c
+rpmuncompress_LDADD = lib/librpm.la rpmio/librpmio.la @WITH_POPT_LIB@
+
bin_PROGRAMS += rpmgraph
rpmgraph_SOURCES = tools/rpmgraph.c
rpmgraph_LDADD = lib/librpm.la rpmio/librpmio.la @WITH_POPT_LIB@
diff --git a/build/parsePrep.c b/build/parsePrep.c
index 9b6b30445..64ade7846 100644
--- a/build/parsePrep.c
+++ b/build/parsePrep.c
@@ -128,98 +128,23 @@ exit:
static char *doUntar(rpmSpec spec, uint32_t c, int quietly)
{
char *buf = NULL;
- char *tar = NULL;
- const char *taropts = ((rpmIsVerbose() && !quietly) ? "-xvvof" : "-xof");
struct Source *sp;
- rpmCompressedMagic compressed = COMPRESSED_NOT;
if ((sp = findSource(spec, c, RPMBUILD_ISSOURCE)) == NULL) {
rpmlog(RPMLOG_ERR, _("No source number %u\n"), c);
goto exit;
}
- const char *fn = sp->path;
- /* XXX On non-build parse's, file cannot be stat'd or read */
- if (!(spec->flags & RPMSPEC_FORCE) && (checkOwners(fn) || rpmFileIsCompressed(fn, &compressed))) {
- goto exit;
- }
-
- tar = rpmGetPath("%{__tar}", NULL);
- if (compressed != COMPRESSED_NOT) {
- char *zipper = NULL;
- const char *t = NULL;
- int needtar = 1;
- int needgemspec = 0;
-
- switch (compressed) {
- case COMPRESSED_NOT: /* XXX can't happen */
- case COMPRESSED_OTHER:
- t = "%{__gzip} -dc";
- break;
- case COMPRESSED_BZIP2:
- t = "%{__bzip2} -dc";
- break;
- case COMPRESSED_ZIP:
- if (rpmIsVerbose() && !quietly)
- t = "%{__unzip}";
- else
- t = "%{__unzip} -qq";
- needtar = 0;
- break;
- case COMPRESSED_LZMA:
- case COMPRESSED_XZ:
- t = "%{__xz} -dc";
- break;
- case COMPRESSED_LZIP:
- t = "%{__lzip} -dc";
- break;
- case COMPRESSED_LRZIP:
- t = "%{__lrzip} -dqo-";
- break;
- case COMPRESSED_7ZIP:
- t = "%{__7zip} x";
- needtar = 0;
- break;
- case COMPRESSED_ZSTD:
- t = "%{__zstd} -dc";
- break;
- case COMPRESSED_GEM:
- t = "%{__gem} unpack";
- needtar = 0;
- needgemspec = 1;
- break;
- }
- zipper = rpmGetPath(t, NULL);
- if (needtar) {
- rasprintf(&buf, "%s '%s' | %s %s -", zipper, fn, tar, taropts);
- } else if (needgemspec) {
- char *gem = rpmGetPath("%{__gem}", NULL);
- char *gemspec = NULL;
- char gemnameversion[strlen(sp->source) - 3];
-
- rstrlcpy(gemnameversion, sp->source, strlen(sp->source) - 3);
- gemspec = rpmGetPath("%{_builddir}/", gemnameversion, ".gemspec", NULL);
-
- rasprintf(&buf, "%s '%s' && %s spec '%s' --ruby > '%s'",
- zipper, fn, gem, fn, gemspec);
-
- free(gemspec);
- free(gem);
- } else {
- rasprintf(&buf, "%s '%s'", zipper, fn);
- }
- free(zipper);
- } else {
- rasprintf(&buf, "%s %s '%s'", tar, taropts, fn);
- }
+ buf = rpmExpand("%{__rpmuncompress} -x ",
+ quietly ? "" : "-v", sp->path, NULL);
+ rstrcat(&buf,
+ "\nSTATUS=$?\n"
+ "if [ $STATUS -ne 0 ]; then\n"
+ " exit $STATUS\n"
+ "fi");
exit:
- free(tar);
- return buf ? rstrcat(&buf,
- "\nSTATUS=$?\n"
- "if [ $STATUS -ne 0 ]; then\n"
- " exit $STATUS\n"
- "fi") : NULL;
+ return buf;
}
/**
diff --git a/macros.in b/macros.in
index 6177e6fec..99857b9e1 100644
--- a/macros.in
+++ b/macros.in
@@ -67,6 +67,7 @@
%__ld @__LD@
%__objdump @__OBJDUMP@
%__strip @__STRIP@
+%__rpmuncompress %{_rpmconfigdir}/rpmuncompress
%__find_debuginfo @__FIND_DEBUGINFO@
diff --git a/po/POTFILES.in b/po/POTFILES.in
index d507aca23..f8b5e49ba 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -99,3 +99,4 @@ sign/rpmsignfiles.c
tools/rpmdeps.c
tools/rpmgraph.c
tools/rpmlua.c
+tools/rpmuncompress.c
diff --git a/tests/rpmbuild.at b/tests/rpmbuild.at
index 5d762a97d..c15e6534c 100644
--- a/tests/rpmbuild.at
+++ b/tests/rpmbuild.at
@@ -1792,16 +1792,32 @@ AT_CLEANUP
# Check that rpmbuild aborts with missing Source
AT_SETUP([rpmbuild -ba missing source])
AT_KEYWORDS([build])
-AT_CHECK_UNQUOTED([
RPMDB_INIT
+runroot_other sed -i -e 's/^%patch0.*//g' /data/SPECS/hello.spec
+
+AT_CHECK_UNQUOTED([
+runroot rpmbuild \
+ --define "_sourcedir /notthere" \
+ --quiet -bb /data/SPECS/hello.spec 2> cmd.err
+ec=$?
+grep "^error: File" cmd.err >&2
+exit ${ec}
+],
+[1],
+[],
+[error: File /notthere/hello-1.0.tar.gz: No such file or directory
+])
+
+AT_CHECK_UNQUOTED([
runroot rpmbuild \
--define "_sourcedir /notthere" \
- -bb /data/SPECS/hello.spec
+ --quiet -bs /data/SPECS/hello.spec
],
[1],
[],
-[error: Bad source: /notthere/hello-1.0.tar.gz: No such file or directory
+[error: Bad file: /notthere/hello-1.0-modernize.patch: No such file or directory
+error: Bad file: /notthere/hello-1.0.tar.gz: No such file or directory
])
AT_CLEANUP
diff --git a/tools/rpmuncompress.c b/tools/rpmuncompress.c
new file mode 100644
index 000000000..950f23470
--- /dev/null
+++ b/tools/rpmuncompress.c
@@ -0,0 +1,156 @@
+#include "system.h"
+
+#include <popt.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <rpm/rpmcli.h>
+#include <rpm/rpmstring.h>
+
+#include "debug.h"
+
+static int verbose = 0;
+static int extract = 0;
+
+static struct poptOption optionsTable[] = {
+ { "extract", 'x', POPT_ARG_VAL, &extract, 1,
+ N_("extract an archive"), NULL },
+ { "verbose", 'v', POPT_ARG_VAL, &verbose, 1,
+ N_("provide more detailed output"), NULL },
+
+ POPT_AUTOALIAS
+ POPT_AUTOHELP
+ POPT_TABLEEND
+};
+
+/* XXX this is silly, merge with the doUntar() uncompress logic */
+static char *doUncompress(const char *fn)
+{
+ return rpmExpand("%{uncompress:", fn, "}", NULL);
+}
+
+static char *doUntar(const char *fn)
+{
+ char *buf = NULL;
+ char *tar = NULL;
+ const char *taropts = verbose ? "-xvvof" : "-xof";
+ rpmCompressedMagic compressed = COMPRESSED_NOT;
+
+ /* XXX On non-build parse's, file cannot be stat'd or read */
+ if (rpmFileIsCompressed(fn, &compressed)) {
+ goto exit;
+ }
+
+ tar = rpmGetPath("%{__tar}", NULL);
+ if (compressed != COMPRESSED_NOT) {
+ char *zipper = NULL;
+ const char *t = NULL;
+ int needtar = 1;
+ int needgemspec = 0;
+
+ switch (compressed) {
+ case COMPRESSED_NOT: /* XXX can't happen */
+ case COMPRESSED_OTHER:
+ t = "%{__gzip} -dc";
+ break;
+ case COMPRESSED_BZIP2:
+ t = "%{__bzip2} -dc";
+ break;
+ case COMPRESSED_ZIP:
+ if (verbose)
+ t = "%{__unzip}";
+ else
+ t = "%{__unzip} -qq";
+ needtar = 0;
+ break;
+ case COMPRESSED_LZMA:
+ case COMPRESSED_XZ:
+ t = "%{__xz} -dc";
+ break;
+ case COMPRESSED_LZIP:
+ t = "%{__lzip} -dc";
+ break;
+ case COMPRESSED_LRZIP:
+ t = "%{__lrzip} -dqo-";
+ break;
+ case COMPRESSED_7ZIP:
+ t = "%{__7zip} x";
+ needtar = 0;
+ break;
+ case COMPRESSED_ZSTD:
+ t = "%{__zstd} -dc";
+ break;
+ case COMPRESSED_GEM:
+ t = "%{__gem} unpack";
+ needtar = 0;
+ needgemspec = 1;
+ break;
+ }
+
+ zipper = rpmGetPath(t, NULL);
+ if (needtar) {
+ rasprintf(&buf, "%s '%s' | %s %s -", zipper, fn, tar, taropts);
+ } else if (needgemspec) {
+ size_t nvlen = strlen(fn) - 3;
+ char *gem = rpmGetPath("%{__gem}", NULL);
+ char *gemspec = NULL;
+ char gemnameversion[nvlen];
+
+ rstrlcpy(gemnameversion, fn, nvlen);
+ gemspec = rpmGetPath("", gemnameversion, ".gemspec", NULL);
+
+ rasprintf(&buf, "%s '%s' && %s spec '%s' --ruby > '%s'",
+ zipper, fn, gem, fn, gemspec);
+
+ free(gemspec);
+ free(gem);
+ } else {
+ rasprintf(&buf, "%s '%s'", zipper, fn);
+ }
+ free(zipper);
+ } else {
+ rasprintf(&buf, "%s %s '%s'", tar, taropts, fn);
+ }
+
+exit:
+ free(tar);
+ return buf;
+}
+
+int main(int argc, char *argv[])
+{
+ int ec = EXIT_FAILURE;
+ poptContext optCon = NULL;
+ const char *arg = NULL;
+
+ optCon = rpmcliInit(argc, argv, optionsTable);
+
+ if (optCon == NULL || ((arg = poptGetArg(optCon)) == NULL)) {
+ poptPrintUsage(optCon, stderr, 0);
+ goto exit;
+ }
+
+ char *cmd = extract ? doUntar(arg) : doUncompress(arg);
+ if (cmd) {
+ FILE *inp = NULL;
+
+ if (verbose)
+ fprintf(stderr, "%s\n", cmd);
+
+ inp = popen(cmd, "r");
+ if (inp) {
+ int status, c;
+ while ((c = fgetc(inp)) != EOF)
+ fputc(c, stdout);
+ status = pclose(inp);
+ if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
+ ec = EXIT_SUCCESS;
+ }
+ free(cmd);
+ }
+
+exit:
+ rpmcliFini(optCon);
+ return ec;
+}