Merge lp:~maxiberta/launchpad/git-get-blob-unexport-api into lp:launchpad

Proposed by Maximiliano Bertacchini
Status: Merged
Approved by: Colin Watson
Approved revision: no longer in the source branch.
Merged at revision: 18018
Proposed branch: lp:~maxiberta/launchpad/git-get-blob-unexport-api
Merge into: lp:launchpad
Diff against target: 165 lines (+54/-30)
5 files modified
lib/lp/code/interfaces/githosting.py (+1/-1)
lib/lp/code/interfaces/gitrepository.py (+1/-9)
lib/lp/code/model/githosting.py (+7/-1)
lib/lp/code/model/tests/test_githosting.py (+41/-7)
lib/lp/code/model/tests/test_gitrepository.py (+4/-12)
To merge this branch: bzr merge lp:~maxiberta/launchpad/git-get-blob-unexport-api
Reviewer Review Type Date Requested Status
Colin Watson (community) Approve
Review via email: mp+293637@code.launchpad.net

Commit message

Unexport GitRepository.getBlob(); return a binary blob instead of dict.

Description of the change

Unexport GitRepository.getBlob(); return a binary blob instead of dict.

To post a comment you must log in.
Revision history for this message
Colin Watson (cjwatson) :
review: Needs Fixing
Revision history for this message
Colin Watson (cjwatson) wrote :

Looks better now, thanks!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/code/interfaces/githosting.py'
2--- lib/lp/code/interfaces/githosting.py 2016-04-29 22:06:11 +0000
3+++ lib/lp/code/interfaces/githosting.py 2016-05-03 18:43:05 +0000
4@@ -96,5 +96,5 @@
5 :param filename: Relative path of a file in the repository.
6 :param rev: An optional revision. Defaults to 'HEAD'.
7 :param logger: An optional logger.
8- :return: A dict with keys 'data' and 'size'.
9+ :return: A binary string with the blob content.
10 """
11
12=== modified file 'lib/lp/code/interfaces/gitrepository.py'
13--- lib/lp/code/interfaces/gitrepository.py 2016-04-29 15:17:20 +0000
14+++ lib/lp/code/interfaces/gitrepository.py 2016-05-03 18:43:05 +0000
15@@ -533,20 +533,12 @@
16 :param logger: An optional logger.
17 """
18
19- @operation_parameters(
20- filename=TextLine(
21- title=_("Relative path of file in the repository."),
22- required=True),
23- rev=TextLine(title=_("An optional revision. Defaults to 'HEAD'.")),
24- )
25- @export_read_operation()
26- @operation_for_version("devel")
27 def getBlob(filename, rev=None):
28 """Get a blob by file name from this repository.
29
30 :param filename: Relative path of a file in the repository.
31 :param rev: An optional revision. Defaults to 'HEAD'.
32- :return: A dict with keys 'data' and 'size'.
33+ :return: A binary string with the blob content.
34 """
35
36
37
38=== modified file 'lib/lp/code/model/githosting.py'
39--- lib/lp/code/model/githosting.py 2016-04-29 22:06:11 +0000
40+++ lib/lp/code/model/githosting.py 2016-05-03 18:43:05 +0000
41@@ -155,7 +155,13 @@
42 logger.info(
43 "Fetching file %s from repository %s" % (filename, path))
44 url = "/repo/%s/blob/%s" % (path, quote(filename))
45- return self._get(url, params={"rev": rev})
46+ response = self._get(url, params={"rev": rev})
47+ blob = response["data"].decode("base64")
48+ if len(blob) != response["size"]:
49+ raise GitRepositoryScanFault(
50+ "Unexpected size (%s vs %s)" % (
51+ len(blob), response["size"]))
52+ return blob
53 except Exception as e:
54 raise GitRepositoryScanFault(
55 "Failed to get file from Git repository: %s" % unicode(e))
56
57=== modified file 'lib/lp/code/model/tests/test_githosting.py'
58--- lib/lp/code/model/tests/test_githosting.py 2016-04-29 22:06:11 +0000
59+++ lib/lp/code/model/tests/test_githosting.py 2016-05-03 18:43:05 +0000
60@@ -185,20 +185,20 @@
61 self.client.delete, "123")
62
63 def test_getBlob(self):
64- blob = b''.join(chr(i) for i in range(256)).encode("base64")
65- content = {"data": blob, "size": len(blob)}
66+ blob = b''.join(chr(i) for i in range(256))
67+ content = {"data": blob.encode("base64"), "size": len(blob)}
68 with self.mockRequests(content=json.dumps(content)):
69 response = self.client.getBlob("123", "dir/path/file/name")
70- self.assertEqual(content, response)
71+ self.assertEqual(blob, response)
72 self.assertRequest(
73 "repo/123/blob/dir/path/file/name", method="GET")
74
75 def test_getBlob_revision(self):
76- blob = b''.join(chr(i) for i in range(256)).encode("base64")
77- content = {"data": blob, "size": len(blob)}
78+ blob = b''.join(chr(i) for i in range(256))
79+ content = {"data": blob.encode("base64"), "size": len(blob)}
80 with self.mockRequests(content=json.dumps(content)):
81 response = self.client.getBlob("123", "dir/path/file/name", "dev")
82- self.assertEqual(content, response)
83+ self.assertEqual(blob, response)
84 self.assertRequest(
85 "repo/123/blob/dir/path/file/name?rev=dev", method="GET")
86
87@@ -210,8 +210,42 @@
88 self.client.getBlob, "123", "dir/path/file/name")
89
90 def test_getBlob_url_quoting(self):
91- with self.mockRequests():
92+ blob = b''.join(chr(i) for i in range(256))
93+ content = {"data": blob.encode("base64"), "size": len(blob)}
94+ with self.mockRequests(content=json.dumps(content)):
95 self.client.getBlob("123", "dir/+file name?.txt", "+rev/ no?")
96 self.assertRequest(
97 "repo/123/blob/dir/%2Bfile%20name%3F.txt?rev=%2Brev%2F+no%3F",
98 method="GET")
99+
100+ def test_getBlob_no_data(self):
101+ with self.mockRequests(content=json.dumps({"size": 1})):
102+ self.assertRaisesWithContent(
103+ GitRepositoryScanFault,
104+ "Failed to get file from Git repository: 'data'",
105+ self.client.getBlob, "123", "dir/path/file/name")
106+
107+ def test_getBlob_no_size(self):
108+ with self.mockRequests(content=json.dumps({"data": "data"})):
109+ self.assertRaisesWithContent(
110+ GitRepositoryScanFault,
111+ "Failed to get file from Git repository: 'size'",
112+ self.client.getBlob, "123", "dir/path/file/name")
113+
114+ def test_getBlob_bad_encoding(self):
115+ content = {"data": "x", "size": 1}
116+ with self.mockRequests(content=json.dumps(content)):
117+ self.assertRaisesWithContent(
118+ GitRepositoryScanFault,
119+ "Failed to get file from Git repository: Incorrect padding",
120+ self.client.getBlob, "123", "dir/path/file/name")
121+
122+ def test_getBlob_wrong_size(self):
123+ blob = b''.join(chr(i) for i in range(256))
124+ content = {"data": blob.encode("base64"), "size": 0}
125+ with self.mockRequests(content=json.dumps(content)):
126+ self.assertRaisesWithContent(
127+ GitRepositoryScanFault,
128+ "Failed to get file from Git repository: Unexpected size"
129+ " (256 vs 0)",
130+ self.client.getBlob, "123", "dir/path/file/name")
131
132=== modified file 'lib/lp/code/model/tests/test_gitrepository.py'
133--- lib/lp/code/model/tests/test_gitrepository.py 2016-04-29 22:06:11 +0000
134+++ lib/lp/code/model/tests/test_gitrepository.py 2016-05-03 18:43:05 +0000
135@@ -2041,26 +2041,18 @@
136 def test_getBlob_with_default_rev(self):
137 repository = self.factory.makeGitRepository()
138 hosting_client = FakeMethod()
139- expected_result = {
140- 'data': u'Some text'.encode('base64'),
141- 'size': len(u'Some Text'),
142- }
143- hosting_client.getBlob = FakeMethod(result=expected_result)
144+ hosting_client.getBlob = FakeMethod(result='Some text')
145 self.useFixture(ZopeUtilityFixture(hosting_client, IGitHostingClient))
146 ret = repository.getBlob('src/README.txt')
147- self.assertEqual(expected_result, ret)
148+ self.assertEqual('Some text', ret)
149
150 def test_getBlob_with_rev(self):
151 repository = self.factory.makeGitRepository()
152 hosting_client = FakeMethod()
153- expected_result = {
154- 'data': u'Some text'.encode('base64'),
155- 'size': len(u'Some Text'),
156- }
157- hosting_client.getBlob = FakeMethod(result=expected_result)
158+ hosting_client.getBlob = FakeMethod(result='Some text')
159 self.useFixture(ZopeUtilityFixture(hosting_client, IGitHostingClient))
160 ret = repository.getBlob('src/README.txt', 'some-rev')
161- self.assertEqual(expected_result, ret)
162+ self.assertEqual('Some text', ret)
163
164
165 class TestGitRepositorySet(TestCaseWithFactory):