diff --git a/libwyag.py b/libwyag.py index 37593bd..bf4ce4c 100644 --- a/libwyag.py +++ b/libwyag.py @@ -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)