Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 1 addition & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,7 @@ Writing a PR description after the coding is finished is easy to postpone. diffn

## Quick start

```bash
git clone https://github.com/LucasXlab/diffnote.git && cd diffnote
python3 -m pip install .
python3 scripts/demo.py
```


## Features

Expand Down Expand Up @@ -80,12 +76,6 @@ python3 -m pytest -q

The demo uses a temporary fixture and does not inspect your personal repositories or agent homes.

## Roadmap

- [ ] Improve error messages for invalid refs and empty histories.
- [ ] Add configurable grouping rules.

## Contributing

Read [CONTRIBUTING.md](CONTRIBUTING.md). Report reproducible problems in [Issues](https://github.com/LucasXlab/diffnote/issues). Follow [SECURITY.md](SECURITY.md) for sensitive reports.

Expand Down
18 changes: 16 additions & 2 deletions src/diffnote/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ def build_parser():
fmt = p.add_argument_group("output")
fmt.add_argument("--markdown", action="store_true",
help="Print a GitHub PR-body markdown.")
fmt.add_argument("--save", metavar="PATH",
help="Write markdown output to PATH instead of stdout (requires --markdown).")
fmt.add_argument("--json", action="store_true",
help="Print machine-readable JSON.")
color = fmt.add_mutually_exclusive_group()
Expand Down Expand Up @@ -55,7 +57,10 @@ def get_diff(args, cwd):


def main(argv=None):
args = build_parser().parse_args(argv)
parser = build_parser()
args = parser.parse_args(argv)
if args.save and (not args.markdown or args.json):
parser.error("--save requires --markdown and cannot be used with --json")
try:
cwd = gitutil.repo_root()
except gitutil.GitError as exc:
Expand Down Expand Up @@ -89,7 +94,16 @@ def main(argv=None):
if args.json:
print(render.render_json(summary, llm_prose))
elif args.markdown:
print(render.render_markdown(summary, llm_prose))
markdown = render.render_markdown(summary, llm_prose)
if args.save:
try:
with open(args.save, "w", encoding="utf-8", newline="\n") as output_file:
output_file.write(markdown + "\n")
except OSError as exc:
print(f"diffnote: could not write {args.save}: {exc}", file=sys.stderr)
return 1
else:
print(markdown)
else:
print(render.render_terminal(summary, use_color=args.use_color, llm_prose=llm_prose))
return 0
Expand Down
19 changes: 19 additions & 0 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,25 @@ def test_markdown_output(capsys):
assert "## Changes" in out


def test_save_markdown_writes_file_without_stdout(capsys):
d = _make_dirty_repo()
output_path = os.path.join(d, "pr-body.md")
old = os.getcwd()
os.chdir(d)
try:
rc = cli.main(["--save", output_path, "--markdown"])
finally:
os.chdir(old)
captured = capsys.readouterr()
with open(output_path, encoding="utf-8") as output_file:
saved = output_file.read()
assert rc == 0
assert captured.out == ""
assert "## Summary" in saved
assert "## Changes" in saved
assert saved.endswith("\n")


def test_no_changes(capsys):
import os
d = tempfile.mkdtemp()
Expand Down