git » git-arr » commit 0ba89d7

git.py: introduce Blob abstraction

author Eric Sunshine
2015-01-13 09:57:09 UTC
committer Alberto Bertogli
2015-01-13 19:51:44 UTC
parent 6b83e32bc1cc6adb831631e30de59b026971534a

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>

git.py +11 -2
utils.py +1 -1
views/blob.html +4 -4

diff --git a/git.py b/git.py
index 58b0c4c..78f5b1e 100644
--- a/git.py
+++ b/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
diff --git a/utils.py b/utils.py
index 46407bd..be6ab78 100644
--- a/utils.py
+++ b/utils.py
@@ -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))
 
diff --git a/views/blob.html b/views/blob.html
index e44ff99..f744cd9 100644
--- a/views/blob.html
+++ b/views/blob.html
@@ -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