Add checkout

This commit is contained in:
Nathan McRae 2024-07-07 10:46:01 -07:00
parent b1df1875c7
commit cd2aca3ca5

View File

@ -566,3 +566,44 @@ def ls_tree(repo, ref, recursive=None, prefix=""):
))
else: # This is a branch (vs. leaf), recurse
ls_tree(repo, item.sha, recursive, os.path.join(prefix, item.path))
argsp = argsubparsers.add_parser("checkout", help="Checkout a commit inside of a directory.")
argsp.add_argument("commit",
help="The commit or tree to checkout.")
argsp.add_argument("path",
help="The EMPTY directory to checkout on.")
def cmd_checkout(args):
repo = repo_find()
obj = object_read(repo, object_find(repo, args.commit))
# If the object is a commit, we grab its tree
if obj.fmt == b'commit':
obj = object_read(repo, obj.kvlm[b'tree'].decode("ascii"))
# Verify the path is an empty directory
if os.path.exists(args.path):
if not os.path.isdir(args.path):
raise Exception(f"This is not a directory: '{ags.path}'")
if os.listdir(args.path):
raise Exception(f"Directory '{args.path}' is not empty")
else:
os.makedirs(args.path)
tree_checkout(repo, obj, os.path.realpath(args.path))
def tree_checkout(repo, tree, path):
for item in tree.items:
obj = object_read(repo, item.sha)
dest = os.path.join(path, item.path)
if obj.fmt == b'tree':
os.mkdir(dest)
tree_checkout(repo, obj, dest)
elif obj.fmt == b'blob':
# TODO: Support symlinks (identified by mode 12*****)
with open(dest, 'wb') as f:
f.write(obj.blobdata)