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}")
|
case _ : raise Exception(f"Unknown type {fmt}")
|
||||||
|
|
||||||
return object_write(obj, repo)
|
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