前言
记录下开发的一些事,加强自己对nodejs的应用。共勉!
有让你操蛋的事,就有需求
对于经常参与开源贡献,或者看见某些库,像试试手的人来说,经常需要git clone https://xxxx
操蛋的是,程序员是懒的,一般不会手动去删除某个项目,导致于克隆的项目会越来越多。
对于这些项目的管理,则会变得越来越困难,放眼放去,全是文件夹。
所以,需求就诞生了。
雏形
参考于GO的项目管理,发现非常的优雅。
GO的项目类似的结构是这样的
https://{source}/{owner}/{name}
- source
- owner
- name
- name
- owner
- name
- name
- name
- source
- owner
- name
- name
所以就想着写一个功能与之类似的。
这样基本就确定了一个项目目录的唯一性。
简单无脑,我只管克隆,却不用管克隆的项目在哪个文件夹,想删就删。
于是,雏形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或者给一些建议
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。