Skip to content

Commit 32c4acd

Browse files
Mathias de Riesemdrie
authored andcommitted
MDEPLOY-118: Add parameter comparePomWithDeployed to deploy goal.
1 parent dbf3a07 commit 32c4acd

File tree

2 files changed

+226
-5
lines changed

2 files changed

+226
-5
lines changed

src/main/java/org/apache/maven/plugins/deploy/DeployMojo.java

Lines changed: 122 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
*/
2121

2222
import java.io.File;
23+
import java.io.IOException;
24+
import java.util.Collections;
2325
import java.util.List;
2426
import java.util.Map;
2527
import java.util.regex.Matcher;
@@ -36,13 +38,22 @@
3638
import org.apache.maven.project.MavenProject;
3739
import org.apache.maven.project.artifact.ProjectArtifact;
3840
import org.apache.maven.project.artifact.ProjectArtifactMetadata;
41+
import org.codehaus.plexus.util.ReaderFactory;
42+
import org.codehaus.plexus.util.xml.Xpp3Dom;
43+
import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
44+
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
45+
import org.eclipse.aether.artifact.Artifact;
46+
import org.eclipse.aether.artifact.DefaultArtifact;
3947
import org.eclipse.aether.deployment.DeployRequest;
4048
import org.eclipse.aether.repository.RemoteRepository;
49+
import org.eclipse.aether.resolution.ArtifactRequest;
50+
import org.eclipse.aether.resolution.ArtifactResolutionException;
51+
import org.eclipse.aether.resolution.ArtifactResult;
4152
import org.eclipse.aether.util.artifact.SubArtifact;
4253

4354
/**
4455
* Deploys an artifact to remote repository.
45-
*
56+
*
4657
* @author <a href="mailto:[email protected]">Emmanuel Venisse</a>
4758
* @author <a href="mailto:[email protected]">John Casey (refactoring only)</a>
4859
*/
@@ -67,7 +78,7 @@ public class DeployMojo
6778
* Whether every project should be deployed during its own deploy-phase or at the end of the multimodule build. If
6879
* set to {@code true} and the build fails, none of the reactor projects is deployed.
6980
* <strong>(experimental)</strong>
70-
*
81+
*
7182
* @since 2.8
7283
*/
7384
@Parameter( defaultValue = "false", property = "deployAtEnd" )
@@ -128,6 +139,13 @@ public class DeployMojo
128139
@Parameter( property = "maven.deploy.skip", defaultValue = "false" )
129140
private String skip = Boolean.FALSE.toString();
130141

142+
/**
143+
*
144+
* @since 3.0.1
145+
*/
146+
@Parameter( property = "comparePomWithDeployed", defaultValue = "false" )
147+
private boolean comparePomWithDeployed;
148+
131149
private enum State
132150
{
133151
SKIPPED, DEPLOYED, TO_BE_DEPLOYED
@@ -173,6 +191,7 @@ private boolean hasState( MavenProject project )
173191
return pluginContext.containsKey( DEPLOY_PROCESSED_MARKER );
174192
}
175193

194+
@Override
176195
public void execute()
177196
throws MojoExecutionException, MojoFailureException
178197
{
@@ -261,7 +280,8 @@ private DeployRequest processProject( final MavenProject project,
261280

262281
if ( pomFile != null )
263282
{
264-
request.addArtifact( RepositoryUtils.toArtifact( new ProjectArtifact( project ) ) );
283+
Artifact pomArtifact = RepositoryUtils.toArtifact( new ProjectArtifact( project ) );
284+
new DeployedPomChecker( pomArtifact, request ).addPomConditionally();
265285
pomArtifactAttached = true;
266286
}
267287

@@ -279,11 +299,12 @@ private DeployRequest processProject( final MavenProject project,
279299
{
280300
if ( metadata instanceof ProjectArtifactMetadata )
281301
{
282-
request.addArtifact( new SubArtifact(
302+
Artifact pomArtifact = new SubArtifact(
283303
mainArtifact,
284304
"",
285305
"pom"
286-
).setFile( ( (ProjectArtifactMetadata) metadata ).getFile() ) );
306+
).setFile( ( (ProjectArtifactMetadata) metadata ).getFile() );
307+
new DeployedPomChecker( pomArtifact, request ).addPomConditionally();
287308
pomArtifactAttached = true;
288309
}
289310
}
@@ -315,6 +336,102 @@ else if ( !project.getAttachedArtifacts().isEmpty() )
315336
return request;
316337
}
317338

339+
private class DeployedPomChecker
340+
{
341+
final Artifact pomArtifact;
342+
final DeployRequest request;
343+
final RemoteRepository repo;
344+
345+
DeployedPomChecker( Artifact pomArtifact, DeployRequest request )
346+
{
347+
this.pomArtifact = pomArtifact;
348+
this.request = request;
349+
this.repo = request.getRepository();
350+
}
351+
352+
public void addPomConditionally ()
353+
throws MojoExecutionException, MojoFailureException
354+
{
355+
if ( comparePomWithDeployed )
356+
{
357+
try
358+
{
359+
if ( deployedPomIsEqual() )
360+
{
361+
return;
362+
}
363+
}
364+
catch ( IOException | XmlPullParserException e )
365+
{
366+
throw new MojoExecutionException( "Failed to compare POM with a version "
367+
+ "previously deployed to the repository: " + e.getMessage(), e );
368+
}
369+
}
370+
371+
request.addArtifact( pomArtifact );
372+
}
373+
374+
private boolean deployedPomIsEqual()
375+
throws IOException, XmlPullParserException, MojoFailureException
376+
{
377+
Xpp3Dom deployedPomDom = retrieveDeployedPom();
378+
if ( deployedPomDom == null )
379+
{
380+
return false;
381+
}
382+
383+
File pomFile = pomArtifact.getFile();
384+
Xpp3Dom newPomDom = Xpp3DomBuilder.build( ReaderFactory.newXmlReader( pomFile ) );
385+
386+
if ( newPomDom.equals( deployedPomDom ) )
387+
{
388+
getLog().info( "Not deploying POM, since deployed POM is equal to current POM." );
389+
return true;
390+
}
391+
else
392+
{
393+
String artifactId = RepositoryUtils.toArtifact( pomArtifact ).getId();
394+
String gav = pomArtifact.getGroupId() + ":" + pomArtifact.getArtifactId()
395+
+ ":" + pomArtifact.getVersion();
396+
397+
String shortMsg = "Project version " + gav + " already deployed with a differing POM.";
398+
getLog().error( shortMsg );
399+
400+
throw new MojoFailureException( artifactId,
401+
shortMsg,
402+
"Project version " + gav + " already deployed and the POM '" + artifactId + "' "
403+
+ "deployed in repository '" + repo.getUrl() + "' "
404+
+ "differs from the POM that would be deployed. No artifacts will be deployed." );
405+
}
406+
}
407+
408+
private Xpp3Dom retrieveDeployedPom ()
409+
throws IOException, XmlPullParserException
410+
{
411+
Artifact lookupArtifact =
412+
new DefaultArtifact( pomArtifact.getGroupId(), pomArtifact.getArtifactId(),
413+
pomArtifact.getClassifier(), pomArtifact.getExtension(),
414+
pomArtifact.getVersion(), pomArtifact.getProperties(),
415+
(File) null );
416+
List<RemoteRepository> repos = Collections.singletonList( repo );
417+
418+
ArtifactRequest request = new ArtifactRequest( lookupArtifact, repos, null );
419+
420+
try ( TempLocalRepoSession tempRepoSession =
421+
TempLocalRepoSession.create( session.getRepositorySession(), repositorySystem ) )
422+
{
423+
ArtifactResult result = repositorySystem.resolveArtifact( tempRepoSession, request );
424+
425+
File deployedPom = result.getArtifact().getFile();
426+
return Xpp3DomBuilder.build( ReaderFactory.newXmlReader( deployedPom ) );
427+
}
428+
catch ( ArtifactResolutionException ex )
429+
{
430+
return null;
431+
}
432+
}
433+
}
434+
318435
/**
319436
* Visible for testing.
320437
*/
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package org.apache.maven.plugins.deploy;
2+
3+
/*
4+
* Licensed to the Apache Software Foundation (ASF) under one
5+
* or more contributor license agreements. See the NOTICE file
6+
* distributed with this work for additional information
7+
* regarding copyright ownership. The ASF licenses this file
8+
* to you under the Apache License, Version 2.0 (the
9+
* "License"); you may not use this file except in compliance
10+
* with the License. You may obtain a copy of the License at
11+
*
12+
* http://www.apache.org/licenses/LICENSE-2.0
13+
*
14+
* Unless required by applicable law or agreed to in writing,
15+
* software distributed under the License is distributed on an
16+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17+
* KIND, either express or implied. See the License for the
18+
* specific language governing permissions and limitations
19+
* under the License.
20+
*/
21+
22+
import java.io.Closeable;
23+
import java.io.File;
24+
import java.io.IOException;
25+
import java.nio.file.Files;
26+
import java.nio.file.Path;
27+
import org.codehaus.plexus.util.FileUtils;
28+
import org.eclipse.aether.AbstractForwardingRepositorySystemSession;
29+
import org.eclipse.aether.DefaultRepositoryCache;
30+
import org.eclipse.aether.RepositoryCache;
31+
import org.eclipse.aether.RepositorySystem;
32+
import org.eclipse.aether.RepositorySystemSession;
33+
import org.eclipse.aether.repository.LocalRepository;
34+
import org.eclipse.aether.repository.LocalRepositoryManager;
35+
import org.eclipse.aether.repository.WorkspaceReader;
36+
37+
/**
38+
*
39+
*/
40+
class TempLocalRepoSession extends AbstractForwardingRepositorySystemSession implements Closeable
41+
{
42+
private final RepositorySystemSession origSession;
43+
private final RepositoryCache cache;
44+
private final File tempBasedir;
45+
private LocalRepositoryManager lrm;
46+
47+
private TempLocalRepoSession( RepositorySystemSession origSession, File tempBasedir )
48+
{
49+
this.origSession = origSession;
50+
this.cache = new DefaultRepositoryCache();
51+
this.tempBasedir = tempBasedir;
52+
this.lrm = null;
53+
}
54+
55+
public static TempLocalRepoSession create( RepositorySystemSession origSession, RepositorySystem repoSystem )
56+
throws IOException
57+
{
58+
// Place a temporary local repository next to the regular one, as done on the maven-assembly-plugin.
59+
File origBasedir = origSession.getLocalRepository().getBasedir();
60+
Path parentDir = origBasedir.getParentFile().toPath();
61+
File newBasedir = Files.createTempDirectory( parentDir, origBasedir.getName() ).toFile();
62+
63+
TempLocalRepoSession newSession = new TempLocalRepoSession( origSession, newBasedir );
64+
65+
String contentType = origSession.getLocalRepository().getContentType();
66+
String repositoryType = "enhanced".equals( contentType ) ? "default" : contentType;
67+
LocalRepository localRepository = new LocalRepository( newBasedir, repositoryType );
68+
69+
newSession.lrm = repoSystem.newLocalRepositoryManager( newSession, localRepository );
70+
71+
return newSession;
72+
}
73+
74+
@Override
75+
protected RepositorySystemSession getSession()
76+
{
77+
return origSession;
78+
}
79+
80+
@Override
81+
public RepositoryCache getCache()
82+
{
83+
return cache;
84+
}
85+
86+
@Override
87+
public LocalRepositoryManager getLocalRepositoryManager()
88+
{
89+
return lrm;
90+
}
91+
92+
@Override
93+
public WorkspaceReader getWorkspaceReader()
94+
{
95+
return null;
96+
}
97+
98+
@Override
99+
public void close()
100+
throws IOException
101+
{
102+
FileUtils.deleteDirectory( tempBasedir );
103+
}
104+
}

0 commit comments

Comments
 (0)