Skip to content

Commit 9f0ec9c

Browse files
committed
[F] Fix list orphan plugins
1 parent 285230a commit 9f0ec9c

File tree

1 file changed

+86
-0
lines changed

1 file changed

+86
-0
lines changed

src/main/java/org/hydev/mcpm/client/local/SuperLocalPluginTracker.java

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,4 +263,90 @@ public List<String> listManuallyInstalled() {
263263

264264
return Stream.concat(inLock, noLock).toList();
265265
}
266+
267+
/**
268+
* List installed plugins in an index map
269+
*
270+
* @return Index map (dict[name: plugin])
271+
*/
272+
private Map<String, PluginYml> mapInstalled() {
273+
return listInstalled().stream()
274+
.map(it -> new Pair<>(it.name(), it))
275+
.collect(Pair.toMap());
276+
}
277+
278+
/**
279+
* Get a list of automatically installed plugin dependencies that are no longer required
280+
*
281+
* @param considerSoftDependencies Whether to preserve soft dependencies (should be false)
282+
* @return List of plugins
283+
*/
284+
@Override
285+
public List<PluginYml> listOrphanPlugins(boolean considerSoftDependencies) {
286+
Map<String, PluginYml> installed = mapInstalled();
287+
List<String> manual = listManuallyInstalled();
288+
List<String> deps = new ArrayList<>();
289+
290+
// Get all the dependencies of the manually installed plugins
291+
for (String name : manual) {
292+
293+
// If the plugin is not in the local installed folder, skip it
294+
if (!installed.containsKey(name)) continue;
295+
296+
// Read plugin yml
297+
var p = installed.get(name);
298+
299+
// Add the dependencies of the plugin to the list of required dependencies
300+
if (p.depend() != null)
301+
deps.addAll(p.depend());
302+
303+
// If considerSoftDependencies is true, add the soft dependencies to the list of
304+
// required dependencies
305+
if (p.softdepend() != null && considerSoftDependencies)
306+
deps.addAll(p.softdepend());
307+
}
308+
309+
// Get the difference between the set of manually installed plugins,
310+
// the set of required dependencies, and the set of all installed plugins.
311+
return installed.values().stream()
312+
.filter(it -> !manual.contains(it.name()) && !deps.contains(it.name())).toList();
313+
}
314+
315+
/**
316+
* Get a list of plugin (as pluginYml) that are outdated
317+
*
318+
* @return List of plugin names
319+
*/
320+
@Override
321+
public List<PluginVersion> listOutdatedPlugins(Database database) {
322+
// Database plugins' latest versions
323+
var versions = database.plugins().stream().map(PluginModel::getLatestPluginVersion)
324+
.filter(Optional::isPresent).map(Optional::get).toList();
325+
326+
// Database index map by plugin ID
327+
var dbIdIndex = versions.stream().map(it -> new Pair<>(it.id(), it)).collect(Pair.toMap());
328+
329+
// Database index map by fuzzy identifier ("{name},{main}")
330+
var dbFuzzyIndex = versions.stream()
331+
.map(it -> new Pair<>(String.format("%s,%s", it.meta().name(), it.meta().main()), it))
332+
.collect(Pair.toMap());
333+
334+
var installed = listInstalled();
335+
var entries = mapLock();
336+
337+
// For plugins that have plugin id and version ids recorded:
338+
var outdatedEntries = entries.values().stream().filter(it -> dbIdIndex.containsKey(it.getPluginId()))
339+
.map(it -> new Pair<>(it, dbIdIndex.get(it.getPluginId())))
340+
.filter(it -> it.v() != null && it.v().id() > it.k().getVersionId())
341+
.map(Pair::v);
342+
343+
// For plugins that are installed through other means that don't have a plugin id recorded.
344+
// It requires an exact match of the plugin name + plugin main class
345+
var outdatedFuzzy = installed.stream().filter(it -> !entries.containsKey(it.name()))
346+
.map(it -> String.format("%s,%s", it.name(), it.main()))
347+
.filter(dbFuzzyIndex::containsKey)
348+
.map(dbFuzzyIndex::get);
349+
350+
return Stream.concat(outdatedFuzzy, outdatedEntries).toList();
351+
}
266352
}

0 commit comments

Comments
 (0)