Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions pyvcs/backends/bzr.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,16 @@ def __init__(self, *args, **kwargs):
def _rev_to_commit(self, rev):
# TODO: this doesn't yet handle the case of multiple parent revisions
current = self._branch.repository.revision_tree(rev.revision_id)
prev = self._branch.repository.revision_tree(rev.parent_ids[0])
if len(rev.parent_ids):
prev = self._branch.repository.revision_tree(rev.parent_ids[0])
else:
prev = self._branch.repository.revision_tree('null:')

delta = current.changes_from(prev)
files = [f[0] for f in delta.added + delta.removed + delta.renamed + delta.kind_changed + delta.modified]

diff_file = StringIO.StringIO()

diff_tree = diff.DiffTree(prev, current, diff_file)

self._branch.lock_read()
Expand Down Expand Up @@ -85,9 +89,7 @@ def get_recent_commits(self, since=None):

def list_directory(self, path, revision=None):
path = path.rstrip(os.path.sep)

tree = self._get_tree(revision)

dir_iter = tree.walkdirs(path)
try:
entries = dir_iter.next()
Expand Down
56 changes: 37 additions & 19 deletions pyvcs/backends/git.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from dulwich.repo import Repo
from dulwich import objects
from dulwich.errors import NotCommitError

from pyvcs.commit import Commit
from pyvcs.exceptions import CommitDoesNotExist, FileDoesNotExist, FolderDoesNotExist
Expand Down Expand Up @@ -63,41 +64,48 @@ def __init__(self, *args, **kwargs):

def _get_commit(self, commit_id):
try:
return self._repo.commit(commit_id)
return self._repo[commit_id]
except Exception, e:
raise CommitDoesNotExist("%s is not a commit" % commit_id)

def _get_obj(self, sha):
return self._repo.get_object(sha)

def _diff_files(self, commit_id1, commit_id2):
if commit_id1 == 'NULL':
commit_id1 = None
if commit_id2 == 'NULL':
commit_id2 = None
tree1 = self._get_obj(self._get_obj(commit_id1).tree) if commit_id1 else None
tree2 = self._get_obj(self._get_obj(commit_id2).tree) if commit_id2 else None
return sorted(get_differing_files(
self._repo,
self._get_obj(self._get_obj(commit_id1).tree),
self._get_obj(self._get_obj(commit_id2).tree),
tree1,
tree2,
))

def get_commit_by_id(self, commit_id):
commit = self._get_commit(commit_id)
files = self._diff_files(commit.id, commit.parents[0])
parent = commit.parents[0] if len(commit.parents) else 'NULL'
files = self._diff_files(commit.id, parent)
return Commit(commit.id, commit.committer,
datetime.fromtimestamp(commit.commit_time), commit.message, files,
lambda: generate_unified_diff(self, files, commit.parents[0], commit.id))
lambda: generate_unified_diff(self, files, parent, commit.id))

def get_recent_commits(self, since=None):
if since is None:
since = datetime.fromtimestamp(self._repo.commit(self._repo.head()).commit_time) - timedelta(days=5)
#since = datetime.fromtimestamp(self._repo.commit(self._repo.head()).commit_time) - timedelta(days=5)
since = datetime.fromtimestamp(self._repo[self._repo.head()].commit_time) - timedelta(days=5)
pending_commits = self._repo.get_refs().values()#[self._repo.head()]
history = {}
while pending_commits:
head = pending_commits.pop(0)
try:
commit = self._get_obj(head)
commit = self._repo[head]
except KeyError:
raise CommitDoesNotExist
if not hasattr(commit, 'commit_time'):
continue
if commit.id in history or datetime.fromtimestamp(commit.commit_time) <= since:
if not isinstance(commit, objects.Commit) or commit.id in history or\
datetime.fromtimestamp(commit.commit_time) <= since:
continue
history[commit.id] = commit
pending_commits.extend(commit.parents)
Expand All @@ -106,16 +114,21 @@ def get_recent_commits(self, since=None):
return sorted(commits, key=attrgetter('time'), reverse=True)

def list_directory(self, path, revision=None):
commit = self._get_commit(revision or self._repo.head())
tree = self._repo.tree(commit.tree)
if revision is None:
commit = self._get_commit(self._repo.head())
elif revision is 'NULL':
return ([],[])
else:
commit = self._get_commit(revision)
tree = self._repo[commit.tree]
path = filter(bool, path.split(os.path.sep))
while path:
part = path.pop(0)
found = False
for mode, name, hexsha in self._repo.tree(tree.id).entries():
for mode, name, hexsha in self._repo[tree.id].entries():
if part == name:
found = True
tree = self._repo.tree(hexsha)
tree = self._repo[hexsha]
break
if not found:
raise FolderDoesNotExist
Expand All @@ -128,17 +141,22 @@ def list_directory(self, path, revision=None):
return files, folders

def file_contents(self, path, revision=None):
commit = self._get_commit(revision or self._repo.head())
tree = self._repo.tree(commit.tree)
if revision is None:
commit = self._get_commit(self._repo.head())
elif revision is 'NULL':
return ''
else:
commit = self._get_commit(revision)
tree = self._repo[commit.tree]
path = path.split(os.path.sep)
path, filename = path[:-1], path[-1]
while path:
part = path.pop(0)
for mode, name, hexsha in self._repo.tree(tree.id).entries():
for mode, name, hexsha in self._repo[tree.id].entries():
if part == name:
tree = self._repo.tree(hexsha)
tree = self._repo[hexsha]
break
for mode, name, hexsha in tree.entries():
if name == filename:
return self._repo.get_object(hexsha).as_pretty_string()
return self._repo[hexsha].as_pretty_string()
raise FileDoesNotExist
18 changes: 18 additions & 0 deletions tests/setup_git_test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/sh

#NOTE: this script depends on git being installed and having access to the /tmp directory...

echo Setting up the directory for the git repository
mkdir /tmp/pyvcs-test
mkdir /tmp/pyvcs-test/git-test

cd /tmp/pyvcs-test/git-test
git init
echo this is a test README file for a mock project > README
echo print 'hello, world!' > hello_world.py
git add README
git add hello_world.py
git commit -m "initial add of files to repo"
echo this is a new line added to the README >> README
git commit -a -m "slight change to the README"

50 changes: 50 additions & 0 deletions tests/simple_git_tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#!/usr/bin/env python
from datetime import datetime
import unittest
import os
import subprocess

from pyvcs.backends import get_backend
from pyvcs.exceptions import FileDoesNotExist, FolderDoesNotExist, CommitDoesNotExist

class GitSimpleTest(unittest.TestCase):

def setUp(self):
git = get_backend('git')
ret = subprocess.call('./setup_git_test.sh')
self.repo = git.Repository('/tmp/pyvcs-test/git-test/')

def tearDown(self):
ret = subprocess.call('./teardown_git_test.sh')

def test_recent_commits(self):
recent_commits = self.repo.get_recent_commits()
self.assertEqual(len(recent_commits),2)

def test_commits(self):
recent_commits = self.repo.get_recent_commits()
commit = self.repo.get_commit_by_id(recent_commits[1].commit_id)
self.assert_(commit.message.startswith('initial add of files'))
self.assertEqual(commit.time.date(), datetime.today().date())
self.assertEqual(commit.files, ['README', 'hello_world.py'])
self.assert_('this is a test README file for a mock project' in commit.diff)
self.assertRaises(CommitDoesNotExist,self.repo.get_commit_by_id,'crap')

def test_list_directory(self):
files, folders = self.repo.list_directory('')
self.assertEqual(files, ['README', 'hello_world.py'])
self.assertEqual(folders, [])
self.assertRaises(FolderDoesNotExist, self.repo.list_directory, 'tests/awesometests/')

def test_file_contents(self):
contents = self.repo.file_contents('hello_world.py')
self.assertEqual(contents,'print hello, world!\n')
self.assertRaises(FileDoesNotExist, self.repo.file_contents, 'waybettertest.py')

def test_diffs(self):
recent_commits = self.repo.get_recent_commits()
self.assertEqual(self.repo._diff_files(recent_commits[0].commit_id,recent_commits[1].commit_id),['README'])


if __name__ == '__main__':
unittest.main()
2 changes: 2 additions & 0 deletions tests/teardown_git_test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/sh
rm -r -f /tmp/pyvcs-test