Skip to content

Commit

Permalink
Add an option to filter repo-references before being added to a p2-repo
Browse files Browse the repository at this point in the history
Add a new parameter named 'repositoryReferenceFilter' to the
AssembleRepositoryMojo to better control the automatic addition of
repository references with matching locations.
This can be used with ANT-style or Java RegEx patterns as follows:

<repositoryReferenceFilter>
	<exclude>
		<location>https://foo.bar.org/hidden/**</location>
		<location>https://foo.bar.org/secret/**</location>
	</exclude>
	<include>%regex[http(s)?:\/\/foo\.bar\.org\/.*]</include>
</repositoryReferenceFilter>

The is especially convenient in combination with the automatic addition
of IU Target-Repository or POM-Repository references, if some but not
all repos should be added.
  • Loading branch information
HannesWell committed Sep 5, 2023
1 parent 9a9852e commit a586e22
Show file tree
Hide file tree
Showing 7 changed files with 216 additions and 119 deletions.
23 changes: 23 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,29 @@

This page describes the noteworthy improvements provided by each release of Eclipse Tycho.

## 4.0.3

### new option to filter added repository-references when assembling a p2-repository

The repository references automatically added to a assembled p2-repository (via `tycho-p2-repository-plugin`'s `addIUTargetRepositoryReferences` or `addPomRepositoryReferences`)
can now be filtered by their location using exclusion and inclusion patterns and therefore allows more fine-grained control which references are added.
```xml
<plugin>
<groupId>org.eclipse.tycho</groupId>
<artifactId>tycho-p2-repository-plugin</artifactId>
<version>${tycho-version}</version>
<configuration>
... other configuration options ...
<repositoryReferenceFilter>
<exclude>
<location>https://foo.bar.org/hidden/**</location>
<location>https://foo.bar.org/secret/**</location>
</exclude>
<include>%regex[http(s)?:\/\/foo\.bar\.org\/.*]</include>
</repositoryReferenceFilter>
</configuration>
</plugin>

## 4.0.2
- new option to include referenced repositories when resolving the target platform
- Add dummy parameter to prevent warnings with jgit as timestamp provider
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<site>
<category-def name="Test Category" label="Test Category Label">
<description>
Test Category Description
</description>
</category-def>
<repository-reference location="https://some.where/from/category" enabled="true" />
</site>
55 changes: 55 additions & 0 deletions tycho-its/projects/p2Repository.repositoryRef.filter/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>

<version>1.0.0</version>
<groupId>tycho-its-project.p2Repository.repositoryRef.location</groupId>
<artifactId>repositoryRef.location</artifactId>
<packaging>eclipse-repository</packaging>

<repositories>
<repository>
<id>repo1</id>
<url>https://download.eclipse.org/tm4e/releases/0.8.1</url>
<layout>p2</layout>
</repository>
<repository>
<id>repo2</id>
<url>https://download.eclipse.org/lsp4e/releases/0.24.1</url>
<layout>p2</layout>
</repository>
<repository>
<id>repo3</id>
<url>https://download.eclipse.org/lsp4j/updates/releases/0.21.1</url>
<layout>p2</layout>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<groupId>org.eclipse.tycho</groupId>
<artifactId>tycho-maven-plugin</artifactId>
<version>${tycho-version}</version>
<extensions>true</extensions>
</plugin>
<plugin>
<groupId>org.eclipse.tycho</groupId>
<artifactId>tycho-p2-repository-plugin</artifactId>
<version>${tycho-version}</version>
<configuration>
<compress>false</compress>
<addPomRepositoryReferences>true</addPomRepositoryReferences>
<repositoryReferenceFilter>
<exclude>
<location>https://download.eclipse.org/lsp4e/**</location>
<location>https://download.eclipse.org/lsp4j/**</location>
</exclude>
<include>%regex[http(s)?:\/\/download\.eclipse\.org\/.*]</include>
</repositoryReferenceFilter>
</configuration>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -12,92 +12,63 @@
*******************************************************************************/
package org.eclipse.tycho.test.p2Repository;

import static org.eclipse.equinox.p2.repository.IRepository.ENABLED;
import static org.eclipse.equinox.p2.repository.IRepository.NONE;
import static org.eclipse.equinox.p2.repository.IRepository.TYPE_ARTIFACT;
import static org.eclipse.equinox.p2.repository.IRepository.TYPE_METADATA;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.io.File;
import java.util.List;
import java.util.Objects;

import org.apache.maven.it.Verifier;
import org.eclipse.tycho.test.AbstractTychoIntegrationTest;
import org.eclipse.tycho.test.util.P2RepositoryTool;
import org.eclipse.tycho.test.util.P2RepositoryTool.RepositoryReference;
import org.eclipse.tycho.test.util.ResourceUtil;
import org.junit.BeforeClass;
import org.junit.Test;

import de.pdark.decentxml.Document;
import de.pdark.decentxml.Element;
import de.pdark.decentxml.XMLParser;

public class RepoRefLocationP2RepositoryIntegrationTest extends AbstractTychoIntegrationTest {

private static Verifier verifier;

private static class RepositoryReferenceData {
private String uri;
private String type;
private String enabled;

public RepositoryReferenceData(String uri, String type, String enabled) {
this.uri = uri;
this.type = type;
this.enabled = enabled;
}
@Test
public void testRefLocation() throws Exception {
Verifier verifier = getVerifier("/p2Repository.repositoryRef.location", false);
verifier.addCliOption("-Dtest-data-repo=" + ResourceUtil.P2Repositories.ECLIPSE_LATEST.toString());
verifier.executeGoal("package");
verifier.verifyErrorFreeLog();

@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
RepositoryReferenceData other = (RepositoryReferenceData) obj;
return Objects.equals(enabled, other.enabled) && Objects.equals(type, other.type)
&& Objects.equals(uri, other.uri);
}
P2RepositoryTool p2Repo = P2RepositoryTool.forEclipseRepositoryModule(new File(verifier.getBasedir()));
List<RepositoryReference> allRepositoryReferences = p2Repo.getAllRepositoryReferences();

@Override
public String toString() {
return "[uri=" + uri + ", type=" + type + ", enabled=" + enabled + "]";
}
assertEquals(4, allRepositoryReferences.size());
assertThat(allRepositoryReferences,
containsInAnyOrder(new RepositoryReference("http://some.where", TYPE_ARTIFACT, NONE),
new RepositoryReference("http://some.where", TYPE_METADATA, NONE),
new RepositoryReference("http://some.where.else", TYPE_ARTIFACT, ENABLED),
new RepositoryReference("http://some.where.else", TYPE_METADATA, ENABLED)));
}

@BeforeClass
public static void executeBuild() throws Exception {
verifier = new RepoRefLocationP2RepositoryIntegrationTest().getVerifier("/p2Repository.repositoryRef.location",
false);
verifier.addCliOption("-Dtest-data-repo=" + ResourceUtil.P2Repositories.ECLIPSE_LATEST.toString());
@Test
public void testReferenceFiltering() throws Exception {
// Of course it is actually a bit pointless to filter explicitly specified
// references, but it makes the test simple/faster instead of preparing a
// target-definition with IU-location so that it can be added automatically,
// which is the main use-case.
Verifier verifier = getVerifier("/p2Repository.repositoryRef.filter", false);
verifier.executeGoal("package");
verifier.verifyErrorFreeLog();
}

@Test
public void testRefLocation() throws Exception {
File target = new File(verifier.getBasedir(), "target");
File repository = new File(target, "repository");
File contentXml = new File(repository, "content.xml");
assertTrue(contentXml.isFile());
File artifactXml = new File(repository, "artifacts.xml");
assertTrue(artifactXml.isFile());
assertTrue(new File(target, "category.xml").isFile());
P2RepositoryTool p2Repo = P2RepositoryTool.forEclipseRepositoryModule(new File(verifier.getBasedir()));
List<RepositoryReference> allRepositoryReferences = p2Repo.getAllRepositoryReferences();

Document artifactsDocument = XMLParser.parse(contentXml);
// See MetadataRepositoryIO.Writer#writeRepositoryReferences
List<Element> repositories = artifactsDocument.getChild("repository").getChild("references")
.getChildren("repository");
assertEquals(4, repositories.size());
List<RepositoryReferenceData> actual = repositories.stream()
.map(e -> new RepositoryReferenceData(e.getAttributeValue("uri"), e.getAttributeValue("type"),
e.getAttributeValue("options")))
.toList();
assertThat(actual,
containsInAnyOrder(new RepositoryReferenceData("http://some.where", "1", "0"),
new RepositoryReferenceData("http://some.where", "0", "0"),
new RepositoryReferenceData("http://some.where.else", "1", "1"),
new RepositoryReferenceData("http://some.where.else", "0", "1")));
assertEquals(4, allRepositoryReferences.size());
assertThat(allRepositoryReferences, containsInAnyOrder( //
new RepositoryReference("https://download.eclipse.org/tm4e/releases/0.8.1", TYPE_ARTIFACT, ENABLED),
new RepositoryReference("https://download.eclipse.org/tm4e/releases/0.8.1", TYPE_METADATA, ENABLED),
new RepositoryReference("https://some.where/from/category", TYPE_ARTIFACT, ENABLED),
new RepositoryReference("https://some.where/from/category", TYPE_METADATA, ENABLED)));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public void testFilterProvided() throws Exception {
P2RepositoryTool p2Repo = P2RepositoryTool
.forEclipseRepositoryModule(new File(verifier.getBasedir(), "repository"));
p2Repo.getUniqueIU("bundle");
p2Repo.assertNumberOfUnits(1, u -> u.id.equals("a.jre.javase") || u.id.endsWith(".test.category"));
p2Repo.assertNumberOfUnits(1, u -> u.id().equals("a.jre.javase") || u.id().endsWith(".test.category"));
assertTrue("Bundle artifact not found!", p2Repo.findBundleArtifact("bundle").isPresent());
p2Repo.assertNumberOfBundles(1);
p2Repo.assertNumberOfFeatures(0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import org.apache.maven.model.Repository;
Expand All @@ -29,6 +31,7 @@
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.MatchPatterns;
import org.eclipse.tycho.PackagingType;
import org.eclipse.tycho.ReactorProject;
import org.eclipse.tycho.TychoConstants;
Expand Down Expand Up @@ -73,6 +76,12 @@
*/
@Mojo(name = "assemble-repository", defaultPhase = LifecyclePhase.PACKAGE, threadSafe = true)
public class AssembleRepositoryMojo extends AbstractRepositoryMojo {

public static class RepositoryReferenceFilter {
List<String> exclude;
List<String> include;
}

private static final Object LOCK = new Object();
/**
* <p>
Expand Down Expand Up @@ -217,6 +226,40 @@ public class AssembleRepositoryMojo extends AbstractRepositoryMojo {
@Parameter()
private boolean addIUTargetRepositoryReferences;

/**
* A list of patterns to filter the automatically derived repository references by including or
* excluding their location to control if they are eventually added to the assembled repository.
* <p>
* Each pattern is either an <em>inclusion</em> or <em>exclusion</em> and an arbitrary number of
* each can be specified. The location of a repository reference must match at least one
* <em>inclusion</em>-pattern (if any is specified) and must not be match by any
* <em>exclusion</em>-pattern, in order to be eventually added to the assembled repository.<br>
* The specified filters are only applied to those repository references derived from the
* target-definition or pom file, when {@link #addIUTargetRepositoryReferences} respectively
* {@link #addPomRepositoryReferences} is set to {@code true}.
* </p>
* <p>
* Configuration example
*
* <pre>
* &lt;repositoryReferenceFilter&gt;
* &lt;exclude&gt;
* &lt;location&gt;https://foo.bar.org/hidden/**&lt;/location&gt;
* &lt;location&gt;https://foo.bar.org/secret/**&lt;/location&gt;
* &lt;/exclude&gt;
* &lt;include&gt;%regex[http(s)?:\/\/foo\.bar\.org\/.*]&lt;/include&gt;
* &lt;/repositoryReferenceFilter&gt;
* </pre>
*
* It contains two <em>exclusion</em> patterns using {@code ANT}-style syntax and one
* <em>inclusion</em> using a {@code Java RegEx} {@link Pattern} (enclosed in
* {@code %regex[<the-regex-pattern>]}). The <em>inclusion</em> pattern uses the shorthand
* notation for singleton lists.
* </p>
*/
@Parameter
private RepositoryReferenceFilter repositoryReferenceFilter = null;

/**
* If enabled, an
* <a href="https://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.repository.html">OSGi
Expand Down Expand Up @@ -265,11 +308,14 @@ public void execute() throws MojoExecutionException, MojoFailureException {
.flatMap(List::stream)//
.map(ref -> new RepositoryReference(ref.getName(), ref.getLocation(), ref.isEnabled()))//
.collect(Collectors.toCollection(ArrayList::new));
Predicate<String> autoReferencesFilter = buildRepositoryReferenceLocationFilter();
if (addPomRepositoryReferences) {
for (Repository pomRepo : getProject().getRepositories()) {
if ("p2".equals(pomRepo.getLayout())) {
repositoryReferences
.add(new RepositoryReference(pomRepo.getName(), pomRepo.getUrl(), true));
String locationURL = pomRepo.getUrl();
if (autoReferencesFilter.test(locationURL)) {
repositoryReferences.add(new RepositoryReference(pomRepo.getName(), locationURL, true));
}
}
}
}
Expand All @@ -278,9 +324,11 @@ public void execute() throws MojoExecutionException, MojoFailureException {
.getTargetPlatformConfiguration(getProject()).getTargets()) {
for (Location location : targetDefinitionFile.getLocations()) {
if (location instanceof InstallableUnitLocation iu) {
for (org.eclipse.tycho.targetplatform.TargetDefinition.Repository iuRepo : iu
.getRepositories()) {
repositoryReferences.add(new RepositoryReference(null, iuRepo.getLocation(), true));
for (var iuRepo : iu.getRepositories()) {
String locationURL = iuRepo.getLocation();
if (autoReferencesFilter.test(locationURL)) {
repositoryReferences.add(new RepositoryReference(null, locationURL, true));
}
}
}
}
Expand Down Expand Up @@ -351,4 +399,20 @@ private List<Category> getCategories(final File categoriesDirectory) {
return eclipseRepositoryProject.loadCategories(categoriesDirectory);
}

private Predicate<String> buildRepositoryReferenceLocationFilter() {
Predicate<String> filter = l -> true;
if (repositoryReferenceFilter != null) {
if (repositoryReferenceFilter.include != null && !repositoryReferenceFilter.include.isEmpty()) {
MatchPatterns inclusionPattern = MatchPatterns.from(repositoryReferenceFilter.include);
filter = l -> inclusionPattern.matches(l, true);
}
if (repositoryReferenceFilter.exclude != null && !repositoryReferenceFilter.exclude.isEmpty()) {
MatchPatterns exclusionPattern = MatchPatterns.from(repositoryReferenceFilter.exclude);
Predicate<String> exclusionFilter = l -> !exclusionPattern.matches(l, true);
filter = filter.and(exclusionFilter);
}
}
return filter;
}

}
Loading

0 comments on commit a586e22

Please sign in to comment.