From 46c329081f147d68ba38e7256481d8e432cac64c Mon Sep 17 00:00:00 2001 From: Peter Date: Sat, 5 Feb 2022 16:43:34 +0000 Subject: [PATCH] Fix `exiv2`: verbose extract stdout mutli-file (#2068) When using `exiv2 --verbose --extract` with stdout and multiple files, the output is concatenated together. --- exiv2.md | 2 +- src/exiv2.cpp | 35 +++++++++++++++------------ tests/bugfixes/github/test_pr_2068.py | 16 ++++++++++++ 3 files changed, 37 insertions(+), 16 deletions(-) create mode 100644 tests/bugfixes/github/test_pr_2068.py diff --git a/exiv2.md b/exiv2.md index c3134ad0..6049327f 100644 --- a/exiv2.md +++ b/exiv2.md @@ -660,7 +660,7 @@ Extract target(s) for the [extract](#ex_extract) action. Possible targets are: | C | Extract ICC profile, to a file called *\.icc* (see [ICC PROFILES](#icc_profiles)) | | X | Extract metadata to an XMP sidecar file, \.xmp. Other targets cannot be used with this, as only XMP data is written. Extracted XMP tags include those converted from Exif and IPTC | | XX | Extract "raw" metadata to a sidecar file, \.exv. The remaining targets determine which metadata to include, possible are Exif and IPTC (XMP is always included) | -| - | Output to stdout (see [--insert tgt2](#insert_tgt2) for an example of this feature). This argument ignores [--verbose](#verbose) | +| - | Output to stdout (see example in [--insert tgt2](#insert_tgt2)). This ignores [--verbose](#verbose) and only allows extracting from 1 file | To extract to a location other than the current directory, use [--location dir](#location_dir). diff --git a/src/exiv2.cpp b/src/exiv2.cpp index c353ea04..8478278e 100644 --- a/src/exiv2.cpp +++ b/src/exiv2.cpp @@ -159,23 +159,28 @@ int main(int argc, char* const argv[]) // Process all files int n = 1; int s = static_cast(params.files_.size()); - int w = s > 9 ? s > 99 ? 3 : 2 : 1; - for (auto&& file : params.files_) { - // If extracting to stdout then ignore verbose - if (params.verbose_ && !(params.action_ & Action::extract && params.target_ & Params::ctStdInOut)) { - std::cout << _("File") << " " << std::setw(w) << std::right << n++ << "/" << s << ": " << file - << std::endl; - } - task->setBinary(params.binary_); - int ret = task->run(file); - if (rc == 0) - rc = ret; + if (params.action_ & Action::extract && params.target_ & Params::ctStdInOut && s > 1) { + std::cerr << params.progname() << ": " << _("Only one file is allowed when extracting to stdout") << std::endl; + rc = 1; } + else { + int w = s > 9 ? s > 99 ? 3 : 2 : 1; + for (auto&& file : params.files_) { + // If extracting to stdout then ignore verbose + if (params.verbose_ && !(params.action_ & Action::extract && params.target_ & Params::ctStdInOut)) { + std::cout << _("File") << " " << std::setw(w) << std::right << n++ << "/" << s << ": " << file + << std::endl; + } + task->setBinary(params.binary_); + int ret = task->run(file); + if (rc == 0) + rc = ret; + } - taskFactory.cleanup(); - Params::cleanup(); - Exiv2::XmpParser::terminate(); - + taskFactory.cleanup(); + Params::cleanup(); + Exiv2::XmpParser::terminate(); + } } catch (const std::exception& exc) { std::cerr << "Uncaught exception: " << exc.what() << std::endl; rc = 1; diff --git a/tests/bugfixes/github/test_pr_2068.py b/tests/bugfixes/github/test_pr_2068.py new file mode 100644 index 00000000..d25c1860 --- /dev/null +++ b/tests/bugfixes/github/test_pr_2068.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- + +import system_tests +from system_tests import CaseMeta, path + +class TestVerboseExtractStdoutMultiFile(metaclass=CaseMeta): + + filename = path("$data_path/exiv2-empty.jpg") + commands = ["$exiv2 --verbose --extract X- $filename $filename"] + + stdout = [""""""] + + stderr = ["""exiv2: Only one file is allowed when extracting to stdout +"""] + retval = [1] +