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

devonfw / IDEasy / 27957744076

22 Jun 2026 01:51PM UTC coverage: 71.342% (-0.04%) from 71.381%
27957744076

Pull #2062

github

web-flow
Merge 6c4391aff into 3a08f1d5c
Pull Request #2062: #1982: Modified fallback link creation on windows

4701 of 7290 branches covered (64.49%)

Branch coverage included in aggregate %.

12113 of 16278 relevant lines covered (74.41%)

3.15 hits per line

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

71.43
cli/src/main/java/com/devonfw/tools/ide/commandlet/LnCommandlet.java
1
package com.devonfw.tools.ide.commandlet;
2

3
import java.nio.file.Files;
4
import java.nio.file.Path;
5

6
import org.slf4j.Logger;
7
import org.slf4j.LoggerFactory;
8

9
import com.devonfw.tools.ide.cli.CliException;
10
import com.devonfw.tools.ide.context.IdeContext;
11
import com.devonfw.tools.ide.io.PathLinkType;
12
import com.devonfw.tools.ide.property.FlagProperty;
13
import com.devonfw.tools.ide.property.PathProperty;
14

15
/**
16
 * // * Link creation {@link Commandlet} similar to {@code ln -s}.
17
 * <p>
18
 * It tries to create a true symbolic link first. On Windows, symlink creation may be restricted due to missing privileges. In that case, IDEasy will create a
19
 * hard link as an alternative (file-only, same volume) to avoid the Git-Bash behavior of silently copying files.
20
 */
21
public final class LnCommandlet extends Commandlet {
22

23
  private static final Logger LOG = LoggerFactory.getLogger(LnCommandlet.class);
4✔
24

25
  /** Grammar token {@code -s} (optional). */
26
  public final FlagProperty symbolic;
27

28
  /** Grammar token {@code -r} (optional). */
29
  public final FlagProperty relative;
30

31
  /** The source path to link to. */
32
  public final PathProperty source;
33

34
  /** The target path (the created link). */
35
  public final PathProperty link;
36

37
  /**
38
   * The constructor.
39
   *
40
   * @param context the {@link IdeContext}.
41
   */
42
  public LnCommandlet(IdeContext context) {
43

44
    super(context);
3✔
45
    addKeyword(getName());
4✔
46

47
    this.symbolic = add(new FlagProperty("--symbolic", false, "-s"));
11✔
48
    this.relative = add(new FlagProperty("--relative", false, "-r"));
11✔
49
    this.source = add(new PathProperty("", true, "source", true));
12✔
50
    this.link = add(new PathProperty("", true, "link", false));
12✔
51
  }
1✔
52

53
  @Override
54
  public String getName() {
55

56
    return "ln";
2✔
57
  }
58

59
  @Override
60
  public boolean isIdeRootRequired() {
61

62
    return false;
×
63
  }
64

65
  @Override
66
  public boolean isIdeHomeRequired() {
67

68
    return false;
2✔
69
  }
70

71
  @Override
72
  public boolean isWriteLogFile() {
73

74
    return false;
×
75
  }
76

77
  @Override
78
  protected void doRun() {
79

80
    Path cwd = this.context.getCwd();
4✔
81
    if (cwd == null) {
2!
82
      throw new CliException("Missing current working directory!");
×
83
    }
84

85
    Path sourcePath = cwd.resolve(this.source.getValue()).normalize();
8✔
86
    Path linkPath = cwd.resolve(this.link.getValue()).normalize();
8✔
87
    boolean relative = this.relative.isTrue();
4✔
88

89
    if (!Files.exists(sourcePath)) {
5!
90
      throw new CliException("Source does not exist: " + sourcePath);
×
91
    }
92

93
    PathLinkType linkType = this.symbolic.isTrue() ? PathLinkType.SYMBOLIC_LINK : PathLinkType.HARD_LINK;
7!
94
    PathLinkType result = this.context.getFileAccess().link(sourcePath, linkPath, relative, linkType);
9✔
95
    if (this.relative.isTrue() && result == null) {
6!
96
      LOG.info(
×
97
          "Due to lack of permissions, Microsoft's mklink with junction had to be used to create a Symlink. See\n"
98
              + "https://github.com/devonfw/IDEasy/blob/main/documentation/symlink.adoc for further details.");
99
    }
100
  }
1✔
101
}
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