主要根据svn log命令解析出需要的数据,为了做到通用,使用了传参的方式。
1、执行以下命令
python svn_info.py "代码仓" "写入日志的文件"
2、代码如下
import subprocess
import os
import sys
import xml.etree.ElementTree
from datetime import datetime, timedelta
from urllib.parse import unquote
changed = {
"A": "Added",
"D": "Deleted",
"M": "Modified",
"R": "Replacing"
}
class Client:
def __init__(self, resp_url, stdout=subprocess.PIPE):
self.cmd = ["svn"]
self.resp_url = resp_url
self.log_content = None
self.stdout = stdout
self.diff_cache = {}
def all_log_info(self):
log_cmd = self.cmd + ["log", "-v", self.resp_url, "--xml"]
return self.formate_data(log_cmd)
def log_info(self, start_version, end_version=None):
if end_version:
log_cmd = self.cmd + ["log", "-r", "{0}:{1}".format(start_version, end_version), "-v", self.resp_url,
"--xml"]
else:
log_cmd = self.cmd + ["log", "-r", str(start_version), "-v", self.resp_url, "--xml"]
return self.formate_data(log_cmd)
def formate_data(self, log_cmd):
if self.log_content is None:
self.log_content = []
data = subprocess.Popen(log_cmd, stdout=self.stdout).stdout.read()
root = xml.etree.ElementTree.fromstring(data)
for e in root.iter('logentry'):
entry_info = {x.tag: x.text for x in list(e)}
log_entry = {
'msg': entry_info.get('msg'),
'author': entry_info.get('author'),
'revision': int(e.get('revision')),
'date': entry_info.get('date')
}
cl = []
try:
for ch in e.findall('paths/path'):
cl.append("%s: %s" % (changed[ch.attrib['action']], ch.text))
except Exception:
pass
log_entry['changelist'] = cl
self.log_content.append(log_entry)
return self.log_content
def diff(self, start_version, end_version=None, decoding='utf8', cache=False):
if end_version is None:
end_version = start_version
start_version = end_version - 1
diff_cmd = self.cmd + ["diff", "-r", "{0}:{1}".format(start_version, end_version), "--summarize", self.resp_url]
if cache and self.diff_cache.setdefault(start_version, {})[end_version]:
diff_content = self.diff_cache[start_version][end_version]
else:
diff_content = []
data = subprocess.Popen(diff_cmd, stdout=self.stdout).stdout.read()
for b in data.split(b'\n'):
try:
diff_content.append(bytes.decode(b, decoding))
except:
diff_content.append(bytes.decode(b, "gbk"))
else:
pass
diff_content = "\n".join(diff_content)
if cache and self.diff_cache[start_version][end_version] is None:
self.diff_cache[start_version][end_version] = diff_content
return diff_content
def numstat(self, start_version, end_version=None, decoding='utf8', cache=False):
diff_content = self.diff(start_version, end_version, decoding, cache)
changed_file = []
for s in diff_content.split('\n'):
changed_file = self.parase_info(s)
return changed_file
def parase_info(self, s):
changed_file = []
if s and s.startswith(s[0]):
s_split = s.split(" ")
temp_split = list(filter(lambda x: x != "", s_split))
if len(temp_split) > 0:
remove_http = temp_split[1]
changed_file.append("%s: %s" % (changed[temp_split[0]], unquote(remove_http)))
return changed_file
def write_info(self, file_path, entrys, mode="w"):
"""默认重写"""
with open(file_path, mode=mode, encoding='utf8') as f:
for entry in entrys[::-1]:
version = entry['revision']
author = entry['author']
date = entry['date']
try:
date_temp = datetime.strptime(date.replace("T", " ").replace("Z", ""), '%Y-%m-%d %H:%M:%S.%f')
except AttributeError:
continue
utc_8 = date_temp + timedelta(hours=8)
msg = entry['msg']
changelist = entry['changelist']
f.write("Revision: %s\n" % version)
f.write("Author: %s\n" % author)
f.write("Date: %s\n" % utc_8)
f.write("Message: %s\n" % msg)
f.write("-" * 40 + "\n")
f.write("\n".join(changelist) + "\n")
f.write("-" * 40 + "\n")
f.write("=" * 80 + "\n")
if __name__ == '__main__':
"""
sys.argv[1]: resp_url
sys.argv[2]: file
"""
resp_url = sys.argv[1]
file = sys.argv[2]
client = Client(resp_url)
all_log = client.all_log_info()
client.write_info(file, all_log)