[osmium-tool] 01/03: Add patch for libosmium 2.10.2 support.
Bas Couwenberg
sebastic at debian.org
Thu Nov 17 19:05:28 UTC 2016
This is an automated email from the git hooks/post-receive script.
sebastic pushed a commit to branch master
in repository osmium-tool.
commit 2e6e3b28ed81843b637c11340d9583ee17772473
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date: Thu Nov 17 19:44:41 2016 +0100
Add patch for libosmium 2.10.2 support.
---
debian/changelog | 6 +
debian/patches/libosmium-2.10.2.patch | 1336 +++++++++++++++++++++++++++++++++
debian/patches/series | 1 +
3 files changed, 1343 insertions(+)
diff --git a/debian/changelog b/debian/changelog
index 655b8ba..86f01ab 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+osmium-tool (1.4.0-3) UNRELEASED; urgency=medium
+
+ * Add patch for libosmium 2.10.2 support.
+
+ -- Bas Couwenberg <sebastic at debian.org> Thu, 17 Nov 2016 19:44:39 +0100
+
osmium-tool (1.4.0-2) unstable; urgency=medium
* Ignore test failures on problematic architectures.
diff --git a/debian/patches/libosmium-2.10.2.patch b/debian/patches/libosmium-2.10.2.patch
new file mode 100644
index 0000000..840b686
--- /dev/null
+++ b/debian/patches/libosmium-2.10.2.patch
@@ -0,0 +1,1336 @@
+Description: Add support for libosmium 2.10.2.
+Origin: https://github.com/osmcode/osmium-tool
+
+--- a/CHANGELOG.md
++++ b/CHANGELOG.md
+@@ -8,10 +8,28 @@ This project adheres to [Semantic Versio
+
+ ### Added
+
++- Add hint to error message about `--overwrite` option when trying to open
++ an existing file.
++- Check the required libosmium version in CMake build.
++
+ ### Changed
+
++- Add --ignore-missing-nodes to `add-locations-to-ways` subcommand. If this
++ is not set, the command will now fail if there are missing nodes needed
++ for ways.
++- The `check-refs` and `getid` subcommands now use the IdSet class from the
++ newest libosmium making them more efficient (especially on very large input
++ files).
++- Improved error messages for low-level errors.
++
+ ### Fixed
+
++- Consistently handle `--output-header` option in all commands that create
++ standard OSM files.
++- Handling of some output options was not correct in `diff` command. They
++ do now what is documented and it is documented what they do.
++- Progress bar and output from verbose mode will now be kept separate.
++
+
+ ## [1.4.0] - 2016-09-15
+
+@@ -27,7 +45,7 @@ This project adheres to [Semantic Versio
+ shown in verbose mode.
+ - Added `iwyu` target to CMake config.
+ - Progress bars will be shown on some commands. (This is configurable at
+- run time with the --progress and --no-progress options.)
++ run time with the `--progress` and `--no-progress` options.)
+
+ ### Changed
+
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -44,7 +44,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
+ find_package(Boost 1.55.0 REQUIRED COMPONENTS program_options)
+ include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
+
+-find_package(Osmium REQUIRED COMPONENTS io)
++find_package(Osmium 2.10.2 REQUIRED COMPONENTS io)
+ include_directories(SYSTEM ${OSMIUM_INCLUDE_DIRS})
+
+
+--- a/README.md
++++ b/README.md
+@@ -4,8 +4,8 @@
+ A multipurpose command line tool for working with OpenStreetMap data based on
+ the Osmium library.
+
+-[![Build Status](https://secure.travis-ci.org/osmcode/osmium-tool.png)](http://travis-ci.org/osmcode/osmium-tool)
+-[![Build Status](https://ci.appveyor.com/api/projects/status/ttem4j2gxa64p3w8?svg=true)](https://ci.appveyor.com/project/Mapbox/osmium-tool)
++[![Build Status](https://secure.travis-ci.org/osmcode/osmium-tool.svg)](http://travis-ci.org/osmcode/osmium-tool)
++[![Build Status](https://ci.appveyor.com/api/projects/status/github/osmcode/osmium-tool?svg=true)](https://ci.appveyor.com/project/Mapbox/osmium-tool)
+
+ ## Prerequisites
+
+@@ -14,11 +14,11 @@ later are known to work. It also works o
+
+ You also need the following libraries:
+
+- Libosmium (>= 2.9.0)
++ Libosmium (>= 2.10.2)
+ http://osmcode.org/libosmium
+ Debian/Ubuntu: libosmium2-dev
+
+- Protozero (>= 1.4.0)
++ Protozero (>= 1.4.4)
+ This is included in the libosmium repository and might or might not
+ have been installed with it. See the libosmium README.
+ https://github.com/mapbox/protozero
+@@ -112,7 +112,7 @@ More extensive tests of the libosmium I/
+
+ ## License
+
+-Copyright (C) 2013-2016 Jochen Topf <jochen at topf.org>
++Copyright (C) 2013-2016 Jochen Topf (jochen at topf.org)
+
+ This program is available under the GNU GENERAL PUBLIC LICENSE Version 3.
+ See the file LICENSE.txt for the complete text of the license.
+@@ -120,5 +120,5 @@ See the file LICENSE.txt for the complet
+
+ ## Authors
+
+-This program was written and is maintained by Jochen Topf <jochen at topf.org>.
++This program was written and is maintained by Jochen Topf (jochen at topf.org).
+
+--- a/cmake/FindOsmium.cmake
++++ b/cmake/FindOsmium.cmake
+@@ -2,8 +2,8 @@
+ #
+ # FindOsmium.cmake
+ #
+-# Find the Libosmium headers and, optionally, several components needed for
+-# different Libosmium functions.
++# Find the Libosmium headers and, optionally, several components needed
++# for different Libosmium functions.
+ #
+ #----------------------------------------------------------------------
+ #
+@@ -18,9 +18,12 @@
+ #
+ # Then add the following in your CMakeLists.txt:
+ #
+-# find_package(Osmium REQUIRED COMPONENTS <XXX>)
++# find_package(Osmium [version] REQUIRED COMPONENTS <XXX>)
+ # include_directories(SYSTEM ${OSMIUM_INCLUDE_DIRS})
+ #
++# The version number is optional. If it is not set, any version of
++# libosmium will do.
++#
+ # For the <XXX> substitute a space separated list of one or more of the
+ # following components:
+ #
+@@ -51,10 +54,9 @@
+ #
+ #----------------------------------------------------------------------
+
+-# Look for the header file.
+-find_path(OSMIUM_INCLUDE_DIR osmium/osm.hpp
+- PATH_SUFFIXES include
+- PATHS
++# This is the list of directories where we look for osmium and protozero
++# includes.
++set(_osmium_include_path
+ ../libosmium
+ ~/Library/Frameworks
+ /Library/Frameworks
+@@ -62,6 +64,22 @@ find_path(OSMIUM_INCLUDE_DIR osmium/osm.
+ /opt
+ )
+
++# Look for the header file.
++find_path(OSMIUM_INCLUDE_DIR osmium/version.hpp
++ PATH_SUFFIXES include
++ PATHS ${_osmium_include_path}
++)
++
++# Check libosmium version number
++if(Osmium_FIND_VERSION)
++ file(STRINGS "${OSMIUM_INCLUDE_DIR}/osmium/version.hpp" _libosmium_version_define REGEX "#define LIBOSMIUM_VERSION_STRING")
++ if("${_libosmium_version_define}" MATCHES "#define LIBOSMIUM_VERSION_STRING \"([0-9.]+)\"")
++ set(_libosmium_version "${CMAKE_MATCH_1}")
++ else()
++ set(_libosmium_version "unknown")
++ endif()
++endif()
++
+ set(OSMIUM_INCLUDE_DIRS "${OSMIUM_INCLUDE_DIR}")
+
+ #----------------------------------------------------------------------
+@@ -95,17 +113,31 @@ if(Osmium_USE_PBF)
+ find_package(ZLIB)
+ find_package(Threads)
+
+- list(APPEND OSMIUM_EXTRA_FIND_VARS ZLIB_FOUND Threads_FOUND)
+- if(ZLIB_FOUND AND Threads_FOUND)
++ message(STATUS "Looking for protozero")
++ find_path(PROTOZERO_INCLUDE_DIR protozero/version.hpp
++ PATH_SUFFIXES include
++ PATHS ${_osmium_include_path}
++ ${OSMIUM_INCLUDE_DIR}
++ )
++ if(PROTOZERO_INCLUDE_DIR)
++ message(STATUS "Looking for protozero - found")
++ else()
++ message(STATUS "Looking for protozero - not found")
++ endif()
++
++ list(APPEND OSMIUM_EXTRA_FIND_VARS ZLIB_FOUND Threads_FOUND PROTOZERO_INCLUDE_DIR)
++ if(ZLIB_FOUND AND Threads_FOUND AND PROTOZERO_INCLUDE_DIR)
+ list(APPEND OSMIUM_PBF_LIBRARIES
+ ${ZLIB_LIBRARIES}
+ ${CMAKE_THREAD_LIBS_INIT}
+ )
+ if(WIN32)
++ # This is needed for the ntohl() function
+ list(APPEND OSMIUM_PBF_LIBRARIES ws2_32)
+ endif()
+ list(APPEND OSMIUM_INCLUDE_DIRS
+ ${ZLIB_INCLUDE_DIR}
++ ${PROTOZERO_INCLUDE_DIR}
+ )
+ else()
+ message(WARNING "Osmium: Can not find some libraries for PBF input/output, please install them or configure the paths.")
+@@ -203,7 +235,7 @@ if(Osmium_USE_SPARSEHASH)
+ if(SPARSEHASH_INCLUDE_DIR)
+ # Find size of sparsetable::size_type. This does not work on older
+ # CMake versions because they can do this check only in C, not in C++.
+- if (NOT CMAKE_VERSION VERSION_LESS 3.0)
++ if(NOT CMAKE_VERSION VERSION_LESS 3.0)
+ include(CheckTypeSize)
+ set(CMAKE_REQUIRED_INCLUDES ${SPARSEHASH_INCLUDE_DIR})
+ set(CMAKE_EXTRA_INCLUDE_FILES "google/sparsetable")
+@@ -253,13 +285,15 @@ endif()
+ # Check that all required libraries are available
+ #
+ #----------------------------------------------------------------------
+-if (OSMIUM_EXTRA_FIND_VARS)
++if(OSMIUM_EXTRA_FIND_VARS)
+ list(REMOVE_DUPLICATES OSMIUM_EXTRA_FIND_VARS)
+ endif()
+-# Handle the QUIETLY and REQUIRED arguments and set OSMIUM_FOUND to TRUE if
+-# all listed variables are TRUE.
++# Handle the QUIETLY and REQUIRED arguments and the optional version check
++# and set OSMIUM_FOUND to TRUE if all listed variables are TRUE.
+ include(FindPackageHandleStandardArgs)
+-find_package_handle_standard_args(Osmium REQUIRED_VARS OSMIUM_INCLUDE_DIR ${OSMIUM_EXTRA_FIND_VARS})
++find_package_handle_standard_args(Osmium
++ REQUIRED_VARS OSMIUM_INCLUDE_DIR ${OSMIUM_EXTRA_FIND_VARS}
++ VERSION_VAR _libosmium_version)
+ unset(OSMIUM_EXTRA_FIND_VARS)
+
+ #----------------------------------------------------------------------
+--- a/man/osmium-add-locations-to-ways.md
++++ b/man/osmium-add-locations-to-ways.md
+@@ -16,6 +16,10 @@ IDs of the nodes. This program will copy
+ taking the locations from the nodes and adding them to the ways. This makes
+ it easier for other programs to assemble the way geometries.
+
++The input file must contain all nodes needed for the ways, otherwise there will
++be an error. You can change this behaviour using the `--ignore-missing-nodes`
++option.
++
+ Nodes without any tags will not be copied (unless the **--keep-untagged-nodes**,
+ **-n** option is used). The size of the output file will be similar or a bit
+ smaller than the input file (unless the **--keep-untagged-nodes**,
+@@ -46,6 +50,11 @@ This program will not work on full histo
+ -n, --keep-untagged-nodes
+ : Keep the untagged nodes in the output file.
+
++--ignore-missing-nodes
++: If this is not set a missing node needed for a way results in an error.
++ If this is set, errors are ignored and the way will have an invalid
++ location set for the missing node.
++
+ @MAN_COMMON_OPTIONS@
+ @MAN_PROGRESS_OPTIONS@
+ @MAN_INPUT_OPTIONS@
+--- a/man/osmium-getid.md
++++ b/man/osmium-getid.md
+@@ -58,6 +58,8 @@ If referenced objects are missing from t
+ of those objects is written out to *stderr* at the end of the program unless
+ the **-H**, **--history** option was given.
+
++This command will not work with negative IDs.
++
+
+ # OPTIONS
+
+--- a/src/cmd.hpp
++++ b/src/cmd.hpp
+@@ -47,6 +47,10 @@ const char* yes_no(bool choice) noexcept
+ void warning(const char* text);
+ std::size_t file_size_sum(std::vector<osmium::io::File> files);
+
++namespace osmium { namespace io {
++ class Header;
++}}
++
+ /**
+ * Virtual base class for commands that can be called from the command line.
+ */
+@@ -62,7 +66,6 @@ class Command {
+
+ protected:
+
+- bool m_debug {false};
+ osmium::util::VerboseOutput m_vout {false};
+
+ public:
+@@ -175,10 +178,11 @@ public:
+
+ class with_osm_output {
+
+-protected:
+-
+ std::string m_generator;
+ std::vector<std::string> m_output_headers;
++
++protected:
++
+ std::string m_output_filename = "-"; // default: stdout
+ std::string m_output_format;
+ osmium::io::File m_output_file;
+@@ -202,13 +206,7 @@ public:
+ return m_output_file;
+ }
+
+- const std::string& generator() const {
+- return m_generator;
+- }
+-
+- const std::vector<std::string>& output_headers() const {
+- return m_output_headers;
+- }
++ void setup_header(osmium::io::Header& header) const;
+
+ osmium::io::overwrite output_overwrite() const {
+ return m_output_overwrite;
+--- a/src/command_add_locations_to_ways.cpp
++++ b/src/command_add_locations_to_ways.cpp
+@@ -54,6 +54,7 @@ bool CommandAddLocationsToWays::setup(co
+ ("index-type,i", po::value<std::string>()->default_value(default_index_type), "Index type to use")
+ ("show-index-types,I", "Show available index types")
+ ("keep-untagged-nodes,n", "Keep untagged nodes")
++ ("ignore-missing-nodes", "Ignore missing nodes")
+ ;
+
+ po::options_description opts_common{add_common_options()};
+@@ -101,6 +102,10 @@ bool CommandAddLocationsToWays::setup(co
+ m_keep_untagged_nodes = true;
+ }
+
++ if (vm.count("ignore-missing-nodes")) {
++ m_ignore_missing_nodes = true;
++ }
++
+ return true;
+ }
+
+@@ -114,13 +119,6 @@ void CommandAddLocationsToWays::show_arg
+ m_vout << "\n";
+ }
+
+-void CommandAddLocationsToWays::setup_header(osmium::io::Header& header) const {
+- header.set("generator", m_generator);
+- for (const auto& h : m_output_headers) {
+- header.set(h);
+- }
+-}
+-
+ void CommandAddLocationsToWays::copy_data(osmium::ProgressBar& progress_bar, osmium::io::Reader& reader, osmium::io::Writer& writer, location_handler_type& location_handler) {
+ while (osmium::memory::Buffer buffer = reader.read()) {
+ progress_bar.update(reader.offset());
+@@ -142,7 +140,10 @@ bool CommandAddLocationsToWays::run() {
+ const auto& map_factory = osmium::index::MapFactory<osmium::unsigned_object_id_type, osmium::Location>::instance();
+ auto location_index = map_factory.create_map(m_index_type_name);
+ location_handler_type location_handler(*location_index);
+- location_handler.ignore_errors(); // XXX
++
++ if (m_ignore_missing_nodes) {
++ location_handler.ignore_errors();
++ }
+
+ m_output_file.set("locations_on_ways");
+
+@@ -166,6 +167,7 @@ bool CommandAddLocationsToWays::run() {
+
+ osmium::ProgressBar progress_bar{file_size_sum(m_input_files), display_progress()};
+ for (const auto& input_file : m_input_files) {
++ progress_bar.remove();
+ m_vout << "Copying input file '" << input_file.filename() << "'\n";
+ osmium::io::Reader reader(input_file);
+
+--- a/src/command_add_locations_to_ways.hpp
++++ b/src/command_add_locations_to_ways.hpp
+@@ -45,11 +45,11 @@ using location_handler_type = osmium::ha
+
+ class CommandAddLocationsToWays : public Command, public with_multiple_osm_inputs, public with_osm_output {
+
+- void setup_header(osmium::io::Header& header) const;
+ void copy_data(osmium::ProgressBar& progress_bar, osmium::io::Reader& reader, osmium::io::Writer& writer, location_handler_type& location_handler);
+
+ std::string m_index_type_name;
+ bool m_keep_untagged_nodes = false;
++ bool m_ignore_missing_nodes = false;
+
+ public:
+
+--- a/src/command_apply_changes.cpp
++++ b/src/command_apply_changes.cpp
+@@ -169,7 +169,7 @@ bool CommandApplyChanges::run() {
+ osmium::io::Reader reader{m_input_file, osmium::osm_entity_bits::object};
+
+ osmium::io::Header header{reader.header()};
+- header.set("generator", m_generator);
++ setup_header(header);
+
+ m_vout << "Opening output file...\n";
+ osmium::io::Writer writer{m_output_file, header, m_output_overwrite, m_fsync};
+--- a/src/command_cat.cpp
++++ b/src/command_cat.cpp
+@@ -81,13 +81,6 @@ void CommandCat::show_arguments() {
+ show_object_types(m_vout);
+ }
+
+-void CommandCat::setup_header(osmium::io::Header& header) const {
+- header.set("generator", m_generator);
+- for (const auto& h : m_output_headers) {
+- header.set(h);
+- }
+-}
+-
+ bool CommandCat::run() {
+ if (m_input_files.size() == 1) { // single input file
+ m_vout << "Copying input file '" << m_input_files[0].filename() << "'\n";
+@@ -112,6 +105,7 @@ bool CommandCat::run() {
+
+ osmium::ProgressBar progress_bar{file_size_sum(m_input_files), display_progress()};
+ for (const auto& input_file : m_input_files) {
++ progress_bar.remove();
+ m_vout << "Copying input file '" << input_file.filename() << "'\n";
+ osmium::io::Reader reader{input_file, osm_entity_bits()};
+ while (osmium::memory::Buffer buffer = reader.read()) {
+--- a/src/command_cat.hpp
++++ b/src/command_cat.hpp
+@@ -34,8 +34,6 @@ namespace osmium { namespace io {
+
+ class CommandCat : public Command, public with_multiple_osm_inputs, public with_osm_output {
+
+- void setup_header(osmium::io::Header& header) const;
+-
+ public:
+
+ CommandCat() = default;
+--- a/src/command_changeset_filter.cpp
++++ b/src/command_changeset_filter.cpp
+@@ -205,7 +205,7 @@ bool CommandChangesetFilter::run() {
+ auto input = osmium::io::make_input_iterator_range<osmium::Changeset>(reader);
+
+ osmium::io::Header header{reader.header()};
+- header.set("generator", m_generator);
++ setup_header(header);
+
+ m_vout << "Opening output file...\n";
+ osmium::io::Writer writer{m_output_file, header, m_output_overwrite, m_fsync};
+--- a/src/command_check_refs.cpp
++++ b/src/command_check_refs.cpp
+@@ -31,7 +31,7 @@ along with this program. If not, see <h
+
+ #include <osmium/handler.hpp>
+ #include <osmium/handler/check_order.hpp>
+-#include <osmium/index/bool_vector.hpp>
++#include <osmium/index/id_set.hpp>
+ #include <osmium/io/reader.hpp>
+ #include <osmium/osm.hpp>
+ #include <osmium/util/progress_bar.hpp>
+@@ -92,10 +92,10 @@ void CommandCheckRefs::show_arguments()
+
+ class RefCheckHandler : public osmium::handler::Handler {
+
+- osmium::index::BoolVector<osmium::unsigned_object_id_type> m_nodes;
+- osmium::index::BoolVector<osmium::unsigned_object_id_type> m_ways;
++ osmium::index::IdSetDense<osmium::unsigned_object_id_type> m_nodes;
++ osmium::index::IdSetDense<osmium::unsigned_object_id_type> m_ways;
++ osmium::index::IdSetDense<osmium::unsigned_object_id_type> m_relations;
+
+- std::vector<uint32_t> m_relation_ids;
+ std::vector<std::pair<uint32_t, uint32_t>> m_relation_refs;
+
+ osmium::handler::CheckOrder m_check_order;
+@@ -109,13 +109,15 @@ class RefCheckHandler : public osmium::h
+ uint64_t m_missing_ways_in_relations = 0;
+
+ osmium::util::VerboseOutput& m_vout;
++ osmium::ProgressBar& m_progress_bar;
+ bool m_show_ids;
+ bool m_check_relations;
+
+ public:
+
+- RefCheckHandler(osmium::util::VerboseOutput& vout, bool show_ids, bool check_relations) :
++ RefCheckHandler(osmium::util::VerboseOutput& vout, osmium::ProgressBar& progress_bar, bool show_ids, bool check_relations) :
+ m_vout(vout),
++ m_progress_bar(progress_bar),
+ m_show_ids(show_ids),
+ m_check_relations(check_relations) {
+ }
+@@ -153,7 +155,7 @@ public:
+
+ m_relation_refs.erase(
+ std::remove_if(m_relation_refs.begin(), m_relation_refs.end(), [this](std::pair<uint32_t, uint32_t> refs){
+- return std::binary_search(m_relation_ids.begin(), m_relation_ids.end(), refs.first);
++ return m_relations.get(refs.first);
+ }),
+ m_relation_refs.end()
+ );
+@@ -170,6 +172,7 @@ public:
+ m_check_order.node(node);
+
+ if (m_node_count == 0) {
++ m_progress_bar.remove();
+ m_vout << "Reading nodes...\n";
+ }
+ ++m_node_count;
+@@ -181,6 +184,7 @@ public:
+ m_check_order.way(way);
+
+ if (m_way_count == 0) {
++ m_progress_bar.remove();
+ m_vout << "Reading ways...\n";
+ }
+ ++m_way_count;
+@@ -203,12 +207,13 @@ public:
+ m_check_order.relation(relation);
+
+ if (m_relation_count == 0) {
++ m_progress_bar.remove();
+ m_vout << "Reading relations...\n";
+ }
+ ++m_relation_count;
+
+ if (m_check_relations) {
+- m_relation_ids.push_back(uint32_t(relation.id()));
++ m_relations.set(relation.positive_id());
+ for (const auto& member : relation.members()) {
+ switch (member.type()) {
+ case osmium::item_type::node:
+@@ -230,7 +235,7 @@ public:
+ }
+ break;
+ case osmium::item_type::relation:
+- if (member.ref() > relation.id() || !std::binary_search(m_relation_ids.begin(), m_relation_ids.end(), uint32_t(member.ref()))) {
++ if (member.ref() > relation.id() || !m_relations.get(member.positive_ref())) {
+ m_relation_refs.emplace_back(uint32_t(member.ref()), uint32_t(relation.id()));
+ }
+ break;
+@@ -251,9 +256,9 @@ public:
+
+ bool CommandCheckRefs::run() {
+ osmium::io::Reader reader{m_input_file};
+- RefCheckHandler handler{m_vout, m_show_ids, m_check_relations};
+-
+ osmium::ProgressBar progress_bar{reader.file_size(), display_progress()};
++ RefCheckHandler handler{m_vout, progress_bar, m_show_ids, m_check_relations};
++
+ while (osmium::memory::Buffer buffer = reader.read()) {
+ progress_bar.update(reader.offset());
+ osmium::apply(buffer, handler);
+@@ -270,7 +275,9 @@ bool CommandCheckRefs::run() {
+ }
+ }
+
+- std::cerr << "There are " << handler.node_count() << " nodes, " << handler.way_count() << " ways, and " << handler.relation_count() << " relations in this file.\n";
++ std::cerr << "There are " << handler.node_count() << " nodes, "
++ << handler.way_count() << " ways, and "
++ << handler.relation_count() << " relations in this file.\n";
+
+ if (m_check_relations) {
+ std::cerr << "Nodes in ways missing: " << handler.missing_nodes_in_ways() << "\n";
+--- a/src/command_derive_changes.cpp
++++ b/src/command_derive_changes.cpp
+@@ -143,8 +143,10 @@ bool CommandDeriveChanges::run() {
+ if (m_output_file.format() != osmium::io::file_format::xml || !m_output_file.is_true("xml_change_format")) {
+ warning("Output format chosen is not the XML change format. Use .osc(.gz|bz2) as suffix or -f option.\n");
+ }
++
+ osmium::io::Header header;
+- header.set("generator", m_generator);
++ setup_header(header);
++
+ osmium::io::Writer writer{m_output_file, header};
+
+ m_vout << "Deriving changes...\n";
+--- a/src/command_diff.cpp
++++ b/src/command_diff.cpp
+@@ -49,15 +49,17 @@ along with this program. If not, see <h
+ bool CommandDiff::setup(const std::vector<std::string>& arguments) {
+ po::options_description opts_cmd{"COMMAND OPTIONS"};
+ opts_cmd.add_options()
+- ("suppress-common,c", "Suppress common objects")
++ ("object-type,t", po::value<std::vector<std::string>>(), "Read only objects of given type (node, way, relation)")
++ ("output,o", po::value<std::string>(), "Output file")
++ ("output-format,f", po::value<std::string>(), "Format of output file")
++ ("overwrite,O", "Allow existing output file to be overwritten")
+ ("quiet,q", "Report only when files differ")
+ ("summary,s", "Show summary on STDERR")
+- ("object-type,t", po::value<std::vector<std::string>>(), "Read only objects of given type (node, way, relation)")
++ ("suppress-common,c", "Suppress common objects")
+ ;
+
+ po::options_description opts_common{add_common_options()};
+ po::options_description opts_input{add_multiple_inputs_options()};
+- po::options_description opts_output{add_output_options()};
+
+ po::options_description hidden;
+ hidden.add_options()
+@@ -65,7 +67,7 @@ bool CommandDiff::setup(const std::vecto
+ ;
+
+ po::options_description desc;
+- desc.add(opts_cmd).add(opts_common).add(opts_input).add(opts_output);
++ desc.add(opts_cmd).add(opts_common).add(opts_input);
+
+ po::options_description parsed_options;
+ parsed_options.add(desc).add(hidden);
+@@ -93,24 +95,16 @@ bool CommandDiff::setup(const std::vecto
+ m_output_format = vm["output-format"].as<std::string>();
+ }
+
+- if (vm.count("output-header")) {
+- m_output_headers = vm["output-header"].as<std::vector<std::string>>();
+- }
+-
+ if (vm.count("overwrite")) {
+ m_output_overwrite = osmium::io::overwrite::allow;
+ }
+
+- if (vm.count("fsync")) {
+- m_fsync = osmium::io::fsync::yes;
+- }
+-
+ if (vm.count("summary")) {
+ m_show_summary = true;
+ }
+
+ if (vm.count("quiet")) {
+- if (vm.count("output") || vm.count("output-format") || vm.count("output-header") || vm.count("overwrite") || vm.count("fsync") || vm.count("suppress-common")) {
++ if (vm.count("output") || vm.count("output-format") || vm.count("overwrite") || vm.count("suppress-common")) {
+ throw argument_error("Do not use --quiet/-q with any of the output options.");
+ }
+ m_output_action = "none";
+@@ -218,8 +212,8 @@ class OutputActionOSM : public OutputAct
+
+ public:
+
+- OutputActionOSM(const osmium::io::File& file) :
+- m_writer(file) {
++ OutputActionOSM(const osmium::io::File& file, osmium::io::overwrite ow) :
++ m_writer(file, ow) {
+ }
+
+ void left(osmium::OSMObject& object) override {
+@@ -254,11 +248,11 @@ bool CommandDiff::run() {
+ std::unique_ptr<OutputAction> action;
+
+ if (m_output_action == "compact") {
+- int fd = osmium::io::detail::open_for_writing(m_output_filename, m_output_overwrite);
++ const int fd = osmium::io::detail::open_for_writing(m_output_filename, m_output_overwrite);
+ action.reset(new OutputActionCompact{fd});
+ } else if (m_output_action == "osm") {
+ m_output_file.set("diff");
+- action.reset(new OutputActionOSM{m_output_file});
++ action.reset(new OutputActionOSM{m_output_file, m_output_overwrite});
+ }
+
+ uint64_t count_left = 0;
+--- a/src/command_fileinfo.cpp
++++ b/src/command_fileinfo.cpp
+@@ -157,7 +157,7 @@ off_t filesize(const std::string& filena
+
+ struct stat s;
+ if (::stat(filename.c_str(), &s) == -1) {
+- throw std::system_error{errno, std::system_category(), "stat failed"};
++ throw std::system_error{errno, std::system_category(), std::string{"Could not get file size of file '"} + filename + "'"};
+ }
+
+ return s.st_size;
+--- a/src/command_getid.cpp
++++ b/src/command_getid.cpp
+@@ -44,17 +44,12 @@ along with this program. If not, see <h
+ #include "command_getid.hpp"
+ #include "exception.hpp"
+
+-std::set<osmium::object_id_type>& CommandGetId::ids(osmium::item_type type) noexcept {
+- return m_ids[osmium::item_type_to_nwr_index(type)];
+-}
+-
+-const std::set<osmium::object_id_type>& CommandGetId::ids(osmium::item_type type) const noexcept {
+- return m_ids[osmium::item_type_to_nwr_index(type)];
+-}
+-
+ void CommandGetId::parse_and_add_id(const std::string& s) {
+ auto p = osmium::string_to_object_id(s.c_str(), osmium::osm_entity_bits::nwr, m_default_item_type);
+- ids(p.first).insert(p.second);
++ if (p.second < 0) {
++ throw std::runtime_error("osmium-getid does not work with negative IDs");
++ }
++ m_ids(p.first).set(p.second);
+ }
+
+ void CommandGetId::read_id_file(std::istream& stream) {
+@@ -71,15 +66,15 @@ void CommandGetId::read_id_file(std::ist
+ }
+
+ bool CommandGetId::no_ids() const {
+- return ids(osmium::item_type::node).empty() &&
+- ids(osmium::item_type::way).empty() &&
+- ids(osmium::item_type::relation).empty();
++ return m_ids(osmium::item_type::node).empty() &&
++ m_ids(osmium::item_type::way).empty() &&
++ m_ids(osmium::item_type::relation).empty();
+ }
+
+ std::size_t CommandGetId::count_ids() const {
+- return ids(osmium::item_type::node).size() +
+- ids(osmium::item_type::way).size() +
+- ids(osmium::item_type::relation).size();
++ return m_ids(osmium::item_type::node).size() +
++ m_ids(osmium::item_type::way).size() +
++ m_ids(osmium::item_type::relation).size();
+ }
+
+ bool CommandGetId::setup(const std::vector<std::string>& arguments) {
+@@ -203,37 +198,37 @@ void CommandGetId::show_arguments() {
+ if (m_verbose_ids) {
+ m_vout << " looking for these ids:\n";
+ m_vout << " nodes:";
+- for (osmium::object_id_type id : ids(osmium::item_type::node)) {
++ for (osmium::object_id_type id : m_ids(osmium::item_type::node)) {
+ m_vout << " " << id;
+ }
+ m_vout << "\n";
+ m_vout << " ways:";
+- for (osmium::object_id_type id : ids(osmium::item_type::way)) {
++ for (osmium::object_id_type id : m_ids(osmium::item_type::way)) {
+ m_vout << " " << id;
+ }
+ m_vout << "\n";
+ m_vout << " relations:";
+- for (osmium::object_id_type id : ids(osmium::item_type::relation)) {
++ for (osmium::object_id_type id : m_ids(osmium::item_type::relation)) {
+ m_vout << " " << id;
+ }
+ m_vout << "\n";
+ } else {
+- m_vout << " looking for " << ids(osmium::item_type::node).size() << " node ID(s), "
+- << ids(osmium::item_type::way).size() << " way ID(s), and "
+- << ids(osmium::item_type::relation).size() << " relation ID(s)\n";
++ m_vout << " looking for " << m_ids(osmium::item_type::node).size() << " node ID(s), "
++ << m_ids(osmium::item_type::way).size() << " way ID(s), and "
++ << m_ids(osmium::item_type::relation).size() << " relation ID(s)\n";
+ }
+ }
+
+ osmium::osm_entity_bits::type CommandGetId::get_needed_types() const {
+ osmium::osm_entity_bits::type types = osmium::osm_entity_bits::nothing;
+
+- if (! ids(osmium::item_type::node).empty()) {
++ if (! m_ids(osmium::item_type::node).empty()) {
+ types |= osmium::osm_entity_bits::node;
+ }
+- if (! ids(osmium::item_type::way).empty()) {
++ if (! m_ids(osmium::item_type::way).empty()) {
+ types |= osmium::osm_entity_bits::way;
+ }
+- if (! ids(osmium::item_type::relation).empty()) {
++ if (! m_ids(osmium::item_type::relation).empty()) {
+ types |= osmium::osm_entity_bits::relation;
+ }
+
+@@ -242,17 +237,17 @@ osmium::osm_entity_bits::type CommandGet
+
+ void CommandGetId::add_nodes(const osmium::Way& way) {
+ for (const auto& nr : way.nodes()) {
+- ids(osmium::item_type::node).insert(nr.ref());
++ m_ids(osmium::item_type::node).set(nr.positive_ref());
+ }
+ }
+
+ void CommandGetId::add_members(const osmium::Relation& relation) {
+ for (const auto& member : relation.members()) {
+- ids(member.type()).insert(member.ref());
++ m_ids(member.type()).set(member.positive_ref());
+ }
+ }
+
+-static void print_missing_ids(const char* type, std::set<osmium::object_id_type>& set) {
++static void print_missing_ids(const char* type, const osmium::index::IdSetDense<osmium::unsigned_object_id_type>& set) {
+ if (set.empty()) {
+ return;
+ }
+@@ -268,7 +263,7 @@ void CommandGetId::read_id_osm_file(cons
+ osmium::io::Reader reader{file_name, osmium::osm_entity_bits::object};
+ while (osmium::memory::Buffer buffer = reader.read()) {
+ for (const auto& object : buffer.select<osmium::OSMObject>()) {
+- ids(object.type()).insert(object.id());
++ m_ids(object.type()).set(object.positive_id());
+ if (object.type() == osmium::item_type::way) {
+ add_nodes(static_cast<const osmium::Way&>(object));
+ } else if (object.type() == osmium::item_type::relation) {
+@@ -282,8 +277,7 @@ void CommandGetId::read_id_osm_file(cons
+ void CommandGetId::mark_rel_ids(const std::multimap<osmium::object_id_type, osmium::object_id_type>& rel_in_rel, osmium::object_id_type id) {
+ auto range = rel_in_rel.equal_range(id);
+ for (auto it = range.first; it != range.second; ++it) {
+- if (ids(osmium::item_type::relation).count(it->second) == 0) {
+- ids(osmium::item_type::relation).insert(it->second);
++ if (m_ids(osmium::item_type::relation).check_and_set(it->second)) {
+ mark_rel_ids(rel_in_rel, it->second);
+ }
+ }
+@@ -299,11 +293,11 @@ bool CommandGetId::find_relations_in_rel
+ for (const auto& member : relation.members()) {
+ if (member.type() == osmium::item_type::relation) {
+ rel_in_rel.emplace(relation.id(), member.ref());
+- } else if (ids(osmium::item_type::relation).count(relation.id())) {
++ } else if (m_ids(osmium::item_type::relation).get(relation.positive_id())) {
+ if (member.type() == osmium::item_type::node) {
+- ids(osmium::item_type::node).insert(member.ref());
++ m_ids(osmium::item_type::node).set(member.positive_ref());
+ } else if (member.type() == osmium::item_type::way) {
+- ids(osmium::item_type::way).insert(member.ref());
++ m_ids(osmium::item_type::way).set(member.positive_ref());
+ }
+ }
+ }
+@@ -315,7 +309,7 @@ bool CommandGetId::find_relations_in_rel
+ return false;
+ }
+
+- for (const osmium::object_id_type id : ids(osmium::item_type::relation)) {
++ for (const osmium::unsigned_object_id_type id : m_ids(osmium::item_type::relation)) {
+ mark_rel_ids(rel_in_rel, id);
+ }
+
+@@ -328,12 +322,12 @@ void CommandGetId::find_nodes_and_ways_i
+ osmium::io::Reader reader{m_input_file, osmium::osm_entity_bits::relation};
+ while (osmium::memory::Buffer buffer = reader.read()) {
+ for (const auto& relation : buffer.select<osmium::Relation>()) {
+- if (ids(osmium::item_type::relation).count(relation.id())) {
++ if (m_ids(osmium::item_type::relation).get(relation.positive_id())) {
+ for (const auto& member : relation.members()) {
+ if (member.type() == osmium::item_type::node) {
+- ids(osmium::item_type::node).insert(member.ref());
++ m_ids(osmium::item_type::node).set(member.positive_ref());
+ } else if (member.type() == osmium::item_type::way) {
+- ids(osmium::item_type::way).insert(member.ref());
++ m_ids(osmium::item_type::way).set(member.positive_ref());
+ }
+ }
+ }
+@@ -348,7 +342,7 @@ void CommandGetId::find_nodes_in_ways()
+ osmium::io::Reader reader{m_input_file, osmium::osm_entity_bits::way};
+ while (osmium::memory::Buffer buffer = reader.read()) {
+ for (const auto& way : buffer.select<osmium::Way>()) {
+- if (ids(osmium::item_type::way).count(way.id())) {
++ if (m_ids(osmium::item_type::way).get(way.positive_id())) {
+ add_nodes(way);
+ }
+ }
+@@ -358,7 +352,7 @@ void CommandGetId::find_nodes_in_ways()
+
+ void CommandGetId::find_referenced_objects() {
+ m_vout << "Following references...\n";
+- bool todo = !ids(osmium::item_type::relation).empty();
++ bool todo = !m_ids(osmium::item_type::relation).empty();
+ if (todo) {
+ todo = find_relations_in_relations();
+ }
+@@ -367,7 +361,7 @@ void CommandGetId::find_referenced_objec
+ find_nodes_and_ways_in_relations();
+ }
+
+- if (!ids(osmium::item_type::way).empty()) {
++ if (!m_ids(osmium::item_type::way).empty()) {
+ find_nodes_in_ways();
+ }
+ m_vout << "Done following references.\n";
+@@ -383,7 +377,8 @@ bool CommandGetId::run() {
+
+ m_vout << "Opening output file...\n";
+ osmium::io::Header header = reader.header();
+- header.set("generator", m_generator);
++ setup_header(header);
++
+ osmium::io::Writer writer{m_output_file, header, m_output_overwrite, m_fsync};
+
+ m_vout << "Copying from source to output file...\n";
+@@ -391,10 +386,9 @@ bool CommandGetId::run() {
+ while (osmium::memory::Buffer buffer = reader.read()) {
+ progress_bar.update(reader.offset());
+ for (const auto& object : buffer.select<osmium::OSMObject>()) {
+- auto& index = ids(object.type());
+- if (index.count(object.id())) {
++ if (m_ids(object.type()).get(object.positive_id())) {
+ if (!m_work_with_history) {
+- index.erase(object.id());
++ m_ids(object.type()).unset(object.positive_id());
+ }
+ writer(object);
+ }
+@@ -414,9 +408,9 @@ bool CommandGetId::run() {
+ } else {
+ m_vout << "Did not find " << count_ids() << " object(s).\n";
+ if (m_verbose_ids) {
+- print_missing_ids("node", ids(osmium::item_type::node));
+- print_missing_ids("way", ids(osmium::item_type::way));
+- print_missing_ids("relation", ids(osmium::item_type::relation));
++ print_missing_ids("node", m_ids(osmium::item_type::node));
++ print_missing_ids("way", m_ids(osmium::item_type::way));
++ print_missing_ids("relation", m_ids(osmium::item_type::relation));
+ }
+ }
+ }
+--- a/src/command_getid.hpp
++++ b/src/command_getid.hpp
+@@ -29,6 +29,7 @@ along with this program. If not, see <h
+ #include <vector>
+
+ #include <osmium/fwd.hpp>
++#include <osmium/index/id_set.hpp>
+ #include <osmium/osm/entity_bits.hpp>
+ #include <osmium/osm/item_type.hpp>
+ #include <osmium/osm/types.hpp>
+@@ -43,10 +44,7 @@ class CommandGetId : public Command, pub
+ bool m_work_with_history = false;
+ bool m_verbose_ids = false;
+
+- std::set<osmium::object_id_type> m_ids[3];
+-
+- std::set<osmium::object_id_type>& ids(osmium::item_type type) noexcept;
+- const std::set<osmium::object_id_type>& ids(osmium::item_type type) const noexcept;
++ osmium::index::NWRIdSet<osmium::index::IdSetDense> m_ids;
+
+ void parse_and_add_id(const std::string& s);
+
+--- a/src/command_merge.cpp
++++ b/src/command_merge.cpp
+@@ -147,7 +147,8 @@ bool operator!=(const QueueElement& lhs,
+ bool CommandMerge::run() {
+ m_vout << "Opening output file...\n";
+ osmium::io::Header header;
+- header.set("generator", m_generator);
++ setup_header(header);
++
+ osmium::io::Writer writer{m_output_file, header, m_output_overwrite, m_fsync};
+
+ if (m_input_files.size() == 1) {
+--- a/src/command_merge_changes.cpp
++++ b/src/command_merge_changes.cpp
+@@ -90,7 +90,8 @@ void CommandMergeChanges::show_arguments
+ bool CommandMergeChanges::run() {
+ m_vout << "Opening output file...\n";
+ osmium::io::Header header;
+- header.set("generator", m_generator);
++ setup_header(header);
++
+ osmium::io::Writer writer{m_output_file, header, m_output_overwrite, m_fsync};
+ auto out = osmium::io::make_output_iterator(writer);
+
+--- a/src/command_renumber.cpp
++++ b/src/command_renumber.cpp
+@@ -218,7 +218,7 @@ void CommandRenumber::read_index(osmium:
+ if (errno == ENOENT) {
+ return;
+ }
+- throw std::runtime_error{std::string{"Can't open file '"} + f + "': " + std::strerror(errno)};
++ throw std::runtime_error{std::string{"Could not open file '"} + f + "': " + std::strerror(errno)};
+ }
+ #ifdef _WIN32
+ _setmode(fd, _O_BINARY);
+@@ -227,7 +227,7 @@ void CommandRenumber::read_index(osmium:
+ const std::size_t file_size = osmium::util::file_size(fd);
+
+ if (file_size % sizeof(osmium::object_id_type) != 0) {
+- throw std::runtime_error{std::string{"index file '"} + f + "' has wrong file size"};
++ throw std::runtime_error{std::string{"Index file '"} + f + "' has wrong file size"};
+ }
+
+ map(type).read(fd, file_size);
+@@ -243,7 +243,7 @@ void CommandRenumber::write_index(osmium
+ const std::string f{filename(osmium::item_type_to_name(type))};
+ const int fd = ::open(f.c_str(), O_WRONLY | O_CREAT, 0666);
+ if (fd < 0) {
+- throw std::runtime_error{std::string{"Can't open file '"} + f + "': " + std::strerror(errno)};
++ throw std::runtime_error{std::string{"Could not open file '"} + f + "': " + std::strerror(errno)};
+ }
+ #ifdef _WIN32
+ _setmode(fd, _O_BINARY);
+@@ -288,11 +288,9 @@ bool CommandRenumber::run() {
+ osmium::io::Reader reader_pass2{m_input_file};
+
+ osmium::io::Header header = reader_pass2.header();
+- header.set("generator", m_generator);
++ setup_header(header);
+ header.set("xml_josm_upload", "false");
+- for (const auto& h : m_output_headers) {
+- header.set(h);
+- }
++
+ osmium::io::Writer writer{m_output_file, header, m_output_overwrite, m_fsync};
+
+ osmium::ProgressBar progress_bar{reader_pass2.file_size(), display_progress()};
+--- a/src/command_show.cpp
++++ b/src/command_show.cpp
+@@ -131,12 +131,12 @@ bool CommandShow::setup(const std::vecto
+ static int execute_pager(const std::string& pager) {
+ int pipefd[2];
+ if (::pipe(pipefd) < 0) {
+- throw std::system_error{errno, std::system_category(), "opening pipe failed"};
++ throw std::system_error{errno, std::system_category(), "Could not run pager: pipe() call failed"};
+ }
+
+ pid_t pid = fork();
+ if (pid < 0) {
+- throw std::system_error{errno, std::system_category(), "fork failed"};
++ throw std::system_error{errno, std::system_category(), "Could not run pager: fork() call failed"};
+ }
+
+ if (pid == 0) {
+@@ -159,7 +159,7 @@ static int execute_pager(const std::stri
+ ::close(pipefd[0]); // close read end of the pipe
+
+ if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
+- throw std::system_error{errno, std::system_category(), "signal call failed"};
++ throw std::system_error{errno, std::system_category(), "Could not run pager: signal() call failed"};
+ }
+
+ return pipefd[1];
+@@ -183,7 +183,7 @@ bool CommandShow::run() {
+
+ ::close(1); // close stdout
+ if (::dup2(fd, 1) < 0) { // put end of pipe as stdout
+- throw std::system_error{errno, std::system_category(), "dup2 failed"};
++ throw std::system_error{errno, std::system_category(), "Could not run pager: dup2() call failed"};
+ }
+
+ osmium::io::File file{"-", m_output_format};
+@@ -204,10 +204,10 @@ bool CommandShow::run() {
+ int status = 0;
+ const int pid = ::wait(&status);
+ if (pid < 0) {
+- throw std::system_error{errno, std::system_category(), "wait failed"};
++ throw std::system_error{errno, std::system_category(), "Could not run pager: wait() call failed"};
+ }
+ if (WIFEXITED(status) && WEXITSTATUS(status) == 1) {
+- throw argument_error{std::string{"Could not execute pager '"} + m_pager + "'"};
++ throw argument_error{std::string{"Could not run pager '"} + m_pager + "'"};
+ }
+ #endif
+ }
+--- a/src/command_sort.cpp
++++ b/src/command_sort.cpp
+@@ -99,10 +99,11 @@ bool CommandSort::run() {
+
+ m_vout << "Opening output file...\n";
+ osmium::io::Header header;
++ setup_header(header);
+ if (bounding_box) {
+ header.add_box(bounding_box);
+ }
+- header.set("generator", m_generator);
++
+ osmium::io::Writer writer{m_output_file, header, m_output_overwrite, m_fsync};
+
+ m_vout << "Sorting data...\n";
+--- a/src/command_time_filter.cpp
++++ b/src/command_time_filter.cpp
+@@ -126,7 +126,8 @@ bool CommandTimeFilter::run() {
+
+ m_vout << "Opening output file...\n";
+ osmium::io::Header header{reader.header()};
+- header.set("generator", m_generator);
++ setup_header(header);
++
+ osmium::io::Writer writer{m_output_file, header, m_output_overwrite, m_fsync};
+
+ m_vout << "Filter data while copying it from input to output...\n";
+--- a/src/io.cpp
++++ b/src/io.cpp
+@@ -29,6 +29,7 @@ along with this program. If not, see <h
+ #include <osmium/io/any_input.hpp> // IWYU pragma: keep
+ #include <osmium/io/any_output.hpp> // IWYU pragma: keep
+ #include <osmium/io/file.hpp>
++#include <osmium/io/header.hpp>
+ #include <osmium/io/writer_options.hpp>
+ #include <osmium/util/file.hpp>
+ #include <osmium/util/verbose_output.hpp>
+@@ -180,6 +181,13 @@ void with_osm_output::show_output_argume
+ }
+ }
+
++void with_osm_output::setup_header(osmium::io::Header& header) const {
++ header.set("generator", m_generator);
++ for (const auto& h : m_output_headers) {
++ header.set(h);
++ }
++}
++
+ std::size_t file_size_sum(std::vector<osmium::io::File> files) {
+ std::size_t sum = 0;
+
+--- a/src/main.cpp
++++ b/src/main.cpp
+@@ -20,6 +20,7 @@ along with this program. If not, see <h
+
+ */
+
++#include <cerrno>
+ #include <exception>
+ #include <iostream>
+ #include <memory>
+@@ -105,10 +106,10 @@ int main(int argc, char *argv[]) {
+ return return_code::okay;
+ }
+ } catch (const boost::program_options::error& e) {
+- std::cerr << "Error parsing command line: " << e.what() << std::endl;
++ std::cerr << "Error parsing command line: " << e.what() << '\n';
+ return return_code::fatal;
+ } catch (const std::exception& e) {
+- std::cerr << e.what() << std::endl;
++ std::cerr << e.what() << '\n';
+ return return_code::fatal;
+ }
+
+@@ -121,11 +122,17 @@ int main(int argc, char *argv[]) {
+ } catch (const std::bad_alloc&) {
+ std::cerr << "Out of memory. Read the MEMORY USAGE section of the osmium(1) manpage.\n";
+ } catch (const osmium::out_of_order_error& e) {
+- std::cerr << e.what() << "\n";
++ std::cerr << e.what() << '\n';
+ std::cerr << "This command expects the input file to be ordered: First nodes in order of ID,\n"
+ << "then ways in order of ID, then relations in order of ID.\n";
++ } catch (const std::system_error& e) {
++ std::cerr << e.what();
++ if (e.code().value() == EEXIST) {
++ std::cerr << ". Try using --overwrite if you are sure you want to overwrite the file.";
++ }
++ std::cerr << '\n';
+ } catch (const std::exception& e) {
+- std::cerr << e.what() << "\n";
++ std::cerr << e.what() << '\n';
+ }
+
+ return return_code::error;
+--- a/test/diff/test_setup.cpp
++++ b/test/diff/test_setup.cpp
+@@ -7,7 +7,7 @@ TEST_CASE("diff") {
+
+ CommandDiff cmd;
+
+- SECTION("no argments - need exactly two arguments") {
++ SECTION("no arguments - need exactly two arguments") {
+ REQUIRE_THROWS_AS(cmd.setup({}), argument_error);
+ }
+
+@@ -27,12 +27,8 @@ TEST_CASE("diff") {
+ REQUIRE_THROWS_AS(cmd.setup({"-q", "-f", "opl"}), argument_error);
+ }
+
+- SECTION("quiet with output parameter --fsync") {
+- REQUIRE_THROWS_AS(cmd.setup({"-q", "--fsync"}), argument_error);
+- }
+-
+- SECTION("quiet with output parameter --output-header") {
+- REQUIRE_THROWS_AS(cmd.setup({"-q", "--output-header", "foo"}), argument_error);
++ SECTION("parameter --fsync") {
++ REQUIRE_THROWS_AS(cmd.setup({"--fsync"}), boost::program_options::unknown_option);
+ }
+
+ SECTION("quiet with output parameter -O") {
+--- a/test/include/catch.hpp
++++ b/test/include/catch.hpp
+@@ -1,6 +1,6 @@
+ /*
+- * Catch v1.5.6
+- * Generated: 2016-06-09 19:20:41.460328
++ * Catch v1.5.8
++ * Generated: 2016-10-26 12:07:30.938259
+ * ----------------------------------------------------------
+ * This file has been merged from multiple headers. Please don't edit it directly
+ * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
+@@ -3223,10 +3223,11 @@ namespace Catch {
+
+ bool matches( TestCaseInfo const& testCase ) const {
+ // All patterns in a filter must match for the filter to be a match
+- for( std::vector<Ptr<Pattern> >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it )
++ for( std::vector<Ptr<Pattern> >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) {
+ if( !(*it)->matches( testCase ) )
+ return false;
+- return true;
++ }
++ return true;
+ }
+ };
+
+@@ -4719,8 +4720,11 @@ namespace Catch {
+ std::string line;
+ while( std::getline( f, line ) ) {
+ line = trim(line);
+- if( !line.empty() && !startsWith( line, "#" ) )
+- addTestOrTags( config, "\"" + line + "\"," );
++ if( !line.empty() && !startsWith( line, "#" ) ) {
++ if( !startsWith( line, "\"" ) )
++ line = "\"" + line + "\"";
++ addTestOrTags( config, line + "," );
++ }
+ }
+ }
+
+@@ -5368,7 +5372,10 @@ namespace Catch {
+ ++it ) {
+ matchedTests++;
+ TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
+- Catch::cout() << testCaseInfo.name << std::endl;
++ if( startsWith( testCaseInfo.name, "#" ) )
++ Catch::cout() << "\"" << testCaseInfo.name << "\"" << std::endl;
++ else
++ Catch::cout() << testCaseInfo.name << std::endl;
+ }
+ return matchedTests;
+ }
+@@ -6454,7 +6461,7 @@ namespace Catch {
+ namespace Catch {
+
+ struct RandomNumberGenerator {
+- typedef int result_type;
++ typedef std::ptrdiff_t result_type;
+
+ result_type operator()( result_type n ) const { return std::rand() % n; }
+
+@@ -7571,7 +7578,7 @@ namespace Catch {
+ return os;
+ }
+
+- Version libraryVersion( 1, 5, 6, "", 0 );
++ Version libraryVersion( 1, 5, 8, "", 0 );
+
+ }
+
+@@ -7802,8 +7809,11 @@ namespace Catch {
+ bool contains( std::string const& s, std::string const& infix ) {
+ return s.find( infix ) != std::string::npos;
+ }
++ char toLowerCh(char c) {
++ return static_cast<char>( ::tolower( c ) );
++ }
+ void toLowerInPlace( std::string& s ) {
+- std::transform( s.begin(), s.end(), s.begin(), ::tolower );
++ std::transform( s.begin(), s.end(), s.begin(), toLowerCh );
+ }
+ std::string toLower( std::string const& s ) {
+ std::string lc = s;
+@@ -8951,9 +8961,10 @@ namespace Catch {
+ break;
+
+ default:
+- // Escape control chars - based on contribution by @espenalb in PR #465
++ // Escape control chars - based on contribution by @espenalb in PR #465 and
++ // by @mrpi PR #588
+ if ( ( c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' )
+- os << "&#x" << std::uppercase << std::hex << static_cast<int>( c );
++ os << "&#x" << std::uppercase << std::hex << std::setfill('0') << std::setw(2) << static_cast<int>( c ) << ';';
+ else
+ os << c;
+ }
+@@ -9008,13 +9019,20 @@ namespace Catch {
+ : m_tagIsOpen( false ),
+ m_needsNewline( false ),
+ m_os( &Catch::cout() )
+- {}
++ {
++ // We encode control characters, which requires
++ // XML 1.1
++ // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
++ *m_os << "<?xml version=\"1.1\" encoding=\"UTF-8\"?>\n";
++ }
+
+ XmlWriter( std::ostream& os )
+ : m_tagIsOpen( false ),
+ m_needsNewline( false ),
+ m_os( &os )
+- {}
++ {
++ *m_os << "<?xml version=\"1.1\" encoding=\"UTF-8\"?>\n";
++ }
+
+ ~XmlWriter() {
+ while( !m_tags.empty() )
+@@ -9181,7 +9199,7 @@ namespace Catch {
+
+ virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
+ StreamingReporterBase::testCaseStarting(testInfo);
+- m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) );
++ m_xml.startElement( "TestCase" ).writeAttribute( "name", testInfo.name );
+
+ if ( m_config->showDurations() == ShowDurations::Always )
+ m_testCaseTimer.start();
+@@ -9243,7 +9261,7 @@ namespace Catch {
+ .writeText( assertionResult.getMessage() );
+ break;
+ case ResultWas::FatalErrorCondition:
+- m_xml.scopedElement( "Fatal Error Condition" )
++ m_xml.scopedElement( "FatalErrorCondition" )
+ .writeAttribute( "filename", assertionResult.getSourceInfo().file )
+ .writeAttribute( "line", assertionResult.getSourceInfo().line )
+ .writeText( assertionResult.getMessage() );
+--- a/test/io/Makefile.in
++++ b/test/io/Makefile.in
+@@ -32,7 +32,8 @@ OSMOSIS := /usr/bin/osmosis
+
+ OSMIUM := @CMAKE_BINARY_DIR@/src/osmium
+
+-OSMIUM_CMD := $(OSMIUM) cat --overwrite
++OSMIUM_CMD := $(OSMIUM) cat --overwrite --no-progress
++OSMIUM_FILEINFO := $(OSMIUM) fileinfo --no-progress -e -g data.crc32
+
+ ifeq ($(suffix $(INPUT)),.pbf)
+ OSMOSIS_READ := $(OSMOSIS) --read-pbf
+@@ -99,7 +100,7 @@ $(DIR)/osmium-DCbmg-fake.osm.opl: $(DIR)
+ sed -e 's/ v.* T/ v0 dV c0 t i0 u T/' $^ >$@
+
+ $(DIR)/osmium-DCbMG-fake.osm.opl: $(DIR)/osmium-DCbMg.osm.opl
+- grep '^n' $^ | sed -e 's/[0-9][0-9] y/00 y/' -e 's/[0-9][0-9]$$/00/' >$@
++ grep '^n' $^ | sed -e 's/[0-9][0-9] y/ y/' -e 's/\(.*\) y\([0-9]\.[0-9][0-9][0-9][0-9][0-9]\).*/\1 y\2/' -e 's/0\+$$//' >$@
+ grep '^[wr]' $^ >>$@
+
+ $(DIR)/report_opl: opl_input opl_files \
+@@ -157,7 +158,7 @@ $(DIR)/report_default: \
+ echo "Default:" >$@; \
+ for i in $^; do \
+ filename=`basename $$i`; \
+- crc=`$(OSMIUM) fileinfo -e -g data.crc32 $$i`; \
++ crc=`$(OSMIUM_FILEINFO) $$i`; \
+ echo $$crc $$filename >>$@; \
+ done; \
+ echo >>$@
+@@ -167,7 +168,7 @@ $(DIR)/report_granularity: \
+ echo "Non-standard granularity:" >$@; \
+ for i in $^; do \
+ filename=`basename $$i`; \
+- crc=`$(OSMIUM) fileinfo -e -g data.crc32 $$i`; \
++ crc=`$(OSMIUM_FILEINFO) $$i`; \
+ echo $$crc $$filename >>$@; \
+ done; \
+ echo >>$@
+@@ -180,7 +181,7 @@ $(DIR)/report_without_metadata: \
+ echo "Without metadata:" >$@; \
+ for i in $^; do \
+ filename=`basename $$i`; \
+- crc=`$(OSMIUM) fileinfo -e -g data.crc32 $$i`; \
++ crc=`$(OSMIUM_FILEINFO) $$i`; \
+ echo $$crc $$filename >>$@; \
+ done; \
+ echo >>$@
diff --git a/debian/patches/series b/debian/patches/series
index 38edaa7..5ad459e 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1 +1,2 @@
spelling-errors.patch
+libosmium-2.10.2.patch
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/osmium-tool.git
More information about the Pkg-grass-devel
mailing list