OTAlgorithms { public static <K, D> Promise<List<D>> diff(OTRepository<K, D> repository, OTSystem<D> system, K node1, K node2) { Set<K> startCut = set(node1, node2); return reduce(repository, system, startCut, new FindAnyCommonParentReducer<>(DiffsReducer.toList())) .map(entry -> { List<D> diffs1 = entry.getValue().get(node1); List<D> diffs2 = entry.getValue().get(node2); return concat(diffs2, system.invert(diffs1)); }) .whenComplete(toLogger(logger, thisMethod(), startCut)); }  static Promise<R> reduce(OTRepository<K, D> repository, OTSystem<D> system,
			Set<K> heads, GraphReducer<K, D, R> reducer); static Promise<FindResult<K, A>> findParent(OTRepository<K, D> repository, OTSystem<D> system,
			Set<K> startNodes, DiffsReducer<A, D> diffsReducer, AsyncPredicate<OTCommit<K, D>> matchPredicate); static Promise<K> mergeAndPush(OTRepository<K, D> repository, OTSystem<D> system); static Promise<K> mergeAndPush(OTRepository<K, D> repository, OTSystem<D> system, @NotNull Set<K> heads); static Promise<K> mergeAndUpdateHeads(OTRepository<K, D> repository, OTSystem<D> system); static Promise<K> mergeAndUpdateHeads(OTRepository<K, D> repository, OTSystem<D> system, Set<K> heads); @NotNull static Promise<OTCommit<K, D>> merge(OTRepository<K, D> repository, OTSystem<D> system, @NotNull Set<K> heads); static Promise<Set<K>> findCut(OTRepository<K, D> repository, OTSystem<D> system, Set<K> startNodes,
			Predicate<Collection<OTCommit<K, D>>> matchPredicate); static Promise<K> findAnyCommonParent(OTRepository<K, D> repository, OTSystem<D> system, Set<K> startCut); static Promise<Set<K>> findAllCommonParents(OTRepository<K, D> repository, OTSystem<D> system, Set<K> startCut); static Promise<List<D>> diff(OTRepository<K, D> repository, OTSystem<D> system, K node1, K node2); static Promise<Set<K>> excludeParents(OTRepository<K, D> repository, OTSystem<D> system, Set<K> startNodes); static Promise<Map<K, A>> reduceEdges(OTRepository<K, D> repository, OTSystem<D> system, Set<K> heads, K parentNode,
			DiffsReducer<A, D> diffAccumulator); static Promise<List<D>> checkout(OTRepository<K, D> repository, OTSystem<D> system); static Promise<List<D>> checkout(OTRepository<K, D> repository, OTSystem<D> system, K commitId); static Promise<Void> saveSnapshot(OTRepository<K, D> repository, OTSystem<D> system, K revisionId); static Promise<OTLoadedGraph<K, D>> loadForMerge(OTRepository<K, D> repository, OTSystem<D> system, Set<K> heads); static Promise<OTLoadedGraph<K, D>> loadGraph(OTRepository<K, D> repository, OTSystem<D> system, Set<K> heads, OTLoadedGraph<K, D> graph); static Promise<OTLoadedGraph<K, D>> loadGraph(OTRepository<K, D> repository, OTSystem<D> system, Set<K> heads); static Promise<OTLoadedGraph<K, D>> loadGraph(OTRepository<K, D> repository, OTSystem<D> system, Set<K> heads, Function<K, String> idToString, Function<D, String> diffToString); static Promise<Void> copy(OTRepository<K, D> from, OTRepository<K, D> to); static final StacklessException GRAPH_EXHAUSTED; }
@Test public void testDiffBetween() { graph1(); List<TestOp> diff = await(diff(REPOSITORY, TEST_OP, 5, 9)); assertEquals(applyToState(asList(add(10))), applyToState(diff)); diff = await(diff(REPOSITORY, TEST_OP, 5, 0)); assertEquals(applyToState(asList(add(-6))), applyToState(diff)); diff = await(diff(REPOSITORY, TEST_OP, 5, 6)); assertEquals(applyToState(asList(add(+3))), applyToState(diff)); diff = await(diff(REPOSITORY, TEST_OP, 5, 5)); assertEquals(emptyList(), diff); graph2(); diff = await(diff(REPOSITORY, TEST_OP, 6, 3)); assertEquals(applyToState(asList(add(-2))), applyToState(diff)); diff = await(diff(REPOSITORY, TEST_OP, 0, 6)); assertEquals(applyToState(asList(add(5))), applyToState(diff)); diff = await(diff(REPOSITORY, TEST_OP, 4, 5)); assertEquals(applyToState(emptyList()), applyToState(diff)); diff = await(diff(REPOSITORY, TEST_OP, 3, 2)); assertEquals(applyToState(asList(add(-1))), applyToState(diff)); }