summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Thiel <byronimo@gmail.com>2009-10-08 23:41:21 +0200
committerSebastian Thiel <byronimo@gmail.com>2009-10-08 23:41:21 +0200
commit88cc927ff2f8560cb2f224c313a5e5e8d64aa414 (patch)
tree819051315aa6c0fa8aac7cde5f5e57396a5c44b0
parent07eaa4ce2696a88ec0db6e91f191af1e48226aca (diff)
parentac13dbce276f81b5839987140cdd8db3d15d42a1 (diff)
downloadgitpython-88cc927ff2f8560cb2f224c313a5e5e8d64aa414.tar.gz
Merge branches 'doc_enhancements' and 'fixes_for_mainline' into improvements_for_mainline
* doc_enhancements: improved repo documentation Improved head and tag object documentation slightly Added docs for the error module Added missing information to docstrings of commit and stats module improved git.cmd documentation Improved documentation on Actor and Blob * fixes_for_mainline: repo_tests: fixed duplicate test-method name which would redefine the previous one which never ran Fixed Diff class which used Commits instead of Blobs - as Blobs contain the path ( in the 'name' member variable ), the a|b_path members of Diff have been removed. Tests were adjusted and run git.git.Git.__init__ takes None as default argument as the execute method handles this correctly Fixed git.blob.Blob.blame function which would return the text-per-commit as individual characters Conflicts: lib/git/cmd.py test/git/test_repo.py
-rw-r--r--CHANGES14
-rw-r--r--lib/git/blob.py2
-rw-r--r--lib/git/cmd.py2
-rw-r--r--lib/git/diff.py55
-rw-r--r--test/git/test_blob.py8
-rw-r--r--test/git/test_commit.py55
-rw-r--r--test/git/test_repo.py72
7 files changed, 97 insertions, 111 deletions
diff --git a/CHANGES b/CHANGES
index 8c67a7e5..63ca47e8 100644
--- a/CHANGES
+++ b/CHANGES
@@ -49,6 +49,20 @@ Repo
* Corrected ``commits_between`` always returning None instead of the reversed
list.
+
+0.1.X
+=====
+( Future Release )
+General
+-------
+* See changes in Diff class as your client code needs adjustments to work with it
+
+Diff
+----
+* Members a a_commit and b_commit renamed to a_blob and b_blob - they are populated
+ with Blob objects if possible
+* Members a_path and b_path removed as this information is kept in the blobs
+
0.1.5
=====
diff --git a/lib/git/blob.py b/lib/git/blob.py
index eea04490..82a41f73 100644
--- a/lib/git/blob.py
+++ b/lib/git/blob.py
@@ -152,7 +152,7 @@ class Blob(object):
m = re.search(r'^\t(.*)$', line)
text, = m.groups()
blames[-1][0] = c
- blames[-1][1] += text
+ blames[-1][1].append( text )
info = None
return blames
diff --git a/lib/git/cmd.py b/lib/git/cmd.py
index 796928b3..aef53350 100644
--- a/lib/git/cmd.py
+++ b/lib/git/cmd.py
@@ -35,7 +35,7 @@ class Git(object):
of the command to stdout.
Set its value to 'full' to see details about the returned values.
"""
- def __init__(self, git_dir):
+ def __init__(self, git_dir=None):
"""
Initialize this instance with:
diff --git a/lib/git/diff.py b/lib/git/diff.py
index 0216e061..44f55602 100644
--- a/lib/git/diff.py
+++ b/lib/git/diff.py
@@ -5,28 +5,44 @@
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
import re
-import commit
+import blob
class Diff(object):
"""
A Diff contains diff information between two commits.
+
+ It contains two sides a and b of the diff, members are prefixed with
+ "a" and "b" respectively to inidcate that.
+
+ Diffs keep information about the changed blob objects, the file mode, renames,
+ deletions and new files.
+
+ There are a few cases where None has to be expected as member variable value:
+
+ ``New File``::
+
+ a_mode is None
+ a_blob is None
+
+ ``Deleted File``::
+
+ b_mode is None
+ b_blob is NOne
"""
- def __init__(self, repo, a_path, b_path, a_commit, b_commit, a_mode,
+ def __init__(self, repo, a_path, b_path, a_blob, b_blob, a_mode,
b_mode, new_file, deleted_file, rename_from,
rename_to, diff):
self.repo = repo
- self.a_path = a_path
- self.b_path = b_path
- if not a_commit or re.search(r'^0{40}$', a_commit):
- self.a_commit = None
+ if not a_blob or re.search(r'^0{40}$', a_blob):
+ self.a_blob = None
else:
- self.a_commit = commit.Commit(repo, id=a_commit)
- if not b_commit or re.search(r'^0{40}$', b_commit):
- self.b_commit = None
+ self.a_blob = blob.Blob(repo, id=a_blob, mode=a_mode, name=a_path)
+ if not b_blob or re.search(r'^0{40}$', b_blob):
+ self.b_blob = None
else:
- self.b_commit = commit.Commit(repo, id=b_commit)
+ self.b_blob = blob.Blob(repo, id=b_blob, mode=b_mode, name=b_path)
self.a_mode = a_mode
self.b_mode = b_mode
@@ -39,6 +55,17 @@ class Diff(object):
@classmethod
def list_from_string(cls, repo, text):
+ """
+ Create a new diff object from the given text
+ ``repo``
+ is the repository we are operating on - it is required
+
+ ``text``
+ result of 'git diff' between two commits or one commit and the index
+
+ Returns
+ git.Diff[]
+ """
diffs = []
diff_header = re.compile(r"""
@@ -51,8 +78,8 @@ class Diff(object):
^new[ ]mode[ ](?P<new_mode>\d+)(?:\n|$))?
(?:^new[ ]file[ ]mode[ ](?P<new_file_mode>.+)(?:\n|$))?
(?:^deleted[ ]file[ ]mode[ ](?P<deleted_file_mode>.+)(?:\n|$))?
- (?:^index[ ](?P<a_commit>[0-9A-Fa-f]+)
- \.\.(?P<b_commit>[0-9A-Fa-f]+)[ ]?(?P<b_mode>.+)?(?:\n|$))?
+ (?:^index[ ](?P<a_blob>[0-9A-Fa-f]+)
+ \.\.(?P<b_blob>[0-9A-Fa-f]+)[ ]?(?P<b_mode>.+)?(?:\n|$))?
""", re.VERBOSE | re.MULTILINE).match
for diff in ('\n' + text).split('\ndiff --git')[1:]:
@@ -60,10 +87,10 @@ class Diff(object):
a_path, b_path, similarity_index, rename_from, rename_to, \
old_mode, new_mode, new_file_mode, deleted_file_mode, \
- a_commit, b_commit, b_mode = header.groups()
+ a_blob, b_blob, b_mode = header.groups()
new_file, deleted_file = bool(new_file_mode), bool(deleted_file_mode)
- diffs.append(Diff(repo, a_path, b_path, a_commit, b_commit,
+ diffs.append(Diff(repo, a_path, b_path, a_blob, b_blob,
old_mode or deleted_file_mode, new_mode or new_file_mode or b_mode,
new_file, deleted_file, rename_from, rename_to, diff[header.end():]))
diff --git a/test/git/test_blob.py b/test/git/test_blob.py
index 8f83f391..5bd74ff7 100644
--- a/test/git/test_blob.py
+++ b/test/git/test_blob.py
@@ -69,6 +69,7 @@ class TestBlob(object):
git.return_value = fixture('blame')
b = Blob.blame(self.repo, 'master', 'lib/git.py')
assert_equal(13, len(b))
+ assert_equal( 2, len(b[0]) )
# assert_equal(25, reduce(lambda acc, x: acc + len(x[-1]), b))
assert_equal(hash(b[0][0]), hash(b[9][0]))
c = b[0][0]
@@ -83,6 +84,13 @@ class TestBlob(object):
assert_equal('tom@mojombo.com', c.committer.email)
assert_equal(time.gmtime(1191997100), c.committed_date)
assert_equal('initial grit setup', c.message)
+
+ # test the 'lines per commit' entries
+ tlist = b[0][1]
+ assert_true( tlist )
+ assert_true( isinstance( tlist[0], basestring ) )
+ assert_true( len( tlist ) < sum( len(t) for t in tlist ) ) # test for single-char bug
+
def test_should_return_appropriate_representation(self):
blob = Blob(self.repo, **{'id': 'abc'})
diff --git a/test/git/test_commit.py b/test/git/test_commit.py
index 3e37a7a4..c36d0c72 100644
--- a/test/git/test_commit.py
+++ b/test/git/test_commit.py
@@ -37,18 +37,19 @@ class TestCommit(object):
assert_equal(15, len(diffs))
- assert_equal('.gitignore', diffs[0].a_path)
- assert_equal('.gitignore', diffs[0].b_path)
- assert_equal('4ebc8aea50e0a67e000ba29a30809d0a7b9b2666', diffs[0].a_commit.id)
- assert_equal('2dd02534615434d88c51307beb0f0092f21fd103', diffs[0].b_commit.id)
- assert_equal('100644', diffs[0].b_mode)
+ assert_equal('.gitignore', diffs[0].a_blob.name)
+ assert_equal('.gitignore', diffs[0].b_blob.name)
+ assert_equal('4ebc8aea50e0a67e000ba29a30809d0a7b9b2666', diffs[0].a_blob.id)
+ assert_equal('2dd02534615434d88c51307beb0f0092f21fd103', diffs[0].b_blob.id)
+ assert_equal('100644', diffs[0].b_blob.mode)
assert_equal(False, diffs[0].new_file)
assert_equal(False, diffs[0].deleted_file)
assert_equal("--- a/.gitignore\n+++ b/.gitignore\n@@ -1 +1,2 @@\n coverage\n+pkg", diffs[0].diff)
- assert_equal('lib/grit/actor.rb', diffs[5].a_path)
- assert_equal(None, diffs[5].a_commit)
- assert_equal('f733bce6b57c0e5e353206e692b0e3105c2527f4', diffs[5].b_commit.id)
+ assert_equal('lib/grit/actor.rb', diffs[5].b_blob.name)
+ assert_equal(None, diffs[5].a_blob)
+ assert_equal('f733bce6b57c0e5e353206e692b0e3105c2527f4', diffs[5].b_blob.id)
+ assert_equal( None, diffs[5].a_mode )
assert_equal(True, diffs[5].new_file)
assert_true(git.called)
@@ -88,7 +89,7 @@ class TestCommit(object):
diffs = Commit.diff(self.repo, '59ddc32', ['lib'])
assert_equal(1, len(diffs))
- assert_equal('lib/grit/diff.rb', diffs[0].a_path)
+ assert_equal('lib/grit/diff.rb', diffs[0].a_blob.name)
assert_true(git.called)
assert_equal(git.call_args, (('diff', '-M', '59ddc32', '--', 'lib'), {'full_index': True}))
@@ -100,7 +101,7 @@ class TestCommit(object):
diffs = Commit.diff(self.repo, '59ddc32', '13d27d5', ['lib'])
assert_equal(1, len(diffs))
- assert_equal('lib/grit/commit.rb', diffs[0].a_path)
+ assert_equal('lib/grit/commit.rb', diffs[0].a_blob.name)
assert_true(git.called)
assert_equal(git.call_args, (('diff', '-M', '59ddc32', '13d27d5', '--', 'lib'), {'full_index': True}))
@@ -114,18 +115,18 @@ class TestCommit(object):
assert_equal(15, len(diffs))
- assert_equal('.gitignore', diffs[0].a_path)
- assert_equal('.gitignore', diffs[0].b_path)
- assert_equal('4ebc8aea50e0a67e000ba29a30809d0a7b9b2666', diffs[0].a_commit.id)
- assert_equal('2dd02534615434d88c51307beb0f0092f21fd103', diffs[0].b_commit.id)
- assert_equal('100644', diffs[0].b_mode)
+ assert_equal('.gitignore', diffs[0].a_blob.name)
+ assert_equal('.gitignore', diffs[0].b_blob.name)
+ assert_equal('4ebc8aea50e0a67e000ba29a30809d0a7b9b2666', diffs[0].a_blob.id)
+ assert_equal('2dd02534615434d88c51307beb0f0092f21fd103', diffs[0].b_blob.id)
+ assert_equal('100644', diffs[0].b_blob.mode)
assert_equal(False, diffs[0].new_file)
assert_equal(False, diffs[0].deleted_file)
assert_equal("--- a/.gitignore\n+++ b/.gitignore\n@@ -1 +1,2 @@\n coverage\n+pkg", diffs[0].diff)
- assert_equal('lib/grit/actor.rb', diffs[5].a_path)
- assert_equal(None, diffs[5].a_commit)
- assert_equal('f733bce6b57c0e5e353206e692b0e3105c2527f4', diffs[5].b_commit.id)
+ assert_equal('lib/grit/actor.rb', diffs[5].b_blob.name)
+ assert_equal(None, diffs[5].a_blob)
+ assert_equal('f733bce6b57c0e5e353206e692b0e3105c2527f4', diffs[5].b_blob.id)
assert_equal(True, diffs[5].new_file)
assert_true(git.called)
@@ -144,18 +145,17 @@ class TestCommit(object):
assert_equal(10, len(diffs))
- assert_equal('History.txt', diffs[0].a_path)
- assert_equal('History.txt', diffs[0].b_path)
- assert_equal(None, diffs[0].a_commit)
- assert_equal('100644', diffs[0].b_mode)
- assert_equal('81d2c27608b352814cbe979a6acd678d30219678', diffs[0].b_commit.id)
+ assert_equal('History.txt', diffs[0].b_blob.name)
+ assert_equal(None, diffs[0].a_blob)
+ assert_equal('100644', diffs[0].b_blob.mode)
+ assert_equal('81d2c27608b352814cbe979a6acd678d30219678', diffs[0].b_blob.id)
assert_equal(True, diffs[0].new_file)
assert_equal(False, diffs[0].deleted_file)
assert_equal("--- /dev/null\n+++ b/History.txt\n@@ -0,0 +1,5 @@\n+== 1.0.0 / 2007-10-09\n+\n+* 1 major enhancement\n+ * Birthday!\n+", diffs[0].diff)
- assert_equal('lib/grit.rb', diffs[5].a_path)
- assert_equal(None, diffs[5].a_commit)
- assert_equal('32cec87d1e78946a827ddf6a8776be4d81dcf1d1', diffs[5].b_commit.id)
+ assert_equal('lib/grit.rb', diffs[5].b_blob.name)
+ assert_equal(None, diffs[5].a_blob)
+ assert_equal('32cec87d1e78946a827ddf6a8776be4d81dcf1d1', diffs[5].b_blob.id)
assert_equal(True, diffs[5].new_file)
assert_true(git.called)
@@ -181,7 +181,10 @@ class TestCommit(object):
commit.__bake_it__()
diffs = commit.diffs
+ # in case of mode-only changes, there is no blob
assert_equal(23, len(diffs))
+ assert_equal(None, diffs[0].a_blob)
+ assert_equal(None, diffs[0].b_blob)
assert_equal('100644', diffs[0].a_mode)
assert_equal('100755', diffs[0].b_mode)
diff --git a/test/git/test_repo.py b/test/git/test_repo.py
index c0236799..82f27001 100644
--- a/test/git/test_repo.py
+++ b/test/git/test_repo.py
@@ -185,7 +185,7 @@ class TestRepo(object):
assert_equal(git.call_args, (('diff', 'master^', 'master', '--', 'foo/bar', 'foo/baz'), {}))
@patch_object(Git, '_call_process')
- def test_diff(self, git):
+ def test_diff_with_parents(self, git):
git.return_value = fixture('diff_p')
diffs = self.repo.commit_diff('master')
@@ -193,10 +193,10 @@ class TestRepo(object):
assert_true(git.called)
def test_archive_tar(self):
- assert self.repo.archive_tar()
+ self.repo.archive_tar()
def test_archive_tar_gz(self):
- assert self.repo.archive_tar_gz()
+ self.repo.archive_tar_gz()
@patch('git.utils.touch')
def test_enable_daemon_serve(self, touch):
@@ -207,19 +207,6 @@ class TestRepo(object):
self.repo.daemon_serve = True
assert_true(self.repo.daemon_serve)
- # @patch_object(os.path, 'exists')
- # @patch_object('__builtin__', 'open')
- # def test_alternates_with_two_alternates(self, exists, read):
- # # File.expects(:exist?).with("#{absolute_project_path}/.git/objects/info/alternates").returns(true)
- # # File.expects(:read).returns("/path/to/repo1/.git/objects\n/path/to/repo2.git/objects\n")
- # exists.return_value = True
- # read.return_value = ("/path/to/repo1/.git/objects\n/path/to/repo2.git/objects\n")
- #
- # assert_equal(["/path/to/repo1/.git/objects", "/path/to/repo2.git/objects"], self.repo.alternates)
- #
- # assert_true(exists.called)
- # assert_true(read.called)
- #
@patch_object(os.path, 'exists')
def test_alternates_no_file(self, os):
os.return_value = False
@@ -227,32 +214,6 @@ class TestRepo(object):
assert_true(os.called)
- # @patch_object(os.path, 'exists')
- # def test_alternates_setter_ok(self, os):
- # os.return_value = True
- # alts = ['/path/to/repo.git/objects', '/path/to/repo2.git/objects']
- #
- # # File.any_instance.expects(:write).with(alts.join("\n"))
- #
- # self.repo.alternates = alts
- #
- # assert_true(os.called)
- # # assert_equal(os.call_args, ((alts,), {}))
- # # for alt in alts:
- #
- # @patch_object(os.path, 'exists')
- # @raises(NoSuchPathError)
- # def test_alternates_setter_bad(self, os):
- # os.return_value = False
- #
- # alts = ['/path/to/repo.git/objects']
- # # File.any_instance.expects(:write).never
- # self.repo.alternates = alts
- #
- # for alt in alts:
- # assert_true(os.called)
- # assert_equal(os.call_args, (alt, {}))
-
@patch_object(os, 'remove')
def test_alternates_setter_empty(self, os):
self.repo.alternates = []
@@ -278,33 +239,6 @@ class TestRepo(object):
assert_true(git.called)
assert_equal(git.call_args, (('log', 'master', '--', 'file.rb'), {'pretty': 'raw', 'max_count': 1}))
- # @patch_object(Git, '_call_process')
- # @patch_object(Git, '_call_process')
- # def test_commit_deltas_from_nothing_new(self, gitb, gita):
- # gitb.return_value = fixture("rev_list_delta_b")
- # gita.return_value = fixture("rev_list_delta_a")
- # other_repo = Repo(GIT_REPO)
- # # self.repo.git.expects(:rev_list).with({}, "master").returns(fixture("rev_list_delta_b"))
- # # other_repo.git.expects(:rev_list).with({}, "master").returns(fixture("rev_list_delta_a"))
- #
- # delta_commits = self.repo.commit_deltas_from(other_repo)
- # assert_equal(0, len(delta_commits))
- # assert_true(gitb.called)
- # assert_equal(gitb.call_args, (('rev_list', 'master'), {}))
- # assert_true(gita.called)
- # assert_equal(gita.call_args, (('rev_list', 'master'), {}))
- #
- # def test_commit_deltas_from_when_other_has_new(self):
- # other_repo = Repo(GIT_REPO)
- # # self.repo.git.expects(:rev_list).with({}, "master").returns(fixture("rev_list_delta_a"))
- # # other_repo.git.expects(:rev_list).with({}, "master").returns(fixture("rev_list_delta_b"))
- # # for ref in ['4c8124ffcf4039d292442eeccabdeca5af5c5017',
- # # '634396b2f541a9f2d58b00be1a07f0c358b999b3',
- # # 'ab25fd8483882c3bda8a458ad2965d2248654335']:
- # # Commit.expects(:find_all).with(other_repo, ref, :max_count => 1).returns([stub()])
- # delta_commits = self.repo.commit_deltas_from(other_repo)
- # assert_equal(3, len(delta_commits))
-
def test_is_dirty_with_bare_repository(self):
self.repo.bare = True
assert_false(self.repo.is_dirty)