Skip to content

Commit da2ed1e

Browse files
laeubieclipse-tycho-bot
authored andcommitted
Add a version report to target update mojo
Fix #4668 (cherry picked from commit 18d50ba)
1 parent 483cc67 commit da2ed1e

5 files changed

Lines changed: 308 additions & 32 deletions

File tree

tycho-core/src/main/java/org/eclipse/tycho/core/MarkdownBuilder.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ public MarkdownBuilder addListItem(String item) {
4545
return this;
4646
}
4747

48+
public MarkdownBuilder addListItem2(String item) {
49+
lines.add(" - " + escape(item));
50+
return this;
51+
}
52+
4853
public static String escape(String item) {
4954
return item.replace("@", "<span>@</span>").replace("#", "<span>#</span>");
5055
}
@@ -80,4 +85,9 @@ public void h3(String string) {
8085
lines.add("");
8186
}
8287

88+
public void h4(String string) {
89+
lines.add("#### " + escape(string));
90+
lines.add("");
91+
}
92+
8393
}

tycho-extras/tycho-version-bump-plugin/src/main/java/org/eclipse/tycho/versionbump/InstallableUnitLocationUpdater.java

Lines changed: 174 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,12 @@
4141
import org.eclipse.equinox.p2.core.IProvisioningAgent;
4242
import org.eclipse.equinox.p2.core.ProvisionException;
4343
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
44+
import org.eclipse.equinox.p2.metadata.IRequirement;
4445
import org.eclipse.equinox.p2.metadata.Version;
4546
import org.eclipse.equinox.p2.query.QueryUtil;
4647
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository;
4748
import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
49+
import org.eclipse.tycho.core.MarkdownBuilder;
4850
import org.eclipse.tycho.p2resolver.TargetDefinitionVariableResolver;
4951
import org.eclipse.tycho.targetplatform.TargetDefinition;
5052

@@ -56,6 +58,7 @@
5658
@Named
5759
public class InstallableUnitLocationUpdater {
5860

61+
private static final String EMPTY_VERSION = "0.0.0";
5962
private static final Pattern DEFAULT_VERSION_PATTERN = Pattern.compile("(\\d+)\\.(\\d+)");
6063
private static final Pattern DEFAULT_DATE_PATTERN = Pattern.compile("(\\d{4}-\\d{2})");
6164
private static final Period DEFAULT_PERIOD = Period.ofMonths(3).plusDays(7);
@@ -69,43 +72,88 @@ public class InstallableUnitLocationUpdater {
6972

7073
boolean update(Element iuLocation, UpdateTargetMojo context)
7174
throws MojoFailureException, URISyntaxException, ProvisionException {
75+
Log log = context.getLog();
76+
ResolvedRepository location = getResolvedLocation(iuLocation);
77+
log.info("Check " + location.getLocation() + " for updates...");
7278
List<IU> units = iuLocation.getChildren("unit").stream()
73-
.map(unit -> new IU(unit.getAttributeValue("id"), unit.getAttributeValue("version"), unit)).toList();
74-
IMetadataRepository repository = getMetadataRepository(iuLocation, context, units);
75-
boolean updated = false;
79+
.map(unit -> new IU(unit.getAttributeValue("id"), getUnitVersion(unit), unit)).toList();
80+
IMetadataRepositoryManager repositoryManager = agent.getService(IMetadataRepositoryManager.class);
81+
URI currentLocation = new URI(location.location());
82+
IMetadataRepository currentRepository = null;
83+
MetadataRepositoryUpdate updateRepository = getMetadataRepository(location, context, units, repositoryManager);
84+
boolean updated = updateRepository.updateLocation(location);
85+
List<VersionUpdate> updates = new ArrayList<>();
7686
for (Element unit : iuLocation.getChildren("unit")) {
7787
String id = unit.getAttributeValue("id");
78-
IInstallableUnit latestUnit = repository
88+
IInstallableUnit latestUnit = updateRepository.update()
7989
.query(QueryUtil.createLatestQuery(QueryUtil.createIUQuery(id)), null).stream().findFirst()
8090
.orElse(null);
8191
if (latestUnit != null) {
92+
String currentVersion = getUnitVersion(unit);
93+
if (EMPTY_VERSION.equals(currentVersion) && !context.isUpdateEmptyVersion()) {
94+
continue;
95+
}
8296
String newVersion = latestUnit.getVersion().toString();
83-
String currentVersion = unit.getAttributeValue("version");
8497
if (newVersion.equals(currentVersion)) {
85-
context.getLog().debug("unit '" + id + "' is already up-to date");
98+
log.debug("unit '" + id + "' is already up-to date");
8699
} else {
87-
updated = true;
88-
context.getLog()
89-
.info("Update version of unit '" + id + "' from " + currentVersion + " > " + newVersion);
90-
unit.setAttribute("version", newVersion);
100+
if (currentRepository == null) {
101+
currentRepository = repositoryManager.loadRepository(currentLocation, null);
102+
}
103+
IInstallableUnit currentIU = currentRepository
104+
.query(QueryUtil.createIUQuery(id, Version.create(currentVersion)), null).stream()
105+
.findFirst().orElse(null);
106+
VersionUpdate update = new VersionUpdate(id, currentVersion, currentIU, latestUnit);
107+
if (update.hasVersionChange() && isCompatibleChange(update, context)) {
108+
log.info("Update version of unit '" + id + "' from " + update.getPreviousVersion() + " > "
109+
+ newVersion);
110+
updates.add(update);
111+
updated = true;
112+
unit.setAttribute("version", newVersion);
113+
}
91114
}
92115
} else {
93-
context.getLog().warn(
94-
"Resolution result does not contain root installable unit '" + id + "' update is skipped!");
116+
log.warn("Resolution result does not contain root installable unit '" + id + "' update is skipped!");
117+
}
118+
}
119+
MarkdownBuilder builder = context.builder;
120+
if (updates.isEmpty()) {
121+
if (updateRepository.hasUpdate(currentLocation)) {
122+
builder.h3("The location " + location.location() + " was updated:");
123+
builder.addListItem("Location changed to " + updateRepository.uri());
124+
builder.newLine();
95125
}
126+
return updated;
127+
}
128+
if (updateRepository.hasUpdate(currentLocation)) {
129+
builder.h3("The location " + location.location() + " was updated:");
130+
builder.addListItem("Location changed to " + updateRepository.uri());
131+
} else {
132+
builder.h3("The content of the location " + location.location() + " was updated:");
133+
}
134+
for (VersionUpdate versionUpdate : updates) {
135+
describeUpdate(versionUpdate, builder);
96136
}
137+
builder.newLine();
97138
return updated;
98139
}
99140

100-
private IMetadataRepository getMetadataRepository(Element iuLocation, UpdateTargetMojo context, List<IU> units)
141+
private String getUnitVersion(Element unit) {
142+
String value = unit.getAttributeValue("version");
143+
if (value == null || value.isBlank()) {
144+
return EMPTY_VERSION;
145+
}
146+
return value;
147+
}
148+
149+
private MetadataRepositoryUpdate getMetadataRepository(ResolvedRepository location, UpdateTargetMojo context,
150+
List<IU> units, IMetadataRepositoryManager repositoryManager)
101151
throws URISyntaxException, ProvisionException {
102-
ResolvedRepository location = getResolvedLocation(iuLocation);
103-
String raw = location.getLocation();
104152
Log log = context.getLog();
105-
log.debug("Look for updates of location " + raw);
153+
log.debug("Look for updates of location " + location.getLocation());
154+
String raw = location.getLocation();
106155
URI uri = new URI(raw);
107156
List<String> discovery = context.getUpdateSiteDiscovery();
108-
IMetadataRepositoryManager repositoryManager = agent.getService(IMetadataRepositoryManager.class);
109157
for (String strategy : discovery) {
110158
String trim = strategy.trim();
111159
if (trim.equals("parent")) {
@@ -122,7 +170,7 @@ private IMetadataRepository getMetadataRepository(Element iuLocation, UpdateTarg
122170
log.debug("No parent repository found for location " + uri + " using " + parentURI + ": " + e);
123171
continue;
124172
}
125-
IMetadataRepository bestLocation = findBestLocation(context, units, location, repositoryManager,
173+
MetadataRepositoryUpdate bestLocation = findBestLocation(context, units, location, repositoryManager,
126174
children);
127175
if (bestLocation != null) {
128176
return bestLocation;
@@ -150,8 +198,8 @@ private IMetadataRepository getMetadataRepository(Element iuLocation, UpdateTarg
150198
log.debug("No repository found for location " + repoURI + ": " + e);
151199
}
152200
}
153-
IMetadataRepository bestLocation = findBestLocation(context, units, location, repositoryManager,
154-
repositories);
201+
MetadataRepositoryUpdate bestLocation = findBestLocation(context, units, location,
202+
repositoryManager, repositories);
155203
if (bestLocation != null) {
156204
return bestLocation;
157205
}
@@ -192,7 +240,7 @@ private IMetadataRepository getMetadataRepository(Element iuLocation, UpdateTarg
192240
log.debug("Check location " + nextURL + " for updates with " + currentDateString + " > "
193241
+ nextDateString + "...");
194242
try {
195-
IMetadataRepository bestLocation = findBestLocation(context, units, location,
243+
MetadataRepositoryUpdate bestLocation = findBestLocation(context, units, location,
196244
repositoryManager, List.of(new URI(nextURL)));
197245
if (bestLocation != null) {
198246
return bestLocation;
@@ -207,11 +255,12 @@ private IMetadataRepository getMetadataRepository(Element iuLocation, UpdateTarg
207255
}
208256
}
209257
//if nothing else is applicable return the original location repository...
210-
return repositoryManager.loadRepository(uri, null);
258+
return new MetadataRepositoryUpdate(null, repositoryManager.loadRepository(uri, null));
211259
}
212260

213-
private IMetadataRepository findBestLocation(UpdateTargetMojo context, List<IU> units, ResolvedRepository location,
214-
IMetadataRepositoryManager repositoryManager, Collection<URI> children) throws ProvisionException {
261+
private MetadataRepositoryUpdate findBestLocation(UpdateTargetMojo context, List<IU> units,
262+
ResolvedRepository location, IMetadataRepositoryManager repositoryManager, Collection<URI> children)
263+
throws ProvisionException {
215264
List<IU> bestUnits = units;
216265
URI bestURI = null;
217266
//we now need to find a repository that has all units and they must have the same or higher version
@@ -223,8 +272,7 @@ private IMetadataRepository findBestLocation(UpdateTargetMojo context, List<IU>
223272
}
224273
}
225274
if (bestURI != null) {
226-
location.element().setAttribute("location", bestURI.toString());
227-
return repositoryManager.loadRepository(bestURI, null);
275+
return new MetadataRepositoryUpdate(bestURI, repositoryManager.loadRepository(bestURI, null));
228276
}
229277
return null;
230278
}
@@ -249,6 +297,13 @@ private static Collection<URI> getChildren(IMetadataRepository repository) {
249297
return List.of();
250298
}
251299

300+
private static boolean isCompatibleChange(VersionUpdate update, UpdateTargetMojo context) {
301+
if (update.isMajorChange() && !context.isAllowMajorUpdates()) {
302+
return false;
303+
}
304+
return true;
305+
}
306+
252307
private static Collection<URI> expandRepository(URI uri, IMetadataRepositoryManager repositoryManager)
253308
throws ProvisionException {
254309
IMetadataRepository repository = repositoryManager.loadRepository(uri, null);
@@ -326,6 +381,10 @@ public String getId() {
326381
return id();
327382
}
328383

384+
public void setLocation(URI uri) {
385+
element().setAttribute("location", uri.toString());
386+
}
387+
329388
}
330389

331390
private static record IU(String id, String version, Element element) {
@@ -409,4 +468,93 @@ private static Optional<URI> buildVersionString(int[] versions, String[] prefix,
409468
}
410469
}
411470

471+
private static void describeUpdate(VersionUpdate versionUpdate, MarkdownBuilder builder) {
472+
IInstallableUnit update = versionUpdate.update();
473+
builder.addListItem(String.format("Unit %s was updated from %s to %s", versionUpdate.id(),
474+
versionUpdate.getPreviousVersion(), update.getVersion()));
475+
IInstallableUnit current = versionUpdate.current();
476+
if (current != null) {
477+
Collection<IRequirement> currentRequirements = current.getRequirements();
478+
for (IRequirement requirement : update.getRequirements()) {
479+
if (!currentRequirements.contains(requirement) && requirement.getMin() > 0) {
480+
builder.addListItem2(
481+
String.format("additionally requires %s compared to the previous version", requirement));
482+
}
483+
}
484+
}
485+
}
486+
487+
private static record VersionUpdate(String id, String previousVersion, IInstallableUnit current,
488+
IInstallableUnit update) {
489+
490+
public boolean hasVersionChange() {
491+
if (EMPTY_VERSION.equals(previousVersion)) {
492+
return true;
493+
}
494+
if (current != null) {
495+
return !current.getVersion().equals(update.getVersion());
496+
}
497+
return !update.getVersion().toString().equals(previousVersion);
498+
}
499+
500+
public boolean isMajorChange() {
501+
var currentVersion = getOSGiVersion(current);
502+
var updateVersion = getOSGiVersion(update);
503+
if (isVersion(currentVersion) && isVersion(updateVersion)) {
504+
return updateVersion.getMajor() > currentVersion.getMajor();
505+
}
506+
return false;
507+
}
508+
509+
private boolean isVersion(org.osgi.framework.Version version) {
510+
return version != null && !org.osgi.framework.Version.emptyVersion.equals(version);
511+
}
512+
513+
public String getPreviousVersion() {
514+
if (current != null) {
515+
if (!current.getVersion().toString().equals(update.getVersion().toString())) {
516+
return current.getVersion().toString();
517+
}
518+
}
519+
return previousVersion;
520+
}
521+
522+
}
523+
524+
private static org.osgi.framework.Version getOSGiVersion(IInstallableUnit unit) {
525+
if (unit != null) {
526+
try {
527+
return org.osgi.framework.Version.parseVersion(unit.getVersion().toString());
528+
} catch (RuntimeException e) {
529+
//can't parse
530+
}
531+
}
532+
return null;
533+
}
534+
535+
private static record MetadataRepositoryUpdate(URI uri, IMetadataRepository update) {
536+
537+
public boolean updateLocation(ResolvedRepository element) {
538+
if (uri != null) {
539+
try {
540+
if (new URI(element.getLocation()).equals(uri)) {
541+
return false;
542+
}
543+
} catch (URISyntaxException e) {
544+
}
545+
element.setLocation(uri);
546+
return true;
547+
}
548+
return false;
549+
}
550+
551+
public boolean hasUpdate(URI other) {
552+
if (uri == null) {
553+
return false;
554+
}
555+
return !uri.equals(other);
556+
}
557+
558+
}
559+
412560
}

0 commit comments

Comments
 (0)