GPT老师真好用啊……
1.
需求:需要定期提交commit到远程gerrit仓库,希望可以通过编程的方式让它自动提交。但由于远程仓库代码量过大,不想在本地维护,且commit内容较为独立,不会产生冲突,想要在本地生成一个commit直接交上去。
失败过程:(git是给你这么用的吗这种要求一看就会失败吧)首先我们要捏造一个commit,可以通过操作git暂存区实现。假设我们要把test.txt传到远程仓库r的目录下。先把文件加到.git的object目录下,要加-w选项,不然只会收获一个blob_id,git找不到文件。然后用git update-index把文件以任意路径放在暂存区,最后commit。
git hash-object -w ./test.txt git update-index --add --cacheinfo 100644 $blob_id $your_file_path_in_repository
之后push到仓库,会提示no common ancestor,意思是你的提交和远程仓库提交没有共同的祖先。也正常,这个commit是虚空捏造出来的,如果远程仓库不为空,git是不知道把它接到远程哪个提交后面的。事情到这里已经很复杂了,还是看看远方的gerrit REST API吧。
2.
于是写了一段java调用API,用一个类A封装起来,用类Z调用一下,点击run。然后它报错了,说java.lang.NoClassDefFoundError。这个Error的意思是编译时找到了但运行时找不到。另一个ClassNotFound是编译运行都找不到。我想是不是在BUILD文件里价格runtime_depth,但我抄的代码也没写啊,肯定是别的问题。
看了看这个类,调查了一下,是A里用到的B继承了它,我们就管它叫类C吧。找到类B所在的包,确认了一下,这个依赖引用了啊。用Debug跟了一下,发现new A的过程中Error了,报错信息里说着ClassLoader之类难懂的话,脑子里嗡一下,去年面试背的什么加载验证准备解析全冒出来。已知类B是A的一个成员,那么block了new A也是合理的,解析的时候JVM会将常量池中的符号引用替换为直接引用。于是注释掉B,还是报错,另一个第三方依赖也找不到。
感觉事情不是这样的,在类A里建立了一个main方法调用,诶,跑了,不是A的依赖的问题,那就是Z的依赖的问题。打开GPT老师,说老师我用bazel构建项目找不到依赖怎么办,GPT老师说你清一下缓存。清了几遍还是没用,我又问老师项目找不到依赖的依赖怎么办。GPT说你好bazel是不自动传递依赖的。我感到困惑。虽然很困惑,但还是把依赖复制过去,跑了一下,真的好了,我瞳孔地震。我问GPT老师以后依赖都要复制一遍吗,GPT老师说对哦,但还有更好的方式,你在BUILD里加个export。我心想抄的代码怎么没加呢,一输进去,找不到export选项。仔细看了一遍,原来是我把java_library写成java_binary了啊,引用library会自动加载依赖,但binary是不会的,默认你自己就能跑。所以改回library,也不用在Z里加A的依赖了,一切都很符合我对构建系统的想象。
虽然过程哪哪都不对,但GPT老师两个真假难辨的回答竟将一切拉回了正轨,令人感叹。