当前位置:首页>编程日记>正文

代码打补丁的利器——diff和patch

        一般来说,如果我们在研发过程中需要对代码进行修改,是不需要通过打补丁的方式的,因为我们可以直接改动文件即可。但是如果针对一款要上线的产品,我们总不能在研发的电脑上编译通过后直接发布到线上的。(转载请指明出于breaksoftware的csdn博客)因为这样做有很多缺陷:

  • 最后负责编译的同事,可能忘记提交最终的代码。这样代码库中的代码逻辑和线上运行的产品逻辑将存在差异。
  • 最后负责编译的同事的编译环境可能已经感染病毒,从而导致编译的产品也携带病毒。这样的产品发布到线上将污染生产环境。
  • 无法保证最后负责编译的同事是否对产品逻辑“做过手脚”。
  • 无法保证最后负责编译的系统版本和关联库版本和线上环境一致。

        因为存在种种弊端,所以很多公司都会有专门的编译系统。大家把代码提交到代码库,然后触发编译平台。编译平台会挑选一些编译环境将代码从代码库中拉取下来,然后在这些与外网隔绝的稳定环境中进行代码编译。这样可以杜绝上述问题。

        在一些成规模的公司,会有很多可供大家公用的代码库。如果我们要实现一个功能,可能会用到这些代码库——即依赖,其与我们工程的关系可以分为以下两种:

  1. 把这些依赖放在我们工程代码内部,成为我们自己的私有代码。
  2. 依赖以独立模块存在,不属于我们自己维护的工程代码。只有在编译前才拉取下来。

         可以看出方案1非常不易于维护,因为我们的依赖库会不定期更新,这样就需要定期检查每个依赖库是否有更新并同步更新。而方案2可以让我们从上述繁琐的工作中解脱出来。我们只要在编译前把库(可能是最新的)拉取到本地或者编译环境下即可,而不用关心库的维护者什么时候进行了更新。因此。一般项目我们都是选用方案2的。

        上述看着一切都很美好。而然现实往往比理想要复杂很多。比如我们发现依赖库存在bug,而维护者没有时间去验证bug从而无法提供一个我们认为“稳定”的版本。我们又无法登陆公司的编译环境(实际上公司也不会让普通员工登陆编译环境,否则就太危险了),不可以手工修改依赖库的代码。这种条条规则框住的“无解”问题怎么办?给代码打patch此时就有了用武之地了。

        给代码打patch需要用到两个工具——diff和patch,它们都是linux系统上工具,我们可以很放心的使用。

        diff工具是用于生成补丁文件的。比如依赖库文件中文件A.cpp有bug,我们修改了bug并将文件另存为A_modify.cpp,这样通过下面命令生成补丁文件A_patch.cpp

diff -up A.cpp A_modify.cpp > A_patch.cpp

        代码打补丁的利器——diff和patch 配图01

        在编译前,调用下面指令将补丁临时放到依赖库的A.cpp中

patch -p0 < A_patch.cpp

        代码打补丁的利器——diff和patch 配图02

        这个时候A.cpp代码就已经没有bug了,我们执行编译。等编译结束后,我们可以使用下面指令,还原A.cpp到原始的内容,即去除补丁

patch -RE -p0 < A_patch.cpp

代码打补丁的利器——diff和patch 配图03       

         举个例子:src目录下有不能修改的代码,而我们需要修改其中若干个文件。则我们将创建一个叫做modiy_src的目录,其中文件和src中文件相对路径一致。这样我们就可以修改modify_src下的代码,然后使用cmp工具对比每个文件。如果发现modify_src中的文件和src中的文件不一致,则在patch_src目录下生成一个相对路径一致的补丁文件

#!/bin/shfunction left_to_right(){for element in `ls $1`doleft_dir_or_file=$1"/"$elementright_dir_or_file=$2"/"$elementpatch_dir_or_file=$3"/"$elementif [ -d $left_dir_or_file ];thenleft_to_right $left_dir_or_file $right_dir_or_file $patch_dir_or_fileelseextension=${left_dir_or_file##*.}if [ "$extension"  != "c" -a  "$extension"  != "h" ];thencontinuefiif [ ! -f "$right_dir_or_file" ];thenright_path_floder=$(dirname $right_dir_or_file)if [ ! -d "$right_path_floder" ];thenmkdir -p $right_path_floderficp $left_dir_or_file $right_dir_or_fileelsecmp -s $left_dir_or_file $right_dir_or_filedifferent=$?if [ 0 == $different ];thencontinuefipatch_path_floder=$(dirname $patch_dir_or_file)if [ ! -d "$patch_path_floder" ];thenmkdir -p $patch_path_floderfidiff -up $left_dir_or_file $right_dir_or_file > $patch_dir_or_filefifidone
}left_to_right src/ modify_src/ patch_src/

        然后再写一个脚本,对patch_src下文件进行遍历,并且根据传入的参数决定“打补丁”还是“去除补丁”。

#!/bin/shfunction patch_files(){if [ "$2" == "recover" ];thencover=0elif [ "$2" == "cover" ];thencover=1elseecho "sh patch_files cover/recover"exitfifor element in `ls $1`dopatch_dir_or_file=$1"/"$elementif [ -d $patch_dir_or_file ];thenpatch_files $patch_dir_or_file $2elseif [ 0 == $cover ];thenpatch -RE -p0 < $patch_dir_or_fileelsepatch -p0 < $patch_dir_or_filefifidone
}patch_files patch_src/ $1

        这样在编译时我们这么做,以保证编译正确的代码,同时在编译结束后将代码还原

sh ./patch_files.sh cover
make
sh ./patch_files.sh recover

http://www.coolblog.cn/news/bddc8ab584f2511c.html

相关文章:

  • asp多表查询并显示_SpringBoot系列(五):SpringBoot整合Mybatis实现多表关联查询
  • s7day2学习记录
  • 【求锤得锤的故事】Redis锁从面试连环炮聊到神仙打架。
  • 矿Spring入门Demo
  • 拼音怎么写_老师:不会写的字用圈代替,看到孩子试卷,网友:人才
  • Linux 实时流量监测(iptraf中文图解)
  • Win10 + Python + GPU版MXNet + VS2015 + RTools + R配置
  • 美颜
  • shell访问php文件夹,Shell获取某目录下所有文件夹的名称
  • 如何优雅的实现 Spring Boot 接口参数加密解密?
  • LeCun亲授的深度学习入门课:从飞行器的发明到卷积神经网络
  • Mac原生Terminal快速登录ssh
  • java受保护的数据与_Javascript类定义语法,私有成员、受保护成员、静态成员等介绍...
  • mysql commit 机制_1024MySQL事物提交机制
  • 支撑微博千亿调用的轻量级RPC框架:Motan
  • jquery 使用小技巧
  • 2019-9
  • 法拉利虚拟学院2010 服务器,法拉利虚拟学院2010
  • vscode pylint 错误_将实际未错误的py库添加到pylint白名单
  • 科学计算工具NumPy(3):ndarray的元素处理
  • 工程师在工作电脑存 64G 不雅文件,被公司开除后索赔 41 万,结果…
  • linux批量创建用户和密码
  • newinsets用法java_Java XYPlot.setInsets方法代碼示例
  • js常用阻止冒泡事件
  • 气泡图在开源监控工具中的应用效果
  • 各类型土地利用图例_划重点!国土空间总体规划——土地利用
  • php 启动服务器监听
  • dubbo简单示例
  • 【设计模式】 模式PK:策略模式VS状态模式
  • [iptables]Redhat 7.2下使用iptables实现NAT
  • Ubuntu13.10:[3]如何开启SSH SERVER服务
  • CSS小技巧——CSS滚动条美化
  • JS实现-页面数据无限加载
  • 阿里巴巴分布式服务框架 Dubbo
  • 最新DOS大全
  • Django View(视图系统)
  • 阿里大鱼.net core 发送短信
  • 程序员入错行怎么办?
  • 两张超级大表join优化
  • 第九天函数
  • Linux软件安装-----apache安装
  • HDU 5988 最小费用流
  • Sorenson Capital:值得投资的 5 种 AI 技术
  • 《看透springmvc源码分析与实践》读书笔记一
  • 正式开课!如何学习相机模型与标定?(单目+双目+鱼眼+深度相机)
  • Arm芯片的新革命在缓缓上演
  • nagios自写插件—check_file
  • python3 错误 Max retries exceeded with url 解决方法
  • 行为模式之Template Method模式
  • 通过Spark进行ALS离线和Stream实时推荐