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.
- gitwise/__init__.py +11 -0
- gitwise/__main__.py +113 -0
- gitwise/_cli_completions.py +88 -0
- gitwise/_cli_dispatch.py +469 -0
- gitwise/_cli_introspection.py +275 -0
- gitwise/_cli_parser.py +345 -0
- gitwise/_cli_setup_agents.py +439 -0
- gitwise/_i18n_data.json +1934 -0
- gitwise/_paths.py +22 -0
- gitwise/_runtime_config.py +246 -0
- gitwise/audit.py +338 -0
- gitwise/branches.py +183 -0
- gitwise/clean.py +197 -0
- gitwise/commit.py +142 -0
- gitwise/conflicts.py +112 -0
- gitwise/context.py +163 -0
- gitwise/design.py +383 -0
- gitwise/diff.py +309 -0
- gitwise/doctor.py +116 -0
- gitwise/git.py +254 -0
- gitwise/health.py +345 -0
- gitwise/i18n.py +99 -0
- gitwise/log.py +329 -0
- gitwise/merge.py +193 -0
- gitwise/optimize.py +212 -0
- gitwise/output.py +652 -0
- gitwise/pick.py +102 -0
- gitwise/pr.py +543 -0
- gitwise/py.typed +0 -0
- gitwise/schema.py +49 -0
- gitwise/setup.py +551 -0
- gitwise/setup_agents/__init__.py +36 -0
- gitwise/setup_agents/adapters/__init__.py +17 -0
- gitwise/setup_agents/adapters/aider.py +5 -0
- gitwise/setup_agents/adapters/base.py +5 -0
- gitwise/setup_agents/adapters/codex.py +5 -0
- gitwise/setup_agents/adapters/continue_adapter.py +5 -0
- gitwise/setup_agents/adapters/cursor.py +5 -0
- gitwise/setup_agents/adapters/opencode.py +5 -0
- gitwise/setup_agents/adapters/pi.py +5 -0
- gitwise/setup_agents/exec.py +449 -0
- gitwise/setup_agents/format.py +164 -0
- gitwise/setup_agents/plan.py +254 -0
- gitwise/setup_agents/plan_gitfiles.py +167 -0
- gitwise/setup_agents/plan_skills.py +256 -0
- gitwise/setup_agents/providers/__init__.py +96 -0
- gitwise/setup_agents/providers/aider.py +11 -0
- gitwise/setup_agents/providers/base.py +79 -0
- gitwise/setup_agents/providers/claude.py +408 -0
- gitwise/setup_agents/providers/codex.py +11 -0
- gitwise/setup_agents/providers/continue_adapter.py +11 -0
- gitwise/setup_agents/providers/cursor.py +11 -0
- gitwise/setup_agents/providers/opencode.py +11 -0
- gitwise/setup_agents/providers/pi.py +11 -0
- gitwise/setup_agents/state.py +141 -0
- gitwise/setup_agents/types.py +48 -0
- gitwise/share/agents/skills/git-audit/SKILL.md +25 -0
- gitwise/share/agents/skills/git-clean/SKILL.md +22 -0
- gitwise/share/agents/skills/git-optimize/SKILL.md +21 -0
- gitwise/share/aider/CONVENTIONS.md.template +8 -0
- gitwise/share/aider/aider.conf.yml.template +4 -0
- gitwise/share/claude/CLAUDE.md.template +9 -0
- gitwise/share/claude/rules/gitwise.md +16 -0
- gitwise/share/claude/settings.json.template +47 -0
- gitwise/share/claude/skills/git-audit/SKILL.md +25 -0
- gitwise/share/claude/skills/git-clean/SKILL.md +22 -0
- gitwise/share/claude/skills/git-optimize/SKILL.md +21 -0
- gitwise/share/codex/agents/gitwise.toml.template +18 -0
- gitwise/share/continue/rules/gitwise.md.template +14 -0
- gitwise/share/cursor/rules/gitwise.mdc.template +16 -0
- gitwise/share/git-config-modern.txt +48 -0
- gitwise/share/hooks/commit-msg +22 -0
- gitwise/share/hooks/pre-commit +19 -0
- gitwise/share/opencode/agents/gitwise.md.template +14 -0
- gitwise/share/pi/skills/gitwise.md.template +14 -0
- gitwise/share/schemas/v1/input/audit.json +40 -0
- gitwise/share/schemas/v1/input/branches.json +51 -0
- gitwise/share/schemas/v1/input/clean.json +52 -0
- gitwise/share/schemas/v1/input/commands.json +36 -0
- gitwise/share/schemas/v1/input/commit.json +63 -0
- gitwise/share/schemas/v1/input/completions.json +51 -0
- gitwise/share/schemas/v1/input/conflicts.json +46 -0
- gitwise/share/schemas/v1/input/context.json +36 -0
- gitwise/share/schemas/v1/input/diff.json +56 -0
- gitwise/share/schemas/v1/input/doctor.json +36 -0
- gitwise/share/schemas/v1/input/health.json +36 -0
- gitwise/share/schemas/v1/input/log.json +71 -0
- gitwise/share/schemas/v1/input/merge.json +63 -0
- gitwise/share/schemas/v1/input/optimize.json +44 -0
- gitwise/share/schemas/v1/input/pick.json +63 -0
- gitwise/share/schemas/v1/input/pr.json +51 -0
- gitwise/share/schemas/v1/input/schema.json +48 -0
- gitwise/share/schemas/v1/input/setup-agents.json +108 -0
- gitwise/share/schemas/v1/input/setup.json +55 -0
- gitwise/share/schemas/v1/input/show.json +46 -0
- gitwise/share/schemas/v1/input/snapshot.json +36 -0
- gitwise/share/schemas/v1/input/stash.json +68 -0
- gitwise/share/schemas/v1/input/status.json +36 -0
- gitwise/share/schemas/v1/input/suggest.json +36 -0
- gitwise/share/schemas/v1/input/summarize.json +44 -0
- gitwise/share/schemas/v1/input/sync.json +55 -0
- gitwise/share/schemas/v1/input/tag.json +73 -0
- gitwise/share/schemas/v1/input/undo.json +60 -0
- gitwise/share/schemas/v1/input/update.json +40 -0
- gitwise/share/schemas/v1/input/worktree.json +50 -0
- gitwise/show.py +118 -0
- gitwise/snapshot.py +110 -0
- gitwise/stash.py +188 -0
- gitwise/status.py +93 -0
- gitwise/suggest.py +148 -0
- gitwise/summarize.py +202 -0
- gitwise/sync.py +257 -0
- gitwise/tag.py +252 -0
- gitwise/undo.py +145 -0
- gitwise/update.py +42 -0
- gitwise/utils/__init__.py +1 -0
- gitwise/utils/git_output.py +51 -0
- gitwise/utils/json_envelope.py +58 -0
- gitwise/utils/parsing.py +34 -0
- gitwise/worktree.py +182 -0
- gitwise_cli-0.24.2.dist-info/METADATA +151 -0
- gitwise_cli-0.24.2.dist-info/RECORD +125 -0
- gitwise_cli-0.24.2.dist-info/WHEEL +4 -0
- gitwise_cli-0.24.2.dist-info/entry_points.txt +2 -0
- gitwise_cli-0.24.2.dist-info/licenses/LICENSE +21 -0
gitwise/__init__.py
ADDED
gitwise/__main__.py
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"""CLI entry point — argparse router for all gitwise subcommands."""
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
import time
|
|
5
|
+
|
|
6
|
+
from ._cli_dispatch import DISPATCH
|
|
7
|
+
from ._cli_introspection import extract_command_token, help_payload
|
|
8
|
+
from ._cli_parser import build_parser
|
|
9
|
+
from .i18n import t
|
|
10
|
+
from .output import print_dim, print_json, set_json_pretty
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _is_log_json_enabled() -> bool:
|
|
14
|
+
import os
|
|
15
|
+
|
|
16
|
+
return os.environ.get("GITWISE_LOG_JSON", "").lower() in ("1", "true")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _should_show_rich_traceback() -> bool:
|
|
20
|
+
return (not _is_log_json_enabled()) and sys.stderr.isatty()
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _install_rich_traceback() -> None:
|
|
24
|
+
if not _should_show_rich_traceback():
|
|
25
|
+
return
|
|
26
|
+
try:
|
|
27
|
+
import importlib
|
|
28
|
+
|
|
29
|
+
rich_traceback_install = importlib.import_module("rich.traceback").install
|
|
30
|
+
rich_traceback_install(show_locals=False)
|
|
31
|
+
except ImportError:
|
|
32
|
+
return
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def main() -> int:
|
|
36
|
+
import os
|
|
37
|
+
|
|
38
|
+
from ._runtime_config import reset_runtime_config
|
|
39
|
+
from .i18n import set_locale
|
|
40
|
+
|
|
41
|
+
_install_rich_traceback()
|
|
42
|
+
|
|
43
|
+
parser = build_parser()
|
|
44
|
+
raw_argv = sys.argv[1:]
|
|
45
|
+
wants_json_pretty = "--json-pretty" in raw_argv or "--pretty" in raw_argv
|
|
46
|
+
if wants_json_pretty:
|
|
47
|
+
set_json_pretty(True)
|
|
48
|
+
|
|
49
|
+
wants_json_help = ("--json" in raw_argv or wants_json_pretty) and (
|
|
50
|
+
"--help" in raw_argv or "-h" in raw_argv
|
|
51
|
+
)
|
|
52
|
+
if wants_json_help:
|
|
53
|
+
command = extract_command_token(raw_argv)
|
|
54
|
+
print_json(help_payload(parser, command))
|
|
55
|
+
return 0
|
|
56
|
+
|
|
57
|
+
args = parser.parse_args()
|
|
58
|
+
if args.json_pretty:
|
|
59
|
+
args.json = True
|
|
60
|
+
|
|
61
|
+
if args.command is None:
|
|
62
|
+
if args.json:
|
|
63
|
+
print_json(
|
|
64
|
+
{
|
|
65
|
+
**help_payload(parser),
|
|
66
|
+
"ok": False,
|
|
67
|
+
"error": "missing_command",
|
|
68
|
+
}
|
|
69
|
+
)
|
|
70
|
+
return 1
|
|
71
|
+
parser.print_usage(sys.stderr)
|
|
72
|
+
return 1
|
|
73
|
+
|
|
74
|
+
if args.theme and args.theme != "auto":
|
|
75
|
+
os.environ["GITWISE_THEME"] = args.theme
|
|
76
|
+
reset_runtime_config()
|
|
77
|
+
|
|
78
|
+
set_json_pretty(args.json_pretty)
|
|
79
|
+
|
|
80
|
+
if args.lang:
|
|
81
|
+
set_locale(args.lang)
|
|
82
|
+
|
|
83
|
+
start = time.monotonic()
|
|
84
|
+
|
|
85
|
+
handler = DISPATCH.get(args.command)
|
|
86
|
+
if handler is not None:
|
|
87
|
+
try:
|
|
88
|
+
ret = handler(args)
|
|
89
|
+
except KeyboardInterrupt:
|
|
90
|
+
ret = 130
|
|
91
|
+
except SystemExit:
|
|
92
|
+
raise
|
|
93
|
+
except Exception:
|
|
94
|
+
if _should_show_rich_traceback():
|
|
95
|
+
raise
|
|
96
|
+
from .output import error as _error
|
|
97
|
+
|
|
98
|
+
_error(t("unexpected_error"))
|
|
99
|
+
ret = 1
|
|
100
|
+
else:
|
|
101
|
+
parser.print_help(sys.stderr)
|
|
102
|
+
ret = 1
|
|
103
|
+
|
|
104
|
+
elapsed = time.monotonic() - start
|
|
105
|
+
as_json = getattr(args, "json", False)
|
|
106
|
+
if not as_json and elapsed > 0.2 and args.command not in ("doctor",):
|
|
107
|
+
print_dim(t("completed_in", elapsed=f"{elapsed:.1f}"))
|
|
108
|
+
|
|
109
|
+
return ret
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
if __name__ == "__main__":
|
|
113
|
+
sys.exit(main())
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"""Shell completions generation: bash, zsh, fish."""
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
|
|
5
|
+
from ._cli_introspection import _subparsers_action
|
|
6
|
+
from ._cli_parser import build_parser
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def build_completions_script(*, shell: str, prog: str) -> str:
|
|
10
|
+
parser = build_parser()
|
|
11
|
+
parser.prog = prog
|
|
12
|
+
|
|
13
|
+
if shell in ("bash", "zsh"):
|
|
14
|
+
import importlib
|
|
15
|
+
|
|
16
|
+
shtab_complete = importlib.import_module("shtab").complete
|
|
17
|
+
return shtab_complete(parser, shell=shell)
|
|
18
|
+
|
|
19
|
+
if shell == "fish":
|
|
20
|
+
return _build_fish_completions_script(parser=parser, prog=prog)
|
|
21
|
+
|
|
22
|
+
raise ValueError(f"unsupported shell: {shell}")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _fish_escape(text: str) -> str:
|
|
26
|
+
return text.replace("'", "\\'")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _build_fish_option_line(*, prog: str, condition: str, flag: str, help_text: str) -> str:
|
|
30
|
+
escaped_help = _fish_escape(help_text)
|
|
31
|
+
escaped_prog = _fish_escape(prog)
|
|
32
|
+
escaped_condition = _fish_escape(condition)
|
|
33
|
+
if flag.startswith("--"):
|
|
34
|
+
return (
|
|
35
|
+
f"complete -c '{escaped_prog}' -n \"{escaped_condition}\" "
|
|
36
|
+
f"-l {flag[2:]} -d '{escaped_help}'"
|
|
37
|
+
)
|
|
38
|
+
if flag.startswith("-") and len(flag) == 2:
|
|
39
|
+
return (
|
|
40
|
+
f"complete -c '{escaped_prog}' -n \"{escaped_condition}\" "
|
|
41
|
+
f"-s {flag[1:]} -d '{escaped_help}'"
|
|
42
|
+
)
|
|
43
|
+
return ""
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _build_fish_completions_script(*, parser: argparse.ArgumentParser, prog: str) -> str:
|
|
47
|
+
escaped_prog = _fish_escape(prog)
|
|
48
|
+
lines: list[str] = [f"# fish completion for {escaped_prog}"]
|
|
49
|
+
|
|
50
|
+
sub_action = _subparsers_action(parser)
|
|
51
|
+
command_names = sorted(sub_action.choices.keys()) if sub_action else []
|
|
52
|
+
|
|
53
|
+
if command_names:
|
|
54
|
+
joined = " ".join(command_names)
|
|
55
|
+
lines.append(
|
|
56
|
+
f"complete -c '{escaped_prog}' -f -n \"__fish_use_subcommand\" -a '{_fish_escape(joined)}'"
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
for action in parser._actions:
|
|
60
|
+
if action.dest == "help" or isinstance(action, argparse._SubParsersAction):
|
|
61
|
+
continue
|
|
62
|
+
for flag in action.option_strings:
|
|
63
|
+
line = _build_fish_option_line(
|
|
64
|
+
prog=prog,
|
|
65
|
+
condition="__fish_use_subcommand",
|
|
66
|
+
flag=flag,
|
|
67
|
+
help_text="" if action.help is argparse.SUPPRESS else (action.help or ""),
|
|
68
|
+
)
|
|
69
|
+
if line:
|
|
70
|
+
lines.append(line)
|
|
71
|
+
|
|
72
|
+
if sub_action is not None:
|
|
73
|
+
for command, command_parser in sorted(sub_action.choices.items()):
|
|
74
|
+
condition = f"__fish_seen_subcommand_from {command}"
|
|
75
|
+
for action in command_parser._actions:
|
|
76
|
+
if action.dest == "help" or isinstance(action, argparse._SubParsersAction):
|
|
77
|
+
continue
|
|
78
|
+
for flag in action.option_strings:
|
|
79
|
+
line = _build_fish_option_line(
|
|
80
|
+
prog=prog,
|
|
81
|
+
condition=condition,
|
|
82
|
+
flag=flag,
|
|
83
|
+
help_text="" if action.help is argparse.SUPPRESS else (action.help or ""),
|
|
84
|
+
)
|
|
85
|
+
if line:
|
|
86
|
+
lines.append(line)
|
|
87
|
+
|
|
88
|
+
return "\n".join(lines) + "\n"
|
gitwise/_cli_dispatch.py
ADDED
|
@@ -0,0 +1,469 @@
|
|
|
1
|
+
"""Command dispatchers: thin wrappers that delegate to subcommand modules."""
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
from collections.abc import Callable
|
|
5
|
+
|
|
6
|
+
from . import __version__
|
|
7
|
+
from ._cli_completions import build_completions_script
|
|
8
|
+
from ._cli_introspection import (
|
|
9
|
+
canonical_command_name,
|
|
10
|
+
commands_metadata,
|
|
11
|
+
resolve_command_parser,
|
|
12
|
+
)
|
|
13
|
+
from ._cli_parser import build_parser
|
|
14
|
+
from .i18n import t
|
|
15
|
+
from .output import print_json
|
|
16
|
+
from .utils.json_envelope import error_envelope
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _run_update(args: argparse.Namespace) -> int:
|
|
20
|
+
from .update import run_update
|
|
21
|
+
|
|
22
|
+
return run_update(dry_run=args.dry_run, as_json=args.json)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _run_doctor(args: argparse.Namespace) -> int:
|
|
26
|
+
from .doctor import run_doctor
|
|
27
|
+
|
|
28
|
+
return run_doctor(as_json=args.json)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _run_setup_agents(args: argparse.Namespace) -> int:
|
|
32
|
+
if getattr(args, "list_providers", False) or getattr(args, "list_adapters", False):
|
|
33
|
+
from .i18n import t as _t
|
|
34
|
+
from .setup_agents.providers import list_providers
|
|
35
|
+
|
|
36
|
+
adapter_list = list_providers()
|
|
37
|
+
if args.json:
|
|
38
|
+
print_json({"providers": adapter_list, "adapters": adapter_list})
|
|
39
|
+
else:
|
|
40
|
+
from .output import info
|
|
41
|
+
|
|
42
|
+
info(_t("providers_available", list=", ".join(adapter_list)))
|
|
43
|
+
return 0
|
|
44
|
+
|
|
45
|
+
providers: list[str] | None = args.providers
|
|
46
|
+
adapters_legacy_used = False
|
|
47
|
+
if args.adapters is not None:
|
|
48
|
+
adapters_legacy_used = True
|
|
49
|
+
providers = args.adapters if providers is None else providers + args.adapters
|
|
50
|
+
|
|
51
|
+
from ._cli_setup_agents import run_setup_agents
|
|
52
|
+
|
|
53
|
+
return run_setup_agents(
|
|
54
|
+
local=args.local,
|
|
55
|
+
no_skills=args.no_skills,
|
|
56
|
+
dry_run=args.dry_run,
|
|
57
|
+
yes=args.yes,
|
|
58
|
+
as_json=args.json,
|
|
59
|
+
no_symlinks=args.no_symlinks,
|
|
60
|
+
strict=args.strict,
|
|
61
|
+
replace_claude_with_symlink=args.replace_claude_with_symlink,
|
|
62
|
+
migrate_legacy_claude=args.migrate_legacy_claude,
|
|
63
|
+
frozen_time=args.frozen_time,
|
|
64
|
+
no_git_files=args.no_git_files,
|
|
65
|
+
providers=providers,
|
|
66
|
+
adapters_legacy_used=adapters_legacy_used,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _run_setup(args: argparse.Namespace) -> int:
|
|
71
|
+
from .setup import run_setup
|
|
72
|
+
|
|
73
|
+
return run_setup(
|
|
74
|
+
dry_run=args.dry_run,
|
|
75
|
+
yes=args.yes,
|
|
76
|
+
as_json=args.json,
|
|
77
|
+
hooks_mode=args.hooks_mode,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _run_audit(args: argparse.Namespace) -> int:
|
|
82
|
+
from .audit import run_audit
|
|
83
|
+
|
|
84
|
+
return run_audit(quick=args.quick, as_json=args.json)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def _run_summarize(args: argparse.Namespace) -> int:
|
|
88
|
+
from .summarize import run_summarize
|
|
89
|
+
|
|
90
|
+
return run_summarize(as_json=args.json, diff=args.diff, max_commits=args.max_commits)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _run_snapshot(args: argparse.Namespace) -> int:
|
|
94
|
+
from .snapshot import run_snapshot
|
|
95
|
+
|
|
96
|
+
return run_snapshot(as_json=args.json)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def _run_clean(args: argparse.Namespace) -> int:
|
|
100
|
+
from .clean import run_clean
|
|
101
|
+
|
|
102
|
+
return run_clean(
|
|
103
|
+
branches=args.branches,
|
|
104
|
+
refs=args.refs,
|
|
105
|
+
dry_run=args.dry_run,
|
|
106
|
+
yes=args.yes,
|
|
107
|
+
as_json=args.json,
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def _run_optimize(args: argparse.Namespace) -> int:
|
|
112
|
+
from .optimize import run_optimize
|
|
113
|
+
|
|
114
|
+
return run_optimize(dry_run=args.dry_run, yes=args.yes, as_json=args.json)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def _run_worktree(args: argparse.Namespace) -> int:
|
|
118
|
+
from .worktree import run_worktree
|
|
119
|
+
|
|
120
|
+
return run_worktree(
|
|
121
|
+
args.action, getattr(args, "branch", None), dry_run=args.dry_run, as_json=args.json
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def _run_diff(args: argparse.Namespace) -> int:
|
|
126
|
+
from .diff import run_diff
|
|
127
|
+
|
|
128
|
+
return run_diff(
|
|
129
|
+
staged=args.staged,
|
|
130
|
+
stat=args.stat,
|
|
131
|
+
name_only=args.name_only,
|
|
132
|
+
full=args.full,
|
|
133
|
+
as_json=args.json,
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def _run_log(args: argparse.Namespace) -> int:
|
|
138
|
+
from .log import run_log
|
|
139
|
+
|
|
140
|
+
return run_log(
|
|
141
|
+
as_json=args.json,
|
|
142
|
+
oneline=args.oneline,
|
|
143
|
+
graph=args.graph,
|
|
144
|
+
author=args.author,
|
|
145
|
+
grep=args.grep,
|
|
146
|
+
since=args.since,
|
|
147
|
+
until=args.until,
|
|
148
|
+
file=args.file,
|
|
149
|
+
max_count=args.max_count,
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def _run_show(args: argparse.Namespace) -> int:
|
|
154
|
+
from .show import run_show
|
|
155
|
+
|
|
156
|
+
return run_show(ref=args.ref, stat=args.stat, as_json=args.json)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def _run_commit(args: argparse.Namespace) -> int:
|
|
160
|
+
from .commit import run_commit
|
|
161
|
+
|
|
162
|
+
return run_commit(
|
|
163
|
+
message=args.message,
|
|
164
|
+
type=args.type,
|
|
165
|
+
scope=args.scope,
|
|
166
|
+
breaking=args.breaking,
|
|
167
|
+
amend=args.amend,
|
|
168
|
+
dry_run=args.dry_run,
|
|
169
|
+
as_json=args.json,
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def _run_branches(args: argparse.Namespace) -> int:
|
|
174
|
+
from .branches import run_branches
|
|
175
|
+
|
|
176
|
+
return run_branches(stale=args.stale, remote=args.remote, sort=args.sort, as_json=args.json)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def _run_sync(args: argparse.Namespace) -> int:
|
|
180
|
+
from .sync import run_sync
|
|
181
|
+
|
|
182
|
+
return run_sync(
|
|
183
|
+
pull=args.pull,
|
|
184
|
+
push=args.push,
|
|
185
|
+
remote=args.remote,
|
|
186
|
+
dry_run=args.dry_run,
|
|
187
|
+
as_json=args.json,
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def _run_pr(args: argparse.Namespace) -> int:
|
|
192
|
+
from .pr import run_pr
|
|
193
|
+
|
|
194
|
+
return run_pr(action=args.action, selector=args.selector, as_json=args.json)
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def _run_undo(args: argparse.Namespace) -> int:
|
|
198
|
+
from .undo import run_undo
|
|
199
|
+
|
|
200
|
+
return run_undo(
|
|
201
|
+
ref=args.ref,
|
|
202
|
+
soft=args.soft,
|
|
203
|
+
steps=args.steps,
|
|
204
|
+
dry_run=args.dry_run,
|
|
205
|
+
yes=args.yes,
|
|
206
|
+
as_json=args.json,
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def _run_context(args: argparse.Namespace) -> int:
|
|
211
|
+
from .context import run_context
|
|
212
|
+
|
|
213
|
+
return run_context(as_json=args.json)
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
def _run_health(args: argparse.Namespace) -> int:
|
|
217
|
+
from .health import run_health
|
|
218
|
+
|
|
219
|
+
return run_health(as_json=args.json)
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def _run_stash(args: argparse.Namespace) -> int:
|
|
223
|
+
from .stash import run_stash
|
|
224
|
+
|
|
225
|
+
return run_stash(
|
|
226
|
+
action=args.action,
|
|
227
|
+
index=args.index,
|
|
228
|
+
as_json=args.json,
|
|
229
|
+
yes=args.yes,
|
|
230
|
+
dry_run=args.dry_run,
|
|
231
|
+
patch=args.patch,
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def _run_tag(args: argparse.Namespace) -> int:
|
|
236
|
+
from .tag import run_tag
|
|
237
|
+
|
|
238
|
+
return run_tag(
|
|
239
|
+
action=args.action,
|
|
240
|
+
name=getattr(args, "name", None),
|
|
241
|
+
bump=args.bump,
|
|
242
|
+
message=args.message,
|
|
243
|
+
dry_run=args.dry_run,
|
|
244
|
+
yes=args.yes,
|
|
245
|
+
as_json=args.json,
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
def _run_merge(args: argparse.Namespace) -> int:
|
|
250
|
+
from .merge import run_merge
|
|
251
|
+
|
|
252
|
+
return run_merge(
|
|
253
|
+
args.branch,
|
|
254
|
+
rebase=args.rebase,
|
|
255
|
+
no_ff=args.no_ff,
|
|
256
|
+
dry_run=args.dry_run,
|
|
257
|
+
yes=args.yes,
|
|
258
|
+
as_json=args.json,
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def _run_conflicts(args: argparse.Namespace) -> int:
|
|
263
|
+
from .conflicts import run_conflicts
|
|
264
|
+
|
|
265
|
+
return run_conflicts(ours=args.ours, theirs=args.theirs, as_json=args.json)
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
def _run_suggest(args: argparse.Namespace) -> int:
|
|
269
|
+
from .suggest import run_suggest
|
|
270
|
+
|
|
271
|
+
return run_suggest(as_json=args.json)
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
def _run_pick(args: argparse.Namespace) -> int:
|
|
275
|
+
from .pick import run_pick
|
|
276
|
+
|
|
277
|
+
return run_pick(
|
|
278
|
+
args.refs,
|
|
279
|
+
revert=args.revert,
|
|
280
|
+
continue_=args.continue_,
|
|
281
|
+
abort=args.abort,
|
|
282
|
+
dry_run=args.dry_run,
|
|
283
|
+
as_json=args.json,
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
def _run_status(args: argparse.Namespace) -> int:
|
|
288
|
+
from .status import run_status
|
|
289
|
+
|
|
290
|
+
return run_status(as_json=args.json)
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
def _run_completions(args: argparse.Namespace) -> int:
|
|
294
|
+
shell = args.shell
|
|
295
|
+
prog = args.prog
|
|
296
|
+
try:
|
|
297
|
+
script = build_completions_script(shell=shell, prog=prog)
|
|
298
|
+
except ModuleNotFoundError:
|
|
299
|
+
from .output import error as _error
|
|
300
|
+
|
|
301
|
+
hint = t("missing_dependency_hint")
|
|
302
|
+
message = t("missing_dependency_completions_shtab")
|
|
303
|
+
if args.json:
|
|
304
|
+
print_json(error_envelope(error=message, code="missing_dependency", hint=hint))
|
|
305
|
+
else:
|
|
306
|
+
_error(message, hint=hint)
|
|
307
|
+
return 1
|
|
308
|
+
except RuntimeError as e:
|
|
309
|
+
message = str(e)
|
|
310
|
+
if args.json:
|
|
311
|
+
print_json(error_envelope(error=message, code="runtime_error"))
|
|
312
|
+
else:
|
|
313
|
+
from .output import error as _error
|
|
314
|
+
|
|
315
|
+
_error(message)
|
|
316
|
+
return 1
|
|
317
|
+
except ValueError:
|
|
318
|
+
message = t("completions_unsupported_shell", shell=shell)
|
|
319
|
+
if args.json:
|
|
320
|
+
print_json(error_envelope(error=message, code="unsupported_shell"))
|
|
321
|
+
else:
|
|
322
|
+
from .output import error as _error
|
|
323
|
+
|
|
324
|
+
_error(message)
|
|
325
|
+
return 1
|
|
326
|
+
|
|
327
|
+
if args.json:
|
|
328
|
+
print_json(
|
|
329
|
+
{
|
|
330
|
+
"v": 2,
|
|
331
|
+
"ok": True,
|
|
332
|
+
"kind": "completions",
|
|
333
|
+
"schema": "gitwise/completions/v1",
|
|
334
|
+
"version": __version__,
|
|
335
|
+
"shell": shell,
|
|
336
|
+
"prog": prog,
|
|
337
|
+
"script": script,
|
|
338
|
+
}
|
|
339
|
+
)
|
|
340
|
+
return 0
|
|
341
|
+
|
|
342
|
+
print(script)
|
|
343
|
+
return 0
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
def _run_commands(args: argparse.Namespace) -> int:
|
|
347
|
+
parser = build_parser()
|
|
348
|
+
commands = commands_metadata(parser)
|
|
349
|
+
payload = {
|
|
350
|
+
"v": 2,
|
|
351
|
+
"ok": True,
|
|
352
|
+
"kind": "commands",
|
|
353
|
+
"schema": "gitwise/commands/v1",
|
|
354
|
+
"version": __version__,
|
|
355
|
+
"commands": commands,
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
if args.json:
|
|
359
|
+
print_json(payload)
|
|
360
|
+
return 0
|
|
361
|
+
|
|
362
|
+
aliases_label = t("aliases_label")
|
|
363
|
+
for item in commands:
|
|
364
|
+
aliases_list = item["aliases"]
|
|
365
|
+
alias_text = (
|
|
366
|
+
f" ({aliases_label}: {', '.join(str(alias) for alias in aliases_list)})"
|
|
367
|
+
if aliases_list
|
|
368
|
+
else ""
|
|
369
|
+
)
|
|
370
|
+
print(f"{item['name']}: {item['help']}{alias_text}")
|
|
371
|
+
return 0
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
def _run_schema(args: argparse.Namespace) -> int:
|
|
375
|
+
from .schema import load_command_input_schema
|
|
376
|
+
|
|
377
|
+
parser = build_parser()
|
|
378
|
+
command_parser = resolve_command_parser(parser=parser, name=args.name)
|
|
379
|
+
if command_parser is None:
|
|
380
|
+
message = t("schema_unknown_command", name=args.name)
|
|
381
|
+
hint = t("schema_unknown_command_hint")
|
|
382
|
+
if args.json:
|
|
383
|
+
print_json(
|
|
384
|
+
error_envelope(
|
|
385
|
+
error=message,
|
|
386
|
+
code="unknown_command",
|
|
387
|
+
hint=hint,
|
|
388
|
+
schema="gitwise/schema/v1",
|
|
389
|
+
kind="schema",
|
|
390
|
+
)
|
|
391
|
+
)
|
|
392
|
+
else:
|
|
393
|
+
from .output import error as _error
|
|
394
|
+
|
|
395
|
+
_error(message, hint=hint)
|
|
396
|
+
return 1
|
|
397
|
+
|
|
398
|
+
name = canonical_command_name(command_parser)
|
|
399
|
+
schema = load_command_input_schema(command=name, version=args.version)
|
|
400
|
+
if schema is None:
|
|
401
|
+
message = t("schema_file_missing", command=name, version=args.version)
|
|
402
|
+
hint = t("schema_file_missing_hint")
|
|
403
|
+
if args.json:
|
|
404
|
+
print_json(
|
|
405
|
+
error_envelope(
|
|
406
|
+
error=message,
|
|
407
|
+
code="schema_not_found",
|
|
408
|
+
hint=hint,
|
|
409
|
+
schema="gitwise/schema/v1",
|
|
410
|
+
kind="schema",
|
|
411
|
+
)
|
|
412
|
+
)
|
|
413
|
+
else:
|
|
414
|
+
from .output import error as _error
|
|
415
|
+
|
|
416
|
+
_error(message, hint=hint)
|
|
417
|
+
return 1
|
|
418
|
+
|
|
419
|
+
payload = {
|
|
420
|
+
"v": 2,
|
|
421
|
+
"ok": True,
|
|
422
|
+
"kind": "schema",
|
|
423
|
+
"schema": "gitwise/schema/v1",
|
|
424
|
+
"version": __version__,
|
|
425
|
+
"schema_version": args.version,
|
|
426
|
+
"command": name,
|
|
427
|
+
"schema_kind": "cli_input",
|
|
428
|
+
"json_schema": schema,
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
print_json(payload)
|
|
432
|
+
return 0
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
DISPATCH: dict[str, Callable[[argparse.Namespace], int]] = {
|
|
436
|
+
"doctor": _run_doctor,
|
|
437
|
+
"setup-agents": _run_setup_agents,
|
|
438
|
+
"setup": _run_setup,
|
|
439
|
+
"audit": _run_audit,
|
|
440
|
+
"summarize": _run_summarize,
|
|
441
|
+
"snapshot": _run_snapshot,
|
|
442
|
+
"clean": _run_clean,
|
|
443
|
+
"branch-clean": _run_clean,
|
|
444
|
+
"optimize": _run_optimize,
|
|
445
|
+
"worktree": _run_worktree,
|
|
446
|
+
"diff": _run_diff,
|
|
447
|
+
"log": _run_log,
|
|
448
|
+
"show": _run_show,
|
|
449
|
+
"commit": _run_commit,
|
|
450
|
+
"branches": _run_branches,
|
|
451
|
+
"sync": _run_sync,
|
|
452
|
+
"pr": _run_pr,
|
|
453
|
+
"undo": _run_undo,
|
|
454
|
+
"context": _run_context,
|
|
455
|
+
"health": _run_health,
|
|
456
|
+
"stash": _run_stash,
|
|
457
|
+
"tag": _run_tag,
|
|
458
|
+
"merge": _run_merge,
|
|
459
|
+
"conflicts": _run_conflicts,
|
|
460
|
+
"suggest": _run_suggest,
|
|
461
|
+
"commit-suggest": _run_suggest,
|
|
462
|
+
"pick": _run_pick,
|
|
463
|
+
"cherry-pick": _run_pick,
|
|
464
|
+
"update": _run_update,
|
|
465
|
+
"status": _run_status,
|
|
466
|
+
"completions": _run_completions,
|
|
467
|
+
"commands": _run_commands,
|
|
468
|
+
"schema": _run_schema,
|
|
469
|
+
}
|