Add log
This commit is contained in:
parent
a057ea5831
commit
7ef46efb82
130
libwyag.py
130
libwyag.py
|
@ -327,3 +327,133 @@ def object_hash(fd, fmt, repo=None):
|
|||
case _ : raise Exception(f"Unknown type {fmt}")
|
||||
|
||||
return object_write(obj, repo)
|
||||
|
||||
def kvlm_parse(raw, start=0, dct=None):
|
||||
if not dct:
|
||||
dct = collections.OrderedDict()
|
||||
# You CANNOT declare the argument as dct=OrderedDict() or all
|
||||
# call to the functions will endlessly grow the same dict.
|
||||
|
||||
# This function is recursive: it reads a key/value pair, then call
|
||||
# itself back with the new position. So we first need to know
|
||||
# where we are: at a keyword, or already in the messageQ
|
||||
|
||||
# We search for the next space and the next newline.
|
||||
spc = raw.find(b' ', start)
|
||||
nl = raw.find(b'\n', start)
|
||||
|
||||
# If space appears before newline, we have a keyword. Otherwise,
|
||||
# it's the final message, which we just read to the end of the file.
|
||||
|
||||
# Base case
|
||||
# =========
|
||||
#
|
||||
# If newline appears first (or there's no space at all), we asume
|
||||
# a blank line. A blank line means the remainder of the data is the
|
||||
# message. We store it in the dictionary, with None as the key, and
|
||||
# return.
|
||||
if (spc < 0) or (nl < spc):
|
||||
assert nl == start
|
||||
dct[None] = raw[start+1:]
|
||||
return dct
|
||||
|
||||
# Recursive case
|
||||
# ==============
|
||||
#
|
||||
# We read a key-value pair and recurse for the next.
|
||||
key = raw[start:spc]
|
||||
|
||||
# Find the end of the value. Continuation lines begin with a
|
||||
# space, so we loop until we find a "\n" not followed by a space.
|
||||
end = start
|
||||
while True:
|
||||
end = raw.find(b'\n', end+1)
|
||||
if raw[end+1] != ord(' '): break
|
||||
|
||||
value = raw[spc+1:end].replace(b'\n ', b'\n')
|
||||
|
||||
# Don't overwrite existing data contents
|
||||
if key in dct:
|
||||
if type(dct[key]) == list:
|
||||
dct[key].append(value)
|
||||
else:
|
||||
dct[key] = [ dct[key], value ]
|
||||
else:
|
||||
dct[key] = value
|
||||
|
||||
return kvlm_parse(raw, start=end+1, dct=dct)
|
||||
|
||||
def kvlm_serialize(kvlm):
|
||||
ret = b''
|
||||
|
||||
# Output fiels
|
||||
for k in kvlm.keys():
|
||||
# Skip the message itself
|
||||
if k == None: continue
|
||||
val = kvlm[k]
|
||||
# Normalize to a list
|
||||
if type(val) != list:
|
||||
val = [ val ]
|
||||
|
||||
for v in val:
|
||||
ret += k + b' ' + (v.replace(b'\n', b'\n ')) + b'\n'
|
||||
|
||||
ret += b'\n' + kvlm[None] + b'\n'
|
||||
|
||||
return ret
|
||||
|
||||
class GitCommit(GitObject):
|
||||
fmt = b'commit'
|
||||
|
||||
def deserialize(self, data):
|
||||
self.kvlm = kvlm_parse(data)
|
||||
|
||||
def serialize(self):
|
||||
return kvlm_serialize(self.kvlm)
|
||||
|
||||
def init(self):
|
||||
self.kvlm = dict()
|
||||
|
||||
argsp = argsubparsers.add_parser("log", help="Display history of a given commit.")
|
||||
argsp.add_argument("commit",
|
||||
default="HEAD",
|
||||
nargs="?",
|
||||
help="Commit to start at.")
|
||||
|
||||
def cmd_log(args):
|
||||
repo = repo_find()
|
||||
|
||||
print("digraph wyaglog{")
|
||||
print(" node[shape=rect]")
|
||||
log_graphviz(repo, object_find(repo, args.commit), set())
|
||||
print("}")
|
||||
|
||||
def log_graphviz(repo, sha, seen):
|
||||
if sha in seen:
|
||||
return
|
||||
seen.add(sha)
|
||||
|
||||
commit = object_read(repo, sha)
|
||||
short_hash = sha[0:8]
|
||||
message = commit.kvlm[None].decode("utf8").strip()
|
||||
message = message.replace("\\", "\\\\")
|
||||
message = message.replace("\"", "\\\"")
|
||||
|
||||
if "\n" in message: # keep only the first line
|
||||
message = message[:message.index("\n")]
|
||||
print(f" c_{sha} [label=\"{sha[0:7]}: {message}\"]")
|
||||
assert commit.fmt==b'commit'
|
||||
|
||||
if not b'parent' in commit.kvlm.keys():
|
||||
# Base case: the initial commit.
|
||||
return
|
||||
|
||||
parents = commit.kvlm[b'parent']
|
||||
|
||||
if type(parents) != list:
|
||||
parents = [ parents ]
|
||||
|
||||
for p in parents:
|
||||
p = p.decode("ascii")
|
||||
print (f" c_{sha} -> c_{p}")
|
||||
log_graphviz(repo, p, seen)
|
||||
|
|
Loading…
Reference in New Issue
Block a user