gitmole 0.6.2__tar.gz → 0.6.3__tar.gz

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.
Files changed (55) hide show
  1. {gitmole-0.6.2 → gitmole-0.6.3}/PKG-INFO +1 -1
  2. {gitmole-0.6.2 → gitmole-0.6.3}/gitmole/__init__.py +1 -1
  3. {gitmole-0.6.2 → gitmole-0.6.3}/gitmole/cli.py +13 -4
  4. {gitmole-0.6.2 → gitmole-0.6.3}/gitmole.egg-info/PKG-INFO +1 -1
  5. {gitmole-0.6.2 → gitmole-0.6.3}/tests/test_cli.py +30 -1
  6. {gitmole-0.6.2 → gitmole-0.6.3}/LICENSE +0 -0
  7. {gitmole-0.6.2 → gitmole-0.6.3}/README.md +0 -0
  8. {gitmole-0.6.2 → gitmole-0.6.3}/gitmole/__main__.py +0 -0
  9. {gitmole-0.6.2 → gitmole-0.6.3}/gitmole/backtest.py +0 -0
  10. {gitmole-0.6.2 → gitmole-0.6.3}/gitmole/banner.py +0 -0
  11. {gitmole-0.6.2 → gitmole-0.6.3}/gitmole/blame.py +0 -0
  12. {gitmole-0.6.2 → gitmole-0.6.3}/gitmole/clean.py +0 -0
  13. {gitmole-0.6.2 → gitmole-0.6.3}/gitmole/filetypes.py +0 -0
  14. {gitmole-0.6.2 → gitmole-0.6.3}/gitmole/findings.py +0 -0
  15. {gitmole-0.6.2 → gitmole-0.6.3}/gitmole/functions.py +0 -0
  16. {gitmole-0.6.2 → gitmole-0.6.3}/gitmole/hotspots.py +0 -0
  17. {gitmole-0.6.2 → gitmole-0.6.3}/gitmole/identity.py +0 -0
  18. {gitmole-0.6.2 → gitmole-0.6.3}/gitmole/knowledge.py +0 -0
  19. {gitmole-0.6.2 → gitmole-0.6.3}/gitmole/leaks.py +0 -0
  20. {gitmole-0.6.2 → gitmole-0.6.3}/gitmole/load.py +0 -0
  21. {gitmole-0.6.2 → gitmole-0.6.3}/gitmole/loss.py +0 -0
  22. {gitmole-0.6.2 → gitmole-0.6.3}/gitmole/maat.py +0 -0
  23. {gitmole-0.6.2 → gitmole-0.6.3}/gitmole/render.py +0 -0
  24. {gitmole-0.6.2 → gitmole-0.6.3}/gitmole/run.py +0 -0
  25. {gitmole-0.6.2 → gitmole-0.6.3}/gitmole/textfmt.py +0 -0
  26. {gitmole-0.6.2 → gitmole-0.6.3}/gitmole/trend.py +0 -0
  27. {gitmole-0.6.2 → gitmole-0.6.3}/gitmole/watch.py +0 -0
  28. {gitmole-0.6.2 → gitmole-0.6.3}/gitmole.egg-info/SOURCES.txt +0 -0
  29. {gitmole-0.6.2 → gitmole-0.6.3}/gitmole.egg-info/dependency_links.txt +0 -0
  30. {gitmole-0.6.2 → gitmole-0.6.3}/gitmole.egg-info/entry_points.txt +0 -0
  31. {gitmole-0.6.2 → gitmole-0.6.3}/gitmole.egg-info/requires.txt +0 -0
  32. {gitmole-0.6.2 → gitmole-0.6.3}/gitmole.egg-info/top_level.txt +0 -0
  33. {gitmole-0.6.2 → gitmole-0.6.3}/pyproject.toml +0 -0
  34. {gitmole-0.6.2 → gitmole-0.6.3}/setup.cfg +0 -0
  35. {gitmole-0.6.2 → gitmole-0.6.3}/tests/test_backtest.py +0 -0
  36. {gitmole-0.6.2 → gitmole-0.6.3}/tests/test_banner.py +0 -0
  37. {gitmole-0.6.2 → gitmole-0.6.3}/tests/test_blame.py +0 -0
  38. {gitmole-0.6.2 → gitmole-0.6.3}/tests/test_clean.py +0 -0
  39. {gitmole-0.6.2 → gitmole-0.6.3}/tests/test_filetypes.py +0 -0
  40. {gitmole-0.6.2 → gitmole-0.6.3}/tests/test_findings.py +0 -0
  41. {gitmole-0.6.2 → gitmole-0.6.3}/tests/test_functions.py +0 -0
  42. {gitmole-0.6.2 → gitmole-0.6.3}/tests/test_golden.py +0 -0
  43. {gitmole-0.6.2 → gitmole-0.6.3}/tests/test_hotspots.py +0 -0
  44. {gitmole-0.6.2 → gitmole-0.6.3}/tests/test_identity.py +0 -0
  45. {gitmole-0.6.2 → gitmole-0.6.3}/tests/test_knowledge.py +0 -0
  46. {gitmole-0.6.2 → gitmole-0.6.3}/tests/test_leaks.py +0 -0
  47. {gitmole-0.6.2 → gitmole-0.6.3}/tests/test_load.py +0 -0
  48. {gitmole-0.6.2 → gitmole-0.6.3}/tests/test_loss.py +0 -0
  49. {gitmole-0.6.2 → gitmole-0.6.3}/tests/test_maat.py +0 -0
  50. {gitmole-0.6.2 → gitmole-0.6.3}/tests/test_packaging.py +0 -0
  51. {gitmole-0.6.2 → gitmole-0.6.3}/tests/test_render.py +0 -0
  52. {gitmole-0.6.2 → gitmole-0.6.3}/tests/test_run.py +0 -0
  53. {gitmole-0.6.2 → gitmole-0.6.3}/tests/test_textfmt.py +0 -0
  54. {gitmole-0.6.2 → gitmole-0.6.3}/tests/test_trend.py +0 -0
  55. {gitmole-0.6.2 → gitmole-0.6.3}/tests/test_watch.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gitmole
3
- Version: 0.6.2
3
+ Version: 0.6.3
4
4
  Summary: Offline git repository analysis with a terminal report: hotspots, coupling, ownership, code age, secrets, repo health.
5
5
  License: MIT
6
6
  Project-URL: Homepage, https://github.com/antvinni/gitmole
@@ -1,3 +1,3 @@
1
1
  """gitmole: offline git repository analysis with a terminal report."""
2
2
 
3
- __version__ = "0.6.2"
3
+ __version__ = "0.6.3"
@@ -179,14 +179,23 @@ def _clean(args, console: Console, ask) -> int:
179
179
  """Handle --clean: list what gitmole left behind, ask once, remove. ask(prompt) returns the answer."""
180
180
  from . import clean, render
181
181
 
182
- found = clean.find(args.target or ".", clean.temp_dir())
182
+ tmp = clean.temp_dir()
183
+ found = clean.find(args.target or ".", tmp)
183
184
  if not found:
184
185
  console.print("nothing to clean")
185
186
  return 0
186
187
  total = sum(size for _, size, _ in found)
187
- rows = [(path, clean.human(size), time.strftime("%Y-%m-%d", time.localtime(mtime))) for path, size, mtime in found]
188
- sec = render._section("Left behind", [("directory", render.PATH), ("size", render.RIGHT), ("modified", {})], rows,
189
- caption=f"{_dirs(len(found))}, {clean.human(total)} in all")
188
+ columns = [("directory", {"no_wrap": True}), ("size", render.RIGHT), ("modified", {})]
189
+ clones = [r for r in found if os.path.dirname(r[0]) == tmp]
190
+ listed = found
191
+ if clones and not args.full:
192
+ # one row for the temp folder: the clones differ only in their random suffix; --full lists them all
193
+ label = f"{clean.TEMP_PREFIX}* ({len(clones)} temp clone{'s' if len(clones) > 1 else ''})"
194
+ listed = [(os.path.join(tmp, label), sum(s for _, s, _ in clones), max(m for _, _, m in clones))]
195
+ listed += [r for r in found if os.path.dirname(r[0]) != tmp]
196
+ rows = [(path, clean.human(size), time.strftime("%Y-%m-%d", time.localtime(mtime))) for path, size, mtime in listed]
197
+ rows = render._shorten(rows, console.width, columns) # middle-elided paths, one line per row; the last segment stays whole
198
+ sec = render._section("Left behind", columns, rows, caption=f"{_dirs(len(found))}, {clean.human(total)} in all")
190
199
  render.print_section(console, sec)
191
200
  console.print(Text(""))
192
201
  if not args.yes:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gitmole
3
- Version: 0.6.2
3
+ Version: 0.6.3
4
4
  Summary: Offline git repository analysis with a terminal report: hotspots, coupling, ownership, code age, secrets, repo health.
5
5
  License: MIT
6
6
  Project-URL: Homepage, https://github.com/antvinni/gitmole
@@ -634,13 +634,42 @@ class Clean(unittest.TestCase):
634
634
  self.assertEqual(rc, 0)
635
635
  self.assertIn("Left behind", text)
636
636
  self.assertIn("analysis-a", text)
637
- self.assertIn("gitmole-x", text)
637
+ self.assertIn("gitmole-* (1 temp clone)", text, "temp clones collapse to one row per temp folder")
638
+ self.assertNotIn("gitmole-x", text)
638
639
  self.assertEqual(len(asked), 1)
639
640
  self.assertIn("Delete 2 directories", asked[0])
640
641
  self.assertIn("kept", text)
641
642
  self.assertTrue(out_kept)
642
643
  self.assertTrue(tmp_kept)
643
644
 
645
+ def test_full_lists_every_temp_clone(self):
646
+ def go(work, tmp):
647
+ os.makedirs(os.path.join(tmp, "gitmole-x"))
648
+ os.makedirs(os.path.join(tmp, "gitmole-y"))
649
+ c = Console(file=io.StringIO(), width=120, record=True, force_terminal=True, color_system=None)
650
+ rc = cli.main(["--clean", work, "--full"], console=c, ask=lambda q: "n")
651
+ return rc, c.export_text()
652
+ rc, text = self._with_tmp(go)
653
+ self.assertEqual(rc, 0)
654
+ self.assertIn("gitmole-x", text)
655
+ self.assertIn("gitmole-y", text)
656
+ self.assertNotIn("temp clones", text)
657
+
658
+ def test_rows_stay_on_one_line_at_a_narrow_width(self):
659
+ def go(work, tmp):
660
+ deep = os.path.join(work, "some", "rather", "long", "chain", "of", "directories")
661
+ self._output(os.path.join(deep, "analysis-widgets"))
662
+ os.makedirs(os.path.join(tmp, "gitmole-x"))
663
+ c = Console(file=io.StringIO(), width=60, record=True, force_terminal=True, color_system=None)
664
+ rc = cli.main(["--clean", deep], console=c, ask=lambda q: "n")
665
+ return rc, c.export_text()
666
+ rc, text = self._with_tmp(go)
667
+ self.assertEqual(rc, 0)
668
+ rows = [line for line in text.splitlines() if line.strip().startswith("/")]
669
+ self.assertEqual(len(rows), 2, text)
670
+ self.assertTrue(any("analysis-widgets" in r and "…/" in r for r in rows), text)
671
+ self.assertTrue(all(" B " in r and "2026-" in r for r in rows), "each row carries its size and date on the same line:\n" + text)
672
+
644
673
  def test_yes_answer_removes_and_reports(self):
645
674
  def go(work, tmp):
646
675
  self._output(os.path.join(work, "analysis-a"))
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes