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

jreleaser / jreleaser / #558

08 Dec 2025 02:56PM UTC coverage: 48.239% (+0.02%) from 48.215%
#558

push

github

aalmiray
feat(core): warn when a name template cannot be resolved

Closes #1960

Closes #1961

299 of 573 new or added lines in 133 files covered. (52.18%)

4 existing lines in 4 files now uncovered.

26047 of 53996 relevant lines covered (48.24%)

0.48 hits per line

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

58.16
/core/jreleaser-engine/src/main/java/org/jreleaser/packagers/BrewPackagerProcessor.java
1
/*
2
 * SPDX-License-Identifier: Apache-2.0
3
 *
4
 * Copyright 2020-2025 The JReleaser authors.
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 *     https://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
package org.jreleaser.packagers;
19

20
import org.jreleaser.model.internal.JReleaserContext;
21
import org.jreleaser.model.internal.common.Artifact;
22
import org.jreleaser.model.internal.distributions.Distribution;
23
import org.jreleaser.model.internal.packagers.BrewPackager;
24
import org.jreleaser.model.internal.release.BaseReleaser;
25
import org.jreleaser.model.internal.util.Artifacts;
26
import org.jreleaser.model.spi.packagers.PackagerProcessingException;
27
import org.jreleaser.mustache.MustacheUtils;
28
import org.jreleaser.mustache.TemplateContext;
29
import org.jreleaser.util.Algorithm;
30
import org.jreleaser.util.FileType;
31
import org.jreleaser.util.PlatformUtils;
32

33
import java.nio.file.Path;
34
import java.util.ArrayList;
35
import java.util.Arrays;
36
import java.util.List;
37
import java.util.stream.Collectors;
38

39
import static org.jreleaser.model.Constants.KEY_BREW_CASK_APP;
40
import static org.jreleaser.model.Constants.KEY_BREW_CASK_APPCAST;
41
import static org.jreleaser.model.Constants.KEY_BREW_CASK_DISPLAY_NAME;
42
import static org.jreleaser.model.Constants.KEY_BREW_CASK_HAS_APP;
43
import static org.jreleaser.model.Constants.KEY_BREW_CASK_HAS_APPCAST;
44
import static org.jreleaser.model.Constants.KEY_BREW_CASK_HAS_BINARY;
45
import static org.jreleaser.model.Constants.KEY_BREW_CASK_HAS_PKG;
46
import static org.jreleaser.model.Constants.KEY_BREW_CASK_HAS_UNINSTALL;
47
import static org.jreleaser.model.Constants.KEY_BREW_CASK_HAS_ZAP;
48
import static org.jreleaser.model.Constants.KEY_BREW_CASK_NAME;
49
import static org.jreleaser.model.Constants.KEY_BREW_CASK_PKG;
50
import static org.jreleaser.model.Constants.KEY_BREW_CASK_UNINSTALL;
51
import static org.jreleaser.model.Constants.KEY_BREW_CASK_ZAP;
52
import static org.jreleaser.model.Constants.KEY_BREW_DEPENDENCIES;
53
import static org.jreleaser.model.Constants.KEY_BREW_DOWNLOAD_STRATEGY;
54
import static org.jreleaser.model.Constants.KEY_BREW_FORMULA_NAME;
55
import static org.jreleaser.model.Constants.KEY_BREW_HAS_LIVECHECK;
56
import static org.jreleaser.model.Constants.KEY_BREW_LIVECHECK;
57
import static org.jreleaser.model.Constants.KEY_BREW_MULTIPLATFORM;
58
import static org.jreleaser.model.Constants.KEY_BREW_REQUIRE_RELATIVE;
59
import static org.jreleaser.model.Constants.KEY_DISTRIBUTION_ARTIFACT_FILE_NAME;
60
import static org.jreleaser.model.Constants.KEY_DISTRIBUTION_ARTIFACT_ROOT_ENTRY_NAME;
61
import static org.jreleaser.model.Constants.KEY_DISTRIBUTION_JAVA_MAIN_CLASS;
62
import static org.jreleaser.model.Constants.KEY_DISTRIBUTION_JAVA_MAIN_MODULE;
63
import static org.jreleaser.model.Constants.KEY_DISTRIBUTION_JAVA_VERSION;
64
import static org.jreleaser.model.Constants.KEY_DISTRIBUTION_URL;
65
import static org.jreleaser.model.Constants.KEY_HOMEBREW_REPOSITORY_ALIAS;
66
import static org.jreleaser.model.Constants.KEY_HOMEBREW_REPOSITORY_CLONE_URL;
67
import static org.jreleaser.model.Constants.KEY_HOMEBREW_REPOSITORY_NAME;
68
import static org.jreleaser.model.Constants.KEY_HOMEBREW_REPOSITORY_OWNER;
69
import static org.jreleaser.model.Constants.KEY_HOMEBREW_REPOSITORY_URL;
70
import static org.jreleaser.model.Constants.KEY_HOMEBREW_TAP_NAME;
71
import static org.jreleaser.model.Constants.KEY_HOMEBREW_TAP_REPO_CLONE_URL;
72
import static org.jreleaser.model.Constants.KEY_HOMEBREW_TAP_REPO_NAME;
73
import static org.jreleaser.model.Constants.KEY_HOMEBREW_TAP_REPO_OWNER;
74
import static org.jreleaser.model.Constants.KEY_HOMEBREW_TAP_REPO_URL;
75
import static org.jreleaser.mustache.MustacheUtils.passThrough;
76
import static org.jreleaser.mustache.Templates.resolveTemplate;
77
import static org.jreleaser.templates.TemplateUtils.trimTplExtension;
78
import static org.jreleaser.util.FileType.ZIP;
79
import static org.jreleaser.util.FileUtils.resolveRootEntryName;
80
import static org.jreleaser.util.StringUtils.getFilename;
81
import static org.jreleaser.util.StringUtils.getHyphenatedName;
82
import static org.jreleaser.util.StringUtils.isBlank;
83
import static org.jreleaser.util.StringUtils.isNotBlank;
84
import static org.jreleaser.util.StringUtils.isTrue;
85

86
/**
87
 * @author Andres Almiray
88
 * @since 0.1.0
89
 */
90
public class
91
BrewPackagerProcessor extends AbstractRepositoryPackagerProcessor<BrewPackager> {
92
    private static final String KEY_DISTRIBUTION_CHECKSUM_SHA_256 = "distributionChecksumSha256";
93

94
    private static final String TPL_MAC_ARM = "  if OS.mac? && Hardware::CPU.arm?\n" +
95
        "    url \"{{distributionUrl}}\"{{#brewDownloadStrategy}}, :using => {{.}}{{/brewDownloadStrategy}}\n" +
96
        "    sha256 \"{{distributionChecksumSha256}}\"\n" +
97
        "  end\n";
98
    private static final String TPL_MAC_INTEL = "  if OS.mac? && Hardware::CPU.intel?\n" +
99
        "    url \"{{distributionUrl}}\"{{#brewDownloadStrategy}}, :using => {{.}}{{/brewDownloadStrategy}}\n" +
100
        "    sha256 \"{{distributionChecksumSha256}}\"\n" +
101
        "  end\n";
102
    private static final String TPL_LINUX_ARM = "  if OS.linux? && Hardware::CPU.arm? && Hardware::CPU.is_64_bit?\n" +
103
        "    url \"{{distributionUrl}}\"{{#brewDownloadStrategy}}, :using => {{.}}{{/brewDownloadStrategy}}\n" +
104
        "    sha256 \"{{distributionChecksumSha256}}\"\n" +
105
        "  end\n";
106
    private static final String TPL_LINUX_INTEL = "  if OS.linux? && Hardware::CPU.intel?\n" +
107
        "    url \"{{distributionUrl}}\"{{#brewDownloadStrategy}}, :using => {{.}}{{/brewDownloadStrategy}}\n" +
108
        "    sha256 \"{{distributionChecksumSha256}}\"\n" +
109
        "  end\n";
110

111
    private static final String TPL_MAC_ARM_FLAT_BINARY = "  if OS.mac? && Hardware::CPU.arm?\n" +
112
        "    url \"{{distributionUrl}}\"{{#brewDownloadStrategy}}, :using => {{.}}{{/brewDownloadStrategy}}\n" +
113
        "    sha256 \"{{distributionChecksumSha256}}\"\n" +
114
        "\n" +
115
        "    def install\n" +
116
        "      bin.install \"{{distributionArtifactFileName}}\" => \"{{distributionExecutableName}}\"\n" +
117
        "    end\n" +
118
        "  end\n";
119
    private static final String TPL_MAC_INTEL_FLAT_BINARY = "  if OS.mac? && Hardware::CPU.intel?\n" +
120
        "    url \"{{distributionUrl}}\"{{#brewDownloadStrategy}}, :using => {{.}}{{/brewDownloadStrategy}}\n" +
121
        "    sha256 \"{{distributionChecksumSha256}}\"\n" +
122
        "\n" +
123
        "    def install\n" +
124
        "      bin.install \"{{distributionArtifactFileName}}\" => \"{{distributionExecutableName}}\"\n" +
125
        "    end\n" +
126
        "  end\n";
127
    private static final String TPL_LINUX_ARM_FLAT_BINARY = "  if OS.linux? && Hardware::CPU.arm? && Hardware::CPU.is_64_bit?\n" +
128
        "    url \"{{distributionUrl}}\"{{#brewDownloadStrategy}}, :using => {{.}}{{/brewDownloadStrategy}}\n" +
129
        "    sha256 \"{{distributionChecksumSha256}}\"\n" +
130
        "\n" +
131
        "    def install\n" +
132
        "      bin.install \"{{distributionArtifactFileName}}\" => \"{{distributionExecutableName}}\"\n" +
133
        "    end\n" +
134
        "  end\n";
135
    private static final String TPL_LINUX_INTEL_FLAT_BINARY = "  if OS.linux? && Hardware::CPU.intel?\n" +
136
        "    url \"{{distributionUrl}}\"{{#brewDownloadStrategy}}, :using => {{.}}{{/brewDownloadStrategy}}\n" +
137
        "    sha256 \"{{distributionChecksumSha256}}\"\n" +
138
        "\n" +
139
        "    def install\n" +
140
        "      bin.install \"{{distributionArtifactFileName}}\" => \"{{distributionExecutableName}}\"\n" +
141
        "    end\n" +
142
        "  end\n";
143

144
    private static final String CASK_RB = "cask.rb";
145
    private static final String CASKS = "Casks";
146
    private static final String FORMULA = "Formula";
147
    private static final String FORMULA_RB = "formula.rb";
148
    private static final String FORMULA_MULTI_RB = "formula-multi.rb";
149
    private static final String RB = ".rb";
150
    private static final String SKIP_JAVA = "skipJava";
151
    private static final String USE_VERSIONED_JAVA = "useVersionedJava";
152

153
    private static final List<String> BREW_JDK_ALIASES = Arrays.asList("openjdk", "java");
1✔
154

155
    public BrewPackagerProcessor(JReleaserContext context) {
156
        super(context);
1✔
157
    }
1✔
158

159
    @Override
160
    protected void doPackageDistribution(Distribution distribution, TemplateContext props, Path packageDirectory) throws PackagerProcessingException {
161
        super.doPackageDistribution(distribution, props, packageDirectory);
1✔
162
        copyPreparedFiles(props);
1✔
163
    }
1✔
164

165
    @Override
166
    protected void fillPackagerProperties(TemplateContext props, Distribution distribution) {
167
        props.set(KEY_DISTRIBUTION_JAVA_MAIN_CLASS, distribution.getJava().getMainClass());
1✔
168
        props.set(KEY_DISTRIBUTION_JAVA_MAIN_MODULE, distribution.getJava().getMainModule());
1✔
169
        BaseReleaser<?, ?> releaser = context.getModel().getRelease().getReleaser();
1✔
170

171
        props.set(KEY_BREW_FORMULA_NAME, packager.getResolvedFormulaName(context, props));
1✔
172
        props.set(KEY_BREW_DOWNLOAD_STRATEGY, packager.getDownloadStrategy());
1✔
173
        props.set(KEY_BREW_REQUIRE_RELATIVE, packager.getRequireRelative());
1✔
174

175
        props.set(KEY_HOMEBREW_TAP_REPO_OWNER, packager.getRepository().getOwner());
1✔
176
        props.set(KEY_HOMEBREW_TAP_REPO_NAME, packager.getRepository().getResolvedName());
1✔
177
        props.set(KEY_HOMEBREW_TAP_NAME, packager.getRepository().getResolvedName().substring("homebrew-".length()));
1✔
178
        props.set(KEY_HOMEBREW_TAP_REPO_URL,
1✔
179
            releaser.getResolvedRepoUrl(context, packager.getRepository().getOwner(), packager.getRepository().getResolvedName()));
1✔
180
        props.set(KEY_HOMEBREW_TAP_REPO_CLONE_URL,
1✔
181
            releaser.getResolvedRepoCloneUrl(context, packager.getRepository().getOwner(), packager.getRepository().getResolvedName()));
1✔
182

183
        props.set(KEY_HOMEBREW_REPOSITORY_OWNER, packager.getRepository().getOwner());
1✔
184
        props.set(KEY_HOMEBREW_REPOSITORY_NAME, packager.getRepository().getResolvedName());
1✔
185
        props.set(KEY_HOMEBREW_REPOSITORY_ALIAS, packager.getRepository().getResolvedName().substring("homebrew-".length()));
1✔
186
        props.set(KEY_HOMEBREW_REPOSITORY_URL,
1✔
187
            releaser.getResolvedRepoUrl(context, packager.getRepository().getOwner(), packager.getRepository().getResolvedName()));
1✔
188
        props.set(KEY_HOMEBREW_REPOSITORY_CLONE_URL,
1✔
189
            releaser.getResolvedRepoCloneUrl(context, packager.getRepository().getOwner(), packager.getRepository().getResolvedName()));
1✔
190

191
        props.set(KEY_BREW_HAS_LIVECHECK, packager.hasLivecheck());
1✔
192
        if (packager.hasLivecheck()) {
1✔
193
            props.set(KEY_BREW_LIVECHECK, packager.getLivecheck().stream()
×
NEW
194
                .map(line -> resolveTemplate(context.getLogger(), line, props))
×
195
                .map(MustacheUtils::passThrough)
×
196
                .collect(Collectors.toList()));
×
197
        }
198

199
        BrewPackager.Cask cask = packager.getCask();
1✔
200
        if (cask.isEnabled()) {
1✔
201
            boolean hasPkg = isNotBlank(cask.getPkgName());
×
202
            boolean hasApp = isNotBlank(cask.getAppName());
×
203

NEW
204
            props.set(KEY_BREW_CASK_NAME, cask.getResolvedCaskName(context, props));
×
NEW
205
            props.set(KEY_BREW_CASK_DISPLAY_NAME, cask.getResolvedDisplayName(context, props));
×
206
            props.set(KEY_BREW_CASK_HAS_UNINSTALL, !cask.getUninstallItems().isEmpty());
×
207
            props.set(KEY_BREW_CASK_HAS_PKG, hasPkg);
×
208
            if (hasPkg) {
×
NEW
209
                props.set(KEY_BREW_CASK_PKG, cask.getResolvedPkgName(context, props));
×
210
            }
211
            props.set(KEY_BREW_CASK_HAS_APP, hasApp);
×
212
            if (hasApp) {
×
NEW
213
                props.set(KEY_BREW_CASK_APP, cask.getResolvedAppName(context, props));
×
214
            }
215
            props.set(KEY_BREW_CASK_UNINSTALL, cask.getUninstallItems());
×
216
            props.set(KEY_BREW_CASK_HAS_ZAP, !cask.getZapItems().isEmpty());
×
217
            props.set(KEY_BREW_CASK_ZAP, cask.getZapItems());
×
NEW
218
            String appcast = cask.getResolvedAppcast(context, props);
×
219
            props.set(KEY_BREW_CASK_HAS_APPCAST, isNotBlank(appcast));
×
220
            props.set(KEY_BREW_CASK_APPCAST, appcast);
×
221

222
            if (!hasApp && !hasPkg) {
×
223
                for (Artifact artifact : collectArtifacts(distribution)) {
×
224
                    if (artifact.getPath().endsWith(ZIP.extension())) {
×
225
                        props.set(KEY_DISTRIBUTION_URL, resolveArtifactUrl(distribution, artifact));
×
226
                        props.set(KEY_BREW_CASK_HAS_BINARY, true);
×
227
                        break;
×
228
                    }
229
                }
×
230
            }
231
        } else if (packager.isMultiPlatform()) {
1✔
232
            List<String> multiPlatforms = new ArrayList<>();
1✔
233

234
            Artifact osxIntelArtifact = null;
1✔
235
            Artifact osxArmArtifact = null;
1✔
236

237
            boolean flatBinary = distribution.getType() == org.jreleaser.model.Distribution.DistributionType.FLAT_BINARY;
1✔
238

239
            for (Artifact artifact : collectArtifacts(distribution)) {
1✔
240
                if (!artifact.getPath().endsWith(ZIP.extension()) && !flatBinary ||
1✔
241
                    isBlank(artifact.getPlatform())) {
1✔
242
                    continue;
×
243
                }
244

245
                String template = null;
1✔
246
                String artifactUrl = resolveArtifactUrl(distribution, artifact);
1✔
247
                String artifactFile = artifact.getEffectivePath().getFileName().toString();
1✔
248
                String artifactFileName = getFilename(artifactFile, FileType.getSupportedExtensions());
1✔
249

250
                if (PlatformUtils.isMac(artifact.getPlatform())) {
1✔
251
                    if (PlatformUtils.isArm(artifact.getPlatform())) {
1✔
252
                        template = flatBinary ? TPL_MAC_ARM_FLAT_BINARY : TPL_MAC_ARM;
×
253
                        osxArmArtifact = artifact;
×
254
                    } else {
255
                        template = flatBinary ? TPL_MAC_INTEL_FLAT_BINARY : TPL_MAC_INTEL;
1✔
256
                        osxIntelArtifact = artifact;
1✔
257
                    }
258
                } else if (PlatformUtils.isLinux(artifact.getPlatform())) {
×
259
                    if (PlatformUtils.isArm(artifact.getPlatform())) {
×
260
                        template = flatBinary ? TPL_LINUX_ARM_FLAT_BINARY : TPL_LINUX_ARM;
×
261
                    } else {
262
                        template = flatBinary ? TPL_LINUX_INTEL_FLAT_BINARY : TPL_LINUX_INTEL;
×
263
                    }
264
                }
265

266
                if (isNotBlank(template)) {
1✔
267
                    TemplateContext newProps = new TemplateContext(props);
1✔
268
                    newProps.set(KEY_DISTRIBUTION_URL, artifactUrl);
1✔
269
                    newProps.set(KEY_DISTRIBUTION_ARTIFACT_FILE_NAME, artifactFileName);
1✔
270
                    newProps.set(KEY_DISTRIBUTION_ARTIFACT_ROOT_ENTRY_NAME, resolveRootEntryName(artifact.getEffectivePath()));
1✔
271
                    newProps.set(KEY_DISTRIBUTION_CHECKSUM_SHA_256, artifact.getHash(Algorithm.SHA_256));
1✔
272
                    multiPlatforms.add(resolveTemplate(context.getLogger(), template, newProps));
1✔
273
                }
274
            }
1✔
275

276
            // On OSX, use intel binary for arm if there's no match
277
            if (null != osxIntelArtifact && null == osxArmArtifact) {
1✔
278
                String artifactUrl = resolveArtifactUrl(distribution, osxIntelArtifact);
1✔
279
                String artifactFile = osxIntelArtifact.getEffectivePath().getFileName().toString();
1✔
280
                String artifactFileName = getFilename(artifactFile, FileType.getSupportedExtensions());
1✔
281
                TemplateContext newProps = new TemplateContext(props);
1✔
282
                newProps.set(KEY_DISTRIBUTION_URL, artifactUrl);
1✔
283
                newProps.set(KEY_DISTRIBUTION_ARTIFACT_FILE_NAME, artifactFileName);
1✔
284
                newProps.set(KEY_DISTRIBUTION_ARTIFACT_ROOT_ENTRY_NAME, resolveRootEntryName(osxIntelArtifact.getEffectivePath()));
1✔
285
                newProps.set(KEY_DISTRIBUTION_CHECKSUM_SHA_256, osxIntelArtifact.getHash(Algorithm.SHA_256));
1✔
286
                multiPlatforms.add(resolveTemplate(context.getLogger(), flatBinary ? TPL_LINUX_ARM_FLAT_BINARY : TPL_MAC_ARM, newProps));
1✔
287
            }
288

289
            if (multiPlatforms.isEmpty()) {
1✔
290
                throw new IllegalStateException(org.jreleaser.bundle.RB.$("ERROR_brew_multiplatform_artifacts"));
×
291
            }
292
            props.set(KEY_BREW_MULTIPLATFORM, passThrough(String.join(System.lineSeparator() + "  ", multiPlatforms)));
1✔
293
        } else if (shouldAddJavaDependency(distribution)) {
1✔
294
            boolean useVersionedJava = isTrue(packager.getExtraProperties().get(USE_VERSIONED_JAVA), true);
×
295
            String javaDependency = "openjdk" + (useVersionedJava ? "@" + props.get(KEY_DISTRIBUTION_JAVA_VERSION) : "");
×
296
            packager.addDependency(javaDependency);
×
297
        }
298

299
        props.set(KEY_BREW_DEPENDENCIES, packager.getDependenciesAsList()
1✔
300
            .stream()
1✔
301
            // prevent Mustache from converting quotes into &quot;
302
            .map(dependency -> passThrough(dependency.toString()))
1✔
303
            .collect(Collectors.toList()));
1✔
304
    }
1✔
305

306
    private boolean shouldAddJavaDependency(Distribution distribution) {
307
        if ((distribution.getType() == org.jreleaser.model.Distribution.DistributionType.JAVA_BINARY ||
×
308
            distribution.getType() == org.jreleaser.model.Distribution.DistributionType.SINGLE_JAR) &&
×
309
            !isTrue(packager.getExtraProperties().get(SKIP_JAVA))) {
×
310
            return packager.getDependenciesAsList().stream()
×
311
                .map(BrewPackager.Dependency::getKey).noneMatch(BrewPackagerProcessor::isJdkDependency);
×
312
        }
313
        return false;
×
314
    }
315

316
    private static boolean isJdkDependency(String brewDependency) {
317
        for (String alias : BREW_JDK_ALIASES) {
×
318
            if (brewDependency.equals(alias) || brewDependency.startsWith(alias + "@")) {
×
319
                return true;
×
320
            }
321
        }
×
322
        return false;
×
323
    }
324

325
    private String resolveArtifactUrl(Distribution distribution, Artifact artifact) {
326
        return Artifacts.resolveDownloadUrl(context, org.jreleaser.model.api.packagers.BrewPackager.TYPE, distribution, artifact);
1✔
327
    }
328

329
    @Override
330
    protected void writeFile(Distribution distribution,
331
                             String content,
332
                             TemplateContext props,
333
                             Path outputDirectory,
334
                             String fileName)
335
        throws PackagerProcessingException {
336
        fileName = trimTplExtension(fileName);
1✔
337

338
        if (packager.getCask().isEnabled()) {
1✔
339
            if (FORMULA_RB.equals(fileName) || FORMULA_MULTI_RB.equals(fileName)) return;
×
340
            writeFile(content, CASK_RB.equals(fileName) ?
×
NEW
341
                outputDirectory.resolve(CASKS).resolve(packager.getCask().getResolvedCaskName(context, props).concat(RB)) :
×
342
                outputDirectory.resolve(fileName));
×
343
        } else if (packager.isMultiPlatform()) {
1✔
344
            if (CASK_RB.equals(fileName) || FORMULA_RB.equals(fileName)) return;
1✔
345
            writeFile(content, FORMULA_MULTI_RB.equals(fileName) ?
1✔
346
                outputDirectory.resolve(FORMULA)
1✔
347
                    .resolve(getHyphenatedName(packager.getFormulaName()).concat(RB)) :
1✔
348
                outputDirectory.resolve(fileName));
1✔
349
        } else {
350
            if (CASK_RB.equals(fileName) || FORMULA_MULTI_RB.equals(fileName)) return;
×
351
            writeFile(content, FORMULA_RB.equals(fileName) ?
×
352
                outputDirectory.resolve(FORMULA)
×
353
                    .resolve(getHyphenatedName(packager.getFormulaName()).concat(RB)) :
×
354
                outputDirectory.resolve(fileName));
×
355
        }
356
    }
1✔
357
}
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