Skip to content

Commit

Permalink
[MARTIFACT-73] add describe-build-output experimental goal
Browse files Browse the repository at this point in the history
  • Loading branch information
hboutemy committed Oct 14, 2024
1 parent 4152759 commit 9372b9f
Show file tree
Hide file tree
Showing 3 changed files with 171 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,14 @@ protected void copyAggregateToRoot(File aggregate) throws MojoExecutionException
}
}

protected BuildInfoWriter newBuildInfoWriter(PrintWriter p, boolean mono) {
BuildInfoWriter bi = new BuildInfoWriter(getLog(), p, mono, rtInformation);
bi.setIgnoreJavadoc(ignoreJavadoc);
bi.setIgnore(ignore);
bi.setToolchain(getToolchain());

return bi;
}
/**
* Generate buildinfo file.
*
Expand All @@ -300,11 +308,7 @@ protected Map<Artifact, String> generateBuildinfo(boolean mono) throws MojoExecu

try (PrintWriter p = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(Files.newOutputStream(buildinfoFile.toPath()), StandardCharsets.UTF_8)))) {
BuildInfoWriter bi = new BuildInfoWriter(getLog(), p, mono, rtInformation);
bi.setIgnoreJavadoc(ignoreJavadoc);
bi.setIgnore(ignore);
bi.setToolchain(getToolchain());

BuildInfoWriter bi = newBuildInfoWriter(p, mono);
bi.printHeader(root, mono ? null : project, reproducible);

// artifact(s) fingerprints
Expand Down Expand Up @@ -348,7 +352,7 @@ private MavenProject getLastProject() {
return null;
}

private boolean isSkip(MavenProject project) {
protected boolean isSkip(MavenProject project) {
// manual/configured module skip
boolean skipModule = false;
if (skipModules != null && !skipModules.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ void setIgnore(List<String> ignore) {
this.ignore = ignore.stream().map(i -> fs.getPathMatcher("glob:" + i)).collect(Collectors.toList());
}

private boolean isIgnore(Artifact attached) {
boolean isIgnore(Artifact attached) {
Path path = Paths.get(attached.getGroupId() + '/' + getArtifactFilename(attached));
return ignore.stream().anyMatch(m -> m.matches(path));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
/*
* 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.maven.plugins.artifact.buildinfo;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.Map;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.maven.RepositoryUtils;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.project.MavenProject;
import org.apache.maven.shared.utils.logging.MessageUtils;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.artifact.DefaultArtifact;

/**
* Describe build output.
* It is expected to be used aggregator used from CLI, ie run at root after everything has run, but not bound to any build
* phase, where it would be run at root before modules.
* @since 3.5.2
*/
@Mojo(name = "describe-build-output", aggregator = true, threadSafe = true)
public class DescribeBuildOutputMojo extends AbstractBuildinfoMojo {

@Override
public void execute() throws MojoExecutionException {
// super.execute(); // do not generate buildinfo, just reuse logic from abstract class
describeBuildOutput();
}

private Path rootPath;
private BuildInfoWriter bi;

private void describeBuildOutput() throws MojoExecutionException {
rootPath = getExecutionRoot().getBasedir().toPath();
bi = newBuildInfoWriter(null, false);

getLog().info(MessageUtils.buffer()
.a("skip/ignore artifactId")
.strong("[:classifier][:extension]")
.a(" = build-path repository-filename size [sha256]")
.build());

for (MavenProject p : session.getProjects()) {
boolean skipped = isSkip(p);
String s = skipped ? "not-deployed " : " ";

// project = pom
// detect Maven 4 consumer POM transient attachment
Artifact consumerPom = RepositoryUtils.toArtifacts(p.getAttachedArtifacts()).stream()
.filter(a -> "pom".equals(a.getExtension()) && "consumer".equals(a.getClassifier()))
.findAny()
.orElse(null);

Artifact pomArtifact = new DefaultArtifact(p.getGroupId(), p.getArtifactId(), null, "pom", p.getVersion());
if (consumerPom != null) {
// Maven 4 transient consumer POM attachment is published as the POM, overrides build POM, see
// https://github.com/apache/maven/blob/c79a7a02721f0f9fd7e202e99f60b593461ba8cc/maven-core/src/main/java/org/apache/maven/internal/transformation/ConsumerPomArtifactTransformer.java#L130-L155
try {
Path pomFile = Files.createTempFile(Paths.get(p.getBuild().getDirectory()), "consumer-", ".pom");
Files.copy(consumerPom.getFile().toPath(), pomFile, StandardCopyOption.REPLACE_EXISTING);
pomArtifact = pomArtifact.setFile(pomFile.toFile());
getLog().info(s + describeArtifact(pomArtifact)); // consumer pom
// build pom
pomArtifact =
new DefaultArtifact(p.getGroupId(), p.getArtifactId(), "build", "pom", p.getVersion());
} catch (IOException e) {
throw new MojoExecutionException("Error processing consumer POM", e);
}
}
pomArtifact = pomArtifact.setFile(p.getFile());
getLog().info(s + describeArtifact(pomArtifact));

// main artifact (when available: pom packaging does not provide main artifact)
if (p.getArtifact().getFile() != null) {
getLog().info(s + describeArtifact(RepositoryUtils.toArtifact(p.getArtifact())));
}

// attached artifacts (when available)
for (Artifact a : RepositoryUtils.toArtifacts(p.getAttachedArtifacts())) {
if ("pom".equals(a.getExtension()) && "consumer".equals(a.getClassifier())) {
// ignore transient consumer POM attachment
continue;
}
boolean ignored = skipped ? false : isIgnore(a);
String i = skipped ? s : (ignored ? "RB-ignored " : " ");
getLog().info(i + describeArtifact(a, ignored));
}
}
}

private boolean isIgnore(Artifact a) {
if (a.getExtension().endsWith(".asc")) {
return true;
}
if (bi.getIgnoreJavadoc() && "javadoc".equals(a.getClassifier())) {
return true;
}
return bi.isIgnore(a);
}

private String describeArtifact(Artifact a) throws MojoExecutionException {
return describeArtifact(a, false);
}

private String describeArtifact(Artifact a, boolean skipped) throws MojoExecutionException {
String sha256 = skipped ? "" : (" " + sha256(a.getFile()));
String ce = ("".equals(a.getClassifier()) ? "" : (':' + a.getClassifier()))
+ ("jar".equals(a.getExtension()) ? "" : (":" + a.getExtension()));
String path = rootPath.relativize(a.getFile().toPath()).toString();
int i = path.indexOf("target/");
if (i >= 0) {
path = MessageUtils.buffer().mojo(path.substring(0, i + 7)).build() + path.substring(i + 7);
}
String remoteFilename = BuildInfoWriter.getArtifactFilename(a);
return /*a.getGroupId() + ':' +*/ a.getArtifactId() /*+ ':' + a.getVersion()*/
+ MessageUtils.buffer().strong(ce) + " = "
+ path + " "
+ (path.endsWith(remoteFilename)
? "-"
: MessageUtils.buffer().strong(remoteFilename).build())
+ " " + a.getFile().length() + sha256;
}

private String sha256(File file) throws MojoExecutionException {
try (InputStream is = Files.newInputStream(file.toPath())) {
return DigestUtils.sha256Hex(is);
} catch (IOException ioe) {
throw new MojoExecutionException("cannot read " + file, ioe);
}
}

@Override
public void execute(Map<org.eclipse.aether.artifact.Artifact, String> artifacts) throws MojoExecutionException {
// buildinfo generation skipped, method not called
}
}

0 comments on commit 9372b9f

Please sign in to comment.