1313
1414class GitlabMergeRequestFetcher :
1515 def __init__ (self , project_id , merge_request_iid ):
16+ """
17+ Initialize a GitLab merge request fetcher.
18+
19+ Assigns the project identifier and merge request IID, and sets up caches for
20+ tracking changes, file content, and merge request information.
21+
22+ Parameters:
23+ project_id: The unique identifier for the GitLab project.
24+ merge_request_iid: The internal identifier for the merge request.
25+ """
1626 self .project_id = project_id
1727 self .iid = merge_request_iid
1828 self ._changes_cache = None
@@ -22,17 +32,23 @@ def __init__(self, project_id, merge_request_iid):
2232 @retry (stop_max_attempt_number = 3 , wait_fixed = 2000 )
2333 def get_changes (self , force = False ):
2434 """
25- Get the changes of the merge request
26- :return: changes
35+ Retrieve merge request changes via GitLab API.
36+
37+ If cached changes are available and force is False, returns the cached data.
38+ Otherwise, performs a GET request to fetch the latest changes, caches them on success,
39+ and returns the list of changes. Returns None if the API request fails.
40+
41+ Args:
42+ force (bool): If True, bypasses the cache to fetch fresh changes.
2743 """
2844 if self ._changes_cache and not force :
2945 return self ._changes_cache
3046 # URL for the GitLab API endpoint
31- url = f"{ GITLAB_SERVER_URL } /api/v4/projects/{ self .project_id } /merge_requests/{ self .iid } /changes"
47+ url = f"{ gitlab_server_url } /api/v4/projects/{ self .project_id } /merge_requests/{ self .iid } /changes"
3248
3349 # Headers for the request
3450 headers = {
35- "PRIVATE-TOKEN" : GITLAB_PRIVATE_TOKEN
51+ "PRIVATE-TOKEN" : gitlab_private_token
3652 }
3753
3854 # Make the GET request
@@ -49,20 +65,31 @@ def get_changes(self, force=False):
4965 # 获取文件内容
5066 def get_file_content (self , file_path , branch_name = 'main' , force = False ):
5167 """
52- Get the content of the file
53- :param file_path: The path of the file
54- :return: The content of the file
68+ Fetch the raw content of a repository file via the GitLab API.
69+
70+ This method retrieves the file content from the specified branch by making a GET
71+ request to the GitLab API. The provided file path is URL-encoded for proper API
72+ endpoint formatting. Cached content is returned if available, unless the force
73+ flag is set to True.
74+
75+ Args:
76+ file_path: The repository path of the file; forward slashes are URL-encoded.
77+ branch_name: The branch to fetch the file from (default is 'main').
78+ force: If True, bypasses the cache to retrieve fresh content.
79+
80+ Returns:
81+ The raw file content as a string if the request is successful; otherwise, None.
5582 """
5683 # 对file_path中的'/'转换为'%2F'
5784 file_path = file_path .replace ('/' , '%2F' )
5885 if file_path in self ._file_content_cache and not force :
5986 return self ._file_content_cache [file_path ]
6087 # URL for the GitLab API endpoint
61- url = f"{ GITLAB_SERVER_URL } /api/v4/projects/{ self .project_id } /repository/files/{ file_path } /raw?ref={ branch_name } "
88+ url = f"{ gitlab_server_url } /api/v4/projects/{ self .project_id } /repository/files/{ file_path } /raw?ref={ branch_name } "
6289
6390 # Headers for the request
6491 headers = {
65- "PRIVATE-TOKEN" : GITLAB_PRIVATE_TOKEN
92+ "PRIVATE-TOKEN" : gitlab_private_token
6693 }
6794
6895 # Make the GET request
@@ -78,17 +105,26 @@ def get_file_content(self, file_path, branch_name='main', force=False):
78105 @retry (stop_max_attempt_number = 3 , wait_fixed = 2000 )
79106 def get_info (self , force = False ):
80107 """
81- Get the merge request information
82- :return: Merge request information
108+ Retrieve merge request information.
109+
110+ If cached data is available and force is False, the cached merge request details
111+ are returned. Otherwise, the method calls the GitLab API to fetch fresh information,
112+ caches the result, and returns it. If the API request fails, None is returned.
113+
114+ Args:
115+ force (bool): If True, bypass the cache and retrieve fresh data.
116+
117+ Returns:
118+ dict or None: The merge request information if successful; otherwise, None.
83119 """
84120 if self ._info_cache and not force :
85121 return self ._info_cache
86122 # URL for the GitLab API endpoint
87- url = f"{ GITLAB_SERVER_URL } /api/v4/projects/{ self .project_id } /merge_requests/{ self .iid } "
123+ url = f"{ gitlab_server_url } /api/v4/projects/{ self .project_id } /merge_requests/{ self .iid } "
88124
89125 # Headers for the request
90126 headers = {
91- "PRIVATE-TOKEN" : GITLAB_PRIVATE_TOKEN
127+ "PRIVATE-TOKEN" : gitlab_private_token
92128 }
93129
94130 # Make the GET request
@@ -104,22 +140,37 @@ def get_info(self, force=False):
104140# gitlab仓库clone和管理
105141class GitlabRepoManager :
106142 def __init__ (self , project_id , branch_name = "" ):
143+ """
144+ Initialize a GitlabRepoManager instance.
145+
146+ Creates a unique repository path by combining the provided project ID with the current
147+ timestamp. The repository is initially marked as not cloned. The optional branch name
148+ parameter is accepted for potential branch-related operations, although it is not used
149+ during initialization.
150+
151+ Args:
152+ project_id: Identifier for the GitLab project.
153+ branch_name: Optional branch name for repository operations.
154+ """
107155 self .project_id = project_id
108156 self .timestamp = int (time .time () * 1000 )
109157 self .repo_path = f"./repo/{ self .project_id } _{ self .timestamp } "
110158 self .has_cloned = False
111159
112160 def get_info (self ):
113161 """
114- Get the project information
115- :return: Project information
162+ Retrieve project information from GitLab.
163+
164+ Makes a GET request to the GitLab API to fetch details for the project identified by the
165+ instance's project_id. Returns the JSON-decoded response if the request is successful (HTTP 200);
166+ otherwise, returns None.
116167 """
117168 # URL for the GitLab API endpoint
118- url = f"{ GITLAB_SERVER_URL } /api/v4/projects/{ self .project_id } "
169+ url = f"{ gitlab_server_url } /api/v4/projects/{ self .project_id } "
119170
120171 # Headers for the request
121172 headers = {
122- "PRIVATE-TOKEN" : GITLAB_PRIVATE_TOKEN
173+ "PRIVATE-TOKEN" : gitlab_private_token
123174 }
124175
125176 # Make the GET request
@@ -129,14 +180,20 @@ def get_info(self):
129180 if response .status_code == 200 :
130181 return response .json ()
131182 else :
132- log .error (f"获取项目信息失败: { response .status_code } { response .text } " )
133183 return None
134184
135185 @retry (stop_max_attempt_number = 3 , wait_fixed = 2000 )
136186 def shallow_clone (self , branch_name = "main" ):
137187 """
138- Perform a shallow clone of the repository
139- param branch_name: The name of the branch to clone
188+ Shallow clones the repository to a local directory.
189+
190+ Deletes any existing local clone, constructs an authenticated Git URL using
191+ repository information, and executes a shallow clone (depth of 1) for the specified
192+ branch. If cloning fails, an error is logged; otherwise, the repository is marked
193+ as cloned.
194+
195+ Args:
196+ branch_name (str): The branch to clone (default "main").
140197 """
141198 # If the target directory exists, remove it
142199 self .delete_repo ()
@@ -159,6 +216,17 @@ def shallow_clone(self, branch_name = "main"):
159216 # 切换分支
160217 def checkout_branch (self , branch_name , force = False ):
161218 # Build the Git command
219+ """
220+ Checks out the specified branch by performing a shallow clone if necessary.
221+
222+ If the repository has not been cloned already, the method executes a shallow clone for the target branch.
223+ If the repository is already cloned, it verifies whether the branch is already checked out (unless forced)
224+ and performs a shallow clone if the branch differs or if force is True.
225+
226+ Args:
227+ branch_name: The name of the branch to check out.
228+ force: If True, forces re-cloning of the branch even if it appears to be already checked out.
229+ """
162230 if not self .has_cloned :
163231 self .shallow_clone (branch_name )
164232 else :
@@ -170,11 +238,30 @@ def checkout_branch(self, branch_name, force=False):
170238
171239 # 删除库
172240 def delete_repo (self ):
241+ """
242+ Deletes the cloned repository directory if it exists.
243+
244+ This method checks whether the repository path exists on the filesystem and removes it along with its contents. If the directory is not present, no action is taken.
245+ """
173246 if os .path .exists (self .repo_path ):
174247 shutil .rmtree (self .repo_path )
175248
176249 # 查找相关文件列表
177250 def find_files_by_keyword (self , keyword , branch_name = "main" ):
251+ """
252+ Search for files whose content matches a regex pattern.
253+
254+ Checks out the specified branch and recursively searches for files whose content
255+ matches the provided regular expression. Files that cannot be read due to encoding,
256+ permission, or existence issues are skipped.
257+
258+ Args:
259+ keyword: Regular expression pattern to search for in file contents.
260+ branch_name: Branch to search in; defaults to "main".
261+
262+ Returns:
263+ A list of file paths for files containing a match to the keyword.
264+ """
178265 matching_files = []
179266 regex = re .compile (keyword )
180267 self .checkout_branch (branch_name )
@@ -196,23 +283,19 @@ def find_files_by_keyword(self, keyword, branch_name="main"):
196283 # 构建带有身份验证信息的 URL
197284 def _build_authenticated_url (self , repo_url ):
198285 # 如果 URL 使用 https
199- token = GITLAB_PRIVATE_TOKEN
286+ """
287+ Builds an authenticated URL for repository access.
288+
289+ This method embeds an OAuth2 token into the provided repository URL, supporting only
290+ URLs beginning with "http://" or "https://". For HTTPS URLs, it returns a URL in the
291+ format "https://oauth2:{token}@<rest_of_url>" and similarly for HTTP URLs. If the URL
292+ scheme is unsupported, a ValueError is raised.
293+ """
294+ token = gitlab_private_token
200295 if repo_url .startswith ("https://" ):
201296 return f"https://oauth2:{ token } @{ repo_url [8 :]} "
202297 # 如果 URL 使用 http
203298 elif repo_url .startswith ("http://" ):
204299 return f"http://oauth2:{ token } @{ repo_url [7 :]} "
205300 else :
206- raise ValueError ("Unsupported URL scheme" )
207-
208- def is_merge_request_opened (gitlab_payload ) -> bool :
209- """
210- 判断是否是merge request打开事件
211- """
212- try :
213- gitlab_merge_request_old = gitlab_payload .get ("object_attributes" ).get ("state" ) == "opened" and gitlab_payload .get ("object_attributes" ).get ("merge_status" ) == "preparing"
214- gitlab_merge_request_new = gitlab_payload .get ("object_attributes" ).get ("state" ) == "merged" and gitlab_payload .get ("object_attributes" ).get ("merge_status" ) == "can_be_merged"
215- return gitlab_merge_request_old or gitlab_merge_request_new
216- except Exception as e :
217- log .error (f"判断是否是merge request打开事件失败: { e } " )
218- return False
301+ raise ValueError ("Unsupported URL scheme" )
0 commit comments