git.py: introduce Blob abstraction

Some blob representations (such as embedded images) require raw blob
content, however, the 'blob' view is unconditionally handed cooked
(utf8-encoded) content, thus representations which need raw content are
forced to reload the blob in raw form, which is ugly and expensive (due
to shelling out to git-cat-file a second time).

The ultimate goal is to eliminate the wasteful blob reloading when raw
content is needed. As a first step, introduce a Blob abstraction to be
returned by Repo.blob() rather than the cooked content. A subsequent
change will flesh out Blob, allowing it to return raw or cooked content
on demand without the client having to specify one or the other when
invoking Repo.blob().

Signed-off-by: Eric Sunshine <sunshine@sunshineco.com>
Signed-off-by: Alberto Bertogli <albertito@blitiri.com.ar>
This commit is contained in:
Eric Sunshine 2015-01-13 04:57:09 -05:00 committed by Alberto Bertogli
parent 6b83e32bc1
commit 0ba89d75e6
3 changed files with 16 additions and 7 deletions

13
git.py

@ -340,7 +340,7 @@ class Repo:
return Tree(self, ref)
def blob(self, path, ref = None, raw = False):
"""Returns the contents of the given path."""
"""Returns a Blob instance for the given path."""
if not ref:
ref = self.branch
cmd = self.cmd('cat-file')
@ -356,7 +356,7 @@ class Repo:
if not head or head.strip().endswith('missing'):
return None
return out.read()
return Blob(out.read(), raw)
def last_commit_timestamp(self):
"""Return the timestamp of the last commit."""
@ -555,3 +555,12 @@ class Tree:
# manipulate otherwise.
yield otype, smstr(name), size
class Blob:
"""A git blob."""
def __init__(self, content, raw):
if raw:
self.raw_content = content
else:
self.utf8_content = content

@ -107,5 +107,5 @@ def embed_image_blob(repo, dirname, fname):
raw_blob = repo.blob(dirname + fname, raw = True)
return '<img style="max-width:100%;" src="data:{0};base64,{1}" />'.format( \
mimetype, base64.b64encode(raw_blob))
mimetype, base64.b64encode(raw_blob.raw_content))

@ -42,12 +42,12 @@
% if can_embed_image(repo, fname.unicode):
{{!embed_image_blob(repo, dirname.raw, fname.raw)}}
% elif can_markdown(repo, fname.unicode):
{{!markdown_blob(blob)}}
% elif can_colorize(blob):
{{!colorize_blob(fname.unicode, blob)}}
{{!markdown_blob(blob.utf8_content)}}
% elif can_colorize(blob.utf8_content):
{{!colorize_blob(fname.unicode, blob.utf8_content)}}
% else:
<pre class="blob-body">
{{blob}}
{{blob.utf8_content}}
</pre>
% end