git-hunk 0.4.0__tar.gz → 0.4.2__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: git-hunk
3
- Version: 0.4.0
3
+ Version: 0.4.2
4
4
  Summary: Non-interactive, programmatic git hunk staging with durable Hunk IDs.
5
5
  Project-URL: Homepage, https://github.com/wkentaro/git-hunk
6
6
  Project-URL: Issues, https://github.com/wkentaro/git-hunk/issues
@@ -71,7 +71,7 @@ variant: organize a dirty working tree into correct, focused commits, once
71
71
  following git-hunk's bundled skills and once restricted to bare Git. The
72
72
  [checked-in eval harness](https://github.com/wkentaro/git-hunk/tree/0ef14bef657e187b5ab7283b0dbd64751a02736f/eval)
73
73
  grades the exact resulting repository state — commit partition and order, final
74
- tree, index, and leftovers. This table records the qualifying run; `make eval`
74
+ tree, index, and leftovers. This table records the qualifying run; `just eval`
75
75
  reruns the protocol and prints a table in the same format.
76
76
 
77
77
  | Task | git-hunk | bare Git |
@@ -370,12 +370,16 @@ content and creates new IDs.
370
370
  Bug reports, feature requests, and pull requests are welcome on
371
371
  [GitHub](https://github.com/wkentaro/git-hunk).
372
372
 
373
+ Install [just](https://just.systems/man/en/packages.html) 1.58.0 or newer and
374
+ [uv](https://docs.astral.sh/uv/getting-started/installation/). Recipes use Bash;
375
+ on Windows, install Git for Windows and make its Bash available on `PATH`.
376
+
373
377
  ```bash
374
378
  git clone https://github.com/wkentaro/git-hunk.git
375
379
  cd git-hunk
376
- make setup # install dependencies
377
- make test # run tests
378
- make lint # run linters
380
+ just setup # install dependencies
381
+ just test # run tests
382
+ just lint # run linters
379
383
  ```
380
384
 
381
385
  ## License
@@ -43,7 +43,7 @@ variant: organize a dirty working tree into correct, focused commits, once
43
43
  following git-hunk's bundled skills and once restricted to bare Git. The
44
44
  [checked-in eval harness](https://github.com/wkentaro/git-hunk/tree/0ef14bef657e187b5ab7283b0dbd64751a02736f/eval)
45
45
  grades the exact resulting repository state — commit partition and order, final
46
- tree, index, and leftovers. This table records the qualifying run; `make eval`
46
+ tree, index, and leftovers. This table records the qualifying run; `just eval`
47
47
  reruns the protocol and prints a table in the same format.
48
48
 
49
49
  | Task | git-hunk | bare Git |
@@ -342,12 +342,16 @@ content and creates new IDs.
342
342
  Bug reports, feature requests, and pull requests are welcome on
343
343
  [GitHub](https://github.com/wkentaro/git-hunk).
344
344
 
345
+ Install [just](https://just.systems/man/en/packages.html) 1.58.0 or newer and
346
+ [uv](https://docs.astral.sh/uv/getting-started/installation/). Recipes use Bash;
347
+ on Windows, install Git for Windows and make its Bash available on `PATH`.
348
+
345
349
  ```bash
346
350
  git clone https://github.com/wkentaro/git-hunk.git
347
351
  cd git-hunk
348
- make setup # install dependencies
349
- make test # run tests
350
- make lint # run linters
352
+ just setup # install dependencies
353
+ just test # run tests
354
+ just lint # run linters
351
355
  ```
352
356
 
353
357
  ## License
@@ -69,6 +69,9 @@ JSON_SCHEMA_VERSION: Final = 2
69
69
 
70
70
 
71
71
  class CliError(Exception):
72
+ tip: str | None
73
+ usage: str | None
74
+
72
75
  def __init__(
73
76
  self,
74
77
  message: str,
@@ -425,6 +428,7 @@ def _apply_selection(
425
428
  hunk for hunk in selected if hunk.binary or hunk.change_kind == "T"
426
429
  ]
427
430
 
431
+ changes_applied = False
428
432
  try:
429
433
  patch = (
430
434
  build_patch(patch_hunks, diff_output, reverse=reverse)
@@ -469,6 +473,7 @@ def _apply_selection(
469
473
  reverse=reverse,
470
474
  dry_run=False,
471
475
  )
476
+ changes_applied = True
472
477
  if file_command_files:
473
478
  if reverse and not cached:
474
479
  discard_files(file_command_files, worktree_root=worktree_root)
@@ -479,6 +484,7 @@ def _apply_selection(
479
484
  worktree_root=worktree_root,
480
485
  dry_run=False,
481
486
  )
487
+ changes_applied = True
482
488
  if tracked_file_command_files:
483
489
  unstage_files(
484
490
  tracked_file_command_files,
@@ -491,7 +497,13 @@ def _apply_selection(
491
497
  dry_run=False,
492
498
  )
493
499
  except RuntimeError as exc:
494
- raise CliError(str(exc)) from exc
500
+ message = str(exc)
501
+ if changes_applied:
502
+ message = (
503
+ f"{message}; earlier changes were applied, so the repository may be "
504
+ "partially changed; inspect its state before retrying"
505
+ )
506
+ raise CliError(message) from exc
495
507
 
496
508
  return selected
497
509
 
@@ -550,22 +562,25 @@ def _working_tree_mode(*, path: str) -> str:
550
562
 
551
563
 
552
564
  def _get_untracked_entries(*, worktree_root: str) -> list[Hunk]:
553
- paths = get_untracked_files(worktree_root=worktree_root)
554
- if not paths:
555
- return []
556
- return [
557
- whole_file_hunk(
558
- p,
559
- change_kind="A",
560
- a_mode=None,
561
- b_mode=_working_tree_mode(path=posixpath.join(worktree_root, p)),
562
- binary=False,
563
- a_object_id=None,
564
- b_object_id=None,
565
- status="untracked",
566
- )
567
- for p in paths
568
- ]
565
+ try:
566
+ paths = get_untracked_files(worktree_root=worktree_root)
567
+ if not paths:
568
+ return []
569
+ return [
570
+ whole_file_hunk(
571
+ p,
572
+ change_kind="A",
573
+ a_mode=None,
574
+ b_mode=_working_tree_mode(path=posixpath.join(worktree_root, p)),
575
+ binary=False,
576
+ a_object_id=None,
577
+ b_object_id=None,
578
+ status="untracked",
579
+ )
580
+ for p in paths
581
+ ]
582
+ except (OSError, RuntimeError) as exc:
583
+ raise CliError(str(exc)) from exc
569
584
 
570
585
 
571
586
  def _filter_inventory_hunks(
@@ -868,7 +883,7 @@ def cmd_discard(
868
883
 
869
884
 
870
885
  @cli.command("commit", add_help_option=False)
871
- @click.option("-m", "message", default=None)
886
+ @click.option("-m", "messages", multiple=True)
872
887
  @click.option("-l", "line_spec", default=None)
873
888
  @click.option("--include-matching", "include_matching", multiple=True)
874
889
  @click.option("--exclude-matching", "exclude_matching", multiple=True)
@@ -879,7 +894,7 @@ def cmd_discard(
879
894
  def cmd_commit(
880
895
  *,
881
896
  targets: tuple[str, ...],
882
- message: str | None,
897
+ messages: tuple[str, ...],
883
898
  line_spec: str | None,
884
899
  include_matching: tuple[str, ...],
885
900
  exclude_matching: tuple[str, ...],
@@ -890,7 +905,10 @@ def cmd_commit(
890
905
  if show_help:
891
906
  print_help(HELP_COMMIT)
892
907
  return
893
- if message is None or not message.strip():
908
+ # Each -m is its own paragraph, as in git commit; git's own cleanup then
909
+ # collapses blank ones.
910
+ message = "\n\n".join(messages)
911
+ if not message.strip():
894
912
  raise CliError("commit requires a message (-m)", usage=USAGE_COMMIT)
895
913
 
896
914
  worktree_root, invocation_prefix = _require_worktree_context()
@@ -4,6 +4,8 @@ from typing import Final
4
4
 
5
5
 
6
6
  class GitCommandError(RuntimeError):
7
+ stderr: str
8
+
7
9
  def __init__(self, command: tuple[str, ...], stderr: str, /) -> None:
8
10
  self.stderr = stderr
9
11
  super().__init__(f"git {' '.join(command)} failed: {stderr}")
@@ -46,9 +48,13 @@ def get_diff(*, worktree_root: str, staged: bool) -> str:
46
48
  # floor stays at --no-relative's 2.28 instead of --default-prefix's 2.41.
47
49
  # --no-color: a color.diff or color.ui set to always emits ANSI escapes
48
50
  # even into a pipe, and the parse would find nothing.
51
+ # Display drivers can replace source patches with transformed or empty
52
+ # output, while inventory and mutation need the canonical source bytes.
49
53
  args = [
50
54
  "diff",
51
55
  "--no-color",
56
+ "--no-ext-diff",
57
+ "--no-textconv",
52
58
  "--no-relative",
53
59
  "--src-prefix=a/",
54
60
  "--dst-prefix=b/",
@@ -438,7 +438,7 @@ can retry with [bold cyan]git commit[/bold cyan].
438
438
  {USAGE_COMMIT}
439
439
 
440
440
  [bold green]Options:[/bold green]
441
- [bold cyan]-m[/bold cyan] [cyan]<msg>[/cyan] Commit message (required)
441
+ [bold cyan]-m[/bold cyan] [cyan]<msg>[/cyan] Commit message (required; repeat for more paragraphs)
442
442
  {_LINE_OPT_ROW}
443
443
 
444
444
  {_format_examples(rows=_EXAMPLES_COMMIT)}""" # noqa: E501
@@ -30,7 +30,8 @@ git-hunk list
30
30
  `git-hunk commit <id-or-path>... -m <message>` stages exactly those hunks and
31
31
  commits them; it aborts when the index already holds staged changes. A
32
32
  Repository path selects every changed hunk in one exact file and beats an ID
33
- when committing a whole file.
33
+ when committing a whole file. Repeat `-m` as with `git commit`: each one
34
+ becomes its own paragraph.
34
35
 
35
36
  Committing a complete hunk leaves every other non-`conditional` ID valid, so a
36
37
  whole plan of complete hunks chains in one call.
@@ -59,7 +59,7 @@ include = ["/README.md", "/git_hunk"]
59
59
 
60
60
  [dependency-groups]
61
61
  dev = [
62
- "gruff>=0.0.6",
62
+ "gruff>=0.0.10",
63
63
  "mdformat-frontmatter>=2.0.10",
64
64
  "mdformat>=0.7",
65
65
  "pytest-cov>=4",
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes