Changeset 19228 in josm


Ignore:
Timestamp:
2024-09-20T14:06:54+02:00 (2 months ago)
Author:
taylor.smock
Message:

Fix #23930: Merging duplicated layers with little differences stalls JOSM

This is fixed by keeping the "last" conflict in the problem if statement body.

Location:
trunk
Files:
2 added
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/osm/DataSetMerger.java

    r19175 r19228  
    141141    protected void addConflict(OsmPrimitive my, OsmPrimitive their) {
    142142        addConflict(new Conflict<>(my, their));
     143    }
     144
     145    private void replaceConflict(Conflict<?> oldConflict, Conflict<?> newConflict) {
     146        newConflict.setMergedMap(mergedMap);
     147        conflicts.remove(oldConflict);
     148        conflicts.add(newConflict);
    143149    }
    144150
     
    326332            // otherwise too many conflicts when refreshing from the server
    327333            // but, if source is modified, there is a conflict
     334            Conflict<?> currentConflict = null;
    328335            if (source.isModified()) {
    329                 addConflict(new Conflict<>(target, source, true));
     336                currentConflict = new Conflict<>(target, source, true);
     337                addConflict(currentConflict);
    330338            }
    331339            // or, if source has a referrer that is not in the target dataset there is a conflict
     
    333341            for (OsmPrimitive referrer: source.getReferrers()) {
    334342                if (targetDataSet.getPrimitiveById(referrer.getPrimitiveId()) == null) {
    335                     addConflict(new Conflict<>(target, source, true));
     343                    final Conflict<?> newConflict = new Conflict<>(target, source, true);
     344                    if (currentConflict != null) { // See #23930
     345                        replaceConflict(currentConflict, newConflict);
     346                    } else {
     347                        addConflict(newConflict);
     348                    }
    336349                    target.setDeleted(false);
    337350                    break;
  • trunk/test/unit/org/openstreetmap/josm/data/osm/DataSetMergerTest.java

    r19175 r19228  
    22package org.openstreetmap.josm.data.osm;
    33
     4import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
    45import static org.junit.jupiter.api.Assertions.assertEquals;
    56import static org.junit.jupiter.api.Assertions.assertFalse;
     7import static org.junit.jupiter.api.Assertions.assertInstanceOf;
    68import static org.junit.jupiter.api.Assertions.assertNotNull;
    79import static org.junit.jupiter.api.Assertions.assertNotSame;
     
    1113import static org.junit.jupiter.api.Assertions.fail;
    1214
     15import java.io.File;
     16import java.io.IOException;
    1317import java.io.StringWriter;
    1418import java.time.Instant;
    1519import java.util.Arrays;
     20import java.util.List;
    1621import java.util.function.BiConsumer;
     22import java.util.stream.Collectors;
    1723import java.util.stream.Stream;
    1824
     
    2228import org.junit.jupiter.params.ParameterizedTest;
    2329import org.junit.jupiter.params.provider.MethodSource;
     30import org.openstreetmap.josm.TestUtils;
     31import org.openstreetmap.josm.data.conflict.Conflict;
     32import org.openstreetmap.josm.data.conflict.ConflictCollection;
    2433import org.openstreetmap.josm.data.coor.LatLon;
    2534import org.openstreetmap.josm.data.projection.ProjectionRegistry;
    2635import org.openstreetmap.josm.data.projection.Projections;
     36import org.openstreetmap.josm.gui.layer.OsmDataLayer;
    2737import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
     38import org.openstreetmap.josm.io.IllegalDataException;
     39import org.openstreetmap.josm.io.session.SessionReader;
     40import org.openstreetmap.josm.tools.Logging;
    2841
    2942/**
     
    13611374    }
    13621375
    1363     static Stream<BiConsumer<Node, Node>> testNonRegression23846() {
     1376    static Stream<BiConsumer<Node, Node>> testTicket23846() {
    13641377        return Stream.of(
    13651378                (firstNode, secondNode) -> firstNode.setModified(true),
     
    13701383    @ParameterizedTest
    13711384    @MethodSource
    1372     void testNonRegression23846(BiConsumer<Node, Node> nodeSetup) {
     1385    void testTicket23846(BiConsumer<Node, Node> nodeSetup) {
    13731386        final Node firstNode = new Node(1234, 1);
    13741387        final Node secondNode = new Node(1234, 1);
     
    13861399        assertTrue(secondNode.isReferrersDownloaded());
    13871400    }
     1401
     1402    /**
     1403     * Non-regression test for <a href="https://josm.openstreetmap.de/ticket/23930">#23930</a>
     1404     */
     1405    @Test
     1406    void testTicket23930() throws IOException, IllegalDataException {
     1407        final File file = new File(TestUtils.getRegressionDataFile(23930, "JOSM_conflict.joz"));
     1408        final SessionReader reader = new SessionReader();
     1409        reader.loadSession(file, true, NullProgressMonitor.INSTANCE);
     1410        final List<OsmDataLayer> layers = reader.getLayers().stream()
     1411                .filter(OsmDataLayer.class::isInstance).map(OsmDataLayer.class::cast).collect(Collectors.toList());
     1412        final DataSet newWay = layers.stream().filter(layer -> layer.getName().equals("new_way.osm"))
     1413                .map(OsmDataLayer::getDataSet).findFirst().orElseThrow();
     1414        final DataSet nodeDeleted = layers.stream().filter(layer -> layer.getName().equals("node_deleted.osm"))
     1415                .map(OsmDataLayer::getDataSet).findFirst().orElseThrow();
     1416        final DataSetMerger merge = new DataSetMerger(nodeDeleted, newWay);
     1417        Logging.clearLastErrorAndWarnings();
     1418        assertDoesNotThrow(() -> merge.merge(NullProgressMonitor.INSTANCE));
     1419        assertTrue(Logging.getLastErrorAndWarnings().isEmpty(), String.join("\n", Logging.getLastErrorAndWarnings()));
     1420        final ConflictCollection conflicts = merge.getConflicts();
     1421        // There are a few differences in the files
     1422        // 1. New node in layer 2: No need for conflict
     1423        // 2. node 2427358529: layer 1 deletes it, layer 2 modifies it (conflict required)
     1424        // 3. new way in layer 2 with new node and node 2427358529 (conflict required)
     1425        // 4. Modification of way 32277602 in layer 1 removing node 2427358529 (conflict required)
     1426        // Therefore, conflicts are as follows:
     1427        // 1. A deleted node (n2427358529) with referrers (w32277602 and new way) and new tags ("fix tag=recheck position")
     1428        assertEquals(1, conflicts.size());
     1429        final Conflict<?> conflict = conflicts.iterator().next();
     1430        final Node myNode = assertInstanceOf(Node.class, conflict.getMy());
     1431        final Node theirNode = assertInstanceOf(Node.class, conflict.getTheir());
     1432        assertFalse(theirNode.isDeleted());
     1433        assertFalse(myNode.isDeleted());
     1434    }
    13881435}
Note: See TracChangeset for help on using the changeset viewer.