diff options
-rw-r--r-- | .gita-completion.zsh | 46 | ||||
-rw-r--r-- | .github/FUNDING.yml | 12 | ||||
-rw-r--r-- | CODE_OF_CONDUCT.md | 76 | ||||
-rw-r--r-- | README.md | 110 | ||||
-rw-r--r-- | doc/README_CN.md | 89 | ||||
-rw-r--r-- | gita/__main__.py | 3 | ||||
-rw-r--r-- | gita/common.py | 3 | ||||
-rw-r--r-- | setup.py | 2 | ||||
-rw-r--r-- | tests/test_main.py | 11 |
9 files changed, 253 insertions, 99 deletions
diff --git a/.gita-completion.zsh b/.gita-completion.zsh new file mode 100644 index 0000000..d1fe952 --- /dev/null +++ b/.gita-completion.zsh @@ -0,0 +1,46 @@ + +_gita_completions() +{ + + local cur commands repos cmd + local COMP_CWORD COMP_WORDS # 定义变量,cur表示当前光标下的单词 + read -cn COMP_CWORD # 所有指令集 + read -Ac COMP_WORDS # 当前指令的索引值 + + cur=${COMP_WORDS[COMP_CWORD]} + cmd=${COMP_WORDS[2]} + + # FIXME: this is somewhat slow + commands=`gita -h | sed '2q;d' |sed 's/[{}.,]/ /g'` + + repos=`gita ls` + # this doesn't work for two repos with the same basename + #gita_path=${XDG_CONFIG_HOME:-$HOME/.config}/gita/repo_path + #repos=`awk '{split($0, paths, ":")} END {for (i in paths) {n=split(paths[i],b, /\//); print b[n]}}' ${gita_path}` + + # FIXME(Steve-Xyh): the secondary auto-completion(such as `$repos`) contains first commands / 二级补全候选项中包含一级补全中的 `$commands` + # XXX(Steve-Xyh): the auto-completion is currently case-sensitive / 当前的补全区分大小写, 应该改成大小写不敏感 + # (Steve-Xyh): args in zsh must be `reply` / zsh 中的参数必须为 `reply` + if [ -z "$cmd" ]; then + reply=($(compgen -W "${commands}" ${cur})) + else + cmd_reply=($(compgen -W "${commands}" ${cmd})) + case $cmd in + add) + reply=(cmd_reply $(compgen -d ${cur})) + ;; + ll) + return + ;; + *) + reply=($cmd_reply $(compgen -W "${repos}" ${cur})) + ;; + esac + fi + +} + +# (Steve-Xyh): functions in zsh must be `compctl` / zsh 中必须用 compctl 函数, -K 表示使用函数 +compctl -K _gita_completions gita + + diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..b5ff720 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,12 @@ +# These are supported funding model platforms + +github: nosarthur # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +patreon: # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..d401f78 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,76 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at zhou.dong@gmail.com. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see +https://www.contributor-covenant.org/faq @@ -3,6 +3,7 @@ [![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) +[![Gitter](https://badges.gitter.im/nosarthur/gita.svg)](https://gitter.im/nosarthur/gita?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![Chinese](https://img.shields.io/badge/-中文-lightgrey.svg)](https://github.com/nosarthur/gita/blob/master/doc/README_CN.md) ``` @@ -21,9 +22,9 @@ This tool does two things - display the status of multiple git repos such as branch, modification, commit message side by side -- delegate git commands/aliases from any working directory +- (batch) delegate git commands/aliases from any working directory -If several repos compile together, it helps to see their status together too. +If several repos are related, it helps to see their status together too. I also hate to change directories to execute git commands. ![gita screenshot](https://github.com/nosarthur/gita/raw/master/doc/screenshot.png) @@ -75,6 +76,56 @@ By default, only `fetch` and `pull` take optional input. If more than one repos are specified, the git command will run asynchronously, with the exception of `log`, `difftool` and `mergetool`, which require non-trivial user input. +## Installation + +To install the latest version, run + +``` +pip3 install -U gita +``` + +If development mode is preferred, +download the source code and run + +``` +pip3 install -e <gita-source-folder> +``` + +In either case, calling `gita` in terminal may not work, +then you can put the following line in the `.bashrc` file. + +``` +alias gita="python3 -m gita" +``` + +Windows users may need to enable the ANSI escape sequence in terminal, otherwise +the branch color won't work. +See [this stackoverflow post](https://stackoverflow.com/questions/51680709/colored-text-output-in-powershell-console-using-ansi-vt100-codes) for details. + +## Auto-completion + +Download +[.gita-completion.bash](https://github.com/nosarthur/gita/blob/master/.gita-completion.bash) +or +[.gita-completion.zsh](https://github.com/nosarthur/gita/blob/master/.gita-completion.zsh) +and source it in the .rc file. + +## Superman mode + +The superman mode delegates any git command/alias. +Usage: + +``` +gita super [repo-name(s) or group-name(s)] <any-git-command-with-or-without-options> +``` + +Here `repo-name(s)` or `group-name(s)` are optional, and their absence means all repos. +For example, + +- `gita super checkout master` puts all repos on the master branch +- `gita super frontend-repo backend-repo commit -am 'implement a new feature'` + executes `git commit -am 'implement a new feature'` for `frontend-repo` and `backend-repo` + ## Customization Custom delegating sub-commands can be defined in `$XDG_CONFIG_HOME/gita/cmds.yml` @@ -136,22 +187,6 @@ extra_info_items = {'delim': get_delim} If it works, you will see these extra items in the 'Unused' section of the `gita info` output. To use them, edit `$XDG_CONFIG_HOME/gita/extra_repo_info.py`. -## Superman mode - -The superman mode delegates any git command/alias. -Usage: - -``` -gita super [repo-name(s) or group-name(s)] <any-git-command-with-or-without-options> -``` - -Here `repo-name(s)` or `group-name(s)` are optional, and their absence means all repos. -For example, - -- `gita super checkout master` puts all repos on the master branch -- `gita super frontend-repo backend-repo commit -am 'implement a new feature'` - executes `git commit -am 'implement a new feature'` for `frontend-repo` and `backend-repo` - ## Requirements Gita requires Python 3.6 or higher, due to the use of @@ -163,38 +198,6 @@ Thus the installed git version may matter. I have git `1.8.3.1`, `2.17.2`, and `2.20.1` on my machines, and their results agree. -## Installation - -To install the latest version, run - -``` -pip3 install -U gita -``` - -If development mode is preferred, -download the source code and run - -``` -pip3 install -e <gita-source-folder> -``` - -In either case, calling `gita` in terminal may not work, -then you can put the following line in the `.bashrc` file. - -``` -alias gita="python3 -m gita" -``` - -Windows users may need to enable the ANSI escape sequence in terminal, otherwise -the branch color won't work. -See [this stackoverflow post](https://stackoverflow.com/questions/51680709/colored-text-output-in-powershell-console-using-ansi-vt100-codes) for details. - -## Auto-completion - -Download -[.gita-completion.bash](https://github.com/nosarthur/gita/blob/master/.gita-completion.bash) -and source it in `.bashrc`. - ## Contributing To contribute, you can @@ -203,12 +206,14 @@ To contribute, you can - request/implement features - star/recommend this project +Chat room is available on [![Join the chat at https://gitter.im/nosarthur/gita](https://badges.gitter.im/nosarthur/gita.svg)](https://gitter.im/nosarthur/gita?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + To run tests locally, simply `pytest`. More implementation details are in [design.md](https://github.com/nosarthur/gita/blob/master/doc/design.md). +A step-by-step guide to reproduce this project is [here](https://nosarthur.github.io/side%20project/2019/05/27/gita-breakdown.html). -You can also make donation to me on [patreon](https://www.patreon.com/nosarthur). -Any amount is appreciated! +You can also sponsor me on [GitHub](https://github.com/sponsors/nosarthur). Any amount is appreciated! ## Contributors @@ -220,6 +225,7 @@ Any amount is appreciated! [![TpOut](https://github.com/TpOut.png?size=40 "TpOut")](https://github.com/TpOut) [![PabloCastellano](https://github.com/PabloCastellano.png?size=40 "PabloCastellano")](https://github.com/PabloCastellano) [![cd3](https://github.com/cd3.png?size=40 "cd3")](https://github.com/cd3) +[![Steve-Xyh](https://github.com/Steve-Xyh.png?size=40 "Steve-Xyh")](https://github.com/Steve-Xyh) ## Other multi-repo tools diff --git a/doc/README_CN.md b/doc/README_CN.md index ac688db..433aaec 100644 --- a/doc/README_CN.md +++ b/doc/README_CN.md @@ -3,6 +3,7 @@ [![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) +[![Gitter](https://badges.gitter.im/nosarthur/gita.svg)](https://gitter.im/nosarthur/gita?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![English](https://img.shields.io/badge/-English-lightgrey.svg)](https://github.com/nosarthur/gita) ``` @@ -21,7 +22,7 @@ 这个工具有两个作用: - 并排显示多个库的状态信息,比如分支名,编辑状态,提交信息等 -- 在任何目录下代理执行 git 指令 +- 在任何目录下(批处理)代理执行 git 指令 ![gita screenshot](https://github.com/nosarthur/gita/raw/master/doc/screenshot.png) @@ -69,6 +70,47 @@ 而且被代理的git指令不需要用户输入, 那么各个库的代理指令会被异步执行。 +## 安装指南 + +正常人类按装: + +``` +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`里点它。 + +## 超人模式 + +超人模式可以代理执行任何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'` + ## 私人定制 定制的代理子命令要放在`$XDG_CONFIG_HOME/gita/cmds.yml` (多半是`~/.config/gita/cmds.yml`)。 @@ -117,20 +159,6 @@ 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/) @@ -139,33 +167,6 @@ gita super [repo-name(s) or group-name(s)] <any-git-command-with-or-without-opti 暗地里老夫用`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`里点它。 - ## 有所作为 要想有所作为,你可以 @@ -174,10 +175,12 @@ Windows用户可能需要额外的设置来支持彩色的命令行, 见[这 - 建议/实现功能 - 加星/推荐本作 +聊天请入[![Join the chat at https://gitter.im/nosarthur/gita](https://badges.gitter.im/nosarthur/gita.svg)](https://gitter.im/nosarthur/gita?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + 在本地跑单元测试可以直接用`pytest`。更多的细节可见 [design.md](https://github.com/nosarthur/gita/blob/master/doc/design.md)。 -如果你愿意资助我,请访问[patreon](https://www.patreon.com/nosarthur). +如果你愿意资助我,请访问[GitHub Sponsors](https://github.com/sponsors/nosarthur)。 ## 他山之石 diff --git a/gita/__main__.py b/gita/__main__.py index ba0d270..6e47f8e 100644 --- a/gita/__main__.py +++ b/gita/__main__.py @@ -61,7 +61,6 @@ def f_ls(args: argparse.Namespace): def f_group(args: argparse.Namespace): - repos = utils.get_repos() groups = utils.get_groups() if args.to_group: gname = input('group name? ') @@ -74,7 +73,7 @@ def f_group(args: argparse.Namespace): utils.write_to_groups_file({gname: sorted(args.to_group)}, 'a+') else: for group, repos in groups.items(): - print(f"{group}: {', '.join(repos)}") + print(f"{group}: {' '.join(repos)}") def f_ungroup(args: argparse.Namespace): diff --git a/gita/common.py b/gita/common.py index 61df049..0a271fc 100644 --- a/gita/common.py +++ b/gita/common.py @@ -1,7 +1,8 @@ import os + def get_config_dir() -> str: parent = os.environ.get('XDG_CONFIG_HOME') or os.path.join( os.path.expanduser('~'), '.config') - root = os.path.join(parent,"gita") + root = os.path.join(parent, "gita") return root @@ -7,7 +7,7 @@ with open('README.md', encoding='utf-8') as f: setup( name='gita', packages=['gita'], - version='0.10.9', + version='0.10.10', license='MIT', description='Manage multiple git repos', long_description=long_description, diff --git a/tests/test_main.py b/tests/test_main.py index 1946352..ff28111 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -146,6 +146,17 @@ def test_ungroup(mock_write, _, __, input, expected): mock_write.assert_called_once_with(expected, 'w') +@patch('gita.utils.get_config_fname', return_value=GROUP_FNAME) +def test_group_display(_, capfd): + args = argparse.Namespace() + args.to_group = None + utils.get_groups.cache_clear() + __main__.f_group(args) + out, err = capfd.readouterr() + assert err == '' + assert 'xx: a b\nyy: a c d\n' == out + + @patch('gita.utils.is_git', return_value=True) @patch('gita.utils.get_config_fname', return_value=PATH_FNAME) @patch('gita.utils.rename_repo') |