Esempio n. 1
0
    def create_file(self,
                    path: str,
                    message: str,
                    content: str,
                    branch: Optional[str] = None,
                    committer: Optional[str] = None,
                    author: Optional[dict] = None,
                    encoding: Optional[str] = None):
        """
        Create a new file in Repository
        """
        url = self._url + '/repository/files/' + path
        data = {
            'file_path': path,
            'commit_message': message,
            'content': content,
            'branch': branch,
            'encoding': encoding
        }

        if author:
            data['author_name'] = author['name']
            data['author_email'] = author['email']

        data = eliminate_none(data)
        post(token=self._token, url=url, data=data)

        from IGitt.GitLab.GitLabContent import GitLabContent
        return GitLabContent(self._token, self.full_name, path=path)
Esempio n. 2
0
    def set_status(self, status: CommitStatus):
        """
        Adds the given status to the commit.

        >>> from os import environ
        >>> commit = GitLabCommit(
        ...     GitLabOAuthToken(environ['GITLAB_TEST_TOKEN']),
        ...     'gitmate-test-user/test', '3fc4b86'
        ... )
        >>> status = CommitStatus(Status.FAILED, 'Theres a problem',
        ...                       'gitmate/test')
        >>> commit.set_status(status)
        >>> commit.get_statuses().pop().description
        'Theres a problem'

        If a status with the same context already exists, it will be bluntly
        overridden:

        >>> status.status = Status.SUCCESS
        >>> status.description = "Theres no problem"
        >>> commit.set_status(status)
        >>> len(commit.get_statuses())
        1
        >>> commit.get_statuses().pop().description
        'Theres no problem'

        :param status: The CommitStatus to set to this commit.
        :raises RuntimeError: If something goes wrong (network, auth...).
        """
        data = {'state': GL_STATE_TRANSLATION[status.status],
                'target_url': status.url, 'description': status.description,
                'name': status.context}
        status_url = '/projects/{repo}/statuses/{sha}'.format(
            repo=quote_plus(self._repository), sha=self.sha)
        post(self._token, status_url, data)
Esempio n. 3
0
    def create_merge_request(self,
                             title: str,
                             base: str,
                             head: str,
                             body: Optional[str] = None,
                             target_project_id: Optional[int] = None,
                             target_project: Optional[str] = None):
        """
        Create a new merge request in Repository
        """
        url = self._url + '/merge_requests'
        data = {
            'title': title,
            'target_branch': base,
            'source_branch': head,
            'id': quote_plus(self.full_name),
            'target_project_id': target_project_id
        }
        json = post(self._token, url=url, data=data)

        from IGitt.GitLab.GitLabMergeRequest import GitLabMergeRequest
        return GitLabMergeRequest.from_data(json,
                                            self._token,
                                            repository=target_project,
                                            number=json['iid'])
Esempio n. 4
0
    def create_label(self, name: str, color: str):
        """
        Creates a new label with the given color. For an example,
        see delete_label.

        If a label that already exists is attempted to be created, that throws
        an exception:

        >>> from os import environ
        >>> repo = GitLabRepository(
        ...     GitLabOAuthToken(environ['GITLAB_TEST_TOKEN']),
        ...     'gitmate-test-user/test'
        ... )
        >>> sorted(repo.get_labels())
        ['a', 'b', 'c']
        >>> repo.create_label('c', '#555555')
        Traceback (most recent call last):
         ...
        IGitt.ElementAlreadyExistsError: c already exists.

        :param name: The name of the label to create.
        :param color: A HTML color value with a leading #.
        :raises ElementAlreadyExistsError: If the label name already exists.
        :raises RuntimeError: If something goes wrong (network, auth...).
        """
        if name in self.get_labels():
            raise ElementAlreadyExistsError(name + ' already exists.')

        self.data = post(self._token, self._url + '/labels', {
            'name': name,
            'color': color
        })
Esempio n. 5
0
    def create(token: Union[GitLabOAuthToken, GitLabPrivateToken],
               repository: str,
               title: str,
               body: str = ''):
        """
        Create a new issue with given title and body.

        >>> from os import environ
        >>> issue = GitLabIssue.create(
        ...     GitLabOAuthToken(environ['GITLAB_TEST_TOKEN']),
        ...     'gitmate-test-user/test',
        ...     'test issue title',
        ...     'sample description'
        ... )
        >>> issue.state
        <IssueStates.OPEN: 'open'>

        Delete the issue to avoid filling the test repo with issues.

        >>> issue.delete()

        :return: GitLabIssue object of the newly created issue.
        """
        url = '/projects/{repo}/issues'.format(repo=quote_plus(repository))
        issue = post(token, url, {'title': title, 'description': body})

        return GitLabIssue.from_data(issue, token, repository, issue['iid'])
Esempio n. 6
0
    def add_comment(self, body):
        """
        Adds a comment to the issue.

        >>> from os import environ
        >>> issue = GitLabIssue(GitLabOAuthToken(environ['GITLAB_TEST_TOKEN']),
        ...                     'gitmate-test-user/test', 1)
        >>> comment = issue.add_comment("Doh!")

        You can use the comment right after:

        >>> comment.body
        'Doh!'
        >>> comment.delete()

        The comment will be created by the user authenticated via the oauth
        token.

        :param body: The body of the new comment to create.
        :return: The newly created comment.
        """
        result = post(self._token, self._url + '/notes', {'body': body})

        return GitLabComment(self._token, self._repository, self.number,
                             CommentType.ISSUE, result['id'])
Esempio n. 7
0
    def create_fork(self,
                    organization: Optional[str] = None,
                    namespace: Optional[str] = None):
        """
        Create a fork of Repository
        """
        url = self._url + '/fork'
        data = {'id': self.full_name, 'namespace': namespace}
        res = post(self._token, url=url, data=data)

        return GitLabRepository(self._token, res['path_with_namespace'])
Esempio n. 8
0
    def register_hook(self,
                      url: str,
                      secret: Optional[str] = None,
                      events: Optional[Set[WebhookEvents]] = None):
        """
        Registers a webhook to the given URL. Use it as simple as:

        >>> from os import environ
        >>> repo = GitLabRepository(environ['GITLAB_TEST_TOKEN'],
        ...                         'gitmate-test-user/test')
        >>> repo.register_hook("http://some.url/in/the/world")

        It does nothing if the hook is already there:

        >>> repo.register_hook("http://some.url/in/the/world")

        To register a secret token with the webhook, simply add
        the secret param:

        >>> repo.register_hook("http://some.url/i/have/a/secret",
        ...     "mylittlesecret")

        To delete it simply run:

        >>> repo.delete_hook("http://some.url/in/the/world")
        >>> repo.delete_hook("http://some.url/i/have/a/secret")

        :param url: The URL to fire the webhook to.
        :param secret:
            An optional secret token to be registered with the webhook.
        :param events:
            The events for which the webhook is to be registered against.
            Defaults to all possible events.
        :raises RuntimeError: If something goes wrong (network, auth...).
        """
        if url in self.hooks:
            return

        config = {
            'url': url,
            'enable_ssl_verification': False,
        }

        if secret:
            config['token'] = secret

        if events and len(events):
            config.update(
                {GL_WEBHOOK_TRANSLATION[event]: True
                 for event in events})
        else:
            config.update({event: True for event in GL_WEBHOOK_EVENTS})

        self.data = post(self._token, self._url + '/hooks', config)
Esempio n. 9
0
    def comment(self, message: str, file: Optional[str]=None,
                line: Optional[int]=None,
                mr_number: Optional[int]=None) -> GitLabComment:
        """
        Places a comment on the commit.

        >>> from os import environ
        >>> commit = GitLabCommit(
        ...     GitLabOAuthToken(environ['GITLAB_TEST_TOKEN']),
        ...     'gitmate-test-user/test', '3fc4b86'
        ... )

        So this line places a comment on the bottom of the commit,
        not associated to any particular piece of code:

        >>> commit.comment("An issue is here!")

        However, we can also comment on a particular file and line, if that is
        included in the diff:

        >>> commit.comment("Here in line 4, there's a spelling mistake!",
        ...                'README.md', 4)

        If you supply the ``pr_number`` argument, the comment will appear in
        the review UI of that pull request:

        >>> commit.comment("Here in line 4, there's a spelling mistake!",
        ...                'README.md', 4, mr_number=7)

        Beat that! Of course, there's a lot of error handling. If you give the
        wrong file, the comment will appear below the commit with a note about
        the commit, file and line:

        >>> commit.comment("Oh, this'll end up below!!", 'READMENOT.md', 4)

        Also if the line isn't contained in the diff GitLab won't accept that
        and it'll also end up below - sorry!

        >>> commit.comment("Oh, this'll too end up below!!", 'README.md', 8)

        If you give a pull request, the comment will appear on the PR instead:

        >>> commit.comment("Oh, this'll too end up on the PR.",
        ...                'README.md', 8, mr_number=7)

        :param message: The body of the comment.
        :param file: The file to place the comment, relative to repo root.
        :param line: The line in the file in the comment or None.
        :param mr_number: The iid of a merge request if this should end up in
                          the discussions UI of the merge request.
        """
        data = {'note': message, 'line_type': 'new'}

        if file is not None and line is not None:
            try:
                patch = self.get_patch_for_file(file)
                index = get_diff_index(patch, line)
                if index:  # Else, fallback to comment below file
                    data['line'] = index
                    data['path'] = file
            except ElementDoesntExistError:
                pass  # Fallback to comment below the file

        if 'line' not in data:
            file_str = '' if file is None else ', file ' + file
            line_str = '' if line is None else ', line ' + str(line)
            data['note'] = ('Comment on ' + self.sha + file_str + line_str +
                            '.\n\n' + data['note'])

        # post a comment on commit
        if 'line' in data and 'path' in data or mr_number is None:
            url = '/projects/{id}/repository/commits/{sha}/comments'.format(
                id=quote_plus(self._repository), sha=self.sha)
            res = post(self._token, url, data)
            return

        # fallback to post the comment on relevant merge request
        if mr_number is not None:
            data['body'] = data['note']  # because gitlab is stupid
            res = post(self._token,
                       '/projects/{id}/merge_requests/{mr_iid}/notes'.format(
                           id=quote_plus(self._repository), mr_iid=mr_number),
                       data)
            return GitLabComment.from_data(res, self._token, self._repository,
                                           mr_number, CommentType.MERGE_REQUEST,
                                           res['id'])