git-recap 0.1.5__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.
@@ -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
 
@@ -290,12 +286,92 @@ class URLFetcher(BaseFetcher):
290
286
  """
291
287
  raise NotImplementedError("Pull request creation is not supported for generic Git URLs (URLFetcher).")
292
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
+
293
368
  def clear(self) -> None:
294
369
  """Clean up temporary directory."""
295
370
  if self.temp_dir and os.path.exists(self.temp_dir):
296
371
  try:
297
372
  shutil.rmtree(self.temp_dir, ignore_errors=True)
298
373
  except Exception:
299
- pass # Ensure we don't raise during cleanup
374
+ pass
300
375
  finally:
301
- 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.5
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
 
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ git-recap = git_recap.cli:main
@@ -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=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,,