Skip to content

Commit 33d493c

Browse files
author
TheSnoozer
committed
move the 'Externalize' class from the git-commit-id-maven-plugin into the core project (use commit 1eefeb6d43792cd0f80d8435137442364e387267 as reference)
1 parent f14ed77 commit 33d493c

1 file changed

Lines changed: 367 additions & 0 deletions

File tree

Lines changed: 367 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,367 @@
1+
/*
2+
* This file is part of git-commit-id-plugin-core by Konrad 'ktoso' Malawski <konrad.malawski@java.pl>
3+
*
4+
* git-commit-id-plugin-core is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU Lesser General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* git-commit-id-plugin-core is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU Lesser General Public License
15+
* along with git-commit-id-plugin-core. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
package pl.project13.core;
19+
20+
import pl.project13.core.cibuild.BuildServerDataProvider;
21+
import pl.project13.core.git.GitDescribeConfig;
22+
import pl.project13.core.log.LogInterface;
23+
import pl.project13.core.util.BuildFileChangeListener;
24+
25+
import javax.annotation.Nonnull;
26+
import javax.annotation.Nullable;
27+
import java.io.File;
28+
import java.nio.charset.Charset;
29+
import java.text.SimpleDateFormat;
30+
import java.util.*;
31+
import java.util.function.Supplier;
32+
33+
public class GitCommitIdPlugin {
34+
public interface Callback {
35+
36+
/**
37+
* @return Supplier that provides the version of the project that is currently evaluated.
38+
* Used to determine {@link GitCommitPropertyConstant#BUILD_VERSION}.
39+
*/
40+
Supplier<String> supplyProjectVersion();
41+
42+
/**
43+
* @return Logging Interface
44+
*/
45+
@Nonnull
46+
LogInterface getLogInterface();
47+
48+
/**
49+
* @return The date format to be used for any dates exported by this plugin.
50+
* It should be a valid {@link SimpleDateFormat} string.
51+
*/
52+
@Nonnull
53+
String getDateFormat();
54+
55+
/**
56+
* <p>The timezone used in the date format of dates exported by this plugin.
57+
* It should be a valid Timezone string such as {@code 'America/Los_Angeles'}, {@code 'GMT+10'} or {@code 'PST'}.</p>
58+
*
59+
* <p>Try to avoid three-letter time zone IDs because the same abbreviation is often used for multiple time zones.
60+
* Please review <a href="https://docs.oracle.com/javase/7/docs/api/java/util/TimeZone.html">https://docs.oracle.com/javase/7/docs/api/java/util/TimeZone.html</a> for more information on this issue.</p>
61+
*
62+
* @return The timezone used in the date format of dates exported by this plugin.
63+
*/
64+
@Nonnull
65+
String getDateFormatTimeZone();
66+
67+
/**
68+
* The prefix to expose the properties on. For example {@code 'git'} would allow you to access {@code ${git.branch}}.
69+
*
70+
* @return The prefix to expose the properties on.
71+
*/
72+
@Nonnull
73+
String getPrefixDot();
74+
75+
/**
76+
* <p>List of properties to exclude from the resulting file.
77+
* May be useful when you want to hide {@code 'git.remote.origin.url'} (maybe because it contains your repo password?)
78+
* or the email of the committer.</p>
79+
*
80+
* <p>Supports wildcards: you can write {@code 'git.commit.user.*'} to exclude both the {@code 'name'}
81+
* as well as {@code 'email'} properties from being emitted into the resulting files.</p>
82+
*
83+
* <p><b>Note:</b> The strings here are Java regular expressions: {@code '.*'} is a wildcard, not plain {@code '*'}.</p>
84+
*
85+
* @return List of properties to exclude
86+
*/
87+
List<String> getExcludeProperties();
88+
89+
/**
90+
* <p>List of properties to include into the resulting file. Only properties specified here will be included.
91+
* This list will be overruled by the {@code 'excludeProperties'}.</p>
92+
*
93+
* <p>Supports wildcards: you can write {@code 'git.commit.user.*'} to include both the {@code 'name'}
94+
* as well as {@code 'email'} properties into the resulting files.</p>
95+
*
96+
* <p><b>Note:</b> The strings here are Java regular expressions: {@code '.*'} is a wildcard, not plain {@code '*'}.</p>
97+
*
98+
* @return List of properties to include
99+
*/
100+
List<String> getIncludeOnlyProperties();
101+
102+
/**
103+
* Timestamp for reproducible output archive entries
104+
* (https://maven.apache.org/guides/mini/guide-reproducible-builds.html).
105+
* The value from <code>${project.build.outputTimestamp}</code> is either formatted as ISO 8601
106+
* <code>yyyy-MM-dd'T'HH:mm:ssXXX</code> or as an int representing seconds since the epoch (like
107+
* <a href="https://reproducible-builds.org/docs/source-date-epoch/">SOURCE_DATE_EPOCH</a>.
108+
*
109+
* @throws GitCommitIdExecutionException In case the user provided time stamp is invalid a GitCommitIdExecutionException is thrown
110+
* @return Timestamp for reproducible output archive entries.
111+
*/
112+
@Nullable
113+
Date getReproducibleBuildOutputTimestamp() throws GitCommitIdExecutionException;
114+
115+
/**
116+
* Set this to {@code 'true'} to use native Git executable to fetch information about the repository.
117+
* It is in most cases faster but requires a git executable to be installed in system.
118+
* By default the plugin will use jGit implementation as a source of information about the repository.
119+
*
120+
* @return Controls if this plugin should use the native Git executable.
121+
*/
122+
boolean useNativeGit();
123+
124+
/**
125+
* Allow to specify a timeout (in milliseconds) for fetching information with the native Git executable.
126+
* Note that {@code useNativeGit} needs to be set to {@code 'true'} to use native Git executable.
127+
*
128+
* @return A timeout (in milliseconds) for fetching information with the native Git executable.
129+
*/
130+
long getNativeGitTimeoutInMs();
131+
132+
/**
133+
* <p>Minimum length of {@code 'git.commit.id.abbrev'} property.
134+
* Value must be from 2 to 40 (inclusive), other values will result in an exception.</p>
135+
*
136+
* <p>An abbreviated commit is a shorter version of commit id. However, it is guaranteed to be unique.
137+
* To keep this contract, the plugin may decide to print an abbreviated version
138+
* that is longer than the value specified here.</p>
139+
*
140+
* <p><b>Example:</b> You have a very big repository, yet you set this value to 2. It's very probable that you'll end up
141+
* getting a 4 or 7 char long abbrev version of the commit id. If your repository, on the other hand,
142+
* has just 4 commits, you'll probably get a 2 char long abbreviation.</p>
143+
*
144+
* @return Minimum length of {@code 'git.commit.id.abbrev'} property.
145+
*/
146+
int getAbbrevLength();
147+
148+
/**
149+
* Configuration for the {@code 'git-describe'} command.
150+
* You can modify the dirty marker, abbrev length and other options here.
151+
*
152+
* @return Configuration for the {@code 'git-describe'} command.
153+
*/
154+
GitDescribeConfig getGitDescribe();
155+
156+
/**
157+
* <p>The mode of {@code 'git.commit.id'} property generation.</p>
158+
*
159+
* {@code 'git.commit.id'} property name is incompatible with json export
160+
* (see <a href="https://github.com/git-commit-id/git-commit-id-maven-plugin/issues/122">issue #122</a>).
161+
* This property allows one either to preserve backward compatibility or to enable fully valid json export:
162+
*
163+
* <ol>
164+
* <li>{@code 'flat'} (default) generates the property {@code 'git.commit.id'}, preserving backwards compatibility.</li>
165+
* <li>{@code 'full'} generates the property {@code 'git.commit.id.full'}, enabling fully valid json object export.</li>
166+
* </ol>
167+
*
168+
* <p><b>Note:</b> Depending on your plugin configuration you obviously can choose the `prefix` of your properties
169+
* by setting it accordingly in the plugin's configuration. As a result this is therefore only an illustration
170+
* what the switch means when the 'prefix' is set to it's default value.</p>
171+
* <p><b>Note:</b> If you set the value to something that's not equal to {@code 'flat'} or {@code 'full'} (ignoring the case)
172+
* the plugin will output a warning and will fallback to the default {@code 'flat'} mode.</p>
173+
*
174+
* @return The mode of {@code 'git.commit.id'} property generation.
175+
*/
176+
CommitIdGenerationMode getCommitIdGenerationMode();
177+
178+
/**
179+
* Use branch name from build environment. Set to {@code 'false'} to use JGit/GIT to get current branch name.
180+
* Useful when using the JGitflow maven plugin.
181+
* Note: If not using "Check out to specific local branch' and setting this to false may result in getting
182+
* detached head state and therefore a commit id as branch name.
183+
*
184+
* @return Controls if the branch name from build environment should be used.
185+
*/
186+
boolean getUseBranchNameFromBuildEnvironment();
187+
188+
/**
189+
* Controls whether the git plugin tries to access remote repos to fetch latest information
190+
* or only use local information.
191+
*
192+
* :warning: Before version 5.X.X the default was set to {@code false} causing the plugin to operate
193+
* in online-mode by default.
194+
*
195+
* @return Controls whether the git plugin tries to access remote repos to fetch latest information.
196+
*/
197+
boolean isOffline();
198+
199+
/**
200+
* Allow to tell the plugin what commit should be used as reference to generate the properties from.
201+
* By default this property is simply set to <p>HEAD</p> which should reference to the latest commit in your repository.
202+
*
203+
* In general this property can be set to something generic like <p>HEAD^1</p> or point to a branch or tag-name.
204+
* To support any kind or use-case this configuration can also be set to an entire commit-hash or it's abbreviated version.
205+
*
206+
* A use-case for this feature can be found in https://github.com/git-commit-id/git-commit-id-maven-plugin/issues/338.
207+
*
208+
* Please note that for security purposes not all references might be allowed as configuration.
209+
* If you have a specific use-case that is currently not white listed feel free to file an issue.
210+
*
211+
* @return Tell the plugin what commit should be used as reference to generate the properties from.
212+
*/
213+
String getEvaluateOnCommit();
214+
215+
/**
216+
* @return The root directory of the repository we want to check.
217+
*/
218+
File getDotGitDirectory();
219+
220+
/**
221+
* Set this to {@code 'true'} to generate a {@code 'git.properties'} file.
222+
* By default plugin only adds properties to maven project properties.
223+
*
224+
* @return Control if the plugin should generate a {@code 'git.properties'} file.
225+
*/
226+
boolean shouldGenerateGitPropertiesFile();
227+
228+
/**
229+
* Callback when the plugin wants to publish a set of properties.
230+
* @param properties The properties the plugin want's to publish to the user.
231+
*/
232+
void performPublishToAllSystemEnvironments(Properties properties);
233+
234+
/**
235+
* Callback when the plugin wants to perform the properties replacement.
236+
* @param properties The current set of properties.
237+
*/
238+
void performPropertiesReplacement(Properties properties);
239+
240+
/**
241+
* @return The output format of the generated properties file. Can either be "properties" or "json".
242+
*/
243+
// TODO: Why is this a String and not an enum?
244+
String getPropertiesOutputFormat();
245+
246+
/**
247+
* @return The BuildFileChangeListener that will be called when an output file of the plugin has changed
248+
*/
249+
BuildFileChangeListener getBuildFileChangeListener();
250+
251+
/**
252+
* @return The project name
253+
*/
254+
String getProjectName();
255+
256+
/**
257+
* @return The project base dir
258+
*/
259+
File getProjectBaseDir();
260+
261+
/**
262+
* @return The optional name of the properties filename where properties should be dumped into
263+
*/
264+
String getGenerateGitPropertiesFilename();
265+
266+
/**
267+
* @return The Charset in which format the properties should be dumped (e.g. 'UTF-8')
268+
*/
269+
Charset getPropertiesSourceCharset();
270+
271+
boolean shouldPropertiesEscapeUnicode();
272+
}
273+
274+
public static void runPlugin(@Nonnull Callback cb, @Nullable Properties contextProperties) throws GitCommitIdExecutionException {
275+
PropertiesFilterer propertiesFilterer = new PropertiesFilterer(cb.getLogInterface());
276+
277+
// The properties we store our data in and then expose them.
278+
Properties properties = contextProperties == null
279+
? new Properties()
280+
: contextProperties;
281+
282+
loadGitData(cb, properties);
283+
loadBuildData(cb, properties);
284+
// first round of publication and filtering
285+
// (we need to make variables available for the ParameterExpressionEvaluator)
286+
propertiesFilterer.filter(properties, cb.getIncludeOnlyProperties(), cb.getPrefixDot());
287+
propertiesFilterer.filterNot(properties, cb.getExcludeProperties(), cb.getPrefixDot());
288+
cb.performPublishToAllSystemEnvironments(properties);
289+
290+
cb.performPropertiesReplacement(properties);
291+
if (cb.shouldGenerateGitPropertiesFile()) {
292+
new PropertiesFileGenerator(
293+
cb.getLogInterface(),
294+
cb.getBuildFileChangeListener(),
295+
cb.getPropertiesOutputFormat(),
296+
cb.getPrefixDot(),
297+
cb.getProjectName()
298+
).maybeGeneratePropertiesFile(
299+
properties,
300+
cb.getProjectBaseDir(),
301+
cb.getGenerateGitPropertiesFilename(),
302+
cb.getPropertiesSourceCharset(),
303+
cb.shouldPropertiesEscapeUnicode()
304+
);
305+
}
306+
307+
// publish properties again since we might have new properties gained by the replacement
308+
cb.performPublishToAllSystemEnvironments(properties);
309+
}
310+
311+
protected static void loadBuildData(@Nonnull Callback cb, @Nonnull Properties properties) throws GitCommitIdExecutionException {
312+
Map<String, Supplier<String>> additionalProperties = Collections.singletonMap(
313+
GitCommitPropertyConstant.BUILD_VERSION, cb.supplyProjectVersion());
314+
BuildServerDataProvider buildServerDataProvider = BuildServerDataProvider.getBuildServerProvider(
315+
System.getenv(), cb.getLogInterface());
316+
buildServerDataProvider
317+
.setDateFormat(cb.getDateFormat())
318+
.setDateFormatTimeZone(cb.getDateFormatTimeZone())
319+
.setAdditionalProperties(additionalProperties)
320+
.setPrefixDot(cb.getPrefixDot())
321+
.setExcludeProperties(cb.getExcludeProperties())
322+
.setIncludeOnlyProperties(cb.getIncludeOnlyProperties());
323+
buildServerDataProvider.loadBuildData(properties, cb.getReproducibleBuildOutputTimestamp());
324+
}
325+
326+
protected static void loadGitData(@Nonnull Callback cb, @Nonnull Properties properties) throws GitCommitIdExecutionException {
327+
if (cb.useNativeGit()) {
328+
loadGitDataWithNativeGit(cb, properties);
329+
} else {
330+
loadGitDataWithJGit(cb, properties);
331+
}
332+
}
333+
334+
private static void loadGitDataWithNativeGit(@Nonnull Callback cb, @Nonnull Properties properties) throws GitCommitIdExecutionException {
335+
GitDataProvider nativeGitProvider = NativeGitProvider
336+
.on(cb.getDotGitDirectory().getParentFile(), cb.getNativeGitTimeoutInMs(), cb.getLogInterface())
337+
.setPrefixDot(cb.getPrefixDot())
338+
.setAbbrevLength(cb.getAbbrevLength())
339+
.setDateFormat(cb.getDateFormat())
340+
.setDateFormatTimeZone(cb.getDateFormatTimeZone())
341+
.setGitDescribe(cb.getGitDescribe())
342+
.setCommitIdGenerationMode(cb.getCommitIdGenerationMode())
343+
.setUseBranchNameFromBuildEnvironment(cb.getUseBranchNameFromBuildEnvironment())
344+
.setExcludeProperties(cb.getExcludeProperties())
345+
.setIncludeOnlyProperties(cb.getIncludeOnlyProperties())
346+
.setOffline(cb.isOffline());
347+
348+
nativeGitProvider.loadGitData(cb.getEvaluateOnCommit(), properties);
349+
}
350+
351+
private static void loadGitDataWithJGit(@Nonnull Callback cb, @Nonnull Properties properties) throws GitCommitIdExecutionException {
352+
GitDataProvider jGitProvider = JGitProvider
353+
.on(cb.getDotGitDirectory(), cb.getLogInterface())
354+
.setPrefixDot(cb.getPrefixDot())
355+
.setAbbrevLength(cb.getAbbrevLength())
356+
.setDateFormat(cb.getDateFormat())
357+
.setDateFormatTimeZone(cb.getDateFormatTimeZone())
358+
.setGitDescribe(cb.getGitDescribe())
359+
.setCommitIdGenerationMode(cb.getCommitIdGenerationMode())
360+
.setUseBranchNameFromBuildEnvironment(cb.getUseBranchNameFromBuildEnvironment())
361+
.setExcludeProperties(cb.getExcludeProperties())
362+
.setIncludeOnlyProperties(cb.getIncludeOnlyProperties())
363+
.setOffline(cb.isOffline());
364+
365+
jGitProvider.loadGitData(cb.getEvaluateOnCommit(), properties);
366+
}
367+
}

0 commit comments

Comments
 (0)