Commit a7f52745c95e5dd673a79a2281ccd7463ce00ffa
- Diff rendering mode:
- inline
- side by side
CHANGES
(11 / 7)
|   | |||
| 4 | 4 | ||
| 5 | 5 | 0.1.7 | |
| 6 | 6 | ======= | |
| 7 | This is a bugfix release and the last of its kind in 0.1.X, as 0.2.X will receive | ||
| 8 | a major redesign that will change the API. | ||
| 9 | |||
| 10 | Bugfixes | ||
| 11 | -------- | ||
| 12 | * Paths in Tree objects can now handle whitespace | ||
| 13 | * Blob.blame was returning incorrect results which has been fixed. | ||
| 14 | |||
| 7 | 15 | General | |
| 8 | 16 | ------- | |
| 9 | * See changes in Diff class as your client code needs adjustments to work with it | ||
| 10 | |||
| 11 | Diff | ||
| 12 | ---- | ||
| 13 | * Members a a_commit and b_commit renamed to a_blob and b_blob - they are populated | ||
| 14 | with Blob objects if possible | ||
| 15 | * Members a_path and b_path removed as this information is kept in the blobs | ||
| 17 | * The test suite now supports Mock 0.5 and above. The transition between Mock 0.4 | ||
| 18 | 0.5 changed the API which required adjustments. | ||
| 19 | * Many small enhancements done to the method documentation | ||
| 16 | 20 | ||
| 17 | 21 | ||
| 18 | 22 | 0.1.6 |
lib/git/diff.py
(14 / 41)
|   | |||
| 5 | 5 | # the BSD License: http://www.opensource.org/licenses/bsd-license.php | |
| 6 | 6 | ||
| 7 | 7 | import re | |
| 8 | import blob | ||
| 8 | import commit | ||
| 9 | 9 | ||
| 10 | 10 | class Diff(object): | |
| 11 | 11 | """ | |
| 12 | 12 | A Diff contains diff information between two commits. | |
| 13 | |||
| 14 | It contains two sides a and b of the diff, members are prefixed with | ||
| 15 | "a" and "b" respectively to inidcate that. | ||
| 16 | |||
| 17 | Diffs keep information about the changed blob objects, the file mode, renames, | ||
| 18 | deletions and new files. | ||
| 19 | |||
| 20 | There are a few cases where None has to be expected as member variable value: | ||
| 21 | |||
| 22 | ``New File``:: | ||
| 23 | |||
| 24 | a_mode is None | ||
| 25 | a_blob is None | ||
| 26 | |||
| 27 | ``Deleted File``:: | ||
| 28 | |||
| 29 | b_mode is None | ||
| 30 | b_blob is NOne | ||
| 31 | 13 | """ | |
| 32 | 14 | ||
| 33 | def __init__(self, repo, a_path, b_path, a_blob, b_blob, a_mode, | ||
| 15 | def __init__(self, repo, a_path, b_path, a_commit, b_commit, a_mode, | ||
| 34 | 16 | b_mode, new_file, deleted_file, rename_from, | |
| 35 | 17 | rename_to, diff): | |
| 36 | 18 | self.repo = repo | |
| 19 | self.a_path = a_path | ||
| 20 | self.b_path = b_path | ||
| 37 | 21 | ||
| 38 | if not a_blob or re.search(r'^0{40}$', a_blob): | ||
| 39 | self.a_blob = None | ||
| 22 | if not a_commit or re.search(r'^0{40}$', a_commit): | ||
| 23 | self.a_commit = None | ||
| 40 | 24 | else: | |
| 41 | self.a_blob = blob.Blob(repo, id=a_blob, mode=a_mode, name=a_path) | ||
| 42 | if not b_blob or re.search(r'^0{40}$', b_blob): | ||
| 43 | self.b_blob = None | ||
| 25 | self.a_commit = commit.Commit(repo, id=a_commit) | ||
| 26 | if not b_commit or re.search(r'^0{40}$', b_commit): | ||
| 27 | self.b_commit = None | ||
| 44 | 28 | else: | |
| 45 | self.b_blob = blob.Blob(repo, id=b_blob, mode=b_mode, name=b_path) | ||
| 29 | self.b_commit = commit.Commit(repo, id=b_commit) | ||
| 46 | 30 | ||
| 47 | 31 | self.a_mode = a_mode | |
| 48 | 32 | self.b_mode = b_mode | |
| … | … | ||
| 39 | 39 | ||
| 40 | 40 | @classmethod | |
| 41 | 41 | def list_from_string(cls, repo, text): | |
| 42 | """ | ||
| 43 | Create a new diff object from the given text | ||
| 44 | ``repo`` | ||
| 45 | is the repository we are operating on - it is required | ||
| 46 | |||
| 47 | ``text`` | ||
| 48 | result of 'git diff' between two commits or one commit and the index | ||
| 49 | |||
| 50 | Returns | ||
| 51 | git.Diff[] | ||
| 52 | """ | ||
| 53 | 42 | diffs = [] | |
| 54 | 43 | ||
| 55 | 44 | diff_header = re.compile(r""" | |
| … | … | ||
| 51 | 51 | ^new[ ]mode[ ](?P<new_mode>\d+)(?:\n|$))? | |
| 52 | 52 | (?:^new[ ]file[ ]mode[ ](?P<new_file_mode>.+)(?:\n|$))? | |
| 53 | 53 | (?:^deleted[ ]file[ ]mode[ ](?P<deleted_file_mode>.+)(?:\n|$))? | |
| 54 | (?:^index[ ](?P<a_blob>[0-9A-Fa-f]+) | ||
| 55 | \.\.(?P<b_blob>[0-9A-Fa-f]+)[ ]?(?P<b_mode>.+)?(?:\n|$))? | ||
| 54 | (?:^index[ ](?P<a_commit>[0-9A-Fa-f]+) | ||
| 55 | \.\.(?P<b_commit>[0-9A-Fa-f]+)[ ]?(?P<b_mode>.+)?(?:\n|$))? | ||
| 56 | 56 | """, re.VERBOSE | re.MULTILINE).match | |
| 57 | 57 | ||
| 58 | 58 | for diff in ('\n' + text).split('\ndiff --git')[1:]: | |
| … | … | ||
| 60 | 60 | ||
| 61 | 61 | a_path, b_path, similarity_index, rename_from, rename_to, \ | |
| 62 | 62 | old_mode, new_mode, new_file_mode, deleted_file_mode, \ | |
| 63 | a_blob, b_blob, b_mode = header.groups() | ||
| 63 | a_commit, b_commit, b_mode = header.groups() | ||
| 64 | 64 | new_file, deleted_file = bool(new_file_mode), bool(deleted_file_mode) | |
| 65 | 65 | ||
| 66 | diffs.append(Diff(repo, a_path, b_path, a_blob, b_blob, | ||
| 66 | diffs.append(Diff(repo, a_path, b_path, a_commit, b_commit, | ||
| 67 | 67 | old_mode or deleted_file_mode, new_mode or new_file_mode or b_mode, | |
| 68 | 68 | new_file, deleted_file, rename_from, rename_to, diff[header.end():])) | |
| 69 | 69 |
test/git/test_commit.py
(26 / 29)
|   | |||
| 37 | 37 | ||
| 38 | 38 | assert_equal(15, len(diffs)) | |
| 39 | 39 | ||
| 40 | assert_equal('.gitignore', diffs[0].a_blob.name) | ||
| 41 | assert_equal('.gitignore', diffs[0].b_blob.name) | ||
| 42 | assert_equal('4ebc8aea50e0a67e000ba29a30809d0a7b9b2666', diffs[0].a_blob.id) | ||
| 43 | assert_equal('2dd02534615434d88c51307beb0f0092f21fd103', diffs[0].b_blob.id) | ||
| 44 | assert_equal('100644', diffs[0].b_blob.mode) | ||
| 40 | assert_equal('.gitignore', diffs[0].a_path) | ||
| 41 | assert_equal('.gitignore', diffs[0].b_path) | ||
| 42 | assert_equal('4ebc8aea50e0a67e000ba29a30809d0a7b9b2666', diffs[0].a_commit.id) | ||
| 43 | assert_equal('2dd02534615434d88c51307beb0f0092f21fd103', diffs[0].b_commit.id) | ||
| 44 | assert_equal('100644', diffs[0].b_mode) | ||
| 45 | 45 | assert_equal(False, diffs[0].new_file) | |
| 46 | 46 | assert_equal(False, diffs[0].deleted_file) | |
| 47 | 47 | assert_equal("--- a/.gitignore\n+++ b/.gitignore\n@@ -1 +1,2 @@\n coverage\n+pkg", diffs[0].diff) | |
| 48 | 48 | ||
| 49 | assert_equal('lib/grit/actor.rb', diffs[5].b_blob.name) | ||
| 50 | assert_equal(None, diffs[5].a_blob) | ||
| 51 | assert_equal('f733bce6b57c0e5e353206e692b0e3105c2527f4', diffs[5].b_blob.id) | ||
| 52 | assert_equal( None, diffs[5].a_mode ) | ||
| 49 | assert_equal('lib/grit/actor.rb', diffs[5].a_path) | ||
| 50 | assert_equal(None, diffs[5].a_commit) | ||
| 51 | assert_equal('f733bce6b57c0e5e353206e692b0e3105c2527f4', diffs[5].b_commit.id) | ||
| 53 | 52 | assert_equal(True, diffs[5].new_file) | |
| 54 | 53 | ||
| 55 | 54 | assert_true(git.called) | |
| … | … | ||
| 88 | 88 | diffs = Commit.diff(self.repo, '59ddc32', ['lib']) | |
| 89 | 89 | ||
| 90 | 90 | assert_equal(1, len(diffs)) | |
| 91 | assert_equal('lib/grit/diff.rb', diffs[0].a_blob.name) | ||
| 91 | assert_equal('lib/grit/diff.rb', diffs[0].a_path) | ||
| 92 | 92 | ||
| 93 | 93 | assert_true(git.called) | |
| 94 | 94 | assert_equal(git.call_args, (('diff', '-M', '59ddc32', '--', 'lib'), {'full_index': True})) | |
| … | … | ||
| 100 | 100 | diffs = Commit.diff(self.repo, '59ddc32', '13d27d5', ['lib']) | |
| 101 | 101 | ||
| 102 | 102 | assert_equal(1, len(diffs)) | |
| 103 | assert_equal('lib/grit/commit.rb', diffs[0].a_blob.name) | ||
| 103 | assert_equal('lib/grit/commit.rb', diffs[0].a_path) | ||
| 104 | 104 | ||
| 105 | 105 | assert_true(git.called) | |
| 106 | 106 | assert_equal(git.call_args, (('diff', '-M', '59ddc32', '13d27d5', '--', 'lib'), {'full_index': True})) | |
| … | … | ||
| 114 | 114 | ||
| 115 | 115 | assert_equal(15, len(diffs)) | |
| 116 | 116 | ||
| 117 | assert_equal('.gitignore', diffs[0].a_blob.name) | ||
| 118 | assert_equal('.gitignore', diffs[0].b_blob.name) | ||
| 119 | assert_equal('4ebc8aea50e0a67e000ba29a30809d0a7b9b2666', diffs[0].a_blob.id) | ||
| 120 | assert_equal('2dd02534615434d88c51307beb0f0092f21fd103', diffs[0].b_blob.id) | ||
| 121 | assert_equal('100644', diffs[0].b_blob.mode) | ||
| 117 | assert_equal('.gitignore', diffs[0].a_path) | ||
| 118 | assert_equal('.gitignore', diffs[0].b_path) | ||
| 119 | assert_equal('4ebc8aea50e0a67e000ba29a30809d0a7b9b2666', diffs[0].a_commit.id) | ||
| 120 | assert_equal('2dd02534615434d88c51307beb0f0092f21fd103', diffs[0].b_commit.id) | ||
| 121 | assert_equal('100644', diffs[0].b_mode) | ||
| 122 | 122 | assert_equal(False, diffs[0].new_file) | |
| 123 | 123 | assert_equal(False, diffs[0].deleted_file) | |
| 124 | 124 | assert_equal("--- a/.gitignore\n+++ b/.gitignore\n@@ -1 +1,2 @@\n coverage\n+pkg", diffs[0].diff) | |
| 125 | 125 | ||
| 126 | assert_equal('lib/grit/actor.rb', diffs[5].b_blob.name) | ||
| 127 | assert_equal(None, diffs[5].a_blob) | ||
| 128 | assert_equal('f733bce6b57c0e5e353206e692b0e3105c2527f4', diffs[5].b_blob.id) | ||
| 126 | assert_equal('lib/grit/actor.rb', diffs[5].a_path) | ||
| 127 | assert_equal(None, diffs[5].a_commit) | ||
| 128 | assert_equal('f733bce6b57c0e5e353206e692b0e3105c2527f4', diffs[5].b_commit.id) | ||
| 129 | 129 | assert_equal(True, diffs[5].new_file) | |
| 130 | 130 | ||
| 131 | 131 | assert_true(git.called) | |
| … | … | ||
| 144 | 144 | ||
| 145 | 145 | assert_equal(10, len(diffs)) | |
| 146 | 146 | ||
| 147 | assert_equal('History.txt', diffs[0].b_blob.name) | ||
| 148 | assert_equal(None, diffs[0].a_blob) | ||
| 149 | assert_equal('100644', diffs[0].b_blob.mode) | ||
| 150 | assert_equal('81d2c27608b352814cbe979a6acd678d30219678', diffs[0].b_blob.id) | ||
| 147 | assert_equal('History.txt', diffs[0].a_path) | ||
| 148 | assert_equal('History.txt', diffs[0].b_path) | ||
| 149 | assert_equal(None, diffs[0].a_commit) | ||
| 150 | assert_equal('100644', diffs[0].b_mode) | ||
| 151 | assert_equal('81d2c27608b352814cbe979a6acd678d30219678', diffs[0].b_commit.id) | ||
| 151 | 152 | assert_equal(True, diffs[0].new_file) | |
| 152 | 153 | assert_equal(False, diffs[0].deleted_file) | |
| 153 | 154 | 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) | |
| 154 | 155 | ||
| 155 | assert_equal('lib/grit.rb', diffs[5].b_blob.name) | ||
| 156 | assert_equal(None, diffs[5].a_blob) | ||
| 157 | assert_equal('32cec87d1e78946a827ddf6a8776be4d81dcf1d1', diffs[5].b_blob.id) | ||
| 156 | assert_equal('lib/grit.rb', diffs[5].a_path) | ||
| 157 | assert_equal(None, diffs[5].a_commit) | ||
| 158 | assert_equal('32cec87d1e78946a827ddf6a8776be4d81dcf1d1', diffs[5].b_commit.id) | ||
| 158 | 159 | assert_equal(True, diffs[5].new_file) | |
| 159 | 160 | ||
| 160 | 161 | assert_true(git.called) | |
| … | … | ||
| 181 | 181 | commit.__bake_it__() | |
| 182 | 182 | diffs = commit.diffs | |
| 183 | 183 | ||
| 184 | # in case of mode-only changes, there is no blob | ||
| 185 | 184 | assert_equal(23, len(diffs)) | |
| 186 | assert_equal(None, diffs[0].a_blob) | ||
| 187 | assert_equal(None, diffs[0].b_blob) | ||
| 188 | 185 | assert_equal('100644', diffs[0].a_mode) | |
| 189 | 186 | assert_equal('100755', diffs[0].b_mode) | |
| 190 | 187 |

