Skip to content

Commit f269a60

Browse files
committed
Accept common git status remote log flags
1 parent ea43926 commit f269a60

2 files changed

Lines changed: 71 additions & 4 deletions

File tree

‎pythongit/cli.py‎

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -388,12 +388,15 @@ def cmd_mv(argv: list[str]) -> int:
388388
def cmd_status(argv: list[str]) -> int:
389389
ap = argparse.ArgumentParser(prog="pygit status")
390390
ap.add_argument("-s", "--short", action="store_true")
391+
ap.add_argument("-b", "--branch", action="store_true")
391392
args = ap.parse_args(argv)
392393
repo = _repo()
393394
s = workdir.status(repo)
394395
head_sym, _ = refs_mod.read_head(repo)
395396
branch = head_sym[len("refs/heads/") :] if head_sym and head_sym.startswith("refs/heads/") else "(detached)"
396397
if args.short:
398+
if args.branch:
399+
_print(f"## {branch}")
397400
for p in s["staged_new"]:
398401
_print(f"A {p}")
399402
for p in s["staged_mod"]:
@@ -481,14 +484,18 @@ def cmd_commit(argv: list[str]) -> int:
481484
def cmd_log(argv: list[str]) -> int:
482485
ap = argparse.ArgumentParser(prog="pygit log")
483486
ap.add_argument("--oneline", action="store_true")
487+
ap.add_argument("--decorate", nargs="?", const="short", default=None)
488+
ap.add_argument("--no-decorate", action="store_true")
484489
ap.add_argument("-n", "--max-count", type=int, default=None)
485490
ap.add_argument("rev", nargs="?", default="HEAD")
486-
args = ap.parse_args(argv)
491+
args = ap.parse_args(_expand_count_shorthand(argv))
487492
repo = _repo()
488493
sha = refs_mod.rev_parse(repo, args.rev)
489494
if not sha:
490495
_err("fatal: bad revision")
491496
return 128
497+
decorate = args.decorate is not None and not args.no_decorate
498+
decorations = _commit_decorations(repo) if decorate else {}
492499
seen: set[str] = set()
493500
cur = deque([sha])
494501
count = 0
@@ -506,9 +513,10 @@ def cmd_log(argv: list[str]) -> int:
506513
c = objs.parse_commit(data)
507514
if args.oneline:
508515
first = c.message.splitlines()[0] if c.message.strip() else ""
509-
_print(f"{s[:7]} {first}")
516+
deco = _format_decoration(decorations.get(s, []))
517+
_print(f"{s[:7]}{deco} {first}")
510518
else:
511-
_print(f"commit {s}")
519+
_print(f"commit {s}{_format_decoration(decorations.get(s, []))}")
512520
if len(c.parents) > 1:
513521
_print("Merge: " + " ".join(p[:7] for p in c.parents))
514522
_print(f"Author: {c.author}")
@@ -524,6 +532,40 @@ def cmd_log(argv: list[str]) -> int:
524532
return 0
525533

526534

535+
def _expand_count_shorthand(argv: list[str]) -> list[str]:
536+
out: list[str] = []
537+
for a in argv:
538+
if len(a) > 1 and a[0] == "-" and a[1:].isdigit():
539+
out.extend(["-n", a[1:]])
540+
else:
541+
out.append(a)
542+
return out
543+
544+
545+
def _commit_decorations(repo: Repository) -> dict[str, list[str]]:
546+
out: dict[str, list[str]] = {}
547+
head_sym, head_sha = refs_mod.read_head(repo)
548+
if head_sha:
549+
if head_sym and head_sym.startswith("refs/heads/"):
550+
out.setdefault(head_sha, []).append(f"HEAD -> {head_sym[len('refs/heads/') :]}")
551+
else:
552+
out.setdefault(head_sha, []).append("HEAD")
553+
for branch in refs_mod.list_branches(repo):
554+
ref = f"refs/heads/{branch}"
555+
sha = refs_mod.read_ref(repo, ref)
556+
if sha and ref != head_sym:
557+
out.setdefault(sha, []).append(branch)
558+
for tag in refs_mod.list_tags(repo):
559+
sha = refs_mod.read_ref(repo, f"refs/tags/{tag}")
560+
if sha:
561+
out.setdefault(sha, []).append(f"tag: {tag}")
562+
return out
563+
564+
565+
def _format_decoration(names: list[str]) -> str:
566+
return f" ({', '.join(names)})" if names else ""
567+
568+
527569
def cmd_show(argv: list[str]) -> int:
528570
ap = argparse.ArgumentParser(prog="pygit show")
529571
ap.add_argument("rev", nargs="?", default="HEAD")
@@ -837,6 +879,7 @@ def _config_section_key(name: str) -> tuple[str, str]:
837879

838880
def cmd_remote(argv: list[str]) -> int:
839881
ap = argparse.ArgumentParser(prog="pygit remote")
882+
ap.add_argument("-v", "--verbose", action="store_true")
840883
sub = ap.add_subparsers(dest="action")
841884
sub.add_parser("show")
842885
p_add = sub.add_parser("add")
@@ -850,7 +893,14 @@ def cmd_remote(argv: list[str]) -> int:
850893
if args.action in (None, "show"):
851894
for s in cp.sections():
852895
if s.startswith('remote "'):
853-
_print(s[len('remote "') : -1])
896+
name = s[len('remote "') : -1]
897+
if args.verbose:
898+
url = cp.get(s, "url", fallback="")
899+
pushurl = cp.get(s, "pushurl", fallback=url)
900+
_print(f"{name}\t{url} (fetch)")
901+
_print(f"{name}\t{pushurl} (push)")
902+
else:
903+
_print(name)
854904
return 0
855905
cfg_path = repo.gitdir / "config"
856906
if args.action == "add":

‎tests/unit_integration.py‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,23 @@ def test_diff_show_log(tmprepo, capsys):
350350
assert cli_run("log", "--oneline") == 0
351351
out = capsys.readouterr().out
352352
assert "c1" in out and "c2" in out
353+
assert cli_run("log", "--oneline", "--decorate", "-1") == 0
354+
out = capsys.readouterr().out
355+
assert out.count("\n") == 1
356+
assert "(HEAD -> main)" in out
357+
358+
359+
def test_status_short_branch_option(tmprepo, capsys):
360+
assert cli_run("status", "--short", "--branch") == 0
361+
assert capsys.readouterr().out.startswith("## main\n")
362+
363+
364+
def test_remote_verbose_option(tmprepo, capsys):
365+
assert cli_run("remote", "add", "origin", "https://example.com/repo.git") == 0
366+
assert cli_run("remote", "-v") == 0
367+
out = capsys.readouterr().out
368+
assert "origin\thttps://example.com/repo.git (fetch)" in out
369+
assert "origin\thttps://example.com/repo.git (push)" in out
353370

354371

355372
def test_describe_after_tag(tmprepo):

0 commit comments

Comments
 (0)