Merge ~ilasc/launchpad:call-download-api-without-file-id into launchpad:master
- Git
- lp:~ilasc/launchpad
- call-download-api-without-file-id
- Merge into master
Proposed by
Ioana Lasc
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Ioana Lasc | ||||
Approved revision: | 06bfe18c19e6212fc0186d1dab2efaf7256e73a0 | ||||
Merge reported by: | Otto Co-Pilot | ||||
Merged at revision: | not available | ||||
Proposed branch: | ~ilasc/launchpad:call-download-api-without-file-id | ||||
Merge into: | launchpad:master | ||||
Diff against target: |
819 lines (+59/-420) 10 files modified
lib/lp/code/errors.py (+1/-8) lib/lp/code/interfaces/branchhosting.py (+2/-18) lib/lp/code/model/branch.py (+1/-62) lib/lp/code/model/branchhosting.py (+4/-29) lib/lp/code/model/tests/test_branch.py (+6/-149) lib/lp/code/model/tests/test_branchhosting.py (+21/-77) lib/lp/code/tests/helpers.py (+0/-14) lib/lp/services/webapp/publisher.py (+1/-6) lib/lp/snappy/browser/tests/test_snap.py (+2/-7) lib/lp/snappy/tests/test_snap.py (+21/-50) |
||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Colin Watson (community) | Approve | ||
Review via email: mp+429433@code.launchpad.net |
Commit message
Call new Loggerhead download API without file-id
Description of the change
To post a comment you must log in.
Revision history for this message
Ioana Lasc (ilasc) wrote : | # |
Glad we're in agreement on the red quantity, wasn't sure if I had gone a bit too far with it :-)
I've tidied up the url quoting and the filename / path occurrences.
Thanks Colin!
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/lib/lp/code/errors.py b/lib/lp/code/errors.py |
2 | index 2fa4a47..82042a5 100644 |
3 | --- a/lib/lp/code/errors.py |
4 | +++ b/lib/lp/code/errors.py |
5 | @@ -365,23 +365,16 @@ class BranchHostingFault(Exception): |
6 | class BranchFileNotFound(BranchHostingFault): |
7 | """Raised when a file does not exist in a branch.""" |
8 | |
9 | - def __init__(self, branch_id, filename=None, file_id=None, rev=None): |
10 | + def __init__(self, branch_id, filename, rev=None): |
11 | super().__init__() |
12 | - if (filename is None) == (file_id is None): |
13 | - raise AssertionError( |
14 | - "Exactly one of filename and file_id must be given." |
15 | - ) |
16 | self.branch_id = branch_id |
17 | self.filename = filename |
18 | - self.file_id = file_id |
19 | self.rev = rev |
20 | |
21 | def __str__(self): |
22 | message = "Branch ID %s has no file " % self.branch_id |
23 | if self.filename is not None: |
24 | message += self.filename |
25 | - else: |
26 | - message += "with ID %s" % self.file_id |
27 | if self.rev is not None: |
28 | message += " at revision %s" % self.rev |
29 | return message |
30 | diff --git a/lib/lp/code/interfaces/branchhosting.py b/lib/lp/code/interfaces/branchhosting.py |
31 | index e93096a..41b8926 100644 |
32 | --- a/lib/lp/code/interfaces/branchhosting.py |
33 | +++ b/lib/lp/code/interfaces/branchhosting.py |
34 | @@ -28,27 +28,11 @@ class IBranchHostingClient(Interface): |
35 | :return: The diff between `old` and `new` as a byte string. |
36 | """ |
37 | |
38 | - def getInventory(branch_id, dirname, rev=None, logger=None): |
39 | - """Get information on files in a directory. |
40 | - |
41 | - :param branch_id: The ID of the branch. |
42 | - :param dirname: The name of the directory, relative to the root of |
43 | - the branch. |
44 | - :param rev: An optional revno or revision ID. Defaults to 'head:'. |
45 | - :param logger: An optional logger. |
46 | - :raises ValueError: if `rev` is ill-formed. |
47 | - :raises BranchFileNotFound: if the directory does not exist. |
48 | - :raises BranchHostingFault: if the API returned some other error. |
49 | - :return: The directory inventory as a dict: see |
50 | - `loggerhead.controllers.inventory_ui` for details. |
51 | - """ |
52 | - |
53 | - def getBlob(branch_id, file_id, rev=None, logger=None): |
54 | + def getBlob(branch_id, path, rev=None, logger=None): |
55 | """Get a blob by file name from a branch. |
56 | |
57 | :param branch_id: The ID of the branch. |
58 | - :param file_id: The file ID of the file. (`getInventory` may be |
59 | - useful to retrieve this.) |
60 | + :param path: The relative path of the file. |
61 | :param rev: An optional revno or revision ID. Defaults to 'head:'. |
62 | :param logger: An optional logger. |
63 | :raises ValueError: if `rev` is ill-formed. |
64 | diff --git a/lib/lp/code/model/branch.py b/lib/lp/code/model/branch.py |
65 | index 43ed1b0..63d1b13 100644 |
66 | --- a/lib/lp/code/model/branch.py |
67 | +++ b/lib/lp/code/model/branch.py |
68 | @@ -8,13 +8,10 @@ __all__ = [ |
69 | ] |
70 | |
71 | import operator |
72 | -import os.path |
73 | from datetime import datetime |
74 | from functools import partial |
75 | -from urllib.parse import urlsplit |
76 | |
77 | import pytz |
78 | -import six |
79 | from breezy import urlutils |
80 | from breezy.revision import NULL_REVISION |
81 | from breezy.url_policy_open import open_only_scheme |
82 | @@ -66,7 +63,6 @@ from lp.code.enums import ( |
83 | ) |
84 | from lp.code.errors import ( |
85 | AlreadyLatestFormat, |
86 | - BranchFileNotFound, |
87 | BranchMergeProposalExists, |
88 | BranchTargetError, |
89 | BranchTypeError, |
90 | @@ -142,12 +138,10 @@ from lp.services.database.interfaces import IMasterStore, IStore |
91 | from lp.services.database.sqlbase import SQLBase, sqlvalues |
92 | from lp.services.database.sqlobject import ForeignKey, IntCol, StringCol |
93 | from lp.services.database.stormexpr import Array, ArrayAgg, ArrayIntersects |
94 | -from lp.services.features import getFeatureFlag |
95 | from lp.services.helpers import shortlist |
96 | from lp.services.job.interfaces.job import JobStatus |
97 | from lp.services.job.model.job import Job |
98 | from lp.services.mail.notificationrecipientset import NotificationRecipientSet |
99 | -from lp.services.memcache.interfaces import IMemcacheClient |
100 | from lp.services.propertycache import cachedproperty, get_property_cache |
101 | from lp.services.webapp import urlappend |
102 | from lp.services.webapp.authorization import check_permission |
103 | @@ -899,64 +893,9 @@ class Branch(SQLBase, WebhookTargetMixin, BzrIdentityMixin): |
104 | ): |
105 | """See `IBranch`.""" |
106 | hosting_client = getUtility(IBranchHostingClient) |
107 | - if enable_memcache is None: |
108 | - enable_memcache = not getFeatureFlag( |
109 | - "code.bzr.blob.disable_memcache" |
110 | - ) |
111 | if revision_id is None: |
112 | revision_id = self.last_scanned_id |
113 | - if revision_id is None: |
114 | - # revision_id may still be None if the branch scanner hasn't |
115 | - # scanned this branch yet. In this case, we won't be able to |
116 | - # guarantee that subsequent calls to this method within the same |
117 | - # transaction with revision_id=None will see the same revision, |
118 | - # and we won't be able to cache file lists. Neither is fatal, |
119 | - # and this should be relatively rare. |
120 | - enable_memcache = False |
121 | - dirname = os.path.dirname(filename) |
122 | - unset = object() |
123 | - file_list = unset |
124 | - if enable_memcache: |
125 | - memcache_client = getUtility(IMemcacheClient) |
126 | - instance_name = urlsplit( |
127 | - config.codehosting.internal_bzr_api_endpoint |
128 | - ).hostname |
129 | - memcache_key = six.ensure_binary( |
130 | - "%s:bzr-file-list:%s:%s:%s" |
131 | - % (instance_name, self.id, revision_id, dirname) |
132 | - ) |
133 | - description = "file list for %s:%s:%s" % ( |
134 | - self.unique_name, |
135 | - revision_id, |
136 | - dirname, |
137 | - ) |
138 | - file_list = memcache_client.get_json( |
139 | - memcache_key, logger, description, default=unset |
140 | - ) |
141 | - |
142 | - if file_list is unset: |
143 | - try: |
144 | - inventory = hosting_client.getInventory( |
145 | - self.id, dirname, rev=revision_id |
146 | - ) |
147 | - file_list = { |
148 | - entry["filename"]: entry["file_id"] |
149 | - for entry in inventory["filelist"] |
150 | - } |
151 | - except BranchFileNotFound: |
152 | - file_list = None |
153 | - if enable_memcache: |
154 | - # Cache the file list in case there's a request for another |
155 | - # file in the same directory. |
156 | - memcache_client.set_json( |
157 | - memcache_key, file_list, logger=logger |
158 | - ) |
159 | - file_id = (file_list or {}).get(os.path.basename(filename)) |
160 | - if file_id is None: |
161 | - raise BranchFileNotFound( |
162 | - self.unique_name, filename=filename, rev=revision_id |
163 | - ) |
164 | - return hosting_client.getBlob(self.id, file_id, rev=revision_id) |
165 | + return hosting_client.getBlob(self.id, filename, rev=revision_id) |
166 | |
167 | def getDiff(self, new, old=None): |
168 | """See `IBranch`.""" |
169 | diff --git a/lib/lp/code/model/branchhosting.py b/lib/lp/code/model/branchhosting.py |
170 | index 8b5abb4..365a6c8 100644 |
171 | --- a/lib/lp/code/model/branchhosting.py |
172 | +++ b/lib/lp/code/model/branchhosting.py |
173 | @@ -128,43 +128,18 @@ class BranchHostingClient: |
174 | "Failed to get diff from Bazaar branch: %s" % e |
175 | ) |
176 | |
177 | - def getInventory(self, branch_id, dirname, rev=None, logger=None): |
178 | + def getBlob(self, branch_id, path, rev=None, logger=None): |
179 | """See `IBranchHostingClient`.""" |
180 | self._checkRevision(rev) |
181 | try: |
182 | if logger is not None: |
183 | logger.info( |
184 | - "Requesting inventory at %s from branch %s" |
185 | - % (dirname, branch_id) |
186 | - ) |
187 | - quoted_tail = "files/%s/%s" % ( |
188 | - quote(rev or "head:", safe=""), |
189 | - quote(dirname.lstrip("/")), |
190 | - ) |
191 | - return self._get(branch_id, quoted_tail, as_json=True) |
192 | - except requests.RequestException as e: |
193 | - if ( |
194 | - e.response is not None |
195 | - and e.response.status_code == requests.codes.NOT_FOUND |
196 | - ): |
197 | - raise BranchFileNotFound(branch_id, filename=dirname, rev=rev) |
198 | - else: |
199 | - raise BranchHostingFault( |
200 | - "Failed to get inventory from Bazaar branch: %s" % e |
201 | - ) |
202 | - |
203 | - def getBlob(self, branch_id, file_id, rev=None, logger=None): |
204 | - """See `IBranchHostingClient`.""" |
205 | - self._checkRevision(rev) |
206 | - try: |
207 | - if logger is not None: |
208 | - logger.info( |
209 | - "Fetching file ID %s from branch %s" % (file_id, branch_id) |
210 | + "Fetching file ID %s from branch %s" % (path, branch_id) |
211 | ) |
212 | return self._get( |
213 | branch_id, |
214 | "download/%s/%s" |
215 | - % (quote(rev or "head:", safe=""), quote(file_id, safe="")), |
216 | + % (quote(rev or "head:", safe=""), quote(path, safe="/")), |
217 | as_json=False, |
218 | ) |
219 | except requests.RequestException as e: |
220 | @@ -172,7 +147,7 @@ class BranchHostingClient: |
221 | e.response is not None |
222 | and e.response.status_code == requests.codes.NOT_FOUND |
223 | ): |
224 | - raise BranchFileNotFound(branch_id, file_id=file_id, rev=rev) |
225 | + raise BranchFileNotFound(branch_id, filename=path, rev=rev) |
226 | else: |
227 | raise BranchHostingFault( |
228 | "Failed to get file from Bazaar branch: %s" % e |
229 | diff --git a/lib/lp/code/model/tests/test_branch.py b/lib/lp/code/model/tests/test_branch.py |
230 | index 5f037c4..d78c340 100644 |
231 | --- a/lib/lp/code/model/tests/test_branch.py |
232 | +++ b/lib/lp/code/model/tests/test_branch.py |
233 | @@ -3,7 +3,6 @@ |
234 | |
235 | """Tests for Branches.""" |
236 | |
237 | -import json |
238 | from datetime import datetime, timedelta |
239 | |
240 | import transaction |
241 | @@ -117,7 +116,6 @@ from lp.services.features.testing import FeatureFixture |
242 | from lp.services.job.interfaces.job import JobStatus |
243 | from lp.services.job.runner import JobRunner |
244 | from lp.services.job.tests import block_on_job, monitor_celery |
245 | -from lp.services.memcache.interfaces import IMemcacheClient |
246 | from lp.services.osutils import override_environ |
247 | from lp.services.propertycache import clear_property_cache |
248 | from lp.services.webapp.authorization import check_permission |
249 | @@ -3686,157 +3684,39 @@ class TestBranchGetBlob(TestCaseWithFactory): |
250 | |
251 | def test_default_rev_unscanned(self): |
252 | branch = self.factory.makeBranch() |
253 | - hosting_fixture = self.useFixture( |
254 | - BranchHostingFixture( |
255 | - file_list={"README.txt": "some-file-id"}, blob=b"Some text" |
256 | - ) |
257 | - ) |
258 | + self.useFixture(BranchHostingFixture(blob=b"Some text")) |
259 | blob = branch.getBlob("src/README.txt") |
260 | self.assertEqual(b"Some text", blob) |
261 | - self.assertEqual( |
262 | - [((branch.id, "src"), {"rev": None})], |
263 | - hosting_fixture.getInventory.calls, |
264 | - ) |
265 | - self.assertEqual( |
266 | - [((branch.id, "some-file-id"), {"rev": None})], |
267 | - hosting_fixture.getBlob.calls, |
268 | - ) |
269 | - self.assertEqual({}, getUtility(IMemcacheClient)._cache) |
270 | |
271 | def test_default_rev_scanned(self): |
272 | branch = self.factory.makeBranch() |
273 | removeSecurityProxy(branch).last_scanned_id = "scanned-id" |
274 | - hosting_fixture = self.useFixture( |
275 | - BranchHostingFixture( |
276 | - file_list={"README.txt": "some-file-id"}, blob=b"Some text" |
277 | - ) |
278 | - ) |
279 | + self.useFixture(BranchHostingFixture(blob=b"Some text")) |
280 | blob = branch.getBlob("src/README.txt") |
281 | self.assertEqual(b"Some text", blob) |
282 | - self.assertEqual( |
283 | - [((branch.id, "src"), {"rev": "scanned-id"})], |
284 | - hosting_fixture.getInventory.calls, |
285 | - ) |
286 | - self.assertEqual( |
287 | - [((branch.id, "some-file-id"), {"rev": "scanned-id"})], |
288 | - hosting_fixture.getBlob.calls, |
289 | - ) |
290 | - key = ( |
291 | - "bazaar.launchpad.test:bzr-file-list:%s:scanned-id:src" % branch.id |
292 | - ) |
293 | - self.assertEqual( |
294 | - json.dumps({"README.txt": "some-file-id"}), |
295 | - getUtility(IMemcacheClient).get(key.encode("UTF-8")), |
296 | - ) |
297 | |
298 | def test_with_rev(self): |
299 | branch = self.factory.makeBranch() |
300 | - hosting_fixture = self.useFixture( |
301 | - BranchHostingFixture( |
302 | - file_list={"README.txt": "some-file-id"}, blob=b"Some text" |
303 | - ) |
304 | - ) |
305 | - blob = branch.getBlob("src/README.txt", revision_id="some-rev") |
306 | - self.assertEqual(b"Some text", blob) |
307 | - self.assertEqual( |
308 | - [((branch.id, "src"), {"rev": "some-rev"})], |
309 | - hosting_fixture.getInventory.calls, |
310 | - ) |
311 | - self.assertEqual( |
312 | - [((branch.id, "some-file-id"), {"rev": "some-rev"})], |
313 | - hosting_fixture.getBlob.calls, |
314 | - ) |
315 | - key = "bazaar.launchpad.test:bzr-file-list:%s:some-rev:src" % branch.id |
316 | - self.assertEqual( |
317 | - json.dumps({"README.txt": "some-file-id"}), |
318 | - getUtility(IMemcacheClient).get(key.encode("UTF-8")), |
319 | - ) |
320 | - |
321 | - def test_cached_inventory(self): |
322 | - branch = self.factory.makeBranch() |
323 | - hosting_fixture = self.useFixture( |
324 | - BranchHostingFixture(blob=b"Some text") |
325 | - ) |
326 | - key = "bazaar.launchpad.test:bzr-file-list:%s:some-rev:src" % branch.id |
327 | - getUtility(IMemcacheClient).set( |
328 | - key.encode("UTF-8"), json.dumps({"README.txt": "some-file-id"}) |
329 | - ) |
330 | - blob = branch.getBlob("src/README.txt", revision_id="some-rev") |
331 | - self.assertEqual(b"Some text", blob) |
332 | - self.assertEqual([], hosting_fixture.getInventory.calls) |
333 | - self.assertEqual( |
334 | - [((branch.id, "some-file-id"), {"rev": "some-rev"})], |
335 | - hosting_fixture.getBlob.calls, |
336 | - ) |
337 | - |
338 | - def test_disable_memcache(self): |
339 | - self.useFixture( |
340 | - FeatureFixture({"code.bzr.blob.disable_memcache": "on"}) |
341 | - ) |
342 | - branch = self.factory.makeBranch() |
343 | - hosting_fixture = self.useFixture( |
344 | - BranchHostingFixture( |
345 | - file_list={"README.txt": "some-file-id"}, blob=b"Some text" |
346 | - ) |
347 | - ) |
348 | - key = "bazaar.launchpad.test:bzr-file-list:%s:some-rev:src" % branch.id |
349 | - getUtility(IMemcacheClient).set(key.encode("UTF-8"), "{}") |
350 | + self.useFixture(BranchHostingFixture(blob=b"Some text")) |
351 | blob = branch.getBlob("src/README.txt", revision_id="some-rev") |
352 | self.assertEqual(b"Some text", blob) |
353 | - self.assertEqual( |
354 | - [((branch.id, "src"), {"rev": "some-rev"})], |
355 | - hosting_fixture.getInventory.calls, |
356 | - ) |
357 | - self.assertEqual( |
358 | - "{}", getUtility(IMemcacheClient).get(key.encode("UTF-8")) |
359 | - ) |
360 | |
361 | def test_file_at_root_of_branch(self): |
362 | branch = self.factory.makeBranch() |
363 | hosting_fixture = self.useFixture( |
364 | - BranchHostingFixture( |
365 | - file_list={"README.txt": "some-file-id"}, blob=b"Some text" |
366 | - ) |
367 | + BranchHostingFixture(blob=b"Some text") |
368 | ) |
369 | blob = branch.getBlob("README.txt", revision_id="some-rev") |
370 | self.assertEqual(b"Some text", blob) |
371 | self.assertEqual( |
372 | - [((branch.id, ""), {"rev": "some-rev"})], |
373 | - hosting_fixture.getInventory.calls, |
374 | - ) |
375 | - self.assertEqual( |
376 | - [((branch.id, "some-file-id"), {"rev": "some-rev"})], |
377 | + [((branch.id, "README.txt"), {"rev": "some-rev"})], |
378 | hosting_fixture.getBlob.calls, |
379 | ) |
380 | - key = "bazaar.launchpad.test:bzr-file-list:%s:some-rev:" % branch.id |
381 | - self.assertEqual( |
382 | - json.dumps({"README.txt": "some-file-id"}), |
383 | - getUtility(IMemcacheClient).get(key.encode("UTF-8")), |
384 | - ) |
385 | - |
386 | - def test_file_not_in_directory(self): |
387 | - branch = self.factory.makeBranch() |
388 | - hosting_fixture = self.useFixture(BranchHostingFixture(file_list={})) |
389 | - self.assertRaises( |
390 | - BranchFileNotFound, |
391 | - branch.getBlob, |
392 | - "src/README.txt", |
393 | - revision_id="some-rev", |
394 | - ) |
395 | - self.assertEqual( |
396 | - [((branch.id, "src"), {"rev": "some-rev"})], |
397 | - hosting_fixture.getInventory.calls, |
398 | - ) |
399 | - self.assertEqual([], hosting_fixture.getBlob.calls) |
400 | - key = "bazaar.launchpad.test:bzr-file-list:%s:some-rev:src" % branch.id |
401 | - self.assertEqual( |
402 | - "{}", getUtility(IMemcacheClient).get(key.encode("UTF-8")) |
403 | - ) |
404 | |
405 | def test_missing_directory(self): |
406 | branch = self.factory.makeBranch() |
407 | hosting_fixture = self.useFixture(BranchHostingFixture()) |
408 | - hosting_fixture.getInventory = FakeMethod( |
409 | + hosting_fixture.getBlob = FakeMethod( |
410 | failure=BranchFileNotFound( |
411 | branch.unique_name, filename="src", rev="some-rev" |
412 | ) |
413 | @@ -3847,29 +3727,6 @@ class TestBranchGetBlob(TestCaseWithFactory): |
414 | "src/README.txt", |
415 | revision_id="some-rev", |
416 | ) |
417 | - self.assertEqual( |
418 | - [((branch.id, "src"), {"rev": "some-rev"})], |
419 | - hosting_fixture.getInventory.calls, |
420 | - ) |
421 | - self.assertEqual([], hosting_fixture.getBlob.calls) |
422 | - key = "bazaar.launchpad.test:bzr-file-list:%s:some-rev:src" % branch.id |
423 | - self.assertEqual( |
424 | - "null", getUtility(IMemcacheClient).get(key.encode("UTF-8")) |
425 | - ) |
426 | - |
427 | - def test_cached_missing_directory(self): |
428 | - branch = self.factory.makeBranch() |
429 | - hosting_fixture = self.useFixture(BranchHostingFixture()) |
430 | - key = "bazaar.launchpad.test:bzr-file-list:%s:some-rev:src" % branch.id |
431 | - getUtility(IMemcacheClient).set(key.encode("UTF-8"), "null") |
432 | - self.assertRaises( |
433 | - BranchFileNotFound, |
434 | - branch.getBlob, |
435 | - "src/README.txt", |
436 | - revision_id="some-rev", |
437 | - ) |
438 | - self.assertEqual([], hosting_fixture.getInventory.calls) |
439 | - self.assertEqual([], hosting_fixture.getBlob.calls) |
440 | |
441 | |
442 | class TestBranchUnscan(TestCaseWithFactory): |
443 | diff --git a/lib/lp/code/model/tests/test_branchhosting.py b/lib/lp/code/model/tests/test_branchhosting.py |
444 | index ccf6dc8..ddd719d 100644 |
445 | --- a/lib/lp/code/model/tests/test_branchhosting.py |
446 | +++ b/lib/lp/code/model/tests/test_branchhosting.py |
447 | @@ -108,108 +108,44 @@ class TestBranchHostingClient(TestCase): |
448 | "1", |
449 | ) |
450 | |
451 | - def test_getInventory(self): |
452 | - with self.mockRequests("GET", json={"filelist": []}): |
453 | - response = self.client.getInventory(123, "dir/path/file/name") |
454 | - self.assertEqual({"filelist": []}, response) |
455 | - self.assertRequest( |
456 | - "+branch-id/123/+json/files/head%3A/dir/path/file/name" |
457 | - ) |
458 | - |
459 | - def test_getInventory_revision(self): |
460 | - with self.mockRequests("GET", json={"filelist": []}): |
461 | - response = self.client.getInventory( |
462 | - 123, "dir/path/file/name", rev="a" |
463 | - ) |
464 | - self.assertEqual({"filelist": []}, response) |
465 | - self.assertRequest("+branch-id/123/+json/files/a/dir/path/file/name") |
466 | - |
467 | - def test_getInventory_not_found(self): |
468 | - with self.mockRequests("GET", status=404): |
469 | - self.assertRaisesWithContent( |
470 | - BranchFileNotFound, |
471 | - "Branch ID 123 has no file dir/path/file/name", |
472 | - self.client.getInventory, |
473 | - 123, |
474 | - "dir/path/file/name", |
475 | - ) |
476 | - |
477 | - def test_getInventory_revision_not_found(self): |
478 | - with self.mockRequests("GET", status=404): |
479 | - self.assertRaisesWithContent( |
480 | - BranchFileNotFound, |
481 | - "Branch ID 123 has no file dir/path/file/name at revision a", |
482 | - self.client.getInventory, |
483 | - 123, |
484 | - "dir/path/file/name", |
485 | - rev="a", |
486 | - ) |
487 | - |
488 | - def test_getInventory_bad_revision(self): |
489 | - self.assertRaises( |
490 | - ValueError, |
491 | - self.client.getInventory, |
492 | - 123, |
493 | - "dir/path/file/name", |
494 | - rev="x/y", |
495 | - ) |
496 | - |
497 | - def test_getInventory_failure(self): |
498 | - with self.mockRequests("GET", status=400): |
499 | - self.assertRaisesWithContent( |
500 | - BranchHostingFault, |
501 | - "Failed to get inventory from Bazaar branch: " |
502 | - "400 Client Error: Bad Request", |
503 | - self.client.getInventory, |
504 | - 123, |
505 | - "dir/path/file/name", |
506 | - ) |
507 | - |
508 | - def test_getInventory_url_quoting(self): |
509 | - with self.mockRequests("GET", json={"filelist": []}): |
510 | - self.client.getInventory(123, "+file/ name?", rev="+rev id?") |
511 | - self.assertRequest( |
512 | - "+branch-id/123/+json/files/%2Brev%20id%3F/%2Bfile/%20name%3F" |
513 | - ) |
514 | - |
515 | def test_getBlob(self): |
516 | blob = b"".join(bytes((i,)) for i in range(256)) |
517 | with self.mockRequests("GET", body=blob): |
518 | - response = self.client.getBlob(123, "file-id") |
519 | + response = self.client.getBlob(123, "file-name") |
520 | self.assertEqual(blob, response) |
521 | - self.assertRequest("+branch-id/123/download/head%3A/file-id") |
522 | + self.assertRequest("+branch-id/123/download/head%3A/file-name") |
523 | |
524 | def test_getBlob_revision(self): |
525 | blob = b"".join(bytes((i,)) for i in range(256)) |
526 | with self.mockRequests("GET", body=blob): |
527 | - response = self.client.getBlob(123, "file-id", rev="a") |
528 | + response = self.client.getBlob(123, "file-name", rev="a") |
529 | self.assertEqual(blob, response) |
530 | - self.assertRequest("+branch-id/123/download/a/file-id") |
531 | + self.assertRequest("+branch-id/123/download/a/file-name") |
532 | |
533 | def test_getBlob_not_found(self): |
534 | with self.mockRequests("GET", status=404): |
535 | self.assertRaisesWithContent( |
536 | BranchFileNotFound, |
537 | - "Branch ID 123 has no file with ID file-id", |
538 | + "Branch ID 123 has no file src/file", |
539 | self.client.getBlob, |
540 | 123, |
541 | - "file-id", |
542 | + "src/file", |
543 | ) |
544 | |
545 | def test_getBlob_revision_not_found(self): |
546 | with self.mockRequests("GET", status=404): |
547 | self.assertRaisesWithContent( |
548 | BranchFileNotFound, |
549 | - "Branch ID 123 has no file with ID file-id at revision a", |
550 | + "Branch ID 123 has no file src/file at revision a", |
551 | self.client.getBlob, |
552 | 123, |
553 | - "file-id", |
554 | + "src/file", |
555 | rev="a", |
556 | ) |
557 | |
558 | def test_getBlob_bad_revision(self): |
559 | self.assertRaises( |
560 | - ValueError, self.client.getBlob, 123, "file-id", rev="x/y" |
561 | + ValueError, self.client.getBlob, 123, "file-name", rev="x/y" |
562 | ) |
563 | |
564 | def test_getBlob_failure(self): |
565 | @@ -220,7 +156,7 @@ class TestBranchHostingClient(TestCase): |
566 | "400 Client Error: Bad Request", |
567 | self.client.getBlob, |
568 | 123, |
569 | - "file-id", |
570 | + "file-name", |
571 | ) |
572 | |
573 | def test_getBlob_url_quoting(self): |
574 | @@ -228,7 +164,15 @@ class TestBranchHostingClient(TestCase): |
575 | with self.mockRequests("GET", body=blob): |
576 | self.client.getBlob(123, "+file/ id?", rev="+rev id?") |
577 | self.assertRequest( |
578 | - "+branch-id/123/download/%2Brev%20id%3F/%2Bfile%2F%20id%3F" |
579 | + "+branch-id/123/download/%2Brev%20id%3F/%2Bfile/%20id%3F" |
580 | + ) |
581 | + |
582 | + def test_getBlob_url_quoting_forward_slash(self): |
583 | + blob = b"".join(bytes((i,)) for i in range(256)) |
584 | + with self.mockRequests("GET", body=blob): |
585 | + self.client.getBlob(123, "+snap/snapcraft.yaml?", rev="+rev id?") |
586 | + self.assertRequest( |
587 | + "+branch-id/123/download/%2Brev%20id%3F/%2Bsnap/snapcraft.yaml%3F" |
588 | ) |
589 | |
590 | def test_works_in_job(self): |
591 | @@ -246,11 +190,11 @@ class TestBranchHostingClient(TestCase): |
592 | with self.testcase.mockRequests( |
593 | "GET", body=blob, set_default_timeout=False |
594 | ): |
595 | - self.blob = self.testcase.client.getBlob(123, "file-id") |
596 | + self.blob = self.testcase.client.getBlob(123, "file-name") |
597 | # We must make this assertion inside the job, since the job |
598 | # runner creates a separate timeline. |
599 | self.testcase.assertRequest( |
600 | - "+branch-id/123/download/head%3A/file-id" |
601 | + "+branch-id/123/download/head%3A/file-name" |
602 | ) |
603 | |
604 | job = GetBlobJob(self) |
605 | diff --git a/lib/lp/code/tests/helpers.py b/lib/lp/code/tests/helpers.py |
606 | index 7f36b61..ff8165b 100644 |
607 | --- a/lib/lp/code/tests/helpers.py |
608 | +++ b/lib/lp/code/tests/helpers.py |
609 | @@ -311,25 +311,11 @@ class BranchHostingFixture(fixtures.Fixture): |
610 | def __init__( |
611 | self, |
612 | diff=None, |
613 | - inventory=None, |
614 | - file_list=None, |
615 | blob=None, |
616 | disable_memcache=True, |
617 | ): |
618 | self.create = FakeMethod() |
619 | self.getDiff = FakeMethod(result=diff or {}) |
620 | - if inventory is None: |
621 | - if file_list is not None: |
622 | - # Simple common case. |
623 | - inventory = { |
624 | - "filelist": [ |
625 | - {"filename": filename, "file_id": file_id} |
626 | - for filename, file_id in file_list.items() |
627 | - ], |
628 | - } |
629 | - else: |
630 | - inventory = {"filelist": []} |
631 | - self.getInventory = FakeMethod(result=inventory) |
632 | self.getBlob = FakeMethod(result=blob) |
633 | self.disable_memcache = disable_memcache |
634 | |
635 | diff --git a/lib/lp/services/webapp/publisher.py b/lib/lp/services/webapp/publisher.py |
636 | index c44c87b..88e3d76 100644 |
637 | --- a/lib/lp/services/webapp/publisher.py |
638 | +++ b/lib/lp/services/webapp/publisher.py |
639 | @@ -29,12 +29,7 @@ import http.client |
640 | import json |
641 | import re |
642 | from cgi import FieldStorage |
643 | -from typing import ( |
644 | - Any, |
645 | - Dict, |
646 | - Optional, |
647 | - Type, |
648 | -) |
649 | +from typing import Any, Dict, Optional, Type |
650 | from urllib.parse import urlparse |
651 | from wsgiref.headers import Headers |
652 | |
653 | diff --git a/lib/lp/snappy/browser/tests/test_snap.py b/lib/lp/snappy/browser/tests/test_snap.py |
654 | index 74b502c..10af3a1 100644 |
655 | --- a/lib/lp/snappy/browser/tests/test_snap.py |
656 | +++ b/lib/lp/snappy/browser/tests/test_snap.py |
657 | @@ -771,7 +771,6 @@ class TestSnapAddView(BaseTestSnapView): |
658 | def test_initial_name_extraction_bzr_success(self): |
659 | self.useFixture( |
660 | BranchHostingFixture( |
661 | - file_list={"snapcraft.yaml": "file-id"}, |
662 | blob=b"name: test-snap", |
663 | ) |
664 | ) |
665 | @@ -782,7 +781,7 @@ class TestSnapAddView(BaseTestSnapView): |
666 | self.assertEqual("test-snap", initial_values["store_name"]) |
667 | |
668 | def test_initial_name_extraction_bzr_error(self): |
669 | - self.useFixture(BranchHostingFixture()).getInventory = FakeMethod( |
670 | + self.useFixture(BranchHostingFixture()).getBlob = FakeMethod( |
671 | failure=BranchHostingFault |
672 | ) |
673 | branch = self.factory.makeBranch() |
674 | @@ -792,11 +791,7 @@ class TestSnapAddView(BaseTestSnapView): |
675 | self.assertIsNone(initial_values["store_name"]) |
676 | |
677 | def test_initial_name_extraction_bzr_no_name(self): |
678 | - self.useFixture( |
679 | - BranchHostingFixture( |
680 | - file_list={"snapcraft.yaml": "file-id"}, blob=b"some: nonsense" |
681 | - ) |
682 | - ) |
683 | + self.useFixture(BranchHostingFixture(blob=b"some: nonsense")) |
684 | branch = self.factory.makeBranch() |
685 | view = create_initialized_view(branch, "+new-snap") |
686 | initial_values = view.initial_values |
687 | diff --git a/lib/lp/snappy/tests/test_snap.py b/lib/lp/snappy/tests/test_snap.py |
688 | index 5329c46..48b1078 100644 |
689 | --- a/lib/lp/snappy/tests/test_snap.py |
690 | +++ b/lib/lp/snappy/tests/test_snap.py |
691 | @@ -2754,22 +2754,15 @@ class TestSnapSet(TestCaseWithFactory): |
692 | ) |
693 | |
694 | def test_getSnapcraftYaml_bzr_snap_snapcraft_yaml(self): |
695 | - def getInventory(unique_name, dirname, *args, **kwargs): |
696 | - if dirname == "snap": |
697 | - return { |
698 | - "filelist": [ |
699 | - { |
700 | - "filename": "snapcraft.yaml", |
701 | - "file_id": "some-file-id", |
702 | - } |
703 | - ] |
704 | - } |
705 | + def getBlob(path, filename, *args, **kwargs): |
706 | + if filename == "snap/snapcraft.yaml": |
707 | + return b"name: test-snap" |
708 | else: |
709 | - raise BranchFileNotFound("dummy", dirname) |
710 | + raise BranchFileNotFound("dummy", filename) |
711 | |
712 | self.useFixture( |
713 | BranchHostingFixture(blob=b"name: test-snap") |
714 | - ).getInventory = getInventory |
715 | + ).getBlob = getBlob |
716 | branch = self.factory.makeBranch() |
717 | self.assertEqual( |
718 | {"name": "test-snap"}, |
719 | @@ -2777,22 +2770,15 @@ class TestSnapSet(TestCaseWithFactory): |
720 | ) |
721 | |
722 | def test_getSnapcraftYaml_bzr_build_aux_snap_snapcraft_yaml(self): |
723 | - def getInventory(unique_name, dirname, *args, **kwargs): |
724 | - if dirname == "build-aux/snap": |
725 | - return { |
726 | - "filelist": [ |
727 | - { |
728 | - "filename": "snapcraft.yaml", |
729 | - "file_id": "some-file-id", |
730 | - } |
731 | - ] |
732 | - } |
733 | + def getBlob(path, filename, *args, **kwargs): |
734 | + if filename == "build-aux/snap/snapcraft.yaml": |
735 | + return b"name: test-snap" |
736 | else: |
737 | - raise BranchFileNotFound("dummy", dirname) |
738 | + raise BranchFileNotFound("dummy", filename) |
739 | |
740 | self.useFixture( |
741 | BranchHostingFixture(blob=b"name: test-snap") |
742 | - ).getInventory = getInventory |
743 | + ).getBlob = getBlob |
744 | branch = self.factory.makeBranch() |
745 | self.assertEqual( |
746 | {"name": "test-snap"}, |
747 | @@ -2800,22 +2786,15 @@ class TestSnapSet(TestCaseWithFactory): |
748 | ) |
749 | |
750 | def test_getSnapcraftYaml_bzr_plain_snapcraft_yaml(self): |
751 | - def getInventory(unique_name, dirname, *args, **kwargs): |
752 | - if dirname == "": |
753 | - return { |
754 | - "filelist": [ |
755 | - { |
756 | - "filename": "snapcraft.yaml", |
757 | - "file_id": "some-file-id", |
758 | - } |
759 | - ] |
760 | - } |
761 | + def getBlob(path, filename, *args, **kwargs): |
762 | + if filename == "snapcraft.yaml": |
763 | + return b"name: test-snap" |
764 | else: |
765 | - raise BranchFileNotFound("dummy", dirname) |
766 | + raise BranchFileNotFound("dummy", filename) |
767 | |
768 | self.useFixture( |
769 | BranchHostingFixture(blob=b"name: test-snap") |
770 | - ).getInventory = getInventory |
771 | + ).getBlob = getBlob |
772 | branch = self.factory.makeBranch() |
773 | self.assertEqual( |
774 | {"name": "test-snap"}, |
775 | @@ -2823,22 +2802,15 @@ class TestSnapSet(TestCaseWithFactory): |
776 | ) |
777 | |
778 | def test_getSnapcraftYaml_bzr_dot_snapcraft_yaml(self): |
779 | - def getInventory(unique_name, dirname, *args, **kwargs): |
780 | - if dirname == "": |
781 | - return { |
782 | - "filelist": [ |
783 | - { |
784 | - "filename": ".snapcraft.yaml", |
785 | - "file_id": "some-file-id", |
786 | - } |
787 | - ] |
788 | - } |
789 | + def getBlob(path, filename, *args, **kwargs): |
790 | + if filename == ".snapcraft.yaml": |
791 | + return b"name: test-snap" |
792 | else: |
793 | - raise BranchFileNotFound("dummy", dirname) |
794 | + raise BranchFileNotFound("dummy", filename) |
795 | |
796 | self.useFixture( |
797 | BranchHostingFixture(blob=b"name: test-snap") |
798 | - ).getInventory = getInventory |
799 | + ).getBlob = getBlob |
800 | branch = self.factory.makeBranch() |
801 | self.assertEqual( |
802 | {"name": "test-snap"}, |
803 | @@ -2846,7 +2818,7 @@ class TestSnapSet(TestCaseWithFactory): |
804 | ) |
805 | |
806 | def test_getSnapcraftYaml_bzr_error(self): |
807 | - self.useFixture(BranchHostingFixture()).getInventory = FakeMethod( |
808 | + self.useFixture(BranchHostingFixture()).getBlob = FakeMethod( |
809 | failure=BranchHostingFault |
810 | ) |
811 | branch = self.factory.makeBranch() |
812 | @@ -2926,7 +2898,6 @@ class TestSnapSet(TestCaseWithFactory): |
813 | def test_getSnapcraftYaml_snap_bzr(self): |
814 | self.useFixture( |
815 | BranchHostingFixture( |
816 | - file_list={"snapcraft.yaml": "some-file-id"}, |
817 | blob=b"name: test-snap", |
818 | ) |
819 | ) |
Good to see so much red! Just a few things to fix up before landing this, I think.