public void removeOutgoingEdges() {
   for (DependencyEdge outgoingDependency : outgoingEdges) {
     outgoingDependency.removeFromTargetConfigurations();
   }
   outgoingEdges.clear();
   previousTraversal = null;
 }
    public void visitOutgoingDependencies(Collection<DependencyEdge> target) {
      // If this configuration's version is in conflict, don't do anything
      // If not traversed before, add all selected outgoing edges
      // If traversed before, and the selected modules have changed, remove previous outgoing edges
      // and add outgoing edges again with
      //    the new selections.
      // If traversed before, and the selected modules have not changed, ignore
      // If none of the incoming edges are transitive, then the node has no outgoing edges

      if (moduleRevision.state != ModuleState.Selected) {
        LOGGER.debug("version for {} is not selected. ignoring.", this);
        return;
      }

      List<DependencyEdge> transitiveIncoming = new ArrayList<DependencyEdge>();
      for (DependencyEdge edge : incomingEdges) {
        if (edge.isTransitive()) {
          transitiveIncoming.add(edge);
        }
      }

      if (transitiveIncoming.isEmpty() && this != resolveState.root) {
        if (previousTraversal != null) {
          removeOutgoingEdges();
        }
        if (incomingEdges.isEmpty()) {
          LOGGER.debug("{} has no incoming edges. ignoring.", this);
        } else {
          LOGGER.debug("{} has no transitive incoming edges. ignoring outgoing edges.", this);
        }
        return;
      }

      ModuleResolutionFilter resolutionFilter = getSelector(transitiveIncoming);
      if (previousTraversal != null) {
        if (previousTraversal.acceptsSameModulesAs(resolutionFilter)) {
          LOGGER.debug(
              "Changed edges for {} selects same versions as previous traversal. ignoring", this);
          // Don't need to traverse again, but hang on to the new filter as the set of artifact may
          // have changed
          previousTraversal = resolutionFilter;
          return;
        }
        removeOutgoingEdges();
      }

      for (DependencyMetaData dependency : metaData.getDependencies()) {
        ModuleIdentifier targetModuleId =
            DefaultModuleIdentifier.newId(
                dependency.getRequested().getGroup(), dependency.getRequested().getName());
        if (isExcluded(resolutionFilter, targetModuleId)) {
          continue;
        }
        DependencyEdge dependencyEdge =
            new DependencyEdge(this, dependency, resolutionFilter, resolveState);
        outgoingEdges.add(dependencyEdge);
        target.add(dependencyEdge);
      }
      previousTraversal = resolutionFilter;
    }
    public void visitOutgoingDependencies(Collection<DependencyEdge> target) {
      // If this configuration's version is in conflict, don't do anything
      // If not traversed before, add all selected outgoing edges
      // If traversed before, and the selected modules have changed, remove previous outgoing edges
      // and add outgoing edges again with
      //    the new selections.
      // If traversed before, and the selected modules have not changed, ignore
      // If none of the incoming edges are transitive, then the node has no outgoing edges

      if (moduleRevision.state != ModuleState.Selected) {
        LOGGER.debug("version for {} is not selected. ignoring.", this);
        return;
      }

      List<DependencyEdge> transitiveIncoming = new ArrayList<DependencyEdge>();
      for (DependencyEdge edge : incomingEdges) {
        if (edge.isTransitive()) {
          transitiveIncoming.add(edge);
        }
      }

      if (transitiveIncoming.isEmpty() && this != resolveState.root) {
        if (previousTraversal != null) {
          removeOutgoingEdges();
        }
        if (incomingEdges.isEmpty()) {
          LOGGER.debug("{} has no incoming edges. ignoring.", this);
        } else {
          LOGGER.debug("{} has no transitive incoming edges. ignoring outgoing edges.", this);
        }
        return;
      }

      ModuleVersionSpec selectorSpec = getSelector(transitiveIncoming);
      if (previousTraversal != null) {
        if (previousTraversal.acceptsSameModulesAs(selectorSpec)) {
          LOGGER.debug(
              "Changed edges for {} selects same versions as previous traversal. ignoring", this);
          return;
        }
        removeOutgoingEdges();
      }

      for (DependencyMetaData dependency : metaData.getDependencies()) {
        DependencyDescriptor dependencyDescriptor = dependency.getDescriptor();
        ModuleId targetModuleId = dependencyDescriptor.getDependencyRevisionId().getModuleId();
        if (!selectorSpec.isSatisfiedBy(targetModuleId)) {
          LOGGER.debug("{} is excluded from {}.", targetModuleId, this);
          continue;
        }
        DependencyEdge dependencyEdge =
            new DependencyEdge(this, dependency, selectorSpec, resolveState);
        outgoingEdges.add(dependencyEdge);
        target.add(dependencyEdge);
      }
      previousTraversal = selectorSpec;
    }
 public void restart(ModuleVersionResolveState selected) {
   select(selected);
   for (ModuleVersionResolveState version : versions.values()) {
     version.restart(selected);
   }
   for (DependencyEdge dependency : new ArrayList<DependencyEdge>(unattachedDependencies)) {
     dependency.restart(selected);
   }
   unattachedDependencies.clear();
 }
 public void restart(ModuleVersionResolveState selected) {
   // Restarting this configuration after conflict resolution.
   // If this configuration belongs to the select version, queue ourselves up for traversal.
   // If not, then move our incoming edges across to the selected configuration
   if (moduleRevision == selected) {
     resolveState.onMoreSelected(this);
   } else {
     for (DependencyEdge dependency : incomingEdges) {
       dependency.restart(selected);
     }
     incomingEdges.clear();
   }
 }
 private ModuleVersionSpec getSelector(List<DependencyEdge> transitiveEdges) {
   ModuleVersionSpec selector;
   if (transitiveEdges.isEmpty()) {
     selector = ModuleVersionSpec.forExcludes(); // includes all
   } else {
     selector = transitiveEdges.get(0).getSelector();
     for (int i = 1; i < transitiveEdges.size(); i++) {
       DependencyEdge dependencyEdge = transitiveEdges.get(i);
       selector = selector.union(dependencyEdge.getSelector());
     }
   }
   selector = selector.intersect(ModuleVersionSpec.forExcludes(metaData.getExcludeRules()));
   return selector;
 }
 private ModuleResolutionFilter getSelector(List<DependencyEdge> transitiveEdges) {
   ModuleResolutionFilter resolutionFilter;
   if (transitiveEdges.isEmpty()) {
     resolutionFilter = DefaultModuleResolutionFilter.all();
   } else {
     resolutionFilter = transitiveEdges.get(0).getSelector();
     for (int i = 1; i < transitiveEdges.size(); i++) {
       DependencyEdge dependencyEdge = transitiveEdges.get(i);
       resolutionFilter = resolutionFilter.union(dependencyEdge.getSelector());
     }
   }
   resolutionFilter =
       resolutionFilter.intersect(
           DefaultModuleResolutionFilter.excludeAny(metaData.getExcludeRules()));
   return resolutionFilter;
 }
 public void collectFailures(FailureState failureState) {
   for (DependencyEdge dependency : outgoingEdges) {
     dependency.collectFailures(failureState);
   }
 }
 public void attachToParents(ResolvedConfigurationBuilder result) {
   LOGGER.debug("Attaching {} to its parents.", this);
   for (DependencyEdge dependency : incomingEdges) {
     dependency.attachToParents(this, result);
   }
 }
Example #10
0
  /**
   * Traverses the dependency graph, resolving conflicts and building the paths from the root
   * configuration.
   */
  private void traverseGraph(ResolveState resolveState) {
    Set<ModuleIdentifier> conflicts = new LinkedHashSet<ModuleIdentifier>();

    resolveState.onMoreSelected(resolveState.root);

    List<DependencyEdge> dependencies = new ArrayList<DependencyEdge>();
    while (resolveState.peek() != null || !conflicts.isEmpty()) {
      if (resolveState.peek() != null) {
        ConfigurationNode node = resolveState.pop();
        LOGGER.debug("Visiting configuration {}.", node);

        // Calculate the outgoing edges of this configuration
        dependencies.clear();
        node.visitOutgoingDependencies(dependencies);

        for (DependencyEdge dependency : dependencies) {
          LOGGER.debug("Visiting dependency {}", dependency);

          // Resolve dependency to a particular revision
          ModuleVersionResolveState moduleRevision = dependency.resolveModuleRevisionId();
          if (moduleRevision == null) {
            // Failed to resolve.
            continue;
          }
          ModuleIdentifier moduleId = moduleRevision.id.getModule();

          // Check for a new conflict
          if (moduleRevision.state == ModuleState.New) {
            ModuleResolveState module = resolveState.getModule(moduleId);

            // A new module revision. Check for conflict
            Collection<ModuleVersionResolveState> versions = module.getVersions();
            if (versions.size() == 1) {
              // First version of this module. Select it for now
              LOGGER.debug("Selecting new module version {}", moduleRevision);
              module.select(moduleRevision);
            } else {
              // Not the first version of this module. We have a new conflict
              LOGGER.debug("Found new conflicting module version {}", moduleRevision);
              conflicts.add(moduleId);

              // Deselect the currently selected version, and remove all outgoing edges from the
              // version
              // This will propagate through the graph and prune configurations that are no longer
              // required
              ModuleVersionResolveState previouslySelected = module.clearSelection();
              if (previouslySelected != null) {
                for (ConfigurationNode configuration : previouslySelected.configurations) {
                  configuration.removeOutgoingEdges();
                }
              }
            }
          }

          dependency.attachToTargetConfigurations();
        }
      } else {
        // We have some batched up conflicts. Resolve the first, and continue traversing the graph
        ModuleIdentifier moduleId = conflicts.iterator().next();
        conflicts.remove(moduleId);
        ModuleResolveState module = resolveState.getModule(moduleId);
        ModuleVersionResolveState selected =
            conflictResolver.select(module.getVersions(), resolveState.root.moduleRevision);
        LOGGER.debug("Selected {} from conflicting modules {}.", selected, module.getVersions());

        // Restart each configuration. For the evicted configuration, this means moving incoming
        // dependencies across to the
        // matching selected configuration. For the select configuration, this mean traversing its
        // dependencies.
        module.restart(selected);
      }
    }
  }
  /**
   * Traverses the dependency graph, resolving conflicts and building the paths from the root
   * configuration.
   */
  private void traverseGraph(
      final ResolveState resolveState, final ConflictHandler conflictHandler) {
    resolveState.onMoreSelected(resolveState.root);

    List<DependencyEdge> dependencies = new ArrayList<DependencyEdge>();
    while (resolveState.peek() != null || conflictHandler.hasConflicts()) {
      if (resolveState.peek() != null) {
        ConfigurationNode node = resolveState.pop();
        LOGGER.debug("Visiting configuration {}.", node);

        // Calculate the outgoing edges of this configuration
        dependencies.clear();
        node.visitOutgoingDependencies(dependencies);

        for (DependencyEdge dependency : dependencies) {
          LOGGER.debug("Visiting dependency {}", dependency);

          // Resolve dependency to a particular revision
          ModuleVersionResolveState moduleRevision = dependency.resolveModuleRevisionId();
          if (moduleRevision == null) {
            // Failed to resolve.
            continue;
          }
          ModuleIdentifier moduleId = moduleRevision.id.getModule();

          // Check for a new conflict
          if (moduleRevision.state == ModuleState.New) {
            ModuleResolveState module = resolveState.getModule(moduleId);

            // A new module revision. Check for conflict
            PotentialConflict c = conflictHandler.registerModule(module);
            if (!c.conflictExists()) {
              // No conflict. Select it for now
              LOGGER.debug("Selecting new module version {}", moduleRevision);
              module.select(moduleRevision);
            } else {
              // We have a conflict
              LOGGER.debug("Found new conflicting module version {}", moduleRevision);

              // Deselect the currently selected version, and remove all outgoing edges from the
              // version
              // This will propagate through the graph and prune configurations that are no longer
              // required
              // For each module participating in the conflict (many times there is only one
              // participating module that has multiple versions)
              c.withParticipatingModules(
                  new Action<ModuleIdentifier>() {
                    public void execute(ModuleIdentifier module) {
                      ModuleVersionResolveState previouslySelected =
                          resolveState.getModule(module).clearSelection();
                      if (previouslySelected != null) {
                        for (ConfigurationNode configuration : previouslySelected.configurations) {
                          configuration.deselect();
                        }
                      }
                    }
                  });
            }
          }

          dependency.attachToTargetConfigurations();
        }
      } else {
        // We have some batched up conflicts. Resolve the first, and continue traversing the graph
        conflictHandler.resolveNextConflict(
            new Action<ConflictResolutionResult>() {
              public void execute(final ConflictResolutionResult result) {
                result
                    .getConflict()
                    .withParticipatingModules(
                        new Action<ModuleIdentifier>() {
                          public void execute(ModuleIdentifier moduleIdentifier) {
                            ModuleVersionResolveState selected = result.getSelected();
                            // Restart each configuration. For the evicted configuration, this means
                            // moving incoming dependencies across to the
                            // matching selected configuration. For the select configuration, this
                            // mean traversing its dependencies.
                            resolveState.getModule(moduleIdentifier).restart(selected);
                          }
                        });
              }
            });
      }
    }
  }