Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BndPomRepository should support both bsn and gav like MavenBndRepository #5964

Merged

Conversation

chrisrueger
Copy link
Contributor

@chrisrueger chrisrueger commented Jan 11, 2024

Closes #5961

This PR should fix the problem that for a valid OSGi bundle MavenBndRepository.get(bsnOrGav) can be used with bsn or gav and returns something.
BndPomRepostory.get() instead only works with the bsn for a valid OSGi bundle. (Non OSGi bundles which do not have a bsn meta data can only be looked up by gav wich works as expected)

This PR's goal is to make both repos behave the same and support bsn or gav for OSGi bundles.

this PomRepositoryTest. testGetViaBSNAndGAV() will fail, which we try to fix in the next commit.

Signed-off-by: Christoph Rueger <chrisrueger@gmail.com>
1st draft, base for discussion.
I hooked into the indexing of BridgeRepository because commons-cli:commons-cli:1.2 (commons-cli-1.2.jar) is indexed as commons-cli:commons-cli:1.2.0 by bridge repo (notice 1.2 vs. 1.2.0). To satisfy the existing testcase of MavenBndRepo this was the only place where I could get the version as 3 digit semver. To be discussed if it really should be that way

Signed-off-by: Christoph Rueger <chrisrueger@gmail.com>
Signed-off-by: Christoph Rueger <chrisrueger@gmail.com>
@chrisrueger chrisrueger changed the title fail test showing gav is not working in BndPomRepo BndPomRepository should support both bsn and gav like MavenBndRepository Jan 12, 2024
Signed-off-by: Christoph Rueger <chrisrueger@gmail.com>
@chrisrueger
Copy link
Contributor Author

chrisrueger commented Jan 12, 2024

1st draft, base for discussion.

  • I ported MavenBndRepositoryTest.testGetViaBSNAndGAV() to PomRepositoryTest.testGetViaBSNAndGAV() to reproduce the problem
  • next commits are a try to fix it. Not sure if it is a good impl, but at least based for discussion @pkriens

I hooked into the indexing of BridgeRepository because this seems to handle the indexing of 3-digit versions which allows you to lookup for "1.2.0" as well as "1.2" (e.g. for commons-cli:commons-cli:1.2 (commons-cli-1.2.jar) which physically just defines a 2-digit version.

@pkriens
Copy link
Member

pkriens commented Jan 12, 2024

I think you're making it too hard but I might be wrong.

A non-OSGi artifact has nothing to do with the BridgeRepository. They lack any OSGi metadata. Trying to support them as a first class citizen there feels uncomfortable because they wreak havoc on many different places, the bsn is a pretty big invariant of OSGi. This is a hack only the Maven repositories need, it shouldn't touch code unrelated.

That said, to be able to wrap them, and sometimes use in unit tests, we need a way to address them. However, we should keep in mind that they are not the common way to address bundles.

This only needs to be supported in the RepositoryPlugin::get method. It is rather easy to check the bsn for a ':' and if it has, you can directly construct the GA, get the versions, and compare the versions to find the best matching. The BndPomRepository already has a list of archives from the POM.

Something like this:

	@Override
	public File get(String bsn, Version version, Map<String, String> properties, DownloadListener... listeners)
		throws Exception {
		if (!init()) {
			return null;
		}

		Archive archive;
		if (isMavenGAV(bsn)) {
			Archive spec = Archive.valueOf(bsn + ":" + version);
			archive = archives.stream()
				.filter(a -> matches(a, spec))
				.findAny()
				.orElse(null);
			if (archive == null)
				return null;
		} else {
			ResourceInfo resource = bridge.getInfo(bsn, version);
			if (resource == null) {
				archive = trySources(bsn, version);
				if (archive == null)
					return null;
			} else {

				String from = resource.getInfo()
					.from();
				archive = Archive.valueOf(from);
			}
		}
		Promise<File> p = repoImpl.getMavenRepository()
			.get(archive);

		if (listeners.length == 0)
			return p.getValue();

		Map<String, String> attrs = archive.attributes();
		new DownloadListenerPromise(reporter, name + ": get " + bsn + ";" + version, p, attrs, listeners);
		return repoImpl.getMavenRepository()
			.toLocalFile(archive);
	}

Notice that the IndexFile in the MavenBndRepository is basically collapsed into the BndPomRepository. The archives is the index.

@chrisrueger
Copy link
Contributor Author

Thanks @pkriens for the review.
I will rollback the BridgeRepo code.

The archives is the index.

I think I had something similar in between. I saw the archives were null or so.. Not sure anymore, I will double check.

Thanks a lot. I post an update.

This reverts commit 3e82952.

Revert "pass test for GAV"

This reverts commit dabeb36.

Signed-off-by: Christoph Rueger <chrisrueger@gmail.com>
* based on Peter's suggestion. Since BndPomRepository.archives and PomRepository.archives were both null when using a pom.xml (instead of revisions) I populated them in PomRepository.save(). If there is another / better way, we can change that

Signed-off-by: Christoph Rueger <chrisrueger@gmail.com>
Signed-off-by: Christoph Rueger <chrisrueger@gmail.com>
Signed-off-by: Christoph Rueger <chrisrueger@gmail.com>
@chrisrueger
Copy link
Contributor Author

@pkriens I have changed it to something similar to your suggestion.
In order to access the archives found no other way than populating them first in PomRepository

https://github.com/bndtools/bnd/pull/5964/files#diff-3a6aadeb70271d493c56e3f477c4b1ddf7edd867b4b0cfefef9b6bbb20f355fdR94-R95

so I can do pomRepo.archives.stream().... (see)

The archives in BndPomRepository itself were always null when using a pom.xml. They were only populated when setting revisions (configuration.revision()).

After testing the initial problem it turned out the ${repo;gav;latest} also runs through repo.versions(gav) so we have to support it too

Signed-off-by: Christoph Rueger <chrisrueger@gmail.com>
fixes the testcase from previous commit and solves the initial reported issue with (${repo;gav;latest} not working with BndPomRepo)

Signed-off-by: Christoph Rueger <chrisrueger@gmail.com>
@chrisrueger
Copy link
Contributor Author

Furthermore I added the same GAV handling to pomRepo.versions(bsn) because I noticed that this was also related to my initial reported problem and pomRepo.get() was not enough.

After fixing .versions(bsn) too all the errors below in my project went away.

image

@chrisrueger chrisrueger marked this pull request as ready for review January 13, 2024 14:47
@pkriens
Copy link
Member

pkriens commented Jan 15, 2024

Yeah, much better. It is now restricted to the BndPomRepository and does not pollute the generic code. Thanks!

@pkriens pkriens closed this Jan 15, 2024
@pkriens pkriens reopened this Jan 15, 2024
@pkriens pkriens merged commit 63837df into bndtools:master Jan 15, 2024
12 checks passed
@pkriens
Copy link
Member

pkriens commented Jan 15, 2024

pressed the wrong button ... sorry

@chrisrueger
Copy link
Contributor Author

chrisrueger commented Jan 20, 2024

@pkriens

While playing with my fix in this PR I noticed the following behavior:

When the pom.xml contains two versions of the same dep like this:

<dependency>
    <groupId>org.apache.felix</groupId>
    <artifactId>org.apache.felix.gogo.shell</artifactId>
    <version>1.1.4</version>
</dependency>
<dependency>
    <groupId>org.apache.felix</groupId>
    <artifactId>org.apache.felix.gogo.shell</artifactId>
    <version>1.1.0</version>
</dependency>

I get this when I want to start my .bndrun (-runbundles org.apache.felix.gogo.shell;version='[1.1.4,1.1.5)',\)

image

It works fine (no error) if I reverse the order and put 1.1.4 last:

<dependency>
    <groupId>org.apache.felix</groupId>
    <artifactId>org.apache.felix.gogo.shell</artifactId>
    <version>1.1.0</version>
</dependency>

<dependency>
    <groupId>org.apache.felix</groupId>
    <artifactId>org.apache.felix.gogo.shell</artifactId>
    <version>1.1.4</version>
</dependency>

or remove 1.1.0

So it seems: last version wins.

In MavenBndRepository (.mvn) I do not have this problem. Since I generated the pom.xml from my .mvn file, it coindicently ended up in that order in the pom.xml but I just noticed it now with my first steps with BndPomRepo

Question:
Is this expected behavior of BndPomRespository?
Or should I file a bug and dig deeper? Any idea where I could start search putting my breakpoint to search the needle in the haystack?

EDIT:

It can even be seen in the Repo Browser, that only one version per bundle (both are OSGi bundles with a bsn) is shown:

1.1.0 is last:

image

1.1.4 is last:

image

In MavenBndRepo there are both versions in the RepoBrowser.

@pkriens
Copy link
Member

pkriens commented Jan 22, 2024

Well, officially you cannot have 2 versions in maven so from a pom pov it is problematic. From a BndPomRepository pov it is obviously wrong ... We should be able to support multiple versions. I think this is the culprit:

if (deps.containsKey(d.program))

It explicitly removes multiple versions. I'd expect it would only show the first so it could be something else

@chrisrueger
Copy link
Contributor Author

Thanks @pkriens I will create an issue out of it and try digging in during the next days.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

BndPomRepository cannot resolve OSGi dependencies by GAV like MavenBndRepository
2 participants