source: subversion/applications/utils/revert/Revert.pm @ 15672

Last change on this file since 15672 was 15672, checked in by frederik, 10 years ago

bugfix revert.pm

File size: 3.1 KB
Line 
1#!/usr/bin/perl
2
3# Revert.pm
4# ---------
5#
6# Implements whole changeset reverts
7#
8# Part of the "osmtools" suite of programs
9# Originally written by Frederik Ramm <frederik@remote.org>; public domain
10
11package Revert;
12
13use strict;
14use warnings;
15
16use OsmApi;
17use Undo;
18
19# downloads a changeset and attempts to undo all changes
20# within that. currently transaction-based, so the revert will
21# fail if it cannot be done cleanly, but see variable $transaction.
22#
23# parameters:
24#   $undo_changeset: the changeset to nuke
25#   $changeset: the changeset in which the undo happens (must be open)
26# return:
27#   success=1 failure=undef
28
29sub revert
30{
31    my ($undo_changeset, $changeset) = @_;
32
33    my $resp = OsmApi::get("changeset/$undo_changeset/download");
34    if (!$resp->is_success)
35    {
36        print STDERR "changeset $undo_changeset cannot be retrieved: ".$resp->status_line."\n";
37        return undef;
38    }
39
40    my $objects = {};
41    my $action;
42
43    foreach (split(/\n/, $resp->content()))
44    { 
45        if (/<(modify|create|delete)/)
46        {
47            $action = $1;
48        }
49        elsif (/<(node|way|relation).*\sid=["'](\d+)["']/)
50        {
51            unshift(@{$objects->{"$action $1"}}, $2);
52        }
53    }
54
55    # first undelete nodes, ways, relations;
56    # then undo changes to nodes, ways, relations;
57    # then undo creations of relations, ways, nodes (note order).
58
59    my $success = [];
60    my $failure = [];
61    my $transaction = 1;
62    my $oscpart;
63
64    foreach my $operation("delete node", "delete way", "delete relation",
65        "modify node", "modify way", "modify relation", 
66        "create relation", "create way", "create node")
67    {
68        foreach my $object(@{$objects->{$operation}})
69        {
70            my ($dummy, $objtype) = split(/ /, $operation);
71            if ($transaction)
72            {
73                # this collects all undos in one osc document.
74                my ($action, $xml) = Undo::determine_undo_action($objtype, $object, undef, $undo_changeset, $changeset);
75                return undef unless (defined($action));
76                $oscpart->{$action} .= $xml;
77            }
78            else
79            {
80                # this does individual undo operations. currently unused!
81                if (Undo::undo($objtype, $object, undef, $undo_changeset, $changeset))
82                {
83                    push(@$success, "$operation $object");
84                }
85                else
86                {
87                    push(@$failure, "$operation $object");
88                }
89            }
90        }
91    }
92
93    if ($transaction)
94    {
95        my $osc = "<osmChange version='0.6' generator='osmtools'>\n";
96        foreach my $action("modify", "create", "delete")
97        {
98            if (defined($oscpart->{$action}))
99            {
100                $osc .= "<$action>\n".$oscpart->{$action}."</$action>\n";
101            }
102        }
103        $osc .= "</osmChange>\n";
104        my $res = OsmApi::post("changeset/$changeset/upload", $osc);
105        if (!($res->is_success))
106        {
107            print STDERR "changeset upload failed: ".$res->status_line."\n";
108            return undef;
109        }
110    }
111   
112    return 1;
113}
114
1151;
Note: See TracBrowser for help on using the repository browser.