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

背景

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

  • 原生和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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python tkinter (16) —— Progressbar

本文主要介绍Python tkinter 进度条Progressbar应用及示例。 目录 系列文章 进度条Progressbar 基本概念 参数: mode参数 基本应用 动画设计 引入time 具体实现 start/step/stop step(amount): start(interval): stop()&#xff…

QT 范例阅读:系统托盘 The System Tray Icon example

main.cpp QApplication app(argc, argv);//判断系统是否支持 系统托盘功能if (!QSystemTrayIcon::isSystemTrayAvailable()) {QMessageBox::critical(0, QObject::tr("Systray"),QObject::tr("I couldnt detect any system tray ""on this system.&qu…

一文掌握SpringBoot注解之@Configuration知识文集(6)

🏆作者简介,普修罗双战士,一直追求不断学习和成长,在技术的道路上持续探索和实践。 🏆多年互联网行业从业经验,历任核心研发工程师,项目技术负责人。 🎉欢迎 👍点赞✍评论…

ionic报错:Cannot read properties of undefined (reading ‘classList‘)

报错信息&#xff1a; [ionic/vue Warning]: The view you are trying to render for path /tabs/tab1 does not have the required <ion-page> component. Transitions and lifecycle methods may not work as expected.See https://ionicframework.com/docs/vue/navig…

fx-82es软升级至fx-991es整理

fx-82es和fx-991es在硬件上采用的是相同的流水线设计。fx-82es为了降低成本或出于其他考虑&#xff0c;卡西欧在其主板上去掉了一些以微积分为主的功能 也就是说fx-82es理论上是有可能升级到fx-991es的&#xff0c;硬件上进行升级之前有人尝试成功过了&#xff0c;但是有一定风…

30s速通String——从JVM内存 到相关方法

0.深度理解String&#xff08;初学者可后面再看&#xff09; 1.JVM理解两种初始化String方式 1.1直接初始化 栈中保存变量s1,s2&#xff0c;而变量保存“abc”在方法区的地址 这里当“abc”具有唯一性&#xff0c;字符串常量区无此字符串&#xff0c;我们就产生一个新内存“…

【动态规划】【子序列除重】【C++算法】1987不同的好子序列数目

作者推荐 【动态规划】【状态压缩】【2次选择】【广度搜索】1494. 并行课程 II 本文涉及知识点 动态规划汇总 LeetCode1987:不同的好子序列数目 给你一个二进制字符串 binary 。 binary 的一个 子序列 如果是 非空 的且没有 前导 0 &#xff08;除非数字是 “0” 本身&…

EasyRecovery2024永久免费版电脑数据恢复软件下载

EasyRecovery数据恢复软件是一款非常好用且功能全面的工具&#xff0c;它能帮助用户恢复各种丢失或误删除的数据。以下是关于EasyRecovery的详细功能介绍以及下载步骤&#xff1a; EasyRecovery-mac最新版本下载:https://wm.makeding.com/iclk/?zoneid50201 EasyRecovery-win…

AD9361多片同步设计方法

本文基于ZC706FMCOMMS5的平台&#xff0c;介绍了多片AD9361同步的方法。并将该设计移植到自行设计的ZYNQ70354片AD9361(实现8路同步收发)的电路板上。本设计采用纯逻辑的方式&#xff0c;仅使用了ZYNQ芯片的PL部分。 9361多芯片同步主要包括基带同步和射频同步两大块任务。其中…

maven插件docker-maven-plugin打包镜像并发布到dockerHub

文章目录 前言一、使用maven插件制作docker镜像二、发布到dockerHub总结 前言 如果我们的项目要在docker中运行&#xff0c;那么就必须要把我们的项目生成docker镜像&#xff0c;如果要实现远程安装&#xff0c;也就必须要把镜像发布到远程仓库里&#xff0c;如果我们没有自己…

旭华智能水文遥测终端机RTU

SV-RT8588低功耗测控终端&#xff0c;可采集、存储监测点传感器/仪表数据&#xff0c;通过4G/网口等通讯方式上传至监管平台&#xff0c;产品采用高性能32位处理器和工业级无线模块&#xff0c;接口类型丰富配置灵活&#xff0c;能满足不同场景下的各种需求&#xff1b;低功耗设…

JavaEE企业级应用软件开发—Spring框架入门学习笔记(一)

一、认识框架 实际开发中&#xff0c;随着业务的发展&#xff0c;软件系统变得越来越复杂&#xff0c;如果所有的软件都从底层功能开始开发&#xff0c;那将是一个漫长而繁琐的过程。此外&#xff0c;团队协作开发时&#xff0c;由于没有统一的调用规范&#xff0c;系统会出现大…

Vue3.4+element-plus2.5 + Vite 搭建教程整理

一、 Vue3Vite 项目搭建 说明&#xff1a; Vue3 最新版本已经基于Vite构建&#xff0c;关于Vite简介&#xff1a;Vite 下一代的前端工具链&#xff0c;前端开发与构建工具-CSDN博客 1.安装 并 创建Vue3 应用 npm create vuelatest 创建过程可以一路 NO 目前推荐使用 Vue R…

Django前后端分离之后端实践2

小实践&#xff1a;实现用户登录、注销及ORM管理功能、事务开启小实践 models.py class Books(models.Model):id models.CharField(primary_keyTrue,max_length20,verbose_name"图书ID")name models.CharField(max_length20,verbose_name图书名称)status models…

MySQL 小技巧:利用 xtrabackup 完全备份,增量备份及还原

案例&#xff1a;利用 xtrabackup 8.0 完全备份,增量备份及还原 MySQL8.0 在面对海量数据时&#xff0c;我们无法做到每天全量备份&#xff0c;因此 只能每周做一次全量备份。 而每天的话则进行增量备份&#xff0c;确保数据安全。 注意点&#xff1a;MySQL 8.0.26 版本对应需要…

基于Springboot的考编论坛网站的设计与实现(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的考编论坛网站的设计与实现&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层…

Netty重点——ByteBuf特别篇(十五)

ByteBuf为什么好用 在网络编程中&#xff0c;基本都是基于TCP报文的字节流的操作&#xff0c;所以Java的NIO又新增了ByteBuffer&#xff0c;只不过Java原生的ByteBuffer&#xff0c;非常难操作&#xff0c;也不能扩容缩容&#xff0c;所以Netty又重新封装了自己的Bytebuf&#…

力扣经典题:相交链表

题目分析&#xff1a;两个链表如果相交且不存在环&#xff0c;那么这两个链表从相交节点往后的节点都相同&#xff0c;所以&#xff0c;遍历一个链表&#xff0c;在遍历时不断遍历另一个链表&#xff0c;只要相等就可以返回了 struct ListNode *getIntersectionNode(struct Li…

2024智慧城市新纪元:引领未来,重塑都市生活

随着科技的飞速发展和数字化转型的不断深入&#xff0c;2024年智慧城市领域迎来了全新的发展格局。 这一年&#xff0c;智慧城市的建设更加注重人性化、可持续性和创新性&#xff0c;为城市居民带来了前所未有的便捷与舒适。以下将重点关注智慧城市的几个核心内容&#xff0c;…

LeetCode:14.最长公共前缀

14. 最长公共前缀 - 力扣&#xff08;LeetCode&#xff09; 目录 题目&#xff1a; 思路&#xff1a; 代码有限注释&#xff1a; 每日表情包&#xff1a; 题目&#xff1a; 思路&#xff1a; 仅有一种&#xff0c;LeetCode的四种解法&#xff0c;三种都是来水的&#…