From c67560864adcd43828a099afa9be7bf264623f0a Mon Sep 17 00:00:00 2001 From: nvbn Date: Mon, 20 Jul 2015 20:51:18 +0300 Subject: [PATCH] #295 Add `git_push_pull` rule --- README.md | 5 +-- tests/rules/test_git_push_pull.py | 54 +++++++++++++++++++++++++++++++ thefuck/rules/git_push_force.py | 3 ++ thefuck/rules/git_push_pull.py | 17 ++++++++++ 4 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 tests/rules/test_git_push_pull.py create mode 100644 thefuck/rules/git_push_pull.py diff --git a/README.md b/README.md index 5f7fb5b8..565f66b7 100644 --- a/README.md +++ b/README.md @@ -169,7 +169,7 @@ using the matched rule and runs it. Rules enabled by default are as follows: * `git_pull` – sets upstream before executing previous `git pull`; * `git_pull_clone` – clones instead of pulling when the repo does not exist; * `git_push` – adds `--set-upstream origin $branch` to previous failed `git push`; -* `git_push_force` – adds `--force` to a `git push`; +* `git_push_pull` – runs `git pull` when `push` was rejected; * `git_stash` – stashes you local modifications before rebasing or switching branch; * `go_run` – appends `.go` extension when compiling/running Go programs * `grep_recursive` – adds `-r` when you trying to grep directory; @@ -206,7 +206,8 @@ Enabled by default only on specific platforms: * `apt_get` – installs app from apt if it not installed; * `brew_install` – fixes formula name for `brew install`; * `brew_unknown_command` – fixes wrong brew commands, for example `brew docto/brew doctor`; -* `brew_upgrade` – appends `--all` to `brew upgrade` as per Homebrew's new behaviour +* `brew_upgrade` – appends `--all` to `brew upgrade` as per Homebrew's new behaviour; +* `git_push_force` – adds `--force` to a `git push` (may conflict with `git_push_pull`); * `pacman` – installs app with `pacman` or `yaourt` if it is not installed. Bundled, but not enabled by default: diff --git a/tests/rules/test_git_push_pull.py b/tests/rules/test_git_push_pull.py new file mode 100644 index 00000000..dedcfc79 --- /dev/null +++ b/tests/rules/test_git_push_pull.py @@ -0,0 +1,54 @@ +import pytest +from thefuck.rules.git_push_pull import match, get_new_command +from tests.utils import Command + + +git_err = ''' +To /tmp/foo + ! [rejected] master -> master (non-fast-forward) + error: failed to push some refs to '/tmp/bar' + hint: Updates were rejected because the tip of your current branch is behind + hint: its remote counterpart. Integrate the remote changes (e.g. + hint: 'git pull ...') before pushing again. + hint: See the 'Note about fast-forwards' in 'git push --help' for details. +''' + +git_uptodate = 'Everything up-to-date' +git_ok = ''' +Counting objects: 3, done. +Delta compression using up to 4 threads. +Compressing objects: 100% (2/2), done. +Writing objects: 100% (3/3), 282 bytes | 0 bytes/s, done. +Total 3 (delta 0), reused 0 (delta 0) +To /tmp/bar + 514eed3..f269c79 master -> master +''' + + +@pytest.mark.parametrize('command', [ + Command(script='git push', stderr=git_err), + Command(script='git push nvbn', stderr=git_err), + Command(script='git push nvbn master', stderr=git_err)]) +def test_match(command): + assert match(command, None) + + +@pytest.mark.parametrize('command', [ + Command(script='git push', stderr=git_ok), + Command(script='git push', stderr=git_uptodate), + Command(script='git push nvbn', stderr=git_ok), + Command(script='git push nvbn master', stderr=git_uptodate), + Command(script='git push nvbn', stderr=git_ok), + Command(script='git push nvbn master', stderr=git_uptodate)]) +def test_not_match(command): + assert not match(command, None) + + +@pytest.mark.parametrize('command, output', [ + (Command(script='git push', stderr=git_err), 'git pull && git push'), + (Command(script='git push nvbn', stderr=git_err), + 'git pull nvbn && git push nvbn'), + (Command(script='git push nvbn master', stderr=git_err), + 'git pull nvbn master && git push nvbn master')]) +def test_get_new_command(command, output): + assert get_new_command(command, None) == output diff --git a/thefuck/rules/git_push_force.py b/thefuck/rules/git_push_force.py index 53d2117d..46238172 100644 --- a/thefuck/rules/git_push_force.py +++ b/thefuck/rules/git_push_force.py @@ -13,3 +13,6 @@ def match(command, settings): @utils.git_support def get_new_command(command, settings): return command.script.replace('push', 'push --force') + + +enabled_by_default = False diff --git a/thefuck/rules/git_push_pull.py b/thefuck/rules/git_push_pull.py new file mode 100644 index 00000000..2958a2c4 --- /dev/null +++ b/thefuck/rules/git_push_pull.py @@ -0,0 +1,17 @@ +from thefuck import utils +from thefuck.shells import and_ + + +@utils.git_support +def match(command, settings): + return ('git' in command.script + and 'push' in command.script + and '! [rejected]' in command.stderr + and 'failed to push some refs to' in command.stderr + and 'Updates were rejected because the tip of your current branch is behind' in command.stderr) + + +@utils.git_support +def get_new_command(command, settings): + return and_(command.script.replace('push', 'pull'), + command.script)