Skip to content

Commit

Permalink
Smarter versions lock task running (#10)
Browse files Browse the repository at this point in the history
  • Loading branch information
FinlayRJW authored Sep 24, 2024
1 parent 0a6bfa7 commit 5e75d5c
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 20 deletions.
5 changes: 5 additions & 0 deletions changelog/@unreleased/pr-10.v2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
type: improvement
improvement:
description: Smarter versions lock writing
links:
- https://github.com/palantir/gradle-consistent-versions-idea-plugin/pull/10
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,23 @@
import com.intellij.openapi.components.ComponentManager;
import com.intellij.openapi.externalSystem.importing.ImportSpecBuilder;
import com.intellij.openapi.externalSystem.model.execution.ExternalSystemTaskExecutionSettings;
import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode;
import com.intellij.openapi.externalSystem.task.TaskCallback;
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.vfs.AsyncFileListener;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.newvfs.events.VFileContentChangeEvent;
import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.util.PsiTreeUtil;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.function.Predicate;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.util.GradleConstants;
Expand All @@ -38,19 +45,15 @@

public final class VersionPropsFileListener implements AsyncFileListener {
private static final Logger log = LoggerFactory.getLogger(VersionPropsFileListener.class);

public VersionPropsFileListener() {
log.debug("Got created");
}
private static final String TASK_NAME = "writeVersionsLock";

@Nullable
@Override
public ChangeApplier prepareChange(List<? extends VFileEvent> events) {
List<VirtualFile> versionPropsEvents = events.stream()
.filter(VFileEvent::isFromSave) // This is quite expensive and noisy so only run on save
.map(VFileEvent::getFile)
.filter(Objects::nonNull)
.filter(file -> "versions.props".equals(file.getName()))
List<VFileContentChangeEvent> versionPropsEvents = events.stream()
.filter(event -> event instanceof VFileContentChangeEvent)
.map(event -> (VFileContentChangeEvent) event)
.filter(event -> "versions.props".equals(event.getFile().getName()))
.toList();

if (versionPropsEvents.isEmpty()) {
Expand All @@ -62,24 +65,80 @@ public ChangeApplier prepareChange(List<? extends VFileEvent> events) {
.filter(Project::isInitialized)
.filter(Predicate.not(ComponentManager::isDisposed))
.filter(project -> versionPropsEvents.stream()
.anyMatch(event -> event.getPath().startsWith(project.getBasePath())))
.anyMatch(event -> event.getPath().startsWith(project.getBasePath())
&& !isFileMalformed(project, event.getFile())))
.toList();

return new ChangeApplier() {
@Override
public void afterVfsChange() {
projectsAffected.forEach(project -> {
ExternalSystemTaskExecutionSettings settings = new ExternalSystemTaskExecutionSettings();
settings.setExternalProjectPath(project.getBasePath());
settings.setTaskNames(Collections.singletonList("writeVersionsLock"));
settings.setExternalSystemIdString(GradleConstants.SYSTEM_ID.toString());

ExternalSystemUtil.runTask(
settings, DefaultRunExecutor.EXECUTOR_ID, project, GradleConstants.SYSTEM_ID);
ExternalSystemUtil.refreshProject(
project.getBasePath(), new ImportSpecBuilder(project, GradleConstants.SYSTEM_ID).build());
if (hasBuildSrc(project)) {
runTaskThenRefresh(project);
} else {
refreshProjectWithTask(project);
}
});
}
};
}

private boolean hasBuildSrc(Project project) {
return Files.exists(Paths.get(project.getBasePath(), "buildSrc"));
}

private void runTaskThenRefresh(Project project) {
log.debug("Running task {} on project {}", TASK_NAME, project.getName());
TaskCallback callback = new TaskCallback() {
@Override
public void onSuccess() {
log.debug("Task {} successfully executed", TASK_NAME);
refreshProject(project);
}

@Override
public void onFailure() {
log.error("Task {} failed", TASK_NAME);
}
};
ExternalSystemTaskExecutionSettings settings = createExecutionSettings(project);
ExternalSystemUtil.runTask(
settings,
DefaultRunExecutor.EXECUTOR_ID,
project,
GradleConstants.SYSTEM_ID,
callback,
ProgressExecutionMode.IN_BACKGROUND_ASYNC);
}

private ExternalSystemTaskExecutionSettings createExecutionSettings(Project project) {
ExternalSystemTaskExecutionSettings settings = new ExternalSystemTaskExecutionSettings();
settings.setExternalProjectPath(project.getBasePath());
settings.setTaskNames(Collections.singletonList(TASK_NAME));
settings.setExternalSystemIdString(GradleConstants.SYSTEM_ID.toString());
return settings;
}

private void refreshProjectWithTask(Project project) {
log.debug("Refreshing project {} with task {}", project.getName(), TASK_NAME);
refreshProject(project, new ImportSpecBuilder(project, GradleConstants.SYSTEM_ID).withArguments(TASK_NAME));
}

private void refreshProject(Project project) {
refreshProject(project, new ImportSpecBuilder(project, GradleConstants.SYSTEM_ID));
}

private void refreshProject(Project project, ImportSpecBuilder importSpec) {
ExternalSystemUtil.refreshProject(project.getBasePath(), importSpec);
}

private static boolean isFileMalformed(Project project, VirtualFile file) {
PsiFile psiFile = PsiManager.getInstance(project).findFile(file);

if (psiFile == null || !(psiFile.getFileType() instanceof VersionPropsFileType)) {
return true;
}

return PsiTreeUtil.hasErrorElements(psiFile);
}
}

0 comments on commit 5e75d5c

Please sign in to comment.