替换包名中的单词和代码中的变量



在我的android项目中,我得到了非常有趣的任务我的公司想在代码中隐藏所有关于她的信息(变量名,包等)但只针对一种口味,所以我不能为所有项目做一次。

我的第一个想法是写一个简单的gradle任务,它将替换所有适合代码的字符串,但在这种情况下包名将保持不变。

其次,因为我们在Jenkins上有ci,我想到了Jenkins脚本,它将重命名所有文件及其内容,如果它有关键字。但是这个解决方案对我来说太笨重了。

也许有另一种优雅的方式?

盲目地替换包名/变量名似乎有点冒险,因为它也可能替换其他重叠的字符串,这可能导致各种问题。假设您的包名是唯一的,并且没有任何重叠的名称,并且不会导致任何目录名称更改,您可以使用不同的方法来替换包名。

选项1

使用shell实现这一点。有很多不同的方法可以做到这一点,以下是grepsed

的一种选择
sh '''
grep -rl ${PACKAGE_NAME_TO_REPLACE} ${DESTINATION_DIR} | xargs sed -i "s&${PACKAGE_NAME_TO_REPLACE}&${PACKAGE_NAME_NEW}&g"
'''

你可以看看这个和这个来了解你可以使用的不同方法。

选项2

如果你想要一个更可控的方法,你也可以用一些groovy代码来实现。只需在您的Pipeline中运行以下命令:

def dirToSearchIn = "/where/to/replace"
// Change the content on specific files. You can improve the regex pattern below to fine-tune it. With the following pattern only files with extensions .java and .md will be changed.  
def filterFilePattern = ~/.*.java|.*.md$/
def oldString = "replaceme"
def newString = "newme"
new File(dirToSearchIn).traverse(type: groovy.io.FileType.FILES, nameFilter: filterFilePattern) { file ->
println "Processing file: " + file.getPath()
def fileContent = file.text;
if (fileContent.contains(oldString)) {
println "Replacing the content of the file: " + file.getPath()
file.write(fileContent.replaceAll(oldString, newString));
} else {
println "Skipping file: " + file.getPath()
}
}

将以下内容添加到您的顶级build.gradle文件中应该可以做到这一点(假设您的公司名为" ACME ",而您更希望它被称为" foobar "):

def duplicateProjDirName = 'duplicateProj'
def duplicateProjDir = project.layout.buildDirectory.dir(duplicateProjDirName)
def duplicateProj = tasks.register('createDuplicateProject', Copy) {
enabled = (projectDir.name != duplicateProjDirName)
from(project.layout.projectDirectory)
into(duplicateProjDir)
exclude('build', '.gradle')
def acmePattern = /(?i)acme/
def newCompanyName = 'foobar'
eachFile { it.path = it.sourcePath.replaceAll(acmePattern, newCompanyName) }
filter { it.replaceAll(acmePattern, newCompanyName) }
includeEmptyDirs = false
}
def duplicateBuild = tasks.register('buildDuplicateProject', GradleBuild) {
enabled = (projectDir.name != duplicateProjDirName)
dependsOn(duplicateProj)
dir = duplicateProjDir
tasks = ['build']
}
tasks.named('build').configure {
dependsOn(duplicateBuild)
}

这实际上为项目增加了两个任务:

  • createDuplicateProject复制build/duplicateProj/下的项目,将所有提到的"ACME"替换为"foobar"。它还负责重命名文件/目录(与迄今为止其他答案中的解决方案相反)。
  • buildDuplicateProject构建副本项目。

虽然这可能在基本场景下工作(我已经成功地用一个小的虚拟Java项目和Gradle 7.6进行了测试),但有一些边缘情况需要考虑:

  • 可能存在依赖项(库,服务等),其中包含公司名称,并且在重命名后将不再工作。
  • 这种替换方式
    • 可能不适合二进制文件。
    • 不捕获"AC" + "ME"等代码中的错误。
    • 不区分大小写可能会导致不遵循通用约定的奇怪名称。在最坏的情况下,这也可能导致不同的行为。
  • 可能有下游项目依赖于包名或类似的重命名在这里。
  • 您的公司可能不仅仅是通过名称来识别,例如,也可能在图像文件中有徽标等。
  • 和其他

最新更新