11import logging
2+ import os
23import subprocess
4+ from pathlib import Path
35from typing import Any
46
57from pydantic import BaseModel , Field
@@ -42,17 +44,24 @@ class FindCurrentSourceIdError(BaseModel):
4244 suggestion : str | None = Field (default = None , description = "Suggestions for resolving the error" )
4345
4446
45- async def find_current_source_id () -> FindCurrentSourceIdResult | FindCurrentSourceIdError :
47+ async def find_current_source_id (repository_path : str = "." ) -> FindCurrentSourceIdResult | FindCurrentSourceIdError :
4648 """
47- Find the GitGuardian source_id for the current repository.
49+ Find the GitGuardian source_id for a repository.
4850
4951 This tool:
50- 1. Gets the current repository information from git
51- 2. Extracts the repository name from the remote URL
52+ 1. Attempts to get the repository name from git remote URL
53+ 2. If git fails, falls back to using the directory name
5254 3. Searches GitGuardian for matching sources
5355 4. Returns the source_id if an exact match is found
5456 5. If no exact match, returns all search results for the model to choose from
5557
58+ Args:
59+ repository_path: Path to the repository directory. Defaults to "." (current directory).
60+ If you're working in a specific repository, provide the full path to ensure
61+ the correct repository is analyzed (e.g., "/home/user/my-project").
62+ Note: If the directory is not a git repository, the tool will use the
63+ directory name as the repository name.
64+
5665 Returns:
5766 FindCurrentSourceIdResult: Pydantic model containing:
5867 - repository_name: The detected repository name
@@ -70,38 +79,44 @@ async def find_current_source_id() -> FindCurrentSourceIdResult | FindCurrentSou
7079 - suggestion: Suggestions for resolving the error
7180 """
7281 client = get_client ()
73- logger .debug ("Finding source_id for current repository" )
82+ logger .debug (f"Finding source_id for repository at path: { repository_path } " )
83+
84+ repository_name = None
85+ remote_url = None
86+ detection_method = None
7487
7588 try :
76- # Get current repository remote URL
89+ # Try Method 1: Get repository name from git remote URL
7790 try :
7891 result = subprocess .run (
7992 ["git" , "config" , "--get" , "remote.origin.url" ],
8093 capture_output = True ,
8194 text = True ,
8295 check = True ,
8396 timeout = 5 ,
97+ cwd = repository_path ,
8498 )
8599 remote_url = result .stdout .strip ()
86- logger . debug ( f"Found remote URL: { remote_url } " )
87- except subprocess . CalledProcessError as e :
88- return FindCurrentSourceIdError (
89- error = "Not a git repository or no remote 'origin' configured" ,
90- details = str ( e ),
91- )
92- except subprocess . TimeoutExpired :
93- return FindCurrentSourceIdError ( error = "Git command timed out" )
94-
95- # Parse repository name from remote URL
96- repository_name = parse_repo_url ( remote_url ). split ( "/" )[ - 1 ]
100+ repository_name = parse_repo_url ( remote_url ). split ( "/" )[ - 1 ]
101+ detection_method = "git remote URL"
102+ logger . debug ( f"Found remote URL: { remote_url } , parsed repository name: { repository_name } " )
103+ except ( subprocess . CalledProcessError , subprocess . TimeoutExpired ) as e :
104+ logger . debug ( f"Git remote detection failed: { e } , falling back to directory name" )
105+
106+ # Fallback Method 2: Use the directory name as repository name
107+ abs_path = os . path . abspath ( repository_path )
108+ repository_name = Path ( abs_path ). name
109+ detection_method = "directory name"
110+ logger . info ( f"Using directory name as repository name: { repository_name } " )
97111
98112 if not repository_name :
99113 return FindCurrentSourceIdError (
100- error = f"Could not parse repository URL: { remote_url } " ,
101- details = "The URL format is not recognized. Supported platforms: GitHub, GitLab (Cloud & Self-hosted), Bitbucket (Cloud & Data Center), Azure DevOps" ,
114+ error = "Could not determine repository name" ,
115+ message = "Failed to determine repository name from both git remote and directory name." ,
116+ suggestion = "Please ensure you're in a valid directory or provide a valid repository_path parameter." ,
102117 )
103118
104- logger .info (f"Detected repository name: { repository_name } " )
119+ logger .info (f"Detected repository name: { repository_name } (method: { detection_method } ) " )
105120
106121 # Search for the source in GitGuardian with robust non-exact matching
107122 result = await client .get_source_by_name (repository_name , return_all_on_no_match = True )
@@ -110,19 +125,29 @@ async def find_current_source_id() -> FindCurrentSourceIdResult | FindCurrentSou
110125 if isinstance (result , dict ):
111126 source_id = result .get ("id" )
112127 logger .info (f"Found exact match with source_id: { source_id } " )
128+
129+ message = f"Successfully found exact match for GitGuardian source: { repository_name } "
130+ if detection_method == "directory name" :
131+ message += f" (repository name inferred from { detection_method } )"
132+
113133 return FindCurrentSourceIdResult (
114134 repository_name = repository_name ,
115135 source_id = source_id ,
116136 source = result ,
117- message = f"Successfully found exact match for GitGuardian source: { repository_name } " ,
137+ message = message ,
118138 )
119139
120140 # Handle multiple candidates (list result)
121141 elif isinstance (result , list ) and len (result ) > 0 :
122142 logger .info (f"Found { len (result )} candidate sources for repository: { repository_name } " )
143+
144+ message = f"No exact match found for '{ repository_name } ', but found { len (result )} potential matches."
145+ if detection_method == "directory name" :
146+ message += f" (repository name inferred from { detection_method } )"
147+
123148 return FindCurrentSourceIdResult (
124149 repository_name = repository_name ,
125- message = f"No exact match found for ' { repository_name } ', but found { len ( result ) } potential matches." ,
150+ message = message ,
126151 suggestion = "Review the candidates below and determine which source best matches the current repository based on the name and URL." ,
127152 candidates = [
128153 SourceCandidate (
@@ -148,17 +173,27 @@ async def find_current_source_id() -> FindCurrentSourceIdResult | FindCurrentSou
148173 if isinstance (fallback_result , dict ):
149174 source_id = fallback_result .get ("id" )
150175 logger .info (f"Found match using repo name only, source_id: { source_id } " )
176+
177+ message = f"Found match using repository name '{ repo_only } ' (without organization prefix)"
178+ if detection_method == "directory name" :
179+ message += f" (repository name inferred from { detection_method } )"
180+
151181 return FindCurrentSourceIdResult (
152182 repository_name = repository_name ,
153183 source_id = source_id ,
154184 source = fallback_result ,
155- message = f"Found match using repository name ' { repo_only } ' (without organization prefix)" ,
185+ message = message ,
156186 )
157187 elif isinstance (fallback_result , list ) and len (fallback_result ) > 0 :
158188 logger .info (f"Found { len (fallback_result )} candidates using repo name only" )
189+
190+ message = f"No exact match for '{ repository_name } ', but found { len (fallback_result )} potential matches using repo name '{ repo_only } '."
191+ if detection_method == "directory name" :
192+ message += f" (repository name inferred from { detection_method } )"
193+
159194 return FindCurrentSourceIdResult (
160195 repository_name = repository_name ,
161- message = f"No exact match for ' { repository_name } ', but found { len ( fallback_result ) } potential matches using repo name ' { repo_only } '." ,
196+ message = message ,
162197 suggestion = "Review the candidates below and determine which source best matches the current repository." ,
163198 candidates = [
164199 SourceCandidate (
@@ -174,10 +209,15 @@ async def find_current_source_id() -> FindCurrentSourceIdResult | FindCurrentSou
174209
175210 # Absolutely no matches found
176211 logger .warning (f"No sources found for repository: { repository_name } " )
212+
213+ message = "The repository may not be connected to GitGuardian, or you may not have access to it."
214+ if detection_method == "directory name" :
215+ message += f" Note: repository name was inferred from { detection_method } , which may not match the actual GitGuardian source name."
216+
177217 return FindCurrentSourceIdError (
178218 repository_name = repository_name ,
179219 error = f"Repository '{ repository_name } ' not found in GitGuardian" ,
180- message = "The repository may not be connected to GitGuardian, or you may not have access to it." ,
220+ message = message ,
181221 suggestion = "Check that the repository is properly connected to GitGuardian and that your account has access to it." ,
182222 )
183223
0 commit comments