• 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/AbstractTemplatePackagerProcessor.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.apache.commons.io.IOUtils;
21
import org.jreleaser.bundle.RB;
22
import org.jreleaser.model.internal.JReleaserContext;
23
import org.jreleaser.model.internal.distributions.Distribution;
24
import org.jreleaser.model.internal.packagers.TemplatePackager;
25
import org.jreleaser.model.spi.packagers.PackagerProcessingException;
26
import org.jreleaser.mustache.MustacheUtils;
27
import org.jreleaser.mustache.TemplateContext;
28
import org.jreleaser.templates.TemplateResource;
29
import org.jreleaser.util.FileUtils;
30

31
import java.io.IOException;
32
import java.io.InputStream;
33
import java.io.Reader;
34
import java.nio.charset.StandardCharsets;
35
import java.nio.file.Files;
36
import java.nio.file.Path;
37
import java.util.Map;
38

39
import static java.nio.charset.StandardCharsets.UTF_8;
40
import static java.nio.file.StandardOpenOption.CREATE;
41
import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
42
import static java.nio.file.StandardOpenOption.WRITE;
43
import static org.jreleaser.model.Constants.SKIP_LICENSE_FILE;
44
import static org.jreleaser.templates.TemplateUtils.resolveAndMergeTemplates;
45
import static org.jreleaser.templates.TemplateUtils.trimTplExtension;
46
import static org.jreleaser.util.FileUtils.createDirectoriesWithFullAccess;
47
import static org.jreleaser.util.FileUtils.grantFullAccess;
48
import static org.jreleaser.util.StringUtils.isFalse;
49

50
/**
51
 * @author Andres Almiray
52
 * @since 0.6.0
53
 */
54
public abstract class AbstractTemplatePackagerProcessor<T extends TemplatePackager<?>> extends AbstractPackagerProcessor<T> {
55
    protected AbstractTemplatePackagerProcessor(JReleaserContext context) {
UNCOV
56
        super(context);
×
UNCOV
57
    }
×
58

59
    @Override
60
    protected void doPrepareDistribution(Distribution distribution, TemplateContext props) throws PackagerProcessingException {
61
        try {
UNCOV
62
            doPrepareDistribution(distribution, props, distribution.getName(),
×
UNCOV
63
                getPrepareDirectory(props), getPackager().getTemplateDirectory(), getPackagerName(), true);
×
64
        } catch (IOException e) {
×
65
            throw new PackagerProcessingException(e);
×
UNCOV
66
        }
×
UNCOV
67
    }
×
68

69
    protected void doPrepareDistribution(Distribution distribution,
70
                                         TemplateContext props,
71
                                         String distributionName,
72
                                         Path prepareDirectory,
73
                                         String templateDirectory,
74
                                         String packagerName,
75
                                         boolean copyLicense) throws IOException, PackagerProcessingException {
76
        // cleanup from previous session
UNCOV
77
        FileUtils.deleteFiles(prepareDirectory);
×
UNCOV
78
        Files.createDirectories(prepareDirectory);
×
79

UNCOV
80
        context.getLogger().debug(RB.$("packager.resolve.templates"), distributionName, packagerName);
×
UNCOV
81
        Map<String, TemplateResource> templates = resolveAndMergeTemplates(context.getLogger(),
×
UNCOV
82
            distribution.getType().name(),
×
83
            // leave this one be!
UNCOV
84
            getPackagerName(),
×
UNCOV
85
            context.getModel().getProject().isSnapshot(),
×
UNCOV
86
            context.getBasedir().resolve(templateDirectory));
×
87

UNCOV
88
        for (Map.Entry<String, TemplateResource> entry : templates.entrySet()) {
×
UNCOV
89
            String filename = entry.getKey();
×
UNCOV
90
            if (isSkipped(filename)) {
×
91
                context.getLogger().debug(RB.$("packager.skipped.template"), filename, distributionName, packagerName);
×
92
                continue;
×
93
            }
94

UNCOV
95
            TemplateResource value = entry.getValue();
×
UNCOV
96
            if (value.isReader()) {
×
UNCOV
97
                context.getLogger().debug(RB.$("packager.evaluate.template"), filename, distributionName, packagerName);
×
UNCOV
98
                String content = applyTemplate(filename, value.getReader(), props);
×
UNCOV
99
                if (!content.endsWith(System.lineSeparator())) {
×
UNCOV
100
                    content += System.lineSeparator();
×
101
                }
UNCOV
102
                context.getLogger().debug(RB.$("packager.write.template"), filename, distributionName, packagerName);
×
UNCOV
103
                writeFile(distribution, content, props, prepareDirectory, filename);
×
UNCOV
104
            } else {
×
UNCOV
105
                context.getLogger().debug(RB.$("packager.write.file"), filename, distributionName, packagerName);
×
UNCOV
106
                writeFile(distribution, value.getInputStream(), props, prepareDirectory, filename);
×
107
            }
UNCOV
108
        }
×
109

UNCOV
110
        if (copyLicense && isFalse(packager.getExtraProperties().get(SKIP_LICENSE_FILE))) {
×
UNCOV
111
            context.getLogger().debug(RB.$("packager.copy.license"));
×
UNCOV
112
            FileUtils.copyFiles(context.getLogger(),
×
UNCOV
113
                context.getBasedir(),
×
UNCOV
114
                prepareDirectory, path -> path.getFileName().startsWith("LICENSE"));
×
115
        }
UNCOV
116
    }
×
117

118
    protected String applyTemplate(String fileName, Reader reader, TemplateContext props) {
UNCOV
119
        return MustacheUtils.applyTemplate(reader, props);
×
120
    }
121

122
    public boolean isSkipped(String filename) {
123
        // check explicit match
UNCOV
124
        if (packager.getSkipTemplates().contains(filename)) return true;
×
125
        // check using string contains
UNCOV
126
        if (packager.getSkipTemplates().stream()
×
UNCOV
127
            .anyMatch(filename::contains)) return true;
×
128
        // check using regex
UNCOV
129
        if (packager.getSkipTemplates().stream()
×
UNCOV
130
            .anyMatch(filename::matches)) return true;
×
131

132
        // remove .tpl and check again
UNCOV
133
        String fname = trimTplExtension(filename);
×
134

135
        // check explicit match
UNCOV
136
        if (packager.getSkipTemplates().contains(fname)) return true;
×
137
        // check using string contains
UNCOV
138
        if (packager.getSkipTemplates().stream()
×
UNCOV
139
            .anyMatch(fname::contains)) return true;
×
140
        // check using regex
UNCOV
141
        return packager.getSkipTemplates().stream()
×
UNCOV
142
            .anyMatch(fname::matches);
×
143
    }
144

145
    @Override
146
    protected void doPackageDistribution(Distribution distribution, TemplateContext props) throws PackagerProcessingException {
UNCOV
147
        doPackageDistribution(distribution, props, getPackageDirectory(props));
×
UNCOV
148
    }
×
149

150
    protected void doPackageDistribution(Distribution distribution, TemplateContext props, Path packageDirectory) throws PackagerProcessingException {
151
        try {
152
            // cleanup from previous session
UNCOV
153
            FileUtils.deleteFiles(packageDirectory);
×
UNCOV
154
            Files.createDirectories(packageDirectory);
×
155
        } catch (IOException e) {
×
156
            throw new PackagerProcessingException(e);
×
UNCOV
157
        }
×
UNCOV
158
    }
×
159

160
    protected abstract void writeFile(Distribution distribution, String content, TemplateContext props, Path outputDirectory, String fileName) throws PackagerProcessingException;
161

162
    protected void writeFile(Distribution distribution, InputStream inputStream, TemplateContext props, Path outputDirectory, String fileName) throws PackagerProcessingException {
UNCOV
163
        Path outputFile = outputDirectory.resolve(fileName);
×
164

UNCOV
165
        writeFile(inputStream, outputFile);
×
UNCOV
166
    }
×
167

168
    protected void writeFile(Reader reader, Path outputFile) throws PackagerProcessingException {
169
        try {
170
            createDirectoriesWithFullAccess(outputFile.getParent());
×
171
            Files.write(outputFile, IOUtils.toByteArray(reader, StandardCharsets.UTF_8), CREATE, WRITE, TRUNCATE_EXISTING);
×
172
            grantFullAccess(outputFile);
×
173
        } catch (Exception e) {
×
174
            throw new PackagerProcessingException(RB.$("ERROR_unexpected_error_writing_file", outputFile.toAbsolutePath()), e);
×
175
        }
×
176
    }
×
177

178
    protected void writeFile(InputStream inputStream, Path outputFile) throws PackagerProcessingException {
179
        try {
UNCOV
180
            createDirectoriesWithFullAccess(outputFile.getParent());
×
UNCOV
181
            Files.write(outputFile, IOUtils.toByteArray(inputStream), CREATE, WRITE, TRUNCATE_EXISTING);
×
UNCOV
182
            grantFullAccess(outputFile);
×
183
        } catch (Exception e) {
×
184
            throw new PackagerProcessingException(RB.$("ERROR_unexpected_error_writing_file", outputFile.toAbsolutePath()), e);
×
UNCOV
185
        }
×
UNCOV
186
    }
×
187

188
    protected void writeFile(byte[] content, Path outputFile) throws PackagerProcessingException {
189
        try {
UNCOV
190
            createDirectoriesWithFullAccess(outputFile.getParent());
×
UNCOV
191
            Files.write(outputFile, content, CREATE, WRITE, TRUNCATE_EXISTING);
×
UNCOV
192
            grantFullAccess(outputFile);
×
193
        } catch (Exception e) {
×
194
            throw new PackagerProcessingException(RB.$("ERROR_unexpected_error_writing_file", outputFile.toAbsolutePath()), e);
×
UNCOV
195
        }
×
UNCOV
196
    }
×
197

198
    protected void writeFile(String content, Path outputFile) throws PackagerProcessingException {
UNCOV
199
        writeFile(content.getBytes(UTF_8), outputFile);
×
UNCOV
200
    }
×
201
}
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