Skip to content

Commit a2e650f

Browse files
committed
Add options to the "diff" command to ignore certain attributes
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.
1 parent 13a8a0a commit a2e650f

File tree

11 files changed

+107
-8
lines changed

11 files changed

+107
-8
lines changed

man/osmium-diff.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,19 @@ None of the output formats print the headers of the input files.
6363
-f, \--output-format=FORMAT
6464
: See the **OUTPUT FORMATS** section.
6565

66+
\--ignore-changeset
67+
: Ignore changeset id on OSM objects when comparing files. When used with
68+
the OPL output format the 'changeset' attribute is not written to the
69+
output.
70+
71+
\--ignore-uid
72+
: Ignore user id on OSM objects when comparing files. When used with
73+
the OPL output format the 'uid' attribute is not written to the output.
74+
75+
\--ignore-user
76+
: Ignore user name on OSM objects when comparing files. When used with
77+
the OPL output format the 'user' attribute is not written to the output.
78+
6679
-o, \--output=FILE
6780
: Name of the output file. Default is '-' (STDOUT).
6881

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

108121
# EXAMPLES
109122

110-
Show difference between Nepal files from January 2016 and Febrary 2016 in
123+
Show difference between Nepal files from January 2016 and February 2016 in
111124
compact format:
112125

113126
osmium diff nepal-20160101.osm.pbf nepal-20160201.osm.pbf

src/command_diff.cpp

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
5252
bool CommandDiff::setup(const std::vector<std::string>& arguments) {
5353
po::options_description opts_cmd{"COMMAND OPTIONS"};
5454
opts_cmd.add_options()
55+
("ignore-changeset", "Ignore changeset id when comparing objects")
56+
("ignore-uid", "Ignore user id when comparing objects")
57+
("ignore-user", "Ignore user name when comparing objects")
5558
("object-type,t", po::value<std::vector<std::string>>(), "Read only objects of given type (node, way, relation)")
5659
("output,o", po::value<std::string>(), "Output file")
5760
("output-format,f", po::value<std::string>(), "Format of output file")
@@ -93,6 +96,18 @@ bool CommandDiff::setup(const std::vector<std::string>& arguments) {
9396
throw argument_error("You need exactly two input files for this command.");
9497
}
9598

99+
if (vm.count("ignore-changeset")) {
100+
m_ignore_attrs_changeset = true;
101+
}
102+
103+
if (vm.count("ignore-uid")) {
104+
m_ignore_attrs_uid = true;
105+
}
106+
107+
if (vm.count("ignore-user")) {
108+
m_ignore_attrs_user = true;
109+
}
110+
96111
if (vm.count("output")) {
97112
m_output_filename = vm["output"].as<std::string>();
98113
}
@@ -130,6 +145,18 @@ bool CommandDiff::setup(const std::vector<std::string>& arguments) {
130145
m_output_file = osmium::io::File{m_output_filename, m_output_format};
131146
m_output_file.check();
132147

148+
std::string metadata{"version+timestamp"};
149+
if (!m_ignore_attrs_changeset) {
150+
metadata += "+changeset";
151+
}
152+
if (!m_ignore_attrs_uid) {
153+
metadata += "+uid";
154+
}
155+
if (!m_ignore_attrs_changeset) {
156+
metadata += "+user";
157+
}
158+
m_output_file.set("add_metadata", metadata);
159+
133160
auto f = m_output_file.format();
134161
if (f != osmium::io::file_format::opl && f != osmium::io::file_format::debug) {
135162
throw argument_error("File format does not support diff output. Use 'compact', 'opl' or 'debug' format.");
@@ -248,6 +275,21 @@ class OutputActionOSM : public OutputAction {
248275

249276
}; // class OutputActionOSM
250277

278+
void CommandDiff::update_object_crc(osmium::CRC<osmium::CRC_zlib>* crc, const osmium::OSMObject &object) {
279+
crc->update_bool(object.visible());
280+
crc->update(object.timestamp());
281+
crc->update(object.tags());
282+
if (!m_ignore_attrs_changeset) {
283+
crc->update_int32(object.changeset());
284+
}
285+
if (!m_ignore_attrs_uid) {
286+
crc->update_int32(object.uid());
287+
}
288+
if (!m_ignore_attrs_user) {
289+
crc->update_string(object.user());
290+
}
291+
}
292+
251293
bool CommandDiff::run() {
252294
osmium::io::Reader reader1{m_input_files[0], osm_entity_bits()};
253295
osmium::io::ReaderWithProgressBar reader2{display_progress(), m_input_files[1], osm_entity_bits()};
@@ -298,18 +340,20 @@ bool CommandDiff::run() {
298340
} else { /* *it1 == *it2 */
299341
osmium::CRC<osmium::CRC_zlib> crc1;
300342
osmium::CRC<osmium::CRC_zlib> crc2;
343+
update_object_crc(&crc1, *it1);
344+
update_object_crc(&crc2, *it2);
301345
switch (it1->type()) {
302346
case osmium::item_type::node:
303-
crc1.update(static_cast<const osmium::Node&>(*it1));
304-
crc2.update(static_cast<const osmium::Node&>(*it2));
347+
crc1.update(static_cast<const osmium::Node&>(*it1).location());
348+
crc2.update(static_cast<const osmium::Node&>(*it2).location());
305349
break;
306350
case osmium::item_type::way:
307-
crc1.update(static_cast<const osmium::Way&>(*it1));
308-
crc2.update(static_cast<const osmium::Way&>(*it2));
351+
crc1.update(static_cast<const osmium::Way&>(*it1).nodes());
352+
crc2.update(static_cast<const osmium::Way&>(*it2).nodes());
309353
break;
310354
case osmium::item_type::relation:
311-
crc1.update(static_cast<const osmium::Relation&>(*it1));
312-
crc2.update(static_cast<const osmium::Relation&>(*it2));
355+
crc1.update(static_cast<const osmium::Relation&>(*it1).members());
356+
crc2.update(static_cast<const osmium::Relation&>(*it2).members());
313357
break;
314358
default:
315359
break;

src/command_diff.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,23 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
2525

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

28+
#include <osmium/osm/crc.hpp>
29+
#include <osmium/osm/crc_zlib.hpp>
30+
2831
#include <string>
2932
#include <vector>
3033

3134
class CommandDiff : public CommandWithMultipleOSMInputs, public with_osm_output {
3235

3336
std::string m_output_action;
37+
bool m_ignore_attrs_changeset = false;
38+
bool m_ignore_attrs_uid = false;
39+
bool m_ignore_attrs_user = false;
3440
bool m_show_summary = false;
3541
bool m_suppress_common = false;
3642

43+
void update_object_crc(osmium::CRC<osmium::CRC_zlib>* crc, const osmium::OSMObject &object);
44+
3745
public:
3846

3947
explicit CommandDiff(const CommandFactory& command_factory) :

test/diff/CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,12 @@ check_diff(opl-c "-f opl -c" input1.osm input2.osm output-c.opl 1)
2020

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

23+
check_diff(ignore-uid "--ignore-uid -c" input1.osm input2.osm output-compact-c-nouid 1)
24+
25+
check_diff(ignore-uid-15 "--ignore-uid -c" input1uid.osm input2uid.osm output-empty 0)
26+
27+
check_diff(ignore-uid-opl "--ignore-uid -f opl -c" input1.osm input2.osm output-compact-c-nouid-opl 1)
28+
29+
check_diff(ignore-uid-15-opl "--ignore-uid -f opl -c" input1uid.osm input2uid.osm output-empty 0)
30+
2331
#-----------------------------------------------------------------------------

test/diff/input1uid.osm

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?xml version='1.0' encoding='UTF-8'?>
2+
<osm version="0.6" upload="false" generator="testdata">
3+
<node id="15" version="1" timestamp="2015-01-01T02:00:00Z" uid="2" user="test" changeset="1" lat="5" lon="1"/>
4+
</osm>

test/diff/input2.osm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version='1.0' encoding='UTF-8'?>
2-
<osm version="0.6" generator="test">
2+
<osm version="0.6" upload="false" generator="testdata">
33
<node id="10" version="1" timestamp="2015-01-01T01:00:00Z" uid="1" user="test" changeset="1" lat="1" lon="1"/>
44
<node id="11" version="2" timestamp="2015-01-01T02:00:00Z" uid="1" user="test" changeset="2" lat="2" lon="2"/>
55
<node id="12" version="1" timestamp="2015-01-01T01:00:00Z" uid="1" user="test" changeset="1" lat="3" lon="1"/>

test/diff/input2uid.osm

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?xml version='1.0' encoding='UTF-8'?>
2+
<osm version="0.6" upload="false" generator="testdata">
3+
<node id="15" version="1" timestamp="2015-01-01T02:00:00Z" uid="1" user="test" changeset="1" lat="5" lon="1"/>
4+
</osm>

test/diff/output-compact-c-nouid

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
-n11 v1
2+
+n11 v2
3+
-n13 v1
4+
+n14 v1
5+
*n16 v1
6+
-w21 v1
7+
+w21 v2
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
-n11 v1 dV c1 t2015-01-01T01:00:00Z utest T x1 y2
2+
+n11 v2 dV c2 t2015-01-01T02:00:00Z utest T x2 y2
3+
-n13 v1 dV c1 t2015-01-01T01:00:00Z utest T x1 y4
4+
+n14 v1 dV c2 t2015-01-01T02:00:00Z utest T x1 y5
5+
-n16 v1 dV c1 t2015-01-01T02:00:00Z utest T x2 y5
6+
+n16 v1 dV c1 t2015-01-01T02:00:00Z utest T x1 y5
7+
-w21 v1 dV c1 t2015-01-01T01:00:00Z utest Txyz=abc Nn12,n13
8+
+w21 v2 dV c2 t2015-01-01T02:00:00Z utest Txyz=new Nn12,n14

test/diff/output-empty

Whitespace-only changes.

0 commit comments

Comments
 (0)