Skip to content

#1695: Clone settings to temporary directory, analyse, and then move (taken over) - #2249

Open
laim2003 wants to merge 35 commits into
devonfw:mainfrom
laim2003:feature/1695-clone-settings-to-temp-dir-for-verification
Open

#1695: Clone settings to temporary directory, analyse, and then move (taken over)#2249
laim2003 wants to merge 35 commits into
devonfw:mainfrom
laim2003:feature/1695-clone-settings-to-temp-dir-for-verification

Conversation

@laim2003

@laim2003 laim2003 commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

This PR fixes #1695

Implemented changes:

  • When creating a new project, the settings or code repository is first cloned to a temporary location (at $IDE_ROOT/_ide/tmp/projects/<project name>) where it is analyzed for validity. We check whether an ide.properties file exist either at the top level or within a settings folder at the top level. Only if this passes, do we create a new project at $IDE_ROOT/<project name> and move the files from the temporary location to the final location. The temporary folder is fully deleted after this process.
  • Removed the --code option when creating a project. We now automatically determine if the repository is a code or settings repository and act accordingly.

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#

Note: In some places, I used getFileAccess() to copy and subsequently delete files. I am aware that there is a move function. However, this was always failing for some reason

areinicke and others added 29 commits April 27, 2026 13:16
…n' of https://github.com/areinicke/IDEasy into feature/1695-clone-settings-to-temp-dir-for-verification
Co-authored-by: Robin Wenzel <robin@die-wenzels.de>
…n' of https://github.com/areinicke/IDEasy into feature/1695-clone-settings-to-temp-dir-for-verification
@github-project-automation github-project-automation Bot moved this to 🆕 New in IDEasy board Aug 3, 2026
@laim2003 laim2003 moved this from 🆕 New to 🏗 In progress in IDEasy board Aug 3, 2026
@laim2003 laim2003 self-assigned this Aug 3, 2026
@laim2003 laim2003 added enhancement New feature or request settings ide-settings repo and replated processes and features git git version management tool integration create Create commandlet used to create new IDEasy projects with "ide create" labels Aug 3, 2026
@laim2003 laim2003 added this to the release:2026.08.001 milestone Aug 3, 2026
…verification

# Conflicts:
#	cli/src/test/java/com/devonfw/tools/ide/git/GitContextMock.java
…andlet

Signed-off-by: laim2003 <luk.faber@gmx.de>
Signed-off-by: laim2003 <luk.faber@gmx.de>
@laim2003
laim2003 force-pushed the feature/1695-clone-settings-to-temp-dir-for-verification branch from 48ef6c7 to 43ac0f2 Compare August 3, 2026 12:36
Signed-off-by: laim2003 <luk.faber@gmx.de>
Signed-off-by: laim2003 <luk.faber@gmx.de>
@laim2003 laim2003 moved this from 🏗 In progress to 👀 In review in IDEasy board Aug 3, 2026
@laim2003
laim2003 marked this pull request as ready for review August 3, 2026 12:57
@coveralls

Copy link
Copy Markdown
Collaborator

Coverage Report for CI Build 30815427594

Coverage decreased (-0.09%) to 72.518%

Details

  • Coverage decreased (-0.09%) from the base build.
  • Patch coverage: No coverable lines changed in this PR.
  • 40 coverage regressions across 4 files.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

40 previously-covered lines in 4 files lost coverage.

File Lines Losing Coverage Coverage
com/devonfw/tools/ide/commandlet/AbstractUpdateCommandlet.java 19 80.54%
com/devonfw/tools/ide/commandlet/CreateCommandlet.java 14 76.67%
com/devonfw/tools/ide/git/GitUrl.java 6 69.49%
com/devonfw/tools/ide/tool/ide/IdeToolCommandlet.java 1 78.69%

Coverage Stats

Coverage Status
Relevant Lines: 17248
Covered Lines: 13047
Line Coverage: 75.64%
Relevant Branches: 7623
Covered Branches: 4989
Branch Coverage: 65.45%
Branches in Coverage %: Yes
Coverage Strength: 3.21 hits per line

💛 - Coveralls

@laim2003
laim2003 requested a review from hohwille August 4, 2026 07:41

@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.

@laim2003 thank you very much for taking this PR over 👍
It seems to remain complicated.
I tried to make my PoV clear for how we should design this.
However, I also found a problem with that regarding a link that may potentially not be relative. IMHO we should discuss about this together. Maybe you first have a look and think it over. If you find a clean and easy solution we are fine - otherwise lets have a quick call.

Comment on lines +61 to +68
if (Files.exists(tempProjectPath)) {
throw new CliException(
String.format("Temporary project directory already exists in: %s. Please delete it and try again.", tempProjectPath));
} else if (Files.exists(newProjectPath)) {
throw new CliException(
String.format("Project directory already exists in: %s. As the project already exists, try calling 'ide update'.",
newProjectPath));
}

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.

To fail from the start if the final location (newProjectPath) already exists, make somehow sense.
However, keep in mind that before this PR the user got a warning and was asked if he wants to continue.
IMHO this new approach is also valid and we can skip the old behaviour.
This also makes it easier since before that was easy possible since we were adding files to the final project directory and now we create a new project in tmp and finally move it - so if the final project director already exists moving would not work...

However, regarding the existence of tempProjectPath I would simply use FileAccess.backup to get rid of it without further notice. This is in a temp directory so we should not fail, lets just get rid of it and start from scratch or do you fear that the same user by accident is calling two ide create commands for the same project? That would IMHO be stupidity of the end-user...

Comment on lines 71 to 72
if (!this.context.getFileAccess().isEmptyDir(newProjectPath)) {
this.context.askToContinue("Directory {} already exists. Do you want to continue?", newProjectPath);

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.

If you throw an exception for this above this does not make sense any more.

initializeProject(tempProjectPath);
this.context.setIdeHome(tempProjectPath);
super.doRun();
this.context.getFileAccess().writeFileContent(IdeVersion.getVersionString(), newProjectPath.resolve(IdeContext.FILE_SOFTWARE_VERSION));

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.

Here I would expect the move from tempProjectPath to newProjectPath.

* either be a settings repository (with ide.properties or devon.properties on the top level) or a code repository (with a settings folder on the top level
* containing such a file). Otherwise, the project creation fails and an error message is logged.
*/
private void analyzeProject() {

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 method name is odd: As described in JavaDoc and what can be seen in the implementation, it does not "analyse the project" but "analyse the settings and potentially restructure them".
I would not expect a method with this name to do changes as side effect.
I would suggest to rename it to analyzeAndRestructureSettings().
Also this method should be moved to AbstractUpdateCommandlet since also the ide update command can repair the project so if settings folder is missing, it will ask for settings URL and clone the settings again. In that case we should invoke the same logic.

This method should however only move and restructure the settings to follow SoC and NOT move the entire project what IMHO belongs to doRun method that already has the tempProjectPath and newProjectPath variables and the responsibility of handling the tmp creation (and therefore also the according cleanup).

LOG.info(EnvironmentVariables.DEFAULT_PROPERTIES + " or " + EnvironmentVariables.LEGACY_PROPERTIES
+ " found in settings subfolder. This indicates a code repository with a settings folder on the top level.");

String gitProjectName = GitUrl.of(this.settingsRepo.getValue(0)).getProjectName();

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.

Indexed access shall only be used for multi-valued properties.

Suggested change
String gitProjectName = GitUrl.of(this.settingsRepo.getValue(0)).getProjectName();
String gitProjectName = GitUrl.of(this.settingsRepo.getValue()).getProjectName();

moveProject(this.context.getIdeHome(), actualProjectPath);

// Move settings fodler containing code to $IDE_ROOT/<project_name>/workspaces/main/<git_project_name>
moveProject(actualProjectPath.resolve(IdeContext.FOLDER_SETTINGS), codeFolderPath);

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.

The settings are not a project.
Hence the method moveProject is named wrong.

Comment on lines +152 to +160
private void moveProject(Path oldPath, Path newPath) {
FileAccess fileAccess = this.context.getFileAccess();
try {
fileAccess.mkdirs(newPath);
fileAccess.move(oldPath, newPath, StandardCopyOption.REPLACE_EXISTING);
} catch (Exception e) {
LOG.error("Failed to move project from {} to {}. Please move it manually.", oldPath, newPath, e);
}
}

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.

I do not understand the purpose of this method at all.

  1. Why do we do an mkdirs to the target directory if we replace it anyways? Is that because the parent directory may not exist? Shouldn't this be handled by FileAccess.move then?
  2. REPLACE_EXISTING sounds dangerous to me. Do we really want to delete a target project that may have been created in projects folder with the same name concurrently?
  3. The exception handling is crazy: If the move failed we log and error and continue reporting the project creation was successful what is a lie and the implicit icd to navigate to the newly created project will then fail? This is nuts.
  4. So if we do nothing else in the end then calling FileAccess.move why do we need a private method for that?I would simply remove this method.

this.context.setIdeHome(actualProjectPath);

// Link settings folder in IDE_HOME to settings folder in code repository
fileAccess.symlink(codeFolderPath.resolve(IdeContext.FOLDER_SETTINGS), actualProjectPath.resolve(IdeContext.FOLDER_SETTINGS));

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.

Just one thought that I may have missed and that @areinicke never told me.
Is it possible that he did the moving of the project itself before this on purpose?
Assuming we are on Windows and we do not have permissions for proper symlinks, we will fallback to a junction - then IMHO this cannot be created relative.
In that case, we would create an absolute link here and following my review comments about SoC the resulting project would be broken if we move from tmp to projects after creating this absolute link.
Is that thought correct? Do we have a clean solution for this?
We have to keep in mind that we also need to solve and reuse this for the ide update command.
In the original PR we wanted to keep things simpler and after the massive review ping pongs and reworks, we decided to implement this in another go.
However, at least the design should keep that in mind.
Maybe it will not work out, if we do not implement and test these 2 aspects together...

Comment thread CHANGELOG.adoc
* https://github.com/devonfw/IDEasy/issues/1788[#1788]: Add Commandlet to create links
* https://github.com/devonfw/IDEasy/issues/797[#797]: Use system unzip on macOS to preserve symlinks in ZIP extraction
* https://github.com/devonfw/IDEasy/issues/1723[#1723]: Add commandlet for GitHub Copilot CLI
* https://github.com/devonfw/IDEasy/issues/1695[#1695]: Clone settings to temporary directory, analyse, and then move

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.

Please move up

@laim2003

laim2003 commented Aug 4, 2026

Copy link
Copy Markdown
Contributor Author

@laim2003 thank you very much for taking this PR over 👍 It seems to remain complicated. I tried to make my PoV clear for how we should design this. However, I also found a problem with that regarding a link that may potentially not be relative. IMHO we should discuss about this together. Maybe you first have a look and think it over. If you find a clean and easy solution we are fine - otherwise lets have a quick call.

In my opinion, it is better if I complete the other tasks that I have open for the next release first, as in the MacOS installer, the console, the snapshot fix for the GUI. I can see that there is still a lot of structural points open in this PR here 🙂, therefore I believe it makes sense that I take some more time to deeply analyze the issues that we have here, especially since I need to dive deeper into understanding the requirements for this PR. If I am able to work on this issue before the next release, I will try to do that and then let you know about a call if I need help!

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

Labels

create Create commandlet used to create new IDEasy projects with "ide create" enhancement New feature or request git git version management tool integration settings ide-settings repo and replated processes and features

Projects

Status: 👀 In review

Development

Successfully merging this pull request may close these issues.

Clone settings to temporary directory, analyse, and then move

4 participants