Skip to content

Commit

Permalink
Add options to the "diff" command to ignore certain attributes
Browse files Browse the repository at this point in the history
When the new command line options --ignore-changeset, --ignore-uid, or
--ignore-user are used, the respective attributes of OSM objects are
ignored when comparing the input files. This is especially useful for
user names, because OSM users can change their own user names, which
happens often enough to matter.

When used with the OPL output format the ignored attributes are not
written out to the output.
  • Loading branch information
joto committed Jan 10, 2025
1 parent 13a8a0a commit a2e650f
Show file tree
Hide file tree
Showing 11 changed files with 107 additions and 8 deletions.
15 changes: 14 additions & 1 deletion man/osmium-diff.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,19 @@ None of the output formats print the headers of the input files.
-f, \--output-format=FORMAT
: See the **OUTPUT FORMATS** section.

\--ignore-changeset
: Ignore changeset id on OSM objects when comparing files. When used with
the OPL output format the 'changeset' attribute is not written to the
output.

\--ignore-uid
: Ignore user id on OSM objects when comparing files. When used with
the OPL output format the 'uid' attribute is not written to the output.

\--ignore-user
: Ignore user name on OSM objects when comparing files. When used with
the OPL output format the 'user' attribute is not written to the output.

-o, \--output=FILE
: Name of the output file. Default is '-' (STDOUT).

Expand Down Expand Up @@ -107,7 +120,7 @@ None of the output formats print the headers of the input files.

# EXAMPLES

Show difference between Nepal files from January 2016 and Febrary 2016 in
Show difference between Nepal files from January 2016 and February 2016 in
compact format:

osmium diff nepal-20160101.osm.pbf nepal-20160201.osm.pbf
Expand Down
56 changes: 50 additions & 6 deletions src/command_diff.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ 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()
("ignore-changeset", "Ignore changeset id when comparing objects")
("ignore-uid", "Ignore user id when comparing objects")
("ignore-user", "Ignore user name when comparing 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")
Expand Down Expand Up @@ -93,6 +96,18 @@ bool CommandDiff::setup(const std::vector<std::string>& arguments) {
throw argument_error("You need exactly two input files for this command.");
}

if (vm.count("ignore-changeset")) {
m_ignore_attrs_changeset = true;
}

if (vm.count("ignore-uid")) {
m_ignore_attrs_uid = true;
}

if (vm.count("ignore-user")) {
m_ignore_attrs_user = true;
}

if (vm.count("output")) {
m_output_filename = vm["output"].as<std::string>();
}
Expand Down Expand Up @@ -130,6 +145,18 @@ bool CommandDiff::setup(const std::vector<std::string>& arguments) {
m_output_file = osmium::io::File{m_output_filename, m_output_format};
m_output_file.check();

std::string metadata{"version+timestamp"};
if (!m_ignore_attrs_changeset) {
metadata += "+changeset";
}
if (!m_ignore_attrs_uid) {
metadata += "+uid";
}
if (!m_ignore_attrs_changeset) {
metadata += "+user";
}
m_output_file.set("add_metadata", metadata);

auto f = m_output_file.format();
if (f != osmium::io::file_format::opl && f != osmium::io::file_format::debug) {
throw argument_error("File format does not support diff output. Use 'compact', 'opl' or 'debug' format.");
Expand Down Expand Up @@ -248,6 +275,21 @@ class OutputActionOSM : public OutputAction {

}; // class OutputActionOSM

void CommandDiff::update_object_crc(osmium::CRC<osmium::CRC_zlib>* crc, const osmium::OSMObject &object) {
crc->update_bool(object.visible());
crc->update(object.timestamp());
crc->update(object.tags());
if (!m_ignore_attrs_changeset) {
crc->update_int32(object.changeset());
}
if (!m_ignore_attrs_uid) {
crc->update_int32(object.uid());
}
if (!m_ignore_attrs_user) {
crc->update_string(object.user());
}
}

bool CommandDiff::run() {
osmium::io::Reader reader1{m_input_files[0], osm_entity_bits()};
osmium::io::ReaderWithProgressBar reader2{display_progress(), m_input_files[1], osm_entity_bits()};
Expand Down Expand Up @@ -298,18 +340,20 @@ bool CommandDiff::run() {
} else { /* *it1 == *it2 */
osmium::CRC<osmium::CRC_zlib> crc1;
osmium::CRC<osmium::CRC_zlib> crc2;
update_object_crc(&crc1, *it1);
update_object_crc(&crc2, *it2);
switch (it1->type()) {
case osmium::item_type::node:
crc1.update(static_cast<const osmium::Node&>(*it1));
crc2.update(static_cast<const osmium::Node&>(*it2));
crc1.update(static_cast<const osmium::Node&>(*it1).location());
crc2.update(static_cast<const osmium::Node&>(*it2).location());
break;
case osmium::item_type::way:
crc1.update(static_cast<const osmium::Way&>(*it1));
crc2.update(static_cast<const osmium::Way&>(*it2));
crc1.update(static_cast<const osmium::Way&>(*it1).nodes());
crc2.update(static_cast<const osmium::Way&>(*it2).nodes());
break;
case osmium::item_type::relation:
crc1.update(static_cast<const osmium::Relation&>(*it1));
crc2.update(static_cast<const osmium::Relation&>(*it2));
crc1.update(static_cast<const osmium::Relation&>(*it1).members());
crc2.update(static_cast<const osmium::Relation&>(*it2).members());
break;
default:
break;
Expand Down
8 changes: 8 additions & 0 deletions src/command_diff.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,23 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.

#include "cmd.hpp" // IWYU pragma: export

#include <osmium/osm/crc.hpp>
#include <osmium/osm/crc_zlib.hpp>

#include <string>
#include <vector>

class CommandDiff : public CommandWithMultipleOSMInputs, public with_osm_output {

std::string m_output_action;
bool m_ignore_attrs_changeset = false;
bool m_ignore_attrs_uid = false;
bool m_ignore_attrs_user = false;
bool m_show_summary = false;
bool m_suppress_common = false;

void update_object_crc(osmium::CRC<osmium::CRC_zlib>* crc, const osmium::OSMObject &object);

public:

explicit CommandDiff(const CommandFactory& command_factory) :
Expand Down
8 changes: 8 additions & 0 deletions test/diff/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,12 @@ check_diff(opl-c "-f opl -c" input1.osm input2.osm output-c.opl 1)

check_diff(same "" input1.osm input1.osm output-same 0)

check_diff(ignore-uid "--ignore-uid -c" input1.osm input2.osm output-compact-c-nouid 1)

check_diff(ignore-uid-15 "--ignore-uid -c" input1uid.osm input2uid.osm output-empty 0)

check_diff(ignore-uid-opl "--ignore-uid -f opl -c" input1.osm input2.osm output-compact-c-nouid-opl 1)

check_diff(ignore-uid-15-opl "--ignore-uid -f opl -c" input1uid.osm input2uid.osm output-empty 0)

#-----------------------------------------------------------------------------
4 changes: 4 additions & 0 deletions test/diff/input1uid.osm
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version='1.0' encoding='UTF-8'?>
<osm version="0.6" upload="false" generator="testdata">
<node id="15" version="1" timestamp="2015-01-01T02:00:00Z" uid="2" user="test" changeset="1" lat="5" lon="1"/>
</osm>
2 changes: 1 addition & 1 deletion test/diff/input2.osm
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='UTF-8'?>
<osm version="0.6" generator="test">
<osm version="0.6" upload="false" generator="testdata">
<node id="10" version="1" timestamp="2015-01-01T01:00:00Z" uid="1" user="test" changeset="1" lat="1" lon="1"/>
<node id="11" version="2" timestamp="2015-01-01T02:00:00Z" uid="1" user="test" changeset="2" lat="2" lon="2"/>
<node id="12" version="1" timestamp="2015-01-01T01:00:00Z" uid="1" user="test" changeset="1" lat="3" lon="1"/>
Expand Down
4 changes: 4 additions & 0 deletions test/diff/input2uid.osm
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version='1.0' encoding='UTF-8'?>
<osm version="0.6" upload="false" generator="testdata">
<node id="15" version="1" timestamp="2015-01-01T02:00:00Z" uid="1" user="test" changeset="1" lat="5" lon="1"/>
</osm>
7 changes: 7 additions & 0 deletions test/diff/output-compact-c-nouid
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
-n11 v1
+n11 v2
-n13 v1
+n14 v1
*n16 v1
-w21 v1
+w21 v2
8 changes: 8 additions & 0 deletions test/diff/output-compact-c-nouid-opl
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
-n11 v1 dV c1 t2015-01-01T01:00:00Z utest T x1 y2
+n11 v2 dV c2 t2015-01-01T02:00:00Z utest T x2 y2
-n13 v1 dV c1 t2015-01-01T01:00:00Z utest T x1 y4
+n14 v1 dV c2 t2015-01-01T02:00:00Z utest T x1 y5
-n16 v1 dV c1 t2015-01-01T02:00:00Z utest T x2 y5
+n16 v1 dV c1 t2015-01-01T02:00:00Z utest T x1 y5
-w21 v1 dV c1 t2015-01-01T01:00:00Z utest Txyz=abc Nn12,n13
+w21 v2 dV c2 t2015-01-01T02:00:00Z utest Txyz=new Nn12,n14
Empty file added test/diff/output-empty
Empty file.
3 changes: 3 additions & 0 deletions zsh_completion/_osmium
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,9 @@ _osmium-diff() {
${(f)"$(_osmium-multiple-inputs-options)"} \
${(f)"$(_osmium-diff-output-format-options)"} \
${(f)"$(_osmium-output-options)"} \
'--ignore-changeset[ignore changeset id on OSM objects when comparing files]' \
'--ignore-uid[ignore user id on OSM objects when comparing files]' \
'--ignore-user[ignore user name on OSM objects when comparing files]' \
'(--quiet)-q[report only when files differ]' \
'(-q)--quiet[report only when files differ]' \
'(--suppress-common)-c[suppress common objects]' \
Expand Down

0 comments on commit a2e650f

Please sign in to comment.