From e39f8d0f3379bf17d8333a0fc4553dfdc244cf5c Mon Sep 17 00:00:00 2001 From: Matars Date: Wed, 11 Feb 2026 02:46:08 +0100 Subject: [PATCH 1/2] DEBUG=1 --- src/gitfetch/cli.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/gitfetch/cli.py b/src/gitfetch/cli.py index dc6480e..088dfe5 100644 --- a/src/gitfetch/cli.py +++ b/src/gitfetch/cli.py @@ -3,6 +3,7 @@ """ import argparse +import os import sys import subprocess from typing import Optional @@ -45,6 +46,19 @@ def _background_refresh_cache_subprocess(username: str) -> None: pass +def _debug_enabled() -> bool: + """Return True when debug mode is enabled via env var.""" + value = os.environ.get('DEBUG') + if value is None: + # Backward compatibility with older env var name. + value = os.environ.get('GITFETCH_DEBUG') + + if value is None: + return False + + return value.strip().lower() not in {'', '0', 'false', 'no', 'off'} + + def parse_args() -> argparse.Namespace: """Parse command-line arguments.""" parser = argparse.ArgumentParser( @@ -464,9 +478,8 @@ def main() -> int: # (useful when users report errors from package builds / other # environments where the short error message is not enough). try: - import os import traceback - if os.environ.get('GITFETCH_DEBUG'): + if _debug_enabled(): traceback.print_exc() else: print(f"Error: {e}", file=sys.stderr) From 91834da494ab0640b5d970c59f2cf0220821906a Mon Sep 17 00:00:00 2001 From: Matars Date: Wed, 11 Feb 2026 02:47:00 +0100 Subject: [PATCH 2/2] fall back for cont graph --- src/gitfetch/fetcher.py | 85 +++++++++++++++++++++++++++-------------- 1 file changed, 56 insertions(+), 29 deletions(-) diff --git a/src/gitfetch/fetcher.py b/src/gitfetch/fetcher.py index cf36e32..c86e972 100644 --- a/src/gitfetch/fetcher.py +++ b/src/gitfetch/fetcher.py @@ -542,42 +542,69 @@ def _fetch_contribution_graph(self, username: str) -> list: Returns: List of weeks with contribution data """ - # GraphQL query for contribution calendar (inline username) - query = f'''{{ - user(login: "{username}") {{ - contributionsCollection(includePrivate: true) {{ - contributionCalendar {{ - weeks {{ - contributionDays {{ - contributionCount - date + queries = [ + # Preferred query: include private contributions when available. + f'''{{ + user(login: "{username}") {{ + contributionsCollection(includePrivate: true) {{ + contributionCalendar {{ + weeks {{ + contributionDays {{ + contributionCount + date + }} + }} }} }} }} - }} - }} - }}''' + }}''', + # Fallback query for auth/scope combinations where includePrivate + # can fail. + f'''{{ + user(login: "{username}") {{ + contributionsCollection {{ + contributionCalendar {{ + weeks {{ + contributionDays {{ + contributionCount + date + }} + }} + }} + }} + }} + }}''', + ] + + for query in queries: + try: + result = subprocess.run( + ['gh', 'api', 'graphql', '-f', f'query={query}'], + capture_output=True, + text=True, + timeout=30, + env=self._build_env() + ) - try: - result = subprocess.run( - ['gh', 'api', 'graphql', '-f', f'query={query}'], - capture_output=True, - text=True, - timeout=30, - env=self._build_env() - ) + if result.returncode != 0: + continue - if result.returncode != 0: - return [] + data = json.loads(result.stdout) + weeks = data.get('data', {}).get('user', {}).get( + 'contributionsCollection', {}).get( + 'contributionCalendar', {}).get('weeks', None) - data = json.loads(result.stdout) - weeks = data.get('data', {}).get('user', {}).get( - 'contributionsCollection', {}).get( - 'contributionCalendar', {}).get('weeks', []) - return weeks + if isinstance(weeks, list): + if data.get('errors'): + if weeks: + return weeks + continue + return weeks - except (subprocess.TimeoutExpired, json.JSONDecodeError, KeyError): - return [] + except (subprocess.TimeoutExpired, json.JSONDecodeError, KeyError): + continue + + return [] class GitLabFetcher(BaseFetcher):