Skip to content

Commit 9e755d6

Browse files
committed
Add example implementation of ide-starter
1 parent 6677ebb commit 9e755d6

File tree

15 files changed

+169
-23
lines changed

15 files changed

+169
-23
lines changed

gradle/libs.versions.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ testAndroidSdkVersion = "7.3.0"
77

88
[libraries]
99
commonIo = "commons-io:commons-io:2.11.0"
10-
ideStarter = "com.jetbrains.intellij.tools:ide-starter-squashed:233.14475.28"
10+
ideStarter = "com.jetbrains.intellij.tools:ide-starter-squashed:233.15026.9"
1111
toolingApi = "org.gradle:gradle-tooling-api:7.2"
1212

1313
spock-core = { module = "org.spockframework:spock-core", version.ref = "spock" }

src/main/java/org/gradle/profiler/studio/AndroidStudioSyncAction.java

-7
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,9 @@
22

33
import org.gradle.profiler.BuildAction;
44
import org.gradle.profiler.GradleClient;
5-
import org.gradle.profiler.ide.RunIde;
6-
import org.gradle.profiler.instrument.GradleInstrumentation;
75
import org.gradle.profiler.result.BuildActionResult;
86

9-
import java.net.MalformedURLException;
10-
import java.net.URL;
11-
import java.net.URLClassLoader;
12-
import java.util.Arrays;
137
import java.util.List;
14-
import java.util.ServiceLoader;
158

169
/**
1710
* A mock-up of Android studio sync.

src/main/java/org/gradle/profiler/studio/StudioGradleClient.java

+24
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import org.gradle.profiler.InvocationSettings;
66
import org.gradle.profiler.client.protocol.ServerConnection;
77
import org.gradle.profiler.client.protocol.messages.*;
8+
import org.gradle.profiler.ide.RunIdeContext;
9+
import org.gradle.profiler.ide.RunIdeStarter;
810
import org.gradle.profiler.instrument.GradleInstrumentation;
911
import org.gradle.profiler.result.BuildActionResult;
1012
import org.gradle.profiler.studio.invoker.StudioBuildActionResult;
@@ -16,12 +18,15 @@
1618
import org.gradle.profiler.studio.tools.StudioSandboxCreator.StudioSandbox;
1719

1820
import java.io.File;
21+
import java.net.URL;
22+
import java.net.URLClassLoader;
1923
import java.nio.file.Path;
2024
import java.time.Duration;
2125
import java.util.ArrayList;
2226
import java.util.Arrays;
2327
import java.util.List;
2428
import java.util.Optional;
29+
import java.util.ServiceLoader;
2530
import java.util.concurrent.CompletableFuture;
2631
import java.util.concurrent.ExecutorService;
2732
import java.util.concurrent.Executors;
@@ -32,6 +37,8 @@
3237

3338
public class StudioGradleClient implements GradleClient {
3439

40+
41+
3542
public enum CleanCacheMode {
3643
BEFORE_SCENARIO,
3744
BEFORE_BUILD,
@@ -48,11 +55,13 @@ public enum CleanCacheMode {
4855
private final CleanCacheMode cleanCacheMode;
4956
private final ExecutorService executor;
5057
private final StudioSandbox sandbox;
58+
private final InvocationSettings invocationSettings;
5159
private boolean isFirstRun;
5260

5361
public StudioGradleClient(StudioGradleBuildConfiguration buildConfiguration, InvocationSettings invocationSettings, CleanCacheMode cleanCacheMode) {
5462
this.isFirstRun = true;
5563
this.cleanCacheMode = cleanCacheMode;
64+
this.invocationSettings = invocationSettings;
5665
Path studioInstallDir = invocationSettings.getStudioInstallDir().toPath();
5766
Optional<File> studioSandboxDir = invocationSettings.getStudioSandboxDir();
5867
this.sandbox = StudioSandboxCreator.createSandbox(studioSandboxDir.map(File::toPath).orElse(null));
@@ -64,7 +73,22 @@ public StudioGradleClient(StudioGradleBuildConfiguration buildConfiguration, Inv
6473
this.executor = Executors.newSingleThreadExecutor();
6574
}
6675

76+
private RunIdeContext newIdeContext() {
77+
URL[] classpath = GradleInstrumentation.getClasspath("ide-provisioning");
78+
RunIdeStarter ideStarter = ServiceLoader.load(RunIdeStarter.class, new URLClassLoader(classpath, RunIdeStarter.class.getClassLoader())).iterator().next();
79+
return ideStarter.newContext(
80+
invocationSettings.getProjectDir().getAbsolutePath(),
81+
invocationSettings.getStudioInstallDir().getAbsolutePath()
82+
);
83+
}
84+
6785
public BuildActionResult sync(List<String> gradleArgs, List<String> jvmArgs) {
86+
newIdeContext()
87+
.withCommands()
88+
.waitForSmartMode()
89+
.importGradleProject()
90+
.exitApp();
91+
6892
if (shouldCleanCache()) {
6993
processController.runAndWaitToStop((connections) -> {
7094
System.out.println("* Cleaning Android Studio cache, this will require a restart...");

subprojects/ide-provisioning-api/build.gradle.kts

-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
plugins {
22
id("profiler.embedded-library")
3-
id("profiler.publication")
43
}
54

65
description = "Api for IDE provisioning capabilities for Gradle profiler"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package org.gradle.profiler.ide;
2+
3+
public interface CommandChain {
4+
CommandChain importGradleProject();
5+
CommandChain waitForSmartMode();
6+
CommandChain exitApp();
7+
void run();
8+
}

subprojects/ide-provisioning-api/src/main/java/org/gradle/profiler/ide/RunIde.java

-5
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package org.gradle.profiler.ide;
2+
3+
public interface RunIdeContext {
4+
RunIdeContext withSystemProperty(String key, String value);
5+
CommandChain withCommands();
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package org.gradle.profiler.ide;
2+
3+
public interface RunIdeStarter {
4+
RunIdeContext newContext(String projectLocation, String ideLocation);
5+
}

subprojects/ide-provisioning/build.gradle.kts

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ dependencies {
1616
implementation(libs.ideStarter) {
1717
exclude(group = "io.ktor")
1818
}
19+
implementation("org.kodein.di:kodein-di-jvm:7.20.2")
1920
testImplementation(libs.bundles.testDependencies)
2021
testImplementation(libs.commonIo)
2122
}

subprojects/ide-provisioning/src/main/java/org/gradle/profiler/ide/RunIdeImpl.java

-8
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package org.gradle.profiler.ide
2+
3+
import com.intellij.ide.starter.ide.IDETestContext
4+
import com.intellij.tools.ide.performanceTesting.commands.exitApp
5+
import com.intellij.tools.ide.performanceTesting.commands.importGradleProject
6+
import com.intellij.tools.ide.performanceTesting.commands.waitForSmartMode
7+
8+
class CommandChainImpl(private val context: IDETestContext) : CommandChain {
9+
10+
private var commandChain = com.intellij.tools.ide.performanceTesting.commands.CommandChain()
11+
12+
override fun importGradleProject(): CommandChain {
13+
commandChain = commandChain.importGradleProject()
14+
return this
15+
}
16+
17+
override fun waitForSmartMode(): CommandChain {
18+
commandChain = commandChain.waitForSmartMode()
19+
return this
20+
}
21+
22+
override fun exitApp(): CommandChain {
23+
commandChain = commandChain.exitApp()
24+
return this
25+
}
26+
27+
override fun run() {
28+
context.runIDE(commands = commandChain)
29+
}
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package org.gradle.profiler.ide
2+
3+
import com.intellij.ide.starter.ide.IDETestContext
4+
5+
class RunIdeContextImpl(private val context: IDETestContext) : RunIdeContext {
6+
override fun withSystemProperty(key: String, value: String): RunIdeContext {
7+
context.applyVMOptionsPatch {
8+
addSystemProperty(key, value)
9+
}
10+
return this
11+
}
12+
13+
override fun withCommands(): CommandChain {
14+
return CommandChainImpl(context)
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package org.gradle.profiler.ide
2+
3+
import com.intellij.ide.starter.ide.IDETestContext
4+
import com.intellij.ide.starter.ide.IdeDistributionFactory
5+
import com.intellij.ide.starter.ide.IdeInstaller
6+
import com.intellij.ide.starter.ide.InstalledIde
7+
import com.intellij.ide.starter.ide.installer.ExistingIdeInstaller
8+
import com.intellij.ide.starter.ide.installer.IdeInstallerFile
9+
import com.intellij.ide.starter.models.IdeInfo
10+
import com.intellij.ide.starter.models.TestCase
11+
import com.intellij.ide.starter.path.GlobalPaths
12+
import com.intellij.ide.starter.process.exec.ProcessExecutor
13+
import com.intellij.ide.starter.project.LocalProjectInfo
14+
import com.intellij.ide.starter.runner.TestContainer
15+
import com.intellij.ide.starter.runner.TestContainerImpl
16+
import com.intellij.openapi.util.SystemInfo
17+
import com.intellij.openapi.util.io.FileUtil
18+
import java.nio.file.Path
19+
import java.nio.file.Paths
20+
import kotlin.io.path.div
21+
import kotlin.io.path.name
22+
import kotlin.time.Duration.Companion.minutes
23+
24+
class RunIdeStarterImpl : RunIdeStarter {
25+
override fun newContext(projectLocation: String, ideLocation: String): RunIdeContext {
26+
val testVersion = "2023.2.3"
27+
val ideInfo = IdeInfo(
28+
productCode = "IC",
29+
version = "2023.2",
30+
// buildNumber = testVersion,
31+
executableFileName = "idea",
32+
fullName = "IntelliJ IDEA Community",
33+
platformPrefix = "idea",
34+
// getInstaller = { _ -> ExistingIdeInstaller(Paths.get(ideLocation)) }
35+
)
36+
val testCase = TestCase(
37+
ideInfo,
38+
LocalProjectInfo(Paths.get(projectLocation)),
39+
)
40+
val context = Starter.newContext("test", testCase)
41+
return RunIdeContextImpl(context)
42+
}
43+
44+
class ExistingIdeInstaller(private val installedIdePath: Path) : IdeInstaller {
45+
override fun install(ideInfo: IdeInfo, includeRuntimeModuleRepository: Boolean): Pair<String, InstalledIde> {
46+
val ideInstaller = IdeInstallerFile(installedIdePath, "locally-installed-ide")
47+
val installDir = GlobalPaths.instance
48+
.getCacheDirectoryFor("builds") / "${ideInfo.productCode}-${ideInstaller.buildNumber}"
49+
installDir.toFile().deleteRecursively()
50+
val installedIde = installedIdePath.toFile()
51+
val destDir = installDir.resolve(installedIdePath.name).toFile()
52+
if (SystemInfo.isMac) {
53+
ProcessExecutor("copy app", null, 5.minutes, emptyMap(), listOf("ditto", installedIde.absolutePath, destDir.absolutePath)).start()
54+
}
55+
else {
56+
FileUtil.copyDir(installedIde, destDir)
57+
}
58+
return Pair(
59+
ideInstaller.buildNumber,
60+
IdeDistributionFactory.installIDE(installDir.toFile(), ideInfo.executableFileName)
61+
)
62+
}
63+
}
64+
65+
private object Starter {
66+
private fun newTestContainer(): TestContainer<*> {
67+
return TestContainerImpl()
68+
}
69+
70+
fun newContext(testName: String, testCase: TestCase<*>, preserveSystemDir: Boolean = false): IDETestContext =
71+
newTestContainer().initializeTestContext(
72+
testName = testName,
73+
testCase = testCase,
74+
preserveSystemDir = preserveSystemDir
75+
)
76+
}
77+
}

subprojects/ide-provisioning/src/main/resources/META-INF/services/org.gradle.profiler.ide.RunIde

-1
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
org.gradle.profiler.ide.RunIdeStarterImpl

0 commit comments

Comments
 (0)