之前的shell脚本是
2个svn root 同步提交
update:
2010-06-21: 导入文件支持#行注释
现在改成python写,妄图支持windows,未测试.
osx,python2.6下测试通过
目前问题:
optparse的选项默认值不能是unicode,大囧rz
#!/usr/bin/env python
#coding:utf-8
"""
Author: rikugun
Site: http://rikugun.iteye.com/
同时提交北京和本地SVN的脚本
本地环境需要设置环境变量:
如
本地开发编译目录 LOCAL_CRM=/Users/rikugun/Documents/tydic/Projects/LOCAL
本机实际开发目录 CRM=/Users/rikugun/Documents/tydic/Projects/CRM
执行
dsvn CRM_TRANS/src/ngbssIf/InterfaceElec/CheckInfoOrder.pc [...]
后脚本做了以下几件事
* SVN提交 $CRM/CRM_TRANS/src/ngbssIf/InterfaceElec/CheckInfoOrder.pc
* 拷贝/合并(使用合并工具) $CRM/CRM_TRANS/src/ngbssIf/InterfaceElec/CheckInfoOrder.pc $LOCAL_CRM/CRM_TRANS/src/ngbssIf/InterfaceElec/CheckInfoOrder.pc
* 如果$LOCAL_CRM/CRM_TRANS/src/ngbssIf/InterfaceElec/CheckInfoOrder.pc 不存在SVN中,执行 svn add
* SVN提交 $LOCAL_CRM/CRM_TRANS/src/ngbssIf/InterfaceElec/CheckInfoOrder.pc
* TELNET 到开发服务器, 切换到对应目录 执行 svn up 然后编译
"""
import optparse
import sys
import os
import subprocess
import telnetlib
import re
"""需要编译的文件类型"""
SOURCE_FILE_EXT =('.pc','.h','.c')
class TexudoBackend(object):
"""
Texudo后台
可以设置 _DEBUG_LEVEL 开启telnet 调试
"""
_DEBUG_LEVEL=0
def __init__(self, address,username,password=None,quite=False):
super(TexudoBackend, self).__init__()
self.address = address
self.username = username
self.password = password
self.instance = telnetlib.Telnet(host=self.address,timeout=60)
self.instance.set_debuglevel(self._DEBUG_LEVEL)
self.quite = quite
def login(self):
"""登录"""
if self.password:
self.instance.read_until("login: ")
self.instance.write(self.username+'\n')
self.instance.read_until("ssword: ")
self.instance.write(self.password+'\n')
self.instance.read_until('$ ')
return True
def exe_cmd(self,cmd):
"""执行命令"""
# print cmd
self.instance.write(cmd+'\n')
ret = self.instance.read_until('$ ').decode('GBK')
if not self.quite:
print ret
return ret
def close(self):
"""关闭链接"""
self.instance.close()
def getInput(msg):
"""获取用户输入,默认是NO"""
return opts.quite or raw_input(msg) not in ['n','no']
def sysexec(cmd):
"""执行命令幷返回结果"""
msg = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE).communicate()[0].decode('utf-8')
if not opts.quite:
print u'================执行命令==================='
print cmd
print u'================我是分割线==================='
print msg
print u'================已执行命令==================='
return msg
SHARE_DIR_NAME = 'share'
def sort_dirs(dir1,dir2):
"""排序目录,优先编译 share 目录,再编译目录名短的"""
SHARE_DIR_NAME = 'share'
if dir1.endswith(SHARE_DIR_NAME) and not dir2.endswith(SHARE_DIR_NAME):
return -1
elif dir2.endswith(SHARE_DIR_NAME) and not dir1.endswith(SHARE_DIR_NAME):
return 1
elif dir1.endswith(SHARE_DIR_NAME) and dir2.endswith(SHARE_DIR_NAME):
return dir1.find(SHARE_DIR_NAME) - dir2.find(SHARE_DIR_NAME)
else:
return len(dir1)-len(dir2)
if __name__ == "__main__":
opt = optparse.OptionParser("dsvn [-m comments] [-u usernaem] [-p password] [-s host] [-L listfile] filepath [other files]")
opt.add_option("-m","--comments",help=u"提交的注释",default="commit to compile")
opt.add_option("-L","--listfile",help=u"提交的文件列表")
opt.add_option("-u","--username",help=u"登录用户名",default="xxx")
opt.add_option("-p","--password",help=u"登录用户密码",default="xxx")
opt.add_option("-s","--server",help=u"登录服务器",default="xxx.xxx.xxx.xxx")
opt.add_option("-M","--mergetool",help=u"使用工具合并而非拷贝")
opt.add_option("-q","--quite",action="store_true",help=u"安静模式,所有提示都选择Y")
opts,files = opt.parse_args()
if len(files) == 0 and opts.listfile is None:
print u'请输入要提交文件,或者文件列表'
print opt.print_usage()
print __doc__
exit(2)
if not files and opts.listfile:
files = [line for line in open(opts.listfile,'r').readlines() if not line.startswith('#')]
#获取环境变量
# 开发环境
dev_dir =os.getenv('CRM')
# 本地编译目录
local_dir = os.getenv('LOCAL_CRM')
reg = re.compile(dev_dir+os.sep+'(.+)$')
#设置合并工具
if opts.mergetool is not None:
merge_cmd = opts.mergetool
elif os.name =='nt':
merge_cmd = 'copy /Y'
else:
merge_cmd='cp -r'
#过滤文件名 如 CRM_TRANS/src/share/EssErrorTrans.txt
fileset = set([reg.match(os.path.realpath(os.getcwd()+os.sep+it)).group(1).strip() for it in files])
file_list = ','.join(fileset)
#过滤需要编译的目录
dir_list = list(set([ os.path.dirname(x) for x in fileset if x.endswith(SOURCE_FILE_EXT)]))
#排序文件目录
dir_list.sort(sort_dirs)
#开发路径
src_file_list= [ dev_dir+os.sep+x for x in fileset]
#同步到本地的路径
dst_file_list =[local_dir+os.sep+x for x in fileset]
#过滤新加的文件,需要额外执行svn add命令
add_dst_file_list = [x for x in dst_file_list if not os.path.exists(x)]
svn_cmd = ['svn ci -m "%s"' % opts.comments,]
if getInput('commit such files [%s] to BJ SVN ? (y)es/no :' % file_list) :
sysexec(' '.join(svn_cmd+src_file_list))
# 传输文件,本地提交
if getInput('commit such files [%s] to LOCAL SVN ? (y)es/no :' % file_list) :
sysexec(' '.join(['svn revert ']+dst_file_list))
map(lambda ff:sysexec(' '.join([merge_cmd,dev_dir+os.sep+ff,local_dir+os.sep+ff])),fileset)
if len(add_dst_file_list):
sysexec(' '.join(['svn add']+dst_file_list))
sysexec(' '.join(svn_cmd+dst_file_list))
# 切换到服务器编译
if getInput('Compile such files [%s] on server[%s] ? (y)es/no :' % (file_list,opts.server)) :
tn = TexudoBackend(opts.server,opts.username,opts.password)
try:
if tn.login() :
print u'登录成功'
#在服务器上更新文件
tn.exe_cmd('svn up %s' % ' '.join(files))
#逐个目录编译
for dir_path in dir_list:
tn.exe_cmd('cd ~/%s && make && make install ' % dir_path.replace('\\','/'))
except Exception:
print u"传输到服务器中编译发生错误"
tn.close()
exit(2)
print u'脚本执行成功'