遗失的源代码之回归之路的探索与实践

背景

最近比较突然被安排接手一个项目,该项目的情况如下

  • 原生和RN结合的混合开发模式
  • 组件化开发,有很多基础组件以及业务组件

但是在梳理项目依赖时发现了个别组件源码不全的情况,于是写了个cli用于对比两个版本产物文件,生成差异结果以便于快速进行源码找回恢复。
结果如下:
找回前的对比:
在这里插入图片描述

找回后对比:

在这里插入图片描述


遗失的源代码

在梳理项目时,我发现几个比较核心的组件依赖的版本跟git源码仓库的tag和发布版本不一致。

我尼玛顿时惊出一身冷汗,怕不是有些代码没提交吧!

经过核实,的确是部分代码没提交,判断依据如下:

  • 以核心组件A举例说明,它在壳子依赖的版本是2.0.0,但是源码仓库里发布配置的版本是1.0.0,并且找不到2.0.0版本的tag。
  • 源码仓库最新分支的最后一次提交时间比在maven私有仓库中2.0.0版本产物上传的时间早
  • 壳子对该组件的依赖时间从1.0.0变更为2.0.0的时间跟2.0.0版本产物上传的时间一致

由此可以确认,1.0.0到2.0.0之间的代码变更是没有提交到git仓库的,但是产物是打包并上传到私有仓库里了,所以壳子可以正常依赖使用。

找出问题

出现这种问题的原因是我们的组件打包上传流程并没有规范化,而是大家约定了一个打包上传的规范如下:

  1. 先提交代码,并打对应版本tag
  2. 然后再执行gradle打包上传脚本将对应版本的aar或者jar上传到maven私有仓库

但是这种靠人为执行约定流程是不可控的,有时候开发图省事直接自己在项目中执行一个gradle打包上传脚本把产物上传到maven私有仓库,然后壳子工程就可以依赖使用了,但是本地代码忘记提交到git仓库,也不会去打tag,这样就导致了可能出现产物版本是最新的,但是仓库源码并非最新的情况。

解决问题
出现这个问题的根本原因在于没有一个规范的管理流程,解决这个问题也比较简单,就是把开发直接打包上传到maven的权限收回,把打包操作后置例如放到CI上执行。
大致流程如下:

  1. 提供一个入口例如网页,网页上把git仓库管理起来
  2. 需要打包就在网页上选择对应的git仓库,网页把打包相关的配置展示出来,点击确定按钮触发CI打包流程
  3. CI去对应的git仓库执行内部对应的打包上传脚本即可

由于CI是直接去git仓库拉代码打包的,这样就避免出现了代码没提交,但是产物能出来的问题了。
当然,实现这个打包管理的流程设计到前后端以及CI,整体的细节和工作量还是不少的,上面只是一个大致流程。

实际上如何管理打包流程都是后话了,当务之急是要把新版本的代码找回来。
在梳理的时候其实发现了一个更严重的问题是,当时的项目RN升级一个大版本,做法是基于RN的源码做了些修改然后重新打包成aar给壳子工程依赖的,但是,那个基于RN源码定制的git仓库都找不到了,也就是我要先基于RN的源码编译出产物,然后还要找回已有aar和RN源码编译出来的aar之间的代码变更。本来我对RN就不熟悉,又出了这一档子事情,这不是给我加难度吗…
在这里插入图片描述


回归之路的探索

上面也说到了,当务之急是先把源码给恢复好,因为后续还需要基于恢复后的代码继续开发迭代,经过沟通过后得知是不可能再找到之前的开发看看能不能把没提交的代码给提交一下了。

那就只剩下一条路,自己尝试着恢复,那怎么恢复呢?
先来梳理一下现有的东西。

  • git仓库里有旧版本的源码,RN的话github上找对应版本的源码即可,
  • 有新版本的aar文件

思路一

很自然的一个思路就是Android Studio不是能直接看到依赖产物的的代码吗?
例如在这里插入图片描述
那我直接找到对应的产物,跟源码文件一个一个进行内容对比不就可以了。
当然这样理论上是可以实现的,但实际落地下来很难执行,原因如下:

  • 在打包成产物后的源码进行处理过后的,一些注释啊,空格啊,变量名啊,代码的顺序啊都会有变更,AS上显示的产物里的代码是对已经处理过的源码编译后的class文件进行反编译显示,那这样一来,跟原本的源代码就会产生很大的差异。

以RN的源码举例说明,下面是在AS上看的RN源码中的一个类

在这里插入图片描述

再来看下实际的源码
在这里插入图片描述

可以明显的看出从代码行数以及变量名都有变化,这还是一个非常简单的类,这种我们可以肉眼对比出来,RN源码中负责的类有非常多,这种我们如果一个一个对比肉眼去看,那简直是个灾难。

到这里实际上肉眼比较的方案其实已经执行不下去了,原因如下:

  1. 对于源码数量非常多的组件,工作量巨大,因为我们要对比每一个文件还有资源文件,确保找出增,删,改的文件
  2. 人工去对比最终的结果质量无法保证,基本可以遇见的是花了一上午对比了几个文件后就开始心情烦躁,情绪波动,最后直接开摆,扫一眼没啥问题就过。

在这里插入图片描述
3. 心智负担巨大,这种明显是属于吃力也不讨好的方案,最后人家问你确定恢复的没有问题吗?你真的敢说没问题吗?

思路二

基于思路一我们来看一下有什么问题

  • 直接看产物反编译后的代码跟旧版本源码比较差异大,难以确定是否变更
  • 对于代码量多的组件,工作量大,人工对比效率太低
  • 靠人工判断无法保证最终结果的正确性
代码差异大的问题

对于查看反编译后的产物跟源码比较差异大的问题,想办法让他们俩尽量在状态比较一致的情况下再次对比。
我们可以把源码也打包编译成产物,然后对比两个版本产物反编译后的代码内容确定是否有变更。实际操作下来这种方式确实能够极大的减少代码差异大的情况

效率低的问题

上面也说到了,人工对比的心智负担比较大,例如RN源码有700多个类文件,一个一个对比下来先不说时间问题,准确度也没办法保证,毕竟,我们不能仅仅靠代码行数是否一致就去判断代码有没有变更。

准确度的问题

可以通过程序计算对比文件的md5值,给出最终的结果输出,保证最终还原的正确性

解决方案

可以做一个工具,把新老版本的产物丢进去,程序帮我们进行解压,遍历,反编译等操作,然后对反编译后的java文件进行md5值计算,最后输出结果,把md5值不同的文件输出出来,这样依赖,既可以保证每个文件都能对比到,还能确保最终的结果是稳定可靠的。

大致流程如下

  1. 将已有源码编译成产物aar
  2. 设计一个cli工具,用于处理两个版本的产物
  3. 对产物进行解压,先处理资源文件,计算文件的md5值
  4. 针对代码文件进行反编译,随后遍历反编译后的java文件,计算md5值
  5. 新老版本结果进行对比,找出增,删,改的文件
  6. 输出结果

回归之路的实践

确定好方案之后,就可以动手开发了,这里我选择是做一个cli工具。

初步实现

CLI工具可下载直接使用:下载地址 component-diff-1.0.0.jar
使用方式如下:

java -jar jar包路径 true --old 旧版本产物 --new新版本产物 --output 结果输出目录

参数说明

  • jar包路径:就是你下载的jar文件在你的电脑的绝对路径
  • true表示打印执行日志
  • --old后面跟你的旧版本的产物文件路径
  • --new 后面跟你的新版本的产物文件路径
  • --output 后面跟输出结果目录

示例:

java -jar /Users/yuzhiqiang/Documents/组件对比/component-diff-1.0.0.jar true --old //Users/yuzhiqiang/Documents/组件对比/rn_source/old/react-native-0.68.5.aar --new /Users/yuzhiqiang/Documents/组件对比/rn_source/new/react-native-0.68.513.aar --output /Users/yuzhiqiang/Documents/组件对比/r

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/666102.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【lesson9】高并发内存池Page Cache层释放内存的实现

文章目录 Page Cache层释放内存的流程Page Cache层释放内存的实现 Page Cache层释放内存的流程 如果central cache释放回一个span,则依次寻找span的前后page id的没有在使用的空闲span,看是否可以合并,如果合并继续向前寻找。这样就可以将切…

05、全文检索 -- Solr -- Solr 全文检索之图形界面的文档管理(文档的添加、删除,如何通过关键字等参数查询文档)

目录 Solr 全文检索之文档管理添加文档使用 JSON 添加文档:使用 XML 添加文档: 删除文档使用 JSON 删除文档:使用 XML 删除文档: 查询文档查询文档的详细参数fq(Filter Query):过滤sort:排序sta…

[Linux 进程(六)] 写时拷贝 - 进程终止

文章目录 1、写时拷贝2、进程终止2.1 进程退出场景2.1.1 退出码2.1.2 错误码错误码 vs 退出码2.1.3 代码异常终止引入 2.2 进程常见退出方法2.2.1 exit函数2.2.2 _exit函数 本片我们主要来讲进程控制,讲之前我们先把写时拷贝理清,然后再开始讲进程控制。…

简单的程序员简历模板

以下是一个简单的程序员简历模板,您可以根据自己的经验和需求进行调整: 姓名:张三联系方式:XXX-XXXX-XXXX电子邮箱:zhangsanexample.com个人网址:(如果适用,比如GitHub、个人博客等&…

[office] 在Excel2010中设定某些单元格数据不参与排序的方法介绍 #其他#知识分享#笔记

在Excel2010中设定某些单元格数据不参与排序的方法介绍 在Excel中排序,相信大家都会了,直接将一组数据按照从小到大或者从大到小进行排序,但是,现在要求我们规定其中几组数据不进行排序,只排序其余的部分。又该如何操作…

ruoyi(若依)(el-menu也可参考)菜单栏过长显示省略号才显示气泡

一、背景 若依前后端分离的版本,新版本中优化了菜单名称过长悬停显示标题,但是是悬浮所有长度大于5的标题。可以查看提交记录:https://gitee.com/y_project/RuoYi-Cloud/commit/99932d91c0144da9f34f5bb05683cc0b86303217 但是我希望是只悬浮…

如何判断测试覆盖率是否达标?常见提高覆盖率方法总结

前言 大家好,我是chowley,今天来介绍一下测试覆盖率的内容。 在软件开发的过程中,测试覆盖率是衡量测试质量的重要指标之一。通过有效的测试覆盖,我们能够更全面地了解软件在不同条件下的运行情况,减少潜在的缺陷和问…

VC++中使用OpenCV绘制直线、矩形、圆和文字

VC中使用OpenCV绘制直线、矩形、圆和文字 在VC中使用OpenCV绘制直线、矩形、圆和文字非常简单,分别使用OpenCV中的line、rectangle、circle、putText这四个函数即可。具体可以参考OpenCV官方文档:https://docs.opencv.org/4.x/index.html 下面的代码展…

nodejs express中使用连接池或者MySQL链接数据库出现Cannot read property ‘query‘ of undefined报错

1.如果你已经排除了数据库的启动状态原因和本地服务是否启动的原因 2.不妨看看你是否没有排查其他的数据库,我就是一直在排查第一个主数据库,却忘了我还连接了第二个数据库,就是第二个数据库的原因,出现这个错误。 3.我们可以通…

【文本到上下文 #10】探索地平线:GPT 和 NLP 中大型语言模型的未来

一、说明 欢迎阅读我们【文本到上下文 #10】:此为最后一章。以我们之前对 BERT 和迁移学习的讨论为基础,将重点转移到更广阔的视角,包括语言模型的演变和未来,特别是生成式预训练转换器 (GPT) 及其在 NLP 中…

「 CISSP学习笔记 」08. 安全运营

该知识领域涉及如下考点,具体内容分布于如下各个子章节: 理解并遵守调查执行记录和监控活动执行配置管理 (CM)(例如,预配、基线、自动化)应用基本的安全操作概念应用资源保护执行事故管理执行和维护检测和预防措施实施…

我们使用的IPv4耗尽(We‘re running out of IPv4)

IPv4(Internet Protocol version 4)是互联网上使用最广泛的网络层协议之一,于1981年在 RFC 791 中发布,它定义了 32 位的IP地址结构和基本的协议操作。 由于 IPv4 使用 32 位的地址,因此只有四十亿(4,294,967,296,2^32)个地址。 这就导致随着地址不断被分配,IPv4 地…

邦芒忠告:初入职场的菜鸟小白谨记这3种聊天

在人际交往上应该注意分寸,也应该注意尺度,也应该注意不要麻烦别人,也不能够出现一些言语上的漏洞,也不能够说出一些不合时宜的话。 1、不要轻易表现出你特别讨厌的东西 比如某些明星,说不定他们十分喜欢,谈…

【力扣刷题练习】876. 链表的中间结点

题目描述: 给你单链表的头结点 head ,请你找出并返回链表的中间结点。 如果有两个中间结点,则返回第二个中间结点。 题目解答: class Solution {public ListNode middleNode(ListNode head) {ListNode slow head, fast head…

用threejs模拟太阳系运动三维模型

最近在学习threejs,觉得非常有趣。于是决定用这个来模拟太阳系各行星的运行轨迹。 关于threejs的基础知识就不再赘述了,大家可以查看官网:threejs官方网站 本文的demo可以从下面下载:threejs模拟太阳系八大行星公转及自转三维模…

未来电话呼叫技术的社会影响与发展趋势----云微呼

未来电话呼叫技术将以更为智能化、便捷化和个性化为主要发展趋势,其所带来的社会影响也将是多层面的。以下将探讨未来电话呼叫技术可能的发展趋势以及对社会的影响: 智能化助力生活便捷: 未来电话呼叫技术将更加智能化,通过人工智…

聊聊PowerJob日志的上报及存储

序 本文主要研究一下PowerJob的日志上报及存储 OmsLoggerFactory.build tech/powerjob/worker/log/OmsLoggerFactory.java public class OmsLoggerFactory {public static OmsLogger build(Long instanceId, String logConfig, WorkerRuntime workerRuntime) {LogConfig cf…

uniapp 组件封装

1. uniapp 组件封装时间戳格式化为星期 1.1. components/m-week.vue <template><text>{{week}}</text> </template> <script>export default {props: {time: String},mounted(e) {this.week this.getWeek(Number(this.time))},data() {return …

FreeMark ${r‘原样输出‘} ${r“原样输出“}

FreeMark ${r’原样输出’} ${r"原样输出"} 在${}使用 小写字母r接两个单引号或两个双引号包裹的内容可以原样输出, 字母r只能用小写 ${r想要原样输出的内容} --用了单引号${r"想要原样输出的内容"} --用了双引号 例子: ${r"${r}"} 得到 ${r…

Unity引擎学习笔记之【动画、动画器操作】

动画Animate Animation是基于关键帧的动画系统&#xff0c;适用于简单的动画需求&#xff1b; 而Animator是一种状态机驱动的动画系统&#xff0c;适用于更复杂的动画逻辑和交互式动画。 通常&#xff0c;Animator组件更适合用于游戏中的角色动画控制&#xff0c; 而Animation…