Repository: ant-ivy Updated Branches: refs/heads/master 83fcd3e1e -> f6322b7fb
A workspace resolver for Ant. The code is inspired from IvyDEâs one. Work in progress. Project: http://git-wip-us.apache.org/repos/asf/ant-ivy/repo Commit: http://git-wip-us.apache.org/repos/asf/ant-ivy/commit/f6322b7f Tree: http://git-wip-us.apache.org/repos/asf/ant-ivy/tree/f6322b7f Diff: http://git-wip-us.apache.org/repos/asf/ant-ivy/diff/f6322b7f Branch: refs/heads/master Commit: f6322b7fb747b6a6830f6f331e836690adb95067 Parents: 83fcd3e Author: Nicolas LaleveÌe <nicolas.lale...@hibnet.org> Authored: Sun Dec 21 16:10:34 2014 +0100 Committer: Nicolas Lalevée <nicolas.lale...@hibnet.org> Committed: Sun Jan 25 22:32:28 2015 +0100 ---------------------------------------------------------------------- .../apache/ivy/ant/AntWorkspaceResolver.java | 231 ++++++++++++++++++ src/java/org/apache/ivy/ant/IvyAntSettings.java | 9 + src/java/org/apache/ivy/ant/IvyConfigure.java | 5 + src/java/org/apache/ivy/ant/antlib.xml | 1 + .../DefaultWorkspaceModuleDescriptor.java | 42 ++++ .../descriptor/WorkspaceModuleDescriptor.java | 26 ++ .../apache/ivy/core/resolve/IvyNodeUsage.java | 5 + .../apache/ivy/core/settings/IvySettings.java | 64 ++++- .../plugins/latest/WorkspaceLatestStrategy.java | 57 +++++ .../resolver/AbstractWorkspaceResolver.java | 239 +++++++++++++++++++ .../resolver/WorkspaceChainResolver.java | 37 +++ .../apache/ivy/ant/AntBuildResolverTest.java | 213 +++++++++++++++++ test/workspace/ivysettings.xml | 30 +++ test/workspace/project1/ivy.xml | 24 ++ test/workspace/project2/ivy.xml | 24 ++ test/workspace/project3/ivy.xml | 26 ++ .../workspace/repo/org.acme/module1/1.1/ivy.xml | 21 ++ .../repo/org.acme/module1/1.1/module1.jar | 0 .../workspace/repo/org.acme/module2/1.2/ivy.xml | 21 ++ .../repo/org.acme/module2/1.2/module2.jar | 0 20 files changed, 1068 insertions(+), 7 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/f6322b7f/src/java/org/apache/ivy/ant/AntWorkspaceResolver.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/ivy/ant/AntWorkspaceResolver.java b/src/java/org/apache/ivy/ant/AntWorkspaceResolver.java new file mode 100644 index 0000000..27cf686 --- /dev/null +++ b/src/java/org/apache/ivy/ant/AntWorkspaceResolver.java @@ -0,0 +1,231 @@ +/* + * 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.ant; + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.net.URL; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.ivy.core.module.descriptor.Artifact; +import org.apache.ivy.core.module.descriptor.DefaultArtifact; +import org.apache.ivy.core.module.descriptor.DependencyDescriptor; +import org.apache.ivy.core.module.descriptor.ModuleDescriptor; +import org.apache.ivy.core.report.ArtifactDownloadReport; +import org.apache.ivy.core.report.DownloadReport; +import org.apache.ivy.core.report.DownloadStatus; +import org.apache.ivy.core.resolve.DownloadOptions; +import org.apache.ivy.core.resolve.ResolveData; +import org.apache.ivy.core.resolve.ResolvedModuleRevision; +import org.apache.ivy.plugins.parser.ModuleDescriptorParserRegistry; +import org.apache.ivy.plugins.resolver.AbstractWorkspaceResolver; +import org.apache.ivy.util.Message; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.types.DataType; +import org.apache.tools.ant.types.ResourceCollection; +import org.apache.tools.ant.types.resources.FileResource; + +public class AntWorkspaceResolver extends DataType { + + public static final class WorkspaceArtifact { + + private String name; + + private String type; + + private String ext; + + private String path; + + public void setName(String name) { + this.name = name; + } + + public void setType(String type) { + this.type = type; + } + + public void setExt(String ext) { + this.ext = ext; + } + + public void setPath(String path) { + this.path = path; + } + } + + private List<ResourceCollection> allResources = new ArrayList<ResourceCollection>(); + + private boolean haltOnError = true; + + private Resolver resolver; + + private String name; + + private List<WorkspaceArtifact> artifacts = new ArrayList<WorkspaceArtifact>(); + + public void setName(String name) { + this.name = name; + } + + public void setHaltonerror(boolean haltOnError) { + this.haltOnError = haltOnError; + } + + public void addResourceCollection(ResourceCollection resources) { + if (!resources.isFilesystemOnly()) { + throw new BuildException("Only filesystem resource collection is supported"); + } + allResources.add(resources); + } + + public WorkspaceArtifact createArtifact() { + WorkspaceArtifact a = new WorkspaceArtifact(); + artifacts.add(a); + return a; + } + + public Resolver getResolver() { + if (resolver == null) { + if (name == null) { + throw new BuildException("A name is required"); + } + resolver = new Resolver(); + resolver.setName(name); + } + return resolver; + } + + private String getProjectName(File ivyFile) { + return ivyFile.getParentFile().getName(); + } + + private class Resolver extends AbstractWorkspaceResolver { + + private Map<ModuleDescriptor, File> md2IvyFile; + + private synchronized Map<ModuleDescriptor, File> getModuleDescriptors() { + if (md2IvyFile == null) { + md2IvyFile = new HashMap<ModuleDescriptor, File>(); + for (ResourceCollection resources : allResources) { + for (Iterator it = resources.iterator(); it.hasNext();) { + File ivyFile = ((FileResource) it.next()).getFile(); + try { + ModuleDescriptor md = ModuleDescriptorParserRegistry.getInstance() + .parseDescriptor(getParserSettings(), ivyFile.toURI().toURL(), + isValidate()); + md2IvyFile.put(md, ivyFile); + Message.debug("Add " + md.getModuleRevisionId().getModuleId()); + } catch (Exception ex) { + if (haltOnError) { + throw new BuildException("impossible to parse ivy file " + ivyFile + + " exception=" + ex, ex); + } else { + Message.warn("impossible to parse ivy file " + ivyFile + + " exception=" + ex.getMessage()); + } + } + } + } + } + return md2IvyFile; + } + + public ResolvedModuleRevision getDependency(DependencyDescriptor dd, ResolveData data) + throws ParseException { + Map<ModuleDescriptor, File> mds = getModuleDescriptors(); + for (Entry<ModuleDescriptor, File> md : mds.entrySet()) { + ResolvedModuleRevision rmr = checkCandidate(dd, md.getKey(), + getProjectName(md.getValue())); + if (rmr != null) { + return rmr; + } + } + return null; + } + + @Override + protected List<Artifact> createWorkspaceArtifacts(ModuleDescriptor md) { + List<Artifact> res = new ArrayList<Artifact>(); + + for (WorkspaceArtifact wa : artifacts) { + String name = wa.name; + String type = wa.type; + String ext = wa.ext; + String path = wa.path; + if (name == null) { + name = md.getModuleRevisionId().getName(); + } + if (type == null) { + type = "jar"; + } + if (ext == null) { + ext = "jar"; + } + if (path == null) { + path = "target" + File.separator + "dist" + File.separator + type + "s" + + File.separator + name + "." + ext; + } + + URL url; + File ivyFile = md2IvyFile.get(md); + File artifactFile = new File(ivyFile.getParentFile(), path); + try { + url = artifactFile.toURI().toURL(); + } catch (MalformedURLException e) { + throw new RuntimeException("Unsupported file path : " + artifactFile, e); + } + + res.add(new DefaultArtifact(md.getModuleRevisionId(), new Date(), name, type, ext, + url, null)); + } + + return res; + } + + public DownloadReport download(Artifact[] artifacts, DownloadOptions options) { + // Not much to do here - downloads are not required for workspace projects. + DownloadReport dr = new DownloadReport(); + for (int i = 0; i < artifacts.length; i++) { + ArtifactDownloadReport adr = new ArtifactDownloadReport(artifacts[i]); + dr.addArtifactReport(adr); + adr.setDownloadStatus(DownloadStatus.NO); + adr.setSize(0); + URL url = artifacts[i].getUrl(); + File f; + try { + f = new File(url.toURI()); + } catch (URISyntaxException e) { + f = new File(url.getPath()); + } + adr.setLocalFile(f); + Message.verbose("\t[IN WORKSPACE] " + artifacts[i]); + } + return dr; + } + } + +} http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/f6322b7f/src/java/org/apache/ivy/ant/IvyAntSettings.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/ivy/ant/IvyAntSettings.java b/src/java/org/apache/ivy/ant/IvyAntSettings.java index 660ebbe..bb67ba7 100644 --- a/src/java/org/apache/ivy/ant/IvyAntSettings.java +++ b/src/java/org/apache/ivy/ant/IvyAntSettings.java @@ -102,6 +102,8 @@ public class IvyAntSettings extends DataType { private boolean autoRegistered = false; + private AntWorkspaceResolver antWorkspaceResolver; + /** * Returns the default ivy settings of this classloader. If it doesn't exist yet, a new one is * created using the given project to back the VariableContainer. @@ -275,6 +277,10 @@ public class IvyAntSettings extends DataType { defineDefaultSettingFile(ivyAntVariableContainer, task); } + if (antWorkspaceResolver != null) { + settings.addConfigured(antWorkspaceResolver.getResolver()); + } + Ivy ivy = Ivy.newInstance(settings); try { ivy.pushContext(); @@ -388,4 +394,7 @@ public class IvyAntSettings extends DataType { URLHandlerRegistry.setDefault(dispatcher); } + public void addConfiguredWorkspaceResolver(AntWorkspaceResolver antWorkspaceResolver) { + this.antWorkspaceResolver = antWorkspaceResolver; + } } http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/f6322b7f/src/java/org/apache/ivy/ant/IvyConfigure.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/ivy/ant/IvyConfigure.java b/src/java/org/apache/ivy/ant/IvyConfigure.java index 5e05adc..6926d02 100644 --- a/src/java/org/apache/ivy/ant/IvyConfigure.java +++ b/src/java/org/apache/ivy/ant/IvyConfigure.java @@ -130,6 +130,11 @@ public class IvyConfigure extends Task { settings.setPasswd(passwd); } + public void addConfiguredWorkspaceResolver(AntWorkspaceResolver resolver) { + settings.addConfiguredWorkspaceResolver(resolver); + } + + @Override public void execute() throws BuildException { String settingsId = settings.getId(); Object otherRef = getProject().getReference(settingsId); http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/f6322b7f/src/java/org/apache/ivy/ant/antlib.xml ---------------------------------------------------------------------- diff --git a/src/java/org/apache/ivy/ant/antlib.xml b/src/java/org/apache/ivy/ant/antlib.xml index ac32740..0111f78 100644 --- a/src/java/org/apache/ivy/ant/antlib.xml +++ b/src/java/org/apache/ivy/ant/antlib.xml @@ -49,4 +49,5 @@ <taskdef name="fixdeps" classname="org.apache.ivy.ant.FixDepsTask" /> <taskdef name="dependencytree" classname="org.apache.ivy.ant.IvyDependencyTree"/> <taskdef name="checkdepsupdate" classname="org.apache.ivy.ant.IvyDependencyUpdateChecker"/> + <typedef name="workspaceresolver" classname="org.apache.ivy.ant.AntWorkspaceResolver" /> </antlib> http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/f6322b7f/src/java/org/apache/ivy/core/module/descriptor/DefaultWorkspaceModuleDescriptor.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/ivy/core/module/descriptor/DefaultWorkspaceModuleDescriptor.java b/src/java/org/apache/ivy/core/module/descriptor/DefaultWorkspaceModuleDescriptor.java new file mode 100644 index 0000000..1c86f56 --- /dev/null +++ b/src/java/org/apache/ivy/core/module/descriptor/DefaultWorkspaceModuleDescriptor.java @@ -0,0 +1,42 @@ +/* + * 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.module.descriptor; + +import java.util.Date; + +import org.apache.ivy.core.module.id.ModuleRevisionId; +import org.apache.ivy.plugins.parser.ModuleDescriptorParser; +import org.apache.ivy.plugins.repository.Resource; + +public class DefaultWorkspaceModuleDescriptor extends DefaultModuleDescriptor implements + WorkspaceModuleDescriptor { + + public DefaultWorkspaceModuleDescriptor(ModuleDescriptorParser parser, Resource res) { + super(parser, res); + } + + public DefaultWorkspaceModuleDescriptor(ModuleRevisionId id, String status, Date pubDate) { + super(id, status, pubDate); + } + + public DefaultWorkspaceModuleDescriptor(ModuleRevisionId id, String status, Date pubDate, + boolean isDefault) { + super(id, status, pubDate, isDefault); + } + +} http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/f6322b7f/src/java/org/apache/ivy/core/module/descriptor/WorkspaceModuleDescriptor.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/ivy/core/module/descriptor/WorkspaceModuleDescriptor.java b/src/java/org/apache/ivy/core/module/descriptor/WorkspaceModuleDescriptor.java new file mode 100644 index 0000000..4403526 --- /dev/null +++ b/src/java/org/apache/ivy/core/module/descriptor/WorkspaceModuleDescriptor.java @@ -0,0 +1,26 @@ +/* + * 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.module.descriptor; + +/** + * Marker interface for module descriptor of a module in a workspace, then having special semantics, + * like artifacts declared by the resolver rather than the descriptor + */ +public interface WorkspaceModuleDescriptor extends ModuleDescriptor { + +} http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/f6322b7f/src/java/org/apache/ivy/core/resolve/IvyNodeUsage.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/ivy/core/resolve/IvyNodeUsage.java b/src/java/org/apache/ivy/core/resolve/IvyNodeUsage.java index b6631f2..cb0eafe 100644 --- a/src/java/org/apache/ivy/core/resolve/IvyNodeUsage.java +++ b/src/java/org/apache/ivy/core/resolve/IvyNodeUsage.java @@ -27,6 +27,7 @@ import java.util.Set; import org.apache.ivy.core.module.descriptor.DependencyArtifactDescriptor; import org.apache.ivy.core.module.descriptor.DependencyDescriptor; import org.apache.ivy.core.module.descriptor.IncludeRule; +import org.apache.ivy.core.module.descriptor.WorkspaceModuleDescriptor; /** * Class collecting usage data for an IvyNode. @@ -219,6 +220,10 @@ public class IvyNodeUsage { } protected Set<DependencyArtifactDescriptor> getDependencyArtifactsSet(String rootModuleConf) { + if (node.getDescriptor() instanceof WorkspaceModuleDescriptor) { + // for a module in the "workspace" artifacts will be actually declared by the resolver + return null; + } Collection<Depender> dependersInConf = dependers.get(rootModuleConf); if (dependersInConf == null) { return null; http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/f6322b7f/src/java/org/apache/ivy/core/settings/IvySettings.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/ivy/core/settings/IvySettings.java b/src/java/org/apache/ivy/core/settings/IvySettings.java index de806bf..5113cf5 100644 --- a/src/java/org/apache/ivy/core/settings/IvySettings.java +++ b/src/java/org/apache/ivy/core/settings/IvySettings.java @@ -76,6 +76,7 @@ import org.apache.ivy.plugins.latest.LatestLexicographicStrategy; import org.apache.ivy.plugins.latest.LatestRevisionStrategy; import org.apache.ivy.plugins.latest.LatestStrategy; import org.apache.ivy.plugins.latest.LatestTimeStrategy; +import org.apache.ivy.plugins.latest.WorkspaceLatestStrategy; import org.apache.ivy.plugins.lock.CreateFileLockStrategy; import org.apache.ivy.plugins.lock.LockStrategy; import org.apache.ivy.plugins.lock.NIOFileLockStrategy; @@ -92,10 +93,12 @@ import org.apache.ivy.plugins.parser.ParserSettings; import org.apache.ivy.plugins.report.LogReportOutputter; import org.apache.ivy.plugins.report.ReportOutputter; import org.apache.ivy.plugins.report.XmlReportOutputter; +import org.apache.ivy.plugins.resolver.AbstractWorkspaceResolver; import org.apache.ivy.plugins.resolver.ChainResolver; import org.apache.ivy.plugins.resolver.DependencyResolver; import org.apache.ivy.plugins.resolver.DualResolver; import org.apache.ivy.plugins.resolver.ResolverSettings; +import org.apache.ivy.plugins.resolver.WorkspaceChainResolver; import org.apache.ivy.plugins.signer.SignatureGenerator; import org.apache.ivy.plugins.trigger.Trigger; import org.apache.ivy.plugins.version.ChainVersionMatcher; @@ -207,6 +210,8 @@ public class IvySettings implements SortEngineSettings, PublishEngineSettings, P private PackingRegistry packingRegistry = new PackingRegistry(); + private AbstractWorkspaceResolver workspaceResolver; + public IvySettings() { this(new IvyVariableContainerImpl()); } @@ -879,9 +884,20 @@ public class IvySettings implements SortEngineSettings, PublishEngineSettings, P dictatorResolver = resolver; } + private DependencyResolver getDictatorResolver() { + if (dictatorResolver == null) { + return null; + } + if (workspaceResolver != null && !(dictatorResolver instanceof WorkspaceChainResolver)) { + dictatorResolver = new WorkspaceChainResolver(this, dictatorResolver, workspaceResolver); + } + return dictatorResolver; + } + public synchronized DependencyResolver getResolver(ModuleRevisionId mrid) { - if (dictatorResolver != null) { - return dictatorResolver; + DependencyResolver r = getDictatorResolver(); + if (r != null) { + return r; } String resolverName = getResolverName(mrid); return getResolver(resolverName); @@ -892,23 +908,32 @@ public class IvySettings implements SortEngineSettings, PublishEngineSettings, P } public synchronized DependencyResolver getResolver(String resolverName) { - if (dictatorResolver != null) { - return dictatorResolver; + DependencyResolver r = getDictatorResolver(); + if (r != null) { + return r; } DependencyResolver resolver = resolversMap.get(resolverName); if (resolver == null) { Message.error("unknown resolver " + resolverName); } + if (workspaceResolver != null && !(resolver instanceof WorkspaceChainResolver)) { + resolver = new WorkspaceChainResolver(this, resolver, workspaceResolver); + resolversMap.put(resolverName, resolver); + } return resolver; } public synchronized DependencyResolver getDefaultResolver() { - if (dictatorResolver != null) { - return dictatorResolver; + DependencyResolver r = getDictatorResolver(); + if (r != null) { + return r; } if (defaultResolver == null) { defaultResolver = resolversMap.get(defaultResolverName); } + if (workspaceResolver != null && !(defaultResolver instanceof WorkspaceChainResolver)) { + defaultResolver = new WorkspaceChainResolver(this, defaultResolver, workspaceResolver); + } return defaultResolver; } @@ -997,7 +1022,12 @@ public class IvySettings implements SortEngineSettings, PublishEngineSettings, P if ("default".equals(name)) { return getDefaultLatestStrategy(); } - return latestStrategies.get(name); + LatestStrategy strategy = latestStrategies.get(name); + if (workspaceResolver != null && !(strategy instanceof WorkspaceLatestStrategy)) { + strategy = new WorkspaceLatestStrategy(strategy); + latestStrategies.put(name, strategy); + } + return strategy; } public synchronized void addLatestStrategy(String name, LatestStrategy latest) { @@ -1224,6 +1254,10 @@ public class IvySettings implements SortEngineSettings, PublishEngineSettings, P if (defaultLatestStrategy == null) { defaultLatestStrategy = new LatestRevisionStrategy(); } + if (workspaceResolver != null + && !(defaultLatestStrategy instanceof WorkspaceLatestStrategy)) { + defaultLatestStrategy = new WorkspaceLatestStrategy(defaultLatestStrategy); + } return defaultLatestStrategy; } @@ -1500,4 +1534,20 @@ public class IvySettings implements SortEngineSettings, PublishEngineSettings, P public PackingRegistry getPackingRegistry() { return packingRegistry; } + + public void addConfigured(AbstractWorkspaceResolver workspaceResolver) { + this.workspaceResolver = workspaceResolver; + if (workspaceResolver != null) { + workspaceResolver.setSettings(this); + DefaultRepositoryCacheManager cacheManager = new DefaultRepositoryCacheManager(); + String cacheName = "workspace-resolver-cache-" + workspaceResolver.getName(); + cacheManager.setBasedir(new File(getDefaultCache(), cacheName)); + cacheManager.setCheckmodified(true); + cacheManager.setUseOrigin(true); + cacheManager.setName(cacheName); + addRepositoryCacheManager(cacheManager); + workspaceResolver.setCache(cacheName); + } + + } } http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/f6322b7f/src/java/org/apache/ivy/plugins/latest/WorkspaceLatestStrategy.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/ivy/plugins/latest/WorkspaceLatestStrategy.java b/src/java/org/apache/ivy/plugins/latest/WorkspaceLatestStrategy.java new file mode 100644 index 0000000..64ef7ec --- /dev/null +++ b/src/java/org/apache/ivy/plugins/latest/WorkspaceLatestStrategy.java @@ -0,0 +1,57 @@ +/* + * 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.plugins.latest; + +import java.util.ArrayList; +import java.util.List; + +/** + * A strategy which delegate to another strategy, unless for the latest and working revisions which + * are considered as superior to any other revision. < br/> + * NB : it is for internal usage of Ivy only! + */ +public class WorkspaceLatestStrategy extends AbstractLatestStrategy { + + private LatestStrategy delegate; + + public WorkspaceLatestStrategy(LatestStrategy delegate) { + this.delegate = delegate; + setName("workspace-" + delegate.getName()); + } + + public List<ArtifactInfo> sort(ArtifactInfo[] infos) { + List<ArtifactInfo> sorted = delegate.sort(infos); + + List<ArtifactInfo> head = new ArrayList<ArtifactInfo>(); + List<ArtifactInfo> tail = new ArrayList<ArtifactInfo>(); + + for (ArtifactInfo ai : sorted) { + String rev = ai.getRevision(); + boolean latestRev = rev.startsWith("latest") || rev.startsWith("working"); + if (latestRev) { + head.add(ai); + } else { + tail.add(ai); + } + } + + head.addAll(tail); + return head; + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/f6322b7f/src/java/org/apache/ivy/plugins/resolver/AbstractWorkspaceResolver.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/ivy/plugins/resolver/AbstractWorkspaceResolver.java b/src/java/org/apache/ivy/plugins/resolver/AbstractWorkspaceResolver.java new file mode 100644 index 0000000..5444ab0 --- /dev/null +++ b/src/java/org/apache/ivy/plugins/resolver/AbstractWorkspaceResolver.java @@ -0,0 +1,239 @@ +/* + * 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.plugins.resolver; + +import java.io.File; +import java.io.IOException; +import java.text.ParseException; +import java.util.List; + +import org.apache.ivy.Ivy; +import org.apache.ivy.core.module.descriptor.Artifact; +import org.apache.ivy.core.module.descriptor.Configuration; +import org.apache.ivy.core.module.descriptor.DefaultArtifact; +import org.apache.ivy.core.module.descriptor.DefaultWorkspaceModuleDescriptor; +import org.apache.ivy.core.module.descriptor.DependencyDescriptor; +import org.apache.ivy.core.module.descriptor.ExcludeRule; +import org.apache.ivy.core.module.descriptor.License; +import org.apache.ivy.core.module.descriptor.ModuleDescriptor; +import org.apache.ivy.core.module.descriptor.WorkspaceModuleDescriptor; +import org.apache.ivy.core.module.id.ModuleId; +import org.apache.ivy.core.module.id.ModuleRevisionId; +import org.apache.ivy.core.report.DownloadStatus; +import org.apache.ivy.core.report.MetadataArtifactDownloadReport; +import org.apache.ivy.core.resolve.ResolveData; +import org.apache.ivy.core.resolve.ResolvedModuleRevision; +import org.apache.ivy.osgi.core.BundleInfo; +import org.apache.ivy.osgi.core.ManifestHeaderElement; +import org.apache.ivy.osgi.core.ManifestHeaderValue; +import org.apache.ivy.plugins.resolver.util.ResolvedResource; +import org.apache.ivy.plugins.version.VersionMatcher; +import org.apache.ivy.util.Message; + +public abstract class AbstractWorkspaceResolver extends AbstractResolver { + + private boolean ignoreBranch; + + private boolean ignoreVersion; + + public void setIgnoreBranch(boolean ignoreBranch) { + this.ignoreBranch = ignoreBranch; + } + + public void setIgnoreVersion(boolean ignoreVersion) { + this.ignoreVersion = ignoreVersion; + } + + protected ResolvedModuleRevision checkCandidate(DependencyDescriptor dd, ModuleDescriptor md, + String workspaceModuleName) { + + if (workspaceModuleName == null) { + workspaceModuleName = dd.getDependencyId().toString(); + } + + ModuleRevisionId dependencyMrid = dd.getDependencyRevisionId(); + String org = dependencyMrid.getModuleId().getOrganisation(); + String module = dependencyMrid.getModuleId().getName(); + + VersionMatcher versionMatcher = getSettings().getVersionMatcher(); + + ModuleRevisionId candidateMrid = md.getModuleRevisionId(); + + // search a match on the organization and the module name + + if (org.equals(BundleInfo.BUNDLE_TYPE)) { + // looking for an OSGi bundle via its symbolic name + String sn = md.getExtraInfoContentByTagName("Bundle-SymbolicName"); + if (sn == null || !module.equals(sn)) { + // not found, skip to next + return null; + } + } else if (org.equals(BundleInfo.PACKAGE_TYPE)) { + // looking for an OSGi bundle via its exported package + String exportedPackages = md.getExtraInfoContentByTagName("Export-Package"); + if (exportedPackages == null) { + // not found, skip to next + return null; + } + boolean found = false; + String version = null; + ManifestHeaderValue exportElements; + try { + exportElements = new ManifestHeaderValue(exportedPackages); + } catch (ParseException e) { + // wrong OSGi header: skip it + return null; + } + for (ManifestHeaderElement exportElement : exportElements.getElements()) { + if (exportElement.getValues().contains(module)) { + found = true; + version = exportElement.getAttributes().get("version"); + break; + } + } + if (!found) { + // not found, skip to next + return null; + } + if (version == null) { + // no version means anything can match. Let's trick the version matcher by + // setting the exact expected version + version = dependencyMrid.getRevision(); + } + md.setResolvedModuleRevisionId(ModuleRevisionId.newInstance(org, module, version)); + } else { + if (!candidateMrid.getModuleId().equals(dependencyMrid.getModuleId())) { + // it doesn't match org#module, skip to next + return null; + } + } + + Message.verbose("Workspace resolver found potential matching workspace module " + + workspaceModuleName + " with module " + candidateMrid + " for module " + + dependencyMrid); + + if (!ignoreBranch) { + ModuleId mid = dependencyMrid.getModuleId(); + String defaultBranch = getSettings().getDefaultBranch(mid); + String dependencyBranch = dependencyMrid.getBranch(); + String candidateBranch = candidateMrid.getBranch(); + if (dependencyBranch == null) { + dependencyBranch = defaultBranch; + } + if (candidateBranch == null) { + candidateBranch = defaultBranch; + } + if (dependencyBranch != candidateBranch) { + // Both cannot be null + if (dependencyBranch == null || candidateBranch == null) { + Message.verbose("\t\trejected since branches doesn't match (one is set, the other isn't)"); + return null; + } + if (!dependencyBranch.equals(candidateBranch)) { + Message.verbose("\t\trejected since branches doesn't match"); + return null; + } + } + } + + // Found one; check if it is for the module we need + if (!ignoreVersion + && !md.getModuleRevisionId().getRevision().equals(Ivy.getWorkingRevision()) + && !versionMatcher.accept(dd.getDependencyRevisionId(), md)) { + Message.verbose("\t\treject as version didn't match"); + return null; + } + + if (ignoreVersion) { + Message.verbose("\t\tmatched (version are ignored)"); + } else { + Message.verbose("\t\tversion matched"); + } + + WorkspaceModuleDescriptor workspaceMd = createWorkspaceMd(md); + + Artifact mdaf = md.getMetadataArtifact(); + if (mdaf == null) { + mdaf = new DefaultArtifact(md.getModuleRevisionId(), md.getPublicationDate(), + workspaceModuleName, "ivy", ""); + } + MetadataArtifactDownloadReport madr = new MetadataArtifactDownloadReport(mdaf); + madr.setDownloadStatus(DownloadStatus.SUCCESSFUL); + madr.setSearched(true); + + return new ResolvedModuleRevision(this, this, workspaceMd, madr); + } + + protected WorkspaceModuleDescriptor createWorkspaceMd(ModuleDescriptor md) { + DefaultWorkspaceModuleDescriptor newMd = new DefaultWorkspaceModuleDescriptor( + md.getModuleRevisionId(), "release", null, true); + newMd.addConfiguration(new Configuration(ModuleDescriptor.DEFAULT_CONFIGURATION)); + newMd.setLastModified(System.currentTimeMillis()); + + newMd.setDescription(md.getDescription()); + newMd.setHomePage(md.getHomePage()); + newMd.setLastModified(md.getLastModified()); + newMd.setPublicationDate(md.getPublicationDate()); + newMd.setResolvedPublicationDate(md.getResolvedPublicationDate()); + newMd.setStatus(md.getStatus()); + + List<Artifact> artifacts = createWorkspaceArtifacts(md); + + Configuration[] allConfs = md.getConfigurations(); + for (Artifact af : artifacts) { + if (allConfs.length == 0) { + newMd.addArtifact(ModuleDescriptor.DEFAULT_CONFIGURATION, af); + } else { + for (int k = 0; k < allConfs.length; k++) { + newMd.addConfiguration(allConfs[k]); + newMd.addArtifact(allConfs[k].getName(), af); + } + } + } + + DependencyDescriptor[] dependencies = md.getDependencies(); + for (int k = 0; k < dependencies.length; k++) { + newMd.addDependency(dependencies[k]); + } + + ExcludeRule[] allExcludeRules = md.getAllExcludeRules(); + for (int k = 0; k < allExcludeRules.length; k++) { + newMd.addExcludeRule(allExcludeRules[k]); + } + + newMd.getExtraInfos().addAll(md.getExtraInfos()); + + License[] licenses = md.getLicenses(); + for (int k = 0; k < licenses.length; k++) { + newMd.addLicense(licenses[k]); + } + + return newMd; + } + + abstract protected List<Artifact> createWorkspaceArtifacts(ModuleDescriptor md); + + public void publish(Artifact artifact, File src, boolean overwrite) throws IOException { + throw new UnsupportedOperationException("publish not supported by " + getName()); + } + + public ResolvedResource findIvyFileRef(DependencyDescriptor dd, ResolveData data) { + return null; + } + +} http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/f6322b7f/src/java/org/apache/ivy/plugins/resolver/WorkspaceChainResolver.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/ivy/plugins/resolver/WorkspaceChainResolver.java b/src/java/org/apache/ivy/plugins/resolver/WorkspaceChainResolver.java new file mode 100644 index 0000000..a3662cf --- /dev/null +++ b/src/java/org/apache/ivy/plugins/resolver/WorkspaceChainResolver.java @@ -0,0 +1,37 @@ +/* + * 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.plugins.resolver; + +import org.apache.ivy.core.settings.IvySettings; + +/** + * Resolver which decorate normal resolver so that the workspace resolver can hijack the resolve + * process <br /> + * NB : it is for internal usage of Ivy only! + */ +public class WorkspaceChainResolver extends ChainResolver { + + public WorkspaceChainResolver(IvySettings settings, DependencyResolver delegate, + AbstractWorkspaceResolver workspaceResolver) { + setName("workspace-chain-" + delegate.getName()); + setSettings(settings); + setReturnFirst(true); + add(workspaceResolver); + add(delegate); + } +} http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/f6322b7f/test/java/org/apache/ivy/ant/AntBuildResolverTest.java ---------------------------------------------------------------------- diff --git a/test/java/org/apache/ivy/ant/AntBuildResolverTest.java b/test/java/org/apache/ivy/ant/AntBuildResolverTest.java new file mode 100644 index 0000000..6eb3c79 --- /dev/null +++ b/test/java/org/apache/ivy/ant/AntBuildResolverTest.java @@ -0,0 +1,213 @@ +/* + * 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.ant; + +import java.io.File; + +import junit.framework.TestCase; + +import org.apache.ivy.ant.AntWorkspaceResolver.WorkspaceArtifact; +import org.apache.ivy.core.module.id.ModuleRevisionId; +import org.apache.ivy.core.report.DownloadStatus; +import org.apache.ivy.core.report.ResolveReport; +import org.apache.tools.ant.DefaultLogger; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.taskdefs.Delete; +import org.apache.tools.ant.types.FileSet; +import org.apache.tools.ant.types.Path; + +public class AntBuildResolverTest extends TestCase { + + private static final ModuleRevisionId MRID_MODULE1 = ModuleRevisionId.newInstance("org.acme", + "module1", "1.1"); + + private static final ModuleRevisionId MRID_PROJECT1 = ModuleRevisionId.newInstance( + "org.apache.ivy.test", "project1", "0.1"); + + private File cache; + + private Project project; + + private IvyConfigure configure; + + private WorkspaceArtifact wa; + + @Override + protected void setUp() throws Exception { + createCache(); + project = new Project(); + DefaultLogger logger = new DefaultLogger(); + logger.setMessageOutputLevel(Project.MSG_INFO); + logger.setOutputPrintStream(System.out); + logger.setErrorPrintStream(System.err); + project.addBuildListener(logger); + project.setProperty("ivy.cache.dir", cache.getAbsolutePath()); + + AntWorkspaceResolver antWorkspaceResolver = new AntWorkspaceResolver(); + antWorkspaceResolver.setName("test-workspace"); + wa = antWorkspaceResolver.createArtifact(); + FileSet fileset = new FileSet(); + fileset.setProject(project); + fileset.setDir(new File("test/workspace")); + fileset.setIncludes("*/ivy.xml"); + antWorkspaceResolver.addResourceCollection(fileset); + antWorkspaceResolver.setProject(project); + + configure = new IvyConfigure(); + configure.setProject(project); + configure.setFile(new File("test/workspace/ivysettings.xml")); + configure.addConfiguredWorkspaceResolver(antWorkspaceResolver); + configure.execute(); + } + + private void createCache() { + cache = new File("build/cache"); + cache.mkdirs(); + } + + @Override + protected void tearDown() throws Exception { + cleanCache(); + } + + private void cleanCache() { + Delete del = new Delete(); + del.setProject(new Project()); + del.setDir(cache); + del.execute(); + } + + public void testNoProject() throws Exception { + IvyResolve resolve = new IvyResolve(); + resolve.setProject(project); + resolve.setFile(new File("test/workspace/project1/ivy.xml")); + resolve.setKeep(true); + resolve.execute(); + + ResolveReport report = (ResolveReport) project.getReference("ivy.resolved.report"); + assertEquals(1, report.getDependencies().size()); + assertEquals(MRID_MODULE1, report.getDependencies().get(0).getResolvedId()); + } + + public void testProject() throws Exception { + IvyResolve resolve = new IvyResolve(); + resolve.setProject(project); + resolve.setFile(new File("test/workspace/project2/ivy.xml")); + resolve.setKeep(true); + resolve.execute(); + + ResolveReport report = (ResolveReport) project.getReference("ivy.resolved.report"); + assertEquals(2, report.getDependencies().size()); + assertEquals(MRID_PROJECT1, report.getDependencies().get(0).getResolvedId()); + assertEquals(MRID_MODULE1, report.getDependencies().get(1).getResolvedId()); + assertEquals(1, report.getArtifactsReports(MRID_PROJECT1).length); + assertEquals(DownloadStatus.NO, + report.getArtifactsReports(MRID_PROJECT1)[0].getDownloadStatus()); + assertEquals(new File("test/workspace/project1/target/dist/jars/project1.jar").toURI() + .toURL(), report.getArtifactsReports(MRID_PROJECT1)[0].getArtifact().getUrl()); + assertEquals( + new File("test/workspace/project1/target/dist/jars/project1.jar").getAbsoluteFile(), + report.getArtifactsReports(MRID_PROJECT1)[0].getLocalFile()); + } + + public void testProjectFolder() throws Exception { + wa.setPath("target/classes"); + + IvyResolve resolve = new IvyResolve(); + resolve.setProject(project); + resolve.setFile(new File("test/workspace/project2/ivy.xml")); + resolve.setKeep(true); + resolve.execute(); + + ResolveReport report = (ResolveReport) project.getReference("ivy.resolved.report"); + assertEquals(2, report.getDependencies().size()); + assertEquals(MRID_PROJECT1, report.getDependencies().get(0).getResolvedId()); + assertEquals(MRID_MODULE1, report.getDependencies().get(1).getResolvedId()); + assertEquals(1, report.getArtifactsReports(MRID_PROJECT1).length); + assertEquals(DownloadStatus.NO, + report.getArtifactsReports(MRID_PROJECT1)[0].getDownloadStatus()); + assertEquals(new File("test/workspace/project1/target/classes").toURI().toURL(), + report.getArtifactsReports(MRID_PROJECT1)[0].getArtifact().getUrl()); + assertEquals(new File("test/workspace/project1/target/classes").getAbsoluteFile(), + report.getArtifactsReports(MRID_PROJECT1)[0].getLocalFile()); + } + + public void testDependencyArtifact() throws Exception { + IvyResolve resolve = new IvyResolve(); + resolve.setProject(project); + resolve.setFile(new File("test/workspace/project3/ivy.xml")); + resolve.setKeep(true); + resolve.execute(); + + ResolveReport report = (ResolveReport) project.getReference("ivy.resolved.report"); + assertEquals(2, report.getDependencies().size()); + assertEquals(MRID_PROJECT1, report.getDependencies().get(0).getResolvedId()); + assertEquals(MRID_MODULE1, report.getDependencies().get(1).getResolvedId()); + assertEquals(1, report.getArtifactsReports(MRID_PROJECT1).length); + assertEquals(DownloadStatus.NO, + report.getArtifactsReports(MRID_PROJECT1)[0].getDownloadStatus()); + assertEquals(new File("test/workspace/project1/target/dist/jars/project1.jar").toURI() + .toURL(), report.getArtifactsReports(MRID_PROJECT1)[0].getArtifact().getUrl()); + assertEquals( + new File("test/workspace/project1/target/dist/jars/project1.jar").getAbsoluteFile(), + report.getArtifactsReports(MRID_PROJECT1)[0].getLocalFile()); + } + + public void testCachePath() throws Exception { + IvyResolve resolve = new IvyResolve(); + resolve.setProject(project); + resolve.setFile(new File("test/workspace/project2/ivy.xml")); + resolve.setKeep(true); + resolve.execute(); + + IvyCachePath cachePath = new IvyCachePath(); + cachePath.setProject(project); + cachePath.setPathid("test.cachepath.id"); + cachePath.execute(); + + Path path = (Path) project.getReference("test.cachepath.id"); + assertEquals(2, path.size()); + assertEquals( + new File("test/workspace/project1/target/dist/jars/project1.jar").getAbsolutePath(), + path.list()[0]); + assertEquals(new File(cache, "org.acme/module1/jars/module1-1.1.jar").getAbsolutePath(), + path.list()[1]); + } + + public void testCachePathFolder() throws Exception { + wa.setPath("target/classes"); + + IvyResolve resolve = new IvyResolve(); + resolve.setProject(project); + resolve.setFile(new File("test/workspace/project2/ivy.xml")); + resolve.setKeep(true); + resolve.execute(); + + IvyCachePath cachePath = new IvyCachePath(); + cachePath.setProject(project); + cachePath.setPathid("test.cachepath.id"); + cachePath.execute(); + + Path path = (Path) project.getReference("test.cachepath.id"); + assertEquals(2, path.size()); + assertEquals(new File("test/workspace/project1/target/classes").getAbsolutePath(), + path.list()[0]); + assertEquals(new File(cache, "org.acme/module1/jars/module1-1.1.jar").getAbsolutePath(), + path.list()[1]); + } +} http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/f6322b7f/test/workspace/ivysettings.xml ---------------------------------------------------------------------- diff --git a/test/workspace/ivysettings.xml b/test/workspace/ivysettings.xml new file mode 100644 index 0000000..26ebeaa --- /dev/null +++ b/test/workspace/ivysettings.xml @@ -0,0 +1,30 @@ +<!-- + 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. +--> +<ivysettings> + + <settings defaultResolver="repo" /> + + <resolvers> + <filesystem name="repo"> + <ivy pattern="${ivy.settings.dir}/repo/[organisation]/[module]/[revision]/[artifact].[ext]" /> + <artifact pattern="${ivy.settings.dir}/repo/[organisation]/[module]/[revision]/[artifact].[ext]" /> + </filesystem> + </resolvers> + +</ivysettings> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/f6322b7f/test/workspace/project1/ivy.xml ---------------------------------------------------------------------- diff --git a/test/workspace/project1/ivy.xml b/test/workspace/project1/ivy.xml new file mode 100644 index 0000000..bc8cc54 --- /dev/null +++ b/test/workspace/project1/ivy.xml @@ -0,0 +1,24 @@ +<!-- + 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="2.0"> + <info organisation="org.apache.ivy.test" module="project1" revision="0.1" /> + <dependencies> + <dependency org="org.acme" name="module1" rev="1.1" /> + </dependencies> +</ivy-module> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/f6322b7f/test/workspace/project2/ivy.xml ---------------------------------------------------------------------- diff --git a/test/workspace/project2/ivy.xml b/test/workspace/project2/ivy.xml new file mode 100644 index 0000000..d995e6d --- /dev/null +++ b/test/workspace/project2/ivy.xml @@ -0,0 +1,24 @@ +<!-- + 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="2.0"> + <info organisation="org.apache.ivy.test" module="project2" /> + <dependencies> + <dependency org="org.apache.ivy.test" name="project1" rev="latest.integration" /> + </dependencies> +</ivy-module> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/f6322b7f/test/workspace/project3/ivy.xml ---------------------------------------------------------------------- diff --git a/test/workspace/project3/ivy.xml b/test/workspace/project3/ivy.xml new file mode 100644 index 0000000..82441dd --- /dev/null +++ b/test/workspace/project3/ivy.xml @@ -0,0 +1,26 @@ +<!-- + 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="2.0"> + <info organisation="org.apache.ivy.test" module="project3" /> + <dependencies> + <dependency org="org.apache.ivy.test" name="project1" rev="latest.integration"> + <artifact name="test" type="jar" ext="jar" /> + </dependency> + </dependencies> +</ivy-module> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/f6322b7f/test/workspace/repo/org.acme/module1/1.1/ivy.xml ---------------------------------------------------------------------- diff --git a/test/workspace/repo/org.acme/module1/1.1/ivy.xml b/test/workspace/repo/org.acme/module1/1.1/ivy.xml new file mode 100644 index 0000000..754cc1f --- /dev/null +++ b/test/workspace/repo/org.acme/module1/1.1/ivy.xml @@ -0,0 +1,21 @@ +<!-- + 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="2.0"> + <info organisation="org.acme" module="module1" revision="1.1" /> +</ivy-module> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/f6322b7f/test/workspace/repo/org.acme/module1/1.1/module1.jar ---------------------------------------------------------------------- diff --git a/test/workspace/repo/org.acme/module1/1.1/module1.jar b/test/workspace/repo/org.acme/module1/1.1/module1.jar new file mode 100644 index 0000000..e69de29 http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/f6322b7f/test/workspace/repo/org.acme/module2/1.2/ivy.xml ---------------------------------------------------------------------- diff --git a/test/workspace/repo/org.acme/module2/1.2/ivy.xml b/test/workspace/repo/org.acme/module2/1.2/ivy.xml new file mode 100644 index 0000000..990acfb --- /dev/null +++ b/test/workspace/repo/org.acme/module2/1.2/ivy.xml @@ -0,0 +1,21 @@ +<!-- + 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="2.0"> + <info organisation="org.acme" module="module2" revision="1.2" /> +</ivy-module> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ant-ivy/blob/f6322b7f/test/workspace/repo/org.acme/module2/1.2/module2.jar ---------------------------------------------------------------------- diff --git a/test/workspace/repo/org.acme/module2/1.2/module2.jar b/test/workspace/repo/org.acme/module2/1.2/module2.jar new file mode 100644 index 0000000..e69de29