[prev in list] [next in list] [prev in thread] [next in thread]
List: ivy-commits
Subject: svn commit: r542921 - in /incubator/ivy/core/trunk: ./
From: gscokart () apache ! org
Date: 2007-05-30 19:44:29
Message-ID: 20070530194430.371AE1A981A () eris ! apache ! org
[Download RAW message or body]
Author: gscokart
Date: Wed May 30 12:44:28 2007
New Revision: 542921
URL: http://svn.apache.org/viewvc?view=rev&rev=542921
Log:
IVY-493, IVY-509 : fix buildlist regression and add Circular dependency startegy
Added:
incubator/ivy/core/trunk/src/java/org/apache/ivy/core/sort/CollectionOfModulesToSort.java \
(with props) incubator/ivy/core/trunk/src/java/org/apache/ivy/core/sort/DefaultNonMatchingVersionReporter.java \
(with props) incubator/ivy/core/trunk/src/java/org/apache/ivy/core/sort/ModuleInSort.java \
(with props) incubator/ivy/core/trunk/src/java/org/apache/ivy/core/sort/NonMatchingVersionReporter.java \
(with props) Modified:
incubator/ivy/core/trunk/CHANGES.txt
incubator/ivy/core/trunk/doc/doc/configuration/conf.html
incubator/ivy/core/trunk/doc/doc/use/buildlist.html
incubator/ivy/core/trunk/src/java/org/apache/ivy/Ivy.java
incubator/ivy/core/trunk/src/java/org/apache/ivy/ant/IvyBuildList.java
incubator/ivy/core/trunk/src/java/org/apache/ivy/core/sort/ModuleDescriptorSorter.java
incubator/ivy/core/trunk/src/java/org/apache/ivy/core/sort/SortEngine.java
incubator/ivy/core/trunk/src/java/org/apache/ivy/plugins/circular/CircularDependencyHelper.java
incubator/ivy/core/trunk/src/java/org/apache/ivy/tools/analyser/JarJarDependencyAnalyser.java
incubator/ivy/core/trunk/test/java/org/apache/ivy/core/sort/SortTest.java
incubator/ivy/core/trunk/test/java/org/apache/ivy/util/MockMessageImpl.java
Modified: incubator/ivy/core/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/CHANGES.txt?view=diff&rev=542921&r1=542920&r2=542921
==============================================================================
--- incubator/ivy/core/trunk/CHANGES.txt (original)
+++ incubator/ivy/core/trunk/CHANGES.txt Wed May 30 12:44:28 2007
@@ -69,6 +69,9 @@
- FIX: Credentials are shown in build log even if debug is not enabled (IVY-486) \
(thanks to Gilles Scokart)
- FIX: Post-Resolve task shouldn't set the 'resolveid' (IVY-489)
- FIX: build fails without emma code coverage JARs present (IVY-478)
+- FIX: buildlist broken - regression in 2.0.0-alpha1-incubating (IVY-493)
+- FIX: Circular dependency startegy in buildlist (IVY-509)
+- FIX: ivy should stop telling me off twice for ivyconf.xml files (IVY-513)
2.0.0-alpha1-incubating
=====================================
Modified: incubator/ivy/core/trunk/doc/doc/configuration/conf.html
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/doc/doc/configuration/conf.html?view=diff&rev=542921&r1=542920&r2=542921
==============================================================================
--- incubator/ivy/core/trunk/doc/doc/configuration/conf.html (original)
+++ incubator/ivy/core/trunk/doc/doc/configuration/conf.html Wed May 30 12:44:28 2007
@@ -60,7 +60,7 @@
<td>No, defaults to latest-revision</td></tr>
<tr><td>defaultBranch</td><td>the default branch to use for all modules, except \
if they have a <a href="../../doc/configuration/module.html"> module specific branch \
setting</a>. <span class="since">since 1.4</span></td> <td>No, defaults to no \
default branch</td></tr>
- <tr><td>circularDependencyStrategy</td><td>the name of the <a \
href="../../doc/concept#circular.html">circular dependency strategy</a> to use <span \
class="since">since 1.4</span></td> + <tr><td><a \
name="circularDependencyStrategy"></a>circularDependencyStrategy</td><td>the name of \
the <a href="../../doc/concept#circular.html">circular dependency strategy</a> to use \
<span class="since">since 1.4</span></td> <td>No, defaults to warn</td></tr>
<tr><td>validate</td><td>Indicates if ivy files should be validated against \
ivy.xsd or not.</td> <td>No, defaults to true</td></tr>
Modified: incubator/ivy/core/trunk/doc/doc/use/buildlist.html
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/doc/doc/use/buildlist.html?view=diff&rev=542921&r1=542920&r2=542921
==============================================================================
--- incubator/ivy/core/trunk/doc/doc/use/buildlist.html (original)
+++ incubator/ivy/core/trunk/doc/doc/use/buildlist.html Wed May 30 12:44:28 2007
@@ -29,6 +29,9 @@
This is particularly useful combined with subant, to build a set of interelated \
projects being sure that a dependency will be built before any module depending on \
it.
+When the ivy.xml of the modules that you want to order doesn't contains a <a \
href="../ivyfile/info.html">revision</a> numbers, the rev attributes declared in the \
dependency is not used. +When the ivy.xml of the modules that you want to order \
contains a <a href="../ivyfile/info.html">revision</a> numbers, the revision numbers \
are used. If the revision number doesn't match a dependency description a warning \
is logged and the modules is considered as different modules. +
<span class="since">since 1.3</span> A root attribute can also be used to include, \
among all the modules found, only the one that are dependencies (either direct or \
transitive) of a root module. This can also be used with the excluderoot attribute, \
which when set to true will exclude the root itself from the list.
<span class="since">since 1.4.1</span> A leaf attribute can also be used to include, \
among all the modules found, only the one that have dependencies (either direct or \
transitive) on a leaf module. This can also be used with the excludeleaf attribute, \
which when set to true will exclude the leaf itself from the list. @@ -36,6 +39,11 @@
<span class="since">since 1.4</span> The ivy.sorted.modules property is set in the \
ant at the end of the task with a comma separated list of ordered modules. This can \
be useful for debug or information purpose.
<span class="since">since 2.0</span> The root and leaf attributes can be a delimited \
list of modules to use as roots. These modules, and all their dependencies will be \
included in the build list. +
+<span class="since">since 2.0</span> By default, all the modules included in a \
circular dependency are grouped together so that any dependency of any module in the \
loop will apear before the modules in the loop. This garantee that if there is a \
depedendency path between a module A and a module B (but no dependency path from B to \
A), B will alway apear before A even if A is included in a loop in the provided set \
of modules to sort. +Note that circular dependency can also trigger a failure \
depending on the value configured in the circularDependencyStrategy of your <a \
href="../configuration/conf.html#circularDependencyStrategy">settings</a> +
+
<table class="ant">
<thead>
<tr><th class="ant-att">Attribute</th><th class="ant-desc">Description</th><th \
class="ant-req">Required</th></tr> @@ -52,7 +60,7 @@
<tr><td>haltonerror</td><td>true to halt the build when an invalid ivy file is \
encountered, false to continue</td><td>No. Defaults to true</td></tr> \
<tr><td>skipbuildwithoutivy</td><td>true to skip files of the fileset with no \
corresponding ivy file, false otherwise. If false the file with no corresponding ivy \
file will be considered as independent of the other and put at the beginning of the \
built filelist.</td><td>No. Defaults to false</td></tr> <tr><td>reverse</td><td>true \
to obtain the list in the reverse order, i.e. from the most dependent to the least \
one</td><td>No. Defaults to default false</td></tr>
- <tr><td>settingsRef</td><td><span class="since">(since 2.0)</span> A reference \
to the ivy settings that must be used by this task</td><td>No, 'ivy.instance' is \
taken by default.</td></tr> + <tr><td>settingsRef</td><td><span \
class="since">since 2.0</span> A reference to the ivy settings that must be used by \
this task</td><td>No, 'ivy.instance' is taken by default.</td></tr> </tbody>
</table>
Modified: incubator/ivy/core/trunk/src/java/org/apache/ivy/Ivy.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/src/java/org/apache/ivy/Ivy.java?view=diff&rev=542921&r1=542920&r2=542921
==============================================================================
--- incubator/ivy/core/trunk/src/java/org/apache/ivy/Ivy.java (original)
+++ incubator/ivy/core/trunk/src/java/org/apache/ivy/Ivy.java Wed May 30 12:44:28 \
2007 @@ -51,6 +51,7 @@
import org.apache.ivy.core.search.RevisionEntry;
import org.apache.ivy.core.search.SearchEngine;
import org.apache.ivy.core.settings.IvySettings;
+import org.apache.ivy.core.sort.NonMatchingVersionReporter;
import org.apache.ivy.core.sort.SortEngine;
import org.apache.ivy.plugins.matcher.PatternMatcher;
import org.apache.ivy.plugins.repository.TransferEvent;
@@ -332,6 +333,10 @@
return _sortEngine.sortModuleDescriptors(moduleDescriptors);
}
+ public List sortModuleDescriptors(Collection moduleDescriptors, \
NonMatchingVersionReporter nonMatchingVersionReporter) { + return \
_sortEngine.sortModuleDescriptors(moduleDescriptors , nonMatchingVersionReporter); \
+ } +
/////////////////////////////////////////////////////////////////////////
// SEARCH
/////////////////////////////////////////////////////////////////////////
@@ -562,5 +567,7 @@
public void setSettings(IvySettings settings) {
_settings = settings;
}
+
+
}
Modified: incubator/ivy/core/trunk/src/java/org/apache/ivy/ant/IvyBuildList.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/src/java/org/apache/ivy/ant/IvyBuildList.java?view=diff&rev=542921&r1=542920&r2=542921
==============================================================================
--- incubator/ivy/core/trunk/src/java/org/apache/ivy/ant/IvyBuildList.java (original)
+++ incubator/ivy/core/trunk/src/java/org/apache/ivy/ant/IvyBuildList.java Wed May 30 \
12:44:28 2007 @@ -47,86 +47,85 @@
/**
* Creates an ant filelist of files (usually build.xml) ordered according to the \
dependencies declared in ivy files.
- *
*/
public class IvyBuildList extends IvyTask {
- private List _buildFiles = new ArrayList(); // List (FileSet)
- private String _reference;
- private boolean _haltOnError = true;
- private boolean _skipBuildWithoutIvy = false;
- private boolean _reverse = false;
- private String _ivyFilePath;
- private String _root = "*";
- private boolean _excludeRoot = false;
- private String _leaf = "*";
- private String _delimiter = ",";
- private boolean _excludeLeaf = false;
+ private List buildFileSets = new ArrayList(); // List (FileSet)
+ private String reference;
+ private boolean haltOnError = true;
+ private boolean skipBuildWithoutIvy = false;
+ private boolean reverse = false;
+ private String ivyFilePath;
+ private String root = "*";
+ private boolean excludeRoot = false;
+ private String leaf = "*";
+ private String delimiter = ",";
+ private boolean excludeLeaf = false;
public void addFileset(FileSet buildFiles) {
- _buildFiles.add(buildFiles);
+ buildFileSets.add(buildFiles);
}
public String getReference() {
- return _reference;
+ return reference;
}
public void setReference(String reference) {
- _reference = reference;
+ this.reference = reference;
}
public String getRoot() {
- return _root;
+ return root;
}
public void setRoot(String root) {
- _root = root;
+ this.root = root;
}
public boolean isExcludeRoot() {
- return _excludeRoot;
+ return excludeRoot;
}
public void setExcludeRoot(boolean root) {
- _excludeRoot = root;
+ excludeRoot = root;
}
public String getLeaf() {
- return _leaf;
+ return leaf;
}
public void setLeaf(String leaf) {
- _leaf = leaf;
+ this.leaf = leaf;
}
public boolean isExcludeLeaf() {
- return _excludeLeaf;
+ return excludeLeaf;
}
public void setExcludeLeaf(boolean excludeLeaf) {
- _excludeLeaf = excludeLeaf;
+ this.excludeLeaf = excludeLeaf;
}
public String getDelimiter() {
- return _delimiter;
+ return delimiter;
}
public void setDelimiter(String delimiter) {
- _delimiter = delimiter;
+ this.delimiter = delimiter;
}
public void doExecute() throws BuildException {
- if (_reference == null) {
+ if (reference == null) {
throw new BuildException("reference should be provided in ivy build \
list"); }
- if (_buildFiles.isEmpty()) {
+ if (buildFileSets.isEmpty()) {
throw new BuildException("at least one nested fileset should be provided \
in ivy build list"); }
Ivy ivy = getIvyInstance();
IvySettings settings = ivy.getSettings();
- _ivyFilePath = getProperty(_ivyFilePath, settings, "ivy.buildlist.ivyfilepath");
+ ivyFilePath = getProperty(ivyFilePath, settings, "ivy.buildlist.ivyfilepath");
Path path = new Path(getProject());
@@ -135,22 +134,22 @@
List independent = new ArrayList();
Set rootModuleNames = new LinkedHashSet();
- if (!"*".equals(_root)) {
- StringTokenizer st = new StringTokenizer(_root, _delimiter);
+ if (!"*".equals(root)) {
+ StringTokenizer st = new StringTokenizer(root, delimiter);
while (st.hasMoreTokens()) {
rootModuleNames.add(st.nextToken());
}
}
Set leafModuleNames = new LinkedHashSet();
- if (! "*".equals(_leaf)) {
- StringTokenizer st = new StringTokenizer(_leaf, _delimiter);
+ if (! "*".equals(leaf)) {
+ StringTokenizer st = new StringTokenizer(leaf, delimiter);
while (st.hasMoreTokens()) {
leafModuleNames.add(st.nextToken());
}
}
- for (ListIterator iter = _buildFiles.listIterator(); iter.hasNext();) {
+ for (ListIterator iter = buildFileSets.listIterator(); iter.hasNext();) {
FileSet fs = (FileSet)iter.next();
DirectoryScanner ds = fs.getDirectoryScanner(getProject());
String[] builds = ds.getIncludedFiles();
@@ -158,7 +157,7 @@
File buildFile = new File(ds.getBasedir(), builds[i]);
File ivyFile = getIvyFileFor(buildFile);
if (!ivyFile.exists()) {
- if (_skipBuildWithoutIvy) {
+ if (skipBuildWithoutIvy) {
Message.debug("skipping "+buildFile+": ivy file "+ivyFile+" \
doesn't exist"); } else {
Message.verbose("no ivy file for "+buildFile+": \
ivyfile="+ivyFile+": adding it at the beginning of the path"); @@ -170,8 +169,9 @@
ModuleDescriptor md = \
ModuleDescriptorParserRegistry.getInstance().parseDescriptor(settings, \
ivyFile.toURL(), doValidate(settings)); buildFiles.put(md, buildFile);
mdsMap.put(md.getModuleRevisionId().getModuleId().getName(), \
md); + Message.debug("Add " + \
md.getModuleRevisionId().getModuleId()); } catch (Exception ex) {
- if (_haltOnError) {
+ if (haltOnError) {
throw new BuildException("impossible to parse ivy file \
for "+buildFile+": ivyfile="+ivyFile+" exception="+ex, ex); } else {
Message.warn("impossible to parse ivy file for \
"+buildFile+": ivyfile="+ivyFile+" exception="+ex.getMessage()); @@ -257,7 +257,7 @@
ModuleDescriptor rootmd = (ModuleDescriptor) it.next();
processFilterNodeFromRoot(rootmd, toKeep, moduleIdMap);
// With the excluderoot attribute set to true, take the rootmd out of \
the toKeep set.
- if (_excludeRoot) {
+ if (excludeRoot) {
Message.verbose("Excluded module " + \
rootmd.getModuleRevisionId().getModuleId().getName()); toKeep.remove(rootmd);
}
@@ -315,7 +315,7 @@
while (it.hasNext()) {
ModuleDescriptor leafmd = (ModuleDescriptor) it.next();
// With the excludeleaf attribute set to true, take the rootmd out of \
the toKeep set.
- if (_excludeLeaf) {
+ if (excludeLeaf) {
Message.verbose("Excluded module " + \
leafmd.getModuleRevisionId().getModuleId().getName()); } else {
toKeep.add(leafmd);
@@ -365,40 +365,40 @@
}
private File getIvyFileFor(File buildFile) {
- return new File(buildFile.getParentFile(), _ivyFilePath);
+ return new File(buildFile.getParentFile(), ivyFilePath);
}
public boolean isHaltonerror() {
- return _haltOnError;
+ return haltOnError;
}
public void setHaltonerror(boolean haltOnError) {
- _haltOnError = haltOnError;
+ this.haltOnError = haltOnError;
}
public String getIvyfilepath() {
- return _ivyFilePath;
+ return ivyFilePath;
}
public void setIvyfilepath(String ivyFilePath) {
- _ivyFilePath = ivyFilePath;
+ this.ivyFilePath = ivyFilePath;
}
public boolean isSkipbuildwithoutivy() {
- return _skipBuildWithoutIvy;
+ return skipBuildWithoutIvy;
}
public void setSkipbuildwithoutivy(boolean skipBuildFilesWithoutIvy) {
- _skipBuildWithoutIvy = skipBuildFilesWithoutIvy;
+ this.skipBuildWithoutIvy = skipBuildFilesWithoutIvy;
}
public boolean isReverse() {
- return _reverse;
+ return reverse;
}
public void setReverse(boolean reverse) {
- _reverse = reverse;
+ this.reverse = reverse;
}
}
Added: incubator/ivy/core/trunk/src/java/org/apache/ivy/core/sort/CollectionOfModulesToSort.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/src/java/org/apache/ivy/core/sort/CollectionOfModulesToSort.java?view=auto&rev=542921
==============================================================================
--- incubator/ivy/core/trunk/src/java/org/apache/ivy/core/sort/CollectionOfModulesToSort.java \
(added)
+++ incubator/ivy/core/trunk/src/java/org/apache/ivy/core/sort/CollectionOfModulesToSort.java \
Wed May 30 12:44:28 2007 @@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.ivy.core.sort;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
+import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
+import org.apache.ivy.core.module.id.ModuleId;
+import org.apache.ivy.plugins.version.VersionMatcher;
+
+/**
+ * Wrap a collection of descriptores wrapped themself in ModuleInSort elements. It \
contains some + * dedicated function to retrieve module descriptors based on \
dependencies descriptors.<br> + * <i>This class is designed to be used internally by \
the ModuleDescriptorSorter.</i> + */
+class CollectionOfModulesToSort implements Iterable {
+
+ private final List moduleDescriptors; //List<ModuleInSort>
+ private final VersionMatcher versionMatcher;
+ private final Map modulesByModuleId; //Map<ModuleId , Collection<ModuleInSort>
+ private final NonMatchingVersionReporter nonMatchingVersionReporter;
+
+ /**
+ * @param modulesToSort The collection of ModuleDescriptor to sort
+ * @param matcher The matcher to used to check if dependencyDescriptor match a \
module in this collection + * @param nonMatchingVersionReporter
+ */
+ public CollectionOfModulesToSort(Collection modulesToSort, VersionMatcher matcher, \
NonMatchingVersionReporter nonMatchingVersionReporter) { + this.versionMatcher = \
matcher; + this.nonMatchingVersionReporter = nonMatchingVersionReporter;
+ this.modulesByModuleId = new HashMap();
+ moduleDescriptors = new ArrayList(modulesToSort.size());
+ for (Iterator it = modulesToSort.iterator(); it.hasNext();) {
+ ModuleDescriptor md = (ModuleDescriptor) it.next();
+ ModuleInSort mdInSort = new ModuleInSort(md);
+ moduleDescriptors.add(mdInSort);
+ addToModulesByModuleId(md, mdInSort);
+ }
+ }
+
+
+ private void addToModulesByModuleId(ModuleDescriptor md, ModuleInSort mdInSort) {
+ ModuleId mdId = md.getModuleRevisionId().getModuleId();
+ List mdInSortAsList = new LinkedList();
+ mdInSortAsList.add(mdInSort);
+ List previousList = (List) modulesByModuleId.put(mdId, mdInSortAsList);
+ if (previousList!=null) {
+ mdInSortAsList.addAll(previousList);
+ }
+ }
+
+
+ public Iterator iterator() {
+ return moduleDescriptors.iterator();
+ }
+
+
+ public int size() {
+ return moduleDescriptors.size();
+ }
+
+
+ /**
+ * Find a matching module descriptor in the list of module to sort.
+ * @param descriptor
+ * @return a ModuleDescriptor from the collection of module descriptors to sort.
+ * If none exists returns null.
+ */
+ public ModuleInSort getModuleDescriptorDependency(DependencyDescriptor \
descriptor) { + Collection modulesOfSameId = (Collection) \
modulesByModuleId.get(descriptor.getDependencyId()); + if (modulesOfSameId==null) \
return null; + for (Iterator it = modulesOfSameId.iterator(); it.hasNext();) {
+ ModuleInSort mdInSort = (ModuleInSort) it.next();
+ if (mdInSort.match(descriptor, versionMatcher)) {
+ return mdInSort;
+ } else {
+ nonMatchingVersionReporter.reportNonMatchingVersion(descriptor, \
mdInSort.getSortedModuleDescriptor()); + }
+ }
+ return null;
+ }
+
+}
Propchange: incubator/ivy/core/trunk/src/java/org/apache/ivy/core/sort/CollectionOfModulesToSort.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/ivy/core/trunk/src/java/org/apache/ivy/core/sort/DefaultNonMatchingVersionReporter.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/src/java/org/apache/ivy/core/sort/DefaultNonMatchingVersionReporter.java?view=auto&rev=542921
==============================================================================
--- incubator/ivy/core/trunk/src/java/org/apache/ivy/core/sort/DefaultNonMatchingVersionReporter.java \
(added)
+++ incubator/ivy/core/trunk/src/java/org/apache/ivy/core/sort/DefaultNonMatchingVersionReporter.java \
Wed May 30 12:44:28 2007 @@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.ivy.core.sort;
+
+import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
+import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
+import org.apache.ivy.core.module.id.ModuleId;
+import org.apache.ivy.core.module.id.ModuleRevisionId;
+import org.apache.ivy.util.Message;
+
+/**
+ * A default implementation of the reporter used in the sort. The reporting is \
isolated here to make + * it easier to test, and to have a place where adding \
different type of reporting (silent, warning, exceptions) + */
+public class DefaultNonMatchingVersionReporter implements NonMatchingVersionReporter \
{ +
+ public void reportNonMatchingVersion(DependencyDescriptor descriptor, \
ModuleDescriptor md) { + ModuleRevisionId dependencyRevisionId = \
descriptor.getDependencyRevisionId(); + ModuleRevisionId parentRevisionId = \
descriptor.getParentRevisionId(); + if (parentRevisionId==null) {
+ //There are some rare case where DependencyDescriptor have no parent.
+ //This is should not be used in the SortEngine, but if it is, we show a decent \
trace. + Message.warn("Non matching revision detected. Dependency " + \
dependencyRevisionId + + " doesn't match " + md);
+ } else {
+ ModuleId parentModuleId = parentRevisionId.getModuleId();
+ Message.warn("Non matching revision detected. " + parentModuleId + " depends \
on " + + dependencyRevisionId + ", doesn't match " + md);
+ }
+
+ }
+
+}
Propchange: incubator/ivy/core/trunk/src/java/org/apache/ivy/core/sort/DefaultNonMatchingVersionReporter.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: incubator/ivy/core/trunk/src/java/org/apache/ivy/core/sort/ModuleDescriptorSorter.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/src/java/org/apache/ivy/core/sort/ModuleDescriptorSorter.java?view=diff&rev=542921&r1=542920&r2=542921
==============================================================================
--- incubator/ivy/core/trunk/src/java/org/apache/ivy/core/sort/ModuleDescriptorSorter.java \
(original)
+++ incubator/ivy/core/trunk/src/java/org/apache/ivy/core/sort/ModuleDescriptorSorter.java \
Wed May 30 12:44:28 2007 @@ -21,30 +21,31 @@
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
-import java.util.Stack;
import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
-import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
import org.apache.ivy.plugins.circular.CircularDependencyException;
-import org.apache.ivy.plugins.circular.CircularDependencyHelper;
+import org.apache.ivy.plugins.circular.CircularDependencyStrategy;
import org.apache.ivy.plugins.version.VersionMatcher;
import org.apache.ivy.util.Message;
/**
- * Inner helper class for sorting ModuleDescriptors.
- *
+ * Inner helper class for sorting ModuleDescriptors.<br>
+ * ModuleDescriptorSorter use CollectionOfModulesToSort to find the dependencies of \
the modules, and use ModuleInSort + * to store some temporary values attached to the \
modules to sort. + * @see ModuleInSort
+ * @see CollectionOfModulesToSort
*/
public class ModuleDescriptorSorter {
-
-
- private final Collection moduleDescriptors;
- private final Iterator moduleDescriptorsIterator;
+
+ private final CollectionOfModulesToSort moduleDescriptors;
private final List sorted = new LinkedList();
+ private final CircularDependencyStrategy circularDepStrategy;
+
- public ModuleDescriptorSorter(Collection moduleDescriptors) {
- this.moduleDescriptors=moduleDescriptors;
- moduleDescriptorsIterator = new LinkedList(moduleDescriptors).iterator();
+ public ModuleDescriptorSorter(Collection modulesDescriptorsToSort,VersionMatcher \
matcher, NonMatchingVersionReporter nonMatchingVersionReporter, \
CircularDependencyStrategy circularDepStrategy) { + this.circularDepStrategy = \
circularDepStrategy; + moduleDescriptors = new \
CollectionOfModulesToSort(modulesDescriptorsToSort, matcher , \
nonMatchingVersionReporter); }
/**
@@ -52,9 +53,12 @@
* @return sorted module
* @throws CircularDependencyException
*/
- public List sortModuleDescriptors(VersionMatcher matcher) throws \
CircularDependencyException {
- while (moduleDescriptorsIterator.hasNext()) {
- sortModuleDescriptorsHelp(matcher, \
(ModuleDescriptor)moduleDescriptorsIterator.next(), new Stack()); + public List \
sortModuleDescriptors() throws CircularDependencyException { + Message.debug("Nbr \
of module to sort : " + moduleDescriptors.size()); + Iterator \
_moduleDescriptorsIterator = moduleDescriptors.iterator(); + while \
(_moduleDescriptorsIterator.hasNext()) { + ModuleInSort next = \
(ModuleInSort)_moduleDescriptorsIterator.next(); + sortModuleDescriptorsHelp(next, \
next); }
return sorted;
}
@@ -63,52 +67,33 @@
* If current module has already been added to list, returns,
* Otherwise invokes sortModuleDescriptorsHelp for all dependencies
* contained within set of moduleDescriptors. Then finally adds self
- * to list of sorted.
+ * to list of sorted.<br/>
+ * When a loop is detected by a recursive call, the moduleDescriptors are not \
added + * immediately added to the sorted list. They are added as loop \
dependencies of the root, and will be + * added to the sorted list only when the \
root itself will be added.
* @param current Current module to add to sorted list.
* @throws CircularDependencyException
*/
- private void sortModuleDescriptorsHelp(VersionMatcher matcher, ModuleDescriptor \
current, Stack callStack) throws CircularDependencyException { + private void \
sortModuleDescriptorsHelp(ModuleInSort current, ModuleInSort caller) throws \
CircularDependencyException { //if already sorted return
- if (sorted.contains(current)) {
- return;
- }
- if (callStack.contains(current)) {
- callStack.add(current);
- Message.verbose("circular dependency ignored during sort: \
"+CircularDependencyHelper.formatMessage((ModuleDescriptor[]) callStack.toArray(new \
ModuleDescriptor[callStack.size()]))); + if (current.isSorted()) {
return;
}
+ if (current.checkLoop(caller , circularDepStrategy)) {
+ return;
+ }
DependencyDescriptor [] descriptors = current.getDependencies();
- ModuleDescriptor moduleDescriptorDependency = null;
- for (int i = 0; descriptors!=null && i < descriptors.length; i++) {
- moduleDescriptorDependency = getModuleDescriptorDependency(matcher, \
descriptors[i]);
-
- if (moduleDescriptorDependency != null) {
- callStack.push(current);
- sortModuleDescriptorsHelp(matcher, moduleDescriptorDependency, \
callStack);
- callStack.pop();
+ Message.debug("Sort dependencies of : " + current.toString() + " / Number of \
dependencies = " + descriptors.length); + current.setCaller(caller);
+ for (int i = 0; i < descriptors.length; i++) {
+ ModuleInSort child = \
moduleDescriptors.getModuleDescriptorDependency(descriptors[i]); + if \
(child != null) { + sortModuleDescriptorsHelp(child, current);
}
}
- sorted.add(current);
+ current.endOfCall();
+ Message.debug("Sort done for : " + current.toString());
+ current.addToSortedListIfRequired(sorted);
}
- /**
- * @param descriptor
- * @return a ModuleDescriptor from the collection of module descriptors to sort.
- * If none exists returns null.
- */
- private ModuleDescriptor getModuleDescriptorDependency(VersionMatcher matcher, \
DependencyDescriptor descriptor) {
- Iterator i = moduleDescriptors.iterator();
- ModuleDescriptor md = null;
- while (i.hasNext()) {
- md = (ModuleDescriptor) i.next();
- if (descriptor.getDependencyId().equals(md.getModuleRevisionId().getModuleId())) \
{
- if (md.getResolvedModuleRevisionId().getRevision() == null) {
- return md;
- } else if (matcher.accept(descriptor.getDependencyRevisionId(), md)) \
{
- return md;
- }
- }
- }
- return null;
- }
}
Added: incubator/ivy/core/trunk/src/java/org/apache/ivy/core/sort/ModuleInSort.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/src/java/org/apache/ivy/core/sort/ModuleInSort.java?view=auto&rev=542921
==============================================================================
--- incubator/ivy/core/trunk/src/java/org/apache/ivy/core/sort/ModuleInSort.java \
(added)
+++ incubator/ivy/core/trunk/src/java/org/apache/ivy/core/sort/ModuleInSort.java Wed \
May 30 12:44:28 2007 @@ -0,0 +1,164 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.ivy.core.sort;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.ivy.Ivy;
+import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
+import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
+import org.apache.ivy.core.module.id.ModuleRevisionId;
+import org.apache.ivy.plugins.circular.CircularDependencyHelper;
+import org.apache.ivy.plugins.circular.CircularDependencyStrategy;
+import org.apache.ivy.plugins.version.VersionMatcher;
+import org.apache.ivy.util.Message;
+
+/**
+ * Decorates a ModuleDescriptor with some attributes used during the sort. Thus \
every instance of a ModuleInSort can be used in + * only one ModuleDescriptorSorter \
at a time.<br> + * The added fields are : <br>
+ * <ul>
+ * <li><code>isSorted</code> : is true iff this module has already been added to the \
sorted list.</li> + * <li><code>loopElements</code> : When the module is the root of \
a loop (=the first element of a loop met during the sort), + * \
<code>loopElements</code> contains all ModuleInSort of the loop (excluding the root \
itself.</li> + * <li><code>isLoopIntermediateElement</code> : When a loop is \
detected, all modules included in the loop + * (except the root) have \
<code>isLoopIntermediateElement</code> set to true.</li> + * <li><code>caller</code> \
: During the sort, we traverse recursively the graph. When doing that, caller point \
to the parent element. + */
+class ModuleInSort {
+
+ private final ModuleDescriptor module;
+ private boolean isSorted = false;
+ private List loopElements = new LinkedList();
+ private boolean isLoopIntermediateElement = false;
+ private ModuleInSort caller;
+
+ public ModuleInSort(ModuleDescriptor moduleToSort) {
+ module = moduleToSort;
+ }
+
+ public boolean isInLoop() {
+ return isLoopIntermediateElement;
+ }
+
+ public boolean isSorted() {
+ if (isSorted) {
+ Message.debug("Module descriptor already sorted : " + \
module.getModuleRevisionId().toString()); + return true;
+ } else {
+ return false;
+ }
+ }
+
+ public void setCaller(ModuleInSort caller) {
+ this.caller = caller;
+ }
+
+ public void endOfCall() {
+ caller = null;
+ }
+
+ /**
+ * Check if a adding this element as a dependency of caller will introduce a \
circular dependency. + * If it is, all the elements of the loop are flaged as \
'loopIntermediateElement', and the loopElements of this module + * (which is the \
root of the loop) is updated. The depStrategy is invoked on order to report a \
correct circular loop message. + * @param futurCaller
+ * @param depStrategy
+ * @return true if a loop is detected.
+ */
+ public boolean checkLoop(ModuleInSort futurCaller, CircularDependencyStrategy \
depStrategy) { + if (caller!=null) {
+ LinkedList elemOfLoop = new LinkedList();
+ elemOfLoop.add(this.module.getModuleRevisionId());
+ for(ModuleInSort stackElem = futurCaller ; stackElem!=this ; \
stackElem=stackElem.caller) { \
+ elemOfLoop.add(stackElem.module.getModuleRevisionId()); \
+ stackElem.isLoopIntermediateElement = true; + loopElements.add(stackElem);
+ }
+ elemOfLoop.add(this.module.getModuleRevisionId());
+ ModuleRevisionId[] mrids = (ModuleRevisionId[]) elemOfLoop.toArray(new \
ModuleRevisionId[elemOfLoop.size()]); \
+ depStrategy.handleCircularDependency(mrids); + return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Add this module to the sorted list except if this module is an intermediary \
element of a loop. + * If this module is the 'root' of a loop, then all elements of \
that loops are added before. + * @param sorted The list of sorted elements on which \
this module will be added + */
+ public void addToSortedListIfRequired(List sorted) {
+ if (!isLoopIntermediateElement) {
+ addToSortList(sorted);
+ }
+ }
+
+
+ /**
+ * Add this module to the sorted list.
+ * If current is the 'root' of a loop, then all elements of that loops are added \
before. + */
+ private void addToSortList(List sortedList) {
+ for (Iterator it = loopElements.iterator(); it.hasNext();) {
+ ModuleInSort moduleInLoop = (ModuleInSort) it.next();
+ moduleInLoop.addToSortList(sortedList);
+ }
+ if (!this.isSorted()) {
+ sortedList.add(module);
+ this.isSorted = true;
+ }
+ }
+
+
+ public String toString() {
+ return module.getModuleRevisionId().toString();
+ }
+
+ public DependencyDescriptor[] getDependencies() {
+ return module.getDependencies();
+ }
+
+
+
+ /** Log a warning saying that a loop is detected */
+ public static void logLoopWarning(List loopElement) {
+ Message.warn("circular dependency detected during sort: \
"+CircularDependencyHelper.formatMessageFromDescriptors(loopElement)); + }
+
+
+ /**
+ * Return true if this module match the DependencyDescriptor with the given \
versionMatcher. + * If this module has no version defined, then true is always \
returned. + */
+ public boolean match(DependencyDescriptor descriptor, VersionMatcher \
versionMatcher) { + ModuleDescriptor md = module;
+ return md.getResolvedModuleRevisionId().getRevision() == null ||
+ md.getResolvedModuleRevisionId().getRevision().equals(Ivy.getWorkingRevision()) \
|| + versionMatcher.accept(descriptor.getDependencyRevisionId(), md);
+ //Checking md.getResolvedModuleRevisionId().getRevision().equals(Ivy.getWorkingRevision() \
allow to consider any local non resolved ivy.xml + //as a valid module.
+ }
+
+ public ModuleDescriptor getSortedModuleDescriptor() {
+ return module;
+ }
+}
Propchange: incubator/ivy/core/trunk/src/java/org/apache/ivy/core/sort/ModuleInSort.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/ivy/core/trunk/src/java/org/apache/ivy/core/sort/NonMatchingVersionReporter.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/src/java/org/apache/ivy/core/sort/NonMatchingVersionReporter.java?view=auto&rev=542921
==============================================================================
--- incubator/ivy/core/trunk/src/java/org/apache/ivy/core/sort/NonMatchingVersionReporter.java \
(added)
+++ incubator/ivy/core/trunk/src/java/org/apache/ivy/core/sort/NonMatchingVersionReporter.java \
Wed May 30 12:44:28 2007 @@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.ivy.core.sort;
+
+import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
+import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
+
+public interface NonMatchingVersionReporter {
+
+ /**
+ * Report to the user that ivy has detected that a module to sort has a \
dependency + * on an other module to sort, but the revisions doesn't match.
+ * @param descriptor The non matching dependency descriptor.
+ * @param md The module to sort having the corect moduleID but a non matching \
revision + */
+ public void reportNonMatchingVersion(DependencyDescriptor descriptor, \
ModuleDescriptor md); +
+}
Propchange: incubator/ivy/core/trunk/src/java/org/apache/ivy/core/sort/NonMatchingVersionReporter.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: incubator/ivy/core/trunk/src/java/org/apache/ivy/core/sort/SortEngine.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/src/java/org/apache/ivy/core/sort/SortEngine.java?view=diff&rev=542921&r1=542920&r2=542921
==============================================================================
--- incubator/ivy/core/trunk/src/java/org/apache/ivy/core/sort/SortEngine.java \
(original)
+++ incubator/ivy/core/trunk/src/java/org/apache/ivy/core/sort/SortEngine.java Wed \
May 30 12:44:28 2007 @@ -80,7 +80,14 @@
* @throws CircularDependencyException if a circular dependency exists
*/
public List sortModuleDescriptors(Collection moduleDescriptors) throws \
CircularDependencyException {
- return new ModuleDescriptorSorter(moduleDescriptors).sortModuleDescriptors(_settings.getVersionMatcher()); \
+ return sortModuleDescriptors(moduleDescriptors , new \
DefaultNonMatchingVersionReporter()); }
+
+
+ public List sortModuleDescriptors(Collection moduleDescriptors, \
NonMatchingVersionReporter nonMatchingVersionReporter) { + ModuleDescriptorSorter \
sorter = new ModuleDescriptorSorter(moduleDescriptors, + \
_settings.getVersionMatcher(), nonMatchingVersionReporter , \
_settings.getCircularDependencyStrategy()); + return sorter.sortModuleDescriptors();
+ }
}
Modified: incubator/ivy/core/trunk/src/java/org/apache/ivy/plugins/circular/CircularDependencyHelper.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/src/java/org/apache/ivy/plu \
gins/circular/CircularDependencyHelper.java?view=diff&rev=542921&r1=542920&r2=542921 \
==============================================================================
--- incubator/ivy/core/trunk/src/java/org/apache/ivy/plugins/circular/CircularDependencyHelper.java \
(original)
+++ incubator/ivy/core/trunk/src/java/org/apache/ivy/plugins/circular/CircularDependencyHelper.java \
Wed May 30 12:44:28 2007 @@ -17,6 +17,9 @@
*/
package org.apache.ivy.plugins.circular;
+import java.util.Iterator;
+import java.util.List;
+
import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
import org.apache.ivy.core.module.id.ModuleRevisionId;
@@ -40,6 +43,20 @@
public static String formatMessage(final ModuleDescriptor[] descriptors) {
return formatMessage(toMrids(descriptors));
}
+
+ /**
+ * @param loopElements a List<ModuleDescriptor>
+ */
+ public static String formatMessageFromDescriptors(List loopElements) {
+ ModuleRevisionId[] mrids = new ModuleRevisionId[loopElements.size()];
+ int pos = 0;
+ for (Iterator it = loopElements.iterator(); it.hasNext();) {
+ ModuleDescriptor descriptor = (ModuleDescriptor) it.next();
+ mrids[pos] = descriptor.getModuleRevisionId();
+ pos++;
+ }
+ return formatMessage(mrids);
+ }
public static ModuleRevisionId[] toMrids(ModuleDescriptor[] descriptors) {
ModuleRevisionId[] mrids = new ModuleRevisionId[descriptors.length];
@@ -48,5 +65,6 @@
}
return mrids;
}
+
}
Modified: incubator/ivy/core/trunk/src/java/org/apache/ivy/tools/analyser/JarJarDependencyAnalyser.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/src/java/org/apache/ivy/too \
ls/analyser/JarJarDependencyAnalyser.java?view=diff&rev=542921&r1=542920&r2=542921 \
==============================================================================
--- incubator/ivy/core/trunk/src/java/org/apache/ivy/tools/analyser/JarJarDependencyAnalyser.java \
(original)
+++ incubator/ivy/core/trunk/src/java/org/apache/ivy/tools/analyser/JarJarDependencyAnalyser.java \
Wed May 30 12:44:28 2007 @@ -73,7 +73,7 @@
DefaultModuleDescriptor md = (DefaultModuleDescriptor) \
mds.get(module.getMrid());
- DefaultDependencyDescriptor dd = new \
DefaultDependencyDescriptor(dependency.getMrid(), false); \
+ DefaultDependencyDescriptor dd = new \
DefaultDependencyDescriptor(md,dependency.getMrid(), false, false, \
true);
dd.addDependencyConfiguration(ModuleDescriptor.DEFAULT_CONFIGURATION, \
ModuleDescriptor.DEFAULT_CONFIGURATION); md.addDependency(dd);
}
Modified: incubator/ivy/core/trunk/test/java/org/apache/ivy/core/sort/SortTest.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/test/java/org/apache/ivy/core/sort/SortTest.java?view=diff&rev=542921&r1=542920&r2=542921
==============================================================================
--- incubator/ivy/core/trunk/test/java/org/apache/ivy/core/sort/SortTest.java \
(original)
+++ incubator/ivy/core/trunk/test/java/org/apache/ivy/core/sort/SortTest.java Wed May \
30 12:44:28 2007 @@ -19,98 +19,314 @@
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Date;
+import java.util.Iterator;
import java.util.List;
+import junit.framework.Assert;
import junit.framework.TestCase;
import org.apache.ivy.Ivy;
import org.apache.ivy.core.module.descriptor.DefaultDependencyDescriptor;
import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor;
+import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
+import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
import org.apache.ivy.core.module.id.ModuleRevisionId;
+import org.apache.ivy.plugins.circular.CircularDependencyHelper;
+import org.apache.ivy.plugins.circular.CircularDependencyStrategy;
+import org.apache.ivy.util.Message;
-/**
- */
public class SortTest extends TestCase {
- private ModuleRevisionId mrid1;
- private ModuleRevisionId mrid2;
- private ModuleRevisionId mrid3;
- private ModuleRevisionId mrid4;
- private DefaultModuleDescriptor[] md;
- List toSort;
-
-
-
+ private DefaultModuleDescriptor md1;
+ private DefaultModuleDescriptor md2;
+ private DefaultModuleDescriptor md3;
+ private DefaultModuleDescriptor md4;
+ private static Ivy ivy;
+
/* (non-Javadoc)
* @see junit.framework.TestCase#setUp()
*/
protected void setUp() throws Exception {
super.setUp();
- mrid1 = ModuleRevisionId.newInstance("org", "md1", "rev1");
- mrid2 = ModuleRevisionId.newInstance("org", "md2", "rev2");
- mrid3 = ModuleRevisionId.newInstance("org", "md3", "rev3");
- mrid4 = ModuleRevisionId.newInstance("org", "md4", "rev4");
- md = new DefaultModuleDescriptor[] {
- new DefaultModuleDescriptor(mrid1, "integration", new Date()),
- new DefaultModuleDescriptor(mrid2, "integration", new Date()),
- new DefaultModuleDescriptor(mrid3, "integration", new Date()),
- new DefaultModuleDescriptor(mrid4, "integration", new Date())
- };
- md[1].addDependency(new DefaultDependencyDescriptor(mrid1, false));
- md[2].addDependency(new DefaultDependencyDescriptor(mrid2, false));
- md[3].addDependency(new DefaultDependencyDescriptor(mrid3, false));
+ md1 = createModuleDescriptorToSort("md1", null); //The revison is often not \
set in the ivy.xml file that are ordered + md2 = \
createModuleDescriptorToSort("md2", "rev2");//But somtimes they are set + md3 \
= createModuleDescriptorToSort("md3", "rev3"); + md4 = \
createModuleDescriptorToSort("md4", "rev4");
+ ivy = new Ivy();
+ ivy.configureDefault();
+ Message.setImpl(null);
}
- public void testSort() throws Exception {
- Ivy ivy = new Ivy();
- ivy.configureDefault();
- toSort = new ArrayList(Arrays.asList(new Object[] {md[0], md[2], md[1], \
md[3]}));
- assertSorted(md, ivy.sortModuleDescriptors(toSort));
- toSort = new ArrayList(Arrays.asList(new Object[] {md[0], md[1], md[2], \
md[3]}));
- assertSorted(md, ivy.sortModuleDescriptors(toSort));
- toSort = new ArrayList(Arrays.asList(new Object[] {md[1], md[0], md[2], \
md[3]}));
- assertSorted(md, ivy.sortModuleDescriptors(toSort));
- toSort = new ArrayList(Arrays.asList(new Object[] {md[1], md[2], md[0], \
md[3]}));
- assertSorted(md, ivy.sortModuleDescriptors(toSort));
- toSort = new ArrayList(Arrays.asList(new Object[] {md[2], md[1], md[0], \
md[3]}));
- assertSorted(md, ivy.sortModuleDescriptors(toSort));
- toSort = new ArrayList(Arrays.asList(new Object[] {md[2], md[0], md[1], \
md[3]}));
- assertSorted(md, ivy.sortModuleDescriptors(toSort));
- toSort = new ArrayList(Arrays.asList(new Object[] {md[1], md[3], md[2], \
md[0]}));
- assertSorted(md, ivy.sortModuleDescriptors(toSort));
- }
-
- private void assertSorted(DefaultModuleDescriptor[] md, List sorted) {
- assertEquals(md.length, sorted.size());
- for (int i = 0; i < md.length; i++) {
- assertEquals(md[i], sorted.get(i));
- }
- }
- // sorter does not throw circular dependency, circular dependencies are handled \
at resolve time only
- // because circular dependencies are more complicated to evaluate than just a \
callstack comparison + protected void tearDown() throws Exception {
+ Message.sumupProblems();//purge the warning and error messages
+ Message.setImpl(null);
+ }
+
+ public void testSort() throws Exception {
+ addDependency(md2,"md1" , "rev1");
+ addDependency(md3,"md2" , "rev2");
+ addDependency(md4,"md3" , "rev3");
+
+ DefaultModuleDescriptor[][] expectedOrder = new DefaultModuleDescriptor[][] \
{{ md1, md2, md3, md4 }}; +
+ Collection permutations = getAllLists(md1, md3, md2, md4);
+ for (Iterator it = permutations.iterator(); it.hasNext();) {
+ List toSort = (List) it.next();
+ assertSorted(expectedOrder, ivy.sortModuleDescriptors(toSort));
+ }
+ }
+
+
+ /**
+ * Sorter does not throw circular dependency, circular dependencies are handled \
at resolve time only. + * However the sort respect the transitive order when it \
is unambiguous. (if A depends transitively of B, + * but B doesn't depends \
transitively on A then B always comes before A). + */
public void testCircularDependency() throws Exception {
- Ivy ivy = new Ivy();
- ivy.configureDefault();
- md[0].addDependency(new DefaultDependencyDescriptor(mrid4, false));
- toSort = new ArrayList(Arrays.asList(new Object[] {md[0], md[2], md[1], \
md[3]}));
- // the sorted array may begin by any of the modules since there is a \
circular dependency
- // in this case, the result is the following
- DefaultModuleDescriptor[] sorted = new DefaultModuleDescriptor[] {
- md[1], md[2], md[3], md[0]
+ addDependency(md1,"md4" , "rev4");
+ addDependency(md2,"md1" , "rev1");
+ addDependency(md3,"md2" , "rev2");
+ addDependency(md4,"md3" , "rev3");
+
+ DefaultModuleDescriptor[][] possibleOrder = new DefaultModuleDescriptor[][] \
{ + {md2, md3, md4, md1},
+ {md3, md4, md1, md2},
+ {md4, md1, md2, md3},
+ {md1, md2, md3, md4}
};
- assertSorted(sorted, ivy.sortModuleDescriptors(toSort));
+ Collection permutations = getAllLists(md1, md3, md2, md4);
+ for (Iterator it = permutations.iterator(); it.hasNext();) {
+ List toSort = (List) it.next();
+ assertSorted(possibleOrder, ivy.sortModuleDescriptors(toSort));
+ }
}
public void testCircularDependency2() throws Exception {
- Ivy ivy = new Ivy();
- ivy.configureDefault();
- md[1].addDependency(new DefaultDependencyDescriptor(mrid3, false));
- toSort = new ArrayList(Arrays.asList(new Object[] {md[0], md[2], md[1], \
md[3]}));
- assertSorted(md, ivy.sortModuleDescriptors(toSort));
+ addDependency(md2,"md3" , "rev3");
+ addDependency(md2,"md1" , "rev1");
+ addDependency(md3,"md2" , "rev2");
+ addDependency(md4,"md3" , "rev3");
+ DefaultModuleDescriptor[][] possibleOrder = new DefaultModuleDescriptor[][] \
{ + {md1, md3, md2, md4},
+ {md1, md2, md3, md4}//,
+ //{md3, md1, md2, md4} //It should be better to not have this \
solution. The loop should apear has one contigous element. + };
+ Collection permutations = getAllLists(md1, md3, md2, md4);
+ for (Iterator it = permutations.iterator(); it.hasNext();) {
+ List toSort = (List) it.next();
+ assertSorted(possibleOrder, ivy.sortModuleDescriptors(toSort));
+ }
}
+
+
+ /**
+ * In case of Circular dependency a warning is generated.
+ */
+ public void testCircularDependencyReport() {
+ addDependency(md2,"md3" , "rev3");
+ addDependency(md2,"md1" , "rev1");
+ addDependency(md3,"md2" , "rev2");
+ addDependency(md4,"md3" , "rev3");
+
+ //MockMessageImpl mockMessageImpl = new MockMessageImpl();
+ //Message.setImpl(mockMessageImpl);
+
+ //Would be much easier with a tool like jmock
+ class CircularDependencyReporterMock implements CircularDependencyStrategy {
+ private int nbOfCall = 0;
+ public String getName() {
+ return "CircularDependencyReporterMock";
+ }
+ public void handleCircularDependency(ModuleRevisionId[] mrids) {
+ assertEquals("handleCircularDependency is expected to be called only once" , 0, \
nbOfCall); + assertTrue("incorrect cicular dependency invocation" + \
CircularDependencyHelper.formatMessage(mrids), + mrids.length == 3 && (
+ (mrids[0].equals(md2.getModuleRevisionId()) && \
mrids[1].equals(md3.getModuleRevisionId()) && \
mrids[2].equals(md2.getModuleRevisionId())) || \
+ (mrids[0].equals(md3.getModuleRevisionId()) && \
mrids[1].equals(md2.getModuleRevisionId()) && \
mrids[2].equals(md3.getModuleRevisionId())) + ));
+ nbOfCall++;
+ }
+ public void validate() {
+ Assert.assertEquals("handleCircularDependency has nor been called" , 1, \
nbOfCall); + }
+ }
+ CircularDependencyReporterMock circularDepReportMock = new \
CircularDependencyReporterMock(); \
+ ivy.getSettings().setCircularDependencyStrategy(circularDepReportMock); +
+ List toSort = Arrays.asList(new ModuleDescriptor[] {md4 , md3 , md2 , md1});
+ ivy.sortModuleDescriptors(toSort);
+
+ circularDepReportMock.validate();
+ //mockMessageImpl.assertLogWarningContains("circular dependency detected \
during sort: [ org | md3 | rev3 ]->[ org | md2 | rev2 ]->[ org | md3 | rev3 ]"); + \
} +
+ /**
+ * The dependency can ask for the latest integration. It should match whatever \
the version declared in the modules to order. + */
+ public void testLatestIntegration() {
+
+ addDependency(md2,"md1" , "latest.integration");
+ addDependency(md3,"md2" , "latest.integration");
+ addDependency(md4,"md3" , "latest.integration");
+
+ DefaultModuleDescriptor[][] expectedOrder = new DefaultModuleDescriptor[][] \
{{ md1, md2, md3, md4 }}; +
+ Collection permutations = getAllLists(md1, md3, md2, md4);
+ for (Iterator it = permutations.iterator(); it.hasNext();) {
+ List toSort = (List) it.next();
+ assertSorted(expectedOrder, ivy.sortModuleDescriptors(toSort));
+ }
+
+ }
+
+ /**
+ * When the version asked by a dependency is not compatible with the version \
declared in the module to order, + * the two modules should be considered as \
independant + * NB: I'm sure of what 'compatible' means !
+ */
+ public void testDifferentVersionNotConsidered() {
+ //To test it, I use a 'broken' loop (in one step, I change the revision) in \
such a way that I get only one solution. If the loop was + //complete more \
solutions where possible. +
+ addDependency(md1,"md4" , "rev4-other");
+ addDependency(md2,"md1" , "rev1");
+ addDependency(md3,"md2" , "rev2");
+ addDependency(md4,"md3" , "rev3");
+
+ DefaultModuleDescriptor[][] possibleOrder = new DefaultModuleDescriptor[][] \
{ + {md1, md2, md3, md4}
+ };
+
+ Collection permutations = getAllLists(md1, md3, md2, md4);
+ for (Iterator it = permutations.iterator(); it.hasNext();) {
+ List toSort = (List) it.next();
+ assertSorted(possibleOrder, ivy.sortModuleDescriptors(toSort));
+ }
+
+ }
+
+
+ /**
+ * In case of Different version a warning is generated.
+ */
+ public void testDifferentVersionWarning() {
+ final DependencyDescriptor md4OtherDep = addDependency(md1,"md4" , \
"rev4-other"); + addDependency(md2,"md1" , "rev1");
+ addDependency(md3,"md2" , "rev2");
+ addDependency(md4,"md3" , "rev3");
+
+ //Would be much easier with a tool like jmock
+ class NonMatchingVersionReporterMock implements NonMatchingVersionReporter {
+ private int nbOfCall = 0;
+ public void reportNonMatchingVersion(DependencyDescriptor descriptor, \
ModuleDescriptor md) { + Assert.assertEquals("reportNonMatchingVersion should be \
invokded only once" , 0, nbOfCall); + Assert.assertEquals(md4OtherDep, \
descriptor); + Assert.assertEquals(md4, md);
+ nbOfCall++;
+ }
+ public void validate() {
+ Assert.assertEquals("reportNonMatchingVersion has not be called" , 1, nbOfCall);
+ }
+ }
+ NonMatchingVersionReporterMock nonMatchingVersionReporterMock = new \
NonMatchingVersionReporterMock(); + List toSort = Arrays.asList(new \
ModuleDescriptor[] {md4 , md3 , md2 , md1}); + ivy.sortModuleDescriptors(toSort , \
nonMatchingVersionReporterMock); + nonMatchingVersionReporterMock.validate();
+ }
+
+
+
+
+
+
+ private DefaultModuleDescriptor createModuleDescriptorToSort(String moduleName, \
String revision) { + ModuleRevisionId mrid = ModuleRevisionId.newInstance("org", \
moduleName, revision); + return new DefaultModuleDescriptor(mrid, "integration", \
new Date()); + }
+
+ private DependencyDescriptor addDependency(DefaultModuleDescriptor parent, \
String moduleName, String revision) { + ModuleRevisionId mrid = \
ModuleRevisionId.newInstance("org", moduleName, revision); + DependencyDescriptor \
depDescr = new DefaultDependencyDescriptor(parent , mrid , false, false, true); + \
parent.addDependency(depDescr); + return depDescr;
+ }
+
+ /**
+ * Verifies that sorted in one of the list of listOfPossibleSort.
+ * @param An array of possible sort result
+ * @param The actual sortedList to compare
+ */
+ private void assertSorted(DefaultModuleDescriptor[][] listOfPossibleSort, List \
sorted) { + for (int i = 0; i < listOfPossibleSort.length; i++) {
+ DefaultModuleDescriptor[] expectedList = listOfPossibleSort[i];
+ assertEquals(expectedList.length, sorted.size());
+ boolean isExpected = true;
+ for (int j = 0; j < expectedList.length; j++) {
+ if(!expectedList[j].equals(sorted.get(j))) {
+ isExpected = false;
+ break;
+ }
+ }
+ if (isExpected) {
+ return;
+ }
+ }
+ //failed, build a nice message
+ StringBuffer errorMessage = new StringBuffer();
+ errorMessage.append("Unexpected order : \n{ ");
+ for (int i = 0; i < sorted.size(); i++) {
+ if (i>0) errorMessage.append(" , ");
+ errorMessage.append(((DefaultModuleDescriptor)sorted.get(i)).getModuleRevisionId());
+ }
+ errorMessage.append("}\nEpected : \n");
+ for (int i = 0; i < listOfPossibleSort.length; i++) {
+ DefaultModuleDescriptor[] expectedList = listOfPossibleSort[i];
+ if (i>0) errorMessage.append(" or\n");
+ errorMessage.append("{ ");
+ for (int j = 0; j < expectedList.length; j++) {
+ if (j>0) errorMessage.append(" , ");
+ errorMessage.append(expectedList[j].getModuleRevisionId());
+ }
+ errorMessage.append(" } ");
+ }
+ fail(errorMessage.toString());
+ }
+
+ /** Returns a collection of lists that contains the elements a,b,c and d */
+ private Collection getAllLists(Object a, Object b, Object c, Object d) {
+ ArrayList r = new ArrayList(24);
+ r.add(Arrays.asList(new Object[] {a, b, c, d}));
+ r.add(Arrays.asList(new Object[] {a, b, d, c}));
+ r.add(Arrays.asList(new Object[] {a, c, b, d}));
+ r.add(Arrays.asList(new Object[] {a, c, d, b}));
+ r.add(Arrays.asList(new Object[] {a, d, b, c}));
+ r.add(Arrays.asList(new Object[] {a, d, c, b}));
+ r.add(Arrays.asList(new Object[] {b, a, c, d}));
+ r.add(Arrays.asList(new Object[] {b, a, d, c}));
+ r.add(Arrays.asList(new Object[] {b, c, a, d}));
+ r.add(Arrays.asList(new Object[] {b, c, d, a}));
+ r.add(Arrays.asList(new Object[] {b, d, a, c}));
+ r.add(Arrays.asList(new Object[] {b, d, c, a}));
+ r.add(Arrays.asList(new Object[] {c, b, a, d}));
+ r.add(Arrays.asList(new Object[] {c, b, d, a}));
+ r.add(Arrays.asList(new Object[] {c, a, b, d}));
+ r.add(Arrays.asList(new Object[] {c, a, d, b}));
+ r.add(Arrays.asList(new Object[] {c, d, b, a}));
+ r.add(Arrays.asList(new Object[] {c, d, a, b}));
+ r.add(Arrays.asList(new Object[] {d, b, c, a}));
+ r.add(Arrays.asList(new Object[] {d, b, a, c}));
+ r.add(Arrays.asList(new Object[] {d, c, b, a}));
+ r.add(Arrays.asList(new Object[] {d, c, a, b}));
+ r.add(Arrays.asList(new Object[] {d, a, b, c}));
+ r.add(Arrays.asList(new Object[] {d, a, c, b}));
+ return r;
+ }
+
+
}
Modified: incubator/ivy/core/trunk/test/java/org/apache/ivy/util/MockMessageImpl.java
URL: http://svn.apache.org/viewvc/incubator/ivy/core/trunk/test/java/org/apache/ivy/util/MockMessageImpl.java?view=diff&rev=542921&r1=542920&r2=542921
==============================================================================
--- incubator/ivy/core/trunk/test/java/org/apache/ivy/util/MockMessageImpl.java \
(original)
+++ incubator/ivy/core/trunk/test/java/org/apache/ivy/util/MockMessageImpl.java Wed \
May 30 12:44:28 2007 @@ -76,9 +76,24 @@
return;
}
}
- throw new AssertionFailedError("logs do not contain expected message: \
expected='"+message+"' logs='"+join(_logs)+"'" ); + throw new \
AssertionFailedError("logs do not contain expected message: expected='"+message+"' \
logs='\n"+join(_logs)+"'" );
}
+
+ public void assertLogInfoContains(String message) {
+ assertLogContains(Message.MSG_INFO + " " + message);
+ }
+
+ public void assertLogWarningContains(String message) {
+ Message.sumupProblems();
+ assertLogContains(Message.MSG_WARN + " \t" + message);
+ }
+
+ public void assertLogErrorContains(String message) {
+ Message.sumupProblems();
+ assertLogContains(Message.MSG_ERR + " " + message);
+ }
+
private String join(List logs) {
StringBuffer sb = new StringBuffer();
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic