def test_localRealPath(self): # localRealPath takes a URL-encoded relpath and returns a URL-encoded # absolute path. filename = 'foo bar' escaped_filename = urlutils.escape(filename) self.assertNotEqual(filename, escaped_filename) realpath = self.transport.local_realPath(escaped_filename) self.assertEqual(urlutils.escape(os.path.abspath(filename)), realpath)
def test_localRealPath(self): # localRealPath takes a URL-encoded relpath and returns a URL-encoded # absolute path. filename = 'foo bar' escaped_filename = urlutils.escape(filename) self.assertNotEqual(filename, escaped_filename) realpath = self.transport.local_realPath(escaped_filename) self.assertEqual( urlutils.escape(os.path.abspath(filename)), realpath)
def translate_client_path(self, client_path): """Translate a path received from a network client into a local relpath. All paths received from the client *must* be translated. :param client_path: the path from the client. :returns: a relpath that may be used with self._backing_transport (unlike the untranslated client_path, which must not be used with the backing transport). """ if self._root_client_path is None: # no translation necessary! return client_path if not client_path.startswith('/'): client_path = '/' + client_path if client_path + '/' == self._root_client_path: return '.' if client_path.startswith(self._root_client_path): path = client_path[len(self._root_client_path):] relpath = urlutils.joinpath('/', path) if not relpath.startswith('/'): raise ValueError(relpath) return urlutils.escape('.' + relpath) else: raise errors.PathNotChild(client_path, self._root_client_path)
def __init__(self, transport, name, flags, server): self._unescaped_relpath = name self._escaped_path = urlutils.escape(self._unescaped_relpath) self._flags = flags self.transport = transport self._written = False self._server = server
def getAttrs(self, path, followLinks): """See `ISFTPServer`. This just delegates to TransportSFTPFile's implementation. """ deferred = self.transport.stat(urlutils.escape(path)) return deferred.addCallback(self._translate_stat)
def test_no_such_product_series_non_ascii(self): # lp:product/<non-ascii-string> resolves to the branch alias with the # name escaped. product = self.factory.makeProduct() lp_path = '%s/%s' % (product.name, NON_ASCII_NAME) escaped_name = urlutils.escape(lp_path) self.assertResolves(lp_path, None, escaped_name)
def get_url(self): """See bzrlib.transport.Server.get_url.""" homedir = self._homedir if sys.platform != 'win32': # Remove the initial '/' on all platforms but win32 homedir = homedir[1:] return self._get_sftp_url(urlutils.escape(homedir))
def performLookup(self, requester_id, lookup, branch_name_only=False): branch = None if branch_name_only and lookup['type'] != 'branch_name': return if lookup['type'] == 'control_name': return self._serializeControlDirectory(requester_id, lookup) elif lookup['type'] == 'id': branch = self._branch_set.get(lookup['branch_id']) if branch is None: return None trailing = lookup['trailing'] elif lookup['type'] == 'alias': result = get_first_path_result(lookup['lp_path'], lambda l: self.performLookup(requester_id, l, branch_name_only=True), None) if result is not None: return result product_name = lookup['lp_path'].split('/', 2)[0] product = self._product_set.getByName(product_name) if product is None: return None branch = product.development_focus.branch trailing = lookup['lp_path'][len(product_name):] elif lookup['type'] == 'branch_name': branch = self._branch_set._find( unique_name=lookup['unique_name']) trailing = escape(lookup['trailing']) else: return None if branch is not None: serialized = self._serializeBranch(requester_id, branch, trailing.lstrip('/'), lookup['type'] == 'id') if serialized is not None: return serialized
def performLookup(self, lookup): if lookup['type'] == 'id': return (self.get(lookup['branch_id']), lookup['trailing']) elif lookup['type'] == 'alias': try: branch, trail = self.getByLPPath(lookup['lp_path']) return branch, escape(trail) except (InvalidProductName, NoLinkedBranch, CannotHaveLinkedBranch, NameLookupFailed, InvalidNamespace): pass elif lookup['type'] == 'branch_name': result = IStore(Branch).find( Branch, Branch.unique_name == lookup['unique_name']) for branch in result: return (branch, escape(lookup['trailing'])) return None, ''
def local_path_to_url(local_path): """Return a file:// URL to `local_path`. This implementation is unusual in that it returns a file://localhost/ URL. This is to work around the valid_vcs_details constraint on CodeImport. """ return 'file://localhost' + escape( os.path.normpath(os.path.abspath(local_path)))
def performLookup(self, lookup): if lookup['type'] == 'id': return (self.get(lookup['branch_id']), lookup['trailing']) elif lookup['type'] == 'alias': try: branch, trail = self.getByLPPath(lookup['lp_path']) return branch, escape(trail) except (InvalidProductName, NoLinkedBranch, CannotHaveLinkedBranch, NameLookupFailed, InvalidNamespace): pass elif lookup['type'] == 'branch_name': result = IStore(Branch).find(Branch, Branch.unique_name == lookup['unique_name']) for branch in result: return (branch, escape(lookup['trailing'])) return None, ''
def test_resolve_branch_with_no_such_owner_non_ascii(self): # lp:~<non-ascii-string>/product/name returns NoSuchPersonWithName # with the name escaped. nonexistent_owner_branch = u"~%s/%s/%s" % ( NON_ASCII_NAME, self.factory.getUniqueString(), self.factory.getUniqueString()) self.assertFault( nonexistent_owner_branch, faults.NoSuchPersonWithName(urlutils.escape(NON_ASCII_NAME)))
def check_entry(entries, filename): t = get_transport('.') stat = t.stat(urlutils.escape('%s/%s' % (parent_dir, filename))) named_entries = [ entry for entry in entries if entry[0] == filename] self.assertEqual(1, len(named_entries)) name, longname, attrs = named_entries[0] self.assertEqual(lsLine(name, stat), longname) self.assertEqual(self.sftp_server._translate_stat(stat), attrs)
def test_no_such_branch_product_non_ascii(self): # A path to a branch that contains non ascii characters will never # find a branch, but it still resolves rather than erroring. owner = self.factory.makePerson() product = self.factory.makeProduct() nonexistent_branch = u'~%s/%s/%s' % ( owner.name, product.name, NON_ASCII_NAME) self.assertResolves( nonexistent_branch, urlutils.escape(nonexistent_branch))
def test_no_such_branch_product_non_ascii(self): # A path to a branch that contains non ascii characters will never # find a branch, but it still resolves rather than erroring. owner = self.factory.makePerson() product = self.factory.makeProduct() nonexistent_branch = u'~%s/%s/%s' % (owner.name, product.name, NON_ASCII_NAME) self.assertResolves(nonexistent_branch, urlutils.escape(nonexistent_branch))
def realPath(self, relpath): """See `ISFTPServer`.""" deferred = self.transport.local_realPath(urlutils.escape(relpath)) def unescape_path(path): unescaped_path = urlutils.unescape(path) return unescaped_path.encode('utf-8') return deferred.addCallback(unescape_path)
def _serializeControlDirectory(self, requester, lookup): try: namespace = lookup_branch_namespace(lookup['control_name']) except (InvalidNamespace, NotFoundError): return trailing_path = lookup['trailing'].lstrip('/') if not ('.bzr' == trailing_path or trailing_path.startswith('.bzr/')): # '.bzr' is OK, '.bzr/foo' is OK, '.bzrfoo' is not. return default_branch = namespace.target.default_stacked_on_branch if default_branch is None: return try: path = branch_id_alias(default_branch) except Unauthorized: return return (CONTROL_TRANSPORT, { 'default_stack_on': escape(path) }, escape(trailing_path))
def test_realPathEscaping(self): # local_realPath returns an escaped path to the file. escaped_path = escape('~baz') deferred = self.transport.mkdir(escaped_path) def get_real_path(ignored): return self.transport.local_realPath(escaped_path) deferred.addCallback(get_real_path) return deferred.addCallback(self.assertEqual, '/' + escaped_path)
def _serializeControlDirectory(self, requester, lookup): try: namespace = lookup_branch_namespace(lookup['control_name']) except (InvalidNamespace, NotFoundError): return trailing_path = lookup['trailing'].lstrip('/') if not ('.bzr' == trailing_path or trailing_path.startswith('.bzr/')): # '.bzr' is OK, '.bzr/foo' is OK, '.bzrfoo' is not. return default_branch = namespace.target.default_stacked_on_branch if default_branch is None: return try: path = branch_id_alias(default_branch) except Unauthorized: return return ( CONTROL_TRANSPORT, {'default_stack_on': escape(path)}, escape(trailing_path))
def _get_compose_commandline(self, to, subject, attach_path): """See ExternalMailClient._get_compose_commandline""" message_options = {} if subject is not None: message_options['subject'] = subject if attach_path is not None: message_options['attach'] = attach_path options_list = ['%s=%s' % (k, urlutils.escape(v)) for (k, v) in sorted(message_options.iteritems())] return ['mailto:%s?%s' % (self._encode_safe(to or ''), '&'.join(options_list))]
def test_get_mapped_file_escaped_url(self): # Getting a file from a public branch URL gets the file as stored on # the base transport, even when the URL is escaped. branch = self.factory.makeAnyBranch( branch_type=BranchType.HOSTED, owner=self.requester) backing_transport = self._makeOnBackingTransport(branch) backing_transport.put_bytes('hello.txt', 'Hello World!') url = escape('%s/.bzr/hello.txt' % branch.unique_name) transport = self.getTransport() deferred = self._ensureDeferred(transport.get_bytes, url) return deferred.addCallback(self.assertEqual, 'Hello World!')
def test_get_mapped_file_escaped_url(self): # Getting a file from a public branch URL gets the file as stored on # the base transport, even when the URL is escaped. branch = self.factory.makeAnyBranch(branch_type=BranchType.HOSTED, owner=self.requester) backing_transport = self._makeOnBackingTransport(branch) backing_transport.put_bytes('hello.txt', 'Hello World!') url = escape('%s/.bzr/hello.txt' % branch.unique_name) transport = self.getTransport() deferred = self._ensureDeferred(transport.get_bytes, url) return deferred.addCallback(self.assertEqual, 'Hello World!')
def list_dir(self, relpath): """See Transport.list_dir.""" if 'gio' in debug.debug_flags: mutter("GIO list_dir") try: entries = [] f = self._get_GIO(relpath) children = f.enumerate_children(gio.FILE_ATTRIBUTE_STANDARD_NAME) for child in children: entries.append(urlutils.escape(child.get_name())) return entries except gio.Error, e: self._translate_gio_error(e, relpath)
def test_canAccessEscapedPathsOnDisk(self): # Sometimes, the paths to files on disk are themselves URL-escaped. # The AsyncVirtualTransport can access these files. # # This test added in response to https://launchpad.net/bugs/236380. escaped_disk_path = 'prefix_%43razy' content = 'content\n' escaped_file = open(escaped_disk_path, 'w') escaped_file.write(content) escaped_file.close() deferred = self.transport.get_bytes(escape('%43razy')) return deferred.addCallback(self.assertEqual, content)
def openDirectory(self, path): """See `ISFTPServer`.""" escaped_path = urlutils.escape(path) deferred = self.transport.list_dir(escaped_path) def produce_entries_from_file_list(file_list): stats_deferred = self._stat_files_in_list(file_list, escaped_path) stats_deferred.addCallback(self._format_directory_entries, file_list) return stats_deferred return deferred.addCallback( produce_entries_from_file_list).addCallback(DirectoryListing)
def create_branch(requester): if not branch_path.startswith('/'): return faults.InvalidPath(branch_path) escaped_path = unescape(branch_path.strip('/')) try: namespace, branch_name, link_func, path = ( self._getBranchNamespaceExtras(escaped_path, requester)) except ValueError: return faults.PermissionDenied( "Cannot create branch at '%s'" % branch_path) except InvalidNamespace: return faults.PermissionDenied( "Cannot create branch at '%s'" % branch_path) except NoSuchPerson as e: return faults.NotFound( "User/team '%s' does not exist." % e.name) except NoSuchProduct as e: return faults.NotFound( "Project '%s' does not exist." % e.name) except InvalidProductName as e: return faults.InvalidProductName(escape(e.name)) except NoSuchSourcePackageName as e: try: getUtility(ISourcePackageNameSet).new(e.name) except InvalidName: return faults.InvalidSourcePackageName(e.name) return self.createBranch(login_id, branch_path) except NameLookupFailed as e: return faults.NotFound(str(e)) try: branch = namespace.createBranch( BranchType.HOSTED, branch_name, requester) except LaunchpadValidationError as e: msg = e.args[0] if isinstance(msg, unicode): msg = msg.encode('utf-8') return faults.PermissionDenied(msg) except BranchCreationException as e: return faults.PermissionDenied(str(e)) if link_func: try: link_func(branch) except Unauthorized: # We don't want to keep the branch we created. transaction.abort() return faults.PermissionDenied( "Cannot create linked branch at '%s'." % path) return branch.id
def create_branch(requester): if not branch_path.startswith('/'): return faults.InvalidPath(branch_path) escaped_path = unescape(branch_path.strip('/')) try: namespace, branch_name, link_func, path = ( self._getBranchNamespaceExtras(escaped_path, requester)) except ValueError: return faults.PermissionDenied("Cannot create branch at '%s'" % branch_path) except InvalidNamespace: return faults.PermissionDenied("Cannot create branch at '%s'" % branch_path) except NoSuchPerson as e: return faults.NotFound("User/team '%s' does not exist." % e.name) except NoSuchProduct as e: return faults.NotFound("Project '%s' does not exist." % e.name) except InvalidProductName as e: return faults.InvalidProductName(escape(e.name)) except NoSuchSourcePackageName as e: try: getUtility(ISourcePackageNameSet).new(e.name) except InvalidName: return faults.InvalidSourcePackageName(e.name) return self.createBranch(login_id, branch_path) except NameLookupFailed as e: return faults.NotFound(str(e)) try: branch = namespace.createBranch(BranchType.HOSTED, branch_name, requester) except LaunchpadValidationError as e: msg = e.args[0] if isinstance(msg, unicode): msg = msg.encode('utf-8') return faults.PermissionDenied(msg) except BranchCreationException as e: return faults.PermissionDenied(str(e)) if link_func: try: link_func(branch) except Unauthorized: # We don't want to keep the branch we created. transaction.abort() return faults.PermissionDenied( "Cannot create linked branch at '%s'." % path) return branch.id
def _get_compose_commandline(self, to, subject, attach_path): """See ExternalMailClient._get_compose_commandline""" message_options = {} if subject is not None: message_options['subject'] = subject if attach_path is not None: message_options['attach'] = attach_path options_list = [ '%s=%s' % (k, urlutils.escape(v)) for (k, v) in sorted(message_options.iteritems()) ] return [ 'mailto:%s?%s' % (self._encode_safe(to or ''), '&'.join(options_list)) ]
def _getBranchPaths(self, strip_path, supported_schemes): """Get the specific paths for a branch. If the branch is not found, but it looks like a branch name, then we return a writable URL for it. If it doesn't look like a branch name a fault is raised. """ branch_set = getUtility(IBranchLookup) try: branch, suffix = branch_set.getByLPPath(strip_path) except NoSuchBranch: # If the branch isn't found, but it looks like a valid name, then # resolve it anyway, treating the path like a branch's unique # name. This lets people push new branches up to Launchpad using # lp: URL syntax. supported_schemes = ['bzr+ssh'] return self._getUniqueNameResultDict( strip_path, supported_schemes=supported_schemes) # XXX: JonathanLange 2009-03-21 bug=347728: All of this is repetitive # and thus error prone. Alternatives are directly raising faults from # the model code(blech) or some automated way of reraising as faults # or using a narrower range of faults (e.g. only one "NoSuch" fault). except InvalidProductName as e: raise faults.InvalidProductName(urlutils.escape(e.name)) except NoSuchProductSeries as e: raise faults.NoSuchProductSeries(urlutils.escape(e.name), e.product) except NoSuchPerson as e: raise faults.NoSuchPersonWithName(urlutils.escape(e.name)) except NoSuchProduct as e: raise faults.NoSuchProduct(urlutils.escape(e.name)) except NoSuchDistroSeries as e: raise faults.NoSuchDistroSeries(urlutils.escape(e.name)) except NoSuchSourcePackageName as e: raise faults.NoSuchSourcePackageName(urlutils.escape(e.name)) except NoLinkedBranch as e: raise faults.NoLinkedBranch(e.component) except CannotHaveLinkedBranch as e: raise faults.CannotHaveLinkedBranch(e.component) except InvalidNamespace as e: raise faults.InvalidBranchUniqueName(urlutils.escape(e.name)) # Reverse engineer the actual lp_path that is used, so we need to # remove any suffix that may be there from the strip_path. lp_path = strip_path if suffix != '': # E.g. 'project/trunk/filename.txt' the suffix is 'filename.txt' # we want lp_path to be 'project/trunk'. lp_path = lp_path[:-(len(suffix) + 1)] return self._getUrlsForBranch(branch, lp_path, suffix, supported_schemes)
def _serializeControlDirectory(self, requester, lookup): trailing_path = lookup['trailing'].lstrip('/') if not ('.bzr' == trailing_path or trailing_path.startswith('.bzr/')): return target = self._get_product_target(lookup['control_name']) if target is None: target = self._get_package_target(lookup['control_name']) if target is None: return default_branch = IBranchTarget(target).default_stacked_on_branch if default_branch is None: return if not self._canRead(requester, default_branch): return path = branch_id_alias(default_branch) return (CONTROL_TRANSPORT, { 'default_stack_on': escape(path) }, trailing_path)
def _getBranchPaths(self, strip_path, supported_schemes): """Get the specific paths for a branch. If the branch is not found, but it looks like a branch name, then we return a writable URL for it. If it doesn't look like a branch name a fault is raised. """ branch_set = getUtility(IBranchLookup) try: branch, suffix = branch_set.getByLPPath(strip_path) except NoSuchBranch: # If the branch isn't found, but it looks like a valid name, then # resolve it anyway, treating the path like a branch's unique # name. This lets people push new branches up to Launchpad using # lp: URL syntax. supported_schemes = ["bzr+ssh"] return self._getUniqueNameResultDict(strip_path, supported_schemes=supported_schemes) # XXX: JonathanLange 2009-03-21 bug=347728: All of this is repetitive # and thus error prone. Alternatives are directly raising faults from # the model code(blech) or some automated way of reraising as faults # or using a narrower range of faults (e.g. only one "NoSuch" fault). except InvalidProductName as e: raise faults.InvalidProductName(urlutils.escape(e.name)) except NoSuchProductSeries as e: raise faults.NoSuchProductSeries(urlutils.escape(e.name), e.product) except NoSuchPerson as e: raise faults.NoSuchPersonWithName(urlutils.escape(e.name)) except NoSuchProduct as e: raise faults.NoSuchProduct(urlutils.escape(e.name)) except NoSuchDistroSeries as e: raise faults.NoSuchDistroSeries(urlutils.escape(e.name)) except NoSuchSourcePackageName as e: raise faults.NoSuchSourcePackageName(urlutils.escape(e.name)) except NoLinkedBranch as e: raise faults.NoLinkedBranch(e.component) except CannotHaveLinkedBranch as e: raise faults.CannotHaveLinkedBranch(e.component) except InvalidNamespace as e: raise faults.InvalidBranchUniqueName(urlutils.escape(e.name)) # Reverse engineer the actual lp_path that is used, so we need to # remove any suffix that may be there from the strip_path. lp_path = strip_path if suffix != "": # E.g. 'project/trunk/filename.txt' the suffix is 'filename.txt' # we want lp_path to be 'project/trunk'. lp_path = lp_path[: -(len(suffix) + 1)] return self._getUrlsForBranch(branch, lp_path, suffix, supported_schemes)
def _serializeControlDirectory(self, requester, lookup): trailing_path = lookup['trailing'].lstrip('/') if not ('.bzr' == trailing_path or trailing_path.startswith('.bzr/')): return target = self._get_product_target(lookup['control_name']) if target is None: target = self._get_package_target(lookup['control_name']) if target is None: return default_branch = IBranchTarget(target).default_stacked_on_branch if default_branch is None: return if not self._canRead(requester, default_branch): return path = branch_id_alias(default_branch) return ( CONTROL_TRANSPORT, {'default_stack_on': escape(path)}, trailing_path)
def test_url_escaping(self): # Transports accept and return escaped URL segments. The literal path # we use should be preserved, even if it can be unescaped itself. transport = self._getBzrDirTransport() # The bug we are checking only occurs if # unescape(path).encode('utf-8') != path. path = '%41%42%43' escaped_path = escape(path) content = 'content' transport.put_bytes(escaped_path, content) # We can use the escaped path to reach the file. self.assertEqual(content, transport.get_bytes(escaped_path)) # We can also use the value that list_dir returns, which may be # different from our original escaped path. Note that in this case, # returned_path is equivalent but not equal to escaped_path. [returned_path] = list(transport.list_dir('.')) self.assertEqual(content, transport.get_bytes(returned_path))
def test_set_get_parent(self): """Set, re-get and reset the parent""" b = self.make_branch('subdir') url = 'http://example.com/bzr/bzr.dev' b.set_parent(url) self.assertEqual(url, b.get_parent()) self.assertEqual(url, b._get_parent_location()) b.set_parent(None) self.assertEqual(None, b.get_parent()) b.set_parent('../other_branch') expected_parent = urlutils.join(self.get_url('subdir'), '../other_branch') self.assertEqual(expected_parent, b.get_parent()) path = urlutils.join(self.get_url('subdir'), '../yanb') b.set_parent(path) self.assertEqual('../yanb', b._get_parent_location()) self.assertEqual(path, b.get_parent()) self.assertRaises(bzrlib.errors.InvalidURL, b.set_parent, u'\xb5') b.set_parent(urlutils.escape(u'\xb5')) self.assertEqual('%C2%B5', b._get_parent_location()) self.assertEqual(b.base + '%C2%B5', b.get_parent()) # Handle the case for older style absolute local paths if sys.platform == 'win32': # TODO: jam 20060515 Do we want to special case Windows local # paths as well? Nobody has complained about it. pass else: b.lock_write() b._set_parent_location('/local/abs/path') b.unlock() self.assertEqual('file:///local/abs/path', b.get_parent())
def test_escape_unescape(self): self.assertEqual(u'\xe5', urlutils.unescape(urlutils.escape(u'\xe5'))) self.assertEqual('%', urlutils.unescape(urlutils.escape('%')))
def test_escape_tildes(self): self.assertEqual('~foo', urlutils.escape('~foo'))
def test_escape(self): self.assertEqual('%25', urlutils.escape('%')) self.assertEqual('%C3%A5', urlutils.escape(u'\xe5')) self.assertFalse(isinstance(urlutils.escape(u'\xe5'), unicode))
def _escape(self, file_or_path): if not isinstance(file_or_path, basestring): file_or_path = '/'.join(file_or_path) if file_or_path == '': return u'' return urlutils.escape(osutils.safe_unicode(file_or_path))
' Assuming it means empty directory', str(e)) return [] raise finally: # Restore binary mode as nlst switch to ascii mode to retrieve file # list f.voidcmd('TYPE I') # If FTP.nlst returns paths prefixed by relpath, strip 'em if paths and paths[0].startswith(basepath): entries = [path[len(basepath)+1:] for path in paths] else: entries = paths # Remove . and .. if present return [urlutils.escape(entry) for entry in entries if entry not in ('.', '..')] def iter_files_recursive(self): """See Transport.iter_files_recursive. This is cargo-culted from the SFTP transport""" mutter("FTP iter_files_recursive") queue = list(self.list_dir(".")) while queue: relpath = queue.pop(0) st = self.stat(relpath) if stat.S_ISDIR(st.st_mode): for i, basename in enumerate(self.list_dir(relpath)): queue.insert(i, relpath+"/"+basename) else:
def _createBranch(self, registrant, branch_path): """The guts of the create branch method. Raises exceptions on error conditions. """ to_link = None if branch_path.startswith(BRANCH_ALIAS_PREFIX + '/'): branch_path = branch_path[len(BRANCH_ALIAS_PREFIX) + 1:] if branch_path.startswith('~'): data, branch_name = self._parseUniqueName(branch_path) else: tokens = branch_path.split('/') data = { 'person': registrant.name, 'product': tokens[0], } branch_name = 'trunk' # check the series product = self._product_set.getByName(data['product']) if product is not None: if len(tokens) > 1: series = product.getSeries(tokens[1]) if series is None: raise faults.NotFound( "No such product series: '%s'." % tokens[1]) else: to_link = ICanHasLinkedBranch(series) else: to_link = ICanHasLinkedBranch(product) # don't forget the link. else: data, branch_name = self._parseUniqueName(branch_path) owner = self._person_set.getByName(data['person']) if owner is None: raise faults.NotFound( "User/team '%s' does not exist." % (data['person'],)) # The real code consults the branch creation policy of the product. We # don't need to do so here, since the tests above this layer never # encounter that behaviour. If they *do* change to rely on the branch # creation policy, the observed behaviour will be failure to raise # exceptions. if not registrant.inTeam(owner): raise faults.PermissionDenied( ('%s cannot create branches owned by %s' % (registrant.displayname, owner.displayname))) product = sourcepackage = None if data['product'] == '+junk': product = None elif data['product'] is not None: if not valid_name(data['product']): raise faults.InvalidProductName(escape(data['product'])) product = self._product_set.getByName(data['product']) if product is None: raise faults.NotFound( "Project '%s' does not exist." % (data['product'],)) elif data['distribution'] is not None: distro = self._distribution_set.getByName(data['distribution']) if distro is None: raise faults.NotFound( "No such distribution: '%s'." % (data['distribution'],)) distroseries = self._distroseries_set.getByName( data['distroseries']) if distroseries is None: raise faults.NotFound( "No such distribution series: '%s'." % (data['distroseries'],)) sourcepackagename = self._sourcepackagename_set.getByName( data['sourcepackagename']) if sourcepackagename is None: try: sourcepackagename = self._sourcepackagename_set.new( data['sourcepackagename']) except InvalidName: raise faults.InvalidSourcePackageName( data['sourcepackagename']) sourcepackage = self._factory.makeSourcePackage( distroseries, sourcepackagename) else: raise faults.PermissionDenied( "Cannot create branch at '%s'" % branch_path) branch = self._factory.makeBranch( owner=owner, name=branch_name, product=product, sourcepackage=sourcepackage, registrant=registrant, branch_type=BranchType.HOSTED) if to_link is not None: if registrant.inTeam(to_link.product.owner): to_link.branch = branch else: self._branch_set._delete(branch) raise faults.PermissionDenied( "Cannot create linked branch at '%s'." % branch_path) return branch.id
def iter_files_recursive(self): for file in self._files: if file.startswith(self._cwd): yield urlutils.escape(file[len(self._cwd):])
def removeDirectory(self, path): """See `ISFTPServer`.""" return self.transport.rmdir(urlutils.escape(path))
def __call__(self, environ, start_response): environ['loggerhead.static.url'] = environ['SCRIPT_NAME'] if environ['PATH_INFO'].startswith('/static/'): path_info_pop(environ) return static_app(environ, start_response) elif environ['PATH_INFO'] == '/favicon.ico': return favicon_app(environ, start_response) elif environ['PATH_INFO'] == '/robots.txt': return robots_app(environ, start_response) elif environ['PATH_INFO'].startswith('/+login'): return self._complete_login(environ, start_response) elif environ['PATH_INFO'].startswith('/+logout'): return self._logout(environ, start_response) path = environ['PATH_INFO'] trailingSlashCount = len(path) - len(path.rstrip('/')) user = environ[self.session_var].get('user', LAUNCHPAD_ANONYMOUS) lp_server = get_lp_server(user, branch_transport=self.get_transport()) lp_server.start_server() try: try: transport_type, info, trail = self.branchfs.translatePath( user, urlutils.escape(path)) except xmlrpclib.Fault as f: if check_fault(f, faults.PathTranslationError): raise HTTPNotFound() elif check_fault(f, faults.PermissionDenied): # If we're not allowed to see the branch... if environ['wsgi.url_scheme'] != 'https': # ... the request shouldn't have come in over http, as # requests for private branches over http should be # redirected to https by the dynamic rewrite script we # use (which runs before this code is reached), but # just in case... env_copy = environ.copy() env_copy['wsgi.url_scheme'] = 'https' raise HTTPMovedPermanently(construct_url(env_copy)) elif user != LAUNCHPAD_ANONYMOUS: # ... if the user is already logged in and still can't # see the branch, they lose. exc = HTTPUnauthorized() exc.explanation = "You are logged in as %s." % user raise exc else: # ... otherwise, lets give them a chance to log in # with OpenID. return self._begin_login(environ, start_response) else: raise if transport_type != BRANCH_TRANSPORT: raise HTTPNotFound() trail = urlutils.unescape(trail).encode('utf-8') trail += trailingSlashCount * '/' amount_consumed = len(path) - len(trail) consumed = path[:amount_consumed] branch_name = consumed.strip('/') self.log.info('Using branch: %s', branch_name) if trail and not trail.startswith('/'): trail = '/' + trail environ['PATH_INFO'] = trail environ['SCRIPT_NAME'] += consumed.rstrip('/') branch_url = lp_server.get_url() + branch_name branch_link = urlparse.urljoin( config.codebrowse.launchpad_root, branch_name) cachepath = os.path.join( config.codebrowse.cachepath, branch_name[1:]) if not os.path.isdir(cachepath): os.makedirs(cachepath) self.log.info('branch_url: %s', branch_url) base_api_url = allvhosts.configs['api'].rooturl branch_api_url = '%s/%s/%s' % ( base_api_url, 'devel', branch_name, ) self.log.info('branch_api_url: %s', branch_api_url) req = urllib2.Request(branch_api_url) private = False try: # We need to determine if the branch is private response = urllib2.urlopen(req) except urllib2.HTTPError as response: code = response.getcode() if code in (400, 401, 403, 404): # There are several error codes that imply private data. # 400 (bad request) is a default error code from the API # 401 (unauthorized) should never be returned as the # requests are always from anon. If it is returned # however, the data is certainly private. # 403 (forbidden) is obviously private. # 404 (not found) implies privacy from a private team or # similar situation, which we hide as not existing rather # than mark as forbidden. self.log.info("Branch is private") private = True self.log.info( "Branch state not determined; api error, return code: %s", code) response.close() else: self.log.info("Branch is public") response.close() try: bzr_branch = safe_open( lp_server.get_url().strip(':/'), branch_url) except errors.NotBranchError as err: self.log.warning('Not a branch: %s', err) raise HTTPNotFound() bzr_branch.lock_read() try: view = BranchWSGIApp( bzr_branch, branch_name, {'cachepath': cachepath}, self.graph_cache, branch_link=branch_link, served_url=None, private=private) return view.app(environ, start_response) finally: bzr_branch.repository.revisions.clear_cache() bzr_branch.repository.signatures.clear_cache() bzr_branch.repository.inventories.clear_cache() if bzr_branch.repository.chk_bytes is not None: bzr_branch.repository.chk_bytes.clear_cache() bzr_branch.repository.texts.clear_cache() bzr_branch.unlock() finally: lp_server.stop_server()
def removeFile(self, path): """See `ISFTPServer`.""" return self.transport.delete(urlutils.escape(path))
def local_realPath(self, path): """Return the absolute path to `path`.""" abspath = self._abspath(path) return urlutils.escape(os.path.realpath(abspath))
def renameFile(self, oldpath, newpath): """See `ISFTPServer`.""" return self.transport.rename(urlutils.escape(oldpath), urlutils.escape(newpath))