# Path: gg/main.py
# class Config:
#     def __init__(self):
#         self.verbose = False  # default
#         self.configfile = DEFAULT_CONFIGFILE
#         try:
#             self.repo = get_repo()
#         except git.InvalidGitRepositoryError as exception:
#             error_out(f"{exception.args[0]} is not a git repository")
# 
# Path: gg/builtins/push/gg_push.py
# @cli.command()
# @click.option("-f", "--force", is_flag=True, default=False)
# @pass_config
# def push(config, force=False):
#     """Create push the current branch."""
#     repo = config.repo
# 
#     state = read(config.configfile)
#     default_branch = state.get("DEFAULT_BRANCH", "master")
# 
#     active_branch = repo.active_branch
#     if active_branch.name == default_branch:
#         error_out(
#             f"Can't commit when on the {default_branch} branch. "
#             "You really ought to do work in branches."
#         )
# 
#     if not state.get("FORK_NAME"):
#         info_out("Can't help you push the commit. Please run: gg config --help")
#         return 0
# 
#     try:
#         push_to_origin = load_config(config.configfile, "push_to_origin")
#     except KeyError:
#         push_to_origin = False
# 
#         try:
#             repo.remotes[state["FORK_NAME"]]
#         except IndexError:
#             error_out("There is no remote called '{}'".format(state["FORK_NAME"]))
# 
#     origin_name = state.get("ORIGIN_NAME", "origin")
#     destination = repo.remotes[origin_name if push_to_origin else state["FORK_NAME"]]
#     if force:
#         (pushed,) = destination.push(force=True)
#         info_out(pushed.summary)
#     else:
#         (pushed,) = destination.push()
#         # print("PUSHED...")
#     # for enum_name in [
#     #     "DELETED",
#     #     "ERROR",
#     #     "FAST_FORWARD",
#     #     "NEW_HEAD",
#     #     "NEW_TAG",
#     #     "NO_MATCH",
#     #     "REMOTE_FAILURE",
#     # ]:
#     #     print(
#     #         f"{enum_name}?:", pushed.flags & getattr(git.remote.PushInfo, enum_name)
#     #     )
# 
#     if pushed.flags & git.remote.PushInfo.FORCED_UPDATE:
#         success_out(f"Successfully force pushed to {destination}")
#     elif (
#         pushed.flags & git.remote.PushInfo.REJECTED
#         or pushed.flags & git.remote.PushInfo.REMOTE_REJECTED
#     ):
#         error_out('The push was rejected ("{}")'.format(pushed.summary), False)
# 
#         try_force_push = input("Try to force push? [Y/n] ").lower().strip()
#         if try_force_push not in ("no", "n"):
#             (pushed,) = destination.push(force=True)
#             info_out(pushed.summary)
#         else:
#             return 0
#     elif pushed.flags & git.remote.PushInfo.UP_TO_DATE:
#         info_out(f"{destination} already up-to-date")
#     else:
#         success_out(f"Successfully pushed to {destination}")
# 
#     return 0


import json
import os
import tempfile
import shutil
import pytest
import requests_mock
from git.remote import PushInfo
from click.testing import CliRunner
from gg.main import Config
from gg.builtins.push.gg_push import push
def temp_configfile():
    tmp_dir = tempfile.mkdtemp("gg-start")
    fp = os.path.join(tmp_dir, "state.json")
    with open(fp, "w") as f:
        json.dump({}, f)
    yield fp
    shutil.rmtree(tmp_dir)


def test_push(temp_configfile, mocker):
    mocked_git = mocker.patch("git.Repo")
    mocked_git().working_dir = "gg-start-test"
    mocked_git().remotes.__getitem__().push.return_value = [
        PushInfo(0, "All is well", None, None, "origin")
    ]

    state = json.load(open(temp_configfile))
    state["FORK_NAME"] = "peterbe"
    with open(temp_configfile, "w") as f:
        json.dump(state, f)

    runner = CliRunner()
    config = Config()
    config.configfile = temp_configfile
    result = runner.invoke(push, [], obj=config)
    if result.exception:
        raise result.exception
    assert result.exit_code == 0
    assert not result.exception


# Path: gg/main.py
# class Config:
#     def __init__(self):
#         self.verbose = False  # default
#         self.configfile = DEFAULT_CONFIGFILE
#         try:
#             self.repo = get_repo()
#         except git.InvalidGitRepositoryError as exception:
#             error_out(f"{exception.args[0]} is not a git repository")
# 
# Path: gg/builtins/push/gg_push.py
# @cli.command()
# @click.option("-f", "--force", is_flag=True, default=False)
# @pass_config
# def push(config, force=False):
#     """Create push the current branch."""
#     repo = config.repo
# 
#     state = read(config.configfile)
#     default_branch = state.get("DEFAULT_BRANCH", "master")
# 
#     active_branch = repo.active_branch
#     if active_branch.name == default_branch:
#         error_out(
#             f"Can't commit when on the {default_branch} branch. "
#             "You really ought to do work in branches."
#         )
# 
#     if not state.get("FORK_NAME"):
#         info_out("Can't help you push the commit. Please run: gg config --help")
#         return 0
# 
#     try:
#         push_to_origin = load_config(config.configfile, "push_to_origin")
#     except KeyError:
#         push_to_origin = False
# 
#         try:
#             repo.remotes[state["FORK_NAME"]]
#         except IndexError:
#             error_out("There is no remote called '{}'".format(state["FORK_NAME"]))
# 
#     origin_name = state.get("ORIGIN_NAME", "origin")
#     destination = repo.remotes[origin_name if push_to_origin else state["FORK_NAME"]]
#     if force:
#         (pushed,) = destination.push(force=True)
#         info_out(pushed.summary)
#     else:
#         (pushed,) = destination.push()
#         # print("PUSHED...")
#     # for enum_name in [
#     #     "DELETED",
#     #     "ERROR",
#     #     "FAST_FORWARD",
#     #     "NEW_HEAD",
#     #     "NEW_TAG",
#     #     "NO_MATCH",
#     #     "REMOTE_FAILURE",
#     # ]:
#     #     print(
#     #         f"{enum_name}?:", pushed.flags & getattr(git.remote.PushInfo, enum_name)
#     #     )
# 
#     if pushed.flags & git.remote.PushInfo.FORCED_UPDATE:
#         success_out(f"Successfully force pushed to {destination}")
#     elif (
#         pushed.flags & git.remote.PushInfo.REJECTED
#         or pushed.flags & git.remote.PushInfo.REMOTE_REJECTED
#     ):
#         error_out('The push was rejected ("{}")'.format(pushed.summary), False)
# 
#         try_force_push = input("Try to force push? [Y/n] ").lower().strip()
#         if try_force_push not in ("no", "n"):
#             (pushed,) = destination.push(force=True)
#             info_out(pushed.summary)
#         else:
#             return 0
#     elif pushed.flags & git.remote.PushInfo.UP_TO_DATE:
#         info_out(f"{destination} already up-to-date")
#     else:
#         success_out(f"Successfully pushed to {destination}")
# 
#     return 0


# Path: gg/builtins/push/tests/test_gg_push.py
import json
import os
import tempfile
import shutil
import pytest
import requests_mock
from git.remote import PushInfo
from click.testing import CliRunner
from gg.main import Config
from gg.builtins.push.gg_push import push

def temp_configfile():
    tmp_dir = tempfile.mkdtemp("gg-start")
    fp = os.path.join(tmp_dir, "state.json")
    with open(fp, "w") as f:
        json.dump({}, f)
    yield fp
    shutil.rmtree(tmp_dir)


def test_push(temp_configfile, mocker):
    mocked_git = mocker.patch("git.Repo")
    mocked_git().working_dir = "gg-start-test"
    mocked_git().remotes.__getitem__().push.return_value = [
        PushInfo(0, "All is well", None, None, "origin")
    ]

    state = json.load(open(temp_configfile))
    state["FORK_NAME"] = "peterbe"
    with open(temp_configfile, "w") as f:
        json.dump(state, f)

    runner = CliRunner()
    config = Config()
    config.configfile = temp_configfile
    result = runner.invoke(push, [], obj=config)
    if result.exception:
        raise result.exception
    assert result.exit_code == 0
    assert not result.exception


    mocked_git().remotes.__getitem__().push.assert_called_with()