git-recap 0.1.4__py3-none-any.whl → 0.1.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  from azure.devops.connection import Connection
2
2
  from msrest.authentication import BasicAuthentication
3
3
  from datetime import datetime
4
- from typing import List, Dict, Any
4
+ from typing import List, Dict, Any, Optional
5
5
  from git_recap.providers.base_fetcher import BaseFetcher
6
6
 
7
7
  class AzureFetcher(BaseFetcher):
@@ -236,4 +236,81 @@ class AzureFetcher(BaseFetcher):
236
236
  NotImplementedError: Always, since release fetching is not supported for AzureFetcher.
237
237
  """
238
238
  # If Azure DevOps release fetching is supported in the future, implement logic here.
239
- raise NotImplementedError("Release fetching is not supported for Azure DevOps (AzureFetcher).")
239
+ raise NotImplementedError("Release fetching is not supported for Azure DevOps (AzureFetcher).")
240
+
241
+ def get_branches(self) -> List[str]:
242
+ """
243
+ Get all branches in the repository.
244
+
245
+ Returns:
246
+ List[str]: List of branch names.
247
+
248
+ Raises:
249
+ NotImplementedError: Always, since branch listing is not yet implemented for AzureFetcher.
250
+ """
251
+ # TODO: Implement get_branches() for Azure DevOps support
252
+ # This would use: git_client.get_branches(repository_id, project)
253
+ # and extract branch names from the returned objects
254
+ raise NotImplementedError("Branch listing is not yet implemented for Azure DevOps (AzureFetcher).")
255
+
256
+ def get_valid_target_branches(self, source_branch: str) -> List[str]:
257
+ """
258
+ Get branches that can receive a pull request from the source branch.
259
+
260
+ Validates that the source branch exists, filters out branches with existing
261
+ open PRs from source, excludes the source branch itself, and optionally
262
+ checks if source is ahead of target.
263
+
264
+ Args:
265
+ source_branch (str): The source branch name.
266
+
267
+ Returns:
268
+ List[str]: List of valid target branch names.
269
+
270
+ Raises:
271
+ NotImplementedError: Always, since PR target validation is not yet implemented for AzureFetcher.
272
+ """
273
+ # TODO: Implement get_valid_target_branches() for Azure DevOps support
274
+ # This would require:
275
+ # 1. Verify source_branch exists using git_client.get_branch()
276
+ # 2. Get all branches using get_branches()
277
+ # 3. Filter out source branch
278
+ # 4. Check for existing pull requests using git_client.get_pull_requests()
279
+ # 5. Filter out branches with existing open PRs from source
280
+ # 6. Optionally check branch policies and protection rules
281
+ raise NotImplementedError("Pull request target branch validation is not yet implemented for Azure DevOps (AzureFetcher).")
282
+
283
+ def create_pull_request(
284
+ self,
285
+ head_branch: str,
286
+ base_branch: str,
287
+ title: str,
288
+ body: str,
289
+ draft: bool = False,
290
+ reviewers: Optional[List[str]] = None,
291
+ assignees: Optional[List[str]] = None,
292
+ labels: Optional[List[str]] = None
293
+ ) -> Dict[str, Any]:
294
+ """
295
+ Create a pull request between two branches with optional metadata.
296
+
297
+ Args:
298
+ head_branch: Source branch for the PR.
299
+ base_branch: Target branch for the PR.
300
+ title: PR title.
301
+ body: PR description.
302
+ draft: Whether to create as draft PR (default: False).
303
+ reviewers: List of reviewer usernames (optional).
304
+ assignees: List of assignee usernames (optional).
305
+ labels: List of label names (optional).
306
+
307
+ Returns:
308
+ Dict[str, Any]: Dictionary containing PR metadata (url, number, state, success) or error information.
309
+
310
+ Raises:
311
+ NotImplementedError: Always, since PR creation is not yet implemented for AzureFetcher.
312
+ """
313
+ # TODO: Implement create_pull_request() for Azure DevOps support
314
+ # This would use: git_client.create_pull_request() with appropriate parameters
315
+ # Would need to handle reviewers, work item links (assignees), labels, and draft status
316
+ raise NotImplementedError("Pull request creation is not yet implemented for Azure DevOps (AzureFetcher).")
@@ -90,6 +90,72 @@ class BaseFetcher(ABC):
90
90
  """
91
91
  raise NotImplementedError("Release fetching is not implemented for this provider.")
92
92
 
93
+ @abstractmethod
94
+ def get_branches(self) -> List[str]:
95
+ """
96
+ Get all branches in the repository.
97
+
98
+ Returns:
99
+ List[str]: List of branch names.
100
+
101
+ Raises:
102
+ NotImplementedError: Subclasses must implement this method.
103
+ """
104
+ raise NotImplementedError("Subclasses must implement get_branches() to return all repository branches")
105
+
106
+ @abstractmethod
107
+ def get_valid_target_branches(self, source_branch: str) -> List[str]:
108
+ """
109
+ Get branches that can receive a pull request from the source branch.
110
+
111
+ Validates that the source branch exists, filters out branches with existing
112
+ open PRs from source, excludes the source branch itself, and optionally
113
+ checks if source is ahead of target.
114
+
115
+ Args:
116
+ source_branch (str): The source branch name.
117
+
118
+ Returns:
119
+ List[str]: List of valid target branch names.
120
+
121
+ Raises:
122
+ NotImplementedError: Subclasses must implement this method.
123
+ """
124
+ raise NotImplementedError("Subclasses must implement get_valid_target_branches() to return valid PR target branches for the given source branch")
125
+
126
+ @abstractmethod
127
+ def create_pull_request(
128
+ self,
129
+ head_branch: str,
130
+ base_branch: str,
131
+ title: str,
132
+ body: str,
133
+ draft: bool = False,
134
+ reviewers: Optional[List[str]] = None,
135
+ assignees: Optional[List[str]] = None,
136
+ labels: Optional[List[str]] = None
137
+ ) -> Dict[str, Any]:
138
+ """
139
+ Create a pull request between two branches with optional metadata.
140
+
141
+ Args:
142
+ head_branch: Source branch for the PR.
143
+ base_branch: Target branch for the PR.
144
+ title: PR title.
145
+ body: PR description.
146
+ draft: Whether to create as draft PR (default: False).
147
+ reviewers: List of reviewer usernames (optional).
148
+ assignees: List of assignee usernames (optional).
149
+ labels: List of label names (optional).
150
+
151
+ Returns:
152
+ Dict[str, Any]: Dictionary containing PR metadata (url, number, state, success) or error information.
153
+
154
+ Raises:
155
+ NotImplementedError: Subclasses must implement this method.
156
+ """
157
+ raise NotImplementedError("Subclasses must implement create_pull_request() to create a pull request with the specified parameters")
158
+
93
159
  def get_authored_messages(self) -> List[Dict[str, Any]]:
94
160
  """
95
161
  Aggregates all commit, pull request, and issue entries into a single list,
@@ -1,7 +1,12 @@
1
1
  from github import Github
2
+ from github import GithubException
2
3
  from datetime import datetime
3
- from typing import List, Dict, Any
4
+ from typing import List, Dict, Any, Optional
4
5
  from git_recap.providers.base_fetcher import BaseFetcher
6
+ import logging
7
+
8
+ logger = logging.getLogger(__name__)
9
+
5
10
 
6
11
  class GitHubFetcher(BaseFetcher):
7
12
  """
@@ -59,6 +64,32 @@ class GitHubFetcher(BaseFetcher):
59
64
  break
60
65
  return entries
61
66
 
67
+ def fetch_branch_diff_commits(self, source_branch: str, target_branch: str) -> List[Dict[str, Any]]:
68
+ entries = []
69
+ processed_commits = set()
70
+ for repo in self.repos:
71
+ if self.repo_filter and repo.name not in self.repo_filter:
72
+ continue
73
+ try:
74
+ comparison = repo.compare(target_branch, source_branch)
75
+ for commit in comparison.commits:
76
+ commit_date = commit.commit.author.date
77
+ sha = commit.sha
78
+ if sha not in processed_commits:
79
+ entry = {
80
+ "type": "commit",
81
+ "repo": repo.name,
82
+ "message": commit.commit.message.strip(),
83
+ "timestamp": commit_date,
84
+ "sha": sha,
85
+ }
86
+ entries.append(entry)
87
+ processed_commits.add(sha)
88
+ except GithubException as e:
89
+ logger.error(f"Failed to compare branches in {repo.name}: {str(e)}")
90
+ continue
91
+ return entries
92
+
62
93
  def fetch_pull_requests(self) -> List[Dict[str, Any]]:
63
94
  entries = []
64
95
  # Maintain a local set to skip duplicate commits already captured in a PR.
@@ -174,4 +205,204 @@ class GitHubFetcher(BaseFetcher):
174
205
  except Exception:
175
206
  # If fetching releases fails for a repo, skip it (could be permissions or no releases)
176
207
  continue
177
- return releases
208
+ return releases
209
+
210
+ def get_branches(self) -> List[str]:
211
+ """
212
+ Get all branches in the repository.
213
+ Returns:
214
+ List[str]: List of branch names.
215
+ Raises:
216
+ Exception: If API rate limits are exceeded or authentication fails.
217
+ """
218
+ logger.debug("Fetching branches from all accessible repositories")
219
+ try:
220
+ branches = []
221
+ for repo in self.repos:
222
+ if self.repo_filter and repo.name not in self.repo_filter:
223
+ continue
224
+ logger.debug(f"Fetching branches for repository: {repo.name}")
225
+ repo_branches = repo.get_branches()
226
+ for branch in repo_branches:
227
+ branches.append(branch.name)
228
+ logger.debug(f"Successfully fetched {len(branches)} branches")
229
+ return branches
230
+ except GithubException as e:
231
+ if e.status == 403:
232
+ logger.error(f"Rate limit exceeded or authentication failed: {str(e)}")
233
+ raise Exception(f"Failed to fetch branches: Rate limit exceeded or authentication failed - {str(e)}")
234
+ elif e.status == 401:
235
+ logger.error(f"Authentication failed: {str(e)}")
236
+ raise Exception(f"Failed to fetch branches: Authentication failed - {str(e)}")
237
+ else:
238
+ logger.error(f"GitHub API error while fetching branches: {str(e)}")
239
+ raise Exception(f"Failed to fetch branches: {str(e)}")
240
+ except Exception as e:
241
+ logger.error(f"Unexpected error while fetching branches: {str(e)}")
242
+ raise Exception(f"Failed to fetch branches: {str(e)}")
243
+
244
+ def get_valid_target_branches(self, source_branch: str) -> List[str]:
245
+ """
246
+ Get branches that can receive a pull request from the source branch.
247
+ Validates that the source branch exists, filters out branches with existing
248
+ open PRs from source, excludes the source branch itself, and optionally
249
+ checks if source is ahead of target.
250
+ Args:
251
+ source_branch (str): The source branch name.
252
+ Returns:
253
+ List[str]: List of valid target branch names.
254
+ Raises:
255
+ ValueError: If source branch does not exist.
256
+ Exception: If API errors occur during validation.
257
+ """
258
+ logger.debug(f"Validating target branches for source branch: {source_branch}")
259
+ try:
260
+ all_branches = self.get_branches()
261
+ if source_branch not in all_branches:
262
+ logger.error(f"Source branch '{source_branch}' does not exist")
263
+ raise ValueError(f"Source branch '{source_branch}' does not exist")
264
+ valid_targets = []
265
+ for repo in self.repos:
266
+ if self.repo_filter and repo.name not in self.repo_filter:
267
+ continue
268
+ logger.debug(f"Processing repository: {repo.name}")
269
+ repo_branches = [branch.name for branch in repo.get_branches()]
270
+ # Get existing open PRs from source branch
271
+ try:
272
+ open_prs = repo.get_pulls(state='open', head=source_branch)
273
+ except GithubException as e:
274
+ logger.error(f"GitHub API error while getting PRs: {str(e)}")
275
+ raise Exception(f"Failed to validate target branches: {str(e)}")
276
+ existing_pr_targets = set()
277
+ for pr in open_prs:
278
+ existing_pr_targets.add(pr.base.ref)
279
+ logger.debug(f"Found existing PR from {source_branch} to {pr.base.ref}")
280
+ for branch_name in repo_branches:
281
+ if branch_name == source_branch:
282
+ logger.debug(f"Excluding source branch: {branch_name}")
283
+ continue
284
+ if branch_name in existing_pr_targets:
285
+ logger.debug(f"Excluding branch with existing PR: {branch_name}")
286
+ continue
287
+ # Optionally check if source is ahead of target (performance cost)
288
+ valid_targets.append(branch_name)
289
+ logger.debug(f"Valid target branch: {branch_name}")
290
+ logger.debug(f"Found {len(valid_targets)} valid target branches")
291
+ return valid_targets
292
+ except ValueError:
293
+ raise
294
+ except GithubException as e:
295
+ logger.error(f"GitHub API error while validating target branches: {str(e)}")
296
+ raise Exception(f"Failed to validate target branches: {str(e)}")
297
+ except Exception as e:
298
+ logger.error(f"Unexpected error while validating target branches: {str(e)}")
299
+ raise Exception(f"Failed to validate target branches: {str(e)}")
300
+
301
+ def create_pull_request(
302
+ self,
303
+ head_branch: str,
304
+ base_branch: str,
305
+ title: str,
306
+ body: str,
307
+ draft: bool = False,
308
+ reviewers: Optional[List[str]] = None,
309
+ assignees: Optional[List[str]] = None,
310
+ labels: Optional[List[str]] = None
311
+ ) -> Dict[str, Any]:
312
+ """
313
+ Create a pull request between two branches with optional metadata.
314
+ Args:
315
+ head_branch: Source branch for the PR.
316
+ base_branch: Target branch for the PR.
317
+ title: PR title.
318
+ body: PR description.
319
+ draft: Whether to create as draft PR (default: False).
320
+ reviewers: List of reviewer usernames (optional).
321
+ assignees: List of assignee usernames (optional).
322
+ labels: List of label names (optional).
323
+ Returns:
324
+ Dict[str, Any]: Dictionary containing PR metadata or error information.
325
+ Raises:
326
+ ValueError: If branches don't exist or PR already exists.
327
+ """
328
+ logger.info(f"Creating pull request from {head_branch} to {base_branch}")
329
+ try:
330
+ all_branches = self.get_branches()
331
+ if head_branch not in all_branches:
332
+ logger.error(f"Head branch '{head_branch}' does not exist")
333
+ raise ValueError(f"Head branch '{head_branch}' does not exist")
334
+ if base_branch not in all_branches:
335
+ logger.error(f"Base branch '{base_branch}' does not exist")
336
+ raise ValueError(f"Base branch '{base_branch}' does not exist")
337
+ for repo in self.repos:
338
+ if self.repo_filter and repo.name not in self.repo_filter:
339
+ continue
340
+ logger.debug(f"Checking for existing PRs in repository: {repo.name}")
341
+ try:
342
+ existing_prs = repo.get_pulls(state='open', head=head_branch, base=base_branch)
343
+ except GithubException as e:
344
+ logger.error(f"GitHub API error while getting PRs: {str(e)}")
345
+ raise
346
+ if hasattr(existing_prs, "totalCount") and existing_prs.totalCount > 0:
347
+ logger.error(f"Pull request already exists from {head_branch} to {base_branch}")
348
+ raise ValueError(f"Pull request already exists from {head_branch} to {base_branch}")
349
+ elif isinstance(existing_prs, list) and len(existing_prs) > 0:
350
+ logger.error(f"Pull request already exists from {head_branch} to {base_branch}")
351
+ raise ValueError(f"Pull request already exists from {head_branch} to {base_branch}")
352
+ logger.info(f"Creating pull request in repository: {repo.name}")
353
+ try:
354
+ pr = repo.create_pull(
355
+ title=title,
356
+ body=body,
357
+ head=head_branch,
358
+ base=base_branch,
359
+ draft=draft
360
+ )
361
+ logger.info(f"Pull request created successfully: {pr.html_url}")
362
+ if reviewers and len(reviewers) > 0:
363
+ try:
364
+ logger.debug(f"Adding reviewers: {reviewers}")
365
+ pr.create_review_request(reviewers=reviewers)
366
+ logger.info(f"Successfully added reviewers: {reviewers}")
367
+ except GithubException as e:
368
+ logger.warning(f"Failed to add reviewers: {str(e)}")
369
+ if assignees and len(assignees) > 0:
370
+ try:
371
+ logger.debug(f"Adding assignees: {assignees}")
372
+ pr.add_to_assignees(*assignees)
373
+ logger.info(f"Successfully added assignees: {assignees}")
374
+ except GithubException as e:
375
+ logger.warning(f"Failed to add assignees: {str(e)}")
376
+ if labels and len(labels) > 0:
377
+ try:
378
+ logger.debug(f"Adding labels: {labels}")
379
+ pr.add_to_labels(*labels)
380
+ logger.info(f"Successfully added labels: {labels}")
381
+ except GithubException as e:
382
+ logger.warning(f"Failed to add labels: {str(e)}")
383
+ return {
384
+ "url": pr.html_url,
385
+ "number": pr.number,
386
+ "state": pr.state,
387
+ "success": True
388
+ }
389
+ except GithubException as e:
390
+ if e.status == 404:
391
+ logger.error(f"Branch not found: {str(e)}")
392
+ raise ValueError(f"Branch not found: {str(e)}")
393
+ elif e.status == 403:
394
+ logger.error(f"Permission denied: {str(e)}")
395
+ raise GithubException(e.status, f"Permission denied: {str(e)}", e.headers)
396
+ elif e.status == 422:
397
+ logger.error(f"Merge conflict or validation error: {str(e)}")
398
+ raise ValueError(f"Merge conflict or validation error: {str(e)}")
399
+ else:
400
+ logger.error(f"GitHub API error: {str(e)}")
401
+ raise
402
+ logger.error("No repository found to create pull request")
403
+ raise ValueError("No repository found to create pull request")
404
+ except (ValueError, GithubException):
405
+ raise
406
+ except Exception as e:
407
+ logger.error(f"Unexpected error while creating pull request: {str(e)}")
408
+ raise Exception(f"Failed to create pull request: {str(e)}")
@@ -1,6 +1,6 @@
1
1
  import gitlab
2
2
  from datetime import datetime
3
- from typing import List, Dict, Any
3
+ from typing import List, Dict, Any, Optional
4
4
  from git_recap.providers.base_fetcher import BaseFetcher
5
5
 
6
6
  class GitLabFetcher(BaseFetcher):
@@ -183,5 +183,67 @@ class GitLabFetcher(BaseFetcher):
183
183
  Raises:
184
184
  NotImplementedError: Always, since release fetching is not supported for GitLabFetcher.
185
185
  """
186
- # If GitLab release fetching is supported in the future, implement logic here.
187
- raise NotImplementedError("Release fetching is not supported for GitLab (GitLabFetcher).")
186
+ raise NotImplementedError("Release fetching is not supported for GitLab (GitLabFetcher).")
187
+
188
+ def get_branches(self) -> List[str]:
189
+ """
190
+ Get all branches in the repository.
191
+
192
+ Returns:
193
+ List[str]: List of branch names.
194
+
195
+ Raises:
196
+ NotImplementedError: Always, since branch listing is not yet implemented for GitLabFetcher.
197
+ """
198
+ raise NotImplementedError("Branch listing is not yet implemented for GitLab (GitLabFetcher).")
199
+
200
+ def get_valid_target_branches(self, source_branch: str) -> List[str]:
201
+ """
202
+ Get branches that can receive a pull request from the source branch.
203
+
204
+ Validates that the source branch exists, filters out branches with existing
205
+ open PRs from source, excludes the source branch itself, and optionally
206
+ checks if source is ahead of target.
207
+
208
+ Args:
209
+ source_branch (str): The source branch name.
210
+
211
+ Returns:
212
+ List[str]: List of valid target branch names.
213
+
214
+ Raises:
215
+ NotImplementedError: Always, since PR target validation is not yet implemented for GitLabFetcher.
216
+ """
217
+ raise NotImplementedError("Pull request target branch validation is not yet implemented for GitLab (GitLabFetcher).")
218
+
219
+ def create_pull_request(
220
+ self,
221
+ head_branch: str,
222
+ base_branch: str,
223
+ title: str,
224
+ body: str,
225
+ draft: bool = False,
226
+ reviewers: Optional[List[str]] = None,
227
+ assignees: Optional[List[str]] = None,
228
+ labels: Optional[List[str]] = None
229
+ ) -> Dict[str, Any]:
230
+ """
231
+ Create a pull request (merge request) between two branches with optional metadata.
232
+
233
+ Args:
234
+ head_branch: Source branch for the PR.
235
+ base_branch: Target branch for the PR.
236
+ title: PR title.
237
+ body: PR description.
238
+ draft: Whether to create as draft PR (default: False).
239
+ reviewers: List of reviewer usernames (optional).
240
+ assignees: List of assignee usernames (optional).
241
+ labels: List of label names (optional).
242
+
243
+ Returns:
244
+ Dict[str, Any]: Dictionary containing PR metadata (url, number, state, success) or error information.
245
+
246
+ Raises:
247
+ NotImplementedError: Always, since PR creation is not yet implemented for GitLabFetcher.
248
+ """
249
+ raise NotImplementedError("Pull request (merge request) creation is not yet implemented for GitLab (GitLabFetcher).")
@@ -229,10 +229,67 @@ class URLFetcher(BaseFetcher):
229
229
  Raises:
230
230
  NotImplementedError: Always, since release fetching is not supported for URLFetcher.
231
231
  """
232
- # If in the future, support for fetching releases from generic git repos is added,
233
- # implement logic here (e.g., parse tags and annotate with metadata).
234
232
  raise NotImplementedError("Release fetching is not supported for generic Git URLs (URLFetcher).")
235
233
 
234
+ def get_branches(self) -> List[str]:
235
+ """
236
+ Get all branches in the repository.
237
+
238
+ Returns:
239
+ List[str]: List of branch names.
240
+
241
+ Raises:
242
+ NotImplementedError: Always, since branch listing is not yet implemented for URLFetcher.
243
+ """
244
+ raise NotImplementedError("Branch listing is not yet implemented for generic Git URLs (URLFetcher).")
245
+
246
+ def get_valid_target_branches(self, source_branch: str) -> List[str]:
247
+ """
248
+ Get branches that can receive a pull request from the source branch.
249
+
250
+ Args:
251
+ source_branch (str): The source branch name.
252
+
253
+ Returns:
254
+ List[str]: List of valid target branch names.
255
+
256
+ Raises:
257
+ NotImplementedError: Always, since PR target validation is not supported for URLFetcher.
258
+ """
259
+ raise NotImplementedError("Pull request target branch validation is not supported for generic Git URLs (URLFetcher).")
260
+
261
+ def create_pull_request(
262
+ self,
263
+ head_branch: str,
264
+ base_branch: str,
265
+ title: str,
266
+ body: str,
267
+ draft: bool = False,
268
+ reviewers: Optional[List[str]] = None,
269
+ assignees: Optional[List[str]] = None,
270
+ labels: Optional[List[str]] = None
271
+ ) -> Dict[str, Any]:
272
+ """
273
+ Create a pull request between two branches.
274
+
275
+ Args:
276
+ head_branch: Source branch for the PR.
277
+ base_branch: Target branch for the PR.
278
+ title: PR title.
279
+ body: PR description.
280
+ draft: Whether to create as draft PR (default: False).
281
+ reviewers: List of reviewer usernames (optional).
282
+ assignees: List of assignee usernames (optional).
283
+ labels: List of label names (optional).
284
+
285
+ Returns:
286
+ Dict[str, Any]: Dictionary containing PR metadata or error information.
287
+
288
+ Raises:
289
+ NotImplementedError: Always, since PR creation is not supported for URLFetcher.
290
+ """
291
+ raise NotImplementedError("Pull request creation is not supported for generic Git URLs (URLFetcher).")
292
+
236
293
  def clear(self) -> None:
237
294
  """Clean up temporary directory."""
238
295
  if self.temp_dir and os.path.exists(self.temp_dir):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: git-recap
3
- Version: 0.1.4
3
+ Version: 0.1.5
4
4
  Summary: A modular Python tool that aggregates and formats user-authored messages from repositories.
5
5
  Author: Bruno V.
6
6
  Author-email: bruno.vitorino@tecnico.ulisboa.pt
@@ -0,0 +1,14 @@
1
+ git_recap/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ git_recap/fetcher.py,sha256=oRlenzd9OsiBkCtpUgSZGlUoUnVpdkolUZhFOF1USBs,2677
3
+ git_recap/utils.py,sha256=NAG0cvm1sYKEQD5E9PueduB3CZQRTahrioxZNgwwmi4,5481
4
+ git_recap/providers/__init__.py,sha256=njrsu58KB60-wN78P0egm1lkQLIRq_PHLKM4WBt39Os,330
5
+ git_recap/providers/azure_fetcher.py,sha256=ex1XX1SZ5xgWDSEQdsAtaKGaOK21pem_sWdoPZe2DNE,13152
6
+ git_recap/providers/base_fetcher.py,sha256=yqVHTVAPlsDPD85SESx1u6SHeT_I9XLv41SnFo_ESPQ,7472
7
+ git_recap/providers/github_fetcher.py,sha256=pSvpaAoE2-lK-rEwvpliOZh-oIiI0SulHMuiYaqiEts,19239
8
+ git_recap/providers/gitlab_fetcher.py,sha256=i9W00H-DLyc-R--KxWbVy4CSDbORf_BmWcKveWulyzs,9752
9
+ git_recap/providers/url_fetcher.py,sha256=hwASWC8j17P37qLoQxO6WeT1EZ2AqwtYc9kiXKHLBhQ,10753
10
+ git_recap-0.1.5.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
11
+ git_recap-0.1.5.dist-info/METADATA,sha256=CbKCAeuSX9PBSxb8HpYea_OZi8dlzgIpB44Vgur9aNY,4946
12
+ git_recap-0.1.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
13
+ git_recap-0.1.5.dist-info/top_level.txt,sha256=1JUKd3WPB8c3LcD1deIW-1UTmYzA0zJqwugAz72YZ_o,10
14
+ git_recap-0.1.5.dist-info/RECORD,,
@@ -1,14 +0,0 @@
1
- git_recap/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- git_recap/fetcher.py,sha256=oRlenzd9OsiBkCtpUgSZGlUoUnVpdkolUZhFOF1USBs,2677
3
- git_recap/utils.py,sha256=NAG0cvm1sYKEQD5E9PueduB3CZQRTahrioxZNgwwmi4,5481
4
- git_recap/providers/__init__.py,sha256=njrsu58KB60-wN78P0egm1lkQLIRq_PHLKM4WBt39Os,330
5
- git_recap/providers/azure_fetcher.py,sha256=nVJr77EYcuVDEAdY1B4UJCfHQTz8rE7s0Bmz3To1XVU,9722
6
- git_recap/providers/base_fetcher.py,sha256=EIkaqHBl5xyvNigK9jojlVxxbJrWXg0cNnRkmOLoPWk,4980
7
- git_recap/providers/github_fetcher.py,sha256=k9akil096PO29SNk2xaZPjRipnxS_sAO0GukWjMdSf4,7375
8
- git_recap/providers/gitlab_fetcher.py,sha256=apfaRrP7Dat0OKjo3InmNFwNEOiJShA8mSHPyW-9yKg,7333
9
- git_recap/providers/url_fetcher.py,sha256=oQqewY6uo-OgsCvZuodj6vWonHfeANrE-KSiCVH7il8,8741
10
- git_recap-0.1.4.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
11
- git_recap-0.1.4.dist-info/METADATA,sha256=zC2u1gX9G2_VDmdFrJzE2nJykYfuztkHt9DxCgW6v9Q,4946
12
- git_recap-0.1.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
13
- git_recap-0.1.4.dist-info/top_level.txt,sha256=1JUKd3WPB8c3LcD1deIW-1UTmYzA0zJqwugAz72YZ_o,10
14
- git_recap-0.1.4.dist-info/RECORD,,