gitwise-cli 0.24.2__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.
Files changed (125) hide show
  1. gitwise/__init__.py +11 -0
  2. gitwise/__main__.py +113 -0
  3. gitwise/_cli_completions.py +88 -0
  4. gitwise/_cli_dispatch.py +469 -0
  5. gitwise/_cli_introspection.py +275 -0
  6. gitwise/_cli_parser.py +345 -0
  7. gitwise/_cli_setup_agents.py +439 -0
  8. gitwise/_i18n_data.json +1934 -0
  9. gitwise/_paths.py +22 -0
  10. gitwise/_runtime_config.py +246 -0
  11. gitwise/audit.py +338 -0
  12. gitwise/branches.py +183 -0
  13. gitwise/clean.py +197 -0
  14. gitwise/commit.py +142 -0
  15. gitwise/conflicts.py +112 -0
  16. gitwise/context.py +163 -0
  17. gitwise/design.py +383 -0
  18. gitwise/diff.py +309 -0
  19. gitwise/doctor.py +116 -0
  20. gitwise/git.py +254 -0
  21. gitwise/health.py +345 -0
  22. gitwise/i18n.py +99 -0
  23. gitwise/log.py +329 -0
  24. gitwise/merge.py +193 -0
  25. gitwise/optimize.py +212 -0
  26. gitwise/output.py +652 -0
  27. gitwise/pick.py +102 -0
  28. gitwise/pr.py +543 -0
  29. gitwise/py.typed +0 -0
  30. gitwise/schema.py +49 -0
  31. gitwise/setup.py +551 -0
  32. gitwise/setup_agents/__init__.py +36 -0
  33. gitwise/setup_agents/adapters/__init__.py +17 -0
  34. gitwise/setup_agents/adapters/aider.py +5 -0
  35. gitwise/setup_agents/adapters/base.py +5 -0
  36. gitwise/setup_agents/adapters/codex.py +5 -0
  37. gitwise/setup_agents/adapters/continue_adapter.py +5 -0
  38. gitwise/setup_agents/adapters/cursor.py +5 -0
  39. gitwise/setup_agents/adapters/opencode.py +5 -0
  40. gitwise/setup_agents/adapters/pi.py +5 -0
  41. gitwise/setup_agents/exec.py +449 -0
  42. gitwise/setup_agents/format.py +164 -0
  43. gitwise/setup_agents/plan.py +254 -0
  44. gitwise/setup_agents/plan_gitfiles.py +167 -0
  45. gitwise/setup_agents/plan_skills.py +256 -0
  46. gitwise/setup_agents/providers/__init__.py +96 -0
  47. gitwise/setup_agents/providers/aider.py +11 -0
  48. gitwise/setup_agents/providers/base.py +79 -0
  49. gitwise/setup_agents/providers/claude.py +408 -0
  50. gitwise/setup_agents/providers/codex.py +11 -0
  51. gitwise/setup_agents/providers/continue_adapter.py +11 -0
  52. gitwise/setup_agents/providers/cursor.py +11 -0
  53. gitwise/setup_agents/providers/opencode.py +11 -0
  54. gitwise/setup_agents/providers/pi.py +11 -0
  55. gitwise/setup_agents/state.py +141 -0
  56. gitwise/setup_agents/types.py +48 -0
  57. gitwise/share/agents/skills/git-audit/SKILL.md +25 -0
  58. gitwise/share/agents/skills/git-clean/SKILL.md +22 -0
  59. gitwise/share/agents/skills/git-optimize/SKILL.md +21 -0
  60. gitwise/share/aider/CONVENTIONS.md.template +8 -0
  61. gitwise/share/aider/aider.conf.yml.template +4 -0
  62. gitwise/share/claude/CLAUDE.md.template +9 -0
  63. gitwise/share/claude/rules/gitwise.md +16 -0
  64. gitwise/share/claude/settings.json.template +47 -0
  65. gitwise/share/claude/skills/git-audit/SKILL.md +25 -0
  66. gitwise/share/claude/skills/git-clean/SKILL.md +22 -0
  67. gitwise/share/claude/skills/git-optimize/SKILL.md +21 -0
  68. gitwise/share/codex/agents/gitwise.toml.template +18 -0
  69. gitwise/share/continue/rules/gitwise.md.template +14 -0
  70. gitwise/share/cursor/rules/gitwise.mdc.template +16 -0
  71. gitwise/share/git-config-modern.txt +48 -0
  72. gitwise/share/hooks/commit-msg +22 -0
  73. gitwise/share/hooks/pre-commit +19 -0
  74. gitwise/share/opencode/agents/gitwise.md.template +14 -0
  75. gitwise/share/pi/skills/gitwise.md.template +14 -0
  76. gitwise/share/schemas/v1/input/audit.json +40 -0
  77. gitwise/share/schemas/v1/input/branches.json +51 -0
  78. gitwise/share/schemas/v1/input/clean.json +52 -0
  79. gitwise/share/schemas/v1/input/commands.json +36 -0
  80. gitwise/share/schemas/v1/input/commit.json +63 -0
  81. gitwise/share/schemas/v1/input/completions.json +51 -0
  82. gitwise/share/schemas/v1/input/conflicts.json +46 -0
  83. gitwise/share/schemas/v1/input/context.json +36 -0
  84. gitwise/share/schemas/v1/input/diff.json +56 -0
  85. gitwise/share/schemas/v1/input/doctor.json +36 -0
  86. gitwise/share/schemas/v1/input/health.json +36 -0
  87. gitwise/share/schemas/v1/input/log.json +71 -0
  88. gitwise/share/schemas/v1/input/merge.json +63 -0
  89. gitwise/share/schemas/v1/input/optimize.json +44 -0
  90. gitwise/share/schemas/v1/input/pick.json +63 -0
  91. gitwise/share/schemas/v1/input/pr.json +51 -0
  92. gitwise/share/schemas/v1/input/schema.json +48 -0
  93. gitwise/share/schemas/v1/input/setup-agents.json +108 -0
  94. gitwise/share/schemas/v1/input/setup.json +55 -0
  95. gitwise/share/schemas/v1/input/show.json +46 -0
  96. gitwise/share/schemas/v1/input/snapshot.json +36 -0
  97. gitwise/share/schemas/v1/input/stash.json +68 -0
  98. gitwise/share/schemas/v1/input/status.json +36 -0
  99. gitwise/share/schemas/v1/input/suggest.json +36 -0
  100. gitwise/share/schemas/v1/input/summarize.json +44 -0
  101. gitwise/share/schemas/v1/input/sync.json +55 -0
  102. gitwise/share/schemas/v1/input/tag.json +73 -0
  103. gitwise/share/schemas/v1/input/undo.json +60 -0
  104. gitwise/share/schemas/v1/input/update.json +40 -0
  105. gitwise/share/schemas/v1/input/worktree.json +50 -0
  106. gitwise/show.py +118 -0
  107. gitwise/snapshot.py +110 -0
  108. gitwise/stash.py +188 -0
  109. gitwise/status.py +93 -0
  110. gitwise/suggest.py +148 -0
  111. gitwise/summarize.py +202 -0
  112. gitwise/sync.py +257 -0
  113. gitwise/tag.py +252 -0
  114. gitwise/undo.py +145 -0
  115. gitwise/update.py +42 -0
  116. gitwise/utils/__init__.py +1 -0
  117. gitwise/utils/git_output.py +51 -0
  118. gitwise/utils/json_envelope.py +58 -0
  119. gitwise/utils/parsing.py +34 -0
  120. gitwise/worktree.py +182 -0
  121. gitwise_cli-0.24.2.dist-info/METADATA +151 -0
  122. gitwise_cli-0.24.2.dist-info/RECORD +125 -0
  123. gitwise_cli-0.24.2.dist-info/WHEEL +4 -0
  124. gitwise_cli-0.24.2.dist-info/entry_points.txt +2 -0
  125. gitwise_cli-0.24.2.dist-info/licenses/LICENSE +21 -0
gitwise/optimize.py ADDED
@@ -0,0 +1,212 @@
1
+ """Git repo optimizations: commit-graph, repack, prune."""
2
+
3
+ import os
4
+ import subprocess
5
+ import time
6
+ from pathlib import Path
7
+
8
+ from .git import git_dir as get_git_dir
9
+ from .git import require_root
10
+ from .git import run as git_run
11
+ from .git import version as git_version
12
+ from .i18n import t
13
+ from .output import (
14
+ confirm,
15
+ debug,
16
+ ok,
17
+ print_blank,
18
+ print_dim,
19
+ print_header,
20
+ print_json,
21
+ print_section,
22
+ print_status_line,
23
+ status,
24
+ warn,
25
+ )
26
+ from .utils.json_envelope import error_envelope, ok_envelope
27
+
28
+
29
+ def _gc_is_running(cwd: Path) -> bool:
30
+ gd = get_git_dir(cwd)
31
+ if gd is None:
32
+ return False
33
+ pid_file = gd / "gc.pid"
34
+ if not pid_file.exists():
35
+ return False
36
+ try:
37
+ if (time.time() - pid_file.stat().st_mtime) > 86400:
38
+ return False
39
+ pid = int(pid_file.read_text().strip().splitlines()[0])
40
+ os.kill(pid, 0)
41
+ return True
42
+ except (ValueError, ProcessLookupError, PermissionError, OSError):
43
+ return False
44
+
45
+
46
+ def _repo_size_kb(cwd: Path) -> int:
47
+ gd = get_git_dir(cwd)
48
+ if gd is None:
49
+ return 0
50
+ try:
51
+ r = subprocess.run(
52
+ ["du", "-sk", str(gd)], capture_output=True, text=True, check=True, timeout=120
53
+ )
54
+ return int(r.stdout.split()[0])
55
+ except (subprocess.SubprocessError, ValueError, IndexError, FileNotFoundError):
56
+ return sum(f.stat().st_size for f in gd.rglob("*") if f.is_file()) // 1024
57
+
58
+
59
+ def _write_commit_graph(cwd: Path) -> bool:
60
+ args = ["commit-graph", "write", "--reachable"]
61
+ if git_version() >= (2, 31, 0):
62
+ args.append("--changed-paths")
63
+ r = git_run(args, cwd=cwd, check=False)
64
+ return r.returncode == 0
65
+
66
+
67
+ def _repack(cwd: Path) -> bool:
68
+ r = git_run(["repack", "-A", "-d", "--write-bitmap-index"], cwd=cwd, check=False)
69
+ if r.returncode != 0:
70
+ debug(t("repack_fallo_bitmap"))
71
+ r = git_run(["repack", "-A", "-d"], cwd=cwd, check=False)
72
+ return r.returncode == 0
73
+
74
+
75
+ def _prune(cwd: Path) -> bool:
76
+ return git_run(["prune"], cwd=cwd, check=False).returncode == 0
77
+
78
+
79
+ def _get_steps() -> list[tuple[str, str]]:
80
+ return [
81
+ ("commit-graph", t("step_commit_graph")),
82
+ ("repack", t("step_repack")),
83
+ ("prune", t("step_prune")),
84
+ ]
85
+
86
+
87
+ def run_optimize(*, dry_run: bool = False, yes: bool = False, as_json: bool = False) -> int:
88
+ root, err = require_root()
89
+ if err:
90
+ return err
91
+ if root is None:
92
+ return 1
93
+ cwd = root
94
+
95
+ if _gc_is_running(cwd):
96
+ warn(t("gc_already_running"))
97
+ return 1
98
+
99
+ steps = _get_steps()
100
+
101
+ if dry_run:
102
+ if as_json:
103
+ print_json(
104
+ ok_envelope(
105
+ payload={
106
+ "dry_run": True,
107
+ "applied": False,
108
+ "steps": [{"name": n, "desc": d} for n, d in steps],
109
+ }
110
+ )
111
+ )
112
+ return 0
113
+ print_header(t("optimizing", root=str(cwd)))
114
+ print_blank()
115
+ for _name, desc in steps:
116
+ print_status_line("›", desc, t("pending"), ok_flag=False)
117
+ print_blank()
118
+ print_dim(t("dry_run_no_exec"))
119
+ return 0
120
+
121
+ if as_json and not yes:
122
+ print_json(
123
+ error_envelope(
124
+ error=t("yes_required_with_json"),
125
+ code="yes_required",
126
+ hint=t("yes_required_hint"),
127
+ )
128
+ )
129
+ return 2
130
+
131
+ if not as_json:
132
+ print_header(t("optimizing", root=str(cwd)))
133
+ print_blank()
134
+ for _name, desc in steps:
135
+ print_status_line("›", desc, t("pending"), ok_flag=False)
136
+ print_blank()
137
+ if not yes:
138
+ if not confirm(t("confirm_optimize")):
139
+ print_dim(t("cancelled"))
140
+ return 0
141
+ print_blank()
142
+
143
+ size_before = _repo_size_kb(cwd)
144
+
145
+ if as_json:
146
+ graph_ok = _write_commit_graph(cwd)
147
+ repack_ok = _repack(cwd)
148
+ prune_ok = _prune(cwd)
149
+ else:
150
+ with status(t("status_optimize_commit_graph")):
151
+ graph_ok = _write_commit_graph(cwd)
152
+ if graph_ok:
153
+ ok(t("commit_graph_updated"))
154
+ else:
155
+ warn(t("commit_graph_failed"))
156
+
157
+ with status(t("status_optimize_repack")):
158
+ repack_ok = _repack(cwd)
159
+ if repack_ok:
160
+ ok(t("repack_complete"))
161
+ else:
162
+ warn(t("repack_failed"))
163
+
164
+ with status(t("status_optimize_prune")):
165
+ prune_ok = _prune(cwd)
166
+ if prune_ok:
167
+ ok(t("prune_complete"))
168
+ else:
169
+ warn(t("prune_not_critical"))
170
+
171
+ size_after = _repo_size_kb(cwd)
172
+ saved = size_before - size_after
173
+
174
+ if not graph_ok and not repack_ok:
175
+ rc = 1
176
+ elif not prune_ok:
177
+ rc = 2
178
+ else:
179
+ rc = 0
180
+
181
+ if as_json:
182
+ payload: dict[str, object] = {
183
+ "dry_run": False,
184
+ "applied": True,
185
+ "steps": [
186
+ {"name": "commit-graph", "desc": t("step_commit_graph"), "ok": graph_ok},
187
+ {"name": "repack", "desc": t("step_repack"), "ok": repack_ok},
188
+ {"name": "prune", "desc": t("step_prune"), "ok": prune_ok},
189
+ ],
190
+ "size_before_kb": size_before,
191
+ "size_after_kb": size_after,
192
+ "saved_kb": saved,
193
+ "rc": rc,
194
+ }
195
+ if rc == 0:
196
+ print_json(ok_envelope(payload=payload))
197
+ else:
198
+ print_json(
199
+ error_envelope(
200
+ error=t("optimize_partial_failure"),
201
+ code="optimize_partial_failure",
202
+ payload=payload,
203
+ )
204
+ )
205
+ else:
206
+ print_section(t("summary"))
207
+ if saved > 0:
208
+ ok(t("space_freed", saved=str(saved), before=str(size_before), after=str(size_after)))
209
+ else:
210
+ ok(t("repo_size", size=str(size_after)))
211
+
212
+ return rc