You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@ant.apache.org by xa...@apache.org on 2008/07/09 16:23:22 UTC
svn commit: r675186 - in /ant/ivy/core/trunk: ./
src/java/org/apache/ivy/core/resolve/
test/java/org/apache/ivy/core/resolve/ test/repositories/2/mod6.1/
Author: xavier
Date: Wed Jul 9 07:23:22 2008
New Revision: 675186
URL: http://svn.apache.org/viewvc?rev=675186&view=rev
Log:
FIX: dynamic revision resolve does not throw error when configuration is missing (IVY-861)
Added:
ant/ivy/core/trunk/test/repositories/2/mod6.1/ivy-1.5.xml (with props)
Modified:
ant/ivy/core/trunk/CHANGES.txt
ant/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/IvyNode.java
ant/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/IvyNodeUsage.java
ant/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/ResolveEngine.java
ant/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/VisitNode.java
ant/ivy/core/trunk/test/java/org/apache/ivy/core/resolve/ResolveTest.java
Modified: ant/ivy/core/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/CHANGES.txt?rev=675186&r1=675185&r2=675186&view=diff
==============================================================================
--- ant/ivy/core/trunk/CHANGES.txt (original)
+++ ant/ivy/core/trunk/CHANGES.txt Wed Jul 9 07:23:22 2008
@@ -95,6 +95,7 @@
- IMPROVEMENT: Change allownomd and skipbuildwithoutivy into a more semantically correct name (IVY-297)
- IMPROVEMENT: Smarter determination if an expression is exact or not for RegexpPatternMatcher and GlobPatternMatcher
+- FIX: dynamic revision resolve does not throw error when configuration is missing (IVY-861)
- FIX: Referenced resolver not found in macro (IVY-860)
- FIX: Ivy files are not retrieved when using useOrigin=true (IVY-713)
- FIX: NPE in Ivy:install task if the repository cache dir has been cleared (IVY-843)
Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/IvyNode.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/IvyNode.java?rev=675186&r1=675185&r2=675186&view=diff
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/IvyNode.java (original)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/IvyNode.java Wed Jul 9 07:23:22 2008
@@ -133,7 +133,7 @@
* real node after the call IvyNode node = ... node.loadData(); node = node.getRealNode(); ...
*/
public boolean loadData(String rootModuleConf, IvyNode parent, String parentConf, String conf,
- boolean shouldBePublic) {
+ boolean shouldBePublic, IvyNodeUsage usage) {
Message.debug("loadData of " + this.toString() + " of rootConf=" + rootModuleConf);
if (!isRoot() && (data.getReport() != null)) {
data.getReport().addDependency(this);
@@ -203,7 +203,7 @@
// => update it and discard this node
md = module.getDescriptor(); // needed for handleConfiguration
if (!handleConfiguration(loaded, rootModuleConf, parent,
- parentConf, conf, shouldBePublic)) {
+ parentConf, conf, shouldBePublic, usage)) {
return false;
}
@@ -246,7 +246,8 @@
loaded = true;
}
}
- handleConfiguration(loaded, rootModuleConf, parent, parentConf, conf, shouldBePublic);
+ handleConfiguration(
+ loaded, rootModuleConf, parent, parentConf, conf, shouldBePublic, usage);
if (hasProblem()) {
Message.debug("problem : " + problem.getMessage());
return false;
@@ -271,11 +272,10 @@
resolved.searched |= module.getReport().isSearched();
resolved.dds.putAll(dds);
resolved.updateDataFrom(this, rootModuleConf, true);
- resolved.loadData(rootModuleConf, parent, parentConf, conf, shouldBePublic);
+ resolved.loadData(rootModuleConf, parent, parentConf, conf, shouldBePublic, usage);
DependencyDescriptor dd = getDependencyDescriptor(parent);
- if (dd != null) {
- resolved.usage.addUsage(rootModuleConf, dd, parentConf);
- }
+ resolved.usage.updateDataFrom(getAllUsages(), rootModuleConf);
+ usage = resolved.usage;
data.replaceNode(getId(), resolved, rootModuleConf); // this actually discards the node
@@ -336,9 +336,11 @@
}
}
- Collection confs = Arrays.asList(resolveSpecialConfigurations(dependencyConfigurations,
- depNode));
+ String[] confsArray = resolveSpecialConfigurations(dependencyConfigurations,
+ depNode);
+ Collection confs = Arrays.asList(confsArray);
depNode.updateConfsToFetch(confs);
+ depNode.addRootModuleConfigurations(depNode.usage, rootModuleConf, confsArray);
depNode.usage.setRequiredConfs(this, conf, confs);
depNode.addCaller(rootModuleConf, this, conf, dependencyConfigurations, dd);
@@ -374,24 +376,25 @@
}
private boolean handleConfiguration(boolean loaded, String rootModuleConf, IvyNode parent,
- String parentConf, String conf, boolean shouldBePublic) {
+ String parentConf, String conf, boolean shouldBePublic, IvyNodeUsage usage) {
if (md != null) {
String[] confs = getRealConfs(conf);
+ addRootModuleConfigurations(usage, rootModuleConf, confs);
for (int i = 0; i < confs.length; i++) {
Configuration c = md.getConfiguration(confs[i]);
if (c == null) {
confsToFetch.remove(conf);
if (isConfRequiredByMergedUsageOnly(rootModuleConf, conf)) {
- Message.verbose(
+ Message.info(
"configuration required by evicted revision is not available in "
+ "selected revision. skipping " + conf + " in " + this);
} else if (!conf.equals(confs[i])) {
- problem = new RuntimeException("configuration(s) not found in " + this
- + ": " + conf + ". Missing configuration: " + confs[i]
- + ". It was required from " + parent + " " + parentConf);
+ problem = new RuntimeException("configuration not found in " + this
+ + ": '" + conf + "'. Missing configuration: '" + confs[i]
+ + "'. It was required from " + parent + " " + parentConf);
} else {
- problem = new RuntimeException("configuration(s) not found in " + this
- + ": " + confs[i] + ". It was required from " + parent + " "
+ problem = new RuntimeException("configuration not found in " + this
+ + ": '" + confs[i] + "'. It was required from " + parent + " "
+ parentConf);
}
return false;
@@ -399,21 +402,20 @@
&& c.getVisibility() != Configuration.Visibility.PUBLIC) {
confsToFetch.remove(conf);
if (isConfRequiredByMergedUsageOnly(rootModuleConf, conf)) {
- Message.verbose(
+ Message.info(
"configuration required by evicted revision is not visible in "
+ "selected revision. skipping " + conf + " in " + this);
} else {
- problem = new RuntimeException("configuration not public in " + this + ": "
- + c + ". It was required from " + parent + " " + parentConf);
+ problem = new RuntimeException("configuration not public in " + this + ": '"
+ + c + "'. It was required from " + parent + " " + parentConf);
}
return false;
}
- if (loaded) {
- fetchedConfigurations.add(conf);
- confsToFetch.removeAll(Arrays.asList(confs));
- confsToFetch.remove(conf);
- }
- addRootModuleConfigurations(rootModuleConf, confs);
+ }
+ if (loaded) {
+ fetchedConfigurations.add(conf);
+ confsToFetch.removeAll(Arrays.asList(confs));
+ confsToFetch.remove(conf);
}
}
return true;
@@ -554,19 +556,18 @@
}
}
- private void addRootModuleConfigurations(String rootModuleConf, String[] dependencyConfs) {
+ private void addRootModuleConfigurations(
+ IvyNodeUsage usage, String rootModuleConf, String[] dependencyConfs) {
Set depConfs = usage.addAndGetConfigurations(rootModuleConf);
if (md != null) {
// add all given dependency configurations to the set + extended ones
for (int i = 0; i < dependencyConfs.length; i++) {
+ depConfs.add(dependencyConfs[i]);
Configuration conf = md.getConfiguration(dependencyConfs[i]);
if (conf != null) {
String[] exts = conf.getExtends();
- addRootModuleConfigurations(rootModuleConf, exts); // recursive add of extended
- // configurations
- depConfs.add(conf.getName());
- } else {
- Message.warn("unknown configuration in " + getId() + ": " + dependencyConfs[i]);
+ // recursive add of extended
+ addRootModuleConfigurations(usage, rootModuleConf, exts);
}
}
} else {
@@ -679,7 +680,7 @@
callers.updateFrom(node.callers, rootModuleConf, real);
if (real) {
- usage.updateDataFrom(node.usage, rootModuleConf);
+ usage.updateDataFrom(node.getAllUsages(), rootModuleConf);
} else {
// let's copy usage information for the given rootModuleConf, into a separate usage
// object to keep detailed data about where usage comes from
@@ -688,13 +689,20 @@
mergedUsage = new IvyNodeUsage(node);
mergedUsages.put(node.getId(), mergedUsage);
}
- mergedUsage.updateDataFrom(node.usage, rootModuleConf);
+ mergedUsage.updateDataFrom(node.getAllUsages(), rootModuleConf);
}
// update confsToFetch
updateConfsToFetch(node.fetchedConfigurations);
updateConfsToFetch(node.confsToFetch);
}
+
+ private Collection/*<IvyNodeUsage>*/ getAllUsages() {
+ Collection usages = new ArrayList();
+ usages.add(usage);
+ usages.addAll(mergedUsages.values());
+ return usages;
+ }
/**
* Returns all the artifacts of this dependency required in all the root module configurations
@@ -1048,11 +1056,6 @@
public void markEvicted(EvictionData evictionData) {
eviction.markEvicted(evictionData);
String rootModuleConf = evictionData.getRootModuleConf();
- usage.removeRootModuleConf(rootModuleConf);
- for (Iterator iterator = mergedUsages.values().iterator(); iterator.hasNext();) {
- IvyNodeUsage usage = (IvyNodeUsage) iterator.next();
- usage.removeRootModuleConf(rootModuleConf);
- }
// bug 105: update selected data with evicted one
if (evictionData.getSelected() != null) {
@@ -1252,4 +1255,8 @@
return usage.getBlacklistData(rootModuleConf);
}
+ public IvyNodeUsage getMainUsage() {
+ return usage;
+ }
+
}
Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/IvyNodeUsage.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/IvyNodeUsage.java?rev=675186&r1=675185&r2=675186&view=diff
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/IvyNodeUsage.java (original)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/IvyNodeUsage.java Wed Jul 9 07:23:22 2008
@@ -94,6 +94,24 @@
this.dd = dd;
this.dependerConf = dependerConf;
}
+
+ public String toString() {
+ return dd + " [" + dependerConf + "]";
+ }
+
+ public boolean equals(Object obj) {
+ if (! (obj instanceof Depender)) {
+ return false;
+ }
+ Depender other = (Depender) obj;
+ return other.dd == dd && other.dependerConf.equals(dependerConf);
+ }
+ public int hashCode() {
+ int hash = 33;
+ hash += dd.hashCode() * 13;
+ hash += dependerConf.hashCode() * 13;
+ return hash;
+ }
}
private IvyNode node;
@@ -146,7 +164,15 @@
return rootModuleConfs.keySet();
}
- public void updateDataFrom(IvyNodeUsage usage, String rootModuleConf) {
+
+ public void updateDataFrom(Collection/*<IvyNodeUsage>*/ usages, String rootModuleConf) {
+ for (Iterator iterator = usages.iterator(); iterator.hasNext();) {
+ IvyNodeUsage usage = (IvyNodeUsage) iterator.next();
+ updateDataFrom(usage, rootModuleConf);
+ }
+ }
+
+ private void updateDataFrom(IvyNodeUsage usage, String rootModuleConf) {
// update requiredConfs
updateMapOfSet(usage.requiredConfs, requiredConfs);
Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/ResolveEngine.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/ResolveEngine.java?rev=675186&r1=675185&r2=675186&view=diff
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/ResolveEngine.java (original)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/ResolveEngine.java Wed Jul 9 07:23:22 2008
@@ -694,16 +694,18 @@
for (int i = 0; i < confs.length; i++) {
fetchDependencies(dep, confs[i], true);
}
- // if there are still confs to fetch (usually because they have
- // been updated when evicting another module), we fetch them now
- confs = dep.getConfsToFetch();
- for (int i = 0; i < confs.length; i++) {
- //shouldBeFixed=false to because some of those dependencies might
- //be private when they were actually extending public conf.
- //Should we keep two list of confs to fetch (private&public)?
- //I don't think, visibility is already checked, and a change in the
- //configuration between version might anyway have worse problems.
- fetchDependencies(dep, confs[i], false);
+ if (!dep.isEvicted() && !dep.hasProblem()) {
+ // if there are still confs to fetch (usually because they have
+ // been updated when evicting another module), we fetch them now
+ confs = dep.getConfsToFetch();
+ for (int i = 0; i < confs.length; i++) {
+ //shouldBeFixed=false to because some of those dependencies might
+ //be private when they were actually extending public conf.
+ //Should we keep two list of confs to fetch (private&public)?
+ //I don't think, visibility is already checked, and a change in the
+ //configuration between version might anyway have worse problems.
+ fetchDependencies(dep, confs[i], false);
+ }
}
}
markDependenciesFetched(node.getNode(), conf);
Modified: ant/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/VisitNode.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/VisitNode.java?rev=675186&r1=675185&r2=675186&view=diff
==============================================================================
--- ant/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/VisitNode.java (original)
+++ ant/ivy/core/trunk/src/java/org/apache/ivy/core/resolve/VisitNode.java Wed Jul 9 07:23:22 2008
@@ -98,9 +98,21 @@
* the current path. null if not computed yet Boolean.FALSE otherwise
*/
private Boolean isCircular;
+
+ /**
+ * IvyNode usage information to update when visiting the underlying IvyNode.
+ * This is usually the main IvyNodeUsage of the underlying node, except when we are visiting it
+ * coming from an evicted node replaced by the other one.
+ */
+ private IvyNodeUsage usage;
public VisitNode(ResolveData data, IvyNode node, VisitNode parent, String rootModuleConf,
String parentConf) {
+ this(data, node, parent, rootModuleConf, parentConf, null);
+ }
+
+ public VisitNode(ResolveData data, IvyNode node, VisitNode parent, String rootModuleConf,
+ String parentConf, IvyNodeUsage usage) {
Checks.checkNotNull(data, "data");
Checks.checkNotNull(node, "node");
Checks.checkNotNull(rootModuleConf, "rootModuleConf");
@@ -110,6 +122,7 @@
this.parent = parent;
this.rootModuleConf = rootModuleConf;
this.parentConf = parentConf;
+ this.usage = usage;
this.data.register(this);
}
@@ -254,8 +267,8 @@
}
public boolean loadData(String conf, boolean shouldBePublic) {
- boolean loaded = node.loadData(rootModuleConf, getParentNode(), parentConf, conf,
- shouldBePublic);
+ boolean loaded = node.loadData(
+ rootModuleConf, getParentNode(), parentConf, conf, shouldBePublic, getUsage());
if (loaded) {
useRealNode();
@@ -265,7 +278,8 @@
// - the id refers to a dynamic revision, which has been resolved by loadData
// - the loaded module descriptor has extra attributes in his info tag which are not
// used when declaring the dependency
- if (!getId().equals(node.getResolvedId())) {
+ if (data.getNode(node.getResolvedId()) == null
+ || !data.getNode(node.getResolvedId()).getId().equals(node.getResolvedId())) {
data.register(node.getResolvedId(), this);
}
}
@@ -309,19 +323,26 @@
VisitNode vnode = (VisitNode) iter.next();
if ((parent == null && vnode.getParent() == null)
|| (parent != null && parent.getId().equals(vnode.getParent().getId()))) {
+ vnode.parentConf = parentConf;
+ vnode.usage = getUsage();
return vnode;
}
}
// the node has not yet been visited from the current parent, we create a new visit node
- return traverse(parent, parentConf, node);
+ return traverse(parent, parentConf, node, getUsage());
+ }
+
+ private IvyNodeUsage getUsage() {
+ return usage == null ? node.getMainUsage() : usage;
}
private VisitNode traverseChild(String parentConf, IvyNode child) {
VisitNode parent = this;
- return traverse(parent, parentConf, child);
+ return traverse(parent, parentConf, child, null);
}
- private VisitNode traverse(VisitNode parent, String parentConf, IvyNode node) {
+ private VisitNode traverse(
+ VisitNode parent, String parentConf, IvyNode node, IvyNodeUsage usage) {
if (getPath().contains(node)) {
IvyContext.getContext().getCircularDependencyStrategy().handleCircularDependency(
toMrids(getPath(), node.getId()));
@@ -329,7 +350,7 @@
// root
// parent = getVisitNode(depNode).getParent();
}
- return new VisitNode(data, node, parent, rootModuleConf, parentConf);
+ return new VisitNode(data, node, parent, rootModuleConf, parentConf, usage);
}
private ModuleRevisionId[] toMrids(Collection path, ModuleRevisionId last) {
Modified: ant/ivy/core/trunk/test/java/org/apache/ivy/core/resolve/ResolveTest.java
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/test/java/org/apache/ivy/core/resolve/ResolveTest.java?rev=675186&r1=675185&r2=675186&view=diff
==============================================================================
--- ant/ivy/core/trunk/test/java/org/apache/ivy/core/resolve/ResolveTest.java (original)
+++ ant/ivy/core/trunk/test/java/org/apache/ivy/core/resolve/ResolveTest.java Wed Jul 9 07:23:22 2008
@@ -2096,6 +2096,17 @@
assertFalse(getArchiveFileInCache("org5", "mod5.1", "4.0", "art51B", "jar", "jar").exists());
}
+ public void testFailWithMissingConf() throws Exception {
+ // test case for IVY-861
+
+ // mod6.1 r1.5 depends on
+ // mod5.1 [1.0,4.3] conf unknown which doesn't exist in mod5.1;4.3
+ ResolveReport report = ivy.resolve(new File("test/repositories/2/mod6.1/ivy-1.5.xml")
+ .toURL(), getResolveOptions(new String[] {"*"}));
+ assertTrue("missing conf should have raised an error in report", report.hasError());
+ assertTrue(StringUtils.join(report.getAllProblemMessages().toArray(), "\n").indexOf("'unknown'") != -1);
+ }
+
public void testEvictWithConfInMultiConf() throws Exception {
// same as preceding ones but the conflict appears in several root confs
// bug 105 - test #3
Added: ant/ivy/core/trunk/test/repositories/2/mod6.1/ivy-1.5.xml
URL: http://svn.apache.org/viewvc/ant/ivy/core/trunk/test/repositories/2/mod6.1/ivy-1.5.xml?rev=675186&view=auto
==============================================================================
--- ant/ivy/core/trunk/test/repositories/2/mod6.1/ivy-1.5.xml (added)
+++ ant/ivy/core/trunk/test/repositories/2/mod6.1/ivy-1.5.xml Wed Jul 9 07:23:22 2008
@@ -0,0 +1,29 @@
+<!--
+ 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.
+-->
+<ivy-module version="1.0">
+ <info organisation="org6"
+ module="mod6.1"
+ revision="1.5"
+ status="integration"
+ publication="20080401110000"
+ />
+ <dependencies>
+ <dependency org="org5" name="mod5.1" rev="[1.0,4.3]" conf="default->unknown"/>
+ </dependencies>
+</ivy-module>
Propchange: ant/ivy/core/trunk/test/repositories/2/mod6.1/ivy-1.5.xml
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: ant/ivy/core/trunk/test/repositories/2/mod6.1/ivy-1.5.xml
------------------------------------------------------------------------------
svn:mime-type = text/plain