如果追溯性地引入代码格式化规则,则必须解决如何根据新的格式化规则格式化现有代码库的问题。 您可以在IDE中逐个签出每个代码存储库,然后单击“ 自动格式化整个项目”。 但这很无聊,而且浪费时间。
幸运的是,Intellij IDEA的安装中具有格式CLI工具。 您可以在路径<您的Intellij IDEA安装> / bin中找到它。 它称为format.sh 。
在下一节中,我想向您展示如何自动格式化大型代码库。 首先,我将显示准备步骤,例如从IDE导出代码格式设置规则。 然后,我将演示如何使用CLI-Tool format.sh。 最后,我将展示一个小的Groovy脚本,该脚本查询所有存储库(在本例中为Git存储库),格式化代码并将其推回远程SCM。
准备工作
首先,我们需要从Intellij IDEA导出的代码格式化规则设置。 在您的Intellij IDEA中,执行下一步
然后,签出或克隆您的SCM存储库,并记住签出/克隆它的位置(例如, / home / foo / myrepository )。
通过
三个参数对于format.sh很重要:
- -s:设置Intellij IDEA代码样式设置.xml文件的路径(在我们的示例中为/home/foo/Default.xml )。
- -r:设置应递归扫描目录。
- path <n>:设置应格式化的文件或目录的路径(在我们的示例中为/ home / foo / myrepository )。
> ./format.sh
IntelliJ IDEA 2018.2.4, build IC-182.4505.22 Formatter
Usage: format [-h] [-r|-R] [-s|-settings settingsPath] path1 path2...
-h|-help Show a help message and exit.
-s|-settings A path to Intellij IDEA code style settings .xml file.
-r|-R Scan directories recursively.
-m|-mask A comma-separated list of file masks.
path<n> A path to a file or a directory.
> /format.sh -r -s ~/Default.xml ~/myrepository
该工具可能由于java.lang.OutOfMemoryError:Java堆空间而取消了扫描。 然后,您必须在<您的Intellij IDEA安装> /bin/idea64.vmoptions中增加Java的最大内存大小(-Xmx) 。
> nano idea64.vmoptions
-Xms128m
-Xmx750m // <- here increase the maximum memory size
-XX:ReservedCodeCacheSize=240m
-XX:+UseConcMarkSweepGC
-XX:SoftRefLRUPolicyMSPerMB=50
-ea
-Dsun.io.useCanonCaches=false
-Djava.net.preferIPv4Stack=true
-Djdk.http.auth.tunneling.disabledSchemes=""
-XX:+HeapDumpOnOutOfMemoryError
-XX:-OmitStackTraceInFastThrow
-Dawt.useSystemAAFontSettings=lcd
-Dsun.java2d.renderer=sun.java2d.marlin.MarlinRenderingEngine
Groovy脚本,用于连续格式化多个存储库
现在,我们希望将所有内容整合在一起。 该脚本应该做四件事:
- 查找所有必须格式化其代码的存储库URL。
- 签出/克隆存储库。
- 在每个存储库的所有分支中格式化代码。
- 提交更改并将其推送到远程SCM。
在我的示例中,我选择Git作为SCM。 存储库URL的查找取决于您使用的Git管理系统(如BitBucket,Gitlab,SCM管理器等)。 但是方法在所有系统中都是相同的:
- 调用Git管理系统的RESTful API。
- 在网址之后解析响应中的JSON对象。
例如,在BitBucket中是这样的:
@Grab('org.codehaus.groovy.modules.http-builder:http-builder:0.7.1')
import groovyx.net.http.*
import static groovyx.net.http.ContentType.*
import static groovyx.net.http.Method.*
def cloneUrlsForProject() {
def projectUrl = "https://scm/rest/api/1.0/projects/PROJECT_KEY/repos?limit=1000"
def token = "BITBUCKET_TOKEN"
def projects = []
def cloneUrls = []
def http = new HTTPBuilder(projectUrl)
http.request(GET) {
headers."Accept" = "application/json"
headers."Authorization" = "Bearer ${token}"
response.success = { resp -> projects = new JsonSlurper().parseText(resp.entity.content.text)}
response.failure = { resp ->
throw new RuntimeException("Error fetching clone urls for '${projectKey}': ${resp.statusLine}")
}
}
projects.values.each { value ->
def cloneLink = value.links.clone.find { it.name == "ssh" }
cloneUrls.add(cloneLink.href)
}
return cloneUrls
}
然后,我们必须克隆存储库并检出每个分支。 在每个分支中,必须调用format.sh 。 对于git操作,我们使用jgit库,对于format.sh调用,我们使用Groovy功能进行流程调用。 在Groovy中,可以将命令定义为String,然后在此String上调用方法execute() ,例如“ ls -l” .execute()。 因此,最后三个任务的Groovy脚本如下所示:
#!/usr/bin/env groovy
@Grab('org.eclipse.jgit:org.eclipse.jgit:5.1.2.201810061102-r')
import jgit.*
import org.eclipse.jgit.api.CreateBranchCommand
import org.eclipse.jgit.api.Git
import org.eclipse.jgit.api.ListBranchCommand
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider
import java.nio.file.Files
def intellijHome = 'path to your idea home folder'
def codeFormatterSetting = 'path to your exported code formatter setting file'
def allRepositoriesUrls = ["http://scm/repo1","http://scm/repo2"] // for simplifying
allRepositoriesUrls.each { repository ->
def repositoryName = repository.split('/').flatten().findAll { it != null }.last()
File localPath = Files.createTempDirectory("${repositoryName}-").toFile()
println "Clone ${repository} to ${localPath}"
Git.cloneRepository()
.setURI(repository)
.setDirectory(localPath)
.setNoCheckout(true)
.setCredentialsProvider(new UsernamePasswordCredentialsProvider("user", "password")) // only needed when clone url is https / http
.call()
.withCloseable { git ->
def remoteBranches = git.branchList().setListMode(ListBranchCommand.ListMode.REMOTE).call()
def remoteBranchNames = remoteBranches.collect { it.name.replace('refs/remotes/origin/', '') }
println "Found the following branches: ${remoteBranchNames}"
remoteBranchNames.each { remoteBranch ->
println "Checkout branch $remoteBranch"
git.checkout()
.setName(remoteBranch)
.setCreateBranch(true)
.setUpstreamMode(CreateBranchCommand.SetupUpstreamMode.TRACK)
.setStartPoint("origin/" + remoteBranch)
.call()
def formatCommand = "$intellijHome/bin/format.sh -r -s $codeFormatterSetting $localPath"
println formatCommand.execute().text
git.add()
.addFilepattern('.')
.call()
git.commit()
.setAuthor("Automator", "no-reply@yourcompany.com")
.setMessage('Format code according to IntelliJ setting.')
.call()
println "Commit successful!"
}
git.push()
.setCredentialsProvider(new UsernamePasswordCredentialsProvider("user", "password")) // only needed when clone url is https / http
.setPushAll()
.call()
println "Push is done"
}
}
您还有其他方法吗? 让我知道并在下面写评论。
翻译自: https://www.javacodegeeks.com/2018/10/format-large-code-base-automatically.html