@Test void applyDecisionsOnLinesConflicts() throws Exception { MergeResult<String> result; MergeConfiguration<String> mergeConfiguration; result = diffManager.merge( Arrays.asList("Line 1", "Line 2", "Line 3"), Arrays.asList("Line 1", "Line 2 modified", "Line 3"), Arrays.asList("Line 1", "Line 2 another change", "Line 3"), null); assertEquals(1, result.getLog().getLogs(LogLevel.ERROR).size()); assertEquals(1, result.getConflicts().size()); Conflict<String> conflict = createConflict(1, "Line 2", "Line 2 another change", "Line 2 modified"); assertEquals(conflict, result.getConflicts().get(0)); assertEquals(Arrays.asList("Line 1", "Line 2 another change", "Line 3"), result.getMerged()); ConflictDecision<String> conflictDecision = new DefaultConflictDecision<>(conflict); conflictDecision.setType(ConflictDecision.DecisionType.PREVIOUS); List<ConflictDecision<String>> conflictDecisionList = new ArrayList<>(); conflictDecisionList.add(conflictDecision); mergeConfiguration = new MergeConfiguration<>(conflictDecisionList); result = diffManager.merge( Arrays.asList("Line 1", "Line 2", "Line 3"), Arrays.asList("Line 1", "Line 2 modified", "Line 3"), Arrays.asList("Line 1", "Line 2 another change", "Line 3"), mergeConfiguration); assertTrue(result.getConflicts().isEmpty()); assertTrue(result.getLog().getLogs(LogLevel.ERROR).isEmpty()); assertEquals(Arrays.asList("Line 1", "Line 2", "Line 3"), result.getMerged()); conflictDecision.setType(ConflictDecision.DecisionType.NEXT); result = diffManager.merge( Arrays.asList("Line 1", "Line 2", "Line 3"), Arrays.asList("Line 1", "Line 2 modified", "Line 3"), Arrays.asList("Line 1", "Line 2 another change", "Line 3"), mergeConfiguration); assertTrue(result.getConflicts().isEmpty()); assertTrue(result.getLog().getLogs(LogLevel.ERROR).isEmpty()); assertEquals(Arrays.asList("Line 1", "Line 2 modified", "Line 3"), result.getMerged()); conflictDecision.setType(ConflictDecision.DecisionType.CURRENT); result = diffManager.merge( Arrays.asList("Line 1", "Line 2", "Line 3"), Arrays.asList("Line 1", "Line 2 modified", "Line 3"), Arrays.asList("Line 1", "Line 2 another change", "Line 3"), mergeConfiguration); assertTrue(result.getConflicts().isEmpty()); assertTrue(result.getLog().getLogs(LogLevel.ERROR).isEmpty()); assertEquals(Arrays.asList("Line 1", "Line 2 another change", "Line 3"), result.getMerged()); conflictDecision.setType(ConflictDecision.DecisionType.UNDECIDED); result = diffManager.merge( Arrays.asList("Line 1", "Line 2", "Line 3"), Arrays.asList("Line 1", "Line 2 modified", "Line 3"), Arrays.asList("Line 1", "Line 2 another change", "Line 3"), mergeConfiguration); assertEquals(1, result.getLog().getLogs(LogLevel.ERROR).size()); assertEquals(1, result.getConflicts().size()); assertEquals(conflict, result.getConflicts().get(0)); assertEquals(Arrays.asList("Line 1", "Line 2 another change", "Line 3"), result.getMerged()); conflictDecision.setCustom(Arrays.asList("Another complete custom change", "and a line")); result = diffManager.merge( Arrays.asList("Line 1", "Line 2", "Line 3"), Arrays.asList("Line 1", "Line 2 modified", "Line 3"), Arrays.asList("Line 1", "Line 2 another change", "Line 3"), mergeConfiguration); assertTrue(result.getConflicts().isEmpty()); assertTrue(result.getLog().getLogs(LogLevel.ERROR).isEmpty()); assertEquals(Arrays.asList("Line 1", "Another complete custom change", "and a line", "Line 3"), result.getMerged()); conflictDecisionList = new ArrayList<>(); conflict = this.createConflict(1, Type.CHANGE, 1, 1, Arrays.asList("Second line.", "Third line."), Arrays.asList("Second line.", "Line N°4"), Type.CHANGE, 1, 1, Arrays.asList("Second line.", "Third line."), Arrays.asList("Line N°2", "Third line.")); conflictDecision = new DefaultConflictDecision<>(conflict); conflictDecision.setCustom(Arrays.asList("Something", "Completely", "Different")); conflictDecisionList.add(conflictDecision); Conflict<String> conflict2 = this.createConflict(5, Type.CHANGE, 5, 5, Collections.emptyList(), Arrays.asList("6th line."), Type.CHANGE, 5, 5, Collections.emptyList(), Arrays.asList("Sixth line.")); conflictDecision = new DefaultConflictDecision<>(conflict2); conflictDecision.setType(ConflictDecision.DecisionType.PREVIOUS); conflictDecisionList.add(conflictDecision); mergeConfiguration = new MergeConfiguration<>(conflictDecisionList); result = this.diffManager.merge( Arrays.asList( "First line.", "Second line.", "Third line.", "Fourth line.", "Fifth line.", "Seventh line." ), Arrays.asList( "First line.", "Line N°2", "Third line.", "Fifth line.", "Sixth line.", "Seventh line." ), Arrays.asList( "First line.", "Second line.", "Line N°4", "Fifth line.", "6th line.", "Seventh line." ), mergeConfiguration); assertEquals(0, result.getConflicts().size()); assertEquals(Arrays.asList( "First line.", "Something", "Completely", "Different", "Fifth line.", "Seventh line." ), result.getMerged()); }
@Override public <E> MergeResult<E> merge(List<E> commonAncestor, List<E> next, List<E> current, MergeConfiguration<E> configuration) throws MergeException { DefaultMergeResult<E> mergeResult = new DefaultMergeResult<>(commonAncestor, next, current); DiffResult<E> diffNextResult; try { diffNextResult = diff(commonAncestor, next, null); } catch (DiffException e) { throw new MergeException("Faile to diff between common ancestor and next version", e); } mergeResult.getLog().addAll(diffNextResult.getLog()); Patch<E> patchNext = diffNextResult.getPatch(); if (patchNext.isEmpty()) { return mergeResult; } if (current.isEmpty() && (commonAncestor.isEmpty() || next.isEmpty())) { if (commonAncestor.isEmpty()) { mergeResult.setMerged(next); } else if (next.isEmpty()) { mergeResult.getLog().warn("The modification was already applied"); } } else { DiffResult<E> diffCurrentResult; try { diffCurrentResult = diff(commonAncestor, current, null); } catch (DiffException e) { throw new MergeException("Fail to diff between common ancestor and current version", e); } mergeResult.getLog().addAll(diffCurrentResult.getLog()); Patch<E> patchCurrent = diffCurrentResult.getPatch(); mergeResult.setMerged(new ArrayList<>()); if (patchCurrent.isEmpty()) { mergeResult.setMerged(next); } else if (!current.equals(next) && (isFullyModified(commonAncestor, patchCurrent) || isFullyModified(commonAncestor, patchNext))) { Delta<E> deltaNext = nextElement(patchNext); Delta<E> deltaCurrent = nextElement(patchCurrent); List<ConflictDecision<E>> conflictDecisionList = (configuration != null) ? configuration.getConflictDecisionList() : Collections.emptyList(); int newIndex = applyDecision(conflictDecisionList, mergeResult.getMerged(), 0); if (newIndex == Integer.MIN_VALUE) { logConflict(mergeResult, deltaCurrent, deltaNext, commonAncestor, next, current, 0); mergeResult.setMerged(fallback(commonAncestor, next, current, configuration)); } } else { merge(mergeResult, commonAncestor, next, current, patchNext, patchCurrent, configuration); } } return mergeResult; }
DefaultDiffManager implements DiffManager { @Override public <E> MergeResult<E> merge(List<E> commonAncestor, List<E> next, List<E> current, MergeConfiguration<E> configuration) throws MergeException { DefaultMergeResult<E> mergeResult = new DefaultMergeResult<>(commonAncestor, next, current); DiffResult<E> diffNextResult; try { diffNextResult = diff(commonAncestor, next, null); } catch (DiffException e) { throw new MergeException("Faile to diff between common ancestor and next version", e); } mergeResult.getLog().addAll(diffNextResult.getLog()); Patch<E> patchNext = diffNextResult.getPatch(); if (patchNext.isEmpty()) { return mergeResult; } if (current.isEmpty() && (commonAncestor.isEmpty() || next.isEmpty())) { if (commonAncestor.isEmpty()) { mergeResult.setMerged(next); } else if (next.isEmpty()) { mergeResult.getLog().warn("The modification was already applied"); } } else { DiffResult<E> diffCurrentResult; try { diffCurrentResult = diff(commonAncestor, current, null); } catch (DiffException e) { throw new MergeException("Fail to diff between common ancestor and current version", e); } mergeResult.getLog().addAll(diffCurrentResult.getLog()); Patch<E> patchCurrent = diffCurrentResult.getPatch(); mergeResult.setMerged(new ArrayList<>()); if (patchCurrent.isEmpty()) { mergeResult.setMerged(next); } else if (!current.equals(next) && (isFullyModified(commonAncestor, patchCurrent) || isFullyModified(commonAncestor, patchNext))) { Delta<E> deltaNext = nextElement(patchNext); Delta<E> deltaCurrent = nextElement(patchCurrent); List<ConflictDecision<E>> conflictDecisionList = (configuration != null) ? configuration.getConflictDecisionList() : Collections.emptyList(); int newIndex = applyDecision(conflictDecisionList, mergeResult.getMerged(), 0); if (newIndex == Integer.MIN_VALUE) { logConflict(mergeResult, deltaCurrent, deltaNext, commonAncestor, next, current, 0); mergeResult.setMerged(fallback(commonAncestor, next, current, configuration)); } } else { merge(mergeResult, commonAncestor, next, current, patchNext, patchCurrent, configuration); } } return mergeResult; } }
DefaultDiffManager implements DiffManager { @Override public <E> MergeResult<E> merge(List<E> commonAncestor, List<E> next, List<E> current, MergeConfiguration<E> configuration) throws MergeException { DefaultMergeResult<E> mergeResult = new DefaultMergeResult<>(commonAncestor, next, current); DiffResult<E> diffNextResult; try { diffNextResult = diff(commonAncestor, next, null); } catch (DiffException e) { throw new MergeException("Faile to diff between common ancestor and next version", e); } mergeResult.getLog().addAll(diffNextResult.getLog()); Patch<E> patchNext = diffNextResult.getPatch(); if (patchNext.isEmpty()) { return mergeResult; } if (current.isEmpty() && (commonAncestor.isEmpty() || next.isEmpty())) { if (commonAncestor.isEmpty()) { mergeResult.setMerged(next); } else if (next.isEmpty()) { mergeResult.getLog().warn("The modification was already applied"); } } else { DiffResult<E> diffCurrentResult; try { diffCurrentResult = diff(commonAncestor, current, null); } catch (DiffException e) { throw new MergeException("Fail to diff between common ancestor and current version", e); } mergeResult.getLog().addAll(diffCurrentResult.getLog()); Patch<E> patchCurrent = diffCurrentResult.getPatch(); mergeResult.setMerged(new ArrayList<>()); if (patchCurrent.isEmpty()) { mergeResult.setMerged(next); } else if (!current.equals(next) && (isFullyModified(commonAncestor, patchCurrent) || isFullyModified(commonAncestor, patchNext))) { Delta<E> deltaNext = nextElement(patchNext); Delta<E> deltaCurrent = nextElement(patchCurrent); List<ConflictDecision<E>> conflictDecisionList = (configuration != null) ? configuration.getConflictDecisionList() : Collections.emptyList(); int newIndex = applyDecision(conflictDecisionList, mergeResult.getMerged(), 0); if (newIndex == Integer.MIN_VALUE) { logConflict(mergeResult, deltaCurrent, deltaNext, commonAncestor, next, current, 0); mergeResult.setMerged(fallback(commonAncestor, next, current, configuration)); } } else { merge(mergeResult, commonAncestor, next, current, patchNext, patchCurrent, configuration); } } return mergeResult; }  }
DefaultDiffManager implements DiffManager { @Override public <E> MergeResult<E> merge(List<E> commonAncestor, List<E> next, List<E> current, MergeConfiguration<E> configuration) throws MergeException { DefaultMergeResult<E> mergeResult = new DefaultMergeResult<>(commonAncestor, next, current); DiffResult<E> diffNextResult; try { diffNextResult = diff(commonAncestor, next, null); } catch (DiffException e) { throw new MergeException("Faile to diff between common ancestor and next version", e); } mergeResult.getLog().addAll(diffNextResult.getLog()); Patch<E> patchNext = diffNextResult.getPatch(); if (patchNext.isEmpty()) { return mergeResult; } if (current.isEmpty() && (commonAncestor.isEmpty() || next.isEmpty())) { if (commonAncestor.isEmpty()) { mergeResult.setMerged(next); } else if (next.isEmpty()) { mergeResult.getLog().warn("The modification was already applied"); } } else { DiffResult<E> diffCurrentResult; try { diffCurrentResult = diff(commonAncestor, current, null); } catch (DiffException e) { throw new MergeException("Fail to diff between common ancestor and current version", e); } mergeResult.getLog().addAll(diffCurrentResult.getLog()); Patch<E> patchCurrent = diffCurrentResult.getPatch(); mergeResult.setMerged(new ArrayList<>()); if (patchCurrent.isEmpty()) { mergeResult.setMerged(next); } else if (!current.equals(next) && (isFullyModified(commonAncestor, patchCurrent) || isFullyModified(commonAncestor, patchNext))) { Delta<E> deltaNext = nextElement(patchNext); Delta<E> deltaCurrent = nextElement(patchCurrent); List<ConflictDecision<E>> conflictDecisionList = (configuration != null) ? configuration.getConflictDecisionList() : Collections.emptyList(); int newIndex = applyDecision(conflictDecisionList, mergeResult.getMerged(), 0); if (newIndex == Integer.MIN_VALUE) { logConflict(mergeResult, deltaCurrent, deltaNext, commonAncestor, next, current, 0); mergeResult.setMerged(fallback(commonAncestor, next, current, configuration)); } } else { merge(mergeResult, commonAncestor, next, current, patchNext, patchCurrent, configuration); } } return mergeResult; }  @Override DiffResult<E> diff(List<E> previous, List<E> next, DiffConfiguration<E> diff); @Override MergeResult<E> merge(List<E> commonAncestor, List<E> next, List<E> current,
        MergeConfiguration<E> configuration); }
DefaultDiffManager implements DiffManager { @Override public <E> MergeResult<E> merge(List<E> commonAncestor, List<E> next, List<E> current, MergeConfiguration<E> configuration) throws MergeException { DefaultMergeResult<E> mergeResult = new DefaultMergeResult<>(commonAncestor, next, current); DiffResult<E> diffNextResult; try { diffNextResult = diff(commonAncestor, next, null); } catch (DiffException e) { throw new MergeException("Faile to diff between common ancestor and next version", e); } mergeResult.getLog().addAll(diffNextResult.getLog()); Patch<E> patchNext = diffNextResult.getPatch(); if (patchNext.isEmpty()) { return mergeResult; } if (current.isEmpty() && (commonAncestor.isEmpty() || next.isEmpty())) { if (commonAncestor.isEmpty()) { mergeResult.setMerged(next); } else if (next.isEmpty()) { mergeResult.getLog().warn("The modification was already applied"); } } else { DiffResult<E> diffCurrentResult; try { diffCurrentResult = diff(commonAncestor, current, null); } catch (DiffException e) { throw new MergeException("Fail to diff between common ancestor and current version", e); } mergeResult.getLog().addAll(diffCurrentResult.getLog()); Patch<E> patchCurrent = diffCurrentResult.getPatch(); mergeResult.setMerged(new ArrayList<>()); if (patchCurrent.isEmpty()) { mergeResult.setMerged(next); } else if (!current.equals(next) && (isFullyModified(commonAncestor, patchCurrent) || isFullyModified(commonAncestor, patchNext))) { Delta<E> deltaNext = nextElement(patchNext); Delta<E> deltaCurrent = nextElement(patchCurrent); List<ConflictDecision<E>> conflictDecisionList = (configuration != null) ? configuration.getConflictDecisionList() : Collections.emptyList(); int newIndex = applyDecision(conflictDecisionList, mergeResult.getMerged(), 0); if (newIndex == Integer.MIN_VALUE) { logConflict(mergeResult, deltaCurrent, deltaNext, commonAncestor, next, current, 0); mergeResult.setMerged(fallback(commonAncestor, next, current, configuration)); } } else { merge(mergeResult, commonAncestor, next, current, patchNext, patchCurrent, configuration); } } return mergeResult; }  @Override DiffResult<E> diff(List<E> previous, List<E> next, DiffConfiguration<E> diff); @Override MergeResult<E> merge(List<E> commonAncestor, List<E> next, List<E> current,
        MergeConfiguration<E> configuration);  }