内容简介:python实现web svn diff
最近想做一个在线codereivew的功能,需要在web页面上分两栏(side-by-side)展示新老代码的差异(diff)。
在github参考了一些项目,例如:coderev、cdiff;经过一定的尝试,最终选择了使用 Python 来实现这个功能,因为python内置的difflib标准库里有一个计算diff的函数是专门用来生成两栏(side-by-side)视图用的,而这个算法是挺复杂的,网上并没有资料讲解,所以拿来即用吧。
项目地址: https://github.com/owenliang/side-by-side-diff
项目效果: https://owenliang.github.io/side-by-side-diff/sample/side-by-side-view.html
思路
生成patch
首先,需要生成diff内容,也就是patch。这种patch文件的格式如下:
Index: bgm/application_zdm/views/mgc_detail.php =================================================================== --- bgm/application_zdm/views/mgc_detail.php (revision 172736) +++ bgm/application_zdm/views/mgc_detail.php (working copy) @@ -189,7 +189,7 @@ </div> </div> <div class="button-group pull-right"> - <a class="btn btn-primary btn-lg btn-submit" name="publish"><?= $status != 2 ? '发布榜单' : '保存榜单' ?></a> + <a class="btn btn-primary btn-lg btn-submit" name="publish"><?= $status == 2 ? '保存榜单' : '发布榜单' ?></a> <a class="btn btn-success btn-lg btn-submit" name="draft"><?= $status != 2 ? '保存为草稿' : '榜单已发布,退回为草稿' ?></a> </div> </form> @@ -236,27 +236,6 @@ var uiLi3=[{n:"请选择",k:0}]; $(this).find("ul:first").children().each(function(){ uiLi3.push({ - n:$(this).find("a:first").html(), - k:$(this).find("input:first").val() - }); - }); - uiLi2.push({ - s:$(this).find("a:first").html(), - k:$(this).find("input:first").val(), - r:uiLi3 - }); - }); - uiLi1.push({ - n:$(this).find("a:first").html(), - k:$(this).find("input:first").val(), - a:uiLi2 - }); - }); - cateList.push({ - p:$(this).find("a:first").html(), - k:$(this).find("input:first").val(), - c:uiLi1 - }); }); cateJson = {dataList:cateList}; return cateJson; @@ -285,42 +264,19 @@ } }; - var toolBox={ - cateSelected: function (curSelected) { - //初始化商品分类json数据 - handleCategory.getCateJson(function(data){ - var curSelectedArr=[]; - var catSelectConf={ - jsonData:data, - first:0,//电脑数码 - second:0,//手机通讯 - third:0,//非智能手机 - four:0, - nodata:"none" + var toolBox={vwregergweartvwertgreqgewr }; if(curSelected){//商品分类id匹配成功 curSelectedArr=curSelected.split(","); if(curSelectedArr.length>0){ $.each(curSelectedArr,function(index,cid){ - if(index==0){ - catSelectConf.first=cid; - }else if(index==1){ - catSelectConf.second=cid; - }else if(index==2){ - catSelectConf.third=cid; - }else if(index==3){ - catSelectConf.four=cid; - }else{ + if(index=sfawdv + fdd + fvweq + fa + wefawre + fgvwref - } - }) - } - } - handleCategory.cateInit(catSelectConf);//选中的商品分类填充到select - }); - }, - }; - toolBox.cateSelected("<?= implode(',', $categories) ?>"); </script> @@ -341,38 +297,7 @@ $('#tag-selector').select2({ ajax: { - url: '/tool/tag_search_by_title', - dataType: 'json', - data: function (params) { - return { - term: params.term, - page: params.page - }; - }, - processResults: function (data) { - return { - results: data.data, - pagination: { - more: data.data.length > 0 - } - }; - } - }, - placeholder: '键入关键词开始搜索...', - minimumInputLength: 1 - }); - - $('.btn-submit').click(function (event) { - event.preventDefault(); - - var formData = $(this).closest('form').serializeArray(); - - switch (this.name) { - case 'draft': - formData.push({name: 'status', value: 1}); - formData.push({name: 'is_deleted', value: 0}); - break; - case 'publish': + formData.push({name: 'status', value: 2}); formData.push({name: 'is_deleted', value: 0}); break;
一般我们通过svn diff或者git diff就可以生成,或者通过diff -u filename1 filename2也可以生成。
解析patch
我们需要解析patch文件,这个过程并不复杂。
类似于这种段落,表示是某个文件发生了变更:
Index: bgm/application_zdm/views/mgc_detail.php =================================================================== --- bgm/application_zdm/views/mgc_detail.php (revision 172736) +++ bgm/application_zdm/views/mgc_detail.php (working copy)
类似于这种段落,表示文件内的某一段发生了变化:
@@ -189,7 +189,7 @@ </div> </div> <div class="button-group pull-right"> - <a class="btn btn-primary btn-lg btn-submit" name="publish"><?= $status != 2 ? '发布榜单' : '保存榜单' ?></a> + <a class="btn btn-primary btn-lg btn-submit" name="publish"><?= $status == 2 ? '保存榜单' : '发布榜单' ?></a> <a class="btn btn-success btn-lg btn-submit" name="draft"><?= $status != 2 ? '保存为草稿' : '榜单已发布,退回为草稿' ?></a> </div> </form>
可见,上述段落删掉了一行,又增加了一行,相当于替换了原先的行。
而没有-号与+号的行,称为上下文(context)行,表示新老文件都拥有且没有变化过的行。
还原老与新段落
对于上述每个段落,我们需要还原出老文件和新文件。
context和-的行是老文件拥有的,而context和+的行是新文件拥有的,通过这样划分就可以得到每个差异段落的老内容和新内容。
调用python重算diff
现在可以将每个段落的老内容和新内容,作为一个pair传递给python的difflib._mdiff函数,这个函数会计算返回一个数组,每一个元素代表了双栏(side-by-side)视图中的一行。
我们需要根据_mdiff的返回值,对新老的行号进行重新标记。
在我的diff.py程序中,最终输出的结果在这里查看: https://raw.githubusercontent.com/owenliang/side-by-side-diff/master/sample/diff.json 。
可以观察到,最外层数组是若干的index,即发生变化的文件。
而index.segments里的每一个元素则是一个发生差异的段落。
段落内的rows记录了差异的行,我们只需要顺序的展示为两栏即可;左侧是老文件的行内容,右侧是新文件的行内容,红色标识变化前的行,绿色标识变化后的行。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- php如何实现session,自己实现session,laravel如何实现session
- AOP如何实现及实现原理
- webpack 实现 HMR 及其实现原理
- Docker实现原理之 - OverlayFS实现原理
- 为什么实现 .NET 的 ICollection 集合时需要实现 SyncRoot 属性?如何正确实现这个属性?
- 自己实现集合框架(十):顺序栈的实现
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
人类思维如何与互联网共同进化
[美] 约翰·布罗克曼 / 付晓光 / 浙江人民出版社 / 2017-3 / 79.90元
➢人类是否因互联网的诞生进入了公平竞争的场域? “黑天鹅事件”频频发生,我们的预测能力是否正在退化? 智人的第四阶段有哪些特征? 全球脑会使人类成为“超级英雄”吗? 虚拟现实技术会不会灭绝人类的真实体验? 还有更多不可预知答案的问题,你将在本书中找到属于自己的答案! ➢ 我们的心智正和互联网发生着永无止境的共振,人类思维会因此产生怎样的进化效应?本书编者约翰•布......一起来看看 《人类思维如何与互联网共同进化》 这本书的介绍吧!