python对svn进行操作及信息获取

首页 / 文章分类 / 正文

一、实现效果

1、通过python获取路径下所有文件的svn状态
2、通过python对svn进行“提交、删除、锁、解锁、删除等操作”
3、通过svn打开小乌龟界面

二、完整代码

""" SVN状态对照表 """ class FileState:     Normal = 0  # 000000 正常在svn管理下的最新的文件     RemoteLocked = 1  # 000001 云端锁定态     LocalLocked = 2  # 000010 本地锁定态     Locked = 3  # 000011 已锁定 state and Locked == True     LocalMod = 4  # 000100 本地有修改需提交     RemoteMod = 8  # 001000 远程有修改需要更新     Conflicked = 12  # 001100 冲突 state and Conflicked == Conflicked     UnVersioned = 16  # 010000 未提交到库     Error = 32  # 100000 错误状态 
""" 具体实现逻辑 """ # -*- coding: utf-8 -*- import os import pprint import subprocess import time from threading import Thread from xmltodict import parse as xmlParse   def _doSvnCommandSync(args):     startupinfo = subprocess.STARTUPINFO()     startupinfo.dwFlags = subprocess.CREATE_NEW_CONSOLE | subprocess.STARTF_USESHOWWINDOW     startupinfo.wShowWindow = subprocess.SW_HIDE     p = subprocess.Popen(         args,         stdout=subprocess.PIPE,         stderr=subprocess.PIPE,         startupinfo=startupinfo,         shell=True     )     rst, err = p.communicate()     try:         rst = str(rst, 'utf-8')     except:         rst = str(rst, 'gbk', errors="-ignore")     try:         err = str(err, 'utf-8')     except:         err = str(err, 'gbk', errors="-ignore")     return rst, err   def svnCommitNoUnlockSync(path, comment=""):     rst, err = _doSvnCommandSync("svn commit " + path + " -m \"" + comment + "\"" + " --no-unlock")     return rst, err   def svnCommitSync(path, comment=""):     rst, err = _doSvnCommandSync("svn commit " + path + " -m \"" + comment + "\"")     return rst, err   def _svnStatusSync(path):     rst, err = _doSvnCommandSync("svn status " + path)     if err:         return None, err     data = rst     return data, None   def svnLockSync(path):     rst, err = _doSvnCommandSync("svn lock -m '哈哈哈哈哈哈' " + path)     return rst, err   def svnAddSync(path):     data, err = _doSvnCommandSync("svn add " + path)     return data, err   def svnUnLockSync(path):     rst, err = _doSvnCommandSync("svn unlock " + path)     return rst, err   def svnDeleteSync(path):     return _doSvnCommandSync("svn delete " + path)   def _svnStatusXMLSync(path):     rst, err = _doSvnCommandSync("svn status " + path + " -u --xml")     if err:         return None, err     data = rst     data = xmlParse(data)     return data, None   def syncGetAllFileStatus(rootPath):     data, info = _svnStatusXMLSync(rootPath)     returnDict = {}     lockRole = ""     state = FileState.Normal     if info:         if data is None:             state = state | FileState.UnVersioned         else:             state = state | FileState.Error         return returnDict     target = data["status"]["target"]      if target and "entry" in target:         iterList = []         if not isinstance(target["entry"], list):             iterList.append(target["entry"])         else:             iterList = target["entry"]         for fileStatusItem in iterList:             state = FileState.Normal             filePath = fileStatusItem["@path"]             wc_status = fileStatusItem["wc-status"]             if "unversioned" == wc_status["@item"]:                 state = state | FileState.UnVersioned             elif "modified" == wc_status["@item"]:                 state = state | FileState.LocalMod             elif "repos-status" in fileStatusItem:                 repos_status = fileStatusItem["repos-status"]                 if "lock" in repos_status and "lock" not in wc_status:                     info = repos_status["lock"]["owner"]                     lockRole = info                     state = state | FileState.RemoteLocked                 elif "lock" in wc_status:                     info = wc_status["lock"]["owner"]                     lockRole = info                     state = state | FileState.LocalLocked                 elif "modified" == repos_status["@item"]:                     state = state | FileState.RemoteMod                     info = "%s is modified on remote, you need update first" % filePath                 if "modified" == wc_status["@item"]:                     state = state | FileState.LocalMod                     info = "%s is modified on local, you need commit first" % filePath             returnDict[os.path.normcase(filePath)] = [state, info, lockRole]     return returnDict   def openTortoise():     pathsStr = "".join("G:\SVNCheckOut\Txt2")     cmd = "TortoiseProc.exe /command:commit /path %s" % pathsStr     p = subprocess.Popen(         cmd,         stdout=subprocess.PIPE,         stderr=subprocess.PIPE,         encoding="utf-8",         shell=True     )   # class Process(subprocess.Popen): #     def register_callback(self, callback, *args, **kwargs): #         Thread(target=self._poll_completion, args=(callback, args, kwargs)).start() # #     def _poll_completion(self, callback, args, kwargs): #         while self.poll() is None: #             time.sleep(0.1) #         callback(*args, **kwargs)   # def openTortoise(): #     pathsStr = "".join("G:\SVNCheckOut\Version1") #     cmd = "TortoiseProc.exe /command:commit /path %s" % pathsStr #     handle = Process(cmd) #     handle.register_callback(MyPrint)   # def MyPrint(): #     print("~~~~~~~~~~~~~~~~~")   openTortoise()  data = syncGetAllFileStatus(r"G:\SVNCheckOut\Txt2") pprint.pprint(data) os.system("Pause")   

三、结果展示、代码解析

1、上述代码最终会有两个输出展示

a、打开小乌龟提交界面

python对svn进行操作及信息获取
这里对应的其实就是 “TortoiseProc.exe /command:commit /path %s” % pathsStr" 这句命令行的运行

b、展示SVN 文件状态

python对svn进行操作及信息获取
python对svn进行操作及信息获取
我们需要查看上述 “svn状态对照表”,可以发现状态码 “2、4、16” 分别对应的就是 “本地锁定、本地有修改、未提交到库”,并且到文件夹中查看可知是一一对应的

2、代码解析

首先,我们看 “_doSvnCommandSync” 该函数的实质就是运行命令行

我们将svn的各种命令行传入上述函数 “_doSvnCommandSync”,以此构造了python内的 "提交、删除、锁、解锁 等函数"

比较特殊的是 “_svnStatusXMLSync” 这个获取svn状态的函数,因为我们是将其以xml的格式输出,因此要对其结构进行解析,“svn status " + path + " -u --xml” 这条指令能够获取 path路径下所有文件的svn状态,我们在 “syncGetAllFileStatus” 函数中对其解析便可以得到我们想要的信息,包括 锁的相关信息、提交信息、文件状态等
svn --xml的状态可以查看这里