arctx-cli 0.2.0b2__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 (49) hide show
  1. arctx_cli/__init__.py +1 -0
  2. arctx_cli/alias.py +238 -0
  3. arctx_cli/append_batch.py +90 -0
  4. arctx_cli/commands/__init__.py +85 -0
  5. arctx_cli/commands/alias_cmd.py +174 -0
  6. arctx_cli/commands/anchor.py +82 -0
  7. arctx_cli/commands/current.py +69 -0
  8. arctx_cli/commands/cut.py +89 -0
  9. arctx_cli/commands/dump.py +72 -0
  10. arctx_cli/commands/ext.py +236 -0
  11. arctx_cli/commands/git.py +216 -0
  12. arctx_cli/commands/graph.py +73 -0
  13. arctx_cli/commands/guide.py +360 -0
  14. arctx_cli/commands/init.py +223 -0
  15. arctx_cli/commands/list.py +45 -0
  16. arctx_cli/commands/migrate.py +135 -0
  17. arctx_cli/commands/node.py +55 -0
  18. arctx_cli/commands/outcomes.py +58 -0
  19. arctx_cli/commands/payload.py +192 -0
  20. arctx_cli/commands/reachable.py +75 -0
  21. arctx_cli/commands/show.py +113 -0
  22. arctx_cli/commands/sync.py +244 -0
  23. arctx_cli/commands/trace.py +46 -0
  24. arctx_cli/commands/transition.py +212 -0
  25. arctx_cli/commands/use.py +67 -0
  26. arctx_cli/commands/view.py +82 -0
  27. arctx_cli/commands/work_session.py +330 -0
  28. arctx_cli/context.py +38 -0
  29. arctx_cli/ext/__init__.py +1 -0
  30. arctx_cli/ext/command/__init__.py +110 -0
  31. arctx_cli/ext/git/__init__.py +1 -0
  32. arctx_cli/ext/git/branch.py +140 -0
  33. arctx_cli/ext/git/cherry_pick.py +144 -0
  34. arctx_cli/ext/git/commit.py +205 -0
  35. arctx_cli/ext/git/hook.py +758 -0
  36. arctx_cli/ext/git/merge.py +204 -0
  37. arctx_cli/ext/git/reset.py +138 -0
  38. arctx_cli/ext/git/revert.py +157 -0
  39. arctx_cli/ext/git/verify.py +140 -0
  40. arctx_cli/ext/git/worktree.py +173 -0
  41. arctx_cli/ext_registry.py +34 -0
  42. arctx_cli/main.py +133 -0
  43. arctx_cli/paths.py +27 -0
  44. arctx_cli/payload_builder.py +23 -0
  45. arctx_cli/workspace.py +64 -0
  46. arctx_cli-0.2.0b2.dist-info/METADATA +48 -0
  47. arctx_cli-0.2.0b2.dist-info/RECORD +49 -0
  48. arctx_cli-0.2.0b2.dist-info/WHEEL +4 -0
  49. arctx_cli-0.2.0b2.dist-info/entry_points.txt +2 -0
@@ -0,0 +1,144 @@
1
+ """arctx CLI cherry-pick command.
2
+
3
+ Drives a ``git cherry-pick`` and records the corresponding arctx Transition with
4
+ BranchPayload, GitChangePayload, CherryPickPayload, BranchTipEvent, and
5
+ SessionPointerEvent.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import argparse
11
+ import json
12
+ import sys
13
+
14
+ from arctx_cli.append_batch import graph_counts, maybe_append_or_save
15
+ from arctx_cli.context import (
16
+ resolve_run_id_from_args,
17
+ resolve_store,
18
+ resolve_user_id_from_args,
19
+ resolve_work_session_id_from_args,
20
+ )
21
+
22
+
23
+ def add_parser(subparsers) -> argparse.ArgumentParser:
24
+ """Register the ``cherry-pick`` subcommand parser."""
25
+ p = subparsers.add_parser(
26
+ "cherry-pick",
27
+ help="Cherry-pick a commit and record a arctx transition",
28
+ )
29
+ p.add_argument("--sha", required=True, help="Commit sha to cherry-pick")
30
+ p.add_argument("--branch", default=None, help="Override branch name")
31
+ p.add_argument("--run", default=None, help="Explicit run id")
32
+ p.add_argument("--store-dir", default=None, help="Store directory")
33
+ p.add_argument("--user", default=None, help="User id for attribution")
34
+ p.add_argument("--work-session", default=None, help="Work session id")
35
+ return p
36
+
37
+
38
+ def run_cherry_pick_command(
39
+ *,
40
+ source_sha: str,
41
+ branch: str | None,
42
+ run_id: str | None,
43
+ store_dir: str | None,
44
+ user_id: str | None,
45
+ work_session_id: str | None,
46
+ ) -> dict:
47
+ """Execute a cherry-pick and persist the resulting graph records.
48
+
49
+ Parameters
50
+ ----------
51
+ source_sha:
52
+ Commit SHA to cherry-pick.
53
+ branch:
54
+ Branch name override.
55
+ run_id:
56
+ Explicit run id.
57
+ store_dir:
58
+ Store directory.
59
+ user_id:
60
+ User id for work event attribution.
61
+ work_session_id:
62
+ Work session id.
63
+
64
+ Returns
65
+ -------
66
+ dict with transition_id, output_node_id, branch, head_commit,
67
+ source_transition, source_commit.
68
+ """
69
+ store = resolve_store(store_dir)
70
+ handle = store.load_run(run_id)
71
+
72
+ before = graph_counts(handle)
73
+
74
+ transition = handle.git.cherry_pick(
75
+ source_sha=source_sha,
76
+ branch=branch,
77
+ user_id=user_id,
78
+ work_session_id=work_session_id,
79
+ )
80
+
81
+ maybe_append_or_save(
82
+ store=store,
83
+ handle=handle,
84
+ user_id=user_id,
85
+ work_session_id=work_session_id,
86
+ before=before,
87
+ )
88
+
89
+ # Extract payload info for the result.
90
+ git_payloads = handle.run_graph.payloads_for_transition(
91
+ transition.transition_id, payload_type="git_change"
92
+ )
93
+ head_commit = git_payloads[-1].head_commit if git_payloads else ""
94
+ branch_payloads = handle.run_graph.payloads_for_transition(
95
+ transition.transition_id, payload_type="branch"
96
+ )
97
+ resolved_branch = branch_payloads[-1].branch if branch_payloads else ""
98
+ cp_payloads = handle.run_graph.payloads_for_transition(
99
+ transition.transition_id, payload_type="cherry_pick"
100
+ )
101
+ source_transition = cp_payloads[-1].source_transition if cp_payloads else None
102
+ source_commit = cp_payloads[-1].source_commit if cp_payloads else ""
103
+
104
+ return {
105
+ "transition_id": transition.transition_id,
106
+ "output_node_id": transition.output_node_id,
107
+ "branch": resolved_branch,
108
+ "head_commit": head_commit,
109
+ "source_transition": source_transition,
110
+ "source_commit": source_commit,
111
+ }
112
+
113
+
114
+ def cli_cherry_pick(args) -> int:
115
+ """Entry point for ``arctx cherry-pick`` subcommand."""
116
+ from arctx.ext.git.verbs._forward_transition import ParallelSessionConflict # noqa: PLC0415
117
+
118
+ run_id = resolve_run_id_from_args(args)
119
+ user_id = resolve_user_id_from_args(args)
120
+ work_session_id = resolve_work_session_id_from_args(args)
121
+
122
+ try:
123
+ result = run_cherry_pick_command(
124
+ source_sha=args.sha,
125
+ branch=args.branch,
126
+ run_id=run_id,
127
+ store_dir=args.store_dir,
128
+ user_id=user_id,
129
+ work_session_id=work_session_id,
130
+ )
131
+ except ParallelSessionConflict as exc:
132
+ print(f"error: {exc}", file=sys.stderr)
133
+ print(
134
+ "hint: another session has advanced this branch. "
135
+ "Rebase / pull before committing.",
136
+ file=sys.stderr,
137
+ )
138
+ return 2
139
+ except Exception as exc: # noqa: BLE001
140
+ print(f"error: {exc}", file=sys.stderr)
141
+ return 1
142
+
143
+ print(json.dumps(result, indent=2))
144
+ return 0
@@ -0,0 +1,205 @@
1
+ """arctx CLI commit command.
2
+
3
+ Drives a git commit and records the corresponding arctx Transition with
4
+ BranchPayload, GitChangePayload, BranchTipEvent, and SessionPointerEvent.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import argparse
10
+ import json
11
+ import sys
12
+
13
+ from arctx_cli.append_batch import graph_counts, maybe_append_or_save
14
+ from arctx_cli.context import (
15
+ resolve_run_id_from_args,
16
+ resolve_store,
17
+ resolve_user_id_from_args,
18
+ resolve_work_session_id_from_args,
19
+ )
20
+
21
+
22
+ def add_parser(subparsers) -> argparse.ArgumentParser:
23
+ """Register the ``commit`` subcommand parser."""
24
+ p = subparsers.add_parser(
25
+ "commit",
26
+ help="Drive a git commit and record a arctx transition",
27
+ )
28
+ p.add_argument("-m", "--message", required=True, help="Commit message")
29
+ p.add_argument(
30
+ "--branch",
31
+ default=None,
32
+ help="Override branch name (default: current git branch)",
33
+ )
34
+ p.add_argument(
35
+ "--merge",
36
+ default=None,
37
+ metavar="REF",
38
+ help=(
39
+ "Merge target. Format: 'branch:<name>', 'node:<id>', or just '<name>' "
40
+ "(auto-detected as branch name). Drives git merge and records a "
41
+ "multi-input transition with MergePayload."
42
+ ),
43
+ )
44
+ p.add_argument(
45
+ "--join",
46
+ action="store_true",
47
+ help=(
48
+ "Treat the merge as a arctx-only join (no common ancestor). "
49
+ "Records JoinPayload instead of MergePayload. Only valid with --merge."
50
+ ),
51
+ )
52
+ p.add_argument("--run", default=None, help="Explicit run id")
53
+ p.add_argument("--store-dir", default=None, help="Store directory")
54
+ p.add_argument("--user", default=None, help="User id for attribution")
55
+ p.add_argument("--work-session", default=None, help="Work session id")
56
+ return p
57
+
58
+
59
+ def _parse_merge_ref(ref: str) -> tuple[str | None, str | None]:
60
+ """Parse a merge ref string into (other_branch, other_node_id).
61
+
62
+ Formats accepted:
63
+ - "branch:<name>" → branch name
64
+ - "node:<id>" → node id
65
+ - "<anything>" → treated as branch name (auto-detect)
66
+ """
67
+ if ref.startswith("branch:"):
68
+ return ref[len("branch:"):], None
69
+ if ref.startswith("node:"):
70
+ return None, ref[len("node:"):]
71
+ # Auto-detect: treat as branch name.
72
+ return ref, None
73
+
74
+
75
+ def run_commit_command(
76
+ *,
77
+ message: str,
78
+ branch: str | None,
79
+ run_id: str | None,
80
+ store_dir: str | None,
81
+ user_id: str | None,
82
+ work_session_id: str | None,
83
+ merge: str | None = None,
84
+ join: bool = False,
85
+ # Test-only parameters; not exposed in the CLI parser.
86
+ dry_run: bool = False,
87
+ head_commit: str | None = None,
88
+ ) -> dict:
89
+ """Execute a commit (or merge) and persist the resulting graph records.
90
+
91
+ Parameters
92
+ ----------
93
+ message:
94
+ Git commit message.
95
+ branch:
96
+ Branch name override (None → infer from git).
97
+ run_id:
98
+ Explicit run id. If None, resolved from env / <gitdir>/arctx-id.
99
+ store_dir:
100
+ Store directory. If None, resolved from ARCTX_HOME.
101
+ user_id:
102
+ User id for work event attribution.
103
+ work_session_id:
104
+ Work session id.
105
+ merge:
106
+ If set, drive a merge instead of a plain commit. Format:
107
+ 'branch:<name>', 'node:<id>', or '<name>' (branch auto-detect).
108
+ join:
109
+ If True and merge is set, use JoinPayload instead of MergePayload.
110
+
111
+ Returns
112
+ -------
113
+ dict with transition_id, output_node_id, branch, head_commit.
114
+ """
115
+ store = resolve_store(store_dir)
116
+ handle = store.load_run(run_id)
117
+
118
+ before = graph_counts(handle)
119
+
120
+ if merge is not None:
121
+ other_branch, other_node_id = _parse_merge_ref(merge)
122
+ transition = handle.git.merge(
123
+ other_branch=other_branch,
124
+ other_node_id=other_node_id,
125
+ message=message,
126
+ branch=branch,
127
+ user_id=user_id,
128
+ work_session_id=work_session_id,
129
+ join=join,
130
+ dry_run=dry_run,
131
+ head_commit=head_commit,
132
+ )
133
+ else:
134
+ transition = handle.git.commit(
135
+ message=message,
136
+ branch=branch,
137
+ user_id=user_id,
138
+ work_session_id=work_session_id,
139
+ dry_run=dry_run,
140
+ head_commit=head_commit,
141
+ )
142
+
143
+ maybe_append_or_save(
144
+ store=store,
145
+ handle=handle,
146
+ user_id=user_id,
147
+ work_session_id=work_session_id,
148
+ before=before,
149
+ )
150
+
151
+ # Extract GitChangePayload info for the result.
152
+ git_payloads = handle.run_graph.payloads_for_transition(
153
+ transition.transition_id, payload_type="git_change"
154
+ )
155
+ head_commit = git_payloads[-1].head_commit if git_payloads else ""
156
+ branch_payloads = handle.run_graph.payloads_for_transition(
157
+ transition.transition_id, payload_type="branch"
158
+ )
159
+ resolved_branch = branch_payloads[-1].branch if branch_payloads else ""
160
+
161
+ result: dict = {
162
+ "transition_id": transition.transition_id,
163
+ "output_node_id": transition.output_node_id,
164
+ "branch": resolved_branch,
165
+ "head_commit": head_commit,
166
+ }
167
+ if merge is not None:
168
+ result["merge"] = merge
169
+ result["join"] = join
170
+ return result
171
+
172
+
173
+ def cli_commit(args) -> int:
174
+ """Entry point for ``arctx commit`` subcommand."""
175
+ from arctx.ext.git.verbs._forward_transition import ParallelSessionConflict # noqa: PLC0415
176
+
177
+ run_id = resolve_run_id_from_args(args)
178
+ user_id = resolve_user_id_from_args(args)
179
+ work_session_id = resolve_work_session_id_from_args(args)
180
+
181
+ try:
182
+ result = run_commit_command(
183
+ message=args.message,
184
+ branch=args.branch,
185
+ run_id=run_id,
186
+ store_dir=args.store_dir,
187
+ user_id=user_id,
188
+ work_session_id=work_session_id,
189
+ merge=getattr(args, "merge", None),
190
+ join=getattr(args, "join", False),
191
+ )
192
+ except ParallelSessionConflict as exc:
193
+ print(f"error: {exc}", file=sys.stderr)
194
+ print(
195
+ "hint: another session has advanced this branch. "
196
+ "Rebase / pull before committing.",
197
+ file=sys.stderr,
198
+ )
199
+ return 2
200
+ except Exception as exc: # noqa: BLE001
201
+ print(f"error: {exc}", file=sys.stderr)
202
+ return 1
203
+
204
+ print(json.dumps(result, indent=2))
205
+ return 0