记录我开发gpm,Git仓库管理工具的历程

前言

记录下开发的一些事,增强本身对nodejs的应用。共勉!node

有让你操蛋的事,就有需求

对于常常参与开源贡献,或者看见某些库,像试试手的人来讲,常常须要git clone https://xxxxlinux

操蛋的是,程序员是懒的,通常不会手动去删除某个项目,致使于克隆的项目会愈来愈多。git

对于这些项目的管理,则会变得愈来愈困难,放眼放去,全是文件夹。程序员

因此,需求就诞生了。github

雏形

参考于GO的项目管理,发现很是的优雅。shell

GO的项目相似的结构是这样的npm

https://{source}/{owner}/{name}

- source
    - owner
        - name
        - name
    - owner
        - name
        - name
        - name
- source
    - owner
        - name
        - name

因此就想着写一个功能与之相似的。json

这样基本就肯定了一个项目目录的惟一性。windows

简单无脑,我只管克隆,却不用管克隆的项目在哪一个文件夹,想删就删。安全

因而,雏形git-clone-cli就诞生了

这只是一个简单的,代替git clone xxx的工具

开发

随着需求愈来愈多,已经不能知足简单的git clone了,因此gpm来了

相对与git clone, 丰富了一些东西,更另咱们方便管理

  • 支持克隆Github, Gitlab等等

  • 多样的命令,好比list,find,clean,relink,import

  • 支持插件,配置文件,hook

    > 举个简单的例子,克隆一个Javascript项目,克隆以后,自动运行 npm install 或 yarn
    > 想要什么样的插件,什么用的hook,随你配置

那些踩过的坑

权限问题

FIX ME : Windows下,若是克隆到一半,手动中断进程,则克隆下来的项目是只读,没法修改,没法删除。
尝试经过node修改权限为777,最后无果, 不了了之。

这样会致使一些命令由于没有权限而失败

交互方式

交互方式的选择一直是我蛋疼的问题,又要兼容多平台,又要简单优雅。

好比 gpm find,搜索某个仓库,而后获取相应的信息

方式一:输入(半)全称

gpm find @gpmer/gpm.js

优势:

  • 几乎能精准搜索

  • 跨终端兼容性好

缺点:

  • 太繁琐,除了本身的库,其余人的库我看并不记得。

方式二:询问/筛选

gpm find

会在终端监听输入的关键字,根据关键字筛选出一系列的仓库。
而后经过上下箭头,选择仓库

优势:

  • 不必输入繁琐的关键字,只须要记得大概

缺点:

  • 有兼容性问题,linux和OS X下没有问题,Windows下兼容pwoerShell和cmd,可是不兼容git bash

unix路径和windows路径

Linux和OS X都是unix形式的路径, 在gpm add xxx, 能够直接复制路径, cd到对应的目录.

Windows下, 获取到的是Windows风格的路径, 若是你在使用Git Bash. 很显然是不能cd的.

折中方案是加个-u, --unix参数, 选择输出unix的路径

添加仓库以后, 在终端自动cd到项目目录

在nodejs里面, 不管怎么改变工做目录, 也只是改变了这个(子)进程的工做目录. 无法改变所使用的终端的工做目录.

后来终于发现了robotjs自动化工具.

能够在终端输入命令, 而后Enter.

惋惜的是, 又是Windows不兼容. 并且robotjs的包还不小, 对于频繁升级是一种负担.

所幸就放弃了自动cd到工做目录的念头

全局插件

FIX ME: 添加了插件机制,丰富了一些功能。克隆以后,自动运行 npm install 或 yarn。
只须要在命令后面加个参数: gpm add xxx -p <插件名>
要引用全局插件,就必需要知道npm的全局node_modules在哪里。
很遗憾的是,Windows下,获取到的位置不正确,致使插件不能正常调用。

项目的.gpmrc配置文件

你能够在你的项目建立一个.gpmrc配置文件,里面写一些hook,好比:

{
  "hooks":{
    "add": "npm install"
  }
}

当经过gpm添加这个项目以后,则运行hooks里面对应的shell。

FIX ME 问题就在于这个shell,并不安全。若是要是rm -rf /,恰巧又以root权限运行,那就悲剧了。

还有就是多重的shell,好比npm install && npm run build怎么去运行。

这不是很简单? 直接 exec("npm isntall && npm run build")就完事了啊

NO, NO, NO. exec()并不优雅并且还有限制,我更喜欢用spawn

可是spawn("npm", "isntall && npm run build".split(" "))这样是会报错的. && 不是有效的命令

实际上我是这么作的,上面的命令拆分红为两条spawn("npm", ["isntall"])spawn("npm", ["run", "build"])

导入已存在的项目

你可能已经在~/project/这个目录下存放了不少的项目。若是要让你从新gpm add xxxx一个一个的添加进来,你愿意吗?

程序员要偷懒,因此才有import这个命令。把已存在的项目,按照source > owner > name的目录结构摆放好。

这又涉及到一个问题。我又想导入,又不想破坏原来~/project/的结构,这个时候就用到link。

在对应的source > owner > name目录下,建立一个link,指向~/project/中的项目

问题就来了,当你要删除这个项目的时候,即删除source > owner > name,会报错。link文件须要解除link才能删除

测试用例

有找过相似mock文件系统的方案,可是都感受不太优雅。

某天忽然顿悟,为何还有模拟什么文件系统呢,为何就不能用真实的呢,临时建立一个目录,在这个目录底下完整地走一遍流程,而后再对比预期,这样不就行了吗

总结

从开始写,到如今,commit有差很少300屡次,前先后后一个多月,也一直是我一我的使用,我我的也以为比较好用(好过没有,逃...)

总感受还有不少不完善的地方,可是我的能力和想法都有限,只能慢慢的完善。本身也在使用,打算长期维护。

最后给上项目地址:gpmer/gpm.js

我只是个菜鸡 XD,但愿有大牛给个PR或者给一些建议

相关文章
相关标签/搜索