Add 'commit' command
This commit is contained in:
parent
ff78648324
commit
3f49d9f7db
116
libwyag.py
116
libwyag.py
@ -1342,3 +1342,119 @@ def add(repo, paths, delete=True, skip_missing=False):
|
||||
index.entries.append(entry)
|
||||
|
||||
index_write(repo, index)
|
||||
|
||||
argsp = argsubparsers.add_parser("commit", help="Record changes to the repository.")
|
||||
|
||||
argsp.add_argument("-m",
|
||||
metavar="mesaage",
|
||||
dest="message",
|
||||
help="Message to associate with this commit.")
|
||||
|
||||
def gitconfig_read():
|
||||
xdg_config_home = os.environ["XDG_CONFIG_HOME"] if "XDG_CONFIG_HOME" in os.environ else "~/.config"
|
||||
config_files = [
|
||||
os.path.expanduser(join_path(xdg_config_home, "git/config")).replace("\\", "/"),
|
||||
#os.path.expanduser("~/.gitconfig").replace("\\", "/")
|
||||
]
|
||||
|
||||
config = configparser.ConfigParser()
|
||||
config.read(config_files)
|
||||
return config
|
||||
|
||||
def gitconfig_user_get(config):
|
||||
if "user" in config:
|
||||
if "name" in config["user"] and "email" in config["user"]:
|
||||
return f"{config['user']['name']} <{config['user']['email']}>"
|
||||
return None
|
||||
|
||||
def tree_from_index(repo, index):
|
||||
contents = dict()
|
||||
contents[""] = list()
|
||||
|
||||
# Convert entries to dictionary where keys are directories, and values are
|
||||
# lists of directory contents.
|
||||
for entry in index.entries:
|
||||
dirname = os.path.dirname(entry.name).replace("\\", "/")
|
||||
|
||||
# We create all dictionary entries up to root (""). We need them *all*
|
||||
# because even if a directory holds no files it will contain at least
|
||||
# a tree.
|
||||
key = dirname
|
||||
while key != "":
|
||||
if not key in contents:
|
||||
contents[key] = list()
|
||||
key = os.path.dirname(key).replace("\\", "/")
|
||||
|
||||
contents[dirname].append(entry)
|
||||
|
||||
# Sort keys (= directories) by length, descending. This means that we'll
|
||||
# always encounter a given path before its parent, which is all we need,
|
||||
# since for each directory D we'll need to modify its parent P to add
|
||||
# D's tree.
|
||||
sorted_paths = sorted(contents.keys(), key=len, reverse=True)
|
||||
|
||||
sha = None
|
||||
|
||||
for path in sorted_paths:
|
||||
tree = GitTree()
|
||||
|
||||
for entry in contents[path]:
|
||||
# An entry can be a normal GitIndexEntry read from the index, or
|
||||
# a tree we've created.
|
||||
if isinstance(entry, GitIndexEntry):
|
||||
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])
|
||||
|
||||
tree.items.append(leaf)
|
||||
|
||||
sha = object_write(tree, repo)
|
||||
|
||||
parent = os.path.dirname(path).replace("\\", "/")
|
||||
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")
|
||||
|
||||
offset = int(timestamp.astimezone().utcoffset().total_seconds())
|
||||
hours = offset // 3600
|
||||
minutes = (offset & 3600) // 60
|
||||
tz = f"{'+' if offset > 0 else '-'}{hours:02}{minutes:02}"
|
||||
|
||||
if author == None:
|
||||
author = ""
|
||||
author = 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)
|
||||
|
||||
def cmd_commit(args):
|
||||
repo = repo_find()
|
||||
index = index_read(repo)
|
||||
tree = tree_from_index(repo, index)
|
||||
|
||||
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 on a branch, update that branch
|
||||
with open(GitRepository.repo_file(repo, join_path("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(commit + "\n")
|
||||
|
Loading…
Reference in New Issue
Block a user