git-recap 0.1.4__py3-none-any.whl → 0.1.6__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.
@@ -0,0 +1,390 @@
1
+ import os
2
+ import subprocess
3
+ from typing import List, Dict, Any, Optional
4
+ from datetime import datetime
5
+ from git_recap.providers.base_fetcher import BaseFetcher
6
+
7
+
8
+ class LocalFetcher(BaseFetcher):
9
+ """
10
+ Fetcher implementation for local Git repositories.
11
+
12
+ Works directly on a local git repository path without cloning.
13
+ Supports fetching commits, authors, and branch information.
14
+ """
15
+
16
+ def __init__(
17
+ self,
18
+ repo_path: str,
19
+ authors: Optional[List[str]] = None,
20
+ start_date: Optional[datetime] = None,
21
+ end_date: Optional[datetime] = None,
22
+ repo_filter: Optional[List[str]] = None,
23
+ validate_repo: bool = True
24
+ ):
25
+ """
26
+ Initialize the LocalFetcher.
27
+
28
+ Args:
29
+ repo_path: Path to the local git repository
30
+ authors: List of author names to filter by (optional)
31
+ start_date: Start date for filtering commits (optional)
32
+ end_date: End date for filtering commits (optional)
33
+ repo_filter: List of repository names to filter (optional)
34
+ validate_repo: Whether to validate the repository path (default: True)
35
+ """
36
+ super().__init__(pat=None, start_date=start_date, end_date=end_date, repo_filter=repo_filter, authors=authors)
37
+ self.repo_path = repo_path
38
+ if validate_repo:
39
+ self._validate_repo()
40
+
41
+ def _validate_repo(self) -> None:
42
+ """
43
+ Validate that the provided path is a valid git repository.
44
+
45
+ Raises:
46
+ ValueError: If the path is not a valid git repository.
47
+ """
48
+ if not os.path.exists(self.repo_path):
49
+ raise ValueError(f"Path does not exist: {self.repo_path}")
50
+
51
+ if not os.path.isdir(self.repo_path):
52
+ raise ValueError(f"Path is not a directory: {self.repo_path}")
53
+
54
+ git_dir = os.path.join(self.repo_path, '.git')
55
+ if not os.path.exists(git_dir):
56
+ raise ValueError(f"Not a git repository: {self.repo_path}")
57
+
58
+ # Verify it's a valid git repo by running a simple command
59
+ try:
60
+ _result = subprocess.run(
61
+ ["git", "-C", self.repo_path, "rev-parse", "--git-dir"],
62
+ capture_output=True,
63
+ text=True,
64
+ check=True,
65
+ timeout=10
66
+ )
67
+ except subprocess.TimeoutExpired:
68
+ raise ValueError(f"Timeout while validating git repository: {self.repo_path}")
69
+ except subprocess.CalledProcessError as e:
70
+ raise ValueError(f"Invalid git repository: {self.repo_path}. Error: {e.stderr}")
71
+
72
+ @property
73
+ def repos_names(self) -> List[str]:
74
+ """
75
+ Return the repository name.
76
+
77
+ Returns:
78
+ List[str]: List containing the repository name (single item).
79
+ """
80
+ repo_name = os.path.basename(self.repo_path)
81
+ return [repo_name]
82
+
83
+ def _run_git_log(self, extra_args: List[str] = None) -> List[Dict[str, Any]]:
84
+ """
85
+ Run git log command with common arguments and parse output.
86
+
87
+ Args:
88
+ extra_args (List[str], optional): Additional git log arguments.
89
+
90
+ Returns:
91
+ List[Dict[str, Any]]: Parsed commit entries.
92
+ """
93
+ args = [
94
+ "git",
95
+ "-C", self.repo_path,
96
+ "log",
97
+ "--pretty=format:%H|%an|%ad|%s",
98
+ "--date=iso",
99
+ "--all"
100
+ ]
101
+
102
+ if self.start_date:
103
+ args.extend(["--since", self.start_date.isoformat()])
104
+ if self.end_date:
105
+ args.extend(["--until", self.end_date.isoformat()])
106
+ if self.authors:
107
+ authors_filter = "|".join(self.authors)
108
+ args.extend(["--author", authors_filter])
109
+ if extra_args:
110
+ args.extend(extra_args)
111
+
112
+ try:
113
+ result = subprocess.run(
114
+ args,
115
+ capture_output=True,
116
+ text=True,
117
+ check=True,
118
+ timeout=120
119
+ )
120
+ return self._parse_git_log(result.stdout)
121
+ except subprocess.TimeoutExpired:
122
+ return []
123
+ except subprocess.CalledProcessError:
124
+ return []
125
+
126
+ def _parse_git_log(self, log_output: str) -> List[Dict[str, Any]]:
127
+ """
128
+ Parse git log output into structured data.
129
+
130
+ Args:
131
+ log_output (str): Raw git log output.
132
+
133
+ Returns:
134
+ List[Dict[str, Any]]: Parsed commit entries.
135
+ """
136
+ entries = []
137
+ for line in log_output.splitlines():
138
+ if not line.strip():
139
+ continue
140
+
141
+ try:
142
+ sha, author, date_str, message = line.split("|", 3)
143
+ timestamp = datetime.fromisoformat(date_str)
144
+
145
+ if self.start_date and timestamp < self.start_date:
146
+ continue
147
+ if self.end_date and timestamp > self.end_date:
148
+ continue
149
+
150
+ entries.append({
151
+ "type": "commit",
152
+ "repo": self.repos_names[0],
153
+ "message": message,
154
+ "sha": sha,
155
+ "author": author,
156
+ "timestamp": timestamp
157
+ })
158
+ except ValueError:
159
+ continue
160
+
161
+ return entries
162
+
163
+ def fetch_commits(self) -> List[Dict[str, Any]]:
164
+ """
165
+ Fetch commits from the local repository.
166
+
167
+ Returns:
168
+ List[Dict[str, Any]]: List of commit entries.
169
+ """
170
+ return self._run_git_log()
171
+
172
+ def fetch_pull_requests(self) -> List[Dict[str, Any]]:
173
+ """
174
+ Fetch pull requests (not applicable for local repositories).
175
+
176
+ Returns:
177
+ List[Dict[str, Any]]: Empty list (PRs are platform-specific).
178
+ """
179
+ return []
180
+
181
+ def fetch_issues(self) -> List[Dict[str, Any]]:
182
+ """
183
+ Fetch issues (not applicable for local repositories).
184
+
185
+ Returns:
186
+ List[Dict[str, Any]]: Empty list (issues are platform-specific).
187
+ """
188
+ return []
189
+
190
+ def fetch_releases(self) -> List[Dict[str, Any]]:
191
+ """
192
+ Fetch releases for the repository.
193
+ Not applicable for local repositories.
194
+
195
+ Raises:
196
+ NotImplementedError: Always, since release fetching is not supported for LocalFetcher.
197
+ """
198
+ raise NotImplementedError(
199
+ "Release fetching is not supported for local repositories (LocalFetcher)."
200
+ )
201
+
202
+ def get_branches(self) -> List[str]:
203
+ """
204
+ Get all branches in the local repository.
205
+
206
+ Returns:
207
+ List[str]: List of branch names (both local and remote).
208
+ """
209
+ try:
210
+ # Get local branches
211
+ result = subprocess.run(
212
+ ["git", "-C", self.repo_path, "branch", "--format=%(refname:short)"],
213
+ capture_output=True,
214
+ text=True,
215
+ check=True
216
+ )
217
+ branches = [b.strip() for b in result.stdout.splitlines() if b.strip()]
218
+
219
+ # Get remote branches
220
+ result_remote = subprocess.run(
221
+ ["git", "-C", self.repo_path, "branch", "-r", "--format=%(refname:short)"],
222
+ capture_output=True,
223
+ text=True,
224
+ check=True
225
+ )
226
+ remote_branches = [
227
+ b.strip() for b in result_remote.stdout.splitlines()
228
+ if b.strip() and not b.endswith('/HEAD')
229
+ ]
230
+
231
+ return branches + remote_branches
232
+ except subprocess.CalledProcessError:
233
+ return []
234
+
235
+ def get_valid_target_branches(self, source_branch: str) -> List[str]:
236
+ """
237
+ Get branches that can receive a pull request from the source branch.
238
+ Not applicable for local repositories.
239
+
240
+ Args:
241
+ source_branch (str): The source branch name.
242
+
243
+ Returns:
244
+ List[str]: Empty list (PRs are platform-specific).
245
+
246
+ Raises:
247
+ NotImplementedError: Always, since PR validation is not supported for LocalFetcher.
248
+ """
249
+ raise NotImplementedError(
250
+ "Pull request target branch validation is not supported for local repositories (LocalFetcher)."
251
+ )
252
+
253
+ def create_pull_request(
254
+ self,
255
+ head_branch: str,
256
+ base_branch: str,
257
+ title: str,
258
+ body: str,
259
+ draft: bool = False,
260
+ reviewers: Optional[List[str]] = None,
261
+ assignees: Optional[List[str]] = None,
262
+ labels: Optional[List[str]] = None
263
+ ) -> Dict[str, Any]:
264
+ """
265
+ Create a pull request between two branches.
266
+ Not applicable for local repositories.
267
+
268
+ Args:
269
+ head_branch: Source branch for the PR.
270
+ base_branch: Target branch for the PR.
271
+ title: PR title.
272
+ body: PR description.
273
+ draft: Whether to create as draft PR (default: False).
274
+ reviewers: List of reviewer usernames (optional).
275
+ assignees: List of assignee usernames (optional).
276
+ labels: List of label names (optional).
277
+
278
+ Returns:
279
+ Dict[str, Any]: Empty dict (PRs are platform-specific).
280
+
281
+ Raises:
282
+ NotImplementedError: Always, since PR creation is not supported for LocalFetcher.
283
+ """
284
+ raise NotImplementedError(
285
+ "Pull request creation is not supported for local repositories (LocalFetcher)."
286
+ )
287
+
288
+ def get_authors(self, repo_names: List[str]) -> List[Dict[str, str]]:
289
+ """
290
+ Retrieve unique authors from the local repository using git log.
291
+
292
+ Args:
293
+ repo_names: Not used for local fetcher (single repo only).
294
+
295
+ Returns:
296
+ List[Dict[str, str]]: List of unique author dictionaries with name and email.
297
+ """
298
+ authors_set = set()
299
+
300
+ try:
301
+ # Get authors from commit history
302
+ cmd = [
303
+ 'git', '-C', self.repo_path, 'log',
304
+ '--all',
305
+ '--format=%an|%ae'
306
+ ]
307
+
308
+ result = subprocess.run(
309
+ cmd,
310
+ capture_output=True,
311
+ text=True,
312
+ check=True
313
+ )
314
+
315
+ for line in result.stdout.strip().split('\n'):
316
+ if '|' in line:
317
+ name, email = line.split('|', 1)
318
+ authors_set.add((name.strip(), email.strip()))
319
+
320
+ # Also get committers
321
+ cmd_committer = [
322
+ 'git', '-C', self.repo_path, 'log',
323
+ '--all',
324
+ '--format=%cn|%ce'
325
+ ]
326
+
327
+ result_committer = subprocess.run(
328
+ cmd_committer,
329
+ capture_output=True,
330
+ text=True,
331
+ check=True
332
+ )
333
+
334
+ for line in result_committer.stdout.strip().split('\n'):
335
+ if '|' in line:
336
+ name, email = line.split('|', 1)
337
+ authors_set.add((name.strip(), email.strip()))
338
+
339
+ authors_list = [
340
+ {"name": name, "email": email}
341
+ for name, email in sorted(authors_set)
342
+ ]
343
+
344
+ return authors_list
345
+
346
+ except subprocess.CalledProcessError as e:
347
+ print(f"Git command failed: {e}")
348
+ return []
349
+ except Exception as e:
350
+ print(f"Error in get_authors: {e}")
351
+ return []
352
+
353
+ def get_current_author(self) -> Optional[Dict[str, str]]:
354
+ """
355
+ Retrieve the current git user's information from local configuration.
356
+
357
+ Returns:
358
+ Optional[Dict[str, str]]: Dictionary with 'name' and 'email' keys,
359
+ or None if not configured.
360
+ """
361
+ try:
362
+ # Get user name
363
+ result_name = subprocess.run(
364
+ ["git", "-C", self.repo_path, "config", "user.name"],
365
+ capture_output=True,
366
+ text=True,
367
+ check=True
368
+ )
369
+ user_name = result_name.stdout.strip()
370
+
371
+ # Get user email
372
+ result_email = subprocess.run(
373
+ ["git", "-C", self.repo_path, "config", "user.email"],
374
+ capture_output=True,
375
+ text=True,
376
+ check=True
377
+ )
378
+ user_email = result_email.stdout.strip()
379
+
380
+ if user_name and user_email:
381
+ return {
382
+ "name": user_name,
383
+ "email": user_email
384
+ }
385
+ return None
386
+ except subprocess.CalledProcessError:
387
+ return None
388
+ except Exception as e:
389
+ print(f"Error retrieving current author: {e}")
390
+ return None
@@ -2,7 +2,6 @@ import os
2
2
  import re
3
3
  import shutil
4
4
  import subprocess
5
- from pathlib import Path
6
5
  import tempfile
7
6
  from typing import List, Dict, Any, Optional
8
7
  from datetime import datetime
@@ -36,7 +35,7 @@ class URLFetcher(BaseFetcher):
36
35
  )
37
36
  self.url = self._normalize_url(url)
38
37
  self.temp_dir = None
39
- # self._validate_url()
38
+ self.repo_path = None
40
39
  self._clone_repo()
41
40
 
42
41
  def _normalize_url(self, url: str) -> str:
@@ -59,7 +58,7 @@ class URLFetcher(BaseFetcher):
59
58
  capture_output=True,
60
59
  text=True,
61
60
  check=True,
62
- timeout=10 # Add timeout to prevent hanging
61
+ timeout=10
63
62
  )
64
63
  if not result.stdout.strip():
65
64
  raise ValueError(f"URL {self.url} points to an empty repository")
@@ -71,8 +70,8 @@ class URLFetcher(BaseFetcher):
71
70
  def _clone_repo(self) -> None:
72
71
  """Clone the repository to a temporary directory with all branches."""
73
72
  self.temp_dir = tempfile.mkdtemp(prefix="gitrecap_")
73
+ self.repo_path = self.temp_dir
74
74
  try:
75
- # First clone with --no-checkout to save bandwidth
76
75
  subprocess.run(
77
76
  ["git", "clone", "--no-checkout", self.url, self.temp_dir],
78
77
  check=True,
@@ -81,7 +80,6 @@ class URLFetcher(BaseFetcher):
81
80
  timeout=300
82
81
  )
83
82
 
84
- # Fetch all branches
85
83
  subprocess.run(
86
84
  ["git", "-C", self.temp_dir, "fetch", "--all"],
87
85
  check=True,
@@ -90,7 +88,6 @@ class URLFetcher(BaseFetcher):
90
88
  timeout=300
91
89
  )
92
90
 
93
- # Verify the cloned repository has at least one commit
94
91
  verify_result = subprocess.run(
95
92
  ["git", "-C", self.temp_dir, "rev-list", "--count", "--all"],
96
93
  capture_output=True,
@@ -138,7 +135,6 @@ class URLFetcher(BaseFetcher):
138
135
  check=True
139
136
  )
140
137
  branches = [b.strip() for b in result.stdout.splitlines() if b.strip()]
141
- # Filter out HEAD reference if present
142
138
  return [b for b in branches if not b.endswith('/HEAD')]
143
139
  except subprocess.CalledProcessError:
144
140
  return []
@@ -154,7 +150,7 @@ class URLFetcher(BaseFetcher):
154
150
  "log",
155
151
  "--pretty=format:%H|%an|%ad|%s",
156
152
  "--date=iso",
157
- "--all" # Include all branches and tags
153
+ "--all"
158
154
  ]
159
155
 
160
156
  if self.start_date:
@@ -173,7 +169,7 @@ class URLFetcher(BaseFetcher):
173
169
  capture_output=True,
174
170
  text=True,
175
171
  check=True,
176
- timeout=120 # Increased timeout for large repositories
172
+ timeout=120
177
173
  )
178
174
  return self._parse_git_log(result.stdout)
179
175
  except subprocess.TimeoutExpired:
@@ -206,7 +202,7 @@ class URLFetcher(BaseFetcher):
206
202
  "timestamp": timestamp
207
203
  })
208
204
  except ValueError:
209
- continue # Skip malformed log entries
205
+ continue
210
206
 
211
207
  return entries
212
208
 
@@ -229,16 +225,153 @@ class URLFetcher(BaseFetcher):
229
225
  Raises:
230
226
  NotImplementedError: Always, since release fetching is not supported for URLFetcher.
231
227
  """
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
228
  raise NotImplementedError("Release fetching is not supported for generic Git URLs (URLFetcher).")
235
229
 
230
+ def get_branches(self) -> List[str]:
231
+ """
232
+ Get all branches in the repository.
233
+
234
+ Returns:
235
+ List[str]: List of branch names.
236
+
237
+ Raises:
238
+ NotImplementedError: Always, since branch listing is not yet implemented for URLFetcher.
239
+ """
240
+ raise NotImplementedError("Branch listing is not yet implemented for generic Git URLs (URLFetcher).")
241
+
242
+ def get_valid_target_branches(self, source_branch: str) -> List[str]:
243
+ """
244
+ Get branches that can receive a pull request from the source branch.
245
+
246
+ Args:
247
+ source_branch (str): The source branch name.
248
+
249
+ Returns:
250
+ List[str]: List of valid target branch names.
251
+
252
+ Raises:
253
+ NotImplementedError: Always, since PR target validation is not supported for URLFetcher.
254
+ """
255
+ raise NotImplementedError("Pull request target branch validation is not supported for generic Git URLs (URLFetcher).")
256
+
257
+ def create_pull_request(
258
+ self,
259
+ head_branch: str,
260
+ base_branch: str,
261
+ title: str,
262
+ body: str,
263
+ draft: bool = False,
264
+ reviewers: Optional[List[str]] = None,
265
+ assignees: Optional[List[str]] = None,
266
+ labels: Optional[List[str]] = None
267
+ ) -> Dict[str, Any]:
268
+ """
269
+ Create a pull request between two branches.
270
+
271
+ Args:
272
+ head_branch: Source branch for the PR.
273
+ base_branch: Target branch for the PR.
274
+ title: PR title.
275
+ body: PR description.
276
+ draft: Whether to create as draft PR (default: False).
277
+ reviewers: List of reviewer usernames (optional).
278
+ assignees: List of assignee usernames (optional).
279
+ labels: List of label names (optional).
280
+
281
+ Returns:
282
+ Dict[str, Any]: Dictionary containing PR metadata or error information.
283
+
284
+ Raises:
285
+ NotImplementedError: Always, since PR creation is not supported for URLFetcher.
286
+ """
287
+ raise NotImplementedError("Pull request creation is not supported for generic Git URLs (URLFetcher).")
288
+
289
+ def get_authors(self, repo_names: List[str]) -> List[Dict[str, str]]:
290
+ """
291
+ Retrieve unique authors from cloned repository using git log.
292
+
293
+ Args:
294
+ repo_names: Not used for URL fetcher (single repo only).
295
+
296
+ Returns:
297
+ List of unique author dictionaries with name and email.
298
+ """
299
+ authors_set = set()
300
+
301
+ try:
302
+ if not hasattr(self, 'repo_path') or not os.path.exists(self.repo_path):
303
+ print("Repository not cloned yet")
304
+ return []
305
+
306
+ cmd = [
307
+ 'git', '-C', self.repo_path, 'log',
308
+ '--all',
309
+ '--format=%an|%ae'
310
+ ]
311
+
312
+ result = subprocess.run(
313
+ cmd,
314
+ capture_output=True,
315
+ text=True,
316
+ check=True
317
+ )
318
+
319
+ for line in result.stdout.strip().split('\n'):
320
+ if '|' in line:
321
+ name, email = line.split('|', 1)
322
+ authors_set.add((name.strip(), email.strip()))
323
+
324
+ cmd_committer = [
325
+ 'git', '-C', self.repo_path, 'log',
326
+ '--all',
327
+ '--format=%cn|%ce'
328
+ ]
329
+
330
+ result_committer = subprocess.run(
331
+ cmd_committer,
332
+ capture_output=True,
333
+ text=True,
334
+ check=True
335
+ )
336
+
337
+ for line in result_committer.stdout.strip().split('\n'):
338
+ if '|' in line:
339
+ name, email = line.split('|', 1)
340
+ authors_set.add((name.strip(), email.strip()))
341
+
342
+ authors_list = [
343
+ {"name": name, "email": email}
344
+ for name, email in sorted(authors_set)
345
+ ]
346
+
347
+ return authors_list
348
+
349
+ except subprocess.CalledProcessError as e:
350
+ print(f"Git command failed: {e}")
351
+ return []
352
+ except Exception as e:
353
+ print(f"Error in get_authors: {e}")
354
+ return []
355
+
356
+ def get_current_author(self) -> Optional[Dict[str, str]]:
357
+ """
358
+ Retrieve the current authenticated user's information.
359
+
360
+ For URL-based cloning, there is no authenticated user context,
361
+ so this method always returns None.
362
+
363
+ Returns:
364
+ None: URL fetcher has no default author.
365
+ """
366
+ return None
367
+
236
368
  def clear(self) -> None:
237
369
  """Clean up temporary directory."""
238
370
  if self.temp_dir and os.path.exists(self.temp_dir):
239
371
  try:
240
372
  shutil.rmtree(self.temp_dir, ignore_errors=True)
241
373
  except Exception:
242
- pass # Ensure we don't raise during cleanup
374
+ pass
243
375
  finally:
244
- self.temp_dir = None
376
+ self.temp_dir = None
377
+ self.repo_path = None
@@ -1,25 +1,30 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: git-recap
3
- Version: 0.1.4
3
+ Version: 0.1.6
4
4
  Summary: A modular Python tool that aggregates and formats user-authored messages from repositories.
5
- Author: Bruno V.
6
- Author-email: bruno.vitorino@tecnico.ulisboa.pt
5
+ Author-email: "Bruno V." <bruno.vitorino@tecnico.ulisboa.pt>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/BrunoV21/GitRecap
8
+ Project-URL: Documentation, https://github.com/BrunoV21/GitRecap#readme
9
+ Project-URL: Repository, https://github.com/BrunoV21/GitRecap.git
10
+ Project-URL: Issues, https://github.com/BrunoV21/GitRecap/issues
11
+ Keywords: git,github,gitlab,azure-devops,version-control,repository
7
12
  Classifier: Programming Language :: Python :: 3
8
13
  Classifier: License :: OSI Approved :: MIT License
9
14
  Classifier: Operating System :: OS Independent
15
+ Requires-Python: >=3.10
10
16
  Description-Content-Type: text/markdown
11
17
  License-File: LICENSE
12
18
  Requires-Dist: PyGithub==2.6.1
13
19
  Requires-Dist: azure-devops==7.1.0b4
14
20
  Requires-Dist: python-gitlab==5.6.0
15
- Dynamic: author
16
- Dynamic: author-email
17
- Dynamic: classifier
18
- Dynamic: description
19
- Dynamic: description-content-type
21
+ Provides-Extra: dev
22
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
23
+ Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
24
+ Requires-Dist: black>=22.0.0; extra == "dev"
25
+ Requires-Dist: flake8>=5.0.0; extra == "dev"
26
+ Requires-Dist: mypy>=0.990; extra == "dev"
20
27
  Dynamic: license-file
21
- Dynamic: requires-dist
22
- Dynamic: summary
23
28
 
24
29
  <a href="https://www.uneed.best/tool/gitrecap">
25
30
  <img src="https://www.uneed.best/POTD2A.png" style="width: 250px;" alt="Uneed POTD2 Badge" />
@@ -0,0 +1,17 @@
1
+ git_recap/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ git_recap/cli.py,sha256=oWSHWiIW1I6XyxyzDRVyMukCKs467KaIgDJzg40IsAg,8530
3
+ git_recap/fetcher.py,sha256=7_EZ3Af5jP_dldPbGrgpT-Gzmc1gg1NDxY2TfRuAnyc,3552
4
+ git_recap/utils.py,sha256=NAG0cvm1sYKEQD5E9PueduB3CZQRTahrioxZNgwwmi4,5481
5
+ git_recap/providers/__init__.py,sha256=pGAdkLeklLMD8feL7gZvEeHvsSvZlGpezbPOPKsqH3o,409
6
+ git_recap/providers/azure_fetcher.py,sha256=_hAgt1Za-uGkRuve7-FKq_bQ9-nAlLexD0GsgTBl_1k,14675
7
+ git_recap/providers/base_fetcher.py,sha256=ZANa-vdSpI_wDQ2U0QillSx6V4ljqxuFBn9bjSqq9bg,8633
8
+ git_recap/providers/github_fetcher.py,sha256=n87yYlYmsUyi3O0usqXyYP4ZJ-x3FFE-o9e_tLjDGv0,21638
9
+ git_recap/providers/gitlab_fetcher.py,sha256=IHC4CE3E_0ri2AhS7a5DPesOrSl5YNcP_hYBHzbIZGo,12376
10
+ git_recap/providers/local_fetcher.py,sha256=oCeddwzE7cJzMLCPWCOFRkNqvH45EM2KxxsOg3W5LME,12781
11
+ git_recap/providers/url_fetcher.py,sha256=pSd2PSeYpPsHdws6LsQ3ruZdDd9rz5LN6U7dxF_eHLU,12939
12
+ git_recap-0.1.6.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
13
+ git_recap-0.1.6.dist-info/METADATA,sha256=jXU579yPa9QJHb0s0dII9P35FxYI7tkgmUetuGkAZF8,5404
14
+ git_recap-0.1.6.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
15
+ git_recap-0.1.6.dist-info/entry_points.txt,sha256=28MZTffgA2q41JRbRHe1TQ-u1XtsyJK021ThKbp0bSU,49
16
+ git_recap-0.1.6.dist-info/top_level.txt,sha256=1JUKd3WPB8c3LcD1deIW-1UTmYzA0zJqwugAz72YZ_o,10
17
+ git_recap-0.1.6.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5