Python3下操作SVN

一、背景

在一次需求开发中,需要在python3的环境下,操作SVN,在SVN仓库上实现如下操作:创建SVN目录、拉取SVN文件内容、将文件推送到SVN仓库。

经过不断的探索尝试,最终实现了这些功能,这里将这些功能实现记录下来。

二、python3环境准备

关于python3在linux环境下的安装,可以参考:在Linux系统上安装Python3

下载安装svn相关python库:https://pypi.org/

根据python版本选择合适的whl库

  • pysvn-0.1.0-py3-none-any.whl
  • svn-0.3.44-py2.py3-none-any.whl

安装完之后测试:

$ python3
>>> import stat,os,shutil,time,platform
>>> import svn, svn.remote

三、在svn仓库上创建子目录

# 如果SVN仓库上的子目录不存在,就创建出来
def createSubDirOnSVNReportIfNotExists(svn_base_url, svn_username, svn_password, subDir):
  subDirs = subDir.split("/")
  createDirFlag = False
  current_svn_base_url = svn_base_url
  for oneSubDir in subDirs:
    svnClient = svn.remote.RemoteClient(current_svn_base_url,username=svn_username, password=svn_password)
    current_svn_base_url += "/" + oneSubDir
    # 查询svn当前目录下的所有子目录
    subAll = svnClient.list()
    findFlag = False
    for subName in subAll:
      if oneSubDir in subName:
        findFlag=True
        break
    if not findFlag:
      createDirFlag = True
      break
  # 子目录不存在,创建子目录
  if createDirFlag:
    svnClient = svn.remote.RemoteClient(svn_base_url, username=svn_username, password=svn_password)
    # 执行创建SVN 子目录的命令
    svn_sub_command = 'mkdir'
    command_args = ["--parents", "-m", "python程序创建svn子目录:"+subDir, str(svn_base_url+"/"+subDir).replace(' ', '%20')]
    svnClient.run_command(svn_sub_command, command_args)
  return svn_base_url+"/"+subDir

四、将文件提交到svn仓库

# 判断本地文件是否存在
def isFileAndExists(filePath):
  if os.path.exists(filePath) and os.path.isfile(filePath):
    return True
  else:
    return False

# 执行提交操作
def commitSVNReportFile(svnUrl, target_localfilePath, svn_username, svn_password):
  # 如果本地文件不存在,就不用提交了
  if not isFileAndExists(target_localfilePath):
    raise Exception('要向SVN仓库提交的本地文件不存在');
  # 提交SVN报告
  svnUrl = svnUrl.replace(' ', '%20')
  svnClient = svn.remote.RemoteClient(svnUrl, username=svn_username, password=svn_password)
  # 先执行add操作
  svn_sub_command_add = 'add'
  command_args_add = ["--force", target_localfilePath]
  svnClient.run_command(svn_sub_command_add, command_args_add)
  # 再执行commit操作
  svn_sub_command_commit = 'commit'
  command_args_commit = [target_localfilePath, '-m', 'python3程序提交文件:'+os.path.split(target_localfilePath)[-1]]
  svnClient.run_command(svn_sub_command_commit, command_args_commit)

五、checkout目录

# 如果目录不存在就创建目录
def createDirIfNotExists(dirPath):
  if not os.path.exists(dirPath) or not os.path.isdir(dirPath):
    os.makedirs(dirPath)

# checkout svn 文件
def checkoutSVNFile(local_base_dir, svn_base_url, svn_username, svn_password, svn_subdir):
   # 在本地创建一个SVN临时目录
   svn_local_temp_dir = os.path.join(local_base_dir, 'svn_reports', str(int(time.time())))
   # 创建目录
   createDirIfNotExists(svn_local_temp_dir)
   # 在svn上创建子目录,如果子目录不存在
   svnUrl = createSubDirOnSVNReportIfNotExists(svn_base_url, svn_username, svn_password, svn_subdir)
   svnUrl = svnUrl.replace(' ', '%20')
   # 将目录checkout下来
   svnClient = svn.remote.RemoteClient(svnUrl, username=svn_username, password=svn_password)
   svnClient.checkout(svn_local_temp_dir)
   return svn_local_temp_dir

六、更新svn仓库的文件

# 递归删除
def deleteDirsRecursion(dirPath):
  if not isDirAndExists(dirPath):
    return
  if platform.system().lower()=='windows':
    shutil.rmtree(dirPath, onerror=remove_readonly)
  else:
    shutil.rmtree(dirPath)
 
# 解决: shutil.rmtree 在Windows 上删除只读文件报错问题
def remove_readonly(func, path, _):
  os.chmod(path, stat.S_IWRITE)
  func(path)

# 更新svn仓库的文件
def updateSVNFile(update_filepath, svn_subdir, svn_base_url, svn_username, svn_password):
  if not isFileAndExists(update_filepath):
    raise Exception('要更新的SVN文件不存在: %s' % update_filepath)
   # 在本地创建一个SVN临时目录
   svn_local_temp_dir = os.path.join(local_base_dir, 'svn_reports', str(int(time.time())))
   # 创建目录
   createDirIfNotExists(svn_local_temp_dir)
   # 在svn上创建子目录,如果子目录不存在
   svnUrl = createSubDirOnSVNReportIfNotExists(svn_base_url, svn_username, svn_password, svn_subdir)
   svnUrl = svnUrl.replace(' ', '%20')
   # 将目录checkout下来
   svnClient = svn.remote.RemoteClient(svnUrl, username=svn_username, password=svn_password)
   svnClient.checkout(svn_local_temp_dir)
   # 获取要更新的文件名
   target_localfilePath = os.path.join(svn_local_temp_dir, os.path.split(update_filepath)[-1])
   # 拷贝文件内容
   shutil.copyfile(update_filepath, target_localfilePath)
   # 向SVN仓库提交文件
   commitSVNReportFile(svnUrl, target_localfilePath, svn_username, svn_password)
   # sleep
   time.sleep(3)
   # 删除临时目录
   deleteDirsRecursion(svn_local_temp_dir)
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐