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


做者:HelloGitHub-Prodesire
html

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

1、前言

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

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

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

2、git 經常使用命令

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

git status

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

git add [pathspec [pathspec ...]]

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

git commit -m "your commit message"

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

git push

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

3、關於 gitpython

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

安裝:

pip install gitpython

4、思考

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

docopt

不一樣於使用 argparse 時須要考慮嵌套解析器、各種參數等問題,在使用 docopt 只需將咱們要實現的 git 命令用接口描述先定義清楚便可。

程序結構

程序結構上,除了開頭處定義接口描述外,其他和使用 argparse 實現 git 命令的結構是同樣的:

  • 命令行程序須要一個 cli 函數來做爲統一的入口,它負責構建解析器,並解析命令行參數
  • 咱們還須要四個 handle_xxx 函數響應對應的子命令

則基本結構以下:

import os
import docopt
from git.cmd import Git


def cli():
    """
    git 命名程序入口
    """
    pass


def handle_status(git):
    """
    處理 status 命令
    """
    pass

def handle_add(git, pathspec):
    """
    處理 add 命令
    """
    pass


def handle_commit(git, msg):
    """
    處理 -m <msg> 命令
    """
    pass


def handle_push(git):
    """
    處理 push 命令
    """
    pass


if __name__ == '__main__':
    cli()

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

5、實現

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

5.1 定義接口描述

根據咱們的要求,能夠很容易的定義出接口描述:

Usage:
    git status
    git add [<pathspec>...]
    git commit -m msg
    git push

Options:
  -h --help         Show help.
  -m --message msg  Commit with message.

進而就能夠在 cli() 中解析命令行:

def cli():
    """
    git 命名程序入口
    """
    args = docopt(__doc__)
    git = Git(os.getcwd())

5.2 status 子命令

若是 args['status']True,說明輸入了 status 子命令,那麼就調用 handle_status 函數進行處理。

def cli():
    ...
    if args['status']:
        handle_status(git)


def handle_status(git):
    """
    處理 status 命令
    """
    cmd = ['git', 'status']
    output = git.execute(cmd)
    print(output)

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

5.3 add 子命令

若是 args['add']True,說明輸入了 add 子命令,那麼就調用 handle_add 函數進行處理,須要傳入 args['<pathspec>'] 表示添加的路徑。

def cli():
    ...
    elif args['add']:
        handle_add(git, args['<pathspec>'])


def handle_add(git, pathspec):
    """
    處理 add 命令
    """
    cmd = ['git', 'add'] + pathspec
    output = git.execute(cmd)
    print(output)

5.4 commit 子命令

若是 args['commit']True,說明輸入了 commit 子命令,那麼就調用 handle_commit 函數進行處理,須要傳入 args['--message'] 表示提交的信息。

def cli():
    ...
    elif args['commit']:
        handle_commit(git, args['--message'])


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

5.5 push 子命令

若是 args['push']True,說明輸入了 commit 子命令,那麼就調用 handle_push 函數進行處理。

def cli():
    ...
    elif args['push']:
        handle_push(git)


def handle_push(git):
    """
    處理 push 命令
    """
    cmd = ['git', 'push']
    output = git.execute(cmd)
    print(output)

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

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

6、小結

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

對比 argparse 的實現版本,你會發現使用 docopt 來實現變得很是簡單,子解析器、參數類型什麼的通通不須要關心!這能夠說是 docopt 最大的優點了。

關於 docopt 的講解將告一段落,回顧下 docopt 的三步曲,加上今天的內容,感受它的使用方式仍是比 argparse 簡單很多的。

如今,你已學會了兩個命令行解析庫的使用了。但你覺得這就夠了嗎?

但人類的智慧是多麼璀璨呀,有些人並不喜歡這兩個庫的使用方式,因而他們有開闢了一個全新的思路。

在下篇文章中,將爲你們介紹一個在 Python 界十分流行的命令行庫 —— click


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

相關文章
相關標籤/搜索