Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 97 additions & 1 deletion libtft.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
argsp.add_argument("-w", dest="write", action="store_true", help="Actually write the object into the database")
argsp.add_argument("path", help="Read object from <file>")

#subparser for commit
argsp = argsubparsers.add_parser("commit", help="Record changes to the repository.")
argsp.add_argument("-m", metavar="message", dest="message", help="Message to associate with this commit.")

def main(argv=sys.argv[1:]):
args = argparser.parse_args(argv)
Expand Down Expand Up @@ -364,7 +367,77 @@ def kvlm_serialize(kvlm):
def cat_file(repo, obj, fmt=None):
obj = object_read(repo, object_find(repo, obj, fmt=fmt))
sys.stdout.buffer.write(obj.serialize())


def gitconfig_user_get(config):
if "user" in config:
if "name" in config["user"] and "email" in config["user"]:
return "{} <{}>".format(config["user"]["name"], config["user"]["email"])
return None

def gitconfig_read():
xdg_config_home = os.environ["XDG_CONFIG_HOME"] if "XDG_CONFIG_HOME" in os.environ else "~/.config"
configfiles = [
os.path.expanduser(os.path.join(xdg_config_home, "git/config")),
os.path.expanduser("~/.gitconfig")
]
config = configparser.ConfigParser()
config.read(configfiles)
return config

def tree_from_index(repo, index):
contents = dict()
contents[""] = list()

for entry in index.entries:
dirname = os.path.dirname(entry.name)

key = dirname

while key != "":
if not key in contents:
contents[key] = list()
key = os.path.dirname(key)
contents[dirname].append(entry)

sorted_paths = sorted(contents.keys(), key=len, reverse=True)

sha = None

for path in sorted_paths:
tree = GitTree()

for entry in contents[path]:
if isinstance(entry, GitIndexEntry):
leaf_mode = "{:02o}{:04o}".format(entry.mode_type, entry.mode_perms).encode("ascii")
leaf = GitTreeLeaf(leaf_mode, path=os.path.basename(entry.name), sha=entry.sha)
else:
leaf = GitTreeLeaf(mode = b"040000", path=entry[0], sha=entry[1])
tree.items.append(leaf)
sha = object_write(tree, repo)
parent = os.path.dirname(path)
base = os.path.basename(path)
contents[parent].append((base, sha))
return sha

def commit_create(repo, tree, parent, author, timestamp, message):
commit = GitCommit()
commit.kvlm[b"tree"] = tree.encode("ascii")
if parent:
commit.kvlm[b"parent"] = parent.encode("ascii")

# Timezone
offset = int(timestamp.astimezone().utcoffset().total_seconds())
hours = offset // 3600
minutes = (offset % 3600) // 60
tz = "{}{:02}{:02}".format("+" if offset > 0 else "-", hours, minutes)

author += timestamp.strftime(" %s ") + tz

commit.kvlm[b"author"] = author.encode("utf8")
commit.kvlm[b"committer"] = author.encode("utf8")
commit.kvlm[None] = message.encode("utf8")
return object_write(commit, repo)

#Bride functions
def cmd_init(args):
"""Bridge function to initialize a new repository."""
Expand All @@ -380,3 +453,26 @@ def cmd_hash_object(args):
with open(args.path, "rb") as fd:
sha = object_hash(fd, args.type.encode(), repo)
print(sha)

def cmd_commit(args):
repo = repo_find()
index = index_read(repo)
# Create trees, grab back SHA for the root tree.
tree = tree_from_index(repo, index)

# Create the commit object itself
commit = commit_create(repo,
tree,
object_find(repo, "HEAD"),
gitconfig_user_get(gitconfig_read()),
datetime.now(),
args.message)

# Update HEAD so our commit is now the tip of the active branch.
active_branch = branch_get_active(repo)
if active_branch: # If we're on a branch, we update refs/heads/BRANCH
with open(repo_file(repo, os.path.join("refs/heads", active_branch)), "w") as fd:
fd.write(commit + "\n")
else: # Otherwise, we update HEAD itself.
with open(repo_file(repo, "HEAD"), "w") as fd:
fd.write("\n")