Skip to content

#797: zip symlink pure java#1995

Open
shodiBoy1 wants to merge 7 commits into
devonfw:mainfrom
shodiBoy1:feature/797-zip-symlink-pure-java
Open

#797: zip symlink pure java#1995
shodiBoy1 wants to merge 7 commits into
devonfw:mainfrom
shodiBoy1:feature/797-zip-symlink-pure-java

Conversation

@shodiBoy1
Copy link
Copy Markdown
Contributor

@shodiBoy1 shodiBoy1 commented Jun 1, 2026

This PR fixes #797: fix VSCode install on macOS

Implemented changes:

  • On macOS, installing VSCode was failing because the ZIP extractor could not handle .framework folders. These folders use symlinks that point to other symlinks (a chain). The old code tried to resolve the full path of each symlink before creating it, which fails when the next symlink in the chain does not exist yet.
  • New behavior: write each symlink with the exact text from the ZIP, the same way unzip does. No path resolution, no existence check. The chain just works once all files are on disk.

Testing instructions

  1. Check out the PR:
    gh pr checkout 1995

  2. Run on a Mac:

  • Open the project in IntelliJ.
  • go to 'com.devonfw.tools.ide.cli.Ideasy' -> Modify Run Configuration.
  • Program arguments: vscode
  • Working directory: any empty folder (e.g. ~/test-ideasy).
  • Click Run.

Checklist for this PR

  • 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"

@github-project-automation github-project-automation Bot moved this to 🆕 New in IDEasy board Jun 1, 2026
@shodiBoy1 shodiBoy1 self-assigned this Jun 1, 2026
@shodiBoy1 shodiBoy1 added unpack logic to unpack archives (tar, zip, tgz, zbz2, msi, dmg, etc.) link symlinks and windows junctions labels Jun 1, 2026
@coveralls
Copy link
Copy Markdown
Collaborator

coveralls commented Jun 1, 2026

Coverage Report for CI Build 26784560341

Coverage decreased (-0.02%) to 71.074%

Details

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

Uncovered Changes

No uncovered changes found.

Coverage Regressions

198 previously-covered lines in 2 files lost coverage.

File Lines Losing Coverage Coverage
com/devonfw/tools/ide/io/FileAccessImpl.java 197 67.72%
com/devonfw/tools/ide/version/VersionSegment.java 1 89.76%

Coverage Stats

Coverage Status
Relevant Lines: 15793
Covered Lines: 11711
Line Coverage: 74.15%
Relevant Branches: 7038
Covered Branches: 4516
Branch Coverage: 64.17%
Branches in Coverage %: Yes
Coverage Strength: 3.14 hits per line

💛 - Coveralls

@shodiBoy1 shodiBoy1 marked this pull request as ready for review June 1, 2026 21:58
@shodiBoy1 shodiBoy1 moved this from 🆕 New to Team Review in IDEasy board Jun 1, 2026
@hohwille hohwille changed the title Feature/797 zip symlink pure java #797: zip symlink pure java Jun 3, 2026
Copy link
Copy Markdown
Member

@hohwille hohwille left a comment

Choose a reason for hiding this comment

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

@shodiBoy1 thanks for your PR and your analysis of the root cause. I like that you always take such special problem and analyse it properly trying to come up with a rather small fixing PR👍
Surely we could merge this as is as a quickfix.
However, you revealed here that we have actually implemented our link function wrong (and therefore our "unpack" functions - not only for zip but also for tar).
IMHO your PR is not fixing that bug but adding a workaround with quite some redundancies.

My goal is that we aim for true quality so I would love to fix the link function properly.
Can you maybe extract a JUnit test that reproduces the scenario with invoking our link function?
BTW: We meanwhile also have ide ln -s <source> <link> to test such things. If you want to test with relative being true you can do ide ln -s -r <source> <link>.
If that is buggy, please lets fix the root cause.


final List<PathLink> links = new ArrayList<>();
// link path -> raw target string from the archive; LinkedHashMap keeps entry order for deterministic creation
final Map<Path, String> symlinks = new LinkedHashMap<>();
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.

what is wrong with PathLink object?
I am not getting why you decided not to use it anymore?
IMHO it is still containing the same information in a slightly more structured way.

Comment on lines +801 to +806
// for a symlink entry the file content IS the link target string (Unix zip convention)
String linkTarget = IOUtils.toString(entryStream, StandardCharsets.UTF_8);
Path parent = entryPath.getParent();
Path source = parent.resolve(linkTarget).normalize();
resolveRelativePathSecure(source, root, linkTarget);
links.add(new PathLink(source, entryPath, PathLinkType.SYMBOLIC_LINK));
mkdirs(parent);
// security: refuse archives whose link would resolve outside the extraction root
resolveRelativePathSecure(entryPath.getParent().resolve(linkTarget).normalize(), root, linkTarget);
mkdirs(entryPath.getParent());
symlinks.put(entryPath, linkTarget);
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.

Still I cannot see a reason for this change. Still the same thing is happening here.

Comment on lines +823 to +836
Path linkPath = link.getKey();
String rawTarget = link.getValue();
Files.deleteIfExists(linkPath);
try {
Files.createSymbolicLink(linkPath, Path.of(rawTarget));
} catch (FileSystemException e) {
// on Windows without symlink permission fall back to a junction, same as link() does
if (SystemInfoImpl.INSTANCE.isWindows()) {
Path absoluteSource = linkPath.getParent().resolve(rawTarget).normalize();
mklinkOnWindows(Path.of(rawTarget), absoluteSource, linkPath, PathLinkType.SYMBOLIC_LINK, true);
} else {
throw 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.

you are slightly reimplementing our link function here.
Could the entire fix instead be to simply change true to false here, what would also fix the same bug in "untar" (that we might not yet have discovered)?

default void link(PathLink link) {
link(link.source(), link.link(), true, link.type());
}

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.

OK, seems that there is another "bug" in our link implementation:

public void link(Path source, Path link, boolean relative, PathLinkType type) {
Path finalLink = link.toAbsolutePath().normalize();

This was introduced in commit 083a35d.

My goal is still to get our link and "unpack" methods finally fixed.
IMHO that change was wrong.

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 relative is false, then why should our link function fiddle around with any of the given Path values at all?
IMHO this is all wrong. Maybe it is needed by the fallback for mklink but then it should be done only there if required.

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

Labels

link symlinks and windows junctions unpack logic to unpack archives (tar, zip, tgz, zbz2, msi, dmg, etc.)

Projects

Status: Team Review

Development

Successfully merging this pull request may close these issues.

vscode not working on mac

3 participants