Skip to content

Instantly share code, notes, and snippets.

@dkandalov
Forked from chanshuikay/patchjar.groovy
Last active December 9, 2015 16:13
Show Gist options
  • Save dkandalov/8a9aa14617ec6d3a85b4 to your computer and use it in GitHub Desktop.
Save dkandalov/8a9aa14617ec6d3a85b4 to your computer and use it in GitHub Desktop.
Patchjar live plugin that creates patch.jar based using classes from Favorites Lists
package com.rbsfm.fi.risk.riskcalculator.calc.cds
import com.intellij.ide.favoritesTreeView.FavoritesManager
import com.intellij.ide.projectView.impl.AbstractUrl
import com.intellij.openapi.module.ModuleManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.CompilerModuleExtension
import com.intellij.openapi.roots.ModuleRootManager
import com.intellij.openapi.roots.ProjectRootManager
import com.intellij.openapi.util.Pair
import com.intellij.openapi.vcs.FilePathImpl
import com.intellij.openapi.vcs.ProjectLevelVcsManager
import com.intellij.openapi.vcs.VcsRoot
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiJavaFile
import com.intellij.psi.impl.source.PsiJavaFileImpl
import com.intellij.psi.util.PsiUtilBase
import com.intellij.util.TreeItem
import com.intellij.util.io.ZipUtil
import java.util.zip.ZipOutputStream
import com.intellij.openapi.vfs.VirtualFile
import static liveplugin.PluginUtil.*
import static com.intellij.openapi.util.io.FileUtil.toCanonicalPath as canonicalPathOf
// This is a micro-plugin which creates a .jar "patch file" from a specified favourites list.
// It assumes that project is already compiled.
//
// (Note that it can only be executed within this plugin https://github.com/dkandalov/liveplugin)
if (isIdeStartup) return
catchingAll {
/***** CHANGE THESE TWO BOYS BELOW TO SET THE OUTPUT JAR AND THE CHANGESET TO USE FOR THE CONTENTS. */
def outputJarPath = "c:/temp/patch-temp.jar"
def favoritesListName = "bfm"
def modules = ModuleManager.getInstance(project).modules
def sourceRootPaths = modules.collectMany { module ->
ModuleRootManager.getInstance(module).sourceRoots.collect { canonicalPathOf(it.path) }
}
def compilerOutputPaths = modules.collect { module ->
def extension = ModuleRootManager.getInstance(module).getModuleExtension(CompilerModuleExtension.class)
if (extension?.compilerOutputPath?.path == null) null
else canonicalPathOf(extension.compilerOutputPath.path)
}.findAll{ it != null }
def relativePathOf = { path ->
(sourceRootPaths + compilerOutputPaths).inject(path) { result, pathToExclude -> result.replace(pathToExclude, "") }
}
def urls = FavoritesManager.getInstance(project).getFavoritesListRootUrls(favoritesListName)
def srcFiles = []
for (TreeItem<Pair<AbstractUrl, String>> pair : urls) {
def abstractUrl = pair.data.first
Object[] path = abstractUrl.createPath(project)
if (path == null || path.length < 1 || path[0] == null) {
continue
}
Object element = path[path.length - 1]
if (element instanceof PsiClass || element instanceof PsiJavaFile) {
VirtualFile virtualFile = PsiUtilBase.getVirtualFile((PsiElement)element)
if (virtualFile != null) {
srcFiles << virtualFile
}
} else {
show("Found unhandled psi type : " + element.class.name)
}
}
show(srcFiles.join("\n"))
def classFiles = srcFiles.collectMany { srcFile ->
def relativePathToFileParent = relativePathOf(canonicalPathOf(srcFile.parent.path))
compilerOutputPaths
.collectMany {
def files = new File(it + relativePathToFileParent).listFiles()
files != null ? files.toList() : []
}
.findAll { classFile ->
// find classes and inner classes
def classFilePattern = '^' + srcFile.name.replace(".java", "") + '(\\$\\w+)*\\.class$'
classFile.name.matches(classFilePattern)
}
.collect { [it, relativePathOf(canonicalPathOf(it.absolutePath))] }
}.unique()
show(classFiles*.get(0).join("\n"))
def patchFile = new File(outputJarPath)
if (patchFile.exists()) patchFile.delete()
def outputStream = new ZipOutputStream(new FileOutputStream(patchFile))
classFiles.each { entry ->
def (file, classFileRelativePath) = entry
ZipUtil.addFileToZip(outputStream, file, classFileRelativePath, null, null)
}
outputStream.close()
show("Created $patchFile")
}
static List<VcsRoot> vcsRootsIn(Project project) {
ProjectRootManager.getInstance(project).contentSourceRoots
.collect{ ProjectLevelVcsManager.getInstance(project).getVcsRootObjectFor(it) }
.findAll{ it.path != null }.unique()
}
static List<CommittedChangeList> lastCommitsIn(VcsRoot vcsRoot, int numberOfCommitsToLoad = 1) {
if (numberOfCommitsToLoad == 0) return []
def changesProvider = vcsRoot.vcs.committedChangesProvider
def location = changesProvider.getLocationFor(FilePathImpl.create(vcsRoot.path))
def settings = changesProvider.createDefaultSettings()
changesProvider.getCommittedChanges(settings, location, numberOfCommitsToLoad)
}
static Collection<VirtualFile> virtualFilesIn(Collection<CommittedChangeList> commits) {
commits.collectMany{it.changes.collect{it.virtualFile}}.findAll{ isJavaFile(it) }
}
static boolean isJavaFile(VirtualFile file) {
file != null && file.extension == "java"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment