# 根据SVN增量补丁日志,自动生成补丁包
import tkinter.filedialog as tkFD
import os, shutil, time, sys
from tkinter.filedialog import askopenfilename
from tkinter import *
# 允许的文件扩展名
FILTER_EXTEN = ['.java', '.class', '.xml', '.properties']
# 目标文件夹生产过滤(比如WebRoot目录是不需要的)
FILTER_TARGET_DIR = ['WebRoot/']
# 补丁生成路径
PATCH_GENERATE_PATH = ''
# 补丁包名称
PATCH_NAME = ''
# 异常
IS_EXCEPTION = False
# -------------------- 以下属性由配置文件读出 --------------------
# SVN补丁日志文件默认位置
DEFAULT_SVN_LOG_PATH = ''
# 是否使用SVN补丁日志文件默认位置
IS_DEFAULT_SVN_LOG_PATH = 0
# 工作空间默认位置,可为空
DEFAULT_WORKSPACE_PATH = ''
# 是否使用工作空间默认位置
IS_DEFAULT_WORKSPACE_PATH = 0
# 是否自动生成补丁包名称
IS_AUTO_GENERATE_PATCHNAME = 1
# 创建一个补丁生成类
class Patch():
patchFile = ''
projectName = ''
projectPath = ''
patchFileList = [] # 补丁文件列表
filterPatchFileList = [] # 被过滤的文件列表
patchLog = [] # 日志信息列表
# 构造函数
def __init__(self):
# 解析配置文件
self.parseConfigFile()
# print(DEFAULT_SVN_LOG_PATH)
# print(IS_DEFAULT_SVN_LOG_PATH)
# print(DEFAULT_WORKSPACE_PATH)
# print(IS_DEFAULT_WORKSPACE_PATH)
# pass
# 开始打补丁
def start(self):
# 选择SVN补丁日志文件
self.selectFile()
# 生成补丁包名称
self.generatePatchName()
# 解析文件
self.parseSvnPatchFile()
# 打印补丁包信息
self.printPatchFile()
# 生成补丁包
self.generatePatch()
# 选择文件
def selectFile(self):
global IS_DEFAULT_SVN_LOG_PATH
global DEFAULT_SVN_LOG_PATH
# 根据配置文件中的信息,判断是否需要使用默认的地址
if IS_DEFAULT_SVN_LOG_PATH != '1':
root = Tk()
root.withdraw()
self.patchFile = tkFD.askopenfilename(defaultextension=".txt",initialdir="/home/",title="选择SVN补丁文件")
else:
self.patchFile = DEFAULT_SVN_LOG_PATH
# 解析SVN补丁日志文件
def parseSvnPatchFile(self):
global FILTER_EXTEN
print(self.patchFile)
# 如果文件不存在
if not os.path.exists(self.patchFile):
self.patchLog.append('\r\n')
self.patchLog.append(' >> 不存在的SVN补丁日志文件:' + self.patchFile)
print(' >> 不存在的SVN补丁日志文件:' + self.patchFile)
IS_EXCEPTION = True
return
patchFile = open(self.patchFile, 'r')
'''
# SVN补丁文件规则描述(仅目前所知,非正规文档描述)
# 对于有修改或增加的文件,大致为如下格式(0, 1, 2, 3行):
0 Index: src/gnnt/service/ApplyAndAuditService.java
1 ===================================================================
2 --- src/gnnt/service/ApplyAndAuditService.java (revision 9003)
3 +++ src/gnnt/service/ApplyAndAuditService.java (working copy)
4 ...
# 将根据以上规则获取增量文件名
'''
prepare = False # 准备阶段
possibleFilename = '' # 可能的文件名
for line in patchFile.readlines():
# 解析被记录的文件
prefixIden = line[0: 6] # 获取前6个字符
if prefixIden == 'Index:':
line = line.replace('\t', ' ') # 将制表符转换为空格
line = line.replace('\n', '') # 将换行符去掉
lineList = line.split(' ')
if len(lineList) >= 2:
possibleFilename = lineList[1]
# 保留java源文件
oldFilename = possibleFilename;
# 将java文件替换成class文件
possibleFilename = possibleFilename.replace('src/', 'WebRoot/WEB-INF/classes/')
possibleFilename = possibleFilename.replace('.java', '.class')
self.addPatchFile(possibleFilename)
# 保留java源文件
if oldFilename != possibleFilename:
self.addPatchFile(oldFilename)
continue
# 解析项目名称
prefixIden = line[0: 2] # 获取前2个字符
if prefixIden == '#P':
lineList = line.split(' ')
if len(lineList) >= 2:
self.projectName = lineList[1].replace('\n', '')
# print()
# print('解析到的项目名称:', self.projectName)
self.patchLog.append('\n')
self.patchLog.append('解析到的项目名称:' + self.projectName)
""" 保留但先暂时不使用以下方式解析被修改的补丁文件
if prefixIden == '===':
prepare = True
continue
if prepare == True and prefixIden == '---':
line = line.replace('\t', ' ') # 将制表符转换为空格
lineList = line.split(' ')
if len(lineList) > 2:
possibleFilename = lineList[1]
# print(len(lineList))
# print(possibleFilename)
continue
if prepare == True and prefixIden == '+++':
line = line.replace('\t', ' ') # 将制表符转换为空格
lineList = line.split(' ')
if len(lineList) > 2:
if lineList[1] == possibleFilename:
self.patchFileList.append(possibleFilename)
else:
possibleFilename = ''
"""
# print(prefixIden)
# print(self.patchFileList)
patchFile.close()
# 添加文件至解析完成的补丁文件
def addPatchFile(self, patchFilename):
isAllow = False
for exten in FILTER_EXTEN:
if patchFilename[0 - len(exten):] == exten:
isAllow = True
continue
if not isAllow:
# self.patchLog.append('被过滤的文件:' + patchFilename)
self.filterPatchFileList.append(patchFilename)
else:
self.patchFileList.append(patchFilename)
# 生成补丁包
def generatePatch(self):
global PATCH_GENERATE_PATH
global FILTER_TARGET_DIR
global PATCH_NAME
global IS_DEFAULT_WORKSPACE_PATH
global DEFAULT_WORKSPACE_PATH
# 设置项目地址
if IS_DEFAULT_WORKSPACE_PATH != '1':
projectPath = tkFD.askdirectory(initialdir="/home/",title="选择工作空间") + '/' + self.projectName
else:
projectPath = DEFAULT_WORKSPACE_PATH + '/' + self.projectName
self.projectPath = projectPath
# 补丁生产目录添加上补丁名称与项目名称
if (PATCH_GENERATE_PATH == ''):
patchDir = PATCH_NAME + self.projectName + "/"
else:
patchDir = PATCH_NAME + PATCH_GENERATE_PATH + '/' + self.projectName + "/"
# print()
# print('补丁包生成详细信息:')
self.patchLog.append('\r\n')
self.patchLog.append('补丁�