launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #18307
[Merge] lp:~wgrant/turnip/api-diff-merge into lp:turnip
William Grant has proposed merging lp:~wgrant/turnip/api-diff-merge into lp:turnip.
Commit message:
Add an API to preview a merge diff.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~wgrant/turnip/api-diff-merge/+merge/256599
Add an API to get a merge diff. No prereq support yet, but that'll look something like /compare-merge/{base}/{prereq}/{head}.
--
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~wgrant/turnip/api-diff-merge into lp:turnip.
=== modified file 'turnip/api/store.py'
--- turnip/api/store.py 2015-04-16 16:51:43 +0000
+++ turnip/api/store.py 2015-04-16 22:18:24 +0000
@@ -130,6 +130,23 @@
return get_diff(repo_path, common_ancestor, sha1_source, context_lines)
+def get_merge_diff(repo_path, sha1_base, sha1_head, context_lines=3):
+ """Get diff of common ancestor and source diff.
+
+ :param sha1_base: target sha1 for merge.
+ :param sha1_head: source sha1 for merge.
+ :param context_lines: num unchanged lines that define a hunk boundary.
+ """
+ repo = open_repo(repo_path)
+ merged_index = repo.merge_commits(sha1_base, sha1_head)
+ diff = merged_index.diff_to_tree(
+ repo[sha1_base].tree, context_lines=context_lines).patch
+ shas = [sha1_base, sha1_head]
+ commits = [get_commit(repo_path, sha, repo) for sha in shas]
+ diff = {'commits': commits, 'patch': diff}
+ return diff
+
+
def get_diff(repo_path, sha1_from, sha1_to, context_lines=3):
"""Get patch and associated commits of two sha1s.
=== modified file 'turnip/api/tests/test_api.py'
--- turnip/api/tests/test_api.py 2015-04-16 19:15:23 +0000
+++ turnip/api/tests/test_api.py 2015-04-16 22:18:24 +0000
@@ -238,6 +238,22 @@
self.assertIn('+baz', resp.json_body['patch'])
self.assertNotIn('+corge', resp.json_body['patch'])
+ def test_repo_diff_merge(self):
+ """Ensure expected changes exist in diff patch."""
+ repo = RepoFactory(self.repo_store)
+ c1 = repo.add_commit('foo\nbar\nbaz\n', 'blah.txt')
+ c2_right = repo.add_commit('quux\nbar\nbaz\n', 'blah.txt', parents=[c1])
+ c3_right = repo.add_commit('quux\nbar\nbaz\n', 'blah.txt', parents=[c2_right])
+ c2_left = repo.add_commit('foo\nbar\nbar\n', 'blah.txt', parents=[c1])
+ c3_left = repo.add_commit('foo\nbar\nbar\n', 'blah.txt', parents=[c2_left])
+
+ resp = self.app.get('/repo/{}/compare-merge/{}/{}'.format(
+ self.repo_path, c3_right, c3_left))
+ self.assertIn(' quux', resp.json_body['patch'])
+ self.assertIn('-baz', resp.json_body['patch'])
+ self.assertIn('+bar', resp.json_body['patch'])
+ self.assertNotIn('foo', resp.json_body['patch'])
+
def test_repo_get_commit(self):
factory = RepoFactory(self.repo_store)
message = 'Computers make me angry.'
=== modified file 'turnip/api/views.py'
--- turnip/api/views.py 2015-04-16 16:51:43 +0000
+++ turnip/api/views.py 2015-04-16 22:18:24 +0000
@@ -144,6 +144,30 @@
return patch
+@resource(path='/repo/{name}/compare-merge/{base}/{head}')
+class DiffMergeAPI(BaseAPI):
+ """Provides an HTTP API for merge previews.
+
+ {head} will be merged into {base} and the diff from {base} returned.
+ """
+ def __init__(self, request):
+ super(DiffMergeAPI, self).__init__()
+ self.request = request
+
+ @repo_path
+ def get(self, repo_path):
+ """Returns diff of two commits."""
+ context_lines = int(self.request.params.get('context_lines', 3))
+ try:
+ patch = store.get_merge_diff(
+ repo_path, self.request.matchdict['base'],
+ self.request.matchdict['head'], context_lines)
+ except (ValueError, GitError):
+ # invalid pygit2 sha1's return ValueError: 1: Ambiguous lookup
+ return exc.HTTPNotFound()
+ return patch
+
+
@resource(collection_path='/repo/{name}/commits',
path='/repo/{name}/commits/{sha1}')
class CommitAPI(BaseAPI):
Follow ups