#2372: Add --retention-delay option to ide cleanup - #2378
#2372: Add --retention-delay option to ide cleanup#2378krystynaShatkovska wants to merge 2 commits into
Conversation
Adds a --retention-delay option to the cleanup commandlet to delete stale files that have not been modified within a configurable period. Files are scanned recursively under $IDE_HOME/updates, $IDE_ROOT/_ide/tmp and ~/Downloads/ide. The option accepts a time-based ISO-8601 duration (e.g. P30D) and defaults to 1 year (365 days) if not provided. Empty folders left behind after deleting stale files are removed, while the scanned roots themselves are kept.
Coverage Report for CI Build 33050346294Coverage increased (+0.07%) to 73.694%Details
Uncovered ChangesNo uncovered changes found. Coverage Regressions10 previously-covered lines in 2 files lost coverage.
Coverage Stats💛 - Coveralls |
samuelkos17
left a comment
There was a problem hiding this comment.
Thanks for adding the --retention-dely to the cleanup commandlet. I tried to follow your testing steps, however the commands you provided didn't work out for me. I've manually moved the files to /_ide/tmp though and then ran the cleanup command and it worked!
While reviewing I found some problems that could lead to issues and that really need to get addressed before moving this to In Review. You can find them in the Comments here.
Besides that I still have on recommendation:
documentation/tmp.adoc line 18 needs to be updated according to the new functionality.
| private Duration getRetentionDelay() { | ||
|
|
||
| String value = this.retentionDelay.getValueAsString(); | ||
| if (value == null) { | ||
| return DEFAULT_RETENTION_DELAY; | ||
| } | ||
| try { | ||
| return Duration.parse(value); | ||
| } catch (DateTimeParseException e) { | ||
| throw new CliException( | ||
| "Invalid value '" + value + "' for --retention-delay. Please provide a time-based ISO-8601 duration such as P30D or PT2H30M.", | ||
| e); | ||
| } | ||
| } |
There was a problem hiding this comment.
Duration.parse() legally accepts negative and zero values. This means it won't throw the CliException and later down the line in isStale() every file under all roots becomes stale, which leads to every file being deleted. You should add a positivity check here.
| private void discoverStaleFilesRecursive(Path folder, Duration retentionDelay, List<Path> staleFiles) { | ||
|
|
||
| if (!Files.isDirectory(folder)) { | ||
| return; | ||
| } | ||
|
|
||
| for (Path child : this.context.getFileAccess().listChildren(folder, child -> true)) { | ||
| if (Files.isDirectory(child)) { | ||
| discoverStaleFilesRecursive(child, retentionDelay, staleFiles); | ||
| } else if (isStale(child, retentionDelay)) { | ||
| staleFiles.add(child); | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Files.isDirectory(child) follows links. If a symlink inside any root (e.g. ~/Downloads/ide/work -> C:\data) makes the scan descend outside the roots and delete the target's stale files, which would be a huge problem. Furthermore a self-referencing link causes unbounded recursion. You need to check for link children here and skip these.
| cmd.cleanup=Commandlet to clean up the IDEasy installation by uninstalling all unused tools. | ||
| cmd.cleanup.detail=This will remove any installed tools that are currently not in use by an IDEasy project. Before anything is deleted you are asked for confirmation. Run "ide -b -f cleanup" to skip the confirmation. |
There was a problem hiding this comment.
This needs to be updated to match the new functionality.
| cmd.cleanup=Werkzeug zum Aufräumen der IDEasy-Installation durch Deinstallieren aller ungenutzten Werkzeuge. | ||
| cmd.cleanup.detail=Dies wird alle installierten Werkzeuge entfernen, die derzeit von keinem IDEasy-Projekt verwendet werden. Bevor etwas gelöscht wird, wirst du um Bestätigung gebeten. Führe "ide -b -f cleanup" aus, um die Bestätigung zu überspringen. |
There was a problem hiding this comment.
This needs to be updated to match the new functionality.
| cmd.claude.detail=Claude Code CLI ist ein KI-gestützter Programmierassistent, der über die Befehlszeile ausgeführt wird. Detaillierte Dokumentation ist zu finden unter https://code.claude.com/docs/de/overview | ||
| cmd.cleanup=Werkzeug zum Aufräumen der IDEasy-Installation durch Deinstallieren aller ungenutzten Werkzeuge. | ||
| cmd.cleanup.detail=Dies wird alle installierten Werkzeuge entfernen, die derzeit von keinem IDEasy-Projekt verwendet werden. Bevor etwas gelöscht wird, wirst du um Bestätigung gebeten. Führe "ide -b -f cleanup" aus, um die Bestätigung zu überspringen. | ||
| cmd.cleanup.opt.--retention-delay=die Aufbewahrungsdauer von Dateien in den Ordnern 'updates', '_ide/tmp' und 'Downloads/ide', d.h. Dateien, die innerhalb dieses Zeitraums nicht modifiziert wurden, werden als veraltet gelöscht. Eine zeitbasierte ISO-8601-Dauer (z. B. 'P30D' für 30 Tage oder 'PT2H30M' für 2 Stunden und 30 Minuten). Standardmäßig 1 Jahr (365 Tage), wenn nicht angegeben. |
There was a problem hiding this comment.
| cmd.cleanup.opt.--retention-delay=die Aufbewahrungsdauer von Dateien in den Ordnern 'updates', '_ide/tmp' und 'Downloads/ide', d.h. Dateien, die innerhalb dieses Zeitraums nicht modifiziert wurden, werden als veraltet gelöscht. Eine zeitbasierte ISO-8601-Dauer (z. B. 'P30D' für 30 Tage oder 'PT2H30M' für 2 Stunden und 30 Minuten). Standardmäßig 1 Jahr (365 Tage), wenn nicht angegeben. | |
| cmd.cleanup.opt.--retention-delay=Die Altersgrenze von Dateien in den Ordnern 'updates', '_ide/tmp' und 'Downloads/ide', d.h. Dateien, die innerhalb dieses Zeitraums nicht modifiziert wurden, werden als veraltet gelöscht. Eine zeitbasierte ISO-8601-Dauer (z. B. 'P30D' für 30 Tage oder 'PT2H30M' für 2 Stunden und 30 Minuten). Standardmäßig 1 Jahr (365 Tage), wenn nicht angegeben. |
Furthermore the folders you mention here are correct for Windows and Linux, however on macOS there are somewhere else, maybe just remove the path descriptions and describe the folders?
| if (hasSoftwareToDelete(installedSoftware.getTools())) { | ||
| List<Path> staleRoots = new ArrayList<>(); | ||
| List<Path> staleFiles = new ArrayList<>(); | ||
| if (this.context.getIdeHome() != null) { |
There was a problem hiding this comment.
This if-guard prevents any clean-up from happening, however _ide/tmp and the download cache cleanup would work when IDE_HOME is null. I'm not sure if this intentional, but you might want to change that if it's not.
| cmd.claude.detail=Claude Code CLI is a command-line interface for interacting with the Claude AI assistant. Detailed documentation can be found at https://code.claude.com/docs/en/overview | ||
| cmd.cleanup=Commandlet to clean up the IDEasy installation by uninstalling all unused tools. | ||
| cmd.cleanup.detail=This will remove any installed tools that are currently not in use by an IDEasy project. Before anything is deleted you are asked for confirmation. Run "ide -b -f cleanup" to skip the confirmation. | ||
| cmd.cleanup.opt.--retention-delay=the retention period of files in the 'updates', '_ide/tmp' and 'Downloads/ide' folders, i.e. files that were not modified within this period are deleted as stale. A time-based ISO-8601 duration (e.g. 'P30D' for 30 days or 'PT2H30M' for 2 hours and 30 minutes). Defaults to 1 year (365 days) if not provided. |
There was a problem hiding this comment.
| cmd.cleanup.opt.--retention-delay=the retention period of files in the 'updates', '_ide/tmp' and 'Downloads/ide' folders, i.e. files that were not modified within this period are deleted as stale. A time-based ISO-8601 duration (e.g. 'P30D' for 30 days or 'PT2H30M' for 2 hours and 30 minutes). Defaults to 1 year (365 days) if not provided. | |
| cmd.cleanup.opt.--retention-delay=The retention period of files in the 'updates', '_ide/tmp' and 'Downloads/ide' folders, i.e. files that were not modified within this period are deleted as stale. A time-based ISO-8601 duration (e.g. 'P30D' for 30 days or 'PT2H30M' for 2 hours and 30 minutes). Defaults to 1 year (365 days) if not provided. |
Furthermore the folders you mention here are correct for Windows and Linux, however on macOS there are somewhere else, maybe just remove the path descriptions and describe the folders?
| @@ -1,16 +1,22 @@ | |||
| package com.devonfw.tools.ide.commandlet; | |||
|
|
|||
| import static org.assertj.core.api.Assertions.assertThatThrownBy; | |||
There was a problem hiding this comment.
| import static org.assertj.core.api.Assertions.assertThatThrownBy; |
dead code
|
|
||
| LOG.debug("Start cleanup commandlet"); | ||
|
|
||
| Duration retentionDelay = getRetentionDelay(); |
There was a problem hiding this comment.
You might want to rename this since you already have a StringProperty called retentionDelay in the class.
| private void logStaleFilesToBeDeleted(List<Path> staleFiles, Duration retentionDelay) { | ||
|
|
||
| if (staleFiles.isEmpty()) { | ||
| LOG.info("No stale files older than {} will be deleted.", retentionDelay); | ||
| } else { | ||
| for (Path staleFile : staleFiles) { | ||
| LOG.info("\t - {} will be deleted", staleFile); | ||
| } | ||
| LOG.info("Summary: {} stale file(s) older than {} will be deleted.", staleFiles.size(), retentionDelay); | ||
| } | ||
| } |
There was a problem hiding this comment.
You might want to format the duration human-readably.
This PR fixes #2372
Implemented changes:
Adds a --retention-delay option to ide cleanup. It takes an ISO-8601 duration (e.g. P30D, PT2H30M; default 1 year) and deletes stale files (not modified within that period) in $IDE_HOME/updates, $IDE_ROOT/_ide/tmp and ~/Downloads/ide. After deletion it deletes empty folders (but keeps the scanned roots). Invalid durations are rejected with a clear error.
Testing instructions
Automated tests
Run the test class; it covers all the core cases:
mvn -pl cli test -Dtest=CleanupCommandletTest
Manual test
a.Create a test file in each scanned folder and backdate it so it's older than your retention delay:
(create a "stale" file older than 30 days)
New-Item -Path "$IDE_HOME\updates\stale.bin" -Value "x" -Force
(Get-Item "$IDE_HOME\updates\stale.bin").LastWriteTime = (Get-Date).AddDays(-31)
b Run cleanup with a retention delay shorter than the file's age:
ide cleanup --retention-delay=P30D
Confirm the stale file is gone, and that a recent file in the same folder is kept:
Test-Path "$IDE_HOME/updates/stale.bin" (expected: False)
Verify invalid input is rejected:
ide cleanup --retention-delay=PT6M10D
Checklist for this PR
Make sure everything is checked before merging this PR. For further info please also see
our DoD.
mvn clean testlocally all tests pass and build is successful#«issue-id»: «brief summary»(e.g.#921: fixed setup.batand notfeature/921 fixed setup.bat). If no issue ID exists, title only.In Progressand assigned to you or there is no issue (might happen for very small PRs)with
internalpom.xmlfiles or otherwise if runtime dependencies changed, you have updated our LICENSE.asciidoc