Skip to content

#1953: Complete cleanup commandlet implementation and review handoverShow more lines - #2230

Open
Caylipp wants to merge 42 commits into
devonfw:mainfrom
Caylipp:feature/1953-cleanup-commandlet-handover
Open

#1953: Complete cleanup commandlet implementation and review handoverShow more lines#2230
Caylipp wants to merge 42 commits into
devonfw:mainfrom
Caylipp:feature/1953-cleanup-commandlet-handover

Conversation

@Caylipp

@Caylipp Caylipp commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

This PR fixes #1953

This PR completes and supersedes #1957 after the original author left the team.

Implemented changes:

  • Reused the existing global -f / --force mode instead of introducing a cleanup-specific force option.
  • Removed the obsolete --force-delete help entries.
  • Kept cleanup discovery stateless by creating the discovered-tool list locally for each execution.
  • Moved the cleanup model into reusable top-level classes in the lowercase commandlet.cleanup package.
  • Scanned all repositories below _ide/software, including default, maven, and custom repository IDs.
  • Matched project software references against resolved installation paths instead of relying on fixed path positions.
  • Supported project links to subdirectories of an installation, such as Contents/MacOS.
  • Supported the following software link structures:
    • software/<tool>
    • software/extra/<tool>
    • software/extra/<tool>/<name>
  • Stored project usage only on the concrete tool edition version.
  • Derived the unused state of editions and tools from their child versions.
  • Improved JavaDoc for the cleanup model and its properties.

Testing instructions

Please add conscise, understandable instructions on how a reviewer can test/verify the functionality of your contribution here:

  1. mvn -pl cli -Dtest=CleanupCommandletTest test
  2. mvn clean test

Related

Checklist for this PR

Make sure everything is checked before merging this PR. For further info please also see
our DoD.

  • When running mvn clean test locally all tests pass and build is successful
  • PR title is of the form #«issue-id»: «brief summary» (e.g. #921: fixed setup.bat). If no issue ID exists, title only.
  • PR top-level comment summarizes what has been done and contains link to addressed issue(s)
  • PR and issue(s) have suitable labels
  • Issue is set to In Progress and assigned to you or there is no issue (might happen for very small PRs)
  • You followed all coding conventions
  • You have added the issue implemented by your PR in CHANGELOG.adoc unless issue is labeled
    with internal
  • You have formulated clear instructions on how to test your contribution under "Testing instructions"

Checklist for tool commandlets

Have you added a new «tool» as commandlet? There are the following additional checks:

  • The tool can be installed automatically (during setup via settings) or via the commandlet call
  • The tool is isolated in its IDEasy project, see Sandbox Principle
  • The new tool is added to the table of tools in LICENSE.asciidoc
  • The new commandlet is a command-wrapper for «tool»
  • Proper help texts for all supported languages are added here
  • The new commandlet installs potential dependencies automatically
  • The variables «TOOL»_VERSION and «TOOL»_EDITION are honored by your commandlet
  • The new commandlet is tested on all platforms it is available for or tested on all platforms that are in scope of the linked issue

areinicke and others added 29 commits May 15, 2026 16:05
- scan all global software repositories
- detect used versions by resolved installation paths
- support links to installation subfolders and nested extra tools
- make cleanup discovery stateless
- track project usage only on version level
- reuse the global force mode for confirmation
- add regression tests for used and unused installations
@github-project-automation github-project-automation Bot moved this to 🆕 New in IDEasy board Jul 29, 2026
@Caylipp Caylipp self-assigned this Jul 29, 2026
@Caylipp Caylipp moved this from 🆕 New to Team Review in IDEasy board Jul 29, 2026
@Caylipp Caylipp moved this from Team Review to 👀 In review in IDEasy board Jul 29, 2026
@Caylipp Caylipp moved this from 👀 In review to Team Review in IDEasy board Jul 29, 2026
@Caylipp Caylipp added commandlet ide sub-command enhancement New feature or request labels Jul 29, 2026
@coveralls

coveralls commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator

Coverage Report for CI Build 30885837220

Warning

Build has drifted: This PR's base is out of sync with its target branch, so coverage data may include unrelated changes.
Quick fix: rebase this PR. Learn more →

Coverage increased (+0.2%) to 72.825%

Details

  • Coverage increased (+0.2%) from the base build.
  • Patch coverage: No coverable lines changed in this PR.
  • 125 coverage regressions across 10 files.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

125 previously-covered lines in 10 files lost coverage.

File Lines Losing Coverage Coverage
com/devonfw/tools/ide/tool/LocalToolCommandlet.java 38 80.24%
com/devonfw/tools/ide/tool/ToolCommandlet.java 27 73.99%
com/devonfw/tools/ide/tool/ToolInstallRequest.java 18 71.88%
com/devonfw/tools/ide/context/IdeContext.java 17 77.46%
com/devonfw/tools/ide/tool/gui/Gui.java 8 19.23%
com/devonfw/tools/ide/commandlet/CommandletManagerImpl.java 7 91.94%
com/devonfw/tools/ide/tool/uv/UvBasedCommandlet.java 4 82.93%
com/devonfw/ide/gui/context/ProjectManager.java 3 86.67%
com/devonfw/tools/ide/tool/soapui/SoapUi.java 2 62.5%
com/devonfw/tools/ide/tool/ide/IdeToolCommandlet.java 1 78.69%

Coverage Stats

Coverage Status
Relevant Lines: 17434
Covered Lines: 13242
Line Coverage: 75.96%
Relevant Branches: 7725
Covered Branches: 5080
Branch Coverage: 65.76%
Branches in Coverage %: Yes
Coverage Strength: 3.23 hits per line

💛 - Coveralls

@quando632 quando632 self-assigned this Jul 29, 2026

@hohwille hohwille left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are closing the finishing line 👍
Still I found some points...

Comment thread cli/src/main/java/com/devonfw/tools/ide/commandlet/cleanup/CleanupIdeTool.java Outdated
Comment thread cli/src/main/java/com/devonfw/tools/ide/commandlet/cleanup/CleanupCommandlet.java Outdated
Comment thread cli/src/main/java/com/devonfw/tools/ide/commandlet/cleanup/CleanupCommandlet.java Outdated
Comment thread cli/src/main/java/com/devonfw/tools/ide/commandlet/cleanup/CleanupCommandlet.java Outdated
Comment thread cli/src/main/java/com/devonfw/tools/ide/commandlet/cleanup/CleanupCommandlet.java Outdated

@quando632 quando632 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for picking this up the substance of the #1957 review is addressed and the new tests cover exactly the cases that were requested there. I went through the branch and found a few points before this can go in, three of them blocking from my side:

  • the new tests error out on Windows without symlink privileges (verified locally, 3 of 4 tests)
  • the CHANGELOG entry landed in an already released section
  • the confirmation cannot actually be skipped with -f alone

The remaining ones are smaller correctness and consistency points. I left out anything already covered by the review above (common super class for the model classes, delete flag only on version level, central findProjects()).

Comment thread CHANGELOG.adoc Outdated
Comment thread cli/src/main/resources/nls/Help.properties Outdated
Comment thread cli/src/main/java/com/devonfw/tools/ide/commandlet/cleanup/CleanupCommandlet.java Outdated
Comment thread cli/src/main/java/com/devonfw/tools/ide/commandlet/cleanup/CleanupCommandlet.java Outdated
Caylipp and others added 7 commits July 30, 2026 14:02
- add common abstract base class for installed software items
- centralize software item name and path
- rename cleanup model classes for reuse
- keep deletion state only on software versions
- delete unused versions before empty parent folders
- remove redundant deletion state from tools and editions
- add reusable project discovery to IdeContext
- exclude non project folders centrally
- reuse project discovery in cleanup and GUI
- scan default, Maven, and configured custom repositories explicitly
- update cleanup test for the configured custom repository
Co-authored-by: quando632 <quang-hieu.do@capgemini.com>
- add better help message
- propagate user cancellation through the standard abort handling
- correct software discovery variable names
- report affected tools and editions accurately
- cover batch force mode and Windows symlink restrictions
- adjust CHANGELOG.adoc entry

@quando632 quando632 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All eight points from my previous review are addressed on dc95fdea. mvn -Dtest=CleanupCommandletTest test is green (5 tests, 3 skipped for missing symlink privileges), and checkstyle and spotless report no violations in the new files. Solving the counter problem by reporting "affected" tools and editions is nicer than what I suggested.

Two issues came out of the changes themselves, one of them blocking. Both only appear when the individual fixes are combined, so they are not visible in any single change.

Comment thread cli/src/main/java/com/devonfw/tools/ide/commandlet/cleanup/CleanupCommandlet.java Outdated
Comment thread cli/src/main/java/com/devonfw/tools/ide/commandlet/cleanup/CleanupCommandlet.java Outdated
Comment thread cli/src/main/java/com/devonfw/tools/ide/commandlet/cleanup/CleanupCommandlet.java Outdated
@Caylipp Caylipp moved this from Team Review to 👀 In review in IDEasy board Aug 4, 2026

@hohwille hohwille left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Caylipp thanks for taking up this story and PR. 👍
I still have suggestions for improvement.
I hope you can address them tomorrow and I can merge the next day what would be awesome.
If you are running out of time, you may skip some "nice to haves" and I will create a cleanup issue and merge then. Thanks.

for (Path ideasyProject : ideasyProjects) {
String projectName = ideasyProject.getFileName().toString();
Path ideasyProjectSoftware = ideasyProject.resolve(IdeContext.FOLDER_SOFTWARE);
discoverUsedSoftware(installedSoftwareTools, ideasyProjectSoftware, projectName);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skip pointless recursion here?

Suggested change
discoverUsedSoftware(installedSoftwareTools, ideasyProjectSoftware, projectName);
discoverUsedSoftware(installedSoftwareTools, ideasyProjectSoftware, projectName, 1);

Comment on lines +217 to +227
for (InstalledSoftwareTool tool : installedSoftwareTools) {
for (InstalledSoftwareEdition edition : tool.getEditions()) {
for (InstalledSoftwareVersion version : edition.getVersions()) {
Path versionPath = version.getPath();
if (referencedPath.equals(versionPath) || referencedPath.startsWith(versionPath)) {
version.addUsedBy(projectName);
return true;
}
}
}
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So for complexity we do this

  • for every M projects
  • for every N software folders in project
  • for every O installed tools
  • for every P installed editions per tool
  • for every Q versions per tool-edition

Looks quite inefficient to me.
Our data structure with InstalledSoftwareTool, -Edition, and -Version could be smarter having an internal Map from the versionPath to the InstalledSoftwareVersion populated when the data gets added (what should always happen via methods to make it possible to keep states consistent rather than simply doing get«SomeCollection»().add(...).
Then you have O(1) here instead of O(O*P*Q).

Comment on lines +47 to +53
public void addUsedBy(String projectName) {

if (!this.usedBy.contains(projectName)) {
this.usedBy.add(projectName);
}
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is also odd design. What you want to archive here is exactly provided by a Set instead of a List.
This not only allows you to skip the if but also to make it more efficient since adding or contains check on Set is highly efficient unlike contains on List.

BTW: I just looked again into story #1580 where I wrote:

a Set with the IDEasy projects using this tool+edition+version. If empty, then it can be deleted.

Actually this is never used so we could also entirely omit it and just have deleted initialized with true in constructor and setting it to false whenever we find a project using it.
However, I think I suggested this design on purpose so we can later reuse this data structure in the GUI and show the end user a graphical tree where he can even see which projects are using what, etc.
So just change to Set and keep it.

Comment on lines +57 to +62
step.run(() -> discoverAndReportUnusedSoftware(installedSoftwareTools), true);

if (hasSoftwareToDelete(installedSoftwareTools)) {
// Automatically confirmed in batch mode with the global force option.
this.context.askToContinue("Do you want to continue?");
deleteUnusedSoftware(installedSoftwareTools);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reading this gives me some puzzle in my head:
If there is a question Do you want to continue? where is the information logged so I can answer this question?
Fortunately hasSoftwareToDelete has no side effect and from the naming we can see it is done in discoverAndReportUnusedSoftware.
However, wouldn't it make more sense to move logSoftwareToBeDeleted(installedSoftwareTools) out of discoverAndReportUnusedSoftware renaming it to just discoverUnusedSoftware and then before the if explicitly invoke the logging/reporting method?

I know this is just nice to have but I would better understand such code then...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

commandlet ide sub-command enhancement New feature or request

Projects

Status: 👀 In review

Development

Successfully merging this pull request may close these issues.

Implement Base Functionality of Cleanup Commandlet

6 participants