Skip to content

Instantly share code, notes, and snippets.

@JacobHayes
Last active January 30, 2024 06:22
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JacobHayes/9c86cc650c17a776f4a592fe0b2e7645 to your computer and use it in GitHub Desktop.
Save JacobHayes/9c86cc650c17a776f4a592fe0b2e7645 to your computer and use it in GitHub Desktop.
Reformat python files in git history w/ Black (line=100, py3.7/3.8)
#!/usr/bin/env python3
#
# Modified from https://github.com/newren/git-filter-repo/blob/master/contrib/filter-repo-demos/lint-history
#
# pip3 install git-filter-repo black
# git pull
# git remote prune origin # clean up associated local branches too
# python3 black_history.py
# git remote add origin <url>
# git push -u origin --mirror --no-verify
import subprocess
import black
import git_filter_repo as fr
blobs_handled = {}
cat_file_process = None
def reformat_commit(commit, metadata):
for change in commit.file_changes:
if change.blob_id in blobs_handled:
change.blob_id = blobs_handled[change.blob_id]
elif change.filename.endswith(b".py"):
# change.blob_id is None for deleted files (ex: change.type=b'D')
if change.blob_id is None:
assert change.type == b"D"
continue
# Get the old blob contents
cat_file_process.stdin.write(change.blob_id + b"\n")
cat_file_process.stdin.flush()
objhash, objtype, objsize = cat_file_process.stdout.readline().split()
contents_plus_newline = cat_file_process.stdout.read(int(objsize) + 1)
# Reformat into a new blob
try:
blob = fr.Blob(
# Set fast=False to verify AST integrity after the reformat
black.format_file_contents(
contents_plus_newline.decode(),
fast=True,
mode=black.FileMode(
line_length=100,
target_versions={
black.TargetVersion.PY37,
black.TargetVersion.PY38,
},
),
).encode()
)
except black.NothingChanged:
continue
except black.InvalidInput:
print(f"\nUnable to format {change.filename.decode()}")
continue
# Insert the new file into the filter's stream, and remove the tempfile
filter.insert(blob)
# Record our handling of the blob and use it for this change
blobs_handled[change.blob_id] = blob.id
change.blob_id = blob.id
args = fr.FilteringOptions.default_options()
args.force = True
cat_file_process = subprocess.Popen(
["git", "cat-file", "--batch"], stdin=subprocess.PIPE, stdout=subprocess.PIPE
)
filter = fr.RepoFilter(args, commit_callback=reformat_commit)
filter.run()
cat_file_process.stdin.close()
cat_file_process.wait()
@ozzmanli
Copy link

Is there a way to convert this to clang format ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment