summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/gl_objects/projects.rst4
-rw-r--r--gitlab/exceptions.py4
-rw-r--r--gitlab/v4/objects/projects.py15
-rw-r--r--tests/unit/objects/test_projects.py17
4 files changed, 40 insertions, 0 deletions
diff --git a/docs/gl_objects/projects.rst b/docs/gl_objects/projects.rst
index 88a63aa..775908c 100644
--- a/docs/gl_objects/projects.rst
+++ b/docs/gl_objects/projects.rst
@@ -115,6 +115,10 @@ Delete a project::
# or
project.delete()
+Restore a project marked for deletion (Premium only)::
+
+ project.restore()
+
Fork a project::
fork = project.forks.create({})
diff --git a/gitlab/exceptions.py b/gitlab/exceptions.py
index 4a2f1dc..9ee64e3 100644
--- a/gitlab/exceptions.py
+++ b/gitlab/exceptions.py
@@ -286,6 +286,10 @@ class GitlabRepairError(GitlabOperationError):
pass
+class GitlabRestoreError(GitlabOperationError):
+ pass
+
+
class GitlabRevertError(GitlabOperationError):
pass
diff --git a/gitlab/v4/objects/projects.py b/gitlab/v4/objects/projects.py
index 96d802b..a90bffb 100644
--- a/gitlab/v4/objects/projects.py
+++ b/gitlab/v4/objects/projects.py
@@ -477,6 +477,21 @@ class Project(RefreshMixin, SaveMixin, ObjectDeleteMixin, RepositoryMixin, RESTO
assert isinstance(data, dict)
return {"alt": data["alt"], "url": data["url"], "markdown": data["markdown"]}
+ @cli.register_custom_action("Project")
+ @exc.on_http_error(exc.GitlabRestoreError)
+ def restore(self, **kwargs: Any) -> None:
+ """Restore a project marked for deletion.
+
+ Args:
+ **kwargs: Extra options to send to the server (e.g. sudo)
+
+ Raises:
+ GitlabAuthenticationError: If authentication is not correct
+ GitlabRestoreError: If the server failed to perform the request
+ """
+ path = f"/projects/{self.encoded_id}/restore"
+ self.manager.gitlab.http_post(path, **kwargs)
+
@cli.register_custom_action("Project", optional=("wiki",))
@exc.on_http_error(exc.GitlabGetError)
def snapshot(
diff --git a/tests/unit/objects/test_projects.py b/tests/unit/objects/test_projects.py
index 85bae86..6134382 100644
--- a/tests/unit/objects/test_projects.py
+++ b/tests/unit/objects/test_projects.py
@@ -505,6 +505,19 @@ def resp_delete_push_rules_project(no_content):
@pytest.fixture
+def resp_restore_project(created_content):
+ with responses.RequestsMock() as rsps:
+ rsps.add(
+ method=responses.POST,
+ url="http://localhost/api/v4/projects/1/restore",
+ json=created_content,
+ content_type="application/json",
+ status=201,
+ )
+ yield rsps
+
+
+@pytest.fixture
def resp_start_pull_mirroring_project():
with responses.RequestsMock() as rsps:
rsps.add(
@@ -753,6 +766,10 @@ def test_project_pull_mirror(project, resp_start_pull_mirroring_project):
project.mirror_pull()
+def test_project_restore(project, resp_restore_project):
+ project.restore()
+
+
def test_project_snapshot(project, resp_snapshot_project):
tar_file = project.snapshot()
assert isinstance(tar_file, bytes)