Skip to content
This repository was archived by the owner on Apr 13, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 35 additions & 11 deletions src/git_portfolio/__main__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
"""Command-line interface."""
import sys
from typing import Tuple

import click

import git_portfolio.config_manager as cm
import git_portfolio.github_manager as ghm
import git_portfolio.local_manager as lm
import git_portfolio.portfolio_manager as pm


try:
CONFIG_MANAGER = cm.ConfigManager()
except TypeError as type_error:
click.secho(
f"Error: {type_error}", fg="red", err=True,
)
sys.exit()


@click.group("cli")
Expand All @@ -19,9 +29,7 @@ def main() -> None:
def checkout(args: Tuple[str]) -> None:
"""CLI `git checkout BRANCH` command."""
# TODO add -b option
config_manager = cm.ConfigManager()
configs = config_manager.load_configs()
if not configs.github_selected_repos:
if not CONFIG_MANAGER.config.github_selected_repos:
click.secho(
"Error: no repos selected. Please run `gitp config init`.", fg="red",
)
Expand All @@ -34,7 +42,11 @@ def checkout(args: Tuple[str]) -> None:
fg="red",
)
else:
click.secho(lm.LocalManager().checkout(configs.github_selected_repos, args))
click.secho(
lm.LocalManager().checkout(
CONFIG_MANAGER.config.github_selected_repos, args
)
)


@click.group("config")
Expand Down Expand Up @@ -68,40 +80,52 @@ def delete() -> None:
pass


def _save_config(config: cm.Config) -> None:
"""Save config with ConfigManager."""
CONFIG_MANAGER.config = config
CONFIG_MANAGER.save_config()
click.secho("gitp successfully configured.", fg="blue")


@configure.command("init")
def config_init() -> None:
"""Config init command."""
pm.PortfolioManager()
github_manager = ghm.GithubManager(CONFIG_MANAGER.config)
_save_config(github_manager.config)


@configure.command("repos")
def config_repos() -> None:
"""Config repos command."""
pm.PortfolioManager().config_repos()
config = ghm.GithubManager(CONFIG_MANAGER.config).config_repos()
if config:
_save_config(config)
else:
click.secho("Error: no config found, please run `gitp config init`.", fg="red")


@create.command("issues")
def create_issues() -> None:
"""Create issues command."""
pm.PortfolioManager().create_issues()
ghm.GithubManager(CONFIG_MANAGER.config).create_issues()


@create.command("prs")
def create_prs() -> None:
"""Create prs command."""
pm.PortfolioManager().create_pull_requests()
ghm.GithubManager(CONFIG_MANAGER.config).create_pull_requests()


@merge.command("prs")
def merge_prs() -> None:
"""Merge prs command."""
pm.PortfolioManager().merge_pull_requests()
ghm.GithubManager(CONFIG_MANAGER.config).merge_pull_requests()


@delete.command("branches")
def delete_branches() -> None:
"""Delete branches command."""
pm.PortfolioManager().delete_branches()
ghm.GithubManager(CONFIG_MANAGER.config).delete_branches()


main.add_command(configure)
Expand Down
54 changes: 33 additions & 21 deletions src/git_portfolio/config_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,37 @@ def __init__(
class ConfigManager:
"""Configuration manager class."""

CONFIG_FOLDER = os.path.join(os.path.expanduser("~"), ".gitp")
CONFIG_FILE = "config.yaml"

def load_configs(self) -> Config:
"""Get configs if it exists."""
if os.path.exists(os.path.join(self.CONFIG_FOLDER, self.CONFIG_FILE)):
print("Loading previous configs\n")
with open(
os.path.join(self.CONFIG_FOLDER, self.CONFIG_FILE)
) as config_file:
data = yaml.safe_load(config_file)
return Config(**data)
return Config("", "", [])

def save_configs(self, configs: Config) -> None:
def __init__(self, config_filename: str = "config.yaml") -> None:
"""Load config if it exists."""
self.config_folder = os.path.join(os.path.expanduser("~"), ".gitp")
self.config_path = os.path.join(self.config_folder, config_filename)

if os.path.exists(self.config_path):
print("Loading previous config...\n")
with open(self.config_path) as config_file:
try:
data = yaml.safe_load(config_file)
except yaml.scanner.ScannerError:
raise TypeError("Invalid YAML file.")
if data:
try:
self.config = Config(**data)
return
except TypeError:
raise TypeError("Invalid config file.")
self.config = Config("", "", [])

def _config_is_empty(self) -> bool:
if self.config.github_selected_repos and self.config.github_access_token:
return False
return True

def save_config(self) -> None:
"""Write config to YAML file."""
pathlib.Path(self.CONFIG_FOLDER).mkdir(parents=True, exist_ok=True)
configs_dict = vars(configs)
with open(
os.path.join(self.CONFIG_FOLDER, self.CONFIG_FILE), "w"
) as config_file:
yaml.dump(configs_dict, config_file)
if not self._config_is_empty():
pathlib.Path(self.config_folder).mkdir(parents=True, exist_ok=True)
config_dict = vars(self.config)
with open(self.config_path, "w") as config_file:
yaml.dump(config_dict, config_file)
else:
raise AttributeError
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import github
import requests

import git_portfolio.config_manager as config_manager
import git_portfolio.config_manager as cm
import git_portfolio.prompt as prompt

# starting log
Expand All @@ -20,15 +20,14 @@
LOGGER = logging.getLogger(__name__)


class PortfolioManager:
"""Portfolio manager class."""
class GithubManager:
"""Github manager class."""

def __init__(self) -> None:
def __init__(self, config: cm.Config) -> None:
"""Constructor."""
self.config_manager = config_manager.ConfigManager()
self.configs = self.config_manager.load_configs()
if self.configs.github_access_token:
self.github_setup()
self.config = config
if config.github_access_token:
self._github_setup()
else:
self.config_ini()

Expand All @@ -37,15 +36,15 @@ def create_issues(
) -> None:
"""Create issues."""
if not issue:
issue = prompt.create_issues(self.configs.github_selected_repos)
issue = prompt.create_issues(self.config.github_selected_repos)
labels = (
[label.strip() for label in issue.labels.split(",")] if issue.labels else []
)

if github_repo:
self._create_issue_from_repo(github_repo, issue, labels)
else:
for github_repo in self.configs.github_selected_repos:
for github_repo in self.config.github_selected_repos:
self._create_issue_from_repo(github_repo, issue, labels)

def _create_issue_from_repo(
Expand All @@ -72,12 +71,12 @@ def create_pull_requests(
) -> None:
"""Create pull requests."""
if not pr:
pr = prompt.create_pull_requests(self.configs.github_selected_repos)
pr = prompt.create_pull_requests(self.config.github_selected_repos)

if github_repo:
self._create_pull_request_from_repo(github_repo, pr)
else:
for github_repo in self.configs.github_selected_repos:
for github_repo in self.config.github_selected_repos:
self._create_pull_request_from_repo(github_repo, pr)

def _create_pull_request_from_repo(self, github_repo: str, pr: Any) -> None:
Expand Down Expand Up @@ -127,7 +126,7 @@ def merge_pull_requests(
"""Merge pull requests."""
if not pr_merge:
pr_merge = prompt.merge_pull_requests(
self.github_username, self.configs.github_selected_repos
self.github_username, self.config.github_selected_repos
)
# Important note: base and head arguments have different import formats.
# https://developer.github.com/v3/pulls/#list-pull-requests
Expand All @@ -138,7 +137,7 @@ def merge_pull_requests(
if github_repo:
self._merge_pull_request_from_repo(github_repo, head, pr_merge, state)
else:
for github_repo in self.configs.github_selected_repos:
for github_repo in self.config.github_selected_repos:
self._merge_pull_request_from_repo(github_repo, head, pr_merge, state)

def _merge_pull_request_from_repo(
Expand Down Expand Up @@ -175,12 +174,12 @@ def _merge_pull_request_from_repo(
def delete_branches(self, branch: str = "", github_repo: str = "") -> None:
"""Delete branches."""
if not branch:
branch = prompt.delete_branches(self.configs.github_selected_repos)
branch = prompt.delete_branches(self.config.github_selected_repos)

if github_repo:
self._delete_branch_from_repo(github_repo, branch)
else:
for github_repo in self.configs.github_selected_repos:
for github_repo in self.config.github_selected_repos:
self._delete_branch_from_repo(github_repo, branch)

def _delete_branch_from_repo(self, github_repo: str, branch: str) -> None:
Expand All @@ -196,13 +195,13 @@ def _delete_branch_from_repo(self, github_repo: str, branch: str) -> None:
def get_github_connection(self) -> github.Github:
"""Get Github connection."""
# GitHub Enterprise
if self.configs.github_hostname:
base_url = f"https://{self.configs.github_hostname}/api/v3"
if self.config.github_hostname:
base_url = f"https://{self.config.github_hostname}/api/v3"
return github.Github(
base_url=base_url, login_or_token=self.configs.github_access_token
base_url=base_url, login_or_token=self.config.github_access_token
)
# GitHub.com
return github.Github(self.configs.github_access_token)
return github.Github(self.config.github_access_token)

def get_github_username(
self,
Expand All @@ -216,9 +215,14 @@ def get_github_username(
except (github.BadCredentialsException, github.GithubException):
return ""
except requests.exceptions.ConnectionError:
sys.exit("Unable to reach server. Please check you network.")
sys.exit(
(
"Unable to reach server. Please check you network and credentials "
"and try again."
)
)

def get_github_repos(
def _get_github_repos(
self,
user: Union[
github.AuthenticatedUser.AuthenticatedUser, github.NamedUser.NamedUser
Expand All @@ -227,42 +231,36 @@ def get_github_repos(
"""Get Github repos from user."""
return user.get_repos()

def config_repos(self) -> None:
def config_ini(self) -> None:
"""Initialize app configuration."""
# only config if gets a valid connection
valid = False
while not valid:
answers = prompt.connect_github(self.config.github_access_token)
self.config.github_access_token = answers.github_access_token.strip()
self.config.github_hostname = answers.github_hostname
valid = self._github_setup()
if not valid:
print("Wrong GitHub token/permissions. Please try again.")
self.config_repos()

def config_repos(self) -> Optional[cm.Config]:
"""Configure repos in use."""
if self.configs.github_selected_repos:
print("\nThe configured repos will be used:")
for repo in self.configs.github_selected_repos:
print(" *", repo)
new_repos = prompt.new_repos()
if self.config.github_selected_repos:
new_repos = prompt.new_repos(self.config.github_selected_repos)
if not new_repos:
print("gitp successfully configured.")
return
return None

repo_names = [repo.full_name for repo in self.github_repos]
self.config.github_selected_repos = prompt.select_repos(repo_names)
return self.config

self.configs.github_selected_repos = prompt.select_repos(repo_names)
self.config_manager.save_configs(self.configs)
print("gitp successfully configured.")

def github_setup(self) -> bool:
def _github_setup(self) -> bool:
"""Setup Github connection properties."""
self.github_connection = self.get_github_connection()
user = self.github_connection.get_user()
self.github_username = self.get_github_username(user)
if not self.github_username:
return False
self.github_repos = self.get_github_repos(user)
self.github_repos = self._get_github_repos(user)
return True

def config_ini(self) -> None:
"""Initialize app configuration."""
# only config if gets a valid connection
valid = False
while not valid:
answers = prompt.connect_github(self.configs.github_access_token)
self.configs.github_access_token = answers.github_access_token.strip()
self.configs.github_hostname = answers.github_hostname
valid = self.github_setup()
if not valid:
print("Wrong GitHub token/permissions. Please try again.")
self.config_repos()
10 changes: 6 additions & 4 deletions src/git_portfolio/prompt.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,11 +233,13 @@ def connect_github(github_access_token: str) -> ConnectGithub:
return ConnectGithub(answers["github_access_token"], answers["github_hostname"])


def new_repos() -> Any:
def new_repos(github_selected_repos: List[str]) -> Any:
"""Prompt question to know if you want to select new repositories."""
answer = inquirer.prompt(
[inquirer.Confirm("", message="Do you want to select new repositories?")]
)[""]
message = "\nThe configured repos will be used:"
for repo in github_selected_repos:
message += f" * {repo}\n"
message += "Do you want to select new repositories?"
answer = inquirer.prompt([inquirer.Confirm("", message=message)])[""]
return answer


Expand Down
Loading