Google 開(kāi)源的 Python 命令行庫(kù):fire 實(shí)現(xiàn) git 命令
掃描二維碼
隨時(shí)隨地手機(jī)看文章
一、前言
在前面三篇介紹 fire的文章中,我們?nèi)媪私饬?
fire強(qiáng)大而不失簡(jiǎn)潔的能力。按照慣例,我們要像使用
argparse、
docopt和
click一樣使用
fire來(lái)實(shí)現(xiàn) git 命令。
本文的關(guān)注點(diǎn)并不在
git的各種命令是如何實(shí)現(xiàn)的,而是怎么使用
fire去打造一個(gè)實(shí)用命令行程序,代碼結(jié)構(gòu)是怎樣的。因此,和
git相關(guān)的操作,將會(huì)使用
gitpython庫(kù)來(lái)簡(jiǎn)單實(shí)現(xiàn)。
為了讓沒(méi)讀過(guò)
使用 xxx 實(shí)現(xiàn) git 命令(
xxx指
argparse、
docopt和
click) 的小伙伴也能讀明白本文,我們?nèi)詴?huì)對(duì)
git常用命令和
gitpython做一個(gè)簡(jiǎn)單介紹。
本系列文章默認(rèn)使用 Python 3 作為解釋器進(jìn)行講解。
若你仍在使用 Python 2,請(qǐng)注意兩者之間語(yǔ)法和庫(kù)的使用差異哦~
二、git 常用命令
當(dāng)你寫(xiě)好一段代碼或增刪一些文件后,會(huì)用如下命令查看文件狀態(tài):
git status
確認(rèn)文件狀態(tài)后,會(huì)用如下命令將的一個(gè)或多個(gè)文件(夾)添加到暫存區(qū):
git add [pathspec [pathspec ...]]
然后使用如下命令提交信息:
git commit -m "your commit message"
最后使用如下命令將提交推送到遠(yuǎn)程倉(cāng)庫(kù):
git push
我們將使用 fire和 gitpython庫(kù)來(lái)實(shí)現(xiàn)這 4 個(gè)子命令。
三、關(guān)于 gitpython
gitpython[1] 是一個(gè)和 git倉(cāng)庫(kù)交互的 Python 第三方庫(kù)。我們將借用它的能力來(lái)實(shí)現(xiàn)真正的 git邏輯。
安裝:
pip install gitpython
四、思考
在實(shí)現(xiàn)前,我們不妨先思考下會(huì)用到 fire的哪些功能?整個(gè)程序的結(jié)構(gòu)是怎樣的?
fire
git的 4 個(gè)子命令的實(shí)現(xiàn)其實(shí)對(duì)應(yīng)于四個(gè)函數(shù),我們可以都放到一個(gè)類(lèi)中,實(shí)現(xiàn)四個(gè)實(shí)例方法。而對(duì)于 git add命令,需要接受任意個(gè)參數(shù),在實(shí)例方法中用 *pathspecs參數(shù)來(lái)表達(dá)。對(duì)于 git commit命令,需要接受 -m選項(xiàng),在實(shí)例方法中用 m參數(shù)來(lái)表達(dá)。
程序結(jié)構(gòu)
程序結(jié)構(gòu)上:
-
實(shí)例化 Git對(duì)象,供全局使用
-
在 GitCli類(lèi)中定義四個(gè)命令對(duì)應(yīng)的實(shí)例方法 status、add、commit、push
則基本結(jié)構(gòu)如下:
import os import fire from git.cmd import Git
git = Git(os.getcwd()) class GitCli: def status(self): """
處理 status 命令
""" pass def add(self, *pathspecs): """
處理 add 命令
""" pass def commit(self, m): """
處理 -m命令
""" pass def push(self): """
處理 push 命令
""" pass if __name__ == '__main__':
fire.Fire(GitCli())
下面我們將一步步地實(shí)現(xiàn)我們的 git程序。
五、實(shí)現(xiàn)
假定我們?cè)?fire-git.py[2] 文件中實(shí)現(xiàn)我們的 git程序。
5.1 status 子命令
status子命令不接受任何參數(shù)和選項(xiàng),因此 status方法無(wú)需任何入?yún)ⅰ?
class GitCli: def status(self): """
處理 status 命令
""" cmd = ['git', 'status']
output = git.execute(cmd) return output
不難看出,我們最后調(diào)用了真正的 git status來(lái)實(shí)現(xiàn),并打印了輸出。
5.2 add 子命令
add子命令相對(duì)于 status子命令,需要接受任意個(gè) pathspec 參數(shù),因此 add方法需要增加 *pathspecs入?yún)?。fire 最終傳入的是一個(gè)元組,我們需要將其轉(zhuǎn)換成 list 以便后續(xù)處理。
class GitCli: def add(self, *pathspecs): """
處理 add 命令
""" cmd = ['git', 'add'] + list(pathspecs)
output = git.execute(cmd) return output
當(dāng)我們執(zhí)行 python3 fire-git.py add --help時(shí),結(jié)果如下:
INFO: Showing help with the command 'fire-git.py add -- --help'.
NAME
fire-git.py add - 處理 add 命令
SYNOPSIS
fire-git.py add [PATHSPECS]...
DESCRIPTION
處理 add 命令
POSITIONAL ARGUMENTS
PATHSPECS
5.3 commit 子命令
commit子命令相對(duì)于 status子命令,需要接受 -m選項(xiàng),因此 commit方法需要增加 m入?yún)ⅰ?
class GitCli: def commit(self, m): """
處理 -m命令
""" cmd = ['git', 'commit', '-m', m]
output = git.execute(cmd) return output
5.4 push 子命令
push子命令同 status子命令一樣,不接受任何參數(shù)和選項(xiàng),因此 push方法無(wú)需任何入?yún)ⅰ?
class GitCli: def push(self): """
處理 push 命令
""" cmd = ['git', 'push']
output = git.execute(cmd) return output
至此,我們就實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的 git命令行,使用 python fire-git.py status便可查詢(xún)項(xiàng)目狀態(tài)。
非常方便的是,每個(gè)命令函數(shù)的 docstring都將作為這個(gè)命令的幫助信息,因此,當(dāng)我們執(zhí)行 python3 fire-git.py --help會(huì)自動(dòng)生成如下幫助內(nèi)容:
INFO: Showing help with the command 'fire-git.py -- --help'.
NAME
fire-git.py
SYNOPSIS
fire-git.py COMMAND
COMMANDS
COMMAND is one of the following:
add
處理 add 命令
commit
處理 -m命令
push
處理 push 命令
status
處理 status 命令
想看整個(gè)源碼,請(qǐng)戳 fire-git.py[3] 。
六、小結(jié)
本文簡(jiǎn)單介紹了日常工作中常用的 git命令,然后提出實(shí)現(xiàn)它的思路,最終一步步地使用 fire和 gitpython實(shí)現(xiàn)了 git程序。
對(duì)比 argparse、docopt和 click的實(shí)現(xiàn)版本,你會(huì)發(fā)現(xiàn)使用 fire來(lái)實(shí)現(xiàn)是最簡(jiǎn)單的:
-
相較于 argparse,子解析器、參數(shù)類(lèi)型什么的統(tǒng)統(tǒng)不需要關(guān)心
-
相較于 docopt,參數(shù)解析和命令調(diào)用處理也不需要關(guān)心
-
相較于 click,裝飾器所定義的命令行參數(shù)信息也必須要關(guān)心
無(wú)疑,fire把能簡(jiǎn)化的都簡(jiǎn)化了,簡(jiǎn)直就是懶人福音。
關(guān)于 fire的講解將告一段落,回顧下 fire的至簡(jiǎn)之道,你會(huì)深?lèi)?ài)上它。這也體現(xiàn)出了 Python 之美。
現(xiàn)在,你已學(xué)會(huì)了四個(gè)特點(diǎn)各異的主流命令行解析庫(kù)的使用了,再也不需要為命令行程序的實(shí)現(xiàn)而煩惱了。