Skip to content

Commit b12f4fd

Browse files
authored
Merge pull request #33 from EtienneMiret/23-clean-subprojects
Store sass in a "$rootProject/.gradle/sass" subdirectory per subproject
2 parents b8fbe25 + bfa5eec commit b12f4fd

File tree

10 files changed

+208
-48
lines changed

10 files changed

+208
-48
lines changed

src/functionalTest/java/io/miret/etienne/gradle/sass/MultiProjectTest.java

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -83,26 +83,14 @@ void stopServer() {
8383

8484
@BeforeEach
8585
void setupProject() throws IOException {
86-
List<String> directories = ImmutableList.of(
87-
"app",
88-
"lib"
89-
);
9086
List<String> files = ImmutableList.of(
9187
"app/build.gradle",
9288
"lib/build.gradle",
9389
"build.gradle",
9490
"settings.gradle"
9591
);
9692

97-
for (String subDir : directories) {
98-
Files.createDirectories(projectDir.resolve(subDir));
99-
}
100-
for (String resource : files) {
101-
try (InputStream input = MultiProjectTest.class.getResourceAsStream("multi-project/" + resource)) {
102-
requireNonNull(input, "Missing resource: " + resource);
103-
Files.copy(input, projectDir.resolve(resource));
104-
}
105-
}
93+
Utils.copy("/io/miret/etienne/gradle/sass/multi-project", files, projectDir);
10694
}
10795

10896
@Test
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package io.miret.etienne.gradle.sass;
2+
3+
import com.github.tomakehurst.wiremock.WireMockServer;
4+
import com.google.common.collect.ImmutableList;
5+
import org.assertj.core.api.SoftAssertions;
6+
import org.assertj.core.api.junit.jupiter.InjectSoftAssertions;
7+
import org.assertj.core.api.junit.jupiter.SoftAssertionsExtension;
8+
import org.gradle.testkit.runner.GradleRunner;
9+
import org.junit.jupiter.api.BeforeEach;
10+
import org.junit.jupiter.api.Test;
11+
import org.junit.jupiter.api.extension.ExtendWith;
12+
import org.junit.jupiter.api.io.TempDir;
13+
14+
import java.io.IOException;
15+
import java.nio.file.Path;
16+
import java.util.List;
17+
18+
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
19+
import static com.github.tomakehurst.wiremock.client.WireMock.get;
20+
import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching;
21+
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
22+
import static io.miret.etienne.gradle.sass.Utils.copy;
23+
import static io.miret.etienne.gradle.sass.Utils.createArchive;
24+
import static java.util.Collections.singletonMap;
25+
26+
/**
27+
* Test applying this plugin in multiple subprojects
28+
* instead of only the root project.
29+
*/
30+
@ExtendWith(SoftAssertionsExtension.class)
31+
public class MultipleApplyTest {
32+
33+
@TempDir
34+
Path projectDir;
35+
36+
@InjectSoftAssertions
37+
private SoftAssertions softly;
38+
39+
private WireMockServer server;
40+
41+
@BeforeEach
42+
void startAndSetupWiremockServer () throws IOException {
43+
server = new WireMockServer(options().dynamicPort());
44+
server.start();
45+
server.stubFor(get(urlMatching("/42.0/dart-sass-.*"))
46+
.willReturn(aResponse()
47+
.withStatus(200)
48+
.withBody(createArchive())
49+
)
50+
);
51+
}
52+
53+
@BeforeEach
54+
void setupProject() throws IOException {
55+
List<String> projectResources = ImmutableList.of(
56+
"a/build.gradle",
57+
"b/build.gradle",
58+
"c/build.gradle",
59+
"build.gradle",
60+
"settings.gradle"
61+
);
62+
copy("/io/miret/etienne/gradle/sass/multiple-apply", projectResources, projectDir);
63+
}
64+
65+
@Test
66+
void should_not_create_dot_gradle_directories_in_subprojects() {
67+
GradleRunner runner = GradleRunner.create();
68+
runner.withPluginClasspath();
69+
runner.withEnvironment(singletonMap("URL", server.baseUrl()));
70+
runner.withArguments("installSass");
71+
runner.withProjectDir(projectDir.toFile());
72+
runner.build();
73+
74+
softly.assertThat(projectDir.resolve("a/.gradle")).doesNotExist();
75+
softly.assertThat(projectDir.resolve("b/.gradle")).doesNotExist();
76+
softly.assertThat(projectDir.resolve("c/.gradle")).doesNotExist();
77+
}
78+
79+
}

src/functionalTest/java/io/miret/etienne/gradle/sass/SassGradlePlugin_withWar_FunctionalTest.java

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,26 @@
11
package io.miret.etienne.gradle.sass;
22

33
import com.github.tomakehurst.wiremock.WireMockServer;
4-
import com.google.common.io.ByteStreams;
5-
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
6-
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
7-
import org.apache.tools.ant.taskdefs.condition.Os;
84
import org.gradle.testkit.runner.GradleRunner;
95
import org.junit.jupiter.api.AfterEach;
106
import org.junit.jupiter.api.BeforeEach;
117
import org.junit.jupiter.api.Test;
128
import org.junit.jupiter.api.io.TempDir;
139

14-
import java.io.ByteArrayOutputStream;
1510
import java.io.IOException;
1611
import java.io.InputStream;
1712
import java.nio.file.Files;
1813
import java.nio.file.Path;
1914
import java.util.ArrayList;
2015
import java.util.List;
21-
import java.util.zip.GZIPOutputStream;
2216
import java.util.zip.ZipEntry;
2317
import java.util.zip.ZipInputStream;
24-
import java.util.zip.ZipOutputStream;
2518

2619
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
2720
import static com.github.tomakehurst.wiremock.client.WireMock.get;
2821
import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching;
2922
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
23+
import static io.miret.etienne.gradle.sass.Utils.createArchive;
3024
import static java.util.Collections.singletonMap;
3125
import static org.assertj.core.api.Assertions.assertThat;
3226

@@ -142,31 +136,4 @@ void should_not_copy_css_to_war () throws Exception {
142136
}
143137
}
144138

145-
private byte[] createArchive () throws IOException {
146-
ByteArrayOutputStream bytes = new ByteArrayOutputStream ();
147-
if (Os.isFamily (Os.FAMILY_WINDOWS)) {
148-
try (
149-
ZipOutputStream zip = new ZipOutputStream (bytes);
150-
InputStream sass = SassGradlePlugin_withWar_FunctionalTest.class.getResourceAsStream ("sass.bat")
151-
) {
152-
zip.putNextEntry (new ZipEntry ("dart-sass/sass.bat"));
153-
ByteStreams.copy (sass, zip);
154-
}
155-
} else {
156-
try (
157-
GZIPOutputStream gz = new GZIPOutputStream (bytes);
158-
TarArchiveOutputStream tgz = new TarArchiveOutputStream (gz);
159-
InputStream sass = SassGradlePlugin_withWar_FunctionalTest.class.getResourceAsStream ("sass.sh")
160-
) {
161-
TarArchiveEntry entry = new TarArchiveEntry ("dart-sass/sass");
162-
entry.setSize (sass.available ());
163-
entry.setMode (0755);
164-
tgz.putArchiveEntry (entry);
165-
ByteStreams.copy (sass, tgz);
166-
tgz.closeArchiveEntry ();
167-
}
168-
}
169-
return bytes.toByteArray ();
170-
}
171-
172139
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package io.miret.etienne.gradle.sass;
2+
3+
import com.google.common.io.ByteStreams;
4+
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
5+
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
6+
import org.apache.tools.ant.taskdefs.condition.Os;
7+
8+
import java.io.ByteArrayOutputStream;
9+
import java.io.IOException;
10+
import java.io.InputStream;
11+
import java.nio.file.Files;
12+
import java.nio.file.Path;
13+
import java.nio.file.Paths;
14+
import java.util.Collection;
15+
import java.util.Objects;
16+
import java.util.zip.GZIPOutputStream;
17+
import java.util.zip.ZipEntry;
18+
import java.util.zip.ZipOutputStream;
19+
20+
public class Utils {
21+
22+
/**
23+
* Copies classpath resources to a directory.
24+
* <p>
25+
* Each resource will be searched in the classpath from {@code base} and
26+
* copied to {@code destination}. That is, for {@code base = "/io/miret/"},
27+
* {@code destination = "/var/tmp"} and a {@code foo/bar.txt} resource,
28+
* the {@code /io/miret/foo/bar.txt} classpath resource will be copied
29+
* to {@code /var/tmp/foo/bar.txt}.
30+
* <p>
31+
* Intermediate directories will be created as needed.
32+
*
33+
* @param base base name for the resources, must include the starting '/'.
34+
* @param resources the set of file resources to copy, relative to base.
35+
* @param destination a path that points to an existing directory.
36+
*/
37+
public static void copy(
38+
String base,
39+
Collection<String> resources,
40+
Path destination
41+
) throws IOException {
42+
if (!base.startsWith("/")) {
43+
throw new IllegalArgumentException("Base resource name must start with a '/'");
44+
}
45+
for (String resourceStr : resources) {
46+
Path resourcePath = Paths.get(resourceStr);
47+
if (resourcePath.isAbsolute()) {
48+
throw new IllegalArgumentException("Absolute path provided: " + resourceStr);
49+
}
50+
Path target = destination.resolve(resourcePath);
51+
Files.createDirectories(target.getParent());
52+
try (InputStream input = Utils.class.getResourceAsStream(base + "/" + resourceStr)) {
53+
Objects.requireNonNull(input, "No such resource: " + resourceStr);
54+
Files.copy(input, target);
55+
}
56+
}
57+
}
58+
59+
/**
60+
* Creates an archive with the dummy sass executable from classpath.
61+
* On Windows, this is a ZIP archive with {@code sass.bat}.
62+
* Elsewhere, this is a gzipped, tar archive with {@code sass.sh}.
63+
*/
64+
public static byte[] createArchive() throws IOException {
65+
ByteArrayOutputStream bytes = new ByteArrayOutputStream ();
66+
if (Os.isFamily (Os.FAMILY_WINDOWS)) {
67+
try (
68+
ZipOutputStream zip = new ZipOutputStream (bytes);
69+
InputStream sass = SassGradlePlugin_withWar_FunctionalTest.class.getResourceAsStream ("sass.bat")
70+
) {
71+
assert sass != null;
72+
zip.putNextEntry (new ZipEntry("dart-sass/sass.bat"));
73+
ByteStreams.copy (sass, zip);
74+
}
75+
} else {
76+
try (
77+
GZIPOutputStream gz = new GZIPOutputStream (bytes);
78+
TarArchiveOutputStream tgz = new TarArchiveOutputStream (gz);
79+
InputStream sass = SassGradlePlugin_withWar_FunctionalTest.class.getResourceAsStream ("sass.sh")
80+
) {
81+
assert sass != null;
82+
TarArchiveEntry entry = new TarArchiveEntry ("dart-sass/sass");
83+
entry.setSize (sass.available ());
84+
entry.setMode (0755);
85+
tgz.putArchiveEntry (entry);
86+
ByteStreams.copy (sass, tgz);
87+
tgz.closeArchiveEntry ();
88+
}
89+
}
90+
return bytes.toByteArray ();
91+
}
92+
93+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
plugins {
2+
id 'io.miret.etienne.sass'
3+
}
4+
5+
sass {
6+
version = '42.0'
7+
baseUrl = System.getenv("URL")
8+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
plugins {
2+
id 'io.miret.etienne.sass'
3+
}
4+
5+
sass {
6+
version = '42.0'
7+
baseUrl = System.getenv("URL")
8+
}

src/functionalTest/resources/io/miret/etienne/gradle/sass/multiple-apply/build.gradle

Whitespace-only changes.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
plugins {
2+
id 'io.miret.etienne.sass'
3+
}
4+
5+
sass {
6+
version = '42.0'
7+
baseUrl = System.getenv("URL")
8+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
rootProject.name = 'test-multiple-apply'
2+
include 'a'
3+
include 'b'
4+
include 'c'

src/main/java/io/miret/etienne/gradle/sass/SassGradlePluginExtension.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import org.gradle.api.Project;
66

77
import java.io.File;
8+
import java.nio.file.Path;
89

910
@Getter
1011
@Setter
@@ -19,10 +20,14 @@ public class SassGradlePluginExtension {
1920
private boolean autoCopy;
2021

2122
public SassGradlePluginExtension (Project project) {
23+
Path projectPath = project.getRootDir()
24+
.toPath()
25+
.relativize(project.getProjectDir().toPath());
2226
this.version = "1.54.0";
23-
this.directory = project.getProjectDir ()
27+
this.directory = project.getRootDir()
2428
.toPath ()
2529
.resolve (".gradle/sass")
30+
.resolve(projectPath)
2631
.toFile ();
2732
this.baseUrl = "https://github.com/sass/dart-sass/releases/download";
2833
this.autoCopy = true;

0 commit comments

Comments
 (0)