diff options
author | Aleksey Lim <alsroot@sugarlabs.org> | 2014-04-29 01:46:33 (GMT) |
---|---|---|
committer | Aleksey Lim <alsroot@sugarlabs.org> | 2014-04-29 01:46:33 (GMT) |
commit | 686643208fd9363487f0c89c53440db9d7fd42b3 (patch) | |
tree | e1a48ea6319356931092a673d0f8f0ac5def70a1 | |
parent | 0438dbe5fba595a11a77c5a311512e48cb9cad33 (diff) |
Fix file-less blobs behaviour
-rw-r--r-- | sugar_network/db/blobs.py | 29 | ||||
-rw-r--r-- | sugar_network/db/routes.py | 6 | ||||
-rw-r--r-- | sugar_network/node/model.py | 44 | ||||
-rwxr-xr-x | tests/units/client/client_routes.py | 4 | ||||
-rwxr-xr-x | tests/units/db/blobs.py | 41 |
5 files changed, 71 insertions, 53 deletions
diff --git a/sugar_network/db/blobs.py b/sugar_network/db/blobs.py index 95f1a4e..cc0944f 100644 --- a/sugar_network/db/blobs.py +++ b/sugar_network/db/blobs.py @@ -119,10 +119,12 @@ class Blobs(object): elif isinstance(content, dict): enforce('location' in content, http.BadRequest, 'No location') enforce('digest' in content, http.BadRequest, 'No digest') + enforce('content-length' in content, http.BadRequest, + 'No content-length') meta.append(('status', '301 Moved Permanently')) meta.append(('location', content['location'])) - with toolkit.new_file(tmp_path) as blob: - yield blob, content['digest'] + meta.append(('content-length', content['content-length'])) + yield None, content['digest'] else: with toolkit.new_file(tmp_path) as blob: blob.write(content) @@ -130,13 +132,15 @@ class Blobs(object): with write_blob() as (blob, digest): if digest_to_assert and digest != digest_to_assert: - blob.unlink() + if blob is not None: + blob.unlink() raise http.BadRequest('Digest mismatch') path = self._blob_path(digest) seqno = self._seqno.next() - meta.append(('content-length', str(blob.tell()))) meta.append(('x-seqno', str(seqno))) - blob.name = path + if blob is not None: + meta.append(('content-length', str(blob.tell()))) + blob.name = path _write_meta(path, meta, seqno) _logger.debug('Post %r file', path) @@ -157,7 +161,10 @@ class Blobs(object): elif isdir(path): return _lsdir(path, digest) elif exists(path): - return File(path, digest) + blob = File(path, digest) + blob.meta.set('content-length', str(blob.size)) + blob.meta.set('content-type', _guess_mime(path)) + return blob def delete(self, path): self._delete(self.path(path), None) @@ -206,12 +213,10 @@ class Blobs(object): continue else: _logger.debug('Found new %r blob', path) - mime_type = mimetypes.guess_type(filename)[0] or \ - 'application/octet-stream' if checkin_seqno is None: checkin_seqno = self._seqno.next() seqno = checkin_seqno - meta = [('content-type', mime_type), + meta = [('content-type', _guess_mime(filename)), ('content-length', str(os.stat(path).st_size)), ('x-seqno', str(seqno)), ] @@ -263,7 +268,7 @@ class Blobs(object): def _write_meta(path, meta, seqno): - if seqno: + if seqno and exists(path): os.utime(path, (seqno, seqno)) path += _META_SUFFIX with toolkit.new_file(path) as f: @@ -288,3 +293,7 @@ def _lsdir(root, rel_root): path = join(root, filename) if exists(path + _META_SUFFIX): yield File(path, join(rel_root, filename), _read_meta(path)) + + +def _guess_mime(path): + return mimetypes.guess_type(path)[0] or 'application/octet-stream' diff --git a/sugar_network/db/routes.py b/sugar_network/db/routes.py index 0ea1305..4c29780 100644 --- a/sugar_network/db/routes.py +++ b/sugar_network/db/routes.py @@ -81,7 +81,9 @@ class Routes(object): def find(self, reply, limit): self._preget() request = this.request - if self._find_limit and limit > self._find_limit: + if not limit: + request['limit'] = self._find_limit + elif self._find_limit and limit > self._find_limit: _logger.warning('The find limit is restricted to %s', self._find_limit) request['limit'] = self._find_limit @@ -168,7 +170,7 @@ class Routes(object): @fallbackroute('GET', ['blobs']) def blobs(self): - return self.volume.blobs.get(this.request.guid) + return self.volume.blobs.get(this.request.path[1:]) @contextmanager def _post(self, access): diff --git a/sugar_network/node/model.py b/sugar_network/node/model.py index f178913..d2a6475 100644 --- a/sugar_network/node/model.py +++ b/sugar_network/node/model.py @@ -422,10 +422,10 @@ def presolve(presolve_path): obs.presolve(repo_name, pkgs, presolve_path) -def load_bundle(blob, context=None, initial=False, extra_deps=None): +def load_bundle(blob, context=None, initial=False, extra_deps=None, + license=None, release_notes=None): context_type = None context_meta = None - release_notes = None version = None release = _ReleaseValue() release.guid = blob.digest @@ -437,16 +437,12 @@ def load_bundle(blob, context=None, initial=False, extra_deps=None): if not context: context = this.request['context'] version = this.request['version'] - if 'license' in this.request: - release['license'] = this.request['license'] - if isinstance(release['license'], basestring): - release['license'] = [release['license']] - release['stability'] = 'stable' release['bundles'] = { '*-*': { 'blob': blob.digest, }, } + release['stability'] = 'stable' else: context_type = 'activity' unpack_size = 0 @@ -454,7 +450,7 @@ def load_bundle(blob, context=None, initial=False, extra_deps=None): with bundle: changelog = join(bundle.rootdir, 'CHANGELOG') for arcname in bundle.get_names(): - if changelog and arcname == changelog: + if not release_notes and changelog and arcname == changelog: with bundle.extractfile(changelog) as f: release_notes = f.read() changelog = None @@ -472,8 +468,6 @@ def load_bundle(blob, context=None, initial=False, extra_deps=None): version = spec['version'] release['stability'] = spec['stability'] - if spec['license'] is not EMPTY_LICENSE: - release['license'] = spec['license'] release['commands'] = spec.commands release['requires'] = spec.requires release['bundles'] = { @@ -482,6 +476,8 @@ def load_bundle(blob, context=None, initial=False, extra_deps=None): 'unpack_size': unpack_size, }, } + if not license and spec['license'] is not EMPTY_LICENSE: + license = spec['license'] blob.meta['content-type'] = 'application/vnd.olpc-sugar' enforce(context, http.BadRequest, 'Context is not specified') @@ -502,12 +498,18 @@ def load_bundle(blob, context=None, initial=False, extra_deps=None): enforce(context_type in doc['type'], http.BadRequest, 'Inappropriate bundle type') - if 'license' not in release: + if not license: + license = this.request.get('license') + if license: + if isinstance(license, basestring): + license = [license] + else: releases = doc['releases'].values() enforce(releases, http.BadRequest, 'License is not specified') recent = max(releases, key=lambda x: x.get('value', {}).get('release')) enforce(recent, http.BadRequest, 'License is not specified') - release['license'] = recent['value']['license'] + license = recent['value']['license'] + release['license'] = license _logger.debug('Load %r release: %r', context, release) @@ -522,17 +524,15 @@ def load_bundle(blob, context=None, initial=False, extra_deps=None): else: # TRANS: 3rd party release notes title title = i18n._('%(name)s %(version)s third-party release') + announce = { + 'context': context, + 'type': 'notification', + 'title': i18n.encode(title, name=doc['title'], version=version), + 'message': release_notes or '', + } release['announce'] = this.call(method='POST', path=['post'], - content={ - 'context': context, - 'type': 'notification', - 'title': i18n.encode(title, - name=doc['title'], - version=version, - ), - 'message': release_notes or '', - }, - content_type='application/json', principal=this.principal) + content=announce, content_type='application/json', + principal=this.principal) blob.meta['content-disposition'] = 'attachment; filename="%s-%s%s"' % ( ''.join(i18n.decode(doc['title']).split()), version, diff --git a/tests/units/client/client_routes.py b/tests/units/client/client_routes.py index c000442..bc7572f 100755 --- a/tests/units/client/client_routes.py +++ b/tests/units/client/client_routes.py @@ -981,9 +981,11 @@ class ClientRoutesTest(tests.Test): coroutine.sleep(1) yield 'emote"' + trigger = self.wait_for_events(ipc, event='inline', state='online') + coroutine.dispatch() node_pid = self.fork_master([User], NodeRoutes) self.client_routes._remote_connect() - self.wait_for_events(ipc, event='inline', state='online').wait() + trigger.wait() ts = time.time() self.assertEqual('remote', ipc.get(cmd='sleep')) diff --git a/tests/units/db/blobs.py b/tests/units/db/blobs.py index 35ebb62..d5d2b1e 100755 --- a/tests/units/db/blobs.py +++ b/tests/units/db/blobs.py @@ -40,12 +40,13 @@ class BlobsTest(tests.Test): self.assertEqual( content, file(blob.path).read()) - self.assertEqual([ - 'content-type: application/octet-stream', - 'content-length: %s' % len(content), - 'x-seqno: 1', - ], - file(blob.path + '.meta').read().strip().split('\n')) + self.assertEqual( + sorted([ + 'content-type: application/octet-stream', + 'content-length: %s' % len(content), + 'x-seqno: 1', + ]), + sorted(file(blob.path + '.meta').read().strip().split('\n'))) the_same_blob = blobs.get(blob.digest) assert the_same_blob is not blob @@ -75,12 +76,13 @@ class BlobsTest(tests.Test): self.assertEqual( content, file(blob.path).read()) - self.assertEqual([ - 'content-type: application/octet-stream', - 'content-length: %s' % len(content), - 'x-seqno: 1', - ], - file(blob.path + '.meta').read().strip().split('\n')) + self.assertEqual( + sorted([ + 'content-type: application/octet-stream', + 'content-length: %s' % len(content), + 'x-seqno: 1', + ]), + sorted(file(blob.path + '.meta').read().strip().split('\n'))) the_same_blob = blobs.get(blob.digest) assert the_same_blob is not blob @@ -93,7 +95,12 @@ class BlobsTest(tests.Test): self.assertRaises(http.BadRequest, blobs.post, {}) self.assertRaises(http.BadRequest, blobs.post, {'digest': 'digest'}) - blob = blobs.post({'location': 'location', 'digest': '0000000000000000000000000000000000000000', 'foo': 'bar'}) + blob = blobs.post({ + 'location': 'location', + 'digest': '0000000000000000000000000000000000000000', + 'content-length': '101', + 'foo': 'bar', + }) self.assertEqual( '0000000000000000000000000000000000000000', @@ -105,20 +112,18 @@ class BlobsTest(tests.Test): 'status': '301 Moved Permanently', 'location': 'location', 'content-type': 'application/octet-stream', - 'content-length': '0', + 'content-length': '101', 'x-seqno': '1', }, blob.meta) - self.assertEqual( - '', - file(blob.path).read()) + assert not exists(blob.path) self.assertEqual( sorted([ 'status: 301 Moved Permanently', 'location: location', 'content-type: application/octet-stream', - 'content-length: 0', + 'content-length: 101', 'x-seqno: 1', ]), sorted(file(blob.path + '.meta').read().strip().split('\n'))) |