summaryrefslogtreecommitdiffstats
path: root/doc
diff options
context:
space:
mode:
Diffstat (limited to 'doc')
-rw-r--r--doc/README_CN.md187
-rw-r--r--doc/design.md81
-rw-r--r--doc/screenshot.pngbin0 -> 225737 bytes
3 files changed, 268 insertions, 0 deletions
diff --git a/doc/README_CN.md b/doc/README_CN.md
new file mode 100644
index 0000000..ac688db
--- /dev/null
+++ b/doc/README_CN.md
@@ -0,0 +1,187 @@
+[![PyPi version](https://img.shields.io/pypi/v/gita.svg?color=blue)](https://pypi.org/project/gita/)
+[![Build Status](https://travis-ci.org/nosarthur/gita.svg?branch=master)](https://travis-ci.org/nosarthur/gita)
+[![codecov](https://codecov.io/gh/nosarthur/gita/branch/master/graph/badge.svg)](https://codecov.io/gh/nosarthur/gita)
+[![licence](https://img.shields.io/pypi/l/gita.svg)](https://github.com/nosarthur/gita/blob/master/LICENSE)
+[![PyPI - Downloads](https://img.shields.io/pypi/dm/gita.svg)](https://pypistats.org/packages/gita)
+[![English](https://img.shields.io/badge/-English-lightgrey.svg)](https://github.com/nosarthur/gita)
+
+```
+ _______________________________
+( ____ \__ __|__ __( ___ )
+| ( \/ ) ( ) ( | ( ) |
+| | | | | | | (___) |
+| | ____ | | | | | ___ |
+| | \_ ) | | | | | ( ) |
+| (___) |__) (___ | | | ) ( |
+(_______)_______/ )_( |/ \| v0.10
+```
+
+# Gita:一个管理多个 git 库的命令行工具
+
+这个工具有两个作用:
+
+- 并排显示多个库的状态信息,比如分支名,编辑状态,提交信息等
+- 在任何目录下代理执行 git 指令
+
+![gita screenshot](https://github.com/nosarthur/gita/raw/master/doc/screenshot.png)
+
+本地和远程分支之间的关系有5种情况,在这里分别用5种颜色对应着:
+
+- 绿色:本地和远程保持一致
+- 红色:本地和远程产生了分叉
+- 黄色:本地落后于远程(适合合并merge)
+- 白色:本地没有指定远程
+- 紫色:本地超前于远程(适合推送push)
+
+为什么选择了紫色作为超前以及黄色作为落后,绿色作为基准 的理由在这两篇文章中解释:
+[blueshift](https://en.wikipedia.org/wiki/Blueshift)、[redshift](https://en.wikipedia.org/wiki/Redshift)
+
+额外的状态符号意义:
+
+- `+`: 暂存(staged)
+- `*`: 未暂存(unstaged)
+- `_`: 未追踪(untracked)
+
+基础指令:
+
+- `gita add <repo-path(s)>`: 添加库
+- `gita rm <repo-name(s)>`: 移除库(不会删除文件)
+- `gita group`: 显示库的组群
+- `gita group` <repo-name(s)>: 将库分组
+- `gita ll`: 显示所有库的状态信息
+- `gita ll <group-name>`: 显示一个组群中库的状态信息
+- `gita ls`: 显示所有库的名字
+- `gita ls <repo-name>`: 显示一个库的绝对路径
+- `gita rename <repo-name> <new-name>`: 重命名一个库
+- `gita info`: 显示已用的和未用的信息项
+- `gita -v`: 显示版本号
+
+库的路径存在`$XDG_CONFIG_HOME/gita/repo_path` (多半是`~/.config/gita/repo_path`)。
+
+代理执行的子命令有两种格式:
+
+- `gita <sub-command> [repo-name(s) or group-name(s)]`: 库名或组群名是可选的,缺失表示所有库
+- `gita <sub-command> <repo-name(s) or group-name(s)>`: 必须有库名或组群名
+
+默认只有`fetch`和`pull`是第一种格式。
+
+如果输入了多个库名,
+而且被代理的git指令不需要用户输入,
+那么各个库的代理指令会被异步执行。
+
+## 私人定制
+
+定制的代理子命令要放在`$XDG_CONFIG_HOME/gita/cmds.yml` (多半是`~/.config/gita/cmds.yml`)。
+如果存在命名冲突,它们会覆盖掉默认的指令。
+
+默认代理子指令的定义可见
+[cmds.yml](https://github.com/nosarthur/gita/blob/master/gita/cmds.yml)。
+举个栗子,`gita stat <repo-name(s)>`的定义是
+
+```yaml
+stat:
+ cmd: diff --stat
+ help: show edit statistics
+```
+
+它会执行`git diff --stat`。
+
+如果被代理的指令是一个单词,`cmd`也可以省略。比如`push`。
+如果要取消异步执行,把`disable_async`设成`true`。比如`difftool`。
+
+如果你想让定制的命令跟`gita fetch`等命令一样,可以作用于所有的库,
+就把`allow_all`设成`true`。
+举个栗子,`gita comaster [repo-names(s)]`会生成一个新的定制命令,对于这个命令,库名是可选输入。comaster的解释如下:
+
+```yaml
+comaster:
+ cmd: checkout master
+ allow_all: true
+ help: checkout the master branch
+```
+另一个自定义功能是针对`gita ll`展示的信息项。
+`gita info`可以展示所有用到的和没用到的信息项,并且可以通过修改`$XDG_CONFIG_HOME/gita/info.yml`支持自定义。举个栗子,默认的信息项显示配置相当于是:
+
+```yaml
+- branch
+- commit_msg
+```
+为了创建自己的信息项,命名一个目录为`extra_info_items`。
+在`$XDG_CONFIG_HOME/gita/extra_repo_info.py`中,要把信息项的名字作为字符串映射到方法中,该方法将库的路径作为输入参数。举个栗子:
+
+```python
+def get_delim(path: str) -> str:
+ return '|'
+
+extra_info_items = {'delim': get_delim}
+```
+如果没有遇到问题,你会在`gita info`的输出内容中的`unused`小节中看到这些额外信息项。
+
+## 超人模式
+
+超人模式可以代理执行任何git命令/别名。它的格式是
+
+```
+gita super [repo-name(s) or group-name(s)] <any-git-command-with-or-without-options>
+```
+
+其中库名或组群名是可有可无的。举几个例子
+
+- `gita super checkout master`会把所有库都弄到主库杈上
+- `gita super frontend-repo backend-repo commit -am 'implement a new feature'`
+ 会对`frontend-repo`和`backend-repo`运行`git commit -am 'implement a new feature'`
+
+## 先决条件
+
+因为用了[f-string](https://www.python.org/dev/peps/pep-0498/)
+和[asyncio module](https://docs.python.org/3.6/library/asyncio.html),系统必须要用Python 3.6或以上。
+
+暗地里老夫用`subprocess`来代理执行git指令。所以git的版本有可能会影响结果。
+经测试,`1.8.3.1`, `2.17.2`, 和`2.20.1`的结果是一致的。
+
+## 安装指南
+
+正常人类按装:
+
+```
+pip3 install -U gita
+```
+
+神奇码农安装:先下载源码,然后
+
+```
+pip3 install -e <gita-source-folder>
+```
+
+装完之后在命令行下执行`gita`可能还不行。那就把下面这个昵称放到`.bashrc`里。
+```
+alias gita="python3 -m gita"
+```
+
+Windows用户可能需要额外的设置来支持彩色的命令行, 见[这个帖子](https://stackoverflow.com/questions/51680709/colored-text-output-in-powershell-console-using-ansi-vt100-codes)。
+
+## 自动补全
+
+下载
+[.gita-completion.bash](https://github.com/nosarthur/gita/blob/master/.gita-completion.bash)
+并在`.bashrc`里点它。
+
+## 有所作为
+
+要想有所作为,你可以
+
+- 报告/治理虫子
+- 建议/实现功能
+- 加星/推荐本作
+
+在本地跑单元测试可以直接用`pytest`。更多的细节可见
+[design.md](https://github.com/nosarthur/gita/blob/master/doc/design.md)。
+
+如果你愿意资助我,请访问[patreon](https://www.patreon.com/nosarthur).
+
+## 他山之石
+
+没用过,听说不错
+
+- [myrepos](https://myrepos.branchable.com/)
+- [repo](https://source.android.com/setup/develop/repo)
diff --git a/doc/design.md b/doc/design.md
new file mode 100644
index 0000000..6edf84e
--- /dev/null
+++ b/doc/design.md
@@ -0,0 +1,81 @@
+# design
+
+This document explains the inner workings of this 200 LOC (excluding tests) project.
+
+The main idea of `gita` is to run git command/alias in subprocess or
+asynchronous subprocess, which enables the following features
+
+- execute git commands/aliases from any working directory
+- execute the same command for multiple repos in batch mode
+
+In addition, the `gita ll` command runs various `git` commands to collect
+information for each repo, and displays the result of all repos side by side.
+
+## user interface
+
+There are three types of `gita` sub-commands
+
+- **bookkeeping**: add/remove repos from `gita`, display repo information
+- **delegating**: delegate pre-configured `git` commands or aliases
+- **`super`**: delegate arbitrary `git` commands or aliases
+
+And there are only two `gita` options, i.e., the `-h` for help and `-v` for version.
+
+The bookkeeping and delegating sub-commands all share the formats
+
+```shell
+gita <sub-command> <repo-name(s)>
+gita <sub-command> [repo-name(s)]
+```
+
+The exceptions are `add`, `ll`, and `super`
+
+```shell
+gita ll
+gita add <repo-path(s)>
+gita super [repo-name(s)] <any-git-command-with-options>
+```
+
+The argument choices are determined by two utility functions
+
+- `<repo-name(s)>`: `utils.get_repos() -> Dict[str, str]`
+- `[repo-name(s)]`: `utils.get_choices() -> List[Union[str, None]]` which allows null input
+
+## sub-command actions
+
+The actions of the `gita` sub-commands are defined
+in [`__main__.py`](https://github.com/nosarthur/gita/gita/__main__.py).
+
+All delegating sub-commands call
+
+```python
+f_git_cmd(args: argparse.Namespace)
+```
+
+to run either `subprocess` or `asyncio` APIs.
+`subprocess` is used if there is only one repo input or the sub-command is
+not allowed to run asynchronously. Otherwise `asyncio` is used for efficiency.
+
+The bookkeeping and `super` sub-commands have their own action functions
+
+```python
+f_<sub-command>(args: argparse.Namespace)
+```
+
+Not surprisingly, the `f_super` function calls `f_git_cmd` in the end.
+
+## repo status information
+
+Utility functions to extract repo status information are defined in [utils.py](https://github.com/nosarthur/gita/gita/utils.py).
+For example,
+
+| information | API | note |
+| ------------------------------------------------------------------------------ | ------------------------------------------- | --------------------------------------- |
+| repo name and path | `get_repos() -> Dict[str, str]` | parse `$XDG_CONFIG_HOME/gita/repo_path` |
+| branch name | `get_head(path: str) -> str` | parse `.git/HEAD` |
+| commit message | `get_commit_msg() -> str` | run `subprocess` |
+| loca/remote relation | `_get_repo_status(path: str) -> Tuple[str]` | run `subprocess` |
+| edit status, i.e., unstaged change `*`, staged change `+`, untracked files `_` | `_get_repo_status(path: str) -> Tuple[str]` | run `subprocess` |
+
+I notice that parsing file is faster than running `subprocess`.
+One future improvement could be replacing the `subprocess` calls.
diff --git a/doc/screenshot.png b/doc/screenshot.png
new file mode 100644
index 0000000..d5941d7
--- /dev/null
+++ b/doc/screenshot.png
Binary files differ