Google 開源的 Python 命令行庫:fire 實現 git 命令


作者:HelloGitHub-Prodesire

HelloGitHub 的《講解開源項目》系列,項目地址:https://github.com/HelloGitHub-Team/Article

一、前言

在前面三篇介紹 fire 的文章中,我們全面了解了 fire 強大而不失簡潔的能力。按照慣例,我們要像使用 argparsedocoptclick 一樣使用 fire 來實現 git 命令。

本文的關注點並不在 git 的各種命令是如何實現的,而是怎么使用 fire 去打造一個實用命令行程序,代碼結構是怎樣的。因此,和 git 相關的操作,將會使用 gitpython 庫來簡單實現。

為了讓沒讀過 使用 xxx 實現 git 命令xxxargparsedocoptclick) 的小伙伴也能讀明白本文,我們仍會對 git 常用命令和 gitpython 做一個簡單介紹。

本系列文章默認使用 Python 3 作為解釋器進行講解。
若你仍在使用 Python 2,請注意兩者之間語法和庫的使用差異哦~

二、git 常用命令

當你寫好一段代碼或增刪一些文件后,會用如下命令查看文件狀態:

git status

確認文件狀態后,會用如下命令將的一個或多個文件(夾)添加到暫存區:

git add [pathspec [pathspec ...]]

然后使用如下命令提交信息:

git commit -m "your commit message"

最后使用如下命令將提交推送到遠程倉庫:

git push

我們將使用 firegitpython 庫來實現這 4 個子命令。

三、關於 gitpython

gitpython 是一個和 git 倉庫交互的 Python 第三方庫。
我們將借用它的能力來實現真正的 git 邏輯。

安裝:

pip install gitpython

四、思考

在實現前,我們不妨先思考下會用到 fire 的哪些功能?整個程序的結構是怎樣的?

fire

git 的 4 個子命令的實現其實對應於四個函數,我們可以都放到一個類中,實現四個實例方法。
而對於 git add 命令,需要接受任意個參數,在實例方法中用 *pathspecs 參數來表達。
對於 git commit 命令,需要接受 -m 選項,在實例方法中用 m 參數來表達。

程序結構

程序結構上:

  • 實例化 Git 對象,供全局使用
  • GitCli 類中定義四個命令對應的實例方法 statusaddcommitpush

則基本結構如下:

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 <msg> 命令
        """
        pass

    def push(self):
        """
        處理 push 命令
        """
        pass


if __name__ == '__main__':
    fire.Fire(GitCli())

下面我們將一步步地實現我們的 git 程序。

五、實現

假定我們在 fire-git.py 文件中實現我們的 git 程序。

5.1 status 子命令

status 子命令不接受任何參數和選項,因此 status 方法無需任何入參。

class GitCli:
    def status(self):
        """
        處理 status 命令
        """
        cmd = ['git', 'status']
        output = git.execute(cmd)
        return output

不難看出,我們最后調用了真正的 git status 來實現,並打印了輸出。

5.2 add 子命令

add 子命令相對於 status 子命令,需要接受任意個 pathspec 參數,因此 add 方法需要增加 *pathspecs 入參。
fire 最終傳入的是一個元組,我們需要將其轉換成 list 以便后續處理。

class GitCli:
    def add(self, *pathspecs):
        """
        處理 add 命令
        """
        cmd = ['git', 'add'] + list(pathspecs)
        output = git.execute(cmd)
        return output

當我們執行 python3 fire-git.py add --help 時,結果如下:

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 子命令相對於 status 子命令,需要接受 -m 選項,因此 commit 方法需要增加 m 入參。

class GitCli:
    def commit(self, m):
        """
        處理 -m <msg> 命令
        """
        cmd = ['git', 'commit', '-m', m]
        output = git.execute(cmd)
        return output

5.4 push 子命令

push 子命令同 status 子命令一樣,不接受任何參數和選項,因此 push 方法無需任何入參。

class GitCli:
    def push(self):
        """
        處理 push 命令
        """
        cmd = ['git', 'push']
        output = git.execute(cmd)
        return output

至此,我們就實現了一個簡單的 git 命令行,使用 python fire-git.py status 便可查詢項目狀態。

非常方便的是,每個命令函數的 docstring 都將作為這個命令的幫助信息,因此,當我們執行 python3 fire-git.py --help 會自動生成如下幫助內容:

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 <msg> 命令

     push
       處理 push 命令

     status
       處理 status 命令

想看整個源碼,請戳 fire-git.py

六、小結

本文簡單介紹了日常工作中常用的 git 命令,然后提出實現它的思路,最終一步步地使用 firegitpython 實現了 git 程序。

對比 argparsedocoptclick 的實現版本,你會發現使用 fire 來實現是最簡單的:

  • 相較於 argparse,子解析器、參數類型什么的統統不需要關心
  • 相較於 docopt,參數解析和命令調用處理也不需要關心
  • 相較於 click,裝飾器所定義的命令行參數信息也必須要關心

無疑,fire 把能簡化的都簡化了,簡直就是懶人福音。

關於 fire 的講解將告一段落,回顧下 fire 的至簡之道,你會深愛上它。這也體現出了 Python 之美。

現在,你已學會了四個特點各異的主流命令行解析庫的使用了,再也不需要為命令行程序的實現而煩惱了。

什么,你為要使用哪一個庫而發愁?在下一篇也是最后一篇文章中,我們將對這些庫做一個橫向對比,以對什么場景下使用什么樣的命令行庫了然於胸~


『講解開源項目系列』——讓對開源項目感興趣的人不再畏懼、讓開源項目的發起者不再孤單。跟着我們的文章,你會發現編程的樂趣、使用和發現參與開源項目如此簡單。歡迎留言聯系我們、加入我們,讓更多人愛上開源、貢獻開源~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM