用python重写双重提交svn的脚本

之前的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'脚本执行成功'

你可能感兴趣的:(python,SVN,osx,脚本,OS)