diff --git a/client/config.c b/client/config.c index 4152d367..8ddcc7ae 100644 --- a/client/config.c +++ b/client/config.c @@ -31,7 +31,7 @@ TDNFConfGetRpmVerbosity( ) { rpmlogLvl nLogLevel = RPMLOG_INFO; - if(pTdnf) + if(pTdnf && pTdnf->pArgs->nRpmVerbosity >= 0) { nLogLevel = pTdnf->pArgs->nRpmVerbosity; } diff --git a/client/rpmtrans.c b/client/rpmtrans.c index 5efac025..f5d122ed 100644 --- a/client/rpmtrans.c +++ b/client/rpmtrans.c @@ -671,6 +671,7 @@ TDNFRunTransaction( uint32_t dwSkipSignature = 0; uint32_t dwSkipDigest = 0; int rc; + FD_t fdScript = NULL; if(!pTS || !pTdnf || !pTdnf->pConf || !pTdnf->pArgs) { @@ -692,6 +693,18 @@ TDNFRunTransaction( dwError = TDNFGetSkipDigestOption(pTdnf, &dwSkipDigest); BAIL_ON_TDNF_ERROR(dwError); + /* When json output is enabled redirect stdout from scripts to stderr + to not mess with the json syntax ("json decode failed at ...") */ + if (pTdnf->pArgs->nJsonOutput) { + fdScript = fdDup(STDERR_FILENO); + if (fdScript == NULL) { + pr_err("failed to create script output handle"); + dwError = ERROR_TDNF_RPMTS_FDDUP_FAILED; + BAIL_ON_TDNF_ERROR(dwError); + } + rpmtsSetScriptFd(pTS->pTS, fdScript); + } + //TODO do callbacks for output pr_info("Testing transaction\n"); @@ -741,6 +754,14 @@ TDNFRunTransaction( } cleanup: + if(pTS) { + rpmtsSetScriptFd(pTS->pTS, NULL); + } + if(fdScript) + { + Fclose(fdScript); + fdScript = NULL; + } return dwError; error: diff --git a/include/tdnferror.h b/include/tdnferror.h index 27745a78..12653d1c 100644 --- a/include/tdnferror.h +++ b/include/tdnferror.h @@ -153,6 +153,8 @@ extern "C" { #define ERROR_TDNF_SIZE_MISMATCH 1527 +#define ERROR_TDNF_RPMTS_FDDUP_FAILED 1528 + /* event context */ #define ERROR_TDNF_EVENT_CTXT_ITEM_NOT_FOUND 1551 #define ERROR_TDNF_EVENT_CTXT_ITEM_INVALID_TYPE 1552 diff --git a/pytests/repo/tdnf-verbose-scripts.spec b/pytests/repo/tdnf-verbose-scripts.spec new file mode 100644 index 00000000..4b1e2c71 --- /dev/null +++ b/pytests/repo/tdnf-verbose-scripts.spec @@ -0,0 +1,51 @@ +# +# tdnf test spec file +# +Summary: basic install test file. +Name: tdnf-verbose-scripts +Version: 1.0.1 +Release: 2 +Vendor: VMware, Inc. +Distribution: Photon +License: VMware +Url: http://www.vmware.com +Group: Applications/tdnftest + +%description +Part of tdnf test spec. Basic install/remove/upgrade test + +%prep + +%build + +%install +mkdir -p %_topdir/%buildroot/lib/systemd/system/ +echo %_topdir/%buildroot/lib/systemd/system/%{name}.service +cat << EOF >> %_topdir/%buildroot/lib/systemd/system/%{name}.service +[Unit] +Description=%{name}.service for rpm script test. + +EOF + +%post +echo "echo from post" +echo "echo to stderr from post" >&2 + +%postun +echo "echo from postun" +echo "echo to stderr from postun" >&2 + +%pre +echo "echo from pre" +echo "echo to stderr from pre" >&2 + +%preun +echo "echo from preun" +echo "echo to stderr from preun" >&2 + +%files +/lib/systemd/system/%{name}.service + +%changelog +* Tue Jul 11 2023 Oliver Kurth +- test script output redirection diff --git a/pytests/tests/test_json.py b/pytests/tests/test_json.py index 85101c69..553736a3 100644 --- a/pytests/tests/test_json.py +++ b/pytests/tests/test_json.py @@ -11,6 +11,9 @@ import os +PKGNAME_VERBOSE_SCRIPTS = "tdnf-verbose-scripts" + + @pytest.fixture(scope='function', autouse=True) def setup_test(utils): tdnfj = os.path.join(utils.config['bin_dir'], 'tdnfj') @@ -98,6 +101,43 @@ def test_erase(utils): assert pkg_found +# verbose rpm scriplets should not interfer with json output +def test_install_verbose(utils): + pkgname = PKGNAME_VERBOSE_SCRIPTS + utils.erase_package(pkgname) + ret = utils.run(['tdnf', + '-j', '-y', '--nogpgcheck', + 'install', pkgname]) + assert utils.check_package(pkgname) + install_info = json.loads("\n".join(ret['stdout'])) + + pkg_found = False + install_pkgs = install_info["Install"] + for p in install_pkgs: + if p['Name'] == pkgname: + pkg_found = True + break + assert pkg_found + + +def test_erase_verbose(utils): + pkgname = PKGNAME_VERBOSE_SCRIPTS + utils.install_package(pkgname) + ret = utils.run(['tdnf', + '-j', '-y', '--nogpgcheck', + 'erase', pkgname]) + assert not utils.check_package(pkgname) + install_info = json.loads("\n".join(ret['stdout'])) + + pkg_found = False + install_pkgs = install_info["Remove"] + for p in install_pkgs: + if p['Name'] == pkgname: + pkg_found = True + break + assert pkg_found + + def test_check_update(utils): ret = utils.run(['tdnf', '-j', 'check-update']) d = json.loads("\n".join(ret['stdout'])) diff --git a/tools/cli/lib/parseargs.c b/tools/cli/lib/parseargs.c index c740f410..9029c1bc 100644 --- a/tools/cli/lib/parseargs.c +++ b/tools/cli/lib/parseargs.c @@ -172,6 +172,8 @@ TDNFCliParseArgs( pCmdArgs->nArgc = argc; pCmdArgs->ppszArgv = argv; + pCmdArgs->nRpmVerbosity = -1; + opterr = 0;//tell getopt to not print errors while (1) { @@ -497,7 +499,7 @@ ParseRpmVerbosity( } } - *pnRpmVerbosity = TDNF_RPMLOG_ERR; + *pnRpmVerbosity = TDNF_RPMLOG_INFO; return dwError; }