feat: bun_script
Some checks failed
CI / test (ubuntu-latest, linux-x64) (push) Failing after 39s
Docs Pages / deploy (push) Failing after 37s
CI / test (macos-14, darwin-arm64) (push) Has been cancelled
CI / test (windows-latest, windows) (push) Has been cancelled

This commit is contained in:
Eric
2026-03-06 19:51:52 +01:00
committed by eric
parent 5e8ec20b2e
commit d8e40f7df2
17 changed files with 222 additions and 111 deletions

110
prank.py
View File

@@ -2,8 +2,7 @@
"""
git-claim-authorship.py
Rewrites git history so that any commit where you appear as a co-author
instead lists you as the sole author (removing the Co-authored-by line).
Rewrites git history so that all commits list you as the author.
Usage:
python git-claim-authorship.py --name "Your Name" --email "you@example.com"
@@ -13,7 +12,6 @@ WARNING: This rewrites history. Force-push required afterwards.
"""
import subprocess
import re
import argparse
import sys
@@ -28,53 +26,9 @@ def run(cmd, capture=True, check=True):
def get_all_commits():
output = run("git log --format='%H' --all")
return output.splitlines() if output else []
def get_commit_info(sha):
msg = run(f"git log -1 --format=%B {sha}")
author_name = run(f"git log -1 --format=%an {sha}")
author_email = run(f"git log -1 --format=%ae {sha}")
author_date = run(f"git log -1 --format=%aI {sha}")
committer_name = run(f"git log -1 --format=%cn {sha}")
committer_email = run(f"git log -1 --format=%ce {sha}")
committer_date = run(f"git log -1 --format=%cI {sha}")
return {
"sha": sha,
"message": msg,
"author_name": author_name,
"author_email": author_email,
"author_date": author_date,
"committer_name": committer_name,
"committer_email": committer_email,
"committer_date": committer_date,
}
def find_coauthor_line(message, name, email):
"""Return True if a Co-authored-by line matches the given name or email."""
pattern = re.compile(
r"^Co-authored-by:.*?" + re.escape(name) + r".*$|"
r"^Co-authored-by:.*?" + re.escape(email) + r".*$",
re.IGNORECASE | re.MULTILINE,
)
return bool(pattern.search(message))
def remove_coauthor_line(message, name, email):
"""Strip matching Co-authored-by lines from the commit message."""
pattern = re.compile(
r"^Co-authored-by:.*?" + re.escape(name) + r".*\n?|"
r"^Co-authored-by:.*?" + re.escape(email) + r".*\n?",
re.IGNORECASE | re.MULTILINE,
)
cleaned = pattern.sub("", message)
cleaned = re.sub(r"\n{3,}", "\n\n", cleaned).rstrip() + "\n"
return cleaned
def main():
parser = argparse.ArgumentParser(
description="Claim authorship of co-authored commits."
description="Rewrite history so all commits use the provided author."
)
parser.add_argument("--name", required=True, help="Your full name (as in git)")
parser.add_argument("--email", required=True, help="Your email (as in git)")
@@ -92,24 +46,15 @@ def main():
print("Error: not inside a git repository.", file=sys.stderr)
sys.exit(1)
print(f"Scanning commits for co-authorship by: {args.name} <{args.email}>")
print(f"Scanning commits to rewrite author to: {args.name} <{args.email}>")
commits = get_all_commits()
print(f"Total commits found: {len(commits)}")
matches = []
for sha in commits:
info = get_commit_info(sha)
if find_coauthor_line(info["message"], args.name, args.email):
matches.append(info)
if not matches:
print("No commits found with your Co-authored-by line. Nothing to do.")
if not commits:
print("No commits found. Nothing to do.")
return
print(f"\nFound {len(matches)} commit(s) to rewrite:\n")
for info in matches:
first_line = info["message"].split("\n")[0]
print(f" {info['sha'][:10]} {first_line}")
print(f"\nFound {len(commits)} commit(s) to rewrite.\n")
if args.dry_run:
print("\n[Dry run] No changes made.")
@@ -123,56 +68,17 @@ def main():
return
# Build a filter-branch env filter script
sha_set = {info["sha"] for info in matches}
case_entries = []
for info in matches:
case_entries.append(
f" {info['sha']})\n"
f" export GIT_AUTHOR_NAME='{args.name}'\n"
f" export GIT_AUTHOR_EMAIL='{args.email}'\n"
f" ;;"
)
case_block = "\n".join(case_entries)
env_filter = f"""
case $GIT_COMMIT in
{case_block}
esac
export GIT_AUTHOR_NAME='{args.name}'
export GIT_AUTHOR_EMAIL='{args.email}'
"""
msg_case_entries = []
for info in matches:
new_msg = remove_coauthor_line(info["message"], args.name, args.email)
escaped_msg = new_msg.replace("'", "'\\''").replace("`", "\\`").replace("$", "\\$")
msg_case_entries.append(
f" {info['sha']})\n"
f" printf '%s' '{escaped_msg}'\n"
f" ;;"
)
msg_case_block = "\n".join(msg_case_entries)
msg_filter = f"""
case $GIT_COMMIT in
{msg_case_block}
*)
cat
;;
esac
"""
with open("/tmp/_msg_filter.sh", "w") as f:
f.write(msg_filter)
print("\nRewriting history with git filter-branch...")
try:
result = subprocess.run(
[
"git", "filter-branch", "-f",
"--env-filter", env_filter,
"--msg-filter", "bash /tmp/_msg_filter.sh",
"--tag-name-filter", "cat",
"--", "--all"
],