From 8dc98aa77f93f10cfac27c8477fa04a5ce506829 Mon Sep 17 00:00:00 2001
From: Patrick Pfeifer <p2000@mailinator.com>
Date: Sat, 16 Jun 2012 00:16:25 +0200
Subject: [PATCH 1/2] detect renames in "git diff --raw" output

potentially fixes https://github.com/gitpython-developers/GitPython/issues/36
---
 git/diff.py | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/git/diff.py b/git/diff.py
index d1c6c0ac3..93ef514f0 100644
--- a/git/diff.py
+++ b/git/diff.py
@@ -310,12 +310,11 @@ def _index_from_patch_format(cls, repo, stream):
 	@classmethod
 	def _index_from_raw_format(cls, repo, stream):
 		"""Create a new DiffIndex from the given stream which must be in raw format.
-		:note: 
-			This format is inherently incapable of detecting renames, hence we only 
-			modify, delete and add files
 		:return: git.DiffIndex"""
 		# handles 
 		# :100644 100644 6870991011cc8d9853a7a8a6f02061512c6a8190 37c5e30c879213e9ae83b21e9d11e55fc20c54b7 M	.gitignore
+		# or
+		# :100644 100644 4aab7ea753e2867dd464f2a50dd266d426ddc8c8 4aab7ea753e2867dd464f2a50dd266d426ddc8c8 R100 src/bootstrap/package.json	package.json
 		index = DiffIndex()
 		for line in stream:
 			if not line.startswith(":"):
@@ -323,8 +322,12 @@ def _index_from_raw_format(cls, repo, stream):
 			# END its not a valid diff line
 			old_mode, new_mode, a_blob_id, b_blob_id, change_type, path = line[1:].split(None, 5)
 			path = path.strip()
-			a_path = path
-			b_path = path
+			if change_type[0] != 'R':
+				a_path = b_path = path
+				rename_from = rename_to = None
+			else:
+				a_path, b_path = path.split('\t')
+				rename_from, rename_to = a_path, b_path
 			deleted_file = False
 			new_file = False
 			
@@ -339,7 +342,7 @@ def _index_from_raw_format(cls, repo, stream):
 			# END add/remove handling
 			
 			diff = Diff(repo, a_path, b_path, a_blob_id, b_blob_id, old_mode, new_mode,
-						new_file, deleted_file, None, None, '')
+						new_file, deleted_file, rename_from, rename_to, '')
 			index.append(diff)
 		# END for each line
 		

From 3da67f3c498e607e9bc5f9e24564763402303f39 Mon Sep 17 00:00:00 2001
From: Patrick Pfeifer <p2000@mailinator.com>
Date: Sat, 16 Jun 2012 14:34:45 +0200
Subject: [PATCH 2/2] add tests for git.diff.Diff._index_from_raw_format()

---
 git/test/fixtures/diff_rename_raw |  4 ++++
 git/test/test_diff.py             | 21 +++++++++++++++++++++
 2 files changed, 25 insertions(+)
 create mode 100644 git/test/fixtures/diff_rename_raw

diff --git a/git/test/fixtures/diff_rename_raw b/git/test/fixtures/diff_rename_raw
new file mode 100644
index 000000000..14e617a7d
--- /dev/null
+++ b/git/test/fixtures/diff_rename_raw
@@ -0,0 +1,4 @@
+:000000 100644 0000000000000000000000000000000000000000 8b137891791fe96927ad78e64b0aad7bded08bdc A	git/test/refs/__init__.py
+:100644 100644 271924aa5bf43ef58a0b0dae5a356e502c48dcf8 271924aa5bf43ef58a0b0dae5a356e502c48dcf8 R100	git/test/test_reflog.py	git/test/refs/test_reflog.py
+:100644 100644 e49b23abc5c47f26e8cf64d46aa6851593ce1404 e49b23abc5c47f26e8cf64d46aa6851593ce1404 R100	git/test/test_refs.py	git/test/refs/test_refs.py
+:100644 100644 b9a0b617b66962d2c2ba211641675d06f591461f b9a0b617b66962d2c2ba211641675d06f591461f R100	git/test/test_git.py	git/test/test_cmd.py
diff --git a/git/test/test_diff.py b/git/test/test_diff.py
index 79f038e84..55ad3379c 100644
--- a/git/test/test_diff.py
+++ b/git/test/test_diff.py
@@ -51,6 +51,19 @@ def test_diff_with_rename(self):
 		assert_equal(diff.rename_from, 'AUTHORS')
 		assert_equal(diff.rename_to, 'CONTRIBUTORS')
 
+	def test_diff_with_rename_raw(self):
+		output = StringProcessAdapter(fixture('diff_rename_raw'))
+		diffs = Diff._index_from_raw_format(self.rorepo, output.stdout)
+		self._assert_diff_format(diffs)
+
+		diffs = filter(lambda d: d.renamed, diffs)
+		assert_equal(3, len(diffs))
+
+		diff = diffs[0]
+		assert_true(diff.renamed)
+		assert_equal(diff.rename_from, 'git/test/test_reflog.py')
+		assert_equal(diff.rename_to, 'git/test/refs/test_reflog.py')
+
 	def test_diff_patch_format(self):
 		# test all of the 'old' format diffs for completness - it should at least
 		# be able to deal with it
@@ -98,6 +111,14 @@ def test_diff_interface(self):
 				# END for each path option
 			# END for each other side
 		# END for each commit
+
+		# test rename detection
+		rename_commit = self.rorepo.rev_parse('4772fe0')
+		rename_diffs = rename_commit.parents[0].diff(rename_commit, M=True)
+		rename_diffs = filter(lambda d: d.renamed, rename_diffs)
+		assert len(rename_diffs) == 3
+		assert rename_diffs[0].rename_from == rename_diffs[0].a_blob.path
+		assert rename_diffs[0].rename_to == rename_diffs[0].b_blob.path
 		
 		# assert we could always find at least one instance of the members we 
 		# can iterate in the diff index - if not this indicates its not working correctly