Пример #1
0
    def _find_repository_id(self, plan, owner, repo_name):
        """Finds the ID of a repository matching the given name and owner.

        If the repository could not be found, an appropriate error will be
        raised.
        """
        # GitLab claims pagination support, but it has a number of problems.
        # We have no idea how many pages there are, or even if there's another
        # page of items. Furthermore, if we try to go beyond the last page,
        # we just get the first again, so we can't attempt to guess very
        # well.
        #
        # If the list doesn't return the repository, the user is out of luck.
        #
        # This is true as of GitLab 6.4.3.
        repositories = self._api_get_repositories()

        for repository_entry in repositories:
            namespace = repository_entry['namespace']

            if (namespace['path'] == owner
                    and repository_entry['path'] == repo_name):
                # This is the repository we wanted to find.
                return repository_entry['id']

        if plan == 'personal':
            raise RepositoryError(
                ugettext('A repository with this name was not found, or your '
                         'user may not own it.'))
        elif plan == 'group':
            raise RepositoryError(
                ugettext('A repository with this name was not found on this '
                         'group, or your user may not have access to it.'))
        else:
            raise InvalidPlanError(plan)
Пример #2
0
    def check_repository(self, plan=DEFAULT_PLAN, *args, **kwargs):
        """Checks the validity of a repository.

        This will perform an API request against Bitbucket to get
        information on the repository. This will throw an exception if
        the repository was not found, and return cleanly if it was found.
        """
        repo_name = self._get_repository_name_raw(plan, kwargs)

        if '/' in repo_name:
            raise RepositoryError(
                ugettext('Please specify just the name of the repository, not '
                         'a path.'))

        if '.git' in repo_name:
            raise RepositoryError(
                ugettext(
                    'Please specify just the name of the repository without '
                    '".git".'))

        try:
            self._api_get_repository(
                self._get_repository_owner_raw(plan, kwargs),
                self._get_repository_name_raw(plan, kwargs))
        except HostingServiceError as e:
            if six.text_type(e) == 'Resource not found':
                raise RepositoryError(
                    ugettext('A repository with this name was not found.'))

            raise
Пример #3
0
    def check_repository(self,
                         plan=DEFAULT_PLAN,
                         tool_name=None,
                         *args,
                         **kwargs):
        """Checks the validity of a repository.

        This will perform an API request against Bitbucket to get
        information on the repository. This will throw an exception if
        the repository was not found, and return cleanly if it was found.
        """
        repo_name = self._get_repository_name_raw(plan, kwargs)

        if '/' in repo_name:
            raise RepositoryError(
                ugettext('Please specify just the name of the repository, not '
                         'a path.'))

        if '.git' in repo_name:
            raise RepositoryError(
                ugettext(
                    'Please specify just the name of the repository without '
                    '".git".'))

        try:
            rsp = self.api_get(
                self._build_api_url(
                    'repositories/%s/%s' %
                    (self._get_repository_owner_raw(plan, kwargs),
                     self._get_repository_name_raw(plan, kwargs)),
                    query={
                        'fields': 'scm',
                    }))
        except HostingServiceError as e:
            if six.text_type(e) == 'Resource not found':
                raise RepositoryError(
                    ugettext('A repository with this name was not found.'))

            raise

        scm = rsp['scm']

        if ((scm == 'git' and tool_name != 'Git')
                or (scm == 'hg' and tool_name != 'Mercurial')):
            raise RepositoryError(
                ugettext('The Bitbucket repository being configured does not '
                         'match the type of repository you have selected.'))
Пример #4
0
    def check_repository(self, plan=None, *args, **kwargs):
        """Checks the validity of a repository.

        This will perform an API request against GitHub to get
        information on the repository. This will throw an exception if
        the repository was not found, and return cleanly if it was found.
        """
        try:
            repo_info = self.client.api_get(
                self._build_api_url(
                    self._get_repo_api_url_raw(
                        self._get_repository_owner_raw(plan, kwargs),
                        self._get_repository_name_raw(plan, kwargs))))
        except HostingServiceError as e:
            if e.http_code == 404:
                if plan in ('public', 'private'):
                    raise RepositoryError(
                        ugettext('A repository with this name was not found, '
                                 'or your user may not own it.'))
                elif plan == 'public-org':
                    raise RepositoryError(
                        ugettext('A repository with this organization or '
                                 'name was not found.'))
                elif plan == 'private-org':
                    raise RepositoryError(
                        ugettext('A repository with this organization or name '
                                 'was not found, or your user may not have '
                                 'access to it.'),
                        help_link=self._ORG_ACCESS_SUPPORT_URL,
                        help_link_text=ugettext(
                            'Get help on granting access.'))

            raise

        if 'private' in repo_info:
            is_private = repo_info['private']

            if is_private and plan in ('public', 'public-org'):
                raise RepositoryError(
                    ugettext('This is a private repository, but you have '
                             'selected a public plan.'))
            elif not is_private and plan in ('private', 'private-org'):
                raise RepositoryError(
                    ugettext('This is a public repository, but you have '
                             'selected a private plan.'))
Пример #5
0
    def check_repository(self, plan=None, *args, **kwargs):
        """Checks the validity of a repository.

        This will perform an API request against GitHub to get
        information on the repository. This will throw an exception if
        the repository was not found, and return cleanly if it was found.
        """
        try:
            repo_info = self.client.api_get(
                self._build_api_url(
                    self._get_repo_api_url_raw(
                        self._get_repository_owner_raw(plan, kwargs),
                        self._get_repository_name_raw(plan, kwargs))))
        except Exception as e:
            if six.text_type(e) == 'Not Found':
                if plan in ('public', 'private'):
                    raise RepositoryError(
                        _('A repository with this name was not found, or your '
                          'user may not own it.'))
                elif plan == 'public-org':
                    raise RepositoryError(
                        _('A repository with this organization or name was '
                          'not found.'))
                elif plan == 'private-org':
                    raise RepositoryError(
                        _('A repository with this organization or name was '
                          'not found, or your user may not have access to '
                          'it.'))

            raise

        if 'private' in repo_info:
            is_private = repo_info['private']

            if is_private and plan in ('public', 'public-org'):
                raise RepositoryError(
                    _('This is a private repository, but you have selected '
                      'a public plan.'))
            elif not is_private and plan in ('private', 'private-org'):
                raise RepositoryError(
                    _('This is a public repository, but you have selected '
                      'a private plan.'))
Пример #6
0
    def _api_get_repository(self, account_domain, repository_name, tool_name):
        url = self._build_api_url(account_domain, 'repositories/')

        # Let the exception bubble up.
        results = self._api_get(url)

        for repo in results:
            if repo['abbreviation'] == repository_name:
                unfuddle_tool_name = self.TOOL_NAME_MAP.get(repo['system'])

                if unfuddle_tool_name == tool_name:
                    return repo

        raise RepositoryError(
            six.text_type(_('A repository with this name was not found')))
Пример #7
0
    def check_repository(self, kiln_account_domain=None,
                         kiln_project_name=None, kiln_group_name=None,
                         kiln_repo_name=None, *args, **kwargs):
        """Checks the validity of a repository.

        This will check to see if there's a repository accessible to the
        user matching the provided information. This will throw an exception
        if the repository was not found, and return cleanly if it was found.
        """
        repo_info = self._find_repository_info(kiln_project_name,
                                               kiln_group_name,
                                               kiln_repo_name)

        if not repo_info:
            raise RepositoryError(ugettext(
                'The repository with this project, group, and name was not '
                'found. Please verify that the information exactly matches '
                'the configuration on Kiln.'))
Пример #8
0
    def _find_repository_id_v4(self, plan, owner, repo_name):
        """Find the ID of a repository matching the given name and owner.

        If the repository could not be found, an appropriate error will be
        raised.

        Args:
            plan (unicode):
                The plan name.

            owner (unicode):
                The name of the owning group or user.

            repo_name (unicode):
                The name of the repository.

        Returns:
            int:
            The ID of the repository.

        Raises:
            reviewboard.scmtools.errors.AuthorizationError:
                There was an issue with the authorization credentials.

            reviewboard.scmtools.errors.RepositoryError:
                The repository could be found or accessed.

            urllib2.HTTPError:
                There was an error communicating with the server.
        """
        project = '%s/%s' % (owner, repo_name)

        try:
            data, headers = self._api_get(self.account.hosting_url,
                                          'projects/%s' % quote_plus(project))
            return data['id']
        except HTTPError as e:
            if e.code == 404:
                raise RepositoryError(
                    ugettext('A repository with this name was not found, or '
                             'your user may not own it.'))

            raise
Пример #9
0
    def get_change(self, repository, revision):
        """Return a single change.

        Args:
            repository (reviewboard.scmtools.models.Repository):
                The repository configured to use Gerrit.

            revision (unicode):
                The SHA1 of the commit to fetch.

        Returns:
            reviewboard.scmtools.core.Commit:
            The commit with its diff.
        """
        # The commit endpoint that Gerrit exposes is subtly different from the
        # one our plugin exposes and requires more work on our end to parse, so
        # we just use the all-commits endpoint we expose and limit it to a
        # single commit.
        commit = self.get_commits(repository, start=revision, limit=1)[0]

        url = self._build_project_api_url(repository, 'commits', revision,
                                          'diff')

        try:
            diff = self.client.http_get(url).data
        except HostingServiceError as e:
            logger.exception('Could not retrieve change "%s": %s',
                             revision, e)
            raise RepositoryError(
                ugettext('Could not retrieve change "%(rev)s" from repository '
                         '%(repo)d: %(error)s"')
                % {
                    'rev': revision,
                    'repo': repository.id,
                    'error': e,
                })

        commit.diff = diff

        return commit
Пример #10
0
    def _find_repository_id_v3(self, plan, owner, repo_name):
        """Find the ID of a repository matching the given name and owner.

        If the repository could not be found, an appropriate error will be
        raised.

        Args:
            plan (unicode):
                The plan name.

            owner (unicode):
                The name of the owning group or user.

            repo_name (unicode):
                The name of the repository.

        Returns:
            int:
            The ID of the repository.

        Raises:
            reviewboard.scmtools.errors.AuthorizationError:
                There was an issue with the authorization credentials.

            reviewboard.scmtools.errors.RepositoryError:
                The repository could be found or accessed.

            urllib2.HTTPError:
                There was an error communicating with the server.
        """
        # GitLab claims pagination support, but it has a number of problems.
        # We have no idea how many pages there are, or even if there's another
        # page of items. Furthermore, if we try to go beyond the last page,
        # we just get the first again, so we can't attempt to guess very
        # well.
        #
        # If the list doesn't return the repository, the user is out of luck.
        #
        # This is true as of GitLab 6.4.3.
        if plan == 'personal':
            repositories = self._api_get_repositories()

            for repository_entry in repositories:
                namespace = repository_entry['namespace']

                if (namespace['path'] == owner
                        and repository_entry['path'] == repo_name):
                    # This is the repository we wanted to find.
                    return repository_entry['id']

            raise RepositoryError(
                ugettext('A repository with this name was not found, or your '
                         'user may not own it.'))
        elif plan == 'group':
            groups = self._api_get_groups()

            for group_entry in groups:
                # If the full path is available, use that (to support nested
                # groups). Otherwise fall back on the group name.
                group_name = group_entry.get('full_path', group_entry['name'])

                if group_name == owner:
                    group_id = group_entry['id']
                    group_data = self._api_get_group(group_id)
                    repositories = group_data['projects']

                    for repository_entry in repositories:
                        if repository_entry['name'] == repo_name:
                            return repository_entry['id']

                    raise RepositoryError(
                        ugettext('A repository with this name was not '
                                 'found on this group, or your user may '
                                 'not have access to it.'))
            raise RepositoryError(
                ugettext('A group with this name was not found, or your user '
                         'may not have access to it.'))
        else:
            raise InvalidPlanError(plan)
Пример #11
0
    def check_repository(self, codebasehq_project_name=None,
                         codebasehq_repo_name=None, tool_name=None,
                         *args, **kwargs):
        """Check the validity of a repository.

        This will perform an API request against Codebase to get information on
        the repository. This will throw an exception if the repository was not
        found, and return cleanly if it was found.

        Args:
            codebase_project_name (unicode):
                The name of the project on Codebase.

            codebasehq_repo_name (unicode):
                The name of the repository on Codebase.

            tool_name (unicode):
                The name of the SCMTool for the repository.

            *args (tuple):
                Extra unused positional arguments passed to this function.

            **kwargs (dict):
                Extra unused keyword arguments passed to this function.

        Raises:
            reviewboard.hostingsvcs.errors.RepositoryError:
                The repository was not found.
        """
        # The form should enforce these values.
        assert codebasehq_project_name
        assert codebasehq_repo_name
        assert tool_name

        try:
            info = self.client.api_get_repository(codebasehq_project_name,
                                                  codebasehq_repo_name)
        except HostingServiceAPIError as e:
            logging.error('Error finding Codebase repository "%s" for '
                          'project "%s": %s',
                          codebasehq_repo_name, codebasehq_project_name,
                          e)

            raise RepositoryError(
                ugettext('A repository with this name and project was '
                         'not found.'))

        try:
            scm_type = info['repository']['scm']
        except KeyError:
            logging.error('Missing "scm" field for Codebase HQ repository '
                          'payload: %r',
                          info)

            raise RepositoryError(
                ugettext('Unable to determine the type of repository '
                         'from the Codebase API. Please report this.'))

        try:
            expected_tool_name = self.REPO_SCM_TOOL_MAP[scm_type]
        except KeyError:
            logging.error('Unexpected "scm" value "%s" for Codebase HQ '
                          'repository, using payload: %r',
                          scm_type, info)

            raise RepositoryError(
                ugettext('Unable to determine the type of repository '
                         'from the Codebase API. Please report this.'))

        if expected_tool_name != tool_name:
            raise RepositoryError(
                ugettext("The repository type doesn't match what you "
                         "selected. Did you mean %s?")
                % expected_tool_name)
Пример #12
0
    def check_repository(self, gerrit_url=None, gerrit_project_name=None,
                         *args, **kwargs):
        """Check that the repository is configured correctly.

        This method ensures that the user has access to an existing repository
        on the Gerrit server and that the ``gerrit-reviewboard`` plugin is
        installed and of a compatible version.

        Args:
            gerrit_url (unicode):
                The URL to the Gerrit server.

            gerrit_project_name (unicode):
                The repository's configured project name on Gerrit.

            *args (tuple):
                Ignored positional arguments.

            **kwargs (dict):
                Ignored keyword arguments.

        Raises:
            reviewboard.hostingsvcs.errors.RepositoryError:
                One of the following:

                * The repository does not exist.
                * The user does not have access to the repository.
                * The ``gerrit-reviewboard`` plugin is not installed.
                * The ``gerrit-reviewboard`` plugin that is installed is an
                  incompatible version.
        """
        url = urljoin(gerrit_url,
                      'a/projects/%s' % quote_plus(gerrit_project_name))

        try:
            self.client.api_get(url, json=False)
        except HostingServiceAPIError as e:
            if e.http_code == 404:
                raise RepositoryError(
                    ugettext('The project "%s" does not exist or you do not '
                             'have access to it.')
                    % gerrit_project_name)

            raise

        url = urljoin(gerrit_url, 'a/plugins/')

        try:
            rsp = self.client.api_get(url)
        except HostingServiceError as e:
            logger.exception(
                'Could not retrieve the list of Gerrit plugins from %s: %s',
                url, e)
            raise RepositoryError(
                ugettext('Could not retrieve the list of Gerrit plugins '
                         'from %(url).')
                % {
                    'url': url,
                })

        if 'gerrit-reviewboard' not in rsp:
            raise RepositoryError(
                ugettext('The "gerrit-reviewboard" plugin is not installed '
                         'on the server. See %(plugin_url)s for installation '
                         'instructions.')
                % {
                    'plugin_url': _PLUGIN_URL,
                })
        else:
            version_str = rsp['gerrit-reviewboard']['version']

            try:
                version = self._parse_plugin_version(version_str)
            except Exception as e:
                logger.exception(
                    'Could not parse gerrit-reviewboard plugin version "%s" '
                    'from %s: %s',
                    version, url, e)
                raise RepositoryError(
                    ugettext('Could not parse gerrit-reviewboard version: '
                             '"%(version)s" from URL %(url)s: %(error)s')
                    % {
                        'version': version,
                        'error': e,
                        'url': url,
                    })

            if version < self.REQUIRED_PLUGIN_VERSION:
                raise RepositoryError(
                    ugettext('The "gerrit-reviewboard" plugin on the server '
                             'is an incompatible version: found %(found)s but '
                             'version %(required)s or higher is required.')
                    % {
                        'found': version_str,
                        'required': self.REQUIRED_PLUGIN_VERSION_STR,
                    }
                )
Пример #13
0
 def check_repository(self, test_repo_name, *args, **kwargs):
     if test_repo_name == 'bad':
         raise RepositoryError('Invalid repository name')