Python中如何实现在Web页面展示SVN diff的小程序

项目地址: https://github.com/owenliang/side-by-side-diff

在线体验: https://owenliang.github.io/side-by-side-diff/sample/side-by-side-view.html

测了一下,有些 svn 操作场景还是没有覆盖全,不过基本的 add/del/upd 文件都是可以的。


Python中如何实现在Web页面展示SVN diff的小程序

9 回复

666 可以扩展到任意两种文本进行比对展示 diff 嘛
比如允许修改的论坛发帖 展示编辑版本


要做一个在网页上展示SVN diff的小工具,核心是调用svn diff命令获取差异内容,然后在前端用合适的格式展示。这里给你一个完整的Flask实现方案:

import subprocess
import os
from flask import Flask, render_template_string, request, jsonify

app = Flask(__name__)

def get_svn_diff(repo_path, revision1=None, revision2=None):
    """执行svn diff命令获取差异"""
    cmd = ['svn', 'diff', repo_path]
    
    if revision1 and revision2:
        cmd.extend(['-r', f'{revision1}:{revision2}'])
    elif revision1:
        cmd.extend(['-r', revision1])
    
    try:
        result = subprocess.run(
            cmd, 
            capture_output=True, 
            text=True, 
            check=True
        )
        return result.stdout
    except subprocess.CalledProcessError as e:
        return f"Error executing svn diff: {e.stderr}"

def format_diff_for_html(diff_text):
    """将diff文本转换为HTML格式"""
    if not diff_text:
        return ""
    
    lines = diff_text.split('\n')
    html_lines = []
    
    for line in lines:
        if line.startswith('+'):
            html_lines.append(f'<div class="added">{line}</div>')
        elif line.startswith('-'):
            html_lines.append(f'<div class="removed">{line}</div>')
        elif line.startswith('@@'):
            html_lines.append(f'<div class="chunk-header">{line}</div>')
        else:
            html_lines.append(f'<div>{line}</div>')
    
    return '\n'.join(html_lines)

@app.route('/')
def index():
    """主页面"""
    html_template = '''
    <!DOCTYPE html>
    <html>
    <head>
        <title>SVN Diff Viewer</title>
        <style>
            body { font-family: monospace; margin: 20px; }
            .diff-container { 
                background: #f5f5f5; 
                padding: 15px; 
                border-radius: 5px; 
                white-space: pre-wrap;
                font-size: 14px;
            }
            .added { background-color: #e6ffe6; color: #006600; }
            .removed { background-color: #ffe6e6; color: #cc0000; }
            .chunk-header { background-color: #e6f3ff; color: #0066cc; font-weight: bold; }
            form { margin-bottom: 20px; }
            input, button { padding: 8px; margin: 5px; }
        </style>
    </head>
    <body>
        <h1>SVN Diff Viewer</h1>
        <form id="diffForm">
            <input type="text" name="repo_path" placeholder="SVN仓库路径" required style="width: 300px;">
            <input type="text" name="rev1" placeholder="起始版本号 (可选)">
            <input type="text" name="rev2" placeholder="结束版本号 (可选)">
            <button type="submit">查看差异</button>
        </form>
        <div id="result" class="diff-container"></div>
        
        <script>
            document.getElementById('diffForm').addEventListener('submit', async (e) => {
                e.preventDefault();
                const formData = new FormData(e.target);
                const params = new URLSearchParams(formData);
                
                const response = await fetch('/get_diff?' + params.toString());
                const data = await response.json();
                
                document.getElementById('result').innerHTML = data.html_diff || data.error;
            });
        </script>
    </body>
    </html>
    '''
    return render_template_string(html_template)

@app.route('/get_diff')
def get_diff():
    """获取并格式化diff的API接口"""
    repo_path = request.args.get('repo_path')
    rev1 = request.args.get('rev1')
    rev2 = request.args.get('rev2')
    
    if not repo_path:
        return jsonify({'error': '请提供SVN仓库路径'})
    
    if not os.path.exists(repo_path):
        return jsonify({'error': '指定的路径不存在'})
    
    diff_text = get_svn_diff(repo_path, rev1, rev2)
    html_diff = format_diff_for_html(diff_text)
    
    return jsonify({'html_diff': html_diff})

if __name__ == '__main__':
    app.run(debug=True)

这个方案的工作原理:

  1. 后端用Flask搭建,get_svn_diff()函数调用系统命令获取原始diff
  2. format_diff_for_html()把diff文本转成带CSS样式的HTML
  3. 前端用简单的表单提交路径和版本号,通过AJAX获取并展示差异

运行前需要安装Flask:pip install flask。使用时在浏览器打开http://localhost:5000,输入SVN仓库路径和版本号即可。

如果你需要更高级的功能,比如支持多个文件、语法高亮,可以考虑集成pygments库来美化代码显示。另外注意,这个例子假设SVN客户端已安装且可执行。

核心就是调用svn命令+前端格式化展示。

可以 命令行 diff -u 也可以,稍作适配就差不多。

功能不错~

页面调整了 css,横向拉伸可以实现自适应。

difflib 本来就有 HtmlDiff,make_table

思路来自于他,是为了得到一部分灵活性。

一般我们通过 svn diff 或者 git diff 就可以生成,或者通过 diff -u filename1 filename2 也可以生成。
diff 是什么明了了? cmd 上的 svn 命令?我刚用 cmd 试了一下 diff 不行,svn diff 可以



嗯嗯,当前是为了解析 svn diff 格式做的。

按道理说,git diff,svn diff,diff -u 生成的都是 unified diff 格式的 patch,只是说一些头部的识别标识有点差异,我还没有花时间去分别的做一下适配。

回到顶部