Index: test/java/org/apache/ivy/plugins/resolver/FileSystemResolverTest.java =================================================================== --- test/java/org/apache/ivy/plugins/resolver/FileSystemResolverTest.java (revision 538051) +++ test/java/org/apache/ivy/plugins/resolver/FileSystemResolverTest.java (working copy) @@ -494,8 +494,17 @@ Artifact ivyArtifact = new DefaultArtifact(mrid, new Date(), "ivy", "ivy", "xml"); Artifact artifact = new DefaultArtifact(mrid, new Date(), "myartifact", "mytype", "myext"); File src = new File("test/repositories/ivysettings.xml"); - resolver.publish(ivyArtifact, src, false); - resolver.publish(artifact, src, false); + boolean successfullyPublished = false; + resolver.beginPublishTransaction(mrid); + try { + resolver.publish(ivyArtifact, src, false); + resolver.publish(artifact, src, false); + resolver.commitPublishTransaction(); + successfullyPublished = true; + } finally { + if (!successfullyPublished) + resolver.commitPublishTransaction(); + } assertTrue(new File("test/repositories/1/myorg/mymodule/myrevision/ivy.xml").exists()); assertTrue(new File("test/repositories/1/myorg/mymodule/mytypes/myartifact-myrevision.myext").exists()); Index: src/java/org/apache/ivy/plugins/resolver/DependencyResolver.java =================================================================== --- src/java/org/apache/ivy/plugins/resolver/DependencyResolver.java (revision 538051) +++ src/java/org/apache/ivy/plugins/resolver/DependencyResolver.java (working copy) @@ -24,6 +24,7 @@ import org.apache.ivy.core.module.descriptor.Artifact; import org.apache.ivy.core.module.descriptor.DependencyDescriptor; +import org.apache.ivy.core.module.id.ModuleRevisionId; import org.apache.ivy.core.report.DownloadReport; import org.apache.ivy.core.resolve.DownloadOptions; import org.apache.ivy.core.resolve.ResolveData; @@ -57,6 +58,10 @@ boolean exists(Artifact artifact); void publish(Artifact artifact, File src, boolean overwrite) throws IOException; + void beginPublishTransaction(ModuleRevisionId module) throws IOException; + void abortPublishTransaction() throws IOException; + void commitPublishTransaction() throws IOException; + /** * Reports last resolve failure as Messages */ Index: src/java/org/apache/ivy/plugins/resolver/ChainResolver.java =================================================================== --- src/java/org/apache/ivy/plugins/resolver/ChainResolver.java (revision 538051) +++ src/java/org/apache/ivy/plugins/resolver/ChainResolver.java (working copy) @@ -28,6 +28,7 @@ import org.apache.ivy.core.module.descriptor.Artifact; import org.apache.ivy.core.module.descriptor.DependencyDescriptor; +import org.apache.ivy.core.module.id.ModuleRevisionId; import org.apache.ivy.core.report.ArtifactDownloadReport; import org.apache.ivy.core.report.DownloadReport; import org.apache.ivy.core.report.DownloadStatus; @@ -218,11 +219,16 @@ return _chain; } public void publish(Artifact artifact, File src, boolean overwrite) throws IOException { + + getFirstResolver().publish(artifact, src, overwrite); + } + + private DependencyResolver getFirstResolver() { if (_chain.isEmpty()) { throw new IllegalStateException("invalid chain resolver with no sub resolver"); } - ((DependencyResolver)_chain.get(0)).publish(artifact, src, overwrite); - } + return ((DependencyResolver)_chain.get(0)); + } public boolean isReturnFirst() { return _returnFirst; } @@ -283,4 +289,19 @@ return _dual; } + @Override + public void abortPublishTransaction() throws IOException { + getFirstResolver().abortPublishTransaction(); + } + + @Override + public void beginPublishTransaction(ModuleRevisionId module) throws IOException { + getFirstResolver().beginPublishTransaction(module); + } + + @Override + public void commitPublishTransaction() throws IOException { + getFirstResolver().commitPublishTransaction(); + } + } Index: src/java/org/apache/ivy/plugins/resolver/DualResolver.java =================================================================== --- src/java/org/apache/ivy/plugins/resolver/DualResolver.java (revision 538051) +++ src/java/org/apache/ivy/plugins/resolver/DualResolver.java (working copy) @@ -23,6 +23,7 @@ import org.apache.ivy.core.module.descriptor.Artifact; import org.apache.ivy.core.module.descriptor.DependencyDescriptor; +import org.apache.ivy.core.module.id.ModuleRevisionId; import org.apache.ivy.core.report.DownloadReport; import org.apache.ivy.core.resolve.DownloadOptions; import org.apache.ivy.core.resolve.ResolveData; @@ -136,4 +137,25 @@ public void setAllownomd(boolean allownomd) { _allownomd = allownomd; } + + + @Override + public void abortPublishTransaction() throws IOException { + _ivyResolver.abortPublishTransaction(); + _artifactResolver.abortPublishTransaction(); + } + + + @Override + public void beginPublishTransaction(ModuleRevisionId module) throws IOException { + _ivyResolver.beginPublishTransaction(module); + _artifactResolver.beginPublishTransaction(module); + } + + + @Override + public void commitPublishTransaction() throws IOException { + _ivyResolver.commitPublishTransaction(); + _artifactResolver.commitPublishTransaction(); + } } Index: src/java/org/apache/ivy/plugins/resolver/AbstractResolver.java =================================================================== --- src/java/org/apache/ivy/plugins/resolver/AbstractResolver.java (revision 538051) +++ src/java/org/apache/ivy/plugins/resolver/AbstractResolver.java (working copy) @@ -17,6 +17,7 @@ */ package org.apache.ivy.plugins.resolver; +import java.io.IOException; import java.util.Map; import org.apache.ivy.core.IvyContext; @@ -52,7 +53,19 @@ */ public abstract class AbstractResolver implements DependencyResolver, IvySettingsAware, HasLatestStrategy { - /** + public void abortPublishTransaction() throws IOException { + /* Default implementation is a no-op */ + } + + public void commitPublishTransaction() throws IOException { + /* Default implementation is a no-op */ + } + + public void beginPublishTransaction(ModuleRevisionId module) throws IOException { + /* Default implementation is a no-op */ + } + + /** * True if parsed ivy files should be validated against xsd, false if they should not, * null if default behaviour should be used */ Index: src/java/org/apache/ivy/core/publish/PublishEngine.java =================================================================== --- src/java/org/apache/ivy/core/publish/PublishEngine.java (revision 538051) +++ src/java/org/apache/ivy/core/publish/PublishEngine.java (working copy) @@ -169,34 +169,53 @@ artifactsSet.add(new MDArtifact(md, extraArtifacts[i].getName(), extraArtifacts[i].getType(), extraArtifacts[i].getExt(), extraArtifacts[i].getUrl(), extraArtifacts[i].getExtraAttributes())); } } - // for each declared published artifact in this descriptor, do: - for (Iterator iter = artifactsSet.iterator(); iter.hasNext();) { - Artifact artifact = (Artifact) iter.next(); - // 1) copy the artifact using src patterns and resolver - boolean published = false; - for (Iterator iterator = srcArtifactPattern.iterator(); iterator.hasNext() && !published;) { - String pattern = (String) iterator.next(); - published = publish(artifact, _settings.substitute(pattern), resolver, options.isOverwrite()); + boolean successfullyPublished = false; + try { + // for each declared published artifact in this descriptor, do: + for (Iterator iter = artifactsSet.iterator(); iter.hasNext();) { + Artifact artifact = (Artifact) iter.next(); + // 1) copy the artifact using src patterns and resolver + boolean published = false; + for (Iterator iterator = srcArtifactPattern.iterator(); iterator + .hasNext() + && !published;) { + String pattern = (String) iterator.next(); + published = publish(artifact, + _settings.substitute(pattern), resolver, options + .isOverwrite()); + } + if (!published) { + Message.info("missing artifact " + artifact + ":"); + for (Iterator iterator = srcArtifactPattern.iterator(); iterator + .hasNext();) { + String pattern = (String) iterator.next(); + Message.info("\t" + + new File(IvyPatternHelper.substitute(pattern, + artifact)) + " file does not exist"); + } + missing.add(artifact); + } } - if (!published) { - Message.info("missing artifact "+artifact+":"); - for (Iterator iterator = srcArtifactPattern.iterator(); iterator.hasNext();) { - String pattern = (String) iterator.next(); - Message.info("\t"+new File(IvyPatternHelper.substitute(pattern, artifact))+" file does not exist"); - } - missing.add(artifact); - } - } - if (options.getSrcIvyPattern() != null) { - Artifact artifact = MDArtifact.newIvyArtifact(md); - if (!publish(artifact, options.getSrcIvyPattern(), resolver, options.isOverwrite())) { - Message.info("missing ivy file for "+md.getModuleRevisionId()+": " - + new File(IvyPatternHelper.substitute(options.getSrcIvyPattern(), artifact)) - + " file does not exist"); - missing.add(artifact); - } - } - return missing; + if (options.getSrcIvyPattern() != null) { + Artifact artifact = MDArtifact.newIvyArtifact(md); + if (!publish(artifact, options.getSrcIvyPattern(), resolver, + options.isOverwrite())) { + Message.info("missing ivy file for " + + md.getModuleRevisionId() + + ": " + + new File(IvyPatternHelper.substitute(options + .getSrcIvyPattern(), artifact)) + + " file does not exist"); + missing.add(artifact); + } + } + resolver.commitPublishTransaction(); + successfullyPublished = true; + } finally { + if (!successfullyPublished) + resolver.abortPublishTransaction(); + } + return missing; } private boolean publish(Artifact artifact, String srcArtifactPattern, DependencyResolver resolver, boolean overwrite) throws IOException {