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

jreleaser / jreleaser / #548

30 Oct 2025 09:00PM UTC coverage: 48.236% (-0.02%) from 48.255%
#548

push

github

aalmiray
deps: Update junit5 to 6.0.0

26007 of 53916 relevant lines covered (48.24%)

0.48 hits per line

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

73.68
/core/jreleaser-engine/src/main/java/org/jreleaser/engine/checksum/Checksum.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.engine.checksum;
19

20
import org.jreleaser.bundle.RB;
21
import org.jreleaser.model.JReleaserException;
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.util.Artifacts;
26
import org.jreleaser.util.Algorithm;
27
import org.jreleaser.util.ChecksumUtils;
28

29
import java.io.IOException;
30
import java.nio.file.Files;
31
import java.nio.file.Path;
32
import java.util.ArrayList;
33
import java.util.LinkedHashMap;
34
import java.util.List;
35
import java.util.Map;
36

37
import static java.nio.charset.StandardCharsets.UTF_8;
38
import static org.jreleaser.model.api.checksum.Checksum.KEY_SKIP_CHECKSUM;
39
import static org.jreleaser.util.StringUtils.isNotBlank;
40

41
/**
42
 * @author Andres Almiray
43
 * @since 0.1.0
44
 */
45
public final class Checksum {
46
    private Checksum() {
47
        // noop
48
    }
49

50
    public static void collectAndWriteChecksums(JReleaserContext context) throws JReleaserException {
51
        context.getLogger().info(RB.$("checksum.header"));
1✔
52
        context.getLogger().increaseIndent();
1✔
53
        context.getLogger().setPrefix("checksum");
1✔
54

55
        try {
56
            doCollectAndWriteChecksums(context);
1✔
57
        } finally {
58
            context.getLogger().restorePrefix();
1✔
59
            context.getLogger().decreaseIndent();
1✔
60
        }
61
    }
1✔
62

63
    private static void doCollectAndWriteChecksums(JReleaserContext context) throws JReleaserException {
64
        Map<Algorithm, List<String>> checksums = new LinkedHashMap<>();
1✔
65

66
        if (context.getModel().getChecksum().isFiles()) {
1✔
67
            for (Artifact artifact : Artifacts.resolveFiles(context)) {
1✔
68
                if (!artifact.isActiveAndSelected() || artifact.extraPropertyIsTrue(KEY_SKIP_CHECKSUM) ||
1✔
69
                    artifact.isOptional(context) && !artifact.resolvedPathExists()) continue;
×
70

71
                for (Algorithm algorithm : context.getModel().getChecksum().getAlgorithms()) {
×
72
                    readHash(context, algorithm, artifact);
×
73
                    List<String> list = checksums.computeIfAbsent(algorithm, k -> new ArrayList<>());
×
74
                    list.add(artifact.getHash(algorithm) + "  " + artifact.getEffectivePath(context).getFileName());
×
75
                }
×
76
            }
×
77
        }
78

79
        if (context.getModel().getChecksum().isArtifacts()) {
1✔
80
            for (Distribution distribution : context.getModel().getActiveDistributions()) {
1✔
81
                for (Artifact artifact : distribution.getArtifacts()) {
1✔
82
                    if (!artifact.isActiveAndSelected()) continue;
1✔
83
                    artifact.getEffectivePath(context, distribution);
1✔
84
                    if (artifact.isOptional(context) && !artifact.resolvedPathExists()) continue;
1✔
85

86
                    for (Algorithm algorithm : context.getModel().getChecksum().getAlgorithms()) {
1✔
87
                        readHash(context, distribution, algorithm, artifact);
1✔
88
                        List<String> list = checksums.computeIfAbsent(algorithm, k -> new ArrayList<>());
1✔
89
                        list.add(artifact.getHash(algorithm) + "  " + artifact.getEffectivePath(context, distribution).getFileName());
1✔
90
                    }
1✔
91
                }
1✔
92
            }
1✔
93
        }
94

95
        if (checksums.isEmpty()) {
1✔
96
            context.getLogger().info(RB.$("checksum.not.enabled"));
1✔
97
            context.getLogger().decreaseIndent();
1✔
98
            context.getLogger().restorePrefix();
1✔
99
            return;
1✔
100
        }
101

102
        for (Map.Entry<Algorithm, List<String>> entry : checksums.entrySet()) {
1✔
103
            Algorithm algorithm = entry.getKey();
1✔
104
            List<String> list = entry.getValue();
1✔
105

106
            Path checksumsFilePath = context.getChecksumsDirectory()
1✔
107
                .resolve(context.getModel().getChecksum().getResolvedName(context, algorithm));
1✔
108

109
            String newContent = String.join(System.lineSeparator(), list) + System.lineSeparator();
1✔
110

111
            try {
112
                if (Files.exists(checksumsFilePath)) {
1✔
113
                    String oldContent = new String(Files.readAllBytes(checksumsFilePath), UTF_8);
1✔
114
                    if (newContent.equals(oldContent)) {
1✔
115
                        // no need to write down the same content
116
                        context.getLogger().info(RB.$("checksum.not.changed"));
×
117
                        context.getLogger().restorePrefix();
×
118
                        context.getLogger().decreaseIndent();
×
119
                        return;
×
120
                    }
121
                }
122
            } catch (IOException ignored) {
×
123
                // OK
124
            }
1✔
125

126
            try {
127
                if (isNotBlank(newContent)) {
1✔
128
                    Files.createDirectories(context.getChecksumsDirectory());
1✔
129
                    Files.write(checksumsFilePath, newContent.getBytes(UTF_8));
1✔
130
                } else {
131
                    Files.deleteIfExists(checksumsFilePath);
×
132
                }
133
            } catch (IOException e) {
×
134
                throw new JReleaserException(RB.$("ERROR_unexpected_error_checksum", checksumsFilePath.toAbsolutePath()), e);
×
135
            }
1✔
136
        }
1✔
137
    }
1✔
138

139
    public static void readHash(JReleaserContext context, Distribution distribution, Algorithm algorithm, Artifact artifact) throws JReleaserException {
140
        Path artifactPath = artifact.getEffectivePath(context, distribution);
1✔
141
        Path checksumPath = context.getChecksumsDirectory().resolve(distribution.getName())
1✔
142
            .resolve(artifactPath.getFileName() + "." + algorithm.formatted());
1✔
143

144
        readHash(context, algorithm, artifact, artifactPath, checksumPath);
1✔
145
    }
1✔
146

147
    public static void readHash(JReleaserContext context, Algorithm algorithm, Artifact artifact) throws JReleaserException {
148
        Path artifactPath = artifact.getEffectivePath(context);
1✔
149
        Path checksumPath = context.getChecksumsDirectory()
1✔
150
            .resolve(artifactPath.getFileName() + "." + algorithm.formatted());
1✔
151

152
        readHash(context, algorithm, artifact, artifactPath, checksumPath);
1✔
153
    }
1✔
154

155
    private static void readHash(JReleaserContext context,
156
                                 Algorithm algorithm,
157
                                 Artifact artifact,
158
                                 Path artifactPath,
159
                                 Path checksumPath) throws JReleaserException {
160
        if (!Files.exists(artifactPath)) {
1✔
161
            throw new JReleaserException(RB.$("ERROR_artifact_does_not_exist", context.relativizeToBasedir(artifactPath)));
×
162
        }
163

164
        if (!Files.exists(checksumPath)) {
1✔
165
            context.getLogger().debug(RB.$("checksum.not.exist"), context.relativizeToBasedir(checksumPath));
1✔
166
            calculateHash(context, artifactPath, checksumPath, algorithm);
1✔
167
        } else if (artifactPath.toFile().lastModified() > checksumPath.toFile().lastModified()) {
1✔
168
            context.getLogger().debug(RB.$("checksum.file.newer"),
×
169
                context.relativizeToBasedir(artifactPath),
×
170
                context.relativizeToBasedir(checksumPath));
×
171
            calculateHash(context, artifactPath, checksumPath, algorithm);
×
172
        }
173

174
        try {
175
            context.getLogger().debug(RB.$("checksum.reading"),
1✔
176
                context.relativizeToBasedir(checksumPath));
1✔
177
            artifact.setHash(algorithm, new String(Files.readAllBytes(checksumPath), UTF_8));
1✔
178
        } catch (IOException e) {
×
179
            throw new JReleaserException(RB.$("ERROR_unexpected_error_hash_read", context.relativizeToBasedir(checksumPath)), e);
×
180
        }
1✔
181
    }
1✔
182

183
    public static String calculateHash(JReleaserContext context, Path input, Path output) throws JReleaserException {
184
        return calculateHash(context, input, output, Algorithm.SHA_256);
×
185
    }
186

187
    public static String calculateHash(JReleaserContext context, Path input, Path output, Algorithm algorithm) throws JReleaserException {
188
        try {
189
            context.getLogger().info("{}.{}", context.relativizeToBasedir(input), algorithm.formatted());
1✔
190
            String hashcode = ChecksumUtils.checksum(algorithm, Files.readAllBytes(input));
1✔
191
            output.toFile().getParentFile().mkdirs();
1✔
192
            Files.write(output, hashcode.getBytes(UTF_8));
1✔
193
            return hashcode;
1✔
194
        } catch (IOException e) {
×
195
            throw new JReleaserException(RB.$("ERROR_unexpected_error_calculate_checksum", input), e);
×
196
        }
197
    }
198
}
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