Python 命令行之旅:使用 click 實現 git 命令

做者:HelloGitHub- Prodesire

涉及的示例代碼和歷史文章,已同步更新到 HelloGitHub-Team 倉庫html

1、前言

在前面五篇介紹 click 的文章中,咱們全面瞭解了 click 的強大能力。按照慣例,咱們要像使用 argparsedocopt 同樣使用 click 來實現 git 命令。python

本文的關注點並不在 git 的各類命令是如何實現的,而是怎麼使用 click 去打造一個實用命令行程序,代碼結構是怎樣的。所以,和 git 相關的操做,將會使用 gitpython 庫來簡單實現。git

爲了讓沒讀過 使用 xxx 實現 git 命令xxxargparsedocopt) 的小夥伴也能讀明白本文,咱們仍會對 git 經常使用命令和 gitpython 作一個簡單介紹。github

本系列文章默認使用 Python 3 做爲解釋器進行講解。
若你仍在使用 Python 2,請注意二者之間語法和庫的使用差別哦~
複製代碼

2、git 經常使用命令

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

git status
複製代碼

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

git add [pathspec [pathspec ...]]
複製代碼

而後使用以下命令提交信息:函數

git commit -m "your commit message"
複製代碼

最後使用以下命令將提交推送到遠程倉庫:this

git push
複製代碼

咱們將使用 clickgitpython 庫來實現這 4 個子命令。spa

3、關於 gitpython

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

安裝:

pip install gitpython
複製代碼

4、思考

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

click

git 的 4 個子命令的實現其實對應於四個函數,每一個函數使用 clickcommand 來裝飾。 而對於 git addgit commit,則分別須要表示參數的 click.argument 和表示選項的 click.option 來裝飾。

程序結構

程序結構上:

  • 實例化 Git 對象,供全局使用
  • 定義 cli 函數做爲命令組,也就是整個命令程序的入口
  • 定義四個命令對應的實現函數 statusaddcommitpush

則基本結構以下:

import os
import click
from git.cmd import Git

git = Git(os.getcwd())


@click.group()
def cli():
    """ git 命令行 """
    pass


@cli.command()
def status():
    """ 處理 status 命令 """
    pass


@cli.command()
@click.argument('pathspec', nargs=-1)
def add(pathspec):
    """ 處理 add 命令 """
    pass


@cli.command()
@click.option('-m', 'msg')
def commit(msg):
    """ 處理 -m <msg> 命令 """
    pass


@cli.command()
def push():
    """ 處理 push 命令 """
    pass


if __name__ == '__main__':
    cli()
複製代碼

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

5、實現

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

5.1 status 子命令

status 子命令不接受任何參數和選項,所以其實現函數只需 cli.command() 裝飾。

@cli.command()
def status():
    """ 處理 status 命令 """
    cmd = ['git', 'status']
    output = git.execute(cmd)
    click.echo(output)
複製代碼

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

5.2 add 子命令

add 子命令相對於 status 子命令,須要接受任意個 pathspec 參數,所以增長一個 click.argument 裝飾器,而且在 add 函數中須要增長同名的 pathspec 入參。 經 click 處理後的 pathspec 實際上是個元組,和列表相加前,須要先轉換爲列表。

@cli.command()
@click.argument('pathspec', nargs=-1)
def add(pathspec):
    """ 處理 add 命令 """
    cmd = ['git', 'add'] + list(pathspec)
    output = git.execute(cmd)
    click.echo(output)
複製代碼

當咱們執行 python3 click-git.py add --help 時,結果以下:

Usage: click-git.py add [OPTIONS] [PATHSPEC]...

  處理 add 命令

Options:
  --help  Show this message and exit.
複製代碼

既然 git add 能接受任意多個 pathspec,那麼 add(pathspec) 的參數其實改成複數形式更爲合適,但咱們又但願幫助信息中是單數形式,這就須要額外指定 metavar,則有:

@cli.command()
@click.argument('pathspecs', nargs=-1, metavar='[PATHSPEC]...')
def add(pathspecs):
    """ 處理 add 命令 """
    cmd = ['git', 'add'] + list(pathspecs)
    output = git.execute(cmd)
    click.echo(output)
複製代碼

5.3 commit 子命令

add 子命令相對於 status 子命令,須要接受 -m 選項,所以增長一個 click.option 裝飾器,指定選項名稱 msg,而且在 commit 函數中增長同名入參。

@cli.command()
@click.option('-m', 'msg')
def commit(msg):
    """ 處理 -m <msg> 命令 """
    cmd = ['git', 'commit', '-m', msg]
    output = git.execute(cmd)
    click.echo(output)
複製代碼

5.4 push 子命令

push 子命令同 status 子命令同樣,不接受任何參數和選項,所以其實現函數只需 cli.command() 裝飾。

@cli.command()
def push():
    """ 處理 push 命令 """
    cmd = ['git', 'push']
    output = git.execute(cmd)
    click.echo(output)
複製代碼

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

很是方便的是,每一個命令函數的 docstring 都將做爲這個命令的幫助信息,所以,當咱們執行 python3 click-git.py --help 會自動生成以下幫助內容:

Usage: click-git.py [OPTIONS] COMMAND [ARGS]...

  git 命令行

Options:
  --help  Show this message and exit.

Commands:
  add     處理 add 命令
  commit  處理 -m <msg> 命令
  push    處理 push 命令
  status  處理 status 命令
複製代碼

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

6、小結

本文簡單介紹了平常工做中經常使用的 git 命令,而後提出實現它的思路,最終一步步地使用 clickgitpython 實現了 git 程序。

對比 argparseclick 的實現版本,你會發現使用 click 來實現變得特定簡單:

  • 相較於 argparse,子解析器、參數類型什麼的通通不須要關心
  • 相較於 docopt,參數解析和命令調用處理也不須要關心

這無疑是 click 最大的優點了。

關於 click 的講解將告一段落,回顧下 click 的至簡之道,你會愛上它。

如今,你已學會了三個命令行解析庫的使用了。但你覺得這就夠了嗎?click 已經夠簡單了吧,夠直接了吧?但它仍然不是最簡單的。

在下篇文章中,將爲你們介紹一個由谷歌出品的在 Python 界很火的命令行庫 —— fire


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

相關文章
相關標籤/搜索