# -*- coding:utf-8 -*- # 请使用Python 2.7版本运行; from __future__ import unicode_literals import os import re # 正则表达式; import sys #reload(sys) #sys.setdefaultencoding('utf-8') import time import datetime import shutil from basessh2 import baseSSH2 import subprocess import xlrd import xlwt from xlwt import XFStyle, Pattern import win_subprocess # 此版本对应宽字节,subprocess为acssi; import shutil def copyfile(src_file, dest_file): shutil.copy(src_file, dest_file) def copyfolder(src_foler, dest_folder): if src_folder.endswith(".apk"): copyfile(src_foler, dest_folder) else: src_files = os.listdir(src_foler) # 目标路径是否存在,不存在创建; if not os.path.exists(dest_folder): os.mkdirs(dest_folder) for name in src_files: copyfile(src_foler+"\\"+name, dest_folder+"\\"+name) # 不使用重定向; def cmdExecute2(cmd): # 定义文件名称; file_name = str(time.time()) # 输出到文件中; cmd = cmd + ' >> ' + file_name print u'执行cmd:', cmd proc = subprocess.Popen(cmd, shell=True) # 等待完成; proc.wait() # 读取文件内容; data = '' with open(file_name, mode="rb") as f: data = f.read() os.remove(file_name) print u"cmd结果:", data return data def cmdExecute(cmd): print u'执行cmd:', cmd proc = win_subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) # 等待完成; stdout, stderr = proc.communicate() if proc.returncode == 0: print u'执行成功' # 返回执行结果; # print u"cmdExecute结果:%s" % stdout return stdout class ExcelParser: def __init__(self, excelPath): self.__xlspath = excelPath self.xlsData = [] def readExcel(self, excelPath=None): if excelPath is not None: if type(excelPath) == str: self.__xlspath = excelPath.decode('utf-8') '文件是否存在' if not os.path.exists(self.__xlspath): return False '打开excel文件' wb = xlrd.open_workbook(filename=self.__xlspath) if wb is None: return False '获取所有sheet' sheet = None for item in wb.sheet_names(): sheet = wb.sheet_by_name(item) self.paserExcel(sheet) def paserExcel(self, sheet): if sheet.name == "release": for i in range(1, sheet.nrows): rowDict = {} '获取每行内容:url\版本号\debug svn revision\src svn revision\是否释放' rowData = tuple(sheet.row_values(i)) if rowData.__len__() == 5: if rowData[0].__len__() > 0: # 需要去除空格; rowDict['url'] = rowData[0].strip() rowDict['apk_version'] = str(rowData[1]).strip() rowDict['apk_revision'] = str(rowData[2]).strip('.0') rowDict['src_revision'] = str(rowData[3]).strip('.0') rowDict['sqa_result'] = rowData[4].strip('.0') self.xlsData.append(rowDict) # endif # endif # endfor else: print u"未找到对应的sheet名称:release" # 远程服务器SVN操作; class remoteSVN: def __init__(self, host, user, pwd): self.__user = user self.__pwd = pwd self.__host = host self.__ssh2 = baseSSH2() self.__ssh2.init_ssh2(user, pwd, host) # 获取指定版本信息; def getRevisionInfo(self, revision, url): cmd = 'svn info -r %s %s' % (revision, url) return self.__ssh2.execute_cmd(cmd) # 获取指定版本log; def getRevisionLog(self, revision, url): cmd = 'svn log -r %s %s' % (revision, url) return self.__ssh2.execute_cmd(cmd) # 更新指定目录; def update(self, dir, revision=''): if revision.__len__() > 0: cmd = 'svn up -r %s %s' % (revision, dir) else: cmd = 'svn up %s' % (dir) return self.__ssh2.execute_cmd(cmd) # 提交指定目录; def commit(self): pass # 本地SVN操作,必须安装命令行; class localSVN: def __init__(self): print 'local svn' def revisionInfo(self, revision, url): cmd = 'svn info -r %s %s' % (revision, url) return cmdExecute(cmd) def revisionLog(self, revision, url): cmd = 'svn log -r %s %s' % (revision, url) return cmdExecute(cmd) def checkout(self, dir, url, revision=''): # dir中文必须是unicode的转gbk; if revision.__len__() > 0: cmd = 'svn co -r %s %s %s' % (revision, url, dir) else: cmd = 'svn co %s %s' % (url, dir) return cmdExecute(cmd) def export(self, dir, url, revision=''): # dir中文必须是unicode的转gbk; if revision.__len__() > 0: cmd = 'svn export -r %s %s %s' % (revision, url, dir) else: cmd = 'svn export %s %s' % (url, dir) return cmdExecute(cmd) def update(self, dir, revision=''): # revision只有根目录才有效,即有.svn的目录才有效; dir = dir.replace('\\', '/') # dir中文必须是unicode的转gbk; if revision.__len__() > 0: cmd = 'svn up %s -r %s' % (dir, revision) else: cmd = 'svn up %s' % (dir) return cmdExecute(cmd) def revert(self, dir, revision=''): # dir中文必须是unicode的转gbk; if revision.__len__() > 0: cmd = 'svn revert -r %s %s' % (revision, dir) else: cmd = 'svn revert %s' % (dir) return cmdExecute(cmd) def add(self, file): # file中文必须是unicode的转gbk; cmd = 'svn add %s' % (file) return cmdExecute(cmd) def commit(self, file, desc): # file/desc中文必须是unicode的转gbk; cmd = "svn commit -m %s %s" % (desc, file) return cmdExecute(cmd) def status(self, file): cmd = "svn status %s"%(file) msg = cmdExecute(cmd) if msg.startswith("?"): # 不在控制; return 0 elif msg.startswith("A"): # 预加入; return 1 elif msg.startswith("M"): # 已修改; return 2 elif msg.startswith("C"): # 冲突; return 3 elif msg.startswith("K"): # 被锁定; return 4 if __name__ == "__main__": print "start main" lsvn = localSVN() # 注意:中文字符串,必须加u表示unicode; debug_dir = u"F:\\Moka-Code\\APK自动编译相关\\debug" release_dir = u"F:\\Moka-Code\\APK自动编译相关\\release" excelPath = u"F:\\Moka-Code\\APK自动编译相关\\apk-release.xlsx" # url地址; debug_url = u"https://odm-design-center-hz.tclking.com/svn/scbc_apps/trunk/app/apk/01debug/general" release_url = u"https://odm-design-center-hz.tclking.com/svn/scbc_apps/trunk/app/apk/02release/general" '无则下载有则更新' if os.path.exists(debug_dir + "\\.svn"): lsvn.update(debug_dir) else: lsvn.checkout(debug_dir, debug_url) '无则下载有则更新' if os.path.exists(release_dir + "\\.svn"): lsvn.update(release_dir) else: lsvn.checkout(release_dir, release_url) '读取excel表记录' excel = ExcelParser(excelPath) excel.readExcel() print excel.xlsData for item in excel.xlsData: if item['sqa_result'] == u"释放": '获取apk名称' apk_name = item['url'][debug_url.__len__() + 1:] '更新到释放的版本' lsvn.update(debug_dir + "\\" + apk_name, item['apk_revision']) '复制到release目录' copyfolder(debug_dir + "\\" + apk_name, release_dir + "\\" + apk_name) '获取日志' log = lsvn.revisionLog(item['apk_revision'], item['url']).decode('gbk') listInfo = log.split("\r\n") message = listInfo[3] '获取状态' ret = lsvn.status(release_dir + "\\" + apk_name) if ret == 0: '添加并提交' lsvn.add(release_dir + "\\" + apk_name) lsvn.commit(release_dir + "\\" + apk_name, message) elif ret == 1 or ret == 2: lsvn.commit(release_dir + "\\" + apk_name, message) else: print "不受控,无法提交" # endif # endfor