diff --git a/src/gimmegit/_cli.py b/src/gimmegit/_cli.py index b1a2059..c2fc3ed 100644 --- a/src/gimmegit/_cli.py +++ b/src/gimmegit/_cli.py @@ -459,8 +459,10 @@ def get_default_branch(cloned: git.Repo) -> str: def get_github_login() -> str: api = github.Github(GITHUB_TOKEN) - user = api.get_user() - return user.login + try: + return api.get_user().login # If this raises, it will be 'login' that raises. + except github.BadCredentialsException: + raise ValueError("GitHub rejected the token. Has the token expired?") def get_github_upstream(owner: str, project: str) -> _remote.Remote | None: @@ -469,6 +471,8 @@ def get_github_upstream(owner: str, project: str) -> _remote.Remote | None: api = github.Github(GITHUB_TOKEN) try: repo = api.get_repo(f"{owner}/{project}") + except github.BadCredentialsException: + raise ValueError("GitHub rejected the token. Has the token expired?") except github.UnknownObjectException: raise ValueError( f"Unable to find '{owner}/{project}' on GitHub. Do you have access to the repo?" diff --git a/tests/functional/helpers_functional.py b/tests/functional/helpers_functional.py index 258f1a8..b105015 100644 --- a/tests/functional/helpers_functional.py +++ b/tests/functional/helpers_functional.py @@ -31,6 +31,13 @@ def token_env() -> dict[str, str]: return env +def bad_token_env() -> dict[str, str]: + env = os.environ.copy() + env["GIMMEGIT_FORCE_STDOUT"] = "1" + env["GIMMEGIT_GITHUB_TOKEN"] = "invalid-token" + return env + + def get_branch(dir: Path) -> str: result = subprocess.run( ["git", "branch", "--show-current"], diff --git a/tests/functional/test_token.py b/tests/functional/test_token.py index 04aa8f9..af75942 100644 --- a/tests/functional/test_token.py +++ b/tests/functional/test_token.py @@ -69,6 +69,60 @@ def test_invalid_repo_token(uv_run, test_dir): assert not (test_dir / "invalid").exists() +def test_bad_token_no_owner(uv_run, test_dir): + command = [ + *uv_run, + "gimmegit", + *helpers.no_ssh, + "jubilant", + ] + result = subprocess.run( + command, + cwd=test_dir, + env=helpers.bad_token_env(), + capture_output=True, + text=True, + check=False, + ) + assert result.returncode == 1 + expected_stdout = """\ +Getting repo details +""" + assert result.stdout == expected_stdout + expected_stderr = """\ +Error: GitHub rejected the token. Has the token expired? +""" + assert result.stderr == expected_stderr + assert not (test_dir / "jubilant").exists() + + +def test_bad_token_no_upstream_owner(uv_run, test_dir): + command = [ + *uv_run, + "gimmegit", + *helpers.no_ssh, + "dwilding/jubilant", + ] + result = subprocess.run( + command, + cwd=test_dir, + env=helpers.bad_token_env(), + capture_output=True, + text=True, + check=False, + ) + assert result.returncode == 1 + expected_stdout = """\ +Getting repo details +""" + assert result.stdout == expected_stdout + expected_stderr = """\ +Error: GitHub rejected the token. Has the token expired? +""" + assert result.stderr == expected_stderr + assert not (test_dir / "jubilant").exists() + + @pytest.mark.skipif(helpers.no_token.condition, reason=helpers.no_token.reason) def test_u_sets_upstream_owner(uv_run, test_dir): command = [