pygitcode 0.1.5__tar.gz → 0.1.6__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.
- {pygitcode-0.1.5/src/pygitcode.egg-info → pygitcode-0.1.6}/PKG-INFO +1 -1
- {pygitcode-0.1.5 → pygitcode-0.1.6}/src/gitcode_cli/__init__.py +1 -1
- {pygitcode-0.1.5 → pygitcode-0.1.6}/src/gitcode_cli/commands/pr.py +52 -19
- {pygitcode-0.1.5 → pygitcode-0.1.6}/src/gitcode_cli/compat/entries.py +1 -0
- {pygitcode-0.1.5 → pygitcode-0.1.6}/src/gitcode_cli/services/pulls.py +5 -0
- {pygitcode-0.1.5 → pygitcode-0.1.6/src/pygitcode.egg-info}/PKG-INFO +1 -1
- {pygitcode-0.1.5 → pygitcode-0.1.6}/LICENSE +0 -0
- {pygitcode-0.1.5 → pygitcode-0.1.6}/README.md +0 -0
- {pygitcode-0.1.5 → pygitcode-0.1.6}/pyproject.toml +0 -0
- {pygitcode-0.1.5 → pygitcode-0.1.6}/setup.cfg +0 -0
- {pygitcode-0.1.5 → pygitcode-0.1.6}/src/gitcode_cli/adapters/__init__.py +0 -0
- {pygitcode-0.1.5 → pygitcode-0.1.6}/src/gitcode_cli/adapters/base.py +0 -0
- {pygitcode-0.1.5 → pygitcode-0.1.6}/src/gitcode_cli/adapters/capabilities.py +0 -0
- {pygitcode-0.1.5 → pygitcode-0.1.6}/src/gitcode_cli/adapters/issues.py +0 -0
- {pygitcode-0.1.5 → pygitcode-0.1.6}/src/gitcode_cli/adapters/pulls.py +0 -0
- {pygitcode-0.1.5 → pygitcode-0.1.6}/src/gitcode_cli/audit.py +0 -0
- {pygitcode-0.1.5 → pygitcode-0.1.6}/src/gitcode_cli/cli.py +0 -0
- {pygitcode-0.1.5 → pygitcode-0.1.6}/src/gitcode_cli/cli_compat.py +0 -0
- {pygitcode-0.1.5 → pygitcode-0.1.6}/src/gitcode_cli/client.py +0 -0
- {pygitcode-0.1.5 → pygitcode-0.1.6}/src/gitcode_cli/commands/__init__.py +0 -0
- {pygitcode-0.1.5 → pygitcode-0.1.6}/src/gitcode_cli/commands/auth.py +0 -0
- {pygitcode-0.1.5 → pygitcode-0.1.6}/src/gitcode_cli/commands/compat.py +0 -0
- {pygitcode-0.1.5 → pygitcode-0.1.6}/src/gitcode_cli/commands/issue.py +0 -0
- {pygitcode-0.1.5 → pygitcode-0.1.6}/src/gitcode_cli/commands/setup.py +0 -0
- {pygitcode-0.1.5 → pygitcode-0.1.6}/src/gitcode_cli/compat/__init__.py +0 -0
- {pygitcode-0.1.5 → pygitcode-0.1.6}/src/gitcode_cli/compat/_types.py +0 -0
- {pygitcode-0.1.5 → pygitcode-0.1.6}/src/gitcode_cli/compat/registry.py +0 -0
- {pygitcode-0.1.5 → pygitcode-0.1.6}/src/gitcode_cli/config.py +0 -0
- {pygitcode-0.1.5 → pygitcode-0.1.6}/src/gitcode_cli/context.py +0 -0
- {pygitcode-0.1.5 → pygitcode-0.1.6}/src/gitcode_cli/errors.py +0 -0
- {pygitcode-0.1.5 → pygitcode-0.1.6}/src/gitcode_cli/formatters.py +0 -0
- {pygitcode-0.1.5 → pygitcode-0.1.6}/src/gitcode_cli/gh_proxy.py +0 -0
- {pygitcode-0.1.5 → pygitcode-0.1.6}/src/gitcode_cli/helptext.py +0 -0
- {pygitcode-0.1.5 → pygitcode-0.1.6}/src/gitcode_cli/repo.py +0 -0
- {pygitcode-0.1.5 → pygitcode-0.1.6}/src/gitcode_cli/services/__init__.py +0 -0
- {pygitcode-0.1.5 → pygitcode-0.1.6}/src/gitcode_cli/services/issues.py +0 -0
- {pygitcode-0.1.5 → pygitcode-0.1.6}/src/gitcode_cli/services/users.py +0 -0
- {pygitcode-0.1.5 → pygitcode-0.1.6}/src/gitcode_cli/utils.py +0 -0
- {pygitcode-0.1.5 → pygitcode-0.1.6}/src/pygitcode.egg-info/SOURCES.txt +0 -0
- {pygitcode-0.1.5 → pygitcode-0.1.6}/src/pygitcode.egg-info/dependency_links.txt +0 -0
- {pygitcode-0.1.5 → pygitcode-0.1.6}/src/pygitcode.egg-info/entry_points.txt +0 -0
- {pygitcode-0.1.5 → pygitcode-0.1.6}/src/pygitcode.egg-info/requires.txt +0 -0
- {pygitcode-0.1.5 → pygitcode-0.1.6}/src/pygitcode.egg-info/top_level.txt +0 -0
|
@@ -155,27 +155,26 @@ def _extract_search_filters(
|
|
|
155
155
|
|
|
156
156
|
|
|
157
157
|
def _advance_diff_line(
|
|
158
|
-
raw_line: str, old_line: int, new_line: int, target_line: int, target_side: str
|
|
159
|
-
) -> tuple[
|
|
158
|
+
raw_line: str, old_line: int, new_line: int, target_line: int, target_side: str
|
|
159
|
+
) -> tuple[bool, int, int]:
|
|
160
160
|
prefix = raw_line[:1]
|
|
161
161
|
if prefix == "-":
|
|
162
|
-
return
|
|
162
|
+
return target_side == "LEFT" and old_line == target_line, old_line + 1, new_line
|
|
163
163
|
if prefix == "+":
|
|
164
|
-
return
|
|
164
|
+
return target_side == "RIGHT" and new_line == target_line, old_line, new_line + 1
|
|
165
165
|
matched = (target_side == "LEFT" and old_line == target_line) or (
|
|
166
166
|
target_side == "RIGHT" and new_line == target_line
|
|
167
167
|
)
|
|
168
|
-
return
|
|
168
|
+
return matched, old_line + 1, new_line + 1
|
|
169
169
|
|
|
170
170
|
|
|
171
|
-
def
|
|
171
|
+
def _validate_diff_line(diff_text: str, path: str, line: int, side: str) -> None:
|
|
172
172
|
target_side = side.upper()
|
|
173
173
|
if target_side not in {"LEFT", "RIGHT"}:
|
|
174
174
|
raise click.UsageError("--side must be LEFT or RIGHT")
|
|
175
175
|
|
|
176
176
|
old_line = None
|
|
177
177
|
new_line = None
|
|
178
|
-
position = 0
|
|
179
178
|
in_target_file = False
|
|
180
179
|
saw_target_file = False
|
|
181
180
|
|
|
@@ -183,9 +182,9 @@ def _diff_position_for_line(diff_text: str, path: str, line: int, side: str) ->
|
|
|
183
182
|
if raw_line.startswith("diff --git "):
|
|
184
183
|
old_line = None
|
|
185
184
|
new_line = None
|
|
186
|
-
position = 0
|
|
187
185
|
in_target_file = False
|
|
188
186
|
continue
|
|
187
|
+
# TODO: Handle Git-quoted paths and deleted files whose +++ header is /dev/null.
|
|
189
188
|
if raw_line.startswith("+++ b/"):
|
|
190
189
|
in_target_file = raw_line[6:] == path
|
|
191
190
|
saw_target_file = saw_target_file or in_target_file
|
|
@@ -200,12 +199,9 @@ def _diff_position_for_line(diff_text: str, path: str, line: int, side: str) ->
|
|
|
200
199
|
if old_line is None or new_line is None or raw_line.startswith("\\"):
|
|
201
200
|
continue
|
|
202
201
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
)
|
|
207
|
-
if matched_position is not None:
|
|
208
|
-
return matched_position
|
|
202
|
+
matched, old_line, new_line = _advance_diff_line(raw_line, old_line, new_line, line, target_side)
|
|
203
|
+
if matched:
|
|
204
|
+
return
|
|
209
205
|
|
|
210
206
|
if not saw_target_file:
|
|
211
207
|
raise click.ClickException(f"Path '{path}' was not found in the pull request diff.")
|
|
@@ -220,7 +216,9 @@ def _resolve_comment_position_from_line(
|
|
|
220
216
|
if path is None:
|
|
221
217
|
raise click.UsageError("--path is required when using --line")
|
|
222
218
|
diff_text = service.diff(owner, repo, number)
|
|
223
|
-
|
|
219
|
+
_validate_diff_line(diff_text, path, line, side)
|
|
220
|
+
# GitCode position is an absolute file line, not an ordinal within the diff.
|
|
221
|
+
return line
|
|
224
222
|
|
|
225
223
|
|
|
226
224
|
@click.group("pr", cls=GCSectionGroup, help="Work with GitCode pull requests.")
|
|
@@ -298,10 +296,19 @@ def pr_merge(
|
|
|
298
296
|
@click.option("--edit-last", is_flag=True)
|
|
299
297
|
@click.option("-e", "--editor", is_flag=True)
|
|
300
298
|
@click.option("-w", "--web", is_flag=True, help="Open the pull request in the web browser.")
|
|
299
|
+
@click.option(
|
|
300
|
+
"--discussion-id",
|
|
301
|
+
help="Reply to an existing discussion (gc extension). Find discussion_id with pr view --json comments.",
|
|
302
|
+
)
|
|
301
303
|
@click.option("--path")
|
|
302
|
-
@click.option("--position", type=int)
|
|
303
|
-
@click.option("--line", type=int)
|
|
304
|
-
@click.option(
|
|
304
|
+
@click.option("--position", type=int, help="Pass an absolute file line number directly to GitCode.")
|
|
305
|
+
@click.option("--line", type=int, help="Absolute file line number; validated against the pull request diff.")
|
|
306
|
+
@click.option(
|
|
307
|
+
"--side",
|
|
308
|
+
default="RIGHT",
|
|
309
|
+
show_default=True,
|
|
310
|
+
help="Side used only to validate --line: LEFT or RIGHT. GitCode receives no side; LEFT anchoring is best-effort.",
|
|
311
|
+
)
|
|
305
312
|
@click.option("--commit-id")
|
|
306
313
|
@click.option("--commit", "commit_id")
|
|
307
314
|
@click.option("--yes", is_flag=True)
|
|
@@ -317,6 +324,7 @@ def pr_comment(
|
|
|
317
324
|
edit_last: bool,
|
|
318
325
|
editor: bool,
|
|
319
326
|
web: bool,
|
|
327
|
+
discussion_id: str | None,
|
|
320
328
|
path: str | None,
|
|
321
329
|
position: int | None,
|
|
322
330
|
line: int | None,
|
|
@@ -332,6 +340,23 @@ def pr_comment(
|
|
|
332
340
|
_pending_gh_compat("pr comment --edit-last")
|
|
333
341
|
if yes:
|
|
334
342
|
_pending_gh_compat("pr comment --yes")
|
|
343
|
+
if discussion_id is not None:
|
|
344
|
+
discussion_id = discussion_id.strip()
|
|
345
|
+
if not discussion_id:
|
|
346
|
+
raise click.UsageError("--discussion-id must not be empty")
|
|
347
|
+
if discussion_id in {".", ".."} or any(char in discussion_id for char in "/\\?#%"):
|
|
348
|
+
raise click.UsageError("--discussion-id must be a single path segment without URL-reserved characters")
|
|
349
|
+
if (
|
|
350
|
+
path is not None
|
|
351
|
+
or position is not None
|
|
352
|
+
or line is not None
|
|
353
|
+
or ctx.get_parameter_source("side") != click.core.ParameterSource.DEFAULT
|
|
354
|
+
or commit_id is not None
|
|
355
|
+
or web
|
|
356
|
+
):
|
|
357
|
+
raise click.UsageError(
|
|
358
|
+
"--discussion-id cannot be used with --path, --position, --line, --side, --commit-id/--commit, or --web"
|
|
359
|
+
)
|
|
335
360
|
if commit_id:
|
|
336
361
|
raise click.ClickException("GitCode PR comments do not support selecting a commit for line comments.")
|
|
337
362
|
if line is not None and position is not None:
|
|
@@ -348,7 +373,15 @@ def pr_comment(
|
|
|
348
373
|
return
|
|
349
374
|
body = get_body_from_options(body=body, body_file=body_file, editor=editor)
|
|
350
375
|
body = prompt_if_missing(body, "Body")
|
|
351
|
-
|
|
376
|
+
if discussion_id is not None:
|
|
377
|
+
item = service.reply(owner, repo, number, discussion_id, body=body) or {}
|
|
378
|
+
safe_echo(str(item.get("noteId") or "Reply posted."))
|
|
379
|
+
return
|
|
380
|
+
resolved_position = (
|
|
381
|
+
position
|
|
382
|
+
if position is not None
|
|
383
|
+
else _resolve_comment_position_from_line(service, owner, repo, number, path, line, side)
|
|
384
|
+
)
|
|
352
385
|
item = service.comment(owner, repo, number, body=body, path=path, position=resolved_position)
|
|
353
386
|
safe_echo(str(item["id"]))
|
|
354
387
|
|
|
@@ -341,6 +341,7 @@ ENTRIES: list[CompatEntry] = [
|
|
|
341
341
|
_e("pr comment", "-e/--editor", CompatStatus.IMPLEMENTED),
|
|
342
342
|
_e("pr comment", "-w/--web", CompatStatus.IMPLEMENTED),
|
|
343
343
|
_e("pr comment", "--path", CompatStatus.IMPLEMENTED, "gc extension; not in gh", gc_extension=True),
|
|
344
|
+
_e("pr comment", "--discussion-id", CompatStatus.IMPLEMENTED, "gc extension; not in gh", gc_extension=True),
|
|
344
345
|
_e("pr comment", "--position", CompatStatus.IMPLEMENTED, "gc extension; not in gh", gc_extension=True),
|
|
345
346
|
_e("pr comment", "--line", CompatStatus.IMPLEMENTED, "gc extension; not in gh", gc_extension=True),
|
|
346
347
|
_e("pr comment", "--side", CompatStatus.IMPLEMENTED, "gc extension; not in gh", gc_extension=True),
|
|
@@ -70,6 +70,11 @@ class PullRequestService:
|
|
|
70
70
|
filtered_payload = {k: v for k, v in payload.items() if v is not None}
|
|
71
71
|
return self.client.post(f"/repos/{owner}/{repo}/pulls/{number}/review", json=filtered_payload)
|
|
72
72
|
|
|
73
|
+
def reply(self, owner: str, repo: str, number: int, discussion_id: str, body: str) -> Any | None:
|
|
74
|
+
return self.client.post(
|
|
75
|
+
f"/repos/{owner}/{repo}/pulls/{number}/discussions/{discussion_id}/comments", json={"body": body}
|
|
76
|
+
)
|
|
77
|
+
|
|
73
78
|
def list_comments(self, owner: str, repo: str, number: int) -> Any | None:
|
|
74
79
|
return self._paginate(f"/repos/{owner}/{repo}/pulls/{number}/comments")
|
|
75
80
|
|
|
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
|