[osmium-tool] 01/05: Imported Upstream version 1.4.1

Bas Couwenberg sebastic at debian.org
Sun Nov 20 19:06:46 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 df80928972e60b3658a8d41db718f0313753f7e4
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Sun Nov 20 19:55:44 2016 +0100

    Imported Upstream version 1.4.1
---
 .travis.yml                           | 28 +++++++++++
 CHANGELOG.md                          | 33 ++++++++++++-
 CMakeLists.txt                        |  4 +-
 README.md                             | 12 ++---
 cmake/FindOsmium.cmake                | 62 ++++++++++++++++++------
 man/osmium-add-locations-to-ways.md   |  9 ++++
 man/osmium-derive-changes.md          |  2 +-
 man/osmium-diff.md                    | 16 +++++--
 man/osmium-getid.md                   |  2 +
 man/osmium-merge.md                   |  2 +-
 src/cmd.hpp                           | 18 ++++---
 src/command_add_locations_to_ways.cpp | 18 +++----
 src/command_add_locations_to_ways.hpp |  2 +-
 src/command_apply_changes.cpp         |  2 +-
 src/command_cat.cpp                   |  8 +---
 src/command_cat.hpp                   |  2 -
 src/command_changeset_filter.cpp      |  2 +-
 src/command_check_refs.cpp            | 29 +++++++-----
 src/command_derive_changes.cpp        |  4 +-
 src/command_diff.cpp                  | 28 +++++------
 src/command_fileinfo.cpp              |  2 +-
 src/command_getid.cpp                 | 88 ++++++++++++++++-------------------
 src/command_getid.hpp                 |  6 +--
 src/command_merge.cpp                 |  3 +-
 src/command_merge_changes.cpp         |  3 +-
 src/command_renumber.cpp              | 12 ++---
 src/command_show.cpp                  | 12 ++---
 src/command_sort.cpp                  |  3 +-
 src/command_time_filter.cpp           |  3 +-
 src/io.cpp                            |  8 ++++
 src/main.cpp                          | 15 ++++--
 test/diff/test_setup.cpp              | 10 ++--
 test/include/catch.hpp                | 50 +++++++++++++-------
 test/io/Makefile.in                   | 11 +++--
 34 files changed, 319 insertions(+), 190 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 7919851..581c158 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -130,6 +130,23 @@ matrix:
       env: COMPILER='g++-5' BUILD_TYPE='Dev'
 
 
+    - os: linux
+      compiler: linux-gcc6-release
+      addons:
+        apt:
+          sources: ['ubuntu-toolchain-r-test', 'boost-latest']
+          packages: ['g++-6', 'libboost1.55-all-dev', 'pandoc']
+      env: COMPILER='g++-6' BUILD_TYPE='Release'
+
+    - os: linux
+      compiler: linux-gcc6-dev
+      addons:
+        apt:
+          sources: ['ubuntu-toolchain-r-test', 'boost-latest']
+          packages: ['g++-6', 'libboost1.55-all-dev', 'pandoc']
+      env: COMPILER='g++-6' BUILD_TYPE='Dev'
+
+
     # 3/ OSX Clang Builds
     - os: osx
       osx_image: xcode6.4
@@ -152,6 +169,17 @@ matrix:
       compiler: xcode7-clang-dev
       env: COMPILER='clang++' BUILD_TYPE='Dev'
 
+
+    - os: osx
+      osx_image: xcode8
+      compiler: xcode8-clang-release
+      env: COMPILER='clang++' BUILD_TYPE='Release'
+
+    - os: osx
+      osx_image: xcode8
+      compiler: xcode8-clang-dev
+      env: COMPILER='clang++' BUILD_TYPE='Dev'
+
 #-----------------------------------------------------------------------------
 
 install:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index fe15765..aca591f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,34 @@ This project adheres to [Semantic Versioning](http://semver.org/).
 ### Fixed
 
 
+## [1.4.1] - 2016-11-20
+
+### 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.
+- Now requires at least libosmium 2.10.2 and protozero 1.4.5.
+
+### 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
 
 ### Added
@@ -27,7 +55,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
   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
 
@@ -162,7 +190,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
 - Minor updates to documentation and build system
 
 
-[unreleased]: https://github.com/osmcode/osmium-tool/compare/v1.4.0...HEAD
+[unreleased]: https://github.com/osmcode/osmium-tool/compare/v1.4.1...HEAD
+[1.4.1]: https://github.com/osmcode/osmium-tool/compare/v1.4.0...v1.4.1
 [1.4.0]: https://github.com/osmcode/osmium-tool/compare/v1.3.1...v1.4.0
 [1.3.1]: https://github.com/osmcode/osmium-tool/compare/v1.3.0...v1.3.1
 [1.3.0]: https://github.com/osmcode/osmium-tool/compare/v1.2.1...v1.3.0
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 25e6d14..37da7e6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -26,7 +26,7 @@ project(osmium)
 
 set(OSMIUM_VERSION_MAJOR 1)
 set(OSMIUM_VERSION_MINOR 4)
-set(OSMIUM_VERSION_PATCH 0)
+set(OSMIUM_VERSION_PATCH 1)
 
 set(OSMIUM_VERSION ${OSMIUM_VERSION_MAJOR}.${OSMIUM_VERSION_MINOR}.${OSMIUM_VERSION_PATCH})
 
@@ -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})
 
 
diff --git a/README.md b/README.md
index 3cf7b8a..564a201 100644
--- 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 on modern Visual Studio C++ compilers.
 
 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.5)
         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/O system can also be run. See
 
 ## 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 complete text of the license.
 
 ## 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).
 
diff --git a/cmake/FindOsmium.cmake b/cmake/FindOsmium.cmake
index fba8ffb..2224e18 100644
--- 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.hpp
         /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)
 
 #----------------------------------------------------------------------
diff --git a/man/osmium-add-locations-to-ways.md b/man/osmium-add-locations-to-ways.md
index 5827e99..0b6faac 100644
--- 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 the input file(s) to the output,
 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 history files.
 -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@
diff --git a/man/osmium-derive-changes.md b/man/osmium-derive-changes.md
index fc78817..a228812 100644
--- a/man/osmium-derive-changes.md
+++ b/man/osmium-derive-changes.md
@@ -18,7 +18,7 @@ applied on *OSM-FILE1* to re-create *OSM-FILE2*.
 Objects in both input files must be sorted by type, ID, and version. The first
 input file must be from a point in time before the second input file.
 
-For this command to create a proper chnage file you have to set the
+For this command to create a proper change file you have to set the
 **--output** option or **--output-format** option in a way that it will
 generate an .osc file, typically by using something like '-o out.osc.gz'.
 You can create any other OSM file format, but that is usually not what you
diff --git a/man/osmium-diff.md b/man/osmium-diff.md
index ef9edc2..85dbb73 100644
--- a/man/osmium-diff.md
+++ b/man/osmium-diff.md
@@ -40,12 +40,12 @@ compact
     file, respectively.
 
 opl
-:   The usual OPL format with all lines preceeded by space (' '), minus
+:   The usual OPL format with all lines preceded by space (' '), minus
     ('-'), or plus ('+') characters depending on whether the object is in both,
     the first, or the second file.
 
 debug
-:   The usual debug format with all lines preceeded by space (' '), minus
+:   The usual debug format with all lines preceded by space (' '), minus
     ('-'), or plus ('+') characters depending on whether the object is in both,
     the first, or the second file. Color support can be enabled ('debug,color').
 
@@ -57,6 +57,16 @@ None of the output formats print the headers of the input files.
 -c, --suppress-common
 :   Do not output objects that are the same in both files.
 
+-f, --output-format=FORMAT
+:   See section OUTPUT FORMATS.
+
+-o, --output=FILE
+:   Name of the output file. Default is '-' (*stdout*).
+
+-O, --overwrite
+:   Allow an existing output file to be overwritten. Normally **osmium** will
+    refuse to write over an existing file.
+
 -q, --quiet
 :   No output. Just report when files differ through the return code.
 
@@ -69,10 +79,8 @@ None of the output formats print the headers of the input files.
     By default all types are read. This option can be given multiple times.
     This affects the output as well as the return code of the command.
 
-
 @MAN_COMMON_OPTIONS@
 @MAN_INPUT_OPTIONS@
- at MAN_OUTPUT_OPTIONS@
 
 # DIAGNOSTICS
 
diff --git a/man/osmium-getid.md b/man/osmium-getid.md
index cfe820b..1b248b7 100644
--- a/man/osmium-getid.md
+++ b/man/osmium-getid.md
@@ -58,6 +58,8 @@ If referenced objects are missing from the input file, the type and IDs
 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
 
diff --git a/man/osmium-merge.md b/man/osmium-merge.md
index 72ef2ef..44c5bc1 100644
--- a/man/osmium-merge.md
+++ b/man/osmium-merge.md
@@ -46,7 +46,7 @@ correctly.
 # MEMORY USAGE
 
 **osmium merge** doesn't keep a lot of data in memory, but if you are merging
-many files, the buffers might take a noticable amount of memory.
+many files, the buffers might take a noticeable amount of memory.
 
 
 # EXAMPLES
diff --git a/src/cmd.hpp b/src/cmd.hpp
index a32628d..0e16a56 100644
--- 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;
diff --git a/src/command_add_locations_to_ways.cpp b/src/command_add_locations_to_ways.cpp
index d2e9027..e96a517 100644
--- a/src/command_add_locations_to_ways.cpp
+++ b/src/command_add_locations_to_ways.cpp
@@ -54,6 +54,7 @@ bool CommandAddLocationsToWays::setup(const std::vector<std::string>& arguments)
     ("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(const std::vector<std::string>& arguments)
         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_arguments() {
     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);
 
diff --git a/src/command_add_locations_to_ways.hpp b/src/command_add_locations_to_ways.hpp
index 571fea2..716f63a 100644
--- 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::handler::NodeLocationsForWays<index_type>;
 
 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:
 
diff --git a/src/command_apply_changes.cpp b/src/command_apply_changes.cpp
index 2d36375..4c85a64 100644
--- 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};
diff --git a/src/command_cat.cpp b/src/command_cat.cpp
index a130e7b..f9017af 100644
--- 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()) {
diff --git a/src/command_cat.hpp b/src/command_cat.hpp
index 3debe51..1356857 100644
--- 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;
diff --git a/src/command_changeset_filter.cpp b/src/command_changeset_filter.cpp
index 0413d4b..8f81f4d 100644
--- 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};
diff --git a/src/command_check_refs.cpp b/src/command_check_refs.cpp
index c06beb0..326b993 100644
--- a/src/command_check_refs.cpp
+++ b/src/command_check_refs.cpp
@@ -31,7 +31,7 @@ along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 #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::handler::Handler {
     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";
diff --git a/src/command_derive_changes.cpp b/src/command_derive_changes.cpp
index 6bcdea3..947e7f0 100644
--- 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";
diff --git a/src/command_diff.cpp b/src/command_diff.cpp
index 2445115..aead57f 100644
--- a/src/command_diff.cpp
+++ b/src/command_diff.cpp
@@ -49,15 +49,17 @@ along with this program.  If not, see <https://www.gnu.org/licenses/>.
 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::vector<std::string>& arguments) {
     ;
 
     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::vector<std::string>& arguments) {
         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 OutputAction {
 
 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;
diff --git a/src/command_fileinfo.cpp b/src/command_fileinfo.cpp
index c2f70ea..d61615f 100644
--- a/src/command_fileinfo.cpp
+++ b/src/command_fileinfo.cpp
@@ -157,7 +157,7 @@ off_t filesize(const std::string& filename) {
 
     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;
diff --git a/src/command_getid.cpp b/src/command_getid.cpp
index 2498d76..2844e6b 100644
--- a/src/command_getid.cpp
+++ b/src/command_getid.cpp
@@ -44,17 +44,12 @@ along with this program.  If not, see <https://www.gnu.org/licenses/>.
 #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::istream& stream) {
 }
 
 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 CommandGetId::get_needed_types() const {
 
 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(const std::string& file_name) {
     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(const std::string& file_name) {
 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_relations() {
             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_relations() {
         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_in_relations() {
     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_objects() {
         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));
             }
         }
     }
diff --git a/src/command_getid.hpp b/src/command_getid.hpp
index 908592f..7cfda20 100644
--- a/src/command_getid.hpp
+++ b/src/command_getid.hpp
@@ -29,6 +29,7 @@ along with this program.  If not, see <https://www.gnu.org/licenses/>.
 #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, public with_single_osm_input, public with_o
     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);
 
diff --git a/src/command_merge.cpp b/src/command_merge.cpp
index caed2b2..31d384e 100644
--- a/src/command_merge.cpp
+++ b/src/command_merge.cpp
@@ -147,7 +147,8 @@ bool operator!=(const QueueElement& lhs, const QueueElement& rhs) noexcept {
 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) {
diff --git a/src/command_merge_changes.cpp b/src/command_merge_changes.cpp
index 50fe769..56b477f 100644
--- 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);
 
diff --git a/src/command_renumber.cpp b/src/command_renumber.cpp
index 24b1e84..048676f 100644
--- a/src/command_renumber.cpp
+++ b/src/command_renumber.cpp
@@ -218,7 +218,7 @@ void CommandRenumber::read_index(osmium::item_type type) {
         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::item_type type) {
     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::item_type type) {
     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()};
diff --git a/src/command_show.cpp b/src/command_show.cpp
index a69b1cd..4ec4ac0 100644
--- a/src/command_show.cpp
+++ b/src/command_show.cpp
@@ -131,12 +131,12 @@ bool CommandShow::setup(const std::vector<std::string>& arguments) {
 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::string& pager) {
     ::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
     }
diff --git a/src/command_sort.cpp b/src/command_sort.cpp
index 3148274..171d52e 100644
--- 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";
diff --git a/src/command_time_filter.cpp b/src/command_time_filter.cpp
index 42a556e..90b789c 100644
--- 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";
diff --git a/src/io.cpp b/src/io.cpp
index 4110d31..bdd57ee 100644
--- a/src/io.cpp
+++ b/src/io.cpp
@@ -29,6 +29,7 @@ along with this program.  If not, see <https://www.gnu.org/licenses/>.
 #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_arguments(osmium::util::VerboseOutput& vout) {
     }
 }
 
+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;
 
diff --git a/src/main.cpp b/src/main.cpp
index 93c28e5..9b01212 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -20,6 +20,7 @@ along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 */
 
+#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;
diff --git a/test/diff/test_setup.cpp b/test/diff/test_setup.cpp
index 40e6241..c12e748 100644
--- 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") {
diff --git a/test/include/catch.hpp b/test/include/catch.hpp
index 879fc5b..2e6fe8d 100644
--- 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() );
diff --git a/test/io/Makefile.in b/test/io/Makefile.in
index 86e1217..5a2cfae 100644
--- 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)/osmium-DCbMg.osm.opl
 	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 >>$@

-- 
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