From 94e323ab4084e77b172e35d8473960fcc9cf11a8 Mon Sep 17 00:00:00 2001 From: zeviraty Date: Sat, 13 Dec 2025 18:26:24 +0100 Subject: [PATCH 1/9] fixed possible crash when metadata not installed --- src/gitfetch/__init__.py | 2 +- src/gitfetch/config.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/gitfetch/__init__.py b/src/gitfetch/__init__.py index 46813cb..6713085 100644 --- a/src/gitfetch/__init__.py +++ b/src/gitfetch/__init__.py @@ -12,7 +12,7 @@ def _get_version() -> str: # Try to get version from package metadata from importlib import metadata return metadata.version("gitfetch") - except (ImportError, metadata.PackageNotFoundError): + except (ImportError): pass # Fallback: try to read from pyproject.toml (works in development) diff --git a/src/gitfetch/config.py b/src/gitfetch/config.py index 6c67b4f..4ea1624 100644 --- a/src/gitfetch/config.py +++ b/src/gitfetch/config.py @@ -76,7 +76,8 @@ def _load_config(self) -> None: # Create default config self.config['DEFAULT'] = { 'username': '', - 'cache_expiry_minutes': '15' + 'cache_expiry_minutes': '15', + 'api_key': '', } self.config.add_section('COLORS') for key, value in default_colors.items(): From e98af113750bcfafde553ff3b768a11ec593a762 Mon Sep 17 00:00:00 2001 From: zeviraty Date: Sat, 13 Dec 2025 18:30:40 +0100 Subject: [PATCH 2/9] Fixed dependencies in pyproject.toml --- pyproject.toml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 829abd6..72ada67 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,8 +27,10 @@ classifiers = [ ] dependencies = [ - "requests>=2.0.0", - "readchar>=4.0.0" + "requests>=2.0.0", + "readchar>=4.0.0", + "pytest>=7.0.0", + "webcolors>=24.11.1", ] [project.optional-dependencies] From e7a4abc1cded346ba884e96ce30a5795c0a81577 Mon Sep 17 00:00:00 2001 From: zeviraty Date: Sat, 13 Dec 2025 18:31:24 +0100 Subject: [PATCH 3/9] removed unneeded pytest requirement --- pyproject.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 72ada67..4a6597a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,7 +29,6 @@ classifiers = [ dependencies = [ "requests>=2.0.0", "readchar>=4.0.0", - "pytest>=7.0.0", "webcolors>=24.11.1", ] From f541150a7e67f6e083be531a1bdd1b554266e516 Mon Sep 17 00:00:00 2001 From: zeviraty Date: Sat, 13 Dec 2025 18:43:10 +0100 Subject: [PATCH 4/9] Added personal access token for github and fixed issue with input arguments --- src/gitfetch/cli.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/gitfetch/cli.py b/src/gitfetch/cli.py index f271c41..eef85bc 100644 --- a/src/gitfetch/cli.py +++ b/src/gitfetch/cli.py @@ -534,7 +534,7 @@ def _create_fetcher(provider: str, base_url: str, token: Optional[str] = None): def _initialize_gitfetch(config_manager: ConfigManager) -> bool: """ Initialize gitfetch by creating config directory and setting - the authenticated user as default. + multiple configuration options. Args: config_manager: ConfigManager instance @@ -566,9 +566,10 @@ def _initialize_gitfetch(config_manager: ConfigManager) -> bool: # Ask for token if needed token = None - if provider in ['gitlab', 'gitea', 'sourcehut']: + if provider in ['gitlab', 'gitea', 'sourcehut', 'github']: token_input = input( - f"Enter your {provider} personal access token " + f"Enter your {provider} personal access token{', needed for private repositories' if provider == 'github' else ''}\n" + + "(optional, press Enter to skip): " ).strip() if token_input: From ae7df797d701f65da2e5a1577abb4fb836ba812e Mon Sep 17 00:00:00 2001 From: zeviraty Date: Sat, 13 Dec 2025 18:45:13 +0100 Subject: [PATCH 5/9] renamed api key -> token --- src/gitfetch/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gitfetch/config.py b/src/gitfetch/config.py index 4ea1624..f01b069 100644 --- a/src/gitfetch/config.py +++ b/src/gitfetch/config.py @@ -77,7 +77,7 @@ def _load_config(self) -> None: self.config['DEFAULT'] = { 'username': '', 'cache_expiry_minutes': '15', - 'api_key': '', + 'token': '', } self.config.add_section('COLORS') for key, value in default_colors.items(): From f28a7f93d9c7b3193a802418ed2459ef4d24eab2 Mon Sep 17 00:00:00 2001 From: zeviraty Date: Sat, 13 Dec 2025 18:54:09 +0100 Subject: [PATCH 6/9] Added GH_TOKEN env to gh cli calls, added private repo support --- src/gitfetch/fetcher.py | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/src/gitfetch/fetcher.py b/src/gitfetch/fetcher.py index b71e9b8..8e95e68 100644 --- a/src/gitfetch/fetcher.py +++ b/src/gitfetch/fetcher.py @@ -78,7 +78,8 @@ def _build_contribution_graph_from_git(repo_path: str = ".") -> list: # Get commit dates result = subprocess.run( ['git', 'log', '--pretty=format:%ai', '--all'], - capture_output=True, text=True, cwd=repo_path + capture_output=True, text=True, cwd=repo_path, + env={**os.environ, 'GH_TOKEN': os.getenv('GH_TOKEN')} ) if result.returncode != 0: return [] @@ -130,8 +131,9 @@ def __init__(self, token: Optional[str] = None): Initialize the GitHub fetcher. Args: - token: Optional GitHub personal access token (ignored, uses gh CLI) + token: Optional GitHub personal access token """ + self.token=token pass def _check_gh_cli(self) -> None: @@ -141,7 +143,8 @@ def _check_gh_cli(self) -> None: ['gh', 'auth', 'status'], capture_output=True, text=True, - timeout=5 + timeout=5, + env={**os.environ, 'GH_TOKEN': self.token} ) if result.returncode != 0: print("\n⚠️ GitHub CLI is not authenticated!", file=sys.stderr) @@ -173,7 +176,8 @@ def get_authenticated_user(self) -> str: ['gh', 'auth', 'status', '--json', 'hosts'], capture_output=True, text=True, - timeout=5 + timeout=5, + env={**os.environ, 'GH_TOKEN': os.getenv('GH_TOKEN')} ) if result.returncode != 0: try: @@ -214,7 +218,8 @@ def _gh_api(self, endpoint: str, method: str = "GET") -> Any: ['gh', 'api', endpoint, '-X', method], capture_output=True, text=True, - timeout=30 + timeout=30, + env={**os.environ, 'GH_TOKEN': os.getenv('GH_TOKEN')} ) if result.returncode != 0: raise Exception(f"gh api failed: {result.stderr}") @@ -438,7 +443,8 @@ def _search_items(self, query: str, per_page: int = 5) -> Dict[str, Any]: cmd, capture_output=True, text=True, - timeout=30 + timeout=30, + env={**os.environ, 'GH_TOKEN': os.getenv('GH_TOKEN')} ) if result.returncode != 0: return {'total_count': 0, 'items': []} @@ -531,7 +537,7 @@ def _fetch_contribution_graph(self, username: str) -> list: # GraphQL query for contribution calendar (inline username) query = f'''{{ user(login: "{username}") {{ - contributionsCollection {{ + contributionsCollection(includePrivate: true) {{ contributionCalendar {{ weeks {{ contributionDays {{ @@ -549,7 +555,8 @@ def _fetch_contribution_graph(self, username: str) -> list: ['gh', 'api', 'graphql', '-f', f'query={query}'], capture_output=True, text=True, - timeout=30 + timeout=30, + env={**os.environ, 'GH_TOKEN': os.getenv('GH_TOKEN')} ) if result.returncode != 0: @@ -588,7 +595,8 @@ def _check_glab_cli(self) -> None: ['glab', 'auth', 'status'], capture_output=True, text=True, - timeout=5 + timeout=5, + env={**os.environ, 'GH_TOKEN': os.getenv('GH_TOKEN')} ) if result.returncode != 0: print("GitLab CLI not authenticated", file=sys.stderr) @@ -615,7 +623,8 @@ def get_authenticated_user(self) -> str: ['glab', 'api', '/user'], capture_output=True, text=True, - timeout=10 + timeout=10, + env={**os.environ, 'GH_TOKEN': os.getenv('GH_TOKEN')} ) if result.returncode != 0: raise Exception("Failed to get user info") @@ -641,7 +650,8 @@ def _api_request(self, endpoint: str) -> Any: cmd, capture_output=True, text=True, - timeout=30 + timeout=30, + env={**os.environ, 'GH_TOKEN': os.getenv('GH_TOKEN')} ) if result.returncode != 0: raise Exception(f"API request failed: {result.stderr}") From 242725a8b7822ddbdfc8f4ef829e13e74034d64a Mon Sep 17 00:00:00 2001 From: zeviraty Date: Sat, 13 Dec 2025 18:57:29 +0100 Subject: [PATCH 7/9] Removed env variables where not needed --- src/gitfetch/fetcher.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/gitfetch/fetcher.py b/src/gitfetch/fetcher.py index 8e95e68..23a1591 100644 --- a/src/gitfetch/fetcher.py +++ b/src/gitfetch/fetcher.py @@ -143,8 +143,7 @@ def _check_gh_cli(self) -> None: ['gh', 'auth', 'status'], capture_output=True, text=True, - timeout=5, - env={**os.environ, 'GH_TOKEN': self.token} + timeout=5 ) if result.returncode != 0: print("\n⚠️ GitHub CLI is not authenticated!", file=sys.stderr) @@ -176,8 +175,7 @@ def get_authenticated_user(self) -> str: ['gh', 'auth', 'status', '--json', 'hosts'], capture_output=True, text=True, - timeout=5, - env={**os.environ, 'GH_TOKEN': os.getenv('GH_TOKEN')} + timeout=5 ) if result.returncode != 0: try: @@ -595,8 +593,7 @@ def _check_glab_cli(self) -> None: ['glab', 'auth', 'status'], capture_output=True, text=True, - timeout=5, - env={**os.environ, 'GH_TOKEN': os.getenv('GH_TOKEN')} + timeout=5 ) if result.returncode != 0: print("GitLab CLI not authenticated", file=sys.stderr) @@ -623,8 +620,7 @@ def get_authenticated_user(self) -> str: ['glab', 'api', '/user'], capture_output=True, text=True, - timeout=10, - env={**os.environ, 'GH_TOKEN': os.getenv('GH_TOKEN')} + timeout=10 ) if result.returncode != 0: raise Exception("Failed to get user info") From eb3173eb382c6b7b3cd2968c4768c86a411842bf Mon Sep 17 00:00:00 2001 From: zeviraty Date: Sat, 13 Dec 2025 19:02:53 +0100 Subject: [PATCH 8/9] Fixed error with missing os import --- src/gitfetch/cli.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gitfetch/cli.py b/src/gitfetch/cli.py index eef85bc..7e25003 100644 --- a/src/gitfetch/cli.py +++ b/src/gitfetch/cli.py @@ -201,6 +201,7 @@ def main() -> int: # Check for --local flag if args.local: + import os if not os.path.exists('.git'): print("Error: --local requires .git folder", file=sys.stderr) return 1 From f9b3a4d0de5c9e44777413d0cc9cc693ac70e12b Mon Sep 17 00:00:00 2001 From: zeviraty Date: Sun, 14 Dec 2025 16:50:12 +0100 Subject: [PATCH 9/9] Fixed dependency --- pyproject.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 4a6597a..fc04175 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,7 +29,6 @@ classifiers = [ dependencies = [ "requests>=2.0.0", "readchar>=4.0.0", - "webcolors>=24.11.1", ] [project.optional-dependencies]