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

jreleaser / jreleaser / #475

03 Apr 2025 10:50AM UTC coverage: 40.322% (-8.9%) from 49.193%
#475

push

github

aalmiray
feat(release): Support Forgejo as releaser

Closes #1842

Closes #1843

182 of 1099 new or added lines in 45 files covered. (16.56%)

4239 existing lines in 333 files now uncovered.

20797 of 51577 relevant lines covered (40.32%)

0.4 hits per line

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

0.0
/core/jreleaser-engine/src/main/java/org/jreleaser/packagers/AbstractPackagerProcessor.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.bundle.RB;
21
import org.jreleaser.model.Stereotype;
22
import org.jreleaser.model.internal.JReleaserContext;
23
import org.jreleaser.model.internal.common.Artifact;
24
import org.jreleaser.model.internal.distributions.Distribution;
25
import org.jreleaser.model.internal.packagers.Packager;
26
import org.jreleaser.model.internal.util.Artifacts;
27
import org.jreleaser.model.spi.packagers.PackagerProcessingException;
28
import org.jreleaser.model.spi.packagers.PackagerProcessor;
29
import org.jreleaser.mustache.TemplateContext;
30
import org.jreleaser.sdk.command.Command;
31
import org.jreleaser.sdk.command.CommandException;
32
import org.jreleaser.sdk.command.CommandExecutor;
33
import org.jreleaser.util.Algorithm;
34
import org.jreleaser.util.FileType;
35
import org.jreleaser.util.FileUtils;
36
import org.jreleaser.util.IoUtils;
37

38
import java.io.ByteArrayOutputStream;
39
import java.io.IOException;
40
import java.io.InputStream;
41
import java.nio.file.Files;
42
import java.nio.file.Path;
43
import java.util.Arrays;
44
import java.util.List;
45
import java.util.Map;
46
import java.util.Optional;
47
import java.util.function.Consumer;
48

49
import static java.util.stream.Collectors.toList;
50
import static org.jreleaser.model.Constants.KEY_ARTIFACT_ARCH;
51
import static org.jreleaser.model.Constants.KEY_ARTIFACT_FILE;
52
import static org.jreleaser.model.Constants.KEY_ARTIFACT_FILE_EXTENSION;
53
import static org.jreleaser.model.Constants.KEY_ARTIFACT_FILE_FORMAT;
54
import static org.jreleaser.model.Constants.KEY_ARTIFACT_FILE_NAME;
55
import static org.jreleaser.model.Constants.KEY_ARTIFACT_NAME;
56
import static org.jreleaser.model.Constants.KEY_ARTIFACT_OS;
57
import static org.jreleaser.model.Constants.KEY_ARTIFACT_PLATFORM;
58
import static org.jreleaser.model.Constants.KEY_ARTIFACT_PLATFORM_REPLACED;
59
import static org.jreleaser.model.Constants.KEY_ARTIFACT_ROOT_ENTRY_NAME;
60
import static org.jreleaser.model.Constants.KEY_ARTIFACT_SIZE;
61
import static org.jreleaser.model.Constants.KEY_ARTIFACT_VERSION;
62
import static org.jreleaser.model.Constants.KEY_DISTRIBUTION_ARTIFACT;
63
import static org.jreleaser.model.Constants.KEY_DISTRIBUTION_ARTIFACT_ARCH;
64
import static org.jreleaser.model.Constants.KEY_DISTRIBUTION_ARTIFACT_FILE;
65
import static org.jreleaser.model.Constants.KEY_DISTRIBUTION_ARTIFACT_FILE_EXTENSION;
66
import static org.jreleaser.model.Constants.KEY_DISTRIBUTION_ARTIFACT_FILE_FORMAT;
67
import static org.jreleaser.model.Constants.KEY_DISTRIBUTION_ARTIFACT_FILE_NAME;
68
import static org.jreleaser.model.Constants.KEY_DISTRIBUTION_ARTIFACT_NAME;
69
import static org.jreleaser.model.Constants.KEY_DISTRIBUTION_ARTIFACT_OS;
70
import static org.jreleaser.model.Constants.KEY_DISTRIBUTION_ARTIFACT_PLATFORM;
71
import static org.jreleaser.model.Constants.KEY_DISTRIBUTION_ARTIFACT_PLATFORM_REPLACED;
72
import static org.jreleaser.model.Constants.KEY_DISTRIBUTION_ARTIFACT_ROOT_ENTRY_NAME;
73
import static org.jreleaser.model.Constants.KEY_DISTRIBUTION_ARTIFACT_SIZE;
74
import static org.jreleaser.model.Constants.KEY_DISTRIBUTION_ARTIFACT_VERSION;
75
import static org.jreleaser.model.Constants.KEY_DISTRIBUTION_PACKAGE_DIRECTORY;
76
import static org.jreleaser.model.Constants.KEY_DISTRIBUTION_PREPARE_DIRECTORY;
77
import static org.jreleaser.model.Constants.KEY_DISTRIBUTION_SHA_256;
78
import static org.jreleaser.model.Constants.KEY_DISTRIBUTION_SIZE;
79
import static org.jreleaser.model.Constants.KEY_DISTRIBUTION_URL;
80
import static org.jreleaser.model.Constants.KEY_REVERSE_REPO_HOST;
81
import static org.jreleaser.mustache.MustacheUtils.applyTemplates;
82
import static org.jreleaser.util.FileUtils.resolveRootEntryName;
83
import static org.jreleaser.util.StringUtils.capitalize;
84
import static org.jreleaser.util.StringUtils.getFilename;
85
import static org.jreleaser.util.StringUtils.isBlank;
86
import static org.jreleaser.util.StringUtils.isNotBlank;
87

88
/**
89
 * @author Andres Almiray
90
 * @since 0.1.0
91
 */
92
public abstract class AbstractPackagerProcessor<T extends Packager<?>> implements PackagerProcessor<T> {
93
    private static final String ARTIFACT = "artifact";
94
    private static final String DISTRIBUTION = "distribution";
95
    private static final String NAME = "Name";
96
    private static final String VERSION = "Version";
97
    private static final String OS = "Os";
98
    private static final String ARCH = "Arch";
99
    private static final String FILE = "File";
100
    private static final String SIZE = "Size";
101
    private static final String FILE_NAME = "FileName";
102
    private static final String ROOT_ENTRY_NAME = "RootEntryName";
103
    private static final String FILE_EXTENSION = "FileExtension";
104
    private static final String FILE_FORMAT = "FileFormat";
105
    private static final String CHECKSUM = "Checksum";
106
    private static final String URL = "Url";
107

108
    protected final JReleaserContext context;
109
    protected T packager;
110

UNCOV
111
    protected AbstractPackagerProcessor(JReleaserContext context) {
×
UNCOV
112
        this.context = context;
×
UNCOV
113
    }
×
114

115
    @Override
116
    public T getPackager() {
UNCOV
117
        return packager;
×
118
    }
119

120
    @Override
121
    public void setPackager(T packager) {
UNCOV
122
        this.packager = packager;
×
UNCOV
123
    }
×
124

125
    @Override
126
    public String getPackagerName() {
UNCOV
127
        return packager.getType();
×
128
    }
129

130
    @Override
131
    public boolean supportsDistribution(Distribution distribution) {
UNCOV
132
        return true;
×
133
    }
134

135
    @Override
136
    public void prepareDistribution(Distribution distribution, TemplateContext props) throws PackagerProcessingException {
137
        try {
UNCOV
138
            String distributionName = distribution.getName();
×
UNCOV
139
            context.getLogger().debug(RB.$("packager.create.properties"), distributionName, getPackagerName());
×
UNCOV
140
            TemplateContext newProps = fillProps(distribution, props);
×
UNCOV
141
            if (newProps.isEmpty()) {
×
142
                context.getLogger().warn(RB.$("packager.skip.distribution"), distributionName);
×
143
                return;
×
144
            }
145

UNCOV
146
            doPrepareDistribution(distribution, newProps);
×
147
        } catch (RuntimeException e) {
×
148
            throw new PackagerProcessingException(e);
×
UNCOV
149
        }
×
UNCOV
150
    }
×
151

152
    protected abstract void doPrepareDistribution(Distribution distribution, TemplateContext props) throws PackagerProcessingException;
153

154
    @Override
155
    public void packageDistribution(Distribution distribution, TemplateContext props) throws PackagerProcessingException {
156
        try {
UNCOV
157
            String distributionName = distribution.getName();
×
UNCOV
158
            context.getLogger().debug(RB.$("packager.create.properties"), distributionName, getPackagerName());
×
UNCOV
159
            TemplateContext newProps = fillProps(distribution, props);
×
UNCOV
160
            if (newProps.isEmpty()) {
×
161
                context.getLogger().warn(RB.$("packager.skip.distribution"), distributionName);
×
162
                return;
×
163
            }
164

UNCOV
165
            doPackageDistribution(distribution, newProps);
×
166
        } catch (IllegalArgumentException e) {
×
167
            throw new PackagerProcessingException(e);
×
UNCOV
168
        }
×
UNCOV
169
    }
×
170

171
    @Override
172
    public void publishDistribution(Distribution distribution, TemplateContext props) throws PackagerProcessingException {
UNCOV
173
        if (context.getModel().getProject().isSnapshot() && !packager.isSnapshotSupported()) {
×
174
            context.getLogger().info(RB.$("packager.publish.snapshot.not.supported"));
×
175
            return;
×
176
        }
177

178
        try {
UNCOV
179
            String distributionName = distribution.getName();
×
UNCOV
180
            context.getLogger().debug(RB.$("packager.create.properties"), distributionName, getPackagerName());
×
UNCOV
181
            TemplateContext newProps = fillProps(distribution, props);
×
UNCOV
182
            if (newProps.isEmpty()) {
×
183
                context.getLogger().warn(RB.$("packager.skip.distribution"), distributionName);
×
184
                return;
×
185
            }
186

UNCOV
187
            doPublishDistribution(distribution, newProps);
×
188
        } catch (RuntimeException e) {
×
189
            throw new PackagerProcessingException(e);
×
UNCOV
190
        }
×
UNCOV
191
    }
×
192

193
    protected abstract void doPackageDistribution(Distribution distribution, TemplateContext props) throws PackagerProcessingException;
194

195
    protected abstract void doPublishDistribution(Distribution distribution, TemplateContext props) throws PackagerProcessingException;
196

197
    protected TemplateContext fillProps(Distribution distribution, TemplateContext props) {
UNCOV
198
        TemplateContext newProps = new TemplateContext(props);
×
UNCOV
199
        context.getLogger().debug(RB.$("packager.fill.distribution.properties"));
×
UNCOV
200
        fillDistributionProperties(newProps, distribution);
×
UNCOV
201
        context.getLogger().debug(RB.$("packager.fill.git.properties"));
×
UNCOV
202
        context.getModel().getRelease().getReleaser().fillProps(newProps, context.getModel());
×
UNCOV
203
        context.getLogger().debug(RB.$("packager.fill.artifact.properties"));
×
UNCOV
204
        if (!verifyAndAddArtifacts(newProps, distribution)) {
×
205
            // we can't continue with this packager
206
            return TemplateContext.empty();
×
207
        }
UNCOV
208
        context.getLogger().debug(RB.$("packager.fill.packager.properties"));
×
UNCOV
209
        fillPackagerProperties(newProps, distribution);
×
UNCOV
210
        applyTemplates(newProps, packager.resolvedExtraProperties());
×
UNCOV
211
        if (isBlank(context.getModel().getRelease().getReleaser().getReverseRepoHost())) {
×
212
            newProps.set(KEY_REVERSE_REPO_HOST,
×
213
                packager.getExtraProperties().get(KEY_REVERSE_REPO_HOST));
×
214
        }
UNCOV
215
        applyTemplates(newProps, newProps);
×
UNCOV
216
        return newProps;
×
217
    }
218

219
    protected void fillDistributionProperties(TemplateContext props, Distribution distribution) {
UNCOV
220
        props.setAll(distribution.props());
×
UNCOV
221
    }
×
222

223
    protected abstract void fillPackagerProperties(TemplateContext props, Distribution distribution);
224

225
    protected Command.Result executeCommand(Path directory, Command command) throws PackagerProcessingException {
226
        try {
227
            Command.Result result = new CommandExecutor(context.getLogger())
×
228
                .executeCommand(directory, command);
×
229
            if (result.getExitValue() != 0) {
×
230
                throw new CommandException(RB.$("ERROR_command_execution_exit_value", result.getExitValue()));
×
231
            }
232
            return result;
×
233
        } catch (CommandException e) {
×
234
            throw new PackagerProcessingException(RB.$("ERROR_unexpected_error"), e);
×
235
        }
236
    }
237

238
    protected Command.Result executeCommand(Command command) throws PackagerProcessingException {
239
        try {
240
            Command.Result result = new CommandExecutor(context.getLogger())
×
241
                .executeCommand(command);
×
242
            if (result.getExitValue() != 0) {
×
243
                throw new CommandException(RB.$("ERROR_command_execution_exit_value", result.getExitValue()));
×
244
            }
245
            return result;
×
246
        } catch (CommandException e) {
×
247
            throw new PackagerProcessingException(RB.$("ERROR_unexpected_error"), e);
×
248
        }
249
    }
250

251
    protected Command.Result executeCommand(Command command, InputStream in) throws PackagerProcessingException {
252
        try {
253
            Command.Result result = new CommandExecutor(context.getLogger())
×
254
                .executeCommand(command, in);
×
255
            if (result.getExitValue() != 0) {
×
256
                throw new CommandException(RB.$("ERROR_command_execution_exit_value", result.getExitValue()));
×
257
            }
258
            return result;
×
259
        } catch (CommandException e) {
×
260
            throw new PackagerProcessingException(RB.$("ERROR_unexpected_error"), e);
×
261
        }
262
    }
263

264
    protected void copyPreparedFiles(TemplateContext props) throws PackagerProcessingException {
UNCOV
265
        Path prepareDirectory = getPrepareDirectory(props);
×
UNCOV
266
        Path packageDirectory = getPackageDirectory(props);
×
UNCOV
267
        copyFiles(prepareDirectory, packageDirectory);
×
UNCOV
268
    }
×
269

270
    protected void copyFiles(Path src, Path dest) throws PackagerProcessingException {
271
        try {
UNCOV
272
            if (!Files.exists(dest)) {
×
273
                Files.createDirectories(dest);
×
274
            }
275

UNCOV
276
            if (!FileUtils.copyFilesRecursive(context.getLogger(), src, dest)) {
×
277
                throw new PackagerProcessingException(RB.$("ERROR_copy_files_from_to",
×
278
                    context.relativizeToBasedir(src),
×
279
                    context.relativizeToBasedir(dest)));
×
280
            }
281
        } catch (IOException e) {
×
282
            throw new PackagerProcessingException(RB.$("ERROR_unexpected_copy_files_from_to",
×
283
                context.relativizeToBasedir(src),
×
284
                context.relativizeToBasedir(dest)), e);
×
UNCOV
285
        }
×
UNCOV
286
    }
×
287

288
    protected boolean verifyAndAddArtifacts(TemplateContext props,
289
                                            Distribution distribution) {
UNCOV
290
        return verifyAndAddArtifacts(props, distribution, collectArtifacts(distribution));
×
291
    }
292

293
    protected boolean verifyAndAddArtifacts(TemplateContext props,
294
                                            Distribution distribution,
295
                                            List<Artifact> artifacts) {
UNCOV
296
        List<Artifact> activeArtifacts = artifacts.stream()
×
UNCOV
297
            .filter(Artifact::isActiveAndSelected)
×
UNCOV
298
            .collect(toList());
×
299

UNCOV
300
        if (activeArtifacts.isEmpty()) {
×
301
            // we can't proceed
302
            context.getLogger().warn(RB.$("packager.no.matching.artifacts"),
×
303
                distribution.getName(), capitalize(packager.getType()));
×
304
            return false;
×
305
        }
306

UNCOV
307
        int count = 0;
×
UNCOV
308
        for (Artifact artifact : activeArtifacts) {
×
UNCOV
309
            String artifactUrl = Artifacts.resolveDownloadUrl(context, packager.getType(), distribution, artifact);
×
UNCOV
310
            if (isBlank(artifactUrl)) continue;
×
UNCOV
311
            count++;
×
312

UNCOV
313
            String platform = artifact.getPlatform();
×
UNCOV
314
            String artifactPlatform = isNotBlank(platform) ? capitalize(platform) : "";
×
UNCOV
315
            String platformReplaced = distribution.getPlatform().applyReplacements(platform);
×
UNCOV
316
            String artifactPlatformReplaced = isNotBlank(platformReplaced) ? capitalize(platformReplaced) : "";
×
317
            // add extra properties without clobbering existing keys
UNCOV
318
            Map<String, Object> artifactProps = artifact.resolvedExtraProperties(ARTIFACT + artifactPlatform);
×
UNCOV
319
            artifactProps.keySet().stream()
×
UNCOV
320
                .filter(k -> !props.contains(k))
×
UNCOV
321
                .forEach(k -> props.set(k, artifactProps.get(k)));
×
322

UNCOV
323
            Path artifactPath = artifact.getEffectivePath(context, distribution);
×
324

UNCOV
325
            long artifactSize = 0;
×
326
            try {
UNCOV
327
                artifactSize = Files.size(artifactPath);
×
328
            } catch (IOException ignored) {
×
329
                // this would be strange
330
                context.getLogger().trace(ignored);
×
UNCOV
331
            }
×
332

UNCOV
333
            String artifactFile = artifact.getEffectivePath().getFileName().toString();
×
UNCOV
334
            String artifactFileName = getFilename(artifactFile, FileType.getSupportedExtensions());
×
UNCOV
335
            String artifactRootEntryName = resolveRootEntryName(artifact.getEffectivePath());
×
UNCOV
336
            String artifactFileExtension = "";
×
UNCOV
337
            String artifactFileFormat = "";
×
338

UNCOV
339
            if (!artifactFile.equals(artifactFileName)) {
×
UNCOV
340
                artifactFileExtension = artifactFile.substring(artifactFileName.length());
×
UNCOV
341
                artifactFileFormat = artifactFileExtension.substring(1);
×
342
            }
343

UNCOV
344
            String artifactName = "";
×
UNCOV
345
            String artifactVersion = "";
×
UNCOV
346
            String projectVersion = context.getModel().getProject().getEffectiveVersion();
×
UNCOV
347
            if (isNotBlank(projectVersion) && artifactFileName.contains(projectVersion)) {
×
UNCOV
348
                artifactName = artifactFileName.substring(0, artifactFileName.indexOf(projectVersion));
×
UNCOV
349
                if (artifactName.endsWith("-")) {
×
UNCOV
350
                    artifactName = artifactName.substring(0, artifactName.length() - 1);
×
351
                }
UNCOV
352
                artifactVersion = projectVersion;
×
353
            }
UNCOV
354
            projectVersion = context.getModel().getProject().getVersion();
×
UNCOV
355
            if (isBlank(artifactName) && isNotBlank(projectVersion) && artifactFileName.contains(projectVersion)) {
×
356
                artifactName = artifactFileName.substring(0, artifactFileName.indexOf(projectVersion));
×
357
                if (artifactName.endsWith("-")) {
×
358
                    artifactName = artifactName.substring(0, artifactName.length() - 1);
×
359
                }
360
                artifactVersion = projectVersion;
×
361
            }
362

UNCOV
363
            String artifactOs = "";
×
UNCOV
364
            String artifactArch = "";
×
UNCOV
365
            if (isNotBlank(platform) && platform.contains("-")) {
×
UNCOV
366
                String[] parts = platform.split("-");
×
UNCOV
367
                artifactOs = parts[0];
×
UNCOV
368
                artifactArch = parts[1];
×
369
            }
370

UNCOV
371
            safePut(props, ARTIFACT + artifactPlatform + NAME, artifactName);
×
UNCOV
372
            safePut(props, ARTIFACT + artifactPlatform + VERSION, artifactVersion);
×
UNCOV
373
            safePut(props, ARTIFACT + artifactPlatform + OS, artifactOs);
×
UNCOV
374
            safePut(props, ARTIFACT + artifactPlatform + ARCH, artifactArch);
×
UNCOV
375
            safePut(props, ARTIFACT + artifactPlatform + FILE, artifactFile);
×
UNCOV
376
            safePut(props, ARTIFACT + artifactPlatform + SIZE, artifactSize);
×
UNCOV
377
            safePut(props, ARTIFACT + artifactPlatform + FILE_NAME, artifactFileName);
×
UNCOV
378
            safePut(props, ARTIFACT + artifactPlatform + ROOT_ENTRY_NAME, artifactRootEntryName);
×
UNCOV
379
            safePut(props, ARTIFACT + artifactPlatform + FILE_EXTENSION, artifactFileExtension);
×
UNCOV
380
            safePut(props, ARTIFACT + artifactPlatform + FILE_FORMAT, artifactFileFormat);
×
381

UNCOV
382
            safePut(props, ARTIFACT + artifactPlatformReplaced + NAME, artifactName);
×
UNCOV
383
            safePut(props, ARTIFACT + artifactPlatformReplaced + VERSION, artifactVersion);
×
UNCOV
384
            safePut(props, ARTIFACT + artifactPlatformReplaced + OS, artifactOs);
×
UNCOV
385
            safePut(props, ARTIFACT + artifactPlatformReplaced + ARCH, artifactArch);
×
UNCOV
386
            safePut(props, ARTIFACT + artifactPlatformReplaced + FILE, artifactFile);
×
UNCOV
387
            safePut(props, ARTIFACT + artifactPlatformReplaced + SIZE, artifactSize);
×
UNCOV
388
            safePut(props, ARTIFACT + artifactPlatformReplaced + FILE_NAME, artifactFileName);
×
UNCOV
389
            safePut(props, ARTIFACT + artifactPlatformReplaced + ROOT_ENTRY_NAME, artifactRootEntryName);
×
UNCOV
390
            safePut(props, ARTIFACT + artifactPlatformReplaced + FILE_EXTENSION, artifactFileExtension);
×
UNCOV
391
            safePut(props, ARTIFACT + artifactPlatformReplaced + FILE_FORMAT, artifactFileFormat);
×
392

UNCOV
393
            for (Algorithm algorithm : context.getModel().getChecksum().getAlgorithms()) {
×
UNCOV
394
                safePut(props, ARTIFACT + artifactPlatform + CHECKSUM + capitalize(algorithm.formatted()), artifact.getHash(algorithm));
×
UNCOV
395
                safePut(props, ARTIFACT + artifactPlatformReplaced + CHECKSUM + capitalize(algorithm.formatted()), artifact.getHash(algorithm));
×
UNCOV
396
            }
×
397

UNCOV
398
            safePut(props, ARTIFACT + artifactPlatform + URL, artifactUrl);
×
UNCOV
399
            safePut(props, ARTIFACT + artifactPlatformReplaced + URL, artifactUrl);
×
UNCOV
400
            props.setAll(context.getModel().getUpload()
×
UNCOV
401
                .resolveDownloadUrls(context, distribution, artifact, ARTIFACT + artifactPlatform));
×
UNCOV
402
            props.setAll(context.getModel().getUpload()
×
UNCOV
403
                .resolveDownloadUrls(context, distribution, artifact, ARTIFACT + artifactPlatformReplaced));
×
404

UNCOV
405
            if (count == 1) {
×
UNCOV
406
                props.setAll(context.getModel().getUpload()
×
UNCOV
407
                    .resolveDownloadUrls(context, distribution, artifact, DISTRIBUTION));
×
UNCOV
408
                safePut(props, KEY_DISTRIBUTION_ARTIFACT, artifact);
×
UNCOV
409
                safePut(props, KEY_DISTRIBUTION_URL, artifactUrl);
×
UNCOV
410
                safePut(props, KEY_DISTRIBUTION_SIZE, artifactSize);
×
UNCOV
411
                safePut(props, KEY_DISTRIBUTION_SHA_256, artifact.getHash(Algorithm.SHA_256));
×
UNCOV
412
                for (Algorithm algorithm : context.getModel().getChecksum().getAlgorithms()) {
×
UNCOV
413
                    safePut(props, DISTRIBUTION + CHECKSUM + capitalize(algorithm.formatted()), artifact.getHash(algorithm));
×
UNCOV
414
                }
×
415

UNCOV
416
                safePut(props, KEY_DISTRIBUTION_ARTIFACT_PLATFORM, platform);
×
UNCOV
417
                safePut(props, KEY_DISTRIBUTION_ARTIFACT_PLATFORM_REPLACED, platformReplaced);
×
UNCOV
418
                safePut(props, KEY_DISTRIBUTION_ARTIFACT_NAME, artifactName);
×
UNCOV
419
                safePut(props, KEY_DISTRIBUTION_ARTIFACT_VERSION, artifactVersion);
×
UNCOV
420
                safePut(props, KEY_DISTRIBUTION_ARTIFACT_OS, artifactOs);
×
UNCOV
421
                safePut(props, KEY_DISTRIBUTION_ARTIFACT_ARCH, artifactArch);
×
UNCOV
422
                safePut(props, KEY_DISTRIBUTION_ARTIFACT_SIZE, artifactSize);
×
UNCOV
423
                safePut(props, KEY_DISTRIBUTION_ARTIFACT_FILE, artifactFile);
×
UNCOV
424
                safePut(props, KEY_DISTRIBUTION_ARTIFACT_FILE_NAME, artifactFileName);
×
UNCOV
425
                safePut(props, KEY_DISTRIBUTION_ARTIFACT_ROOT_ENTRY_NAME, artifactRootEntryName);
×
UNCOV
426
                safePut(props, KEY_DISTRIBUTION_ARTIFACT_FILE_EXTENSION, artifactFileExtension);
×
UNCOV
427
                safePut(props, KEY_DISTRIBUTION_ARTIFACT_FILE_FORMAT, artifactFileFormat);
×
428

UNCOV
429
                safePut(props, KEY_ARTIFACT_PLATFORM, platform);
×
UNCOV
430
                safePut(props, KEY_ARTIFACT_PLATFORM_REPLACED, platformReplaced);
×
UNCOV
431
                safePut(props, KEY_ARTIFACT_NAME, artifactName);
×
UNCOV
432
                safePut(props, KEY_ARTIFACT_VERSION, artifactVersion);
×
UNCOV
433
                safePut(props, KEY_ARTIFACT_OS, artifactOs);
×
UNCOV
434
                safePut(props, KEY_ARTIFACT_ARCH, artifactArch);
×
UNCOV
435
                safePut(props, KEY_ARTIFACT_SIZE, artifactSize);
×
UNCOV
436
                safePut(props, KEY_ARTIFACT_FILE, artifactFile);
×
UNCOV
437
                safePut(props, KEY_ARTIFACT_FILE_NAME, artifactFileName);
×
UNCOV
438
                safePut(props, KEY_ARTIFACT_ROOT_ENTRY_NAME, artifactRootEntryName);
×
UNCOV
439
                safePut(props, KEY_ARTIFACT_FILE_EXTENSION, artifactFileExtension);
×
UNCOV
440
                safePut(props, KEY_ARTIFACT_FILE_FORMAT, artifactFileFormat);
×
441

442
                // add extra properties without clobbering existing keys
UNCOV
443
                Map<String, Object> aprops = artifact.resolvedExtraProperties();
×
UNCOV
444
                TemplateContext bprops = new TemplateContext(aprops);
×
UNCOV
445
                applyTemplates(aprops, bprops);
×
UNCOV
446
                aprops.keySet().stream()
×
UNCOV
447
                    .filter(k -> !props.contains(k))
×
UNCOV
448
                    .forEach(k -> props.set(k, aprops.get(k)));
×
449
            }
UNCOV
450
        }
×
451

UNCOV
452
        return count > 0;
×
453
    }
454

455
    protected List<Artifact> collectArtifacts(Distribution distribution) {
UNCOV
456
        return packager.resolveArtifacts(context, distribution);
×
457
    }
458

459
    protected void info(ByteArrayOutputStream out) {
460
        log(out, context.getLogger()::info);
×
461
    }
×
462

463
    protected void error(ByteArrayOutputStream err) {
464
        log(err, context.getLogger()::error);
×
465
    }
×
466

467
    private void log(ByteArrayOutputStream stream, Consumer<? super String> consumer) {
468
        String str = IoUtils.toString(stream);
×
469
        if (isBlank(str)) return;
×
470

471
        Arrays.stream(str.split(System.lineSeparator()))
×
472
            .forEach(consumer);
×
473
    }
×
474

475
    protected Path getPrepareDirectory(TemplateContext props) {
UNCOV
476
        return props.get(KEY_DISTRIBUTION_PREPARE_DIRECTORY);
×
477
    }
478

479
    protected Path getPackageDirectory(TemplateContext props) {
UNCOV
480
        return props.get(KEY_DISTRIBUTION_PACKAGE_DIRECTORY);
×
481
    }
482

483
    protected void safePut(TemplateContext dest, String key, Object value) {
UNCOV
484
        if (value instanceof CharSequence && isNotBlank(String.valueOf(value)) || null != value) {
×
UNCOV
485
            dest.set(key, value);
×
486
        }
UNCOV
487
    }
×
488

489
    protected Optional<Stereotype> resolveStereotype(String fileName) {
UNCOV
490
        for (Stereotype stereotype : packager.getSupportedStereotypes()) {
×
UNCOV
491
            if (fileName.startsWith(stereotype.formatted() + "-")) {
×
UNCOV
492
                return Optional.of(stereotype);
×
493
            }
UNCOV
494
        }
×
495

UNCOV
496
        return Optional.empty();
×
497
    }
498
}
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