2020 */
2121
2222import java .io .File ;
23+ import java .io .IOException ;
24+ import java .util .Collections ;
2325import java .util .List ;
2426import java .util .Map ;
2527import java .util .regex .Matcher ;
3638import org .apache .maven .project .MavenProject ;
3739import org .apache .maven .project .artifact .ProjectArtifact ;
3840import 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 ;
3947import org .eclipse .aether .deployment .DeployRequest ;
4048import 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 ;
4152import 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 */
0 commit comments