Skip to content

Commit

Permalink
Issue #597: Handle Temporary Redirect when a repository or organizati…
Browse files Browse the repository at this point in the history
…on name was changed (#604)
  • Loading branch information
amalota authored Aug 17, 2022
1 parent b7be54a commit b4985ab
Showing 1 changed file with 32 additions and 3 deletions.
35 changes: 32 additions & 3 deletions git_machete/github.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import urllib.request
import urllib.error

from git_machete.utils import debug, fmt
from git_machete.utils import debug, fmt, warn
from git_machete.exceptions import MacheteException, UnprocessableEntityHTTPError
from git_machete.git_operations import GitContext, LocalBranchShortName

Expand Down Expand Up @@ -196,7 +196,7 @@ def __fire_github_api_request(method: str, path: str, token: Optional[str], requ
error_reason: str = __extract_failure_info_from_422(error_response)
raise UnprocessableEntityHTTPError(error_reason)
elif err.code in (http.HTTPStatus.UNAUTHORIZED, http.HTTPStatus.FORBIDDEN):
first_line = f'GitHub API returned {err.code} HTTP status with error message: `{err.reason}`\n'
first_line = f'GitHub API returned `{err.code}` HTTP status with error message: `{err.reason}`\n'
if token:
raise MacheteException(first_line + f'Make sure that the GitHub API token provided by the {__get_github_token_provider()} '
f'is valid and allows for access to `{method.upper()}` `https://{host}{path}`.\n'
Expand All @@ -214,8 +214,31 @@ def __fire_github_api_request(method: str, path: str, token: Optional[str], requ
f'`{method} {url}` request ended up in 404 response from GitHub. A valid GitHub API token is required.\n'
f'Provide a GitHub API token with `repo` access via one of the: {get_github_token_possible_providers()} '
'Visit `https://github.com/settings/tokens` to generate a new one.') # TODO (#164): make dedicated exception here
elif err.code == http.HTTPStatus.TEMPORARY_REDIRECT:
if err.headers['Location'] is not None:
if len(err.headers['Location'].split('/')) >= 5:
current_repo_and_org = get_repo_and_org_names_by_id(err.headers['Location'].split('/')[4])
else:
first_line = fmt(f'GitHub API returned `{err.code}` HTTP status with error message: `{err.reason}`\n')
raise MacheteException(
first_line + 'It looks like the organization or repository name got changed recently and is outdated.\n'
'Inferring current organization or repository... -> Cannot infer current organization or repository\n'
'Update your remote repository manually via: `git remote set-url <remote_name> <new_repository_url>`.')
# err.headers is a case-insensitive dict of class Message with the `__getitem__` and `get` functions implemented in
# https://github.com/python/cpython/blob/3.10/Lib/email/message.py
pulls_or_issues_api_suffix = "/".join(path.split("/")[4:])
new_path = f'/repos/{current_repo_and_org}/{pulls_or_issues_api_suffix}'
# for example when creating a new PR, new_path='/repos/new_org_name/new_repo_name/pulls'
warn(f'GitHub API returned `{err.code}` HTTP status with error message: `{err.reason}`. \n'
'It looks like the organization or repository name got changed recently and is outdated.\n'
'Inferring current organization or repository... '
f'New organization = `{current_repo_and_org.split("/")[0]}`, '
f'new repository = `{current_repo_and_org.split("/")[1]}`.\n'
'You can update your remote repository via: `git remote set-url <remote_name> <new_repository_url>`.',
end='')
return __fire_github_api_request(method=method, path=new_path, token=token, request_body=request_body)
else:
first_line = fmt(f'GitHub API returned {err.code} HTTP status with error message: `{err.reason}`\n')
first_line = fmt(f'GitHub API returned `{err.code}` HTTP status with error message: `{err.reason}`\n')
raise MacheteException(
first_line + "Please open an issue regarding this topic under link: https://github.com/VirtusLab/git-machete/issues/new")
except OSError as e:
Expand Down Expand Up @@ -316,6 +339,12 @@ def checkout_pr_refs(git: GitContext, remote: str, pr_number: int, branch: Local
git.checkout(branch)


def get_repo_and_org_names_by_id(repo_id: str) -> str:
token: Optional[str] = __get_github_token()
repo = __fire_github_api_request('GET', f'/repositories/{repo_id}', token)
return str(repo['full_name'])


def get_github_token_possible_providers() -> str:
return (f'\n\t1. `{GITHUB_TOKEN_ENV_VAR}` environment variable.\n'
'\t2. Content of the `~/.github-token` file.\n'
Expand Down

0 comments on commit b4985ab

Please sign in to comment.