diff --git a/docs/gl_objects/projects.rst b/docs/gl_objects/projects.rst index 3ff72414d..4bae08358 100644 --- a/docs/gl_objects/projects.rst +++ b/docs/gl_objects/projects.rst @@ -180,6 +180,14 @@ Get the repository archive:: # get the archive for a branch/tag/commit tgz = project.repository_archive(sha='4567abc') + # get the archive in a different format + zip = project.repository_archive(format='zip') + +.. note:: + + For the formats available, refer to + https://docs.gitlab.com/ce/api/repositories.html#get-file-archive + .. warning:: Archives are entirely stored in memory unless you use the streaming feature. diff --git a/gitlab/v4/objects/repositories.py b/gitlab/v4/objects/repositories.py index e7e434dc7..b520ab726 100644 --- a/gitlab/v4/objects/repositories.py +++ b/gitlab/v4/objects/repositories.py @@ -186,7 +186,7 @@ def repository_contributors( path = f"/projects/{self.get_id()}/repository/contributors" return self.manager.gitlab.http_list(path, **kwargs) - @cli.register_custom_action("Project", tuple(), ("sha",)) + @cli.register_custom_action("Project", tuple(), ("sha", "format")) @exc.on_http_error(exc.GitlabListError) def repository_archive( self, @@ -194,9 +194,10 @@ def repository_archive( streamed: bool = False, action: Optional[Callable[..., Any]] = None, chunk_size: int = 1024, + format: Optional[str] = None, **kwargs: Any, ) -> Optional[bytes]: - """Return a tarball of the repository. + """Return an archive of the repository. Args: sha: ID of the commit (default branch by default) @@ -206,6 +207,7 @@ def repository_archive( action: Callable responsible of dealing with chunk of data chunk_size: Size of each chunk + format: file format (tar.gz by default) **kwargs: Extra options to send to the server (e.g. sudo) Raises: @@ -216,6 +218,8 @@ def repository_archive( The binary data of the archive """ path = f"/projects/{self.get_id()}/repository/archive" + if format: + path += "." + format query_data = {} if sha: query_data["sha"] = sha diff --git a/tests/functional/api/test_repository.py b/tests/functional/api/test_repository.py index 06d429740..ecef1f164 100644 --- a/tests/functional/api/test_repository.py +++ b/tests/functional/api/test_repository.py @@ -1,5 +1,8 @@ import base64 +import tarfile import time +import zipfile +from io import BytesIO import pytest @@ -48,14 +51,34 @@ def test_repository_tree(project): blob = project.repository_raw_blob(blob_id) assert blob.decode() == "Initial content" + snapshot = project.snapshot() + assert isinstance(snapshot, bytes) + + +def test_repository_archive(project): archive = project.repository_archive() assert isinstance(archive, bytes) archive2 = project.repository_archive("main") assert archive == archive2 - snapshot = project.snapshot() - assert isinstance(snapshot, bytes) + +@pytest.mark.parametrize( + "format,assertion", + [ + ("tbz", tarfile.is_tarfile), + ("tbz2", tarfile.is_tarfile), + ("tb2", tarfile.is_tarfile), + ("bz2", tarfile.is_tarfile), + ("tar", tarfile.is_tarfile), + ("tar.gz", tarfile.is_tarfile), + ("tar.bz2", tarfile.is_tarfile), + ("zip", zipfile.is_zipfile), + ], +) +def test_repository_archive_formats(project, format, assertion): + archive = project.repository_archive(format=format) + assert assertion(BytesIO(archive)) def test_create_commit(project):