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

news2024/11/15 11:06:11

背景

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

  • 原生和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.coloradmin.cn/o/1431016.html

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

相关文章

历年地震数据,shp格式,含时间、位置、类型、震级等信息

基本信息. 数据名称: 历年地震数据 数据格式: Shp 数据时间: 2023年 数据几何类型: 点 数据坐标系: WGS84坐标系 数据来源:网络公开数据 数据字段: 序号字段名称字段说明1dzlx地震类型2zj震级3zysd震源深度(米)4jtwz…

Python 快速入门篇

本文简介 点赞 关注 收藏 学会了 2023年是AI的元年,AI的爆火不仅推动了科技领域的进步,更让 Python 语言成为了这一变革中的关键角色。 Python 语言简单易懂,语法清晰明了,懂一点英语的都能学得会。很适合在职场摸爬滚打多年的…

layui-实现上下表,父子表单选加载事件

layui-实现上下表&#xff0c;父子表单选加载事件 代码HTML代码表格数据加载点击主表行&#xff0c;加载子表数据 实现效果图 代码 主子表&#xff0c;实现点击主表的单元格实现选中主表&#xff0c;并加载子表 HTML代码 //主表 <table class"layui-hide" id&q…

JVM系列——垃圾收集器Parrlel Scavenge、CMS、G1常用参数和使用场景

背景 当前在Java领域&#xff0c;JDK 8版本仍然享有广泛的使用&#xff0c;它支持了Parallel Scavenge、CMS和G1这几种垃圾收集器。因此&#xff0c;为了在业务应用中更加高效地进行开发和性能调优&#xff0c;我们需要对这些垃圾收集器的工作原理和特性有一个全面的理解和认识…

【乳腺肿瘤诊断分类及预测】基于自适应SPREAD-PNN概率神经网络

课题名称&#xff1a;基于自适应SPREAD-PNN的乳腺肿瘤诊断分类及预测 版本日期&#xff1a;2023-06-15 运行方式: 直接运行PNN0501.m 文件即可 代码获取方式&#xff1a;私信博主或QQ&#xff1a;491052175 模型描述&#xff1a; 威斯康辛大学医学院经过多年的收集和整理&…

Rust 第一个rust程序Hello Rust️

文章目录 前言一、vscode 安装rust相关插件二、Cargo New三、vscode调试rustLLDB 前言 Rust学习系列。今天就让我们掌握第一个rust程序。Hello Rust &#x1f980;️。 在上一篇文章我们在macOS成功安装了rust。 一、vscode 安装rust相关插件 以下是一些常用的 Rust 开发插件…

【Java程序设计】【C00245】基于Springboot的家政服务管理平台(有论文)

基于Springboot的家政服务管理平台&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的家政服务管理平台 本系统分为前台模块、管理员功能模块、用户功能模块以及服务人员功能模块。 前台模块&#xff1a;系统首页的…

深入了解 Ansible:全面掌握自动化 IT 环境的利器

本文以详尽的篇幅介绍了 Ansible 的方方面面&#xff0c;旨在帮助读者从入门到精通。无论您是初学者还是有一定经验的 Ansible 用户&#xff0c;都可以在本文中找到对应的内容&#xff0c;加深对 Ansible 的理解和应用。愿本文能成为您在 Ansible 自动化旅程中的良师益友&#…

回归预测 | Matlab实现CPO-CNN-LSTM-Attention冠豪猪优化卷积长短期记忆神经网络注意力机制多变量回归预测(SE注意力机制)

回归预测 | Matlab实现CPO-CNN-LSTM-Attention冠豪猪优化卷积长短期记忆神经网络注意力机制多变量回归预测&#xff08;SE注意力机制&#xff09; 目录 回归预测 | Matlab实现CPO-CNN-LSTM-Attention冠豪猪优化卷积长短期记忆神经网络注意力机制多变量回归预测&#xff08;SE注…

2024 AI 前端:回首展望,光芒未至,破晓之前!

前言 回望 2023 年&#xff0c;ChatGPT 的突然爆火&#xff0c;让 AI 无疑成为最为值得注目的新兴领域之一&#xff0c;我们也一起见证了生成式 AI 的寒武纪大爆发。这一年来&#xff0c;国内外的生成式 AI 、大模型和相关产品以令人眼花缭乱的速度更新迭代&#xff0c;新的创业…

day29 M端事件

M端事件 移动端也有自己独特的地方&#xff0c;比如触屏事件touch&#xff08;也称触摸事件&#xff09;touch对象代表一个触摸点。触摸点可能是一根手指&#xff0c;也可能是一根触摸笔。触屏事件可响应用户手指&#xff08;或触控笔&#xff09;对屏幕或触控板操作。常见的触…

如何从零创建一个机器人模型

1.URDF建模原理 2.机械臂URDF建模 3.三维模型导出URDF 第一步&#xff1a;下载三维模型&#xff0c;并给每个关节设置旋转轴&#xff08;基准轴&#xff09; 第二部&#xff1a;下载 SolidWorks to URDF Exporter 插件 网址&#xff1a;sw_urdf_exporter - ROS Wiki 第三步…

Win10系统搭建个人hMailServer邮件服务结合内网穿透远程发邮件

文章目录 前言1. 安装hMailServer2. 设置hMailServer3. 客户端安装添加账号4. 测试发送邮件5. 安装cpolar6. 创建公网地址7. 测试远程发送邮件8. 固定连接公网地址9. 测试固定远程地址发送邮件 前言 hMailServer 是一个邮件服务器,通过它我们可以搭建自己的邮件服务,通过cpola…

Python tkinter (14) —— 按键事件

本文主要介绍Python tkinter 几种按键事件及其示例。 目录 按键事件 响应所有按键事件 窗体绑定事件 响应特殊按键事件 指定按键事件 组合按键事件 总结 tkinter系列文章 python tkinter窗口简单实现 Python tkinter (1) —— Label标签 Python tkinter (2) —— But…

IP 了解

参考&#xff1a;5.1 IP 基础知识全家桶 | 小林coding IP 在 TCP/IP 参考模型中处于第三层&#xff0c;也就是网络层。 网络层的主要作用是&#xff1a;实现主机与主机之间的通信&#xff0c;也叫点对点&#xff08;end to end&#xff09;通信。 什么是 IP 地址&#xff1f…

大创项目推荐 题目:基于深度学习的人脸表情识别 - 卷积神经网络 大创项目推荐 代码

文章目录 0 简介1 项目说明2 数据集介绍&#xff1a;3 思路分析及代码实现3.1 数据可视化3.2 数据分离3.3 数据可视化3.4 在pytorch下创建数据集3.4.1 创建data-label对照表3.4.2 重写Dataset类3.4.3 数据集的使用 4 网络模型搭建4.1 训练模型4.2 模型的保存与加载 5 相关源码6…

apipost 简单的性能压测总结

1、简单的使用机型牌评估 1&#xff09;jdk默认256M给100用&#xff0c;推荐给1000人同时用JVM 堆栈建议2G~4G&#xff08;目前定了机型4核8G内存 2T磁盘做radio0存储&#xff09;&#xff1b; 2&#xff09;数据库配置文件写了占了2G内存&#xff08;my.cnf文件&#xff09…

2024/1/30 dfs与bfs

想要了解dfs与bfs&#xff0c;就得了解队列和栈。 一、栈与队列 1.栈 栈说白了就是先入后出。把栈类比为一个容器。只有一个口&#xff0c;所以如果我们想要取出最底层也就是最先放入的元素&#xff0c;只能最后取出它。 栈基础操作有如下几种&#xff1a; push 放入pop 拿…

车载以太网:PHY(物理层)介绍

0 工具准备 TJA1101B芯片手册 TJA1101B automotive Ethernet PHY手册 IEEE802.3-2018.pdf 1 车载以太网PHY&#xff08;物理层&#xff09;介绍 常见的普通以太网分为10BASE-2、10/100BASE-TX和1000BASE-T&#xff0c;一般都使用RJ45接口&#xff0c;对于1000BASE-T来说&#…

LabVIEW风力发电机在线监测

LabVIEW风力发电机在线监测 随着可再生能源的发展&#xff0c;风力发电成为越来越重要的能源形式。设计了一个基于控制器局域网&#xff08;CAN&#xff09;总线和LabVIEW的风力发电机在线监测系统&#xff0c;实现风力发电机的实时监控和故障诊断&#xff0c;以提高风力发电的…