Exemple #1
0
    async def _metadata_folder(
            self, path: GitLabPath) -> typing.List[BaseGitLabMetadata]:
        """Fetch metadata for the contents of the folder at ``path`` and return a `list` of
        `GitLabFileMetadata` and `GitLabFolderMetadata` objects.

        :param GitLabPath path: `GitLabPath` representing a folder
        :rtype: `list`
        """
        data = await self._fetch_tree_contents(path)

        ret = []  # type: typing.List[BaseGitLabMetadata]
        for item in data:
            name = item['name']
            if item['type'] == 'tree':
                folder_path = path.child(name, folder=True)
                ret.append(GitLabFolderMetadata(item, folder_path))
            else:
                file_path = path.child(name, folder=False)
                item['mime_type'] = mimetypes.guess_type(name)[0]
                ret.append(
                    GitLabFileMetadata(item,
                                       file_path,
                                       host=self.VIEW_URL,
                                       owner=self.owner,
                                       repo=self.repo))

        return ret
    async def test_metadata_file_with_branch(self, provider):
        path = '/folder1/folder2/file'
        gl_path = GitLabPath(path, _ids=([(None, 'my-branch')] * 4))

        url = ('http://base.url/api/v4/projects/123/repository/files/'
               'folder1%2Ffolder2%2Ffile?ref=my-branch')
        aiohttpretty.register_json_uri('GET',
                                       url,
                                       body=fixtures.simple_file_metadata())

        history_url = ('http://base.url/api/v4/projects/123/repository/commits'
                       '?path=folder1/folder2/file&ref_name=my-branch&page=1'
                       '&per_page={}'.format(provider.MAX_PAGE_SIZE))
        aiohttpretty.register_json_uri('GET',
                                       history_url,
                                       body=fixtures.revisions_for_file())

        result = await provider.metadata(gl_path)
        assert result.json_api_serialized('mst3k')['links'] == {
            'move':
            ('http://localhost:7777/v1/resources/mst3k/providers/gitlab'
             '/folder1/folder2/file?branch=my-branch'),
            'upload':
            None,
            'download':
            ('http://localhost:7777/v1/resources/mst3k/providers/gitlab'
             '/folder1/folder2/file?branch=my-branch'),
            'delete':
            None,
        }
Exemple #3
0
    async def test_download(self, provider):
        path = '/folder1/file.py'
        gl_path = GitLabPath(path, _ids=([('a1b2c3d4', 'master')] * 3))

        url = ('http://base.url/api/v4/projects/123/repository/files'
               '/folder1%2Ffile.py/raw?ref=a1b2c3d4')
        aiohttpretty.register_uri('GET', url, body=b'hello', headers={'X-Gitlab-Size': '5'})

        result = await provider.download(gl_path, branch='master')
        assert await result.read() == b'hello'
    async def test_metadata_file_with_default_ref(self, provider):
        path = '/folder1/folder2/file'
        gl_path = GitLabPath(path, _ids=([('a1b2c3d4', 'master')] * 4))

        url = ('http://base.url/api/v4/projects/123/repository/files/'
               'folder1%2Ffolder2%2Ffile?ref=a1b2c3d4')
        aiohttpretty.register_json_uri('GET',
                                       url,
                                       body=fixtures.simple_file_metadata())

        history_url = ('http://base.url/api/v4/projects/123/repository/commits'
                       '?path=folder1/folder2/file&ref_name=a1b2c3d4&page=1'
                       '&per_page={}'.format(provider.MAX_PAGE_SIZE))
        aiohttpretty.register_json_uri('GET',
                                       history_url,
                                       body=fixtures.revisions_for_file())

        etag = hashlib.sha256('{}::{}::{}'.format('gitlab', path, 'a1b2c3d4').encode('utf-8'))\
                      .hexdigest()
        result = await provider.metadata(gl_path)
        assert result.serialized() == {
            'name': 'file',
            'kind': 'file',
            'size': 123,
            'sizeInt': 123,
            'provider': 'gitlab',
            'path': path,
            'materialized': path,
            'modified': '2017-07-24T16:02:17.000-04:00',
            'modified_utc': '2017-07-24T20:02:17+00:00',
            'created_utc': '2016-11-30T18:30:23+00:00',
            'contentType': None,
            'etag': etag,
            'extra': {
                'commitSha':
                'a1b2c3d4',
                'branch':
                'master',
                'webView':
                'http://base.url/cat/food/blob/master/folder1/folder2/file',
            },
        }
        assert result.json_api_serialized('mst3k')['links'] == {
            'move':
            ('http://localhost:7777/v1/resources/mst3k/providers/gitlab'
             '/folder1/folder2/file?commitSha=a1b2c3d4'),
            'upload':
            None,
            'download':
            ('http://localhost:7777/v1/resources/mst3k/providers/gitlab'
             '/folder1/folder2/file?commitSha=a1b2c3d4'),
            'delete':
            None,
        }
    async def test_no_such_revision(self, provider):
        path = '/folder1/folder2/file'
        gl_path = GitLabPath(path, _ids=([('a1b2c3d4', 'master')] * 4))

        url = ('http://base.url/api/v4/projects/123/repository/commits'
               '?path=folder1/folder2/file&ref_name=a1b2c3d4')
        aiohttpretty.register_json_uri('GET', url, body=[])

        with pytest.raises(exceptions.RevisionsError) as exc:
            await provider.revisions(gl_path)
        assert exc.value.code == 404
Exemple #6
0
    async def validate_path(self, path: str, **kwargs) -> GitLabPath:
        """Turn the string ``path`` into a `GitLabPath` object. Will infer the branch/commit
        information from the query params or from the default branch for the repo if those are
        not provided.  Does no validation to ensure that the entity described by ``path`` actually
        exists.

        Valid kwargs are ``commitSha``, ``branch``, and ``revision``.  If ``revision`` is given,
        its value will be assigned to the commit SHA if it is a valid base-16 number, or branch
        otherwise.  ``revision`` will override ``commitSha`` or ``branch``.  If both a commit SHA
        and branch name are given, both will be associated with the new GitLabPath object.  No
        effort is made to ensure that they point to the same thing.  `GitLabPath` objects default
        to commit SHAs over branch names when building API calls, as a commit SHA is more specific.

        :param str path: The path to a file
        :rtype: GitLabPath
        """
        commit_sha = kwargs.get('commitSha')
        branch_name = kwargs.get('branch')

        # revision query param could be commit sha OR branch
        # take a guess which one it will be.
        revision = kwargs.get('revision', None)
        if revision is not None:
            try:
                int(revision, 16)  # is revision valid hex?
            except (TypeError, ValueError):
                branch_name = revision
            else:
                commit_sha = revision

        if not commit_sha and not branch_name:
            branch_name = await self._fetch_default_branch()

        if path == '/':
            return GitLabPath(path, _ids=[(commit_sha, branch_name)])

        gl_path = GitLabPath(path)
        for part in gl_path.parts:
            part._id = (commit_sha, branch_name)

        return gl_path
    async def test_metadata_file_no_such_file(self, provider):
        path = '/folder1/folder2/file'
        gl_path = GitLabPath(path, _ids=([('a1b2c3d4', 'master')] * 4))

        url = ('http://base.url/api/v4/projects/123/repository/files/'
               'folder1%2Ffolder2%2Ffile?ref=a1b2c3d4')
        aiohttpretty.register_json_uri('GET', url, body={}, status=404)

        with pytest.raises(exceptions.NotFoundError) as exc:
            await provider.metadata(gl_path)

        assert exc.value.code == 404
    async def test_metadata_folder_no_such_folder_404(self, provider):
        path = '/folder1/folder2/folder3/'
        gl_path = GitLabPath(path, _ids=([('a1b2c3d4', 'master')] * 4))

        url = ('http://base.url/api/v4/projects/123/repository/tree'
               '?path=folder1/folder2/folder3/&ref=a1b2c3d4&page=1'
               '&per_page={}'.format(provider.MAX_PAGE_SIZE))
        aiohttpretty.register_json_uri('GET', url, body={}, status=404)

        with pytest.raises(exceptions.NotFoundError) as exc:
            await provider.metadata(gl_path)

        assert exc.value.code == 404
    async def test_download_file_ruby_response(self, provider):
        """See: https://gitlab.com/gitlab-org/gitlab-ce/issues/31790"""
        path = '/folder1/folder2/file'
        gl_path = GitLabPath(path, _ids=([(None, 'my-branch')] * 4))

        url = ('http://base.url/api/v4/projects/123/repository/files/'
               'folder1%2Ffolder2%2Ffile?ref=my-branch')
        aiohttpretty.register_uri('GET',
                                  url,
                                  body=fixtures.weird_ruby_response())

        result = await provider.download(gl_path)
        assert await result.read() == b'rolf\n'
    async def _metadata_folder(self, path: GitLabPath) -> typing.List[BaseGitLabMetadata]:
        """Fetch metadata for the contents of the folder at ``path`` and return a `list` of
        `GitLabFileMetadata` and `GitLabFolderMetadata` objects.

        :param GitLabPath path: `GitLabPath` representing a folder
        :rtype: `list`
        """
        data = await self._fetch_tree_contents(path)

        ret = []  # type: typing.List[BaseGitLabMetadata]
        for item in data:
            name = item['name']
            if item['type'] == 'tree':
                folder_path = path.child(name, folder=True)
                ret.append(GitLabFolderMetadata(item, folder_path))
            else:
                file_path = path.child(name, folder=False)
                item['mime_type'] = mimetypes.guess_type(name)[0]
                ret.append(GitLabFileMetadata(item, file_path, host=self.VIEW_URL,
                                              owner=self.owner, repo=self.repo))

        return ret
    async def test_metadata_folder(self, provider):
        path = '/folder1/folder2/folder3/'
        gl_path = GitLabPath(path, _ids=([('a1b2c3d4', 'master')] * 4))

        url = ('http://base.url/api/v4/projects/123/repository/tree'
               '?path=folder1/folder2/folder3/&ref=a1b2c3d4&page=1'
               '&per_page={}'.format(provider.MAX_PAGE_SIZE))
        aiohttpretty.register_json_uri('GET',
                                       url,
                                       body=[{
                                           'id': '123',
                                           'type': 'tree',
                                           'name': 'my folder'
                                       }, {
                                           'id': '1234',
                                           'type': 'file',
                                           'name': 'my file'
                                       }])

        result = await provider.metadata(gl_path)

        assert isinstance(result[0], GitLabFolderMetadata)
        assert result[0].name == 'my folder'
        assert result[0].json_api_serialized('mst3k')['links'] == {
            'move':
            ('http://localhost:7777/v1/resources/mst3k/providers/gitlab'
             '/folder1/folder2/folder3/my%20folder/?commitSha=a1b2c3d4'),
            'upload':
            None,
            'delete':
            None,
            'new_folder':
            None,
        }

        assert result[1].name == 'my file'
        assert isinstance(result[1], GitLabFileMetadata)

        child_path = provider.path_from_metadata(gl_path, result[1])
        child_path.name == 'my file'
        child_path.commit_sha == 'a1b2c3d4'
        child_path.branch_name == 'master'
    async def test_download_file_ruby_response_range(self, provider):
        """See: https://gitlab.com/gitlab-org/gitlab-ce/issues/31790"""
        path = '/folder1/folder2/file'
        gl_path = GitLabPath(path, _ids=([(None, 'my-branch')] * 4))

        url = ('http://base.url/api/v4/projects/123/repository/files/'
               'folder1%2Ffolder2%2Ffile?ref=my-branch')
        aiohttpretty.register_uri('GET',
                                  url,
                                  body=fixtures.weird_ruby_response())

        result = await provider.download(gl_path, range=(0, 1))
        assert result.partial
        assert await result.read() == b'ro'
        assert aiohttpretty.has_call(method='GET',
                                     uri=url,
                                     headers={
                                         'Range': 'bytes=0-1',
                                         'PRIVATE-TOKEN': 'naps'
                                     })
Exemple #13
0
    async def test_revisions(self, provider, revisions_for_file):
        path = '/folder1/folder2/file'
        gl_path = GitLabPath(path, _ids=([('a1b2c3d4', 'master')] * 4))

        url = ('http://base.url/api/v4/projects/123/repository/commits'
               '?path=folder1/folder2/file&ref_name=a1b2c3d4')
        aiohttpretty.register_json_uri('GET', url, body=revisions_for_file)

        revisions = await provider.revisions(gl_path)
        assert len(revisions) == 3

        assert revisions[0].serialized() == {
            'version': '931aece9275c0d084dfa7f6e0b3b2bb250e4b089',
            'modified': '2017-07-24T16:02:17.000-04:00',
            'modified_utc': '2017-07-24T20:02:17+00:00',
            'versionIdentifier': 'commitSha',
            'extra': {
                'user': {
                    'name': 'Fitz Elliott',
                },
            },
        }
    async def test_metadata_file_ruby_response(self, provider):
        """See: https://gitlab.com/gitlab-org/gitlab-ce/issues/31790"""
        path = '/folder1/folder2/file'
        gl_path = GitLabPath(path, _ids=([(None, 'my-branch')] * 4))

        url = ('http://base.url/api/v4/projects/123/repository/files/'
               'folder1%2Ffolder2%2Ffile?ref=my-branch')
        aiohttpretty.register_uri('GET',
                                  url,
                                  body=fixtures.weird_ruby_response())

        history_url = ('http://base.url/api/v4/projects/123/repository/commits'
                       '?path=folder1/folder2/file&ref_name=my-branch&page=1'
                       '&per_page={}'.format(provider.MAX_PAGE_SIZE))
        aiohttpretty.register_json_uri('GET',
                                       history_url,
                                       body=fixtures.revisions_for_file())

        result = await provider.metadata(gl_path)
        assert result.name == 'file'
        assert result.size == 5
        assert result.content_type == None
    async def test_download_range(self, provider):
        path = '/folder1/file.py'
        gl_path = GitLabPath(path, _ids=([('a1b2c3d4', 'master')] * 3))

        url = ('http://base.url/api/v4/projects/123/repository/files'
               '/folder1%2Ffile.py?ref=a1b2c3d4')
        aiohttpretty.register_json_uri('GET',
                                       url,
                                       body={'content': 'aGVsbG8='})

        result = await provider.download(gl_path,
                                         branch='master',
                                         range=(0, 1))
        assert result.partial
        assert await result.read(
        ) == b'he'  # body content after base64 decoding and slice
        assert aiohttpretty.has_call(method='GET',
                                     uri=url,
                                     headers={
                                         'Range': 'bytes=0-1',
                                         'PRIVATE-TOKEN': 'naps'
                                     })
Exemple #16
0
 def path_from_metadata(
         self,  # type: ignore
         parent_path: GitLabPath,
         metadata) -> GitLabPath:
     """Build a GitLabPath for a the child of ``parent_path`` described by ``metadata``."""
     return parent_path.child(metadata.name, folder=metadata.is_folder)
 def path_from_metadata(self,  # type: ignore
                        parent_path: GitLabPath,
                        metadata) -> GitLabPath:
     """Build a GitLabPath for a the child of ``parent_path`` described by ``metadata``."""
     return parent_path.child(metadata.name, folder=metadata.is_folder)