From 3d08e348dbc95266b9f67861c4014d3f82a581c5 Mon Sep 17 00:00:00 2001 From: Nathan McRae Date: Sat, 13 Jul 2024 14:23:07 -0700 Subject: [PATCH] Fix some bugs --- libwyag.py | 58 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 22 deletions(-) diff --git a/libwyag.py b/libwyag.py index 7dde8f8..0bd1302 100644 --- a/libwyag.py +++ b/libwyag.py @@ -581,14 +581,14 @@ def ls_tree(repo, ref, recursive=None, prefix=""): type = item.mode[0:2] match type: - case b'04': raise Exception("Trees should point to subcommits, not other trees") + case b'04': type = "tree" case b'10': type = "blob" case b'12': type = "blob" # a symlink case b'16': type = "commit" # a submodule case b'sc': type = "subcommit" case _: raise Exception(f"Weird tree leaf mode {item.mode}") - if not (recursive and type=='subcommit'): # This is a leaf + if not (recursive and type=='tree'): # This is a leaf print("{0} {1} {2}\t{3}".format( "0" * (6 - len(item.mode)) + item.mode.decode("ascii"), # Git's ls-tree displays the type @@ -597,10 +597,12 @@ def ls_tree(repo, ref, recursive=None, prefix=""): item.sha, join_path(prefix, item.path) )) - else: # This is a subcommit - commit_obj = object_read(repo, item.sha) - tree_sha = commit_obj.kvlm[b'tree'].decode("ascii") - ls_tree(repo, tree_sha, recursive, join_path(prefix, item.path)) + if type=='subcommit': + commit_obj = object_read(repo, item.sha) + tree_sha = commit_obj.kvlm[b'tree'].decode("ascii") + ls_tree(repo, tree_sha, recursive, join_path(prefix, item.path)) + else: # This is a tree + ls_tree(repo, item.sha, recursive, join_path(prefix, item.path)) argsp = argsubparsers.add_parser("checkout", help="Checkout a commit inside of a directory.") @@ -1119,7 +1121,7 @@ def tree_to_dict(repo, ref, prefix=""): if (leaf.mode.startswith(b'04')): raise Exception("Tree should not be child of tree") - is_subcommit = leaf.mode.startswitch(b'sc') + is_subcommit = leaf.mode.startswith(b'sc') # Depending on the type, we either store the path (if it's a # blob, so a regular file), or recurse (if it's another tree, @@ -1386,9 +1388,10 @@ def create_commit_map(repo, commit): def create_commit_map_recurse(repo, commit, commit_map, path): """From a root commit, walk down the tree of subcommits. Returns a dict mapping - directory paths to commit objects. Note: doesn't include root commit.""" + directory paths to (commit hash, commit objects). + Note: doesn't include root commit.""" - tree_sha = commit.kvlm["tree"].decode('ascii') + tree_sha = commit.kvlm[b"tree"].decode('ascii') obj = object_read(repo, tree_sha) for item in obj.items: if len(item.mode) == 5: @@ -1405,9 +1408,12 @@ def create_commit_map_recurse(repo, commit, commit_map, path): case _: raise Exception(f"Weird tree leaf mode {item.mode}") if type == "subcommit": - fullpath = f"{path}/{item.path}" + if path == "": + fullpath = item.path + else: + fullpath = f"{path}/{item.path}" subcommit = object_read(repo, item.sha) - commit_map[fullpath] = subcommit + commit_map[fullpath] = (item.sha, subcommit) create_commit_map_recurse(repo, subcommit, commit_map, fullpath) @@ -1450,24 +1456,31 @@ def tree_from_index(repo, index, commit_map, author, commit_time, message): leaf_mode = f"{entry.mode_type:02o}{entry.mode_perms:04o}".encode("ascii") leaf = GitTreeLeaf(mode=leaf_mode, path=os.path.basename(entry.name), sha=entry.sha) else: # Tree. We've stored it as a pair: (basename, SHA) - leaf = GitTreeLeaf(mode=b"040000", path=entry[0], sha=entry[1]) + leaf = GitTreeLeaf(mode=b"sc0000", path=entry[0], sha=entry[1]) tree.items.append(leaf) sha = object_write(tree, repo) - subcommit = commit_map[path] + if path in commit_map: + (subcommit_hash, subcommit) = commit_map[path] + else: + subcommit = None - new_subcommit = commit_create(repo, - sha, - subcommit, - author, - commit_time, - message) + if subcommit == None or subcommit.kvlm[b'tree'] != sha.encode('ascii'): + new_subcommit = commit_create(repo, + sha, + subcommit, + author, + commit_time, + message) + else: + # Problem, subcommit is not a hash, but we need a hash + new_subcommit = subcommit_hash parent = os.path.dirname(path).replace("\\", "/") base = os.path.basename(path) - contents[parent].append((base, sha)) + contents[parent].append((base, new_subcommit)) return sha @@ -1495,7 +1508,8 @@ def commit_create(repo, tree, parent, author, timestamp, message): def cmd_commit(args): repo = repo_find() index = index_read(repo) - root_commit = object_find(repo, "HEAD") + root_commit_sha = object_find(repo, "HEAD") + root_commit = object_read(repo, root_commit_sha) commit_time = datetime.now() author = gitconfig_user_get(gitconfig_read()) @@ -1511,7 +1525,7 @@ def cmd_commit(args): commit = commit_create(repo, tree, - root_commit, + root_commit_sha, author, commit_time, args.message)