summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuido Günther <agx@sigxcpu.org>2013-04-08 10:20:23 +0200
committerGuido Günther <agx@sigxcpu.org>2013-04-13 14:26:24 +0200
commit8fd5ec31272984a7fcff628c50b4c22d7e4107ec (patch)
tree412e290a6fcd4000a3671b8e22e3014d67aaa22d
parent6eb2ddcdd4909621e89d5b0c1360eb68bc73f901 (diff)
downloadgit-buildpackage-8fd5ec31272984a7fcff628c50b4c22d7e4107ec.tar.gz
git-buildpackage-8fd5ec31272984a7fcff628c50b4c22d7e4107ec.tar.bz2
git-buildpackage-8fd5ec31272984a7fcff628c50b4c22d7e4107ec.zip
Add minimal vfs interface
so we can access blobs in git as file like objects
-rw-r--r--gbp/git/vfs.py65
-rw-r--r--tests/test_GitVfs.py55
2 files changed, 120 insertions, 0 deletions
diff --git a/gbp/git/vfs.py b/gbp/git/vfs.py
new file mode 100644
index 00000000..81649eb9
--- /dev/null
+++ b/gbp/git/vfs.py
@@ -0,0 +1,65 @@
+# vim: set fileencoding=utf-8 :
+#
+# (C) 2013 Guido Günther <agx@sigxcpu.org>
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+"""Make blobs in a git repository accessible as file like objects"""
+
+import StringIO
+from gbp.git.repository import GitRepositoryError
+
+class GitVfs(object):
+
+ class _File(object):
+ """
+ A file like object representing a file in git
+
+ @todo: We don't support any byte ranges yet.
+ """
+ def __init__(self, content):
+ self._iter = iter
+ self._data = StringIO.StringIO(content)
+
+ def readline(self):
+ return self._data.readline()
+
+ def readlines(self):
+ return self._data.readlines()
+
+ def read(self, size=None):
+ return self._data.read(size)
+
+ def close(self):
+ return self.close()
+
+ def __init__(self, repo, committish=None):
+ """
+ Access files in a unpaced Debian source package.
+
+ @param repo: the git repository to act on
+ @param committish: the committish to act on
+ """
+ self._repo = repo
+ self._committish = committish or 'HEAD'
+
+ def open(self, path, flags=None):
+ flags = flags or 'r'
+
+ if flags != 'r':
+ raise NotImplementedError("Only reading supported so far")
+ try:
+ return GitVfs._File(self._repo.show(
+ "%s:%s" % (self._committish, path)))
+ except GitRepositoryError as e:
+ raise IOError(e)
diff --git a/tests/test_GitVfs.py b/tests/test_GitVfs.py
new file mode 100644
index 00000000..c4e26940
--- /dev/null
+++ b/tests/test_GitVfs.py
@@ -0,0 +1,55 @@
+# vim: set fileencoding=utf-8 :
+
+"""
+Test L{gbp.git.GitVfs}
+"""
+
+import os
+import gbp.log
+
+from . import context
+
+gbp.log.setup(color=False, verbose=True)
+
+def test_read():
+ repo_dir = context.new_tmpdir(__name__)
+ """
+ Create a repository
+
+ Methods tested:
+ - L{gbp.git.GitVfs.open}
+ - L{gbp.git._File.readline}
+ - L{gbp.git._File.readlines}
+ - L{gbp.git._File.read}
+ - L{gbp.git._File.close}
+
+ >>> import os, gbp.git.vfs
+ >>> repo = gbp.git.GitRepository.create(str(repo_dir))
+ >>> f = file(os.path.join(repo.path, 'foo.txt'), 'w')
+ >>> content = 'al pha\\na\\nb\\nc'
+ >>> f.write('al pha\\na\\nb\\nc')
+ >>> f.close()
+ >>> repo.add_files(repo.path, force=True)
+ >>> repo.commit_all(msg="foo")
+ >>> vfs = gbp.git.vfs.GitVfs(repo, 'HEAD')
+ >>> gf = vfs.open('foo.txt')
+ >>> gf.readline()
+ 'al pha\\n'
+ >>> gf.readline()
+ 'a\\n'
+ >>> gf.readlines()
+ ['b\\n', 'c']
+ >>> gf.readlines()
+ []
+ >>> gf.readline()
+ ''
+ >>> gf.readline()
+ ''
+ >>> gbp.git.vfs.GitVfs(repo, 'HEAD').open('foo.txt').read() == content
+ True
+ >>> gf = vfs.open('doesnotexist')
+ Traceback (most recent call last):
+ ...
+ IOError: can't get HEAD:doesnotexist: fatal: Path 'doesnotexist' does not exist in 'HEAD'
+ >>> context.teardown()
+ """