Skip to content

Commit a786e53

Browse files
committed
Allow lenient patching
It will allow users to "unpatch" by just removing the init script. It support the first instinct of an user.
1 parent e4d2918 commit a786e53

File tree

4 files changed

+106
-6
lines changed

4 files changed

+106
-6
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package dev.nokee.init
2+
3+
import dev.gradleplugins.integtests.fixtures.AbstractGradleSpecification
4+
5+
import static dev.gradleplugins.runnerkit.GradleExecutor.gradleWrapper
6+
import static dev.gradleplugins.runnerkit.GradleRunner.create
7+
import static dev.nokee.init.fixtures.GradleRunnerUtils.configurePluginClasspathAsInitScriptDependencies
8+
9+
class GradleWrapperLenientPatchingFunctionalTest extends AbstractGradleSpecification {
10+
def setup() {
11+
def initScriptFile = file('init.gradle')
12+
initScriptFile << configurePluginClasspathAsInitScriptDependencies() << '''
13+
apply plugin: dev.nokee.init.NokeeInitPlugin
14+
'''
15+
executer.usingInitScript(initScriptFile).withArgument('-Dnokee-version').withTasks('wrapper').build()
16+
create(gradleWrapper()).inDirectory(testDirectory).withTasks('nokee').build()
17+
}
18+
19+
def "can delete nokee.init.gradle without breaking the build"() {
20+
file('gradle/nokee.init.gradle').delete()
21+
22+
expect:
23+
def result = create(gradleWrapper()).inDirectory(testDirectory).withTasks('tasks').build()
24+
!result.output.contains('nokee')
25+
}
26+
}

src/main/java/dev/nokee/init/internal/wrapper/GradleWrapperScript.java

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,13 @@
22

33
import lombok.EqualsAndHashCode;
44

5+
import java.util.Arrays;
6+
import java.util.List;
7+
58
import static dev.nokee.init.internal.utils.FilenameUtils.separatorsToUnix;
69
import static dev.nokee.init.internal.utils.FilenameUtils.separatorsToWindows;
10+
import static dev.nokee.init.internal.wrapper.GradleWrapperScriptPatcher.forContent;
11+
import static java.lang.String.join;
712

813
@EqualsAndHashCode
914
public final class GradleWrapperScript {
@@ -20,19 +25,35 @@ public String get() {
2025
public GradleWrapperScript patch(String pathToInitScript) {
2126
// Bash script
2227
if (content.contains("\"$APP_ARGS\"")) {
23-
return new GradleWrapperScript(content.replace("\"$APP_ARGS\"","--init-script \"\\\"$APP_HOME/" + separatorsToUnix(pathToInitScript) + "\\\"\" \"$APP_ARGS\""));
28+
return new GradleWrapperScript(join("\n", forContent(content).findLineWith("\"$APP_ARGS\"").injectBefore(bashScriptPath(pathToInitScript)).andPrependPillWith("\"$NOKEE_ARGS\" ").patch()));
2429
}
2530

2631
// Batch script 6.6 and above
2732
if (content.contains("%*")) {
28-
return new GradleWrapperScript(content.replace("%*", "--init-script \"%APP_HOME%\\" + separatorsToWindows(pathToInitScript) + "\" %*"));
33+
return new GradleWrapperScript(join("\r\n", forContent(content).findLineWith("%*").injectBefore(batchScriptPath(pathToInitScript)).andPrependPillWith("%NOKEE_ARGS% ").patch()));
2934
}
3035

3136
// Batch script 6.5 and lower
3237
if (content.contains("%CMD_LINE_ARGS%")) {
33-
return new GradleWrapperScript(content.replace("%CMD_LINE_ARGS%", "--init-script \"%APP_HOME%\\" + separatorsToWindows(pathToInitScript) + "\" %CMD_LINE_ARGS%"));
38+
return new GradleWrapperScript(join("\r\n", forContent(content).findLineWith("%CMD_LINE_ARGS%").injectBefore(batchScriptPath(pathToInitScript)).andPrependPillWith("%NOKEE_ARGS% ").patch()));
3439
}
3540

3641
throw new IllegalStateException("Could not find patching hook inside Gradle wrapper script.");
3742
}
43+
44+
private static List<String> bashScriptPath(String pathToInitScript) {
45+
return Arrays.asList(
46+
"NOKEE_INIT_SCRIPT_FILE=$APP_HOME/" + separatorsToUnix(pathToInitScript),
47+
"if [ -f \"$NOKEE_INIT_SCRIPT_FILE\" ] ; then",
48+
" NOKEE_ARGS=\"--init-script \\\"$NOKEE_INIT_SCRIPT_FILE\\\"\"",
49+
"fi",
50+
"");
51+
}
52+
53+
private static List<String> batchScriptPath(String pathToInitScript) {
54+
return Arrays.asList(
55+
"set NOKEE_INIT_SCRIPT_FILE=%APP_HOME%\\" + separatorsToWindows(pathToInitScript),
56+
"if exist NOKEE_INIT_SCRIPT_FILE set NOKEE_ARGS=--init-script \"%NOKEE_INIT_SCRIPT_FILE%\"",
57+
"");
58+
}
3859
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package dev.nokee.init.internal.wrapper;
2+
3+
import lombok.val;
4+
5+
import java.io.*;
6+
import java.nio.charset.StandardCharsets;
7+
import java.util.List;
8+
import java.util.stream.Collectors;
9+
import java.util.stream.Stream;
10+
11+
public final class GradleWrapperScriptPatcher {
12+
private final String content;
13+
private String pill;
14+
private List<String> contentToInject;
15+
private String pillPrefix;
16+
17+
private GradleWrapperScriptPatcher(String content) {
18+
this.content = content;
19+
}
20+
21+
public static GradleWrapperScriptPatcher forContent(String content) {
22+
return new GradleWrapperScriptPatcher(content);
23+
}
24+
25+
public GradleWrapperScriptPatcher findLineWith(String pill) {
26+
this.pill = pill;
27+
return this;
28+
}
29+
30+
public GradleWrapperScriptPatcher injectBefore(List<String> contentToInject) {
31+
this.contentToInject = contentToInject;
32+
return this;
33+
}
34+
35+
public GradleWrapperScriptPatcher andPrependPillWith(String pillPrefix) {
36+
this.pillPrefix = pillPrefix;
37+
return this;
38+
}
39+
40+
public List<String> patch() {
41+
try (val reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8))))) {
42+
return reader.lines().flatMap(it -> {
43+
if (it.contains(pill)) {
44+
return Stream.concat(contentToInject.stream(), Stream.of(it.replace(pill, pillPrefix + pill)));
45+
}
46+
return Stream.of(it);
47+
}).collect(Collectors.toList());
48+
} catch (IOException e) {
49+
throw new UncheckedIOException(e);
50+
}
51+
}
52+
}

src/test/groovy/dev/nokee/init/internal/wrapper/GradleWrapperScriptTest.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import static org.hamcrest.MatcherAssert.assertThat;
1111
import static org.junit.jupiter.api.Assertions.assertThrows;
1212

13+
// Real patching is tested in functional tests
1314
class GradleWrapperScriptTest {
1415
private static final String BASH_PATCHABLE_SCRIPT_LINE = "eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS \"\\\"-Dorg.gradle.appname=$APP_BASE_NAME\\\"\" -classpath \"\\\"$CLASSPATH\\\"\" org.gradle.wrapper.GradleWrapperMain \"$APP_ARGS\"";
1516
private static final String BATCH_PATCHABLE_SCRIPT_LINE_6_6_ABOVE = "\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %*";
@@ -18,19 +19,19 @@ class GradleWrapperScriptTest {
1819
@Test
1920
void canPatchBashScript() {
2021
assertThat(script(BASH_PATCHABLE_SCRIPT_LINE).patch("gradle/nokee.init.gradle").get(),
21-
containsString(" --init-script \"\\\"$APP_HOME/gradle/nokee.init.gradle\\\"\" "));
22+
containsString(" \"$NOKEE_ARGS\" "));
2223
}
2324

2425
@Test
2526
void canPatchBatchScriptForGradle6_5Below() {
2627
assertThat(script(BATCH_PATCHABLE_SCRIPT_LINE_6_5_BELOW).patch("gradle/nokee.init.gradle").get(),
27-
containsString(" --init-script \"%APP_HOME%\\gradle\\nokee.init.gradle\" "));
28+
containsString(" %NOKEE_ARGS% "));
2829
}
2930

3031
@Test
3132
void canPatchBatchScriptForGradle6_6Above() {
3233
assertThat(script(BATCH_PATCHABLE_SCRIPT_LINE_6_6_ABOVE).patch("gradle/nokee.init.gradle").get(),
33-
containsString(" --init-script \"%APP_HOME%\\gradle\\nokee.init.gradle\" "));
34+
containsString(" %NOKEE_ARGS% "));
3435
}
3536

3637
@Test

0 commit comments

Comments
 (0)