• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

devonfw / IDEasy / 14879167692

07 May 2025 08:48AM UTC coverage: 67.641% (-0.03%) from 67.672%
14879167692

push

github

web-flow
#583: added status badge (#1288)

* #583: added status badge
* #583: adjusted execute permission

3094 of 4982 branches covered (62.1%)

Branch coverage included in aggregate %.

7964 of 11366 relevant lines covered (70.07%)

3.07 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

84.42
cli/src/main/java/com/devonfw/tools/ide/os/MacOsHelper.java
1
package com.devonfw.tools.ide.os;
2

3
import java.io.IOException;
4
import java.nio.file.Files;
5
import java.nio.file.Path;
6
import java.util.Iterator;
7
import java.util.Set;
8
import java.util.stream.Stream;
9

10
import com.devonfw.tools.ide.context.IdeContext;
11
import com.devonfw.tools.ide.io.FileAccess;
12
import com.devonfw.tools.ide.log.IdeLogger;
13
import com.devonfw.tools.ide.tool.ToolCommandlet;
14
import com.devonfw.tools.ide.tool.repository.ToolRepository;
15

16
/**
17
 * Internal helper class for MacOS workarounds.
18
 */
19
public final class MacOsHelper {
20

21
  private static final Set<String> INVALID_LINK_FOLDERS = Set.of(IdeContext.FOLDER_CONTENTS,
6✔
22
      IdeContext.FOLDER_RESOURCES, IdeContext.FOLDER_BIN);
23

24
  private final FileAccess fileAccess;
25

26
  private final SystemInfo systemInfo;
27

28
  private final IdeLogger logger;
29

30
  /**
31
   * The constructor.
32
   *
33
   * @param context the {@link IdeContext} instance.
34
   */
35
  public MacOsHelper(IdeContext context) {
36

37
    this(context.getFileAccess(), context.getSystemInfo(), context);
7✔
38
  }
1✔
39

40
  /**
41
   * The constructor.
42
   *
43
   * @param fileAccess the {@link FileAccess} instance.
44
   * @param systemInfo the {@link SystemInfo} instance.
45
   * @param logger the {@link IdeLogger} instance.
46
   */
47
  public MacOsHelper(FileAccess fileAccess, SystemInfo systemInfo, IdeLogger logger) {
48

49
    super();
2✔
50
    this.fileAccess = fileAccess;
3✔
51
    this.systemInfo = systemInfo;
3✔
52
    this.logger = logger;
3✔
53
  }
1✔
54

55
  /**
56
   * @param rootDir the {@link Path} to the root directory.
57
   * @return the path to the app directory.
58
   */
59
  public Path findAppDir(Path rootDir) {
60
    return this.fileAccess.findFirst(rootDir,
7✔
61
        p -> p.getFileName().toString().endsWith(".app") && Files.isDirectory(p), false);
15!
62
  }
63

64
  /**
65
   * @param rootDir the {@link Path} to the root directory.
66
   * @param tool the name of the tool to find the link directory for.
67
   * @return the {@link com.devonfw.tools.ide.tool.ToolInstallation#linkDir() link directory}.
68
   */
69
  public Path findLinkDir(Path rootDir, String tool) {
70

71
    if (!this.systemInfo.isMac() || Files.isDirectory(rootDir.resolve(IdeContext.FOLDER_BIN))) {
11✔
72
      return rootDir;
2✔
73
    }
74
    Path contentsDir = rootDir.resolve(IdeContext.FOLDER_CONTENTS);
4✔
75
    if (Files.isDirectory(contentsDir)) {
5✔
76
      return findLinkDir(contentsDir, rootDir, tool);
6✔
77
    }
78
    Path appDir = findAppDir(rootDir);
4✔
79
    if (appDir != null) {
2✔
80
      contentsDir = appDir.resolve(IdeContext.FOLDER_CONTENTS);
4✔
81
      if (Files.isDirectory(contentsDir)) {
5!
82
        return findLinkDir(contentsDir, rootDir, tool);
6✔
83
      }
84
    }
85
    return rootDir;
2✔
86
  }
87

88
  /**
89
   * Finds the root tool path of a tool in MacOS
90
   *
91
   * @param commandlet the {@link ToolCommandlet}
92
   * @param context the {@link IdeContext}
93
   * @return a {@link String}
94
   */
95
  public Path findRootToolPath(ToolCommandlet commandlet, IdeContext context) {
96
    return context.getSoftwareRepositoryPath().resolve(ToolRepository.ID_DEFAULT).resolve(commandlet.getName())
9✔
97
        .resolve(commandlet.getInstalledEdition())
3✔
98
        .resolve(commandlet.getInstalledVersion().toString());
3✔
99
  }
100

101
  private Path findLinkDir(Path contentsDir, Path rootDir, String tool) {
102

103
    this.logger.debug("Found MacOS app in {}", contentsDir);
10✔
104
    Path resourcesAppBin = contentsDir.resolve(IdeContext.FOLDER_RESOURCES).resolve(IdeContext.FOLDER_APP)
6✔
105
        .resolve(IdeContext.FOLDER_BIN);
2✔
106
    if (Files.isDirectory(resourcesAppBin)) {
5✔
107
      return resourcesAppBin.getParent();
3✔
108
    }
109
    Path linkDir = findContentSubfolder(contentsDir, tool);
5✔
110
    if (linkDir != null) {
2!
111
      return linkDir;
2✔
112
    }
113
    return rootDir;
×
114
  }
115

116
  private Path findContentSubfolder(Path dir, String tool) {
117

118
    try (Stream<Path> childStream = Files.list(dir)) {
3✔
119
      Iterator<Path> iterator = childStream.iterator();
3✔
120
      while (iterator.hasNext()) {
3!
121
        Path child = iterator.next();
4✔
122
        String filename = child.getFileName().toString();
4✔
123
        if (INVALID_LINK_FOLDERS.contains(filename) || filename.startsWith("_")) {
8!
124
          continue;
×
125
        } else if (Files.isDirectory(child.resolve(IdeContext.FOLDER_BIN)) || Files.exists(child.resolve(tool))) {
14✔
126
          return child;
4✔
127
        }
128
      }
1✔
129
    } catch (IOException e) {
4!
130
      throw new IllegalStateException("Failed to search for file in " + dir, e);
×
131
    }
×
132
    return null;
×
133
  }
134

135
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc