Last active
February 2, 2023 20:27
-
-
Save Akarys42/47085d16978947039279d75e1773725e to your computer and use it in GitHub Desktop.
The main script created during Ambre Bertucci's talk "Learn Python automation by recreating Git Commit from scratch" at EuroPython 2021.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from hashlib import sha1 | |
from textwrap import dedent | |
from pathlib import Path | |
import sys | |
import zlib | |
OBJECT_PATH = Path(".git/objects") | |
EXCLUDED_FILES = {".git", "__pycache__", "my_commit.py"} | |
AUTHOR_IDENTITY = "Example User <example@localhost>" | |
COMMIT_TIMESTAMP = "1483920000 +0000" | |
def write_object(type_: str, content: bytes) -> str: | |
""" | |
Write down the object with the provided content and type to | |
the Git database and returns its hash | |
""" | |
store = b"%s %d\0%s" % (type_.encode("utf8"), len(content), content) | |
hash_ = sha1(store).hexdigest() | |
compressed = zlib.compress(store) | |
folder = OBJECT_PATH / hash_[:2] | |
# Make sure that the folder exists | |
if not folder.exists(): | |
folder.mkdir() | |
# Write the file | |
with open(folder / hash_[2:], "wb") as file: | |
file.write(compressed) | |
return hash_ | |
def write_blob(path: Path) -> str: | |
"""Write the file to the database as a blob and return its SHA.""" | |
with open(path, "rb") as file: | |
return write_object("blob", file.read()) | |
def write_tree(path: Path) -> str: | |
"""Write the tree to the database and return its SHA.""" | |
lines = [] | |
children = list(path.iterdir()) | |
children.sort() | |
for child in children: | |
# Skip some problematic files. | |
if child.name in EXCLUDED_FILES: | |
continue | |
# Register the file or folder to the database and add it to this tree | |
if child.is_dir(): | |
hash_ = write_tree(child) | |
mode = b"40000" | |
else: | |
hash_ = write_blob(child) | |
mode = b"100644" | |
# Create the line for this object | |
hash_bytes = bytes.fromhex(hash_) | |
line = b"%s %s\0%s" % (mode, child.name.encode("utf8"), hash_bytes) | |
lines.append(line) | |
content = b"".join(lines) | |
return write_object("tree", content) | |
def write_commit(message: str) -> str: | |
"""Write the commit to the database and return its SHA.""" | |
tree = write_tree(Path(".")) | |
commit = dedent(f"""\ | |
tree {tree} | |
author {AUTHOR_IDENTITY} {COMMIT_TIMESTAMP} | |
committer {AUTHOR_IDENTITY} {COMMIT_TIMESTAMP} | |
{message} | |
""").encode("utf8") | |
return write_object("commit", commit) | |
if __name__ == "__main__": | |
if len(sys.argv) == 1: | |
print("my_commit.py: no message provided.") | |
exit(1) | |
message = " ".join(sys.argv[1:]) | |
hash_ = write_commit(message) | |
print(f"Created commit {hash_} !") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment