Skip to content

Commit

Permalink
Fix for releasing extra files with maven
Browse files Browse the repository at this point in the history
Signed-off-by: Peter Kriens <Peter.Kriens@aQute.biz>
  • Loading branch information
pkriens committed Jun 1, 2023
1 parent 170ed5b commit 2bf1463
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import java.util.Collections;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
Expand All @@ -31,6 +32,8 @@
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Predicate;
import java.util.jar.Manifest;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import org.osgi.resource.Capability;
Expand All @@ -51,6 +54,7 @@
import aQute.bnd.osgi.Constants;
import aQute.bnd.osgi.FileResource;
import aQute.bnd.osgi.Jar;
import aQute.bnd.osgi.PreprocessResource;
import aQute.bnd.osgi.Processor;
import aQute.bnd.osgi.Resource;
import aQute.bnd.osgi.repository.BaseRepository;
Expand Down Expand Up @@ -93,6 +97,7 @@
@BndPlugin(name = "MavenBndRepository", parameters = Configuration.class)
public class MavenBndRepository extends BaseRepository implements RepositoryPlugin, RegistryPlugin, Plugin, Closeable,
Refreshable, Actionable, ToDependencyPom, ReleaseBracketingPlugin {
final static Pattern PREPROCESS_P = Pattern.compile("\\{\\s*(?<core>[^}]+)\\s*\\}");

private final static Logger logger = LoggerFactory.getLogger(MavenBndRepository.class);
private static final int DEFAULT_POLL_TIME = 5;
Expand All @@ -103,7 +108,7 @@ public class MavenBndRepository extends BaseRepository implements RepositoryPlug
private Configuration configuration;
private Registry registry;
private File localRepo;
private Reporter reporter;
Reporter reporter;
IMavenRepo storage;
private boolean inited;
IndexFile index;
Expand Down Expand Up @@ -245,20 +250,7 @@ public PutResult put(InputStream stream, PutOptions options) throws Exception {
}
}

for (ExtraDTO extra : instructions.extra) {
String path = extra.path;
String parts[] = Strings.extension(path);
String ext = parts == null ? ".unknown" : parts[1];
File file = new File(path);
if (!file.isFile())
reporter.error("-release-maven.extra contains a path to a file that does not exist: %s",
file);
else {
Archive archive = pom.getRevision()
.archive(ext, extra.clazz);
releaser.add(archive, file);
}
}
doExtra(options, instructions, pom, releaser);
}
if (configuration.noupdateOnRelease() == false) {
index.add(binaryArchive);
Expand All @@ -275,6 +267,35 @@ public PutResult put(InputStream stream, PutOptions options) throws Exception {

}

private void doExtra(PutOptions options, ReleaseDTO instructions, IPom pom, Release releaser)
throws Exception, IOException {
for (ExtraDTO extra : instructions.extra) {
String path = extra.path;
String parts[] = Strings.extension(path);
String ext = parts == null ? ".unknown" : parts[1];
String clazz = extra.clazz;
File file = new File(path);
if (!file.isFile())
reporter.error("-release-maven.extra contains a path to a file that does not exist: %s",
file);
else {
try (Resource r = new FileResource(file)) {
Resource what;
if (extra.preprocess) {
what = new PreprocessResource(options.context, r);
} else
what = r;

Archive archive = pom.getRevision()
.archive(ext, clazz);
try (InputStream in = what.openInputStream()) {
releaser.add(archive, in);
}
}
}
}
}

private Resource getPom(PutOptions options, ReleaseDTO instructions, Jar binary) throws Exception, IOException {
Resource pom = null;

Expand Down Expand Up @@ -459,22 +480,30 @@ private ReleaseDTO getReleaseDTO(Processor context) {
release.passphrase = sign.get("passphrase");
}

if (!p.isEmpty()) {
reporter.warning("The -maven-release instruction contains unrecognized options: %s", p);
}

int clazz = 0;

for (Entry<String, Attrs> e : p.entrySet()) {
for (Iterator<Entry<String, Attrs>> it = p.entrySet()
.iterator(); it.hasNext();) {

Entry<String, Attrs> e = it.next();
String key = Processor.removeDuplicateMarker(e.getKey());
switch (key) {
case "extra" -> {
ExtraDTO extra = new ExtraDTO();
extra.clazz = e.getValue()
.getOrDefault("clazz", "class-" + clazz++);
.getOrDefault("class", "class-" + clazz++);
String path = e.getValue()
.get("path");

boolean preprocess = false;

if (path != null) {
Matcher matcher = PREPROCESS_P.matcher(path);
if (matcher.matches()) {
preprocess = true;
path = matcher.group("core");
}
path = context.getFile(path)
.getAbsolutePath();
} else {
Expand All @@ -483,6 +512,7 @@ private ReleaseDTO getReleaseDTO(Processor context) {
continue;
}
extra.path = path;
extra.preprocess = preprocess;
extra.options.putAll(e.getValue());
release.extra.add(extra);
}
Expand All @@ -491,7 +521,6 @@ private ReleaseDTO getReleaseDTO(Processor context) {
reporter.warning("Unknown option in the -maven-release instruction: %s", e);
}
}

}
return release;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public static class SourceDTO extends DTO {
public static class ExtraDTO extends DTO {
public String path;
public String clazz;
public boolean preprocess;
public Map<String, String> options = new HashMap<>();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,69 @@ public void testPutMavenReleaseSourcesDefaultSourcepath() throws Exception {
}
}

@Test
public void testPutMavenExtraFiles() throws Exception {
Map<String, String> map = new HashMap<>();
map.put("releaseUrl", remote.toURI()
.toString());
config(map);
try (Processor context = new Processor()) {
context.setProperty("test", "123456789012345678901234567890");
context.setProperty("-maven-release",
"extra;path=testresources/extra/test.foo,extra;path={testresources/extra/test.bar};class=BAR");

File jar = IO.getFile("testresources/release-nosource.jar");
PutOptions options = new PutOptions();
options.context = context;
PutResult put = repo.put(new FileInputStream(jar), options);
assertThat(context.check()).isTrue();

assertIsFile(remote, "biz/aQute/bnd/biz.aQute.bnd.maven/3.2.0/biz.aQute.bnd.maven-3.2.0.jar", 89400);
assertIsFile(remote, "biz/aQute/bnd/biz.aQute.bnd.maven/3.2.0/biz.aQute.bnd.maven-3.2.0-class-0.foo", 16);
assertIsFile(remote, "biz/aQute/bnd/biz.aQute.bnd.maven/3.2.0/biz.aQute.bnd.maven-3.2.0-BAR.bar", 53);
}
}

@Test
public void testPutMavenExtraNoFile() throws Exception {
Map<String, String> map = new HashMap<>();
map.put("releaseUrl", remote.toURI()
.toString());
config(map);
try (Processor context = new Processor()) {
context.setProperty("-maven-release", "extra;path=i_do_not_exist");

File jar = IO.getFile("testresources/release-nosource.jar");
PutOptions options = new PutOptions();
options.context = context;
PutResult put = repo.put(new FileInputStream(jar), options);
context.getInfo(repo.reporter);
assertThat(context.check("No metadata for revision", "i_do_not_exist")).isTrue();

assertIsFile(remote, "biz/aQute/bnd/biz.aQute.bnd.maven/3.2.0/biz.aQute.bnd.maven-3.2.0.jar", 89400);
}
}

@Test
public void testPutMavenExtraNoPath() throws Exception {
Map<String, String> map = new HashMap<>();
map.put("releaseUrl", remote.toURI()
.toString());
config(map);
try (Processor context = new Processor()) {
context.setProperty("-maven-release", "extra");

File jar = IO.getFile("testresources/release-nosource.jar");
PutOptions options = new PutOptions();
options.context = context;
PutResult put = repo.put(new FileInputStream(jar), options);
context.getInfo(repo.reporter);
assertThat(context.check("No metadata for revision", "has an extra without the path attribute")).isTrue();

assertIsFile(remote, "biz/aQute/bnd/biz.aQute.bnd.maven/3.2.0/biz.aQute.bnd.maven-3.2.0.jar", 89400);
}
}

@Test
public void testPutMavenReleaseSourcesSourcepath() throws Exception {
Map<String, String> map = new HashMap<>();
Expand Down
1 change: 1 addition & 0 deletions biz.aQute.repository/testresources/extra/test.bar
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
this is test bar with ${test}
1 change: 1 addition & 0 deletions biz.aQute.repository/testresources/extra/test.foo
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
this is test foo
19 changes: 18 additions & 1 deletion docs/_instructions/maven-release.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ Though this instruction is not specific for a plugin, it was developed in conjun

-maven-release ::= ( 'local'|'remote' ( ';' snapshot )? ) ( ',' option )*
snapshot ::= <value to be used for timestamp>
option ::= sources | javadoc | pom | sign
option ::= sources | javadoc | pom | sign | extra*
extra ::= 'extra'
( ';path=' ( PATH | '{' PATH '}' )?
( ';class=' maven-class )?
sources ::= 'sources'
( ';path=' ( 'NONE' | PATH ) )?
( ';force=' ( 'true' | 'false' ) )?
Expand Down Expand Up @@ -42,6 +45,20 @@ The repository has the following parameters:

If the Maven Bnd Repository is asked to put a file, it will look up the `-maven-release` instruction using merged properties. The property is looked up from the bnd file that built the artifact. However, it should in general be possible to define this header in the workspace using macros like `${project}` to specify relative paths.

The `extra` option provides a way to add additional files to release. A Maven release always has a pom and then a number of files that are separated by a _class_. The default class is generally the jar file. Special classes are reserved for the sources and the javadoc.

The `extra` option takes the following parameters:

* `path` : The path to the file that will be placed in the release directory. If the path is surrounded by curly braces, it will be pre-processed.
* `class` : The class of the file. This is the maven class used.

For example:

-maven-release \
extra;\
path=files/feature.json;
class=feature
# Signing

If the instruction contains the sign attribute and release build is detected the repository tries to apply [gnupg](https://gnupg.org/) via a command process to create `.asc` files for all deployed artifacts. This requires a Version of [gnupg](https://gnupg.org/) installed on your build system. By default it uses the `gpg` command. If the `passphrase` is configured, it will hand it over to the command as standard input. The command will be constructed as follows: `gpg --batch --passphrase-fd 0 --output <filetosign>.asc --detach-sign --armor <filetosign>`. Some newer gnupg versions will ignore the passphrase via standard input for the first try and ask again with password screen. This will crash the process. Have a look [here](https://stackoverflow.com/questions/19895122/how-to-use-gnupgs-passphrase-fd-argument) to teach gnupg otherwise. The command can be exchanged or amended with additional options by defining a property named `gpg` in your workspace (e.g. `build.bnd` or somewhere in the ext directory).
Expand Down

0 comments on commit 2bf1463

Please sign in to comment.