[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