17
17
18
18
import static com .diffplug .spotless .GitPrePushHookInstaller .Executor .GRADLE ;
19
19
import static com .diffplug .spotless .GitPrePushHookInstaller .Executor .MAVEN ;
20
+ import static java .util .stream .Collectors .toList ;
20
21
import static org .assertj .core .api .Assertions .assertThat ;
21
22
22
- import java .util .ArrayList ;
23
23
import java .util .List ;
24
+ import java .util .concurrent .CopyOnWriteArrayList ;
25
+ import java .util .stream .IntStream ;
24
26
25
27
import org .junit .jupiter .api .AfterEach ;
26
28
import org .junit .jupiter .api .BeforeEach ;
31
33
class GitPrePushHookInstallerTest extends ResourceHarness {
32
34
private final static String OS = System .getProperty ("os.name" );
33
35
34
- private final List <String > logs = new ArrayList <>();
36
+ private final List <String > logs = new CopyOnWriteArrayList <>();
35
37
private final GitPreHookLogger logger = new GitPreHookLogger () {
36
38
@ Override
37
39
public void info (String format , Object ... arguments ) {
@@ -68,9 +70,9 @@ public void should_not_create_pre_hook_file_when_git_is_not_installed() throws E
68
70
gradle .install ();
69
71
70
72
// then
71
- assertThat (logs ).hasSize ( 2 );
72
- assertThat ( logs ). element ( 0 ). isEqualTo ( "Installing git pre-push hook" );
73
- assertThat ( logs ). element ( 1 ). isEqualTo ( "Git not found in root directory" );
73
+ assertThat (logs ).containsExactly (
74
+ "Installing git pre-push hook" ,
75
+ "Git not found in root directory" );
74
76
assertThat (newFile (".git/hooks/pre-push" )).doesNotExist ();
75
77
}
76
78
@@ -84,11 +86,11 @@ public void should_use_global_gradle_when_gradlew_is_not_installed() throws Exce
84
86
gradle .install ();
85
87
86
88
// then
87
- assertThat (logs ).hasSize ( 4 );
88
- assertThat ( logs ). element ( 0 ). isEqualTo ( "Installing git pre-push hook" );
89
- assertThat ( logs ). element ( 1 ). isEqualTo ( "Git pre-push hook not found, creating it" );
90
- assertThat ( logs ). element ( 2 ). isEqualTo ( "Local gradle wrapper (gradlew) not found, falling back to global command 'gradle'" );
91
- assertThat ( logs ). element ( 3 ). isEqualTo ( "Git pre-push hook installed successfully to the file " + newFile (".git/hooks/pre-push" ).getAbsolutePath ());
89
+ assertThat (logs ).containsExactly (
90
+ "Installing git pre-push hook" ,
91
+ "Git pre-push hook not found, creating it" ,
92
+ "Local gradle wrapper (gradlew) not found, falling back to global command 'gradle'" ,
93
+ "Git pre-push hook installed successfully to the file " + newFile (".git/hooks/pre-push" ).getAbsolutePath ());
92
94
93
95
final var content = gradleHookContent ("git_pre_hook/pre-push.created-tpl" , ExecutorType .GLOBAL );
94
96
assertFile (".git/hooks/pre-push" ).hasContent (content );
@@ -108,10 +110,10 @@ public void should_reinstall_pre_hook_file_when_hook_already_installed() throws
108
110
gradle .install ();
109
111
110
112
// then
111
- assertThat (logs ).hasSize ( 3 );
112
- assertThat ( logs ). element ( 0 ). isEqualTo ( "Installing git pre-push hook" );
113
- assertThat ( logs ). element ( 1 ). isEqualTo ( "Git pre-push hook already installed, reinstalling it" );
114
- assertThat ( logs ). element ( 2 ). isEqualTo ( "Git pre-push hook installed successfully to the file " + hookFile .getAbsolutePath ());
113
+ assertThat (logs ).containsExactly (
114
+ "Installing git pre-push hook" ,
115
+ "Git pre-push hook already installed, reinstalling it" ,
116
+ "Git pre-push hook installed successfully to the file " + hookFile .getAbsolutePath ());
115
117
116
118
final var content = gradleHookContent ("git_pre_hook/pre-push.existing-installed-end-tpl" , ExecutorType .WRAPPER );
117
119
assertFile (".git/hooks/pre-push" ).hasContent (content );
@@ -131,10 +133,10 @@ public void should_reinstall_pre_hook_file_when_hook_already_installed_in_the_mi
131
133
gradle .install ();
132
134
133
135
// then
134
- assertThat (logs ).hasSize ( 3 );
135
- assertThat ( logs ). element ( 0 ). isEqualTo ( "Installing git pre-push hook" );
136
- assertThat ( logs ). element ( 1 ). isEqualTo ( "Git pre-push hook already installed, reinstalling it" );
137
- assertThat ( logs ). element ( 2 ). isEqualTo ( "Git pre-push hook installed successfully to the file " + hookFile .getAbsolutePath ());
136
+ assertThat (logs ).containsExactly (
137
+ "Installing git pre-push hook" ,
138
+ "Git pre-push hook already installed, reinstalling it" ,
139
+ "Git pre-push hook installed successfully to the file " + hookFile .getAbsolutePath ());
138
140
139
141
final var content = gradleHookContent ("git_pre_hook/pre-push.existing-reinstalled-middle-tpl" , ExecutorType .WRAPPER );
140
142
assertFile (".git/hooks/pre-push" ).hasContent (content );
@@ -171,10 +173,10 @@ public void should_create_pre_hook_file_when_hook_file_does_not_exists() throws
171
173
gradle .install ();
172
174
173
175
// then
174
- assertThat (logs ).hasSize ( 3 );
175
- assertThat ( logs ). element ( 0 ). isEqualTo ( "Installing git pre-push hook" );
176
- assertThat ( logs ). element ( 1 ). isEqualTo ( "Git pre-push hook not found, creating it" );
177
- assertThat ( logs ). element ( 2 ). isEqualTo ( "Git pre-push hook installed successfully to the file " + newFile (".git/hooks/pre-push" ).getAbsolutePath ());
176
+ assertThat (logs ).containsExactly (
177
+ "Installing git pre-push hook" ,
178
+ "Git pre-push hook not found, creating it" ,
179
+ "Git pre-push hook installed successfully to the file " + newFile (".git/hooks/pre-push" ).getAbsolutePath ());
178
180
179
181
final var content = gradleHookContent ("git_pre_hook/pre-push.created-tpl" , ExecutorType .WRAPPER );
180
182
assertFile (".git/hooks/pre-push" ).hasContent (content );
@@ -192,9 +194,9 @@ public void should_append_to_existing_pre_hook_file_when_hook_file_exists() thro
192
194
gradle .install ();
193
195
194
196
// then
195
- assertThat (logs ).hasSize ( 2 );
196
- assertThat ( logs ). element ( 0 ). isEqualTo ( "Installing git pre-push hook" );
197
- assertThat ( logs ). element ( 1 ). isEqualTo ( "Git pre-push hook installed successfully to the file " + newFile (".git/hooks/pre-push" ).getAbsolutePath ());
197
+ assertThat (logs ).containsExactly (
198
+ "Installing git pre-push hook" ,
199
+ "Git pre-push hook installed successfully to the file " + newFile (".git/hooks/pre-push" ).getAbsolutePath ());
198
200
199
201
final var content = gradleHookContent ("git_pre_hook/pre-push.existing-installed-end-tpl" , ExecutorType .WRAPPER );
200
202
assertFile (".git/hooks/pre-push" ).hasContent (content );
@@ -211,10 +213,10 @@ public void should_create_pre_hook_file_for_maven_when_hook_file_does_not_exists
211
213
gradle .install ();
212
214
213
215
// then
214
- assertThat (logs ).hasSize ( 3 );
215
- assertThat ( logs ). element ( 0 ). isEqualTo ( "Installing git pre-push hook" );
216
- assertThat ( logs ). element ( 1 ). isEqualTo ( "Git pre-push hook not found, creating it" );
217
- assertThat ( logs ). element ( 2 ). isEqualTo ( "Git pre-push hook installed successfully to the file " + newFile (".git/hooks/pre-push" ).getAbsolutePath ());
216
+ assertThat (logs ).containsExactly (
217
+ "Installing git pre-push hook" ,
218
+ "Git pre-push hook not found, creating it" ,
219
+ "Git pre-push hook installed successfully to the file " + newFile (".git/hooks/pre-push" ).getAbsolutePath ());
218
220
219
221
final var content = mavenHookContent ("git_pre_hook/pre-push.created-tpl" , ExecutorType .WRAPPER );
220
222
assertFile (".git/hooks/pre-push" ).hasContent (content );
@@ -230,11 +232,11 @@ public void should_use_global_maven_when_maven_wrapper_is_not_installed() throws
230
232
gradle .install ();
231
233
232
234
// then
233
- assertThat (logs ).hasSize ( 4 );
234
- assertThat ( logs ). element ( 0 ). isEqualTo ( "Installing git pre-push hook" );
235
- assertThat ( logs ). element ( 1 ). isEqualTo ( "Git pre-push hook not found, creating it" );
236
- assertThat ( logs ). element ( 2 ). isEqualTo ( "Local maven wrapper (mvnw) not found, falling back to global command 'mvn'" );
237
- assertThat ( logs ). element ( 3 ). isEqualTo ( "Git pre-push hook installed successfully to the file " + newFile (".git/hooks/pre-push" ).getAbsolutePath ());
235
+ assertThat (logs ).containsExactly (
236
+ "Installing git pre-push hook" ,
237
+ "Git pre-push hook not found, creating it" ,
238
+ "Local maven wrapper (mvnw) not found, falling back to global command 'mvn'" ,
239
+ "Git pre-push hook installed successfully to the file " + newFile (".git/hooks/pre-push" ).getAbsolutePath ());
238
240
239
241
final var content = mavenHookContent ("git_pre_hook/pre-push.created-tpl" , ExecutorType .GLOBAL );
240
242
assertFile (".git/hooks/pre-push" ).hasContent (content );
@@ -334,6 +336,30 @@ public void should_use_gradle_global_when_bat_and_cmd_files_not_exists_for_windo
334
336
assertThat (hook ).contains ("SPOTLESS_EXECUTOR=gradle" );
335
337
}
336
338
339
+ @ Test
340
+ public void should_handle_parallel_installation () {
341
+ // given
342
+ setFile (".git/config" ).toContent ("" );
343
+
344
+ // when
345
+ parallelRun (() -> {
346
+ final var gradle = new GitPrePushHookInstallerGradle (logger , rootFolder ());
347
+ gradle .install ();
348
+ });
349
+
350
+ // then
351
+ assertThat (logs ).containsExactlyInAnyOrder (
352
+ "Installing git pre-push hook" ,
353
+ "Git pre-push hook not found, creating it" ,
354
+ "Parallel Spotless Git pre-push hook installation detected, skipping installation" ,
355
+ "Parallel Spotless Git pre-push hook installation detected, skipping installation" ,
356
+ "Local gradle wrapper (gradlew) not found, falling back to global command 'gradle'" ,
357
+ "Git pre-push hook installed successfully to the file " + newFile (".git/hooks/pre-push" ).getAbsolutePath ());
358
+
359
+ final var content = gradleHookContent ("git_pre_hook/pre-push.created-tpl" , ExecutorType .GLOBAL );
360
+ assertFile (".git/hooks/pre-push" ).hasContent (content );
361
+ }
362
+
337
363
private String gradleHookContent (String resourcePath , ExecutorType executorType ) {
338
364
return getTestResource (resourcePath )
339
365
.replace ("${executor}" , executorType == ExecutorType .WRAPPER ? "./" + newFile ("gradlew" ).getName () : "gradle" )
@@ -348,7 +374,31 @@ private String mavenHookContent(String resourcePath, ExecutorType executorType)
348
374
.replace ("${applyCommand}" , "spotless:apply" );
349
375
}
350
376
377
+ private void parallelRun (ThrowableRun runnable ) {
378
+ IntStream .range (0 , 3 )
379
+ .mapToObj (i -> new Thread (() -> {
380
+ try {
381
+ runnable .run ();
382
+ } catch (Exception e ) {
383
+ throw new RuntimeException (e );
384
+ }
385
+ }))
386
+ .peek (Thread ::start )
387
+ .collect (toList ())
388
+ .forEach (t -> {
389
+ try {
390
+ t .join ();
391
+ } catch (InterruptedException e ) {
392
+ throw new RuntimeException (e );
393
+ }
394
+ });
395
+ }
396
+
351
397
private enum ExecutorType {
352
398
WRAPPER , GLOBAL
353
399
}
400
+
401
+ private interface ThrowableRun {
402
+ void run () throws Exception ;
403
+ }
354
404
}
0 commit comments